From: Yu Watanabe Date: Fri, 2 Oct 2020 02:32:35 +0000 (+0900) Subject: network: move manager_rtnl_process_address() X-Git-Tag: v247-rc1~117^2~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e1fc2c437125b7098830ef75965614b35258cd62;p=thirdparty%2Fsystemd.git network: move manager_rtnl_process_address() --- diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index bb97fdacfeb..9ec8d4af1fa 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1057,6 +1057,168 @@ int link_set_addresses(Link *link) { return 0; } +int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + _cleanup_free_ char *buf = NULL; + Link *link = NULL; + uint16_t type; + unsigned char flags, prefixlen, scope; + union in_addr_union in_addr = IN_ADDR_NULL; + struct ifa_cacheinfo cinfo; + Address *address = NULL; + char valid_buf[FORMAT_TIMESPAN_MAX]; + const char *valid_str = NULL; + int ifindex, family, r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) { + log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will get the address again, so just + * ignore it */ + if (!m->enumerating) + log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex); + return 0; + } + + r = sd_rtnl_message_addr_get_family(message, &family); + if (r < 0) { + log_link_warning(link, "rtnl: received address message without family, ignoring."); + return 0; + } else if (!IN_SET(family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", family); + return 0; + } + + r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_scope(message, &scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_flags(message, &flags); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); + return 0; + } + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received unsupported address family"); + } + + r = in_addr_to_string(family, &in_addr, &buf); + if (r < 0) + log_link_warning_errno(link, r, "Could not print address: %m"); + + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); + return 0; + } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) + valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, + cinfo.ifa_valid * USEC_PER_SEC, + USEC_PER_SEC); + + (void) address_get(link, family, &in_addr, prefixlen, &address); + + switch (type) { + case RTM_NEWADDR: + if (address) + log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + else { + /* An address appeared that we did not request */ + r = address_add_foreign(link, family, &in_addr, prefixlen, &address); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m", + strnull(buf), prefixlen); + return 0; + } else + log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + } + + /* address_update() logs internally, so we don't need to here. */ + r = address_update(address, flags, scope, &cinfo); + if (r < 0) + link_enter_failed(link); + + break; + + case RTM_DELADDR: + if (address) { + log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + (void) address_drop(address); + } else + log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { _cleanup_free_ char *pretty = NULL; Address *address; diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 472e8ee79a5..5b565b6e55e 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -79,6 +79,8 @@ int link_set_addresses(Link *link); int link_drop_addresses(Link *link); int link_drop_foreign_addresses(Link *link); +int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); + void address_hash_func(const Address *a, struct siphash *state); int address_compare_func(const Address *a1, const Address *a2); extern const struct hash_ops address_hash_ops; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 5cd925a27c0..00f172bc903 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -285,168 +285,6 @@ static int manager_connect_udev(Manager *m) { return 0; } -int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - _cleanup_free_ char *buf = NULL; - Link *link = NULL; - uint16_t type; - unsigned char flags, prefixlen, scope; - union in_addr_union in_addr = IN_ADDR_NULL; - struct ifa_cacheinfo cinfo; - Address *address = NULL; - char valid_buf[FORMAT_TIMESPAN_MAX]; - const char *valid_str = NULL; - int ifindex, family, r; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) { - log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type); - return 0; - } - - r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will get the address again, so just - * ignore it */ - if (!m->enumerating) - log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex); - return 0; - } - - r = sd_rtnl_message_addr_get_family(message, &family); - if (r < 0) { - log_link_warning(link, "rtnl: received address message without family, ignoring."); - return 0; - } else if (!IN_SET(family, AF_INET, AF_INET6)) { - log_link_debug(link, "rtnl: received address message with invalid family '%i', ignoring.", family); - return 0; - } - - r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_scope(message, &scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); - return 0; - } - - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - assert_not_reached("Received unsupported address family"); - } - - r = in_addr_to_string(family, &in_addr, &buf); - if (r < 0) - log_link_warning_errno(link, r, "Could not print address: %m"); - - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); - return 0; - } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) - valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, - cinfo.ifa_valid * USEC_PER_SEC, - USEC_PER_SEC); - - (void) address_get(link, family, &in_addr, prefixlen, &address); - - switch (type) { - case RTM_NEWADDR: - if (address) - log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - else { - /* An address appeared that we did not request */ - r = address_add_foreign(link, family, &in_addr, prefixlen, &address); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m", - strnull(buf), prefixlen); - return 0; - } else - log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - } - - /* address_update() logs internally, so we don't need to here. */ - r = address_update(address, flags, scope, &cinfo); - if (r < 0) - link_enter_failed(link); - - break; - - case RTM_DELADDR: - if (address) { - log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - (void) address_drop(address); - } else - log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.", - strnull(buf), prefixlen, - valid_str ? "for " : "forever", strempty(valid_str)); - - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { Link *link = NULL; NetDev *netdev = NULL; diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 602ae919e94..f95367660ab 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -84,8 +84,6 @@ bool manager_should_reload(Manager *m); int manager_enumerate(Manager *m); -int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); - void manager_dirty(Manager *m); int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);