X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=57e719478a11138d3666b56b7bdf443cbbe8ef6e;hp=6a5fe59d49d4e9673a6be203ea6899ce097082a5;hb=a61bb41c29c370a7e64285525ec35baac8944149;hpb=54cba0b16cdc94d5c21e8d805a4ade1255d43bc9 diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6a5fe59d4..57e719478 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -67,7 +67,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { link->n_ref = 1; link->manager = manager; - link->state = LINK_STATE_INITIALIZING; + link->state = LINK_STATE_PENDING; link->ifindex = ifindex; link->ifname = strdup(ifname); if (!link->ifname) @@ -380,7 +380,8 @@ void link_client_handler(Link *link) { if (!link->dhcp4_configured) return; - link_enter_configured(link); + if (link->state != LINK_STATE_CONFIGURED) + link_enter_configured(link); return; } @@ -862,15 +863,15 @@ static int link_acquire_conf(Link *link) { return 0; } -bool link_has_carrier(unsigned flags, uint8_t operstate) { +bool link_has_carrier(Link *link) { /* see Documentation/networking/operstates.txt in the kernel sources */ - if (operstate == IF_OPER_UP) + if (link->kernel_operstate == IF_OPER_UP) return true; - if (operstate == IF_OPER_UNKNOWN) + if (link->kernel_operstate == IF_OPER_UNKNOWN) /* operstate may not be implemented, so fall back to flags */ - if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT)) + if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT)) return true; return false; @@ -884,7 +885,6 @@ bool link_has_carrier(unsigned flags, uint8_t operstate) { static int link_update_flags(Link *link, sd_rtnl_message *m) { unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags; uint8_t operstate; - bool carrier_gained = false, carrier_lost = false; int r; assert(link); @@ -948,40 +948,11 @@ static int link_update_flags(Link *link, sd_rtnl_message *m) { unknown_flags_removed); } - carrier_gained = !link_has_carrier(link->flags, link->kernel_operstate) && - link_has_carrier(flags, operstate); - carrier_lost = link_has_carrier(link->flags, link->kernel_operstate) && - !link_has_carrier(flags, operstate); - link->flags = flags; link->kernel_operstate = operstate; link_save(link); - if (link->state == LINK_STATE_FAILED || - link->state == LINK_STATE_UNMANAGED) - return 0; - - if (carrier_gained) { - log_info_link(link, "gained carrier"); - - if (link->network) { - r = link_acquire_conf(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } - } else if (carrier_lost) { - log_info_link(link, "lost carrier"); - - r = link_stop_clients(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } - return 0; } @@ -1051,7 +1022,6 @@ static int link_joined(Link *link) { int r; assert(link); - assert(link->state == LINK_STATE_ENSLAVING); assert(link->network); if (!(link->flags & IFF_UP)) { @@ -1071,8 +1041,6 @@ static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m, int r; assert(link); - assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED, - LINK_STATE_LINGER)); assert(link->network); link->enslaving --; @@ -1106,7 +1074,7 @@ static int link_enter_join_netdev(Link *link) { assert(link); assert(link->network); - assert(link->state == LINK_STATE_INITIALIZING); + assert(link->state == LINK_STATE_PENDING); link->state = LINK_STATE_ENSLAVING; @@ -1196,7 +1164,7 @@ static int link_configure(Link *link) { assert(link); assert(link->network); - assert(link->state == LINK_STATE_INITIALIZING); + assert(link->state == LINK_STATE_PENDING); if (link->network->ipv4ll) { r = ipv4ll_configure(link); @@ -1246,7 +1214,7 @@ static int link_configure(Link *link) { return r; } - if (link_has_carrier(link->flags, link->kernel_operstate)) { + if (link_has_carrier(link)) { r = link_acquire_conf(link); if (r < 0) return r; @@ -1265,7 +1233,7 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, assert(link->ifname); assert(link->manager); - if (link->state != LINK_STATE_INITIALIZING) + if (link->state != LINK_STATE_PENDING) return 1; log_debug_link(link, "link state is up-to-date"); @@ -1298,7 +1266,7 @@ int link_initialized(Link *link, struct udev_device *device) { assert(link->manager->rtnl); assert(device); - if (link->state != LINK_STATE_INITIALIZING) + if (link->state != LINK_STATE_PENDING) return 0; if (link->udev_device) @@ -1336,6 +1304,8 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, _cleanup_address_free_ Address *address = NULL; Address *ad; char buf[INET6_ADDRSTRLEN]; + char valid_buf[FORMAT_TIMESPAN_MAX]; + const char *valid_str = NULL; bool address_dropped = false; int r, ifindex; @@ -1386,6 +1356,13 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, return 0; } + r = sd_rtnl_message_addr_get_flags(message, &address->flags); + if (r < 0) { + log_warning_link(link, + "rtnl: received address with invalid flags, ignoring"); + return 0; + } + switch (address->family) { case AF_INET: r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, @@ -1419,6 +1396,17 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, return 0; } + r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO, + &address->cinfo); + if (r >= 0) { + if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME) + valid_str = "ever"; + else + valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, + address->cinfo.ifa_valid * USEC_PER_SEC, + USEC_PER_SEC); + } + LIST_FOREACH(addresses, ad, link->addresses) { if (address_equal(ad, address)) { LIST_REMOVE(addresses, link->addresses, ad); @@ -1434,11 +1422,13 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, switch (type) { case RTM_NEWADDR: if (!address_dropped) - log_debug_link(link, "added address: %s/%u", buf, - address->prefixlen); + log_debug_link(link, "added address: %s/%u (valid for %s)", + buf, address->prefixlen, + strna(valid_str)); else - log_debug_link(link, "updated address: %s/%u", buf, - address->prefixlen); + log_debug_link(link, "updated address: %s/%u (valid for %s)", + buf, address->prefixlen, + strna(valid_str)); LIST_PREPEND(addresses, link->addresses, address); address = NULL; @@ -1448,14 +1438,16 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, break; case RTM_DELADDR: if (address_dropped) { - log_debug_link(link, "removed address: %s/%u", buf, - address->prefixlen); + log_debug_link(link, "removed address: %s/%u (valid for %s)", + buf, address->prefixlen, + strna(valid_str)); link_save(link); } else log_warning_link(link, - "removing non-existent address: %s/%u", - buf, address->prefixlen); + "removing non-existent address: %s/%u (valid for %s)", + buf, address->prefixlen, + strna(valid_str)); break; default: @@ -1509,7 +1501,7 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) { if (udev_device_get_is_initialized(device) <= 0) { /* not yet ready */ - log_debug_link(link, "udev initializing link..."); + log_debug_link(link, "link pending udev initialization..."); return 0; } @@ -1532,6 +1524,7 @@ int link_update(Link *link, sd_rtnl_message *m) { struct ether_addr mac; const char *ifname; uint32_t mtu; + bool had_carrier, carrier_gained, carrier_lost; int r; assert(link); @@ -1628,7 +1621,36 @@ int link_update(Link *link, sd_rtnl_message *m) { } } - return link_update_flags(link, m); + had_carrier = link_has_carrier(link); + + r = link_update_flags(link, m); + if (r < 0) + return r; + + carrier_gained = !had_carrier && link_has_carrier(link); + carrier_lost = had_carrier && !link_has_carrier(link); + + if (carrier_gained) { + log_info_link(link, "gained carrier"); + + if (link->network) { + r = link_acquire_conf(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + } else if (carrier_lost) { + log_info_link(link, "lost carrier"); + + r = link_stop_clients(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; } static void link_update_operstate(Link *link) { @@ -1637,12 +1659,15 @@ static void link_update_operstate(Link *link) { if (link->kernel_operstate == IF_OPER_DORMANT) link->operstate = LINK_OPERSTATE_DORMANT; - else if (link_has_carrier(link->flags, link->kernel_operstate)) { + else if (link_has_carrier(link)) { Address *address; uint8_t scope = RT_SCOPE_NOWHERE; /* if we have carrier, check what addresses we have */ LIST_FOREACH(addresses, address, link->addresses) { + if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) + continue; + if (address->scope < scope) scope = address->scope; } @@ -1657,9 +1682,9 @@ static void link_update_operstate(Link *link) { /* no useful addresses found */ link->operstate = LINK_OPERSTATE_CARRIER; } else if (link->flags & IFF_UP) - link->operstate = LINK_OPERSTATE_UP; + link->operstate = LINK_OPERSTATE_NO_CARRIER; else - link->operstate = LINK_OPERSTATE_DOWN; + link->operstate = LINK_OPERSTATE_OFF; } int link_save(Link *link) { @@ -1703,9 +1728,17 @@ int link_save(Link *link) { admin_state, oper_state); if (link->network) { - char **address; + char **address, **domain; + bool space; fputs("DNS=", f); + space = false; + STRV_FOREACH(address, link->network->dns) { + if (space) + fputc(' ', f); + fputs(*address, f); + space = true; + } if (link->network->dhcp_dns && link->dhcp_lease) { @@ -1713,19 +1746,22 @@ int link_save(Link *link) { r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { + if (space) + fputc(' ', f); serialize_in_addrs(f, addresses, r); - if (link->network->dns) - fputs(" ", f); } } - STRV_FOREACH(address, link->network->dns) - fprintf(f, "%s%s", *address, - (address + 1 ? " " : "")); - fputs("\n", f); fprintf(f, "NTP="); + space = false; + STRV_FOREACH(address, link->network->ntp) { + if (space) + fputc(' ', f); + fputs(*address, f); + space = true; + } if (link->network->dhcp_ntp && link->dhcp_lease) { @@ -1733,18 +1769,40 @@ int link_save(Link *link) { r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { + if (space) + fputc(' ', f); serialize_in_addrs(f, addresses, r); - if (link->network->ntp) - fputs(" ", f); } } - STRV_FOREACH(address, link->network->ntp) - fprintf(f, "%s%s", *address, - (address + 1 ? " " : "")); + fputs("\n", f); + + fprintf(f, "DOMAINS="); + space = false; + STRV_FOREACH(domain, link->network->domains) { + if (space) + fputc(' ', f); + fputs(*domain, f); + space = true; + } + + if (link->network->dhcp_domains && + link->dhcp_lease) { + const char *domainname; + + r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); + if (r >= 0) { + if (space) + fputc(' ', f); + fputs(domainname, f); + } + } fputs("\n", f); + fprintf(f, "WILDCARD_DOMAIN=%s\n", + yes_no(link->network->wildcard_domain)); + fprintf(f, "LLMNR=%s\n", llmnr_support_to_string(link->network->llmnr)); } @@ -1780,7 +1838,7 @@ fail: } static const char* const link_state_table[_LINK_STATE_MAX] = { - [LINK_STATE_INITIALIZING] = "initializing", + [LINK_STATE_PENDING] = "pending", [LINK_STATE_ENSLAVING] = "configuring", [LINK_STATE_SETTING_ADDRESSES] = "configuring", [LINK_STATE_SETTING_ROUTES] = "configuring", @@ -1793,8 +1851,8 @@ static const char* const link_state_table[_LINK_STATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState); static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { - [LINK_OPERSTATE_DOWN] = "down", - [LINK_OPERSTATE_UP] = "up", + [LINK_OPERSTATE_OFF] = "off", + [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", [LINK_OPERSTATE_DORMANT] = "dormant", [LINK_OPERSTATE_CARRIER] = "carrier", [LINK_OPERSTATE_DEGRADED] = "degraded",