From fbbeb65a93e2f90f6576001b69def877cd98722d Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Sun, 11 May 2014 13:58:18 +0200 Subject: [PATCH] networkd: get preexiting addresses when a link is added --- src/network/networkd-link.c | 124 +++++++++++++++++++++++++++++++++ src/network/networkd-manager.c | 95 +------------------------ src/network/networkd.h | 1 + 3 files changed, 127 insertions(+), 93 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3bc9c0ea9aa..d07cc309512 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index effa93c81e9..8bdc60f19c9 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -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; diff --git a/src/network/networkd.h b/src/network/networkd.h index 692b3df9ae0..ec2e111a7b1 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -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);