X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=93b53ee3c059c22ffe27fd9657d470b769f36cd0;hb=49699bac94d24b444274f91f85c82e6fad04d029;hp=a4f8c59e09d1e3e49516c406731bf7fb83a0747d;hpb=e1853b00ef7cb56cafd908327dd44b3ab48b402c;p=elogind.git diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index a4f8c59e0..93b53ee3c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -75,6 +75,19 @@ static bool link_ipv4ll_enabled(Link *link) { return link->network->ipv4ll; } +static bool link_lldp_enabled(Link *link) { + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if(link->network->bridge) + return false; + + return link->network->lldp; +} + #define FLAG_STRING(string, flag, old, new) \ (((old ^ new) & flag) \ ? ((old & flag) ? (" -" string) : (" +" string)) \ @@ -206,6 +219,12 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { if (r < 0) return -ENOMEM; + r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", + link->ifindex); + if (r < 0) + return -ENOMEM; + + r = hashmap_ensure_allocated(&manager->links, NULL); if (r < 0) return r; @@ -246,6 +265,9 @@ static void link_free(Link *link) { unlink(link->lease_file); free(link->lease_file); + unlink(link->lldp_file); + free(link->lldp_file); + sd_ipv4ll_unref(link->ipv4ll); sd_dhcp6_client_unref(link->dhcp6_client); sd_icmp6_nd_unref(link->icmp6_router_discovery); @@ -364,6 +386,16 @@ static int link_stop_clients(Link *link) { } } + if (link->lldp) { + + k = sd_lldp_stop(link->lldp); + if (k < 0) { + log_link_warning(link, "Could not stop LLDP : %s", + strerror(-r)); + r = k; + } + } + return r; } @@ -576,32 +608,6 @@ int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { return 1; } -int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->manager); - - for (; m; m = sd_rtnl_message_next(m)) { - r = sd_rtnl_message_get_errno(m); - if (r < 0) { - log_link_debug(link, "getting address failed: %s", - strerror(-r)); - continue; - } - - r = link_rtnl_process_address(rtnl, m, link->manager); - if (r < 0) - log_link_warning(link, "could not process address: %s", - strerror(-r)); - } - - return 1; -} - static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; @@ -622,11 +628,8 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) log_link_warning_errno(link, -r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname); - else if (r >= 0) { - /* calling handler directly so take a ref */ - link_ref(link); - link_get_address_handler(rtnl, m, link); - } + else if (r >= 0) + link_rtnl_process_address(rtnl, m, link->manager); if (link->link_messages == 0) { log_link_debug(link, "addresses set"); @@ -685,15 +688,30 @@ 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) { + 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); + if(r < 0) { + log_link_error(link, "Failed to add MAC entry to static MAC table: %s", strerror(-r)); + break; + } + } + + return r; +} + static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; - log_debug_link(link, "set link"); + log_link_debug(link, "set link"); r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_struct_link(LOG_ERR, link, + log_link_struct(link, LOG_ERR, "MESSAGE=%-*s: could not join netdev: %s", IFNAMSIZ, link->ifname, strerror(-r), @@ -836,20 +854,20 @@ static int link_set_bridge(Link *link) { r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); if (r < 0) { - log_error_link(link, "Could not allocate RTM_SETLINK message"); + log_link_error(link, "Could not allocate RTM_SETLINK message"); return r; } r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not set message family %s", strerror(-r)); return r; } r = sd_rtnl_message_open_container(req, IFLA_PROTINFO); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not append IFLA_PROTINFO attribute: %s", strerror(-r)); return r; @@ -858,7 +876,7 @@ static int link_set_bridge(Link *link) { if(link->network->cost != 0) { r = sd_rtnl_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not append IFLA_BRPORT_COST attribute: %s", strerror(-r)); return r; @@ -867,7 +885,7 @@ static int link_set_bridge(Link *link) { r = sd_rtnl_message_close_container(req); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not append IFLA_LINKINFO attribute: %s", strerror(-r)); return r; @@ -875,7 +893,7 @@ static int link_set_bridge(Link *link) { r = sd_rtnl_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not send rtnetlink message: %s", strerror(-r)); return r; @@ -886,37 +904,7 @@ static int link_set_bridge(Link *link) { return r; } -static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { - Link *link = userdata; - - assert(link); - assert(link->network); - assert(link->manager); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - switch(event) { - case DHCP6_EVENT_STOP: - case DHCP6_EVENT_RESEND_EXPIRE: - case DHCP6_EVENT_RETRANS_MAX: - case DHCP6_EVENT_IP_ACQUIRE: - log_link_debug(link, "DHCPv6 event %d", event); - - break; - - default: - if (event < 0) - log_link_warning(link, "DHCPv6 error: %s", - strerror(-event)); - else - log_link_warning(link, "DHCPv6 unknown event: %d", - event); - return; - } -} - -static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { +static void lldp_handler(sd_lldp *lldp, int event, void *userdata) { Link *link = userdata; int r; @@ -924,66 +912,13 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { assert(link->network); assert(link->manager); - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + if (event != UPDATE_INFO) return; - switch(event) { - case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE: - case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER: - return; - - case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT: - case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED: - break; - - default: - if (event < 0) - log_link_warning(link, "ICMPv6 error: %s", - strerror(-event)); - else - log_link_warning(link, "ICMPv6 unknown event: %d", - event); - - return; - } - - if (link->dhcp6_client) - return; - - r = sd_dhcp6_client_new(&link->dhcp6_client); + r = sd_lldp_save(link->lldp, link->lldp_file); if (r < 0) - return; - - r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0); - if (r < 0) { - link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); - return; - } - - r = sd_dhcp6_client_set_mac(link->dhcp6_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), ARPHRD_ETHER); - if (r < 0) { - link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); - return; - } + log_link_warning(link, "could not save LLDP"); - r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex); - if (r < 0) { - link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); - return; - } - - r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler, - link); - if (r < 0) { - link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); - return; - } - - r = sd_dhcp6_client_start(link->dhcp6_client); - if (r < 0) - link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); } static int link_acquire_conf(Link *link) { @@ -1033,6 +968,18 @@ static int link_acquire_conf(Link *link) { } } + if (link_lldp_enabled(link)) { + assert(link->lldp); + + log_link_debug(link, "Starting LLDP"); + + r = sd_lldp_start(link->lldp); + if (r < 0) { + log_link_warning(link, "could not start LLDP "); + return r; + } + } + return 0; } @@ -1074,6 +1021,7 @@ static int link_up(Link *link) { int r; assert(link); + assert(link->network); assert(link->manager); assert(link->manager->rtnl); @@ -1093,6 +1041,22 @@ static int link_up(Link *link) { return r; } + if (link->network->mac) { + r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac); + if (r < 0) { + log_link_error(link, "Could not set MAC address: %s", strerror(-r)); + return r; + } + } + + if (link->network->mtu) { + r = sd_rtnl_message_append_u32(req, IFLA_MTU, link->network->mtu); + if (r < 0) { + log_link_error(link, "Could not set MTU: %s", strerror(-r)); + return r; + } + } + r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); if (r < 0) { @@ -1124,7 +1088,7 @@ static int link_joined(Link *link) { if(link->network->bridge) { r = link_set_bridge(link); if (r < 0) { - log_error_link(link, + log_link_error(link, "Could not set bridge message: %s", strerror(-r)); } @@ -1259,6 +1223,10 @@ static int link_configure(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); + r = link_set_bridge_fdb(link); + if (r < 0) + return r; + if (link_ipv4ll_enabled(link)) { r = ipv4ll_configure(link); if (r < 0) @@ -1282,27 +1250,22 @@ static int link_configure(Link *link) { } if (link_dhcp6_enabled(link)) { - r = sd_icmp6_nd_new(&link->icmp6_router_discovery); - if (r < 0) - return r; - - r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery, - NULL, 0); + r = icmp6_configure(link); if (r < 0) return r; + } - r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery, - &link->mac); + if (link_lldp_enabled(link)) { + r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp); if (r < 0) return r; - r = sd_icmp6_nd_set_index(link->icmp6_router_discovery, - link->ifindex); + r = sd_lldp_attach_event(link->lldp, NULL, 0); if (r < 0) return r; - r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery, - icmp6_router_handler, link); + r = sd_lldp_set_callback(link->lldp, + lldp_handler, link); if (r < 0) return r; } @@ -1400,8 +1363,7 @@ 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) { +int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) { Manager *m = userdata; Link *link = NULL; uint16_t type; @@ -1417,6 +1379,14 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, assert(message); assert(m); + if (sd_rtnl_message_is_error(message)) { + r = sd_rtnl_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive address: %m"); + + return 0; + } + r = sd_rtnl_message_get_type(message, &type); if (r < 0) { log_warning("rtnl: could not get message type"); @@ -1424,13 +1394,16 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, } r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); - if (r < 0 || ifindex <= 0) { - log_warning("rtnl: received address message without valid ifindex, ignoring"); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); return 0; } else { r = link_get(m, ifindex, &link); if (r < 0 || !link) { - log_warning("rtnl: received address for a nonexistent link (%d), ignoring", ifindex); + log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); return 0; } } @@ -1559,7 +1532,6 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, 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; @@ -1577,18 +1549,6 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) { log_link_debug(link, "link %d added", link->ifindex); - 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; - - link_ref(link); - if (detect_container(NULL) <= 0) { /* not in a container, udev will be around */ sprintf(ifindex_str, "n%d", link->ifindex); @@ -1926,6 +1886,19 @@ int link_save(Link *link) { } else unlink(link->lease_file); + if (link->lldp) { + assert(link->network); + + r = sd_lldp_save(link->lldp, link->lldp_file); + if (r < 0) + goto fail; + + fprintf(f, + "LLDP_FILE=%s\n", + link->lldp_file); + } else + unlink(link->lldp_file); + r = fflush_and_check(f); if (r < 0) goto fail;