X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fnetwork%2Fnetworkd-manager.c;h=90f734a03c5c52720a063284dea7676dd09c6c82;hb=269e4d2d6b75329ae39a71ebe2c14500e03cda95;hp=a164d6163e7d4cc42e83cbb11baf77b07a38c072;hpb=036eb795ada04e1c38033763c3bef34e02349e9c;p=thirdparty%2Fsystemd.git diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index a164d6163e7..90f734a03c5 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -5,11 +5,13 @@ #include #include #include +#include #include "sd-daemon.h" #include "sd-netlink.h" #include "alloc-util.h" +#include "bus-polkit.h" #include "bus-util.h" #include "conf-parser.h" #include "def.h" @@ -30,14 +32,22 @@ #include "ordered-set.h" #include "path-util.h" #include "set.h" +#include "signal-util.h" #include "strv.h" #include "sysctl-util.h" #include "tmpfile-util.h" #include "udev-util.h" #include "virt.h" -/* use 8 MB for receive socket kernel queue. */ -#define RCVBUF_SIZE (8*1024*1024) +/* use 128 MB for receive socket kernel queue. */ +#define RCVBUF_SIZE (128*1024*1024) + +static int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) { + const char *err_msg = NULL; + + (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); + return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : ""); +} static int setup_default_address_pool(Manager *m) { AddressPool *p; @@ -265,15 +275,13 @@ static int manager_connect_udev(Manager *m) { } int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(route_freep) Route *tmp = NULL; + Route *route = NULL; Manager *m = userdata; Link *link = NULL; + uint32_t ifindex; uint16_t type; - uint32_t ifindex, priority = 0; - unsigned char protocol, scope, tos, table, rt_type; - int family; - unsigned char dst_prefixlen, src_prefixlen; - union in_addr_union dst = IN_ADDR_NULL, gw = IN_ADDR_NULL, src = IN_ADDR_NULL, prefsrc = IN_ADDR_NULL; - Route *route = NULL; + unsigned char table; int r; assert(rtnl); @@ -283,7 +291,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) - log_warning_errno(r, "rtnl: failed to receive route message, ignoring: %m"); + log_message_warning_errno(message, r, "rtnl: failed to receive route message, ignoring"); return 0; } @@ -318,39 +326,46 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo return 0; } - r = sd_rtnl_message_route_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received route message with invalid family, ignoring"); + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_route_get_family(message, &tmp->family); + if (r < 0) { + log_link_warning(link, "rtnl: received route message without family, ignoring"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received route message with invalid family '%i', ignoring", tmp->family); return 0; } - r = sd_rtnl_message_route_get_protocol(message, &protocol); + r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol); if (r < 0) { - log_warning_errno(r, "rtnl: received route message with invalid route protocol: %m"); + log_warning_errno(r, "rtnl: received route message without route protocol: %m"); return 0; } - switch (family) { + switch (tmp->family) { case AF_INET: - r = sd_netlink_message_read_in_addr(message, RTA_DST, &dst.in); + r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &gw.in); + r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_SRC, &src.in); + r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &prefsrc.in); + r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); return 0; @@ -359,25 +374,25 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo break; case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, RTA_DST, &dst.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &gw.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &src.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &prefsrc.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); return 0; @@ -390,31 +405,31 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo return 0; } - r = sd_rtnl_message_route_get_dst_prefixlen(message, &dst_prefixlen); + r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_src_prefixlen(message, &src_prefixlen); + r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_scope(message, &scope); + r = sd_rtnl_message_route_get_scope(message, &tmp->scope); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_tos(message, &tos); + r = sd_rtnl_message_route_get_tos(message, &tmp->tos); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_type(message, &rt_type); + r = sd_rtnl_message_route_get_type(message, &tmp->type); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m"); return 0; @@ -425,14 +440,40 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); return 0; } + tmp->table = table; - r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &priority); + r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m"); return 0; } - (void) route_get(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route); + r = sd_netlink_message_enter_container(message, RTA_METRICS); + if (r < 0 && r != -ENODATA) { + log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m"); + return 0; + } + if (r >= 0) { + r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_exit_container(message); + if (r < 0) { + log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m"); + return 0; + } + } + + (void) route_get(link, tmp, &route); if (DEBUG_LOGGING) { _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, @@ -440,41 +481,39 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX], buf_protocol[ROUTE_PROTOCOL_STR_MAX]; - if (!in_addr_is_null(family, &dst)) { - (void) in_addr_to_string(family, &dst, &buf_dst); - (void) asprintf(&buf_dst_prefixlen, "/%u", dst_prefixlen); + if (!in_addr_is_null(tmp->family, &tmp->dst)) { + (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst); + (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen); } - if (!in_addr_is_null(family, &src)) - (void) in_addr_to_string(family, &src, &buf_src); - if (!in_addr_is_null(family, &gw)) - (void) in_addr_to_string(family, &gw, &buf_gw); - if (!in_addr_is_null(family, &prefsrc)) - (void) in_addr_to_string(family, &prefsrc, &buf_prefsrc); + if (!in_addr_is_null(tmp->family, &tmp->src)) + (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src); + if (!in_addr_is_null(tmp->family, &tmp->gw)) + (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw); + if (!in_addr_is_null(tmp->family, &tmp->prefsrc)) + (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc); log_link_debug(link, "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", - type == RTM_DELROUTE ? "Forgetting" : route ? "Updating remembered" : "Remembering", + type == RTM_DELROUTE ? "Forgetting" : route ? "Received remembered" : "Remembering", strna(buf_dst), strempty(buf_dst_prefixlen), strna(buf_src), strna(buf_gw), strna(buf_prefsrc), - format_route_scope(scope, buf_scope, sizeof buf_scope), - format_route_table(table, buf_table, sizeof buf_table), - format_route_protocol(protocol, buf_protocol, sizeof buf_protocol), - strna(route_type_to_string(rt_type))); + format_route_scope(tmp->scope, buf_scope, sizeof buf_scope), + format_route_table(tmp->table, buf_table, sizeof buf_table), + format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol), + strna(route_type_to_string(tmp->type))); } switch (type) { case RTM_NEWROUTE: if (!route) { /* A route appeared that we did not request */ - r = route_add_foreign(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route); + r = route_add_foreign(link, tmp, &route); if (r < 0) { log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m"); return 0; } } - route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol, rt_type); - break; case RTM_DELROUTE: @@ -548,7 +587,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) - log_warning_errno(r, "rtnl: failed to receive neighbor message, ignoring: %m"); + log_message_warning_errno(message, r, "rtnl: failed to receive neighbor message, ignoring"); return 0; } @@ -590,8 +629,11 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, } r = sd_rtnl_message_neigh_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received neighbor message with invalid family, ignoring."); + if (r < 0) { + log_link_warning(link, "rtnl: received neighbor message without family, ignoring."); + return 0; + } else if (!IN_SET(family, AF_INET, AF_INET6)) { + log_link_debug(link, "rtnl: received neighbor message with invalid family '%i', ignoring.", family); return 0; } @@ -654,8 +696,8 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, strnull(addr_str), strnull(lladdr_str)); (void) neighbor_free(neighbor); } else - log_link_info(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.", - strnull(addr_str), strnull(lladdr_str)); + log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.", + strnull(addr_str), strnull(lladdr_str)); break; @@ -686,7 +728,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) - log_warning_errno(r, "rtnl: failed to receive address message, ignoring: %m"); + log_message_warning_errno(message, r, "rtnl: failed to receive address message, ignoring"); return 0; } @@ -719,8 +761,11 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, } r = sd_rtnl_message_addr_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received address message with invalid family, ignoring."); + 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; } @@ -811,9 +856,9 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, valid_str ? "for " : "forever", strempty(valid_str)); (void) address_drop(address); } else - log_link_info(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)); + 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; @@ -839,7 +884,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) - log_warning_errno(r, "rtnl: Could not receive link message, ignoring: %m"); + log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring"); return 0; } @@ -929,7 +974,7 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi if (sd_netlink_message_is_error(message)) { r = sd_netlink_message_get_errno(message); if (r < 0) - log_warning_errno(r, "rtnl: failed to receive rule message, ignoring: %m"); + log_message_warning_errno(message, r, "rtnl: failed to receive rule message, ignoring"); return 0; } @@ -1126,6 +1171,118 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi return 1; } +int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(nexthop_freep) NextHop *tmp = NULL; + _cleanup_free_ char *gateway = NULL; + NextHop *nexthop = NULL; + Manager *m = userdata; + Link *link = NULL; + uint16_t type; + int 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 rule 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_NEWNEXTHOP, RTM_DELNEXTHOP)) { + log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type); + return 0; + } + + r = nexthop_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_get_family(message, &tmp->family); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + default: + assert_not_reached("Received rule message with unsupported address family"); + } + + r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); + return 0; + } + + r = link_get(m, tmp->oif, &link); + if (r < 0 || !link) { + if (!m->enumerating) + log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif); + return 0; + } + + (void) nexthop_get(link, tmp, &nexthop); + + if (DEBUG_LOGGING) + (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway); + + switch (type) { + case RTM_NEWNEXTHOP: + if (!nexthop) { + log_debug("Remembering foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); + r = nexthop_add_foreign(link, tmp, &nexthop); + if (r < 0) { + log_warning_errno(r, "Could not remember foreign nexthop, ignoring: %m"); + return 0; + } + } + break; + case RTM_DELNEXTHOP: + log_debug("Forgetting foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); + nexthop_free(nexthop); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + static int systemd_netlink_fd(void) { int n, fd, rtnl_fd = -EINVAL; @@ -1226,6 +1383,14 @@ static int manager_connect_rtnl(Manager *m) { if (r < 0) return r; + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + if (r < 0) + return r; + return 0; } @@ -1307,16 +1472,16 @@ static int ordered_set_put_in4_addrv(OrderedSet *s, } static int manager_save(Manager *m) { - _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; - Link *link; - Iterator i; - _cleanup_free_ char *temp_path = NULL; - _cleanup_strv_free_ char **p = NULL; - _cleanup_fclose_ FILE *f = NULL; + _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL; + const char *operstate_str, *carrier_state_str, *address_state_str; LinkOperationalState operstate = LINK_OPERSTATE_OFF; LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF; LinkAddressState address_state = LINK_ADDRESS_STATE_OFF; - const char *operstate_str, *carrier_state_str, *address_state_str; + _cleanup_free_ char *temp_path = NULL; + _cleanup_strv_free_ char **p = NULL; + _cleanup_fclose_ FILE *f = NULL; + Link *link; + Iterator i; int r; assert(m); @@ -1331,6 +1496,10 @@ static int manager_save(Manager *m) { if (!ntp) return -ENOMEM; + sip = ordered_set_new(&string_hash_ops); + if (!sip) + return -ENOMEM; + search_domains = ordered_set_new(&dns_name_hash_ops); if (!search_domains) return -ENOMEM; @@ -1400,6 +1569,18 @@ static int manager_save(Manager *m) { return r; } + if (link->network->dhcp_use_sip) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses); + if (r > 0) { + r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local); + if (r < 0) + return r; + } else if (r < 0 && r != -ENODATA) + return r; + } + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { const char *domainname; char **domains = NULL; @@ -1450,6 +1631,7 @@ static int manager_save(Manager *m) { ordered_set_print(f, "DNS=", dns); ordered_set_print(f, "NTP=", ntp); + ordered_set_print(f, "SIP=", sip); ordered_set_print(f, "DOMAINS=", search_domains); ordered_set_print(f, "ROUTE_DOMAINS=", route_domains); @@ -1518,6 +1700,28 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) { return 1; } +static int signal_terminate_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(m); + m->restarting = false; + + log_debug("Terminate operation initiated."); + + return sd_event_exit(sd_event_source_get_event(s), 0); +} + +static int signal_restart_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(m); + m->restarting = true; + + log_debug("Restart operation initiated."); + + return sd_event_exit(sd_event_source_get_event(s), 0); +} + int manager_new(Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -1538,9 +1742,12 @@ int manager_new(Manager **ret) { if (r < 0) return r; + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0); + (void) sd_event_set_watchdog(m->event, true); - (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); - (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + (void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m); + (void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m); + (void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m); r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); if (r < 0) @@ -1666,11 +1873,11 @@ int manager_load_config(Manager *m) { /* update timestamp */ paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true); - r = netdev_load(m); + r = netdev_load(m, false); if (r < 0) return r; - r = network_load(m); + r = network_load(m, &m->networks); if (r < 0) return r; @@ -1862,6 +2069,47 @@ int manager_rtnl_enumerate_rules(Manager *m) { return r; } +int manager_rtnl_enumerate_nexthop(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *nexthop; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_nexthop(m->rtnl, &req, RTM_GETNEXTHOP, 0, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) { + if (r == -EOPNOTSUPP) { + log_debug("Nexthop are not supported by the kernel. Ignoring."); + return 0; + } + + return r; + } + + for (nexthop = reply; nexthop; nexthop = sd_netlink_message_next(nexthop)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_nexthop(m->rtnl, nexthop, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { AddressPool *p; int r;