Parcourir la source

[1528] nlmsg_list converted to C++ style.

Tomek Mrugalski il y a 13 ans
Parent
commit
7f9ddb4963
1 fichiers modifiés avec 56 ajouts et 61 suppressions
  1. 56 61
      src/lib/dhcp/iface_mgr_linux.cc

+ 56 - 61
src/lib/dhcp/iface_mgr_linux.cc

@@ -28,27 +28,24 @@ using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::dhcp;
 
+typedef vector<struct nlmsghdr*> NetlinkMessages;
+
 /// This is a structure that defines context for netlink connection.
 struct rtnl_handle
 {
-    int                fd;
+    int fd; // netlink file descriptor
     struct sockaddr_nl local;
     struct sockaddr_nl peer;
-    __u32              seq;
-    __u32              dump;
+    __u32 seq;
+    __u32 dump;
 };
 
-struct nlmsg_list
-{
-    struct nlmsg_list *next;
-    struct nlmsghdr h;
-};
-
-const int sndbuf = 32768;
-const int rcvbuf = 32768;
+const size_t sndbuf = 32768;
+const size_t rcvbuf = 32768;
 
 namespace isc {
 
+namespace dhcp {
 
 /// @brief Opens netlink socket and initializes handle structure.
 ///
@@ -121,26 +118,24 @@ void rtnl_send_request(struct rtnl_handle& handle, int family, int type) {
     }
 }
 
-/// @brief Appends nlmsg to a list
+/// @brief Appends nlmsg to a storage.
 ///
-/// @param n a message to be added
-/// @param link_info a list
-void rtnl_store_reply(struct nlmsghdr *n, struct nlmsg_list** link_info)
+/// @param storage a vector that holds netlink messages
+/// @param msg a netlink message to be added
+void rtnl_store_reply(NetlinkMessages& storage, const struct nlmsghdr *msg)
 {
-    struct nlmsg_list *h;
-    struct nlmsg_list **lp;
-
-    h = (nlmsg_list*)malloc(n->nlmsg_len+sizeof(void*));
-    if (h == NULL) {
-        isc_throw(Unexpected, "Failed to allocate " << n->nlmsg_len+sizeof(void*)
+    // we need to make a copy of this message. As those messages are variable size
+    // it is easier to use malloc + C-style case than do new char[X] and then
+    // reinterpret_cast<>  to struct nlmsghdr.
+    struct nlmsghdr* copy = (struct nlmsghdr*)malloc(msg->nlmsg_len);
+    memcpy(copy, msg, msg->nlmsg_len);
+    if (copy == NULL) {
+        isc_throw(Unexpected, "Failed to allocate " << msg->nlmsg_len
                   << " bytes.");
     }
 
-    memcpy(&h->h, n, n->nlmsg_len);
-    h->next = NULL;
-
-    for (lp = link_info; *lp; lp = &(*lp)->next) /* NOTHING */;
-    *lp = h;
+    // push_back copies only pointer content, not the pointed object
+    storage.push_back(copy);
 }
 
 void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
@@ -156,13 +151,13 @@ void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
     }
 }
 
-void ipaddrs_get(IfaceMgr::Iface& iface, struct nlmsg_list *addr_info) {
+void ipaddrs_get(IfaceMgr::Iface& iface, NetlinkMessages& addr_info) {
     uint8_t addr[16];
     struct rtattr * rta_tb[IFA_MAX+1];
 
-    for ( ;addr_info ;  addr_info = addr_info->next) {
-        struct nlmsghdr *n = &addr_info->h;
-        struct ifaddrmsg *ifa = (ifaddrmsg*)NLMSG_DATA(n);
+    for (NetlinkMessages::const_iterator msg = addr_info.begin();
+         msg != addr_info.end(); ++msg) {
+        struct ifaddrmsg *ifa = (ifaddrmsg*)NLMSG_DATA(*msg);
 
         // these are not the addresses you are looking for
         if ( ifa->ifa_index != iface.getIndex()) {
@@ -171,7 +166,7 @@ void ipaddrs_get(IfaceMgr::Iface& iface, struct nlmsg_list *addr_info) {
 
         if ( ifa->ifa_family == AF_INET6 ) {
             memset(rta_tb, 0, sizeof(rta_tb));
-            parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
+            parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), (*msg)->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
             if (!rta_tb[IFA_LOCAL])
                 rta_tb[IFA_LOCAL]   = rta_tb[IFA_ADDRESS];
             if (!rta_tb[IFA_ADDRESS])
@@ -186,7 +181,7 @@ void ipaddrs_get(IfaceMgr::Iface& iface, struct nlmsg_list *addr_info) {
 
         if ( ifa->ifa_family == AF_INET ) {
             memset(rta_tb, 0, sizeof(rta_tb));
-            parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
+            parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), (*msg)->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
             if (!rta_tb[IFA_LOCAL])
                 rta_tb[IFA_LOCAL]   = rta_tb[IFA_ADDRESS];
             if (!rta_tb[IFA_ADDRESS])
@@ -199,8 +194,7 @@ void ipaddrs_get(IfaceMgr::Iface& iface, struct nlmsg_list *addr_info) {
     }
 }
 
-
-void rtnl_process_reply(struct rtnl_handle &rth, struct nlmsg_list *&info) {
+void rtnl_process_reply(const struct rtnl_handle& rth, NetlinkMessages& info) {
 
     struct sockaddr_nl nladdr;
     struct iovec iov;
@@ -214,9 +208,9 @@ void rtnl_process_reply(struct rtnl_handle &rth, struct nlmsg_list *&info) {
     char buf[rcvbuf];
 
     iov.iov_base = buf;
-    while (1) {
+    while (true) {
         int status;
-        struct nlmsghdr *h;
+        struct nlmsghdr* header;
 
         iov.iov_len = sizeof(buf);
         status = recvmsg(rth.fd, &msg, 0);
@@ -231,25 +225,25 @@ void rtnl_process_reply(struct rtnl_handle &rth, struct nlmsg_list *&info) {
             isc_throw(Unexpected, "EOF while reading netlink socket.");
         }
 
-        h = (struct nlmsghdr*)buf;
-        while (NLMSG_OK(h, status)) {
+        header = (struct nlmsghdr*)buf;
+        while (NLMSG_OK(header, status)) {
 
             // why we received this anyway?
             if (nladdr.nl_pid != 0 ||
-                h->nlmsg_pid != rth.local.nl_pid ||
-                h->nlmsg_seq != rth.dump) {
-                h = NLMSG_NEXT(h, status);
+                header->nlmsg_pid != rth.local.nl_pid ||
+                header->nlmsg_seq != rth.dump) {
+                header = NLMSG_NEXT(header, status);
                 continue;
             }
 
-            if (h->nlmsg_type == NLMSG_DONE) {
+            if (header->nlmsg_type == NLMSG_DONE) {
                 // end of message
                 return;
             }
 
-            if (h->nlmsg_type == NLMSG_ERROR) {
-                struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-                if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+            if (header->nlmsg_type == NLMSG_ERROR) {
+                struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(header);
+                if (header->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
                     // we are really out of luck here. We can't even say what is
                     // wrong as error message is truncated. D'oh.
                     isc_throw(Unexpected, "Netlink reply read failed.");
@@ -261,9 +255,9 @@ void rtnl_process_reply(struct rtnl_handle &rth, struct nlmsg_list *&info) {
             }
 
             // store the data
-            rtnl_store_reply(h, &info);
+            rtnl_store_reply(info, header);
 
-            h = NLMSG_NEXT(h, status);
+            header = NLMSG_NEXT(header, status);
         }
         if (msg.msg_flags & MSG_TRUNC) {
             isc_throw(Unexpected, "Message received over netlink truncated.");
@@ -276,22 +270,20 @@ void rtnl_process_reply(struct rtnl_handle &rth, struct nlmsg_list *&info) {
 
 /// @brief releases nlmsg list
 ///
-/// @param head first element of the list to be released
-void release_list(struct nlmsg_list *head) {
-    struct nlmsg_list *tmp;
-    while (head) {
-        tmp = head->next;
-        free(head);
-        head = tmp;
+/// @param messages first element of the list to be released
+void release_list(NetlinkMessages& messages) {
+    // let's free our copies of stored messages
+    for (NetlinkMessages::iterator msg = messages.begin(); msg != messages.end(); ++msg) {
+        free(*msg);
     }
+    messages.clear();
 }
 
 void IfaceMgr::detectIfaces() {
     cout << "Linux: detecting interfaces." << endl;
 
-    struct nlmsg_list* link_info = NULL; // link info list
-    struct nlmsg_list* addr_info = NULL; // address info list
-    struct nlmsg_list* l = NULL;
+    NetlinkMessages link_info; // link info
+    NetlinkMessages addr_info; // address info
     struct rtnl_handle rth;
 
     // required to display information about interface
@@ -318,9 +310,10 @@ void IfaceMgr::detectIfaces() {
     rtnl_process_reply(rth, addr_info);
 
     // Now build list with interface names
-    for (l=link_info; l; l = l->next) {
-        ifi = (ifinfomsg*)NLMSG_DATA(&l->h);
-        len = (&l->h)->nlmsg_len;
+    for (NetlinkMessages::iterator msg = link_info.begin(); msg != link_info.end(); ++msg) {
+        // for (l=link_info; l; l = l->next) {
+        ifi = (ifinfomsg*)NLMSG_DATA(*msg);
+        len = (*msg)->nlmsg_len;
         len -= NLMSG_LENGTH(sizeof(*ifi));
         parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
 
@@ -375,6 +368,8 @@ void IfaceMgr::Iface::setFlags(uint32_t flags) {
     flag_broadcast_ = flags & IFF_BROADCAST;
 }
 
-}
+} // end of isc::dhcp namespace
+
+} // end of isc namespace
 
 #endif // if defined(LINUX)