X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=0665e1fcfa4aa1661b8c15d04990129a4f7a3fac;hb=2bdbf32183fc6816cf34f4850e9fc5f070a34303;hp=22864bd403b89552650ef1f0f9c04643a8c1ecab;hpb=9c0a72f961e00b0447767973e7117e131bea5b5d;p=elogind.git diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 22864bd40..0665e1fcf 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -28,14 +28,11 @@ #include "fileio.h" #include "bus-util.h" #include "udev-util.h" -#include "libudev-private.h" #include "network-internal.h" #include "networkd-link.h" #include "networkd-netdev.h" -#include "conf-parser.h" -#include "dhcp-lease-internal.h" -static bool link_dhcp6_enabled(Link *link) { +bool link_dhcp6_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; @@ -45,7 +42,7 @@ static bool link_dhcp6_enabled(Link *link) { return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); } -static bool link_dhcp4_enabled(Link *link) { +bool link_dhcp4_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; @@ -55,7 +52,7 @@ static bool link_dhcp4_enabled(Link *link) { return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); } -static bool link_dhcp4_server_enabled(Link *link) { +bool link_dhcp4_server_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; @@ -65,17 +62,27 @@ static bool link_dhcp4_server_enabled(Link *link) { return link->network->dhcp_server; } -static bool link_ipv4ll_enabled(Link *link) { +bool link_ipv4ll_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; if (!link->network) return false; - return link->network->ipv4ll; + return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES); } -static bool link_lldp_enabled(Link *link) { +bool link_ipv6ll_enabled(Link *link) { + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + return IN_SET(link->network->link_local, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES); +} + +bool link_lldp_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) return false; @@ -283,12 +290,10 @@ static void link_free(Link *link) { sd_dhcp_client_unref(link->dhcp_client); sd_dhcp_lease_unref(link->dhcp_lease); - unlink(link->lease_file); free(link->lease_file); sd_lldp_free(link->lldp); - unlink(link->lldp_file); free(link->lldp_file); sd_ipv4ll_unref(link->ipv4ll); @@ -300,7 +305,6 @@ static void link_free(Link *link) { free(link->ifname); - unlink(link->state_file); free(link->state_file); udev_device_unref(link->udev_device); @@ -338,11 +342,24 @@ int link_get(Manager *m, int ifindex, Link **ret) { return 0; } +static void link_set_state(Link *link, LinkState state) { + assert(link); + + if (link->state == state) + return; + + link->state = state; + + link_send_changed(link, "AdministrativeState", NULL); + + return; +} + void link_drop(Link *link) { if (!link || link->state == LINK_STATE_LINGER) return; - link->state = LINK_STATE_LINGER; + link_set_state(link, LINK_STATE_LINGER); log_link_debug(link, "link removed"); @@ -356,7 +373,7 @@ static void link_enter_unmanaged(Link *link) { log_link_debug(link, "unmanaged"); - link->state = LINK_STATE_UNMANAGED; + link_set_state(link, LINK_STATE_UNMANAGED); link_save(link); } @@ -430,7 +447,7 @@ void link_enter_failed(Link *link) { log_link_warning(link, "failed"); - link->state = LINK_STATE_FAILED; + link_set_state(link, LINK_STATE_FAILED); link_stop_clients(link); @@ -473,7 +490,7 @@ static int link_enter_configured(Link *link) { log_link_info(link, "link configured"); - link->state = LINK_STATE_CONFIGURED; + link_set_state(link, LINK_STATE_CONFIGURED); link_save(link); @@ -536,7 +553,7 @@ static int link_enter_set_routes(Link *link) { assert(link->network); assert(link->state == LINK_STATE_SETTING_ADDRESSES); - link->state = LINK_STATE_SETTING_ROUTES; + link_set_state(link, LINK_STATE_SETTING_ROUTES); LIST_FOREACH(routes, rt, link->network->static_routes) { r = route_configure(rt, link, &route_handler); @@ -617,7 +634,7 @@ static int link_enter_set_addresses(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); - link->state = LINK_STATE_SETTING_ADDRESSES; + link_set_state(link, LINK_STATE_SETTING_ADDRESSES); LIST_FOREACH(addresses, ad, link->network->static_addresses) { r = address_configure(ad, link, &address_handler); @@ -708,12 +725,12 @@ int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) return 1; } -static int link_set_bridge_fdb(const Link *const link) { +static int link_set_bridge_fdb(Link *const link) { FdbEntry *fdb_entry; int r = 0; LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { - r = fdb_entry_configure(link->manager->rtnl, fdb_entry, link->ifindex); + r = fdb_entry_configure(link, fdb_entry); if(r < 0) { log_link_error(link, "Failed to add MAC entry to static MAC table: %s", strerror(-r)); break; @@ -1038,6 +1055,7 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { static int link_up(Link *link) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; + uint8_t ipv6ll_mode; int r; assert(link); @@ -1077,6 +1095,45 @@ static int link_up(Link *link) { } } + r = sd_rtnl_message_open_container(req, IFLA_AF_SPEC); + if (r < 0) { + log_link_error(link, "Could not open IFLA_AF_SPEC container: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_open_container(req, AF_INET6); + if (r < 0) { + log_link_error(link, "Could not open AF_INET6 container: %s", strerror(-r)); + return r; + } + + ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE; + r = sd_rtnl_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); + if (r < 0) { + log_link_error(link, "Could not append IFLA_INET6_ADDR_GEN_MODE: %s", strerror(-r)); + return r; + } + + if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) { + r = sd_rtnl_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6); + if (r < 0) { + log_link_error(link, "Could not append IFLA_INET6_TOKEN: %s", strerror(-r)); + return r; + } + } + + r = sd_rtnl_message_close_container(req); + if (r < 0) { + log_link_error(link, "Could not close AF_INET6 container: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_close_container(req); + if (r < 0) { + log_link_error(link, "Could not close IFLA_AF_SPEC container: %s", strerror(-r)); + return r; + } + r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); if (r < 0) { @@ -1153,7 +1210,7 @@ static int link_enter_join_netdev(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); - link->state = LINK_STATE_ENSLAVING; + link_set_state(link, LINK_STATE_ENSLAVING); link_save(link); @@ -1381,8 +1438,8 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, return r; if (link->flags & IFF_LOOPBACK) { - if (network->ipv4ll) - log_link_debug(link, "ignoring IPv4LL for loopback link"); + if (network->link_local != ADDRESS_FAMILY_NO) + log_link_debug(link, "ignoring link-local autoconfiguration for loopback link"); if (network->dhcp != ADDRESS_FAMILY_NO) log_link_debug(link, "ignoring DHCP clients for loopback link"); @@ -1492,7 +1549,10 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use } else { r = link_get(m, ifindex, &link); if (r < 0 || !link) { - log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); + /* 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 nonexistent link (%d), ignoring", ifindex); return 0; } } @@ -1721,7 +1781,7 @@ int link_update(Link *link, sd_rtnl_message *m) { if (link->state == LINK_STATE_LINGER) { link_ref(link); log_link_info(link, "link readded"); - link->state = LINK_STATE_ENSLAVING; + link_set_state(link, LINK_STATE_ENSLAVING); } r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname); @@ -1840,11 +1900,11 @@ int link_update(Link *link, sd_rtnl_message *m) { } static void link_update_operstate(Link *link) { - + LinkOperationalState operstate; assert(link); if (link->kernel_operstate == IF_OPER_DORMANT) - link->operstate = LINK_OPERSTATE_DORMANT; + operstate = LINK_OPERSTATE_DORMANT; else if (link_has_carrier(link)) { Address *address; uint8_t scope = RT_SCOPE_NOWHERE; @@ -1860,17 +1920,22 @@ static void link_update_operstate(Link *link) { if (scope < RT_SCOPE_SITE) /* universally accessible addresses found */ - link->operstate = LINK_OPERSTATE_ROUTABLE; + operstate = LINK_OPERSTATE_ROUTABLE; else if (scope < RT_SCOPE_HOST) /* only link or site local addresses found */ - link->operstate = LINK_OPERSTATE_DEGRADED; + operstate = LINK_OPERSTATE_DEGRADED; else /* no useful addresses found */ - link->operstate = LINK_OPERSTATE_CARRIER; + operstate = LINK_OPERSTATE_CARRIER; } else if (link->flags & IFF_UP) - link->operstate = LINK_OPERSTATE_NO_CARRIER; + operstate = LINK_OPERSTATE_NO_CARRIER; else - link->operstate = LINK_OPERSTATE_OFF; + operstate = LINK_OPERSTATE_OFF; + + if (link->operstate != operstate) { + link->operstate = operstate; + link_send_changed(link, "OperationalState", NULL); + } } int link_save(Link *link) {