networkd: get preexiting addresses when a link is added
authorTom Gundersen <teg@jklm.no>
Sun, 11 May 2014 11:58:18 +0000 (13:58 +0200)
committerTom Gundersen <teg@jklm.no>
Sun, 11 May 2014 12:26:10 +0000 (14:26 +0200)
src/network/networkd-link.c
src/network/networkd-manager.c
src/network/networkd.h

index 3bc9c0e..d07cc30 100644 (file)
@@ -1666,13 +1666,129 @@ int link_initialized(Link *link, struct udev_device *device) {
         return 0;
 }
 
+int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
+        Manager *m = userdata;
+        Link *link = NULL;
+        uint16_t type;
+        _cleanup_address_free_ Address *address = NULL;
+        char buf[INET6_ADDRSTRLEN];
+        int r, ifindex;
+
+        assert(rtnl);
+        assert(message);
+        assert(m);
+
+        r = sd_rtnl_message_get_type(message, &type);
+        if (r < 0) {
+                log_warning("rtnl: could not get message type");
+                return 0;
+        }
+
+        r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
+        if (r < 0 || ifindex <= 0) {
+                log_warning("rtnl: received address message without valid ifindix, ignoring");
+                return 0;
+        } else {
+                r = link_get(m, ifindex, &link);
+                if (r < 0 || !link) {
+                        log_warning("rtnl: received address for non-existing link, ignoring");
+                        return 0;
+                }
+        }
+
+        r = address_new_dynamic(&address);
+        if (r < 0)
+                return 0;
+
+        r = sd_rtnl_message_addr_get_family(message, &address->family);
+        if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
+                log_warning("rtnl: received address with invalid family, ignoring");
+                return 0;
+        }
+
+        r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
+        if (r < 0) {
+                log_warning("rtnl: recevied address with invalid prefixlen, ignoring");
+                return 0;
+        }
+
+        switch (address->family) {
+        case AF_INET:
+                r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
+                if (r < 0) {
+                        log_warning("rtnl: received address without valid address, ignoring");
+                        return 0;
+                }
+
+                break;
+
+        case AF_INET6:
+                r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
+                if (r < 0) {
+                        log_warning("rtnl: received address without valid address, ignoring");
+                        return 0;
+                }
+
+                break;
+
+        default:
+                assert_not_reached("invalid address family");
+        }
+
+        if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
+                log_warning("could not print address");
+                return 0;
+        }
+
+        switch (type) {
+        case RTM_NEWADDR:
+                log_info("added address: %s/%u to ifindex %d", buf,
+                         address->prefixlen, ifindex);
+                break;
+
+        case RTM_DELADDR:
+                log_info("removed address: %s/%u from ifindex %d", buf,
+                         address->prefixlen, ifindex);
+                break;
+        default:
+                assert_not_reached("Received invalid RTNL message type");
+        }
+
+        return 1;
+}
+
+static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
+        Link *link = userdata;
+        int r;
+
+        assert(rtnl);
+        assert(m);
+        assert(link);
+
+        for (; m; m = sd_rtnl_message_next(m)) {
+                r = sd_rtnl_message_get_errno(m);
+                if (r < 0) {
+                        log_debug_link(link, "getting address failed: %s", strerror(-r));
+                        continue;
+                }
+
+                r = link_rtnl_process_address(rtnl, m, link->manager);
+                if (r < 0)
+                        log_warning_link(link, "could not process address: %s", strerror(-r));
+        }
+
+        return 1;
+}
+
 int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
         Link *link;
+        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
         char ifindex_str[2 + DECIMAL_STR_MAX(int)];
         int r;
 
         assert(m);
+        assert(m->rtnl);
         assert(message);
         assert(ret);
 
@@ -1684,6 +1800,14 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
 
         log_debug_link(link, "link added");
 
+        r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0, NULL);
+        if (r < 0)
+                return r;
+
         if (detect_container(NULL) <= 0) {
                 /* not in a container, udev will be around */
                 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
index effa93c..8bdc60f 100644 (file)
@@ -217,97 +217,6 @@ static int manager_udev_process_link(Manager *m, struct udev_device *device) {
         return 0;
 }
 
-static int manager_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
-        Manager *m = userdata;
-        Link *link = NULL;
-        uint16_t type;
-        _cleanup_address_free_ Address *address = NULL;
-        char buf[INET6_ADDRSTRLEN];
-        int r, ifindex;
-
-        assert(rtnl);
-        assert(message);
-        assert(m);
-
-        r = sd_rtnl_message_get_type(message, &type);
-        if (r < 0) {
-                log_warning("rtnl: could not get message type");
-                return 0;
-        }
-
-        r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
-        if (r < 0 || ifindex <= 0) {
-                log_warning("rtnl: received address message without valid ifindix, ignoring");
-                return 0;
-        } else {
-                r = link_get(m, ifindex, &link);
-                if (r < 0 || !link) {
-                        log_warning("rtnl: received address for non-existing link, ignoring");
-                        return 0;
-                }
-        }
-
-        r = address_new_dynamic(&address);
-        if (r < 0)
-                return 0;
-
-        r = sd_rtnl_message_addr_get_family(message, &address->family);
-        if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
-                log_warning("rtnl: received address with invalid family, ignoring");
-                return 0;
-        }
-
-        r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
-        if (r < 0) {
-                log_warning("rtnl: recevied address with invalid prefixlen, ignoring");
-                return 0;
-        }
-
-        switch (address->family) {
-        case AF_INET:
-                r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
-                if (r < 0) {
-                        log_warning("rtnl: received address without valid address, ignoring");
-                        return 0;
-                }
-
-                break;
-
-        case AF_INET6:
-                r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
-                if (r < 0) {
-                        log_warning("rtnl: received address without valid address, ignoring");
-                        return 0;
-                }
-
-                break;
-
-        default:
-                assert_not_reached("invalid address family");
-        }
-
-        if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
-                log_warning("could not print address");
-                return 0;
-        }
-
-        switch (type) {
-        case RTM_NEWADDR:
-                log_info("added address: %s/%u to ifindex %d", buf,
-                         address->prefixlen, ifindex);
-                break;
-
-        case RTM_DELADDR:
-                log_info("removed address: %s/%u from ifindex %d", buf,
-                         address->prefixlen, ifindex);
-                break;
-        default:
-                assert_not_reached("Received invalid RTNL message type");
-        }
-
-        return 1;
-}
-
 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
         Manager *m = userdata;
         Link *link = NULL;
@@ -476,11 +385,11 @@ int manager_rtnl_listen(Manager *m) {
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m);
+        r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
         if (r < 0)
                 return r;
 
-        r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m);
+        r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
         if (r < 0)
                 return r;
 
index 692b3df..ec2e111 100644 (file)
@@ -374,6 +374,7 @@ int link_add(Manager *manager, sd_rtnl_message *message, Link **ret);
 void link_drop(Link *link);
 
 int link_update(Link *link, sd_rtnl_message *message);
+int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata);
 
 int link_initialized(Link *link, struct udev_device *device);