diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/networkctl.c | 293 | ||||
-rw-r--r-- | src/network/networkd-link.c | 124 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 2 | ||||
-rw-r--r-- | src/network/networkd-network.c | 10 | ||||
-rw-r--r-- | src/network/networkd-network.h | 14 |
5 files changed, 192 insertions, 251 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 185bdaf293..eecdebd25d 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -23,6 +23,7 @@ #include "sd-device.h" #include "sd-hwdb.h" +#include "sd-lldp.h" #include "sd-netlink.h" #include "sd-network.h" @@ -30,6 +31,7 @@ #include "arphrd-list.h" #include "device-util.h" #include "ether-addr-util.h" +#include "fd-util.h" #include "hwdb-util.h" #include "lldp.h" #include "local-addresses.h" @@ -38,6 +40,7 @@ #include "pager.h" #include "parse-util.h" #include "socket-util.h" +#include "sparse-endian.h" #include "stdio-util.h" #include "string-table.h" #include "string-util.h" @@ -745,162 +748,29 @@ static int link_status(int argc, char *argv[], void *userdata) { return 0; } -const char *lldp_system_capability_to_string(LLDPSystemCapabilities d) _const_; -LLDPSystemCapabilities lldp_system_capability_from_string(const char *d) _pure_; - -static const char* const lldp_system_capability_table[_LLDP_SYSTEM_CAPABILITIES_MAX + 1] = { - [LLDP_SYSTEM_CAPABILITIES_OTHER] = "O", - [LLDP_SYSTEM_CAPABILITIES_REPEATER] = "P", - [LLDP_SYSTEM_CAPABILITIES_BRIDGE] = "B", - [LLDP_SYSTEM_CAPABILITIES_WLAN_AP] = "W", - [LLDP_SYSTEM_CAPABILITIES_ROUTER] = "R", - [LLDP_SYSTEM_CAPABILITIES_PHONE] = "T", - [LLDP_SYSTEM_CAPABILITIES_DOCSIS] = "D", - [LLDP_SYSTEM_CAPABILITIES_STATION] = "A", - [LLDP_SYSTEM_CAPABILITIES_CVLAN] = "C", - [LLDP_SYSTEM_CAPABILITIES_SVLAN] = "S", - [LLDP_SYSTEM_CAPABILITIES_TPMR] = "M", - [_LLDP_SYSTEM_CAPABILITIES_MAX] = "N/A", -}; - -DEFINE_STRING_TABLE_LOOKUP(lldp_system_capability, LLDPSystemCapabilities); - -static char *lldp_system_caps(uint16_t cap) { - _cleanup_free_ char *s = NULL, *t = NULL; - char *capability; - - t = strdup("[ "); - if (!t) - return NULL; - - if (cap & LLDP_SYSTEM_CAPABILITIES_OTHER) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_OTHER), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_REPEATER) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_REPEATER), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_BRIDGE) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_BRIDGE), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_WLAN_AP) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_WLAN_AP), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_ROUTER) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_ROUTER), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_PHONE) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_PHONE), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_DOCSIS) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_DOCSIS), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_STATION) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_STATION), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_CVLAN) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_CVLAN), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_SVLAN) { - s = strjoin(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_SVLAN), " ", NULL); - if (!s) - return NULL; - - free(t); - t = s; - } - - if (cap & LLDP_SYSTEM_CAPABILITIES_TPMR) { - s = strappend(t, lldp_system_capability_to_string(LLDP_SYSTEM_CAPABILITIES_TPMR)); - if (!s) - return NULL; - - free(t); - } - - if (!s) { - s = strappend(t, lldp_system_capability_to_string(_LLDP_SYSTEM_CAPABILITIES_MAX)); - if (!s) - return NULL; - - free(t); - } +static char *lldp_capabilities_to_string(uint16_t x) { + static const char characters[] = { + 'o', 'p', 'b', 'w', 'r', 't', 'd', 'a', 'c', 's', 'm', + }; + char *ret; + unsigned i; - t = strappend(s, "]"); - if (!t) + ret = new(char, ELEMENTSOF(characters) + 1); + if (!ret) return NULL; - free(s); - capability = t; + for (i = 0; i < ELEMENTSOF(characters); i++) + ret[i] = (x & (1U << i)) ? characters[i] : '.'; - s = NULL; - t = NULL; - - return capability; + ret[i] = 0; + return ret; } static int link_lldp_status(int argc, char *argv[], void *userdata) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ LinkInfo *links = NULL; - double ttl = -1; - uint32_t capability; int i, r, c, j; - const char *p; - char **s; pager_open_if_enabled(); @@ -925,88 +795,85 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) { return rtnl_log_parse_error(c); if (arg_legend) - printf("%s %16s %24s %16s %16s\n", "Local Intf", "Device ID", "Port ID", "TTL", "Capability"); + printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", + "LINK", + "CHASSIS ID", + "SYSTEM NAME", + "CAPS", + "PORT ID", + "PORT DESCRIPTION"); for (i = j = 0; i < c; i++) { - _cleanup_free_ char *chassis = NULL, *port = NULL, *cap = NULL, *lldp = NULL; - _cleanup_strv_free_ char **l = NULL; - - r = sd_network_link_get_lldp(links[i].ifindex, &lldp); - if (r < 0) - continue; - - l = strv_split_newlines(lldp); - if (!l) - return -ENOMEM; - - STRV_FOREACH(s, l) { - - p = *s; - for (;;) { - _cleanup_free_ char *a = NULL, *b = NULL, *word = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); - if (r < 0) - return log_error_errno(r, "Failed to parse LLDP syntax \"%s\": %m", *s); - - if (r == 0) - break; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; - r = split_pair(word, "=", &a, &b); - if (r < 0) - continue; + if (asprintf(&p, "/run/systemd/netif/lldp/%i", links[i].ifindex) < 0) + return log_oom(); - if (streq(a, "_Chassis")) { - r = free_and_strdup(&chassis, b); - if (r < 0) - return r; - - } else if (streq(a, "_Port")) { - r = free_and_strdup(&port, b); - if (r < 0) - return r; - - } else if (streq(a, "_TTL")) { - long long unsigned x = 0; - usec_t time; - - r = safe_atollu(b, &x); - if (r < 0 || (usec_t) x != x) - return log_warning_errno(r < 0 ? r : ERANGE, - "Failed to parse TTL \"%s\": %m", b); + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) + continue; - time = now(clock_boottime_or_monotonic()); - if (x < time) - continue; + log_warning_errno(errno, "Failed to open %s, ignoring: %m", p); + continue; + } - ttl = (double) (x - time) / USEC_PER_SEC; + for (;;) { + const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL, *capabilities = NULL; + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + _cleanup_free_ void *raw = NULL; + uint16_t cc; + le64_t u; + size_t l; - } else if (streq(a, "_CAP")) { - sscanf(b, "%x", &capability); + l = fread(&u, 1, sizeof(u), f); + if (l == 0 && feof(f)) /* EOF */ + break; + if (l != sizeof(u)) { + log_warning("Premature end of file, ignoring."); + break; + } - cap = lldp_system_caps(capability); - } + raw = new(uint8_t, le64toh(u)); + if (!raw) + return log_oom(); + if (fread(raw, 1, le64toh(u), f) != le64toh(u)) { + log_warning("Premature end of file, ignoring."); + break; } - if (ttl >= 0) { - printf("%10s %24s %16s %16f %16s\n", - links[i].name, - strna(chassis), strna(port), - ttl, cap); - j++; + r = sd_lldp_neighbor_from_raw(&n, raw, le64toh(u)); + if (r < 0) { + log_warning_errno(r, "Failed to parse LLDP data, ignoring: %m"); + break; } + + (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id); + (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); + (void) sd_lldp_neighbor_get_system_name(n, &system_name); + (void) sd_lldp_neighbor_get_port_description(n, &port_description); + + if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) + capabilities = lldp_capabilities_to_string(cc); + + printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", + links[i].name, + strna(chassis_id), + strna(system_name), + strna(capabilities), + strna(port_id), + strna(port_description)); } } - if (arg_legend) { - printf("\nCapability Codes:\n" - "(O) - Other, (P) - Repeater, (B) - Bridge , (W) - WLAN Access Point, (R) = Router,\n" - "(T) - Telephone, (D) - Data Over Cable Service Interface Specifications, (A) - Station,\n" - "(C) - Customer VLAN, (S) - Service VLAN, (M) - Two-port MAC Relay (TPMR)\n\n"); - - printf("Total entries displayed: %d\n", j); - } + if (arg_legend) + printf("\nCapabilities:\n" + "o - Other; p - Repeater; b - Bridge; w - WLAN Access Point; r - Router;\n" + "t - Telephone; d - DOCSIS cable device; a - Station; c - Customer VLAN;\n" + "s - Service VLAN, m - Two-port MAC Relay (TPMR)\n\n" + "Total entries displayed: %i\n", j); return 0; } @@ -1022,7 +889,7 @@ static void help(void) { "Commands:\n" " list List links\n" " status [LINK...] Show link status\n" - " lldp Show lldp information\n" + " lldp Show lldp neighbors\n" , program_invocation_short_name); } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e63af3afdb..02fb04e0cb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -26,6 +26,7 @@ #include "dhcp-lease-internal.h" #include "fd-util.h" #include "fileio.h" +#include "lldp.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-link.h" @@ -103,7 +104,7 @@ bool link_lldp_enabled(Link *link) { if (link->network->bridge) return false; - return link->network->lldp; + return link->network->lldp_mode != LLDP_MODE_NO; } static bool link_ipv4_forward_enabled(Link *link) { @@ -347,18 +348,15 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); if (r < 0) - log_link_debug(link, "MAC address not found for new device, continuing without"); + log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); - r = asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex); - if (r < 0) + if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) return -ENOMEM; - r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex); - if (r < 0) + if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) return -ENOMEM; - r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex); - if (r < 0) + if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) return -ENOMEM; r = hashmap_ensure_allocated(&manager->links, NULL); @@ -409,7 +407,6 @@ static void link_free(Link *link) { free(link->lease_file); sd_lldp_unref(link->lldp); - free(link->lldp_file); sd_ipv4ll_unref(link->ipv4ll); @@ -1218,7 +1215,7 @@ static int link_set_bridge(Link *link) { if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); - if(link->network->cost != 0) { + if (link->network->cost != 0) { r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); if (r < 0) return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); @@ -1237,24 +1234,83 @@ static int link_set_bridge(Link *link) { return r; } -static void lldp_handler(sd_lldp *lldp, int event, void *userdata) { - Link *link = userdata; - int r; +static int link_lldp_save(Link *link) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + sd_lldp_neighbor **l = NULL; + int n = 0, r, i; assert(link); - assert(link->network); - assert(link->manager); + assert(link->lldp_file); + + if (!link->lldp) { + (void) unlink(link->lldp_file); + return 0; + } + + r = sd_lldp_get_neighbors(link->lldp, &l); + if (r < 0) + goto finish; + if (r == 0) { + (void) unlink(link->lldp_file); + goto finish; + } + + n = r; + + r = fopen_temporary(link->lldp_file, &f, &temp_path); + if (r < 0) + goto finish; + + fchmod(fileno(f), 0644); - switch (event) { - case SD_LLDP_EVENT_UPDATE_INFO: - r = sd_lldp_save(link->lldp, link->lldp_file); + for (i = 0; i < n; i++) { + const void *p; + le64_t u; + size_t sz; + + r = sd_lldp_neighbor_get_raw(l[i], &p, &sz); if (r < 0) - log_link_warning_errno(link, r, "Could not save LLDP: %m"); + goto finish; + + u = htole64(sz); + (void) fwrite(&u, 1, sizeof(u), f); + (void) fwrite(p, 1, sz, f); + } - break; - default: - break; + r = fflush_and_check(f); + if (r < 0) + goto finish; + + if (rename(temp_path, link->lldp_file) < 0) { + r = -errno; + goto finish; } + +finish: + if (r < 0) { + (void) unlink(link->lldp_file); + if (temp_path) + (void) unlink(temp_path); + + log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file); + } + + if (l) { + for (i = 0; i < n; i++) + sd_lldp_neighbor_unref(l[i]); + free(l); + } + + return r; +} + +static void lldp_handler(sd_lldp *lldp, void *userdata) { + Link *link = userdata; + + assert(link); + + (void) link_lldp_save(link); } static int link_acquire_ipv6_conf(Link *link) { @@ -2116,7 +2172,14 @@ static int link_configure(Link *link) { } if (link_lldp_enabled(link)) { - r = sd_lldp_new(link->ifindex, &link->lldp); + r = sd_lldp_new(&link->lldp, link->ifindex); + if (r < 0) + return r; + + r = sd_lldp_match_capabilities(link->lldp, + link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ? + _LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS : + _LLDP_SYSTEM_CAPABILITIES_ALL); if (r < 0) return r; @@ -2714,6 +2777,8 @@ int link_save(Link *link) { return 0; } + link_lldp_save(link); + admin_state = link_state_to_string(link->state); assert(admin_state); @@ -2953,19 +3018,6 @@ int link_save(Link *link) { } } - 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; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 409df1709f..d67da5d7b6 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -40,7 +40,7 @@ Network.DHCPServer, config_parse_bool, Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local) Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) -Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp) +Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode) Network.Address, config_parse_address, 0, 0 Network.Gateway, config_parse_gateway, 0, 0 Network.Domains, config_parse_domains, 0, 0 diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 4315790093..a6512d26e5 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -1013,3 +1013,13 @@ static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); + +DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting."); + +static const char* const lldp_mode_table[_LLDP_MODE_MAX] = { + [LLDP_MODE_NO] = "no", + [LLDP_MODE_YES] = "yes", + [LLDP_MODE_ROUTERS_ONLY] = "routers-only", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 03c3f206c3..9dcebfbf7b 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -58,6 +58,14 @@ typedef enum DHCPUseDomains { _DHCP_USE_DOMAINS_INVALID = -1, } DHCPUseDomains; +typedef enum LLDPMode { + LLDP_MODE_NO = 0, + LLDP_MODE_YES = 1, + LLDP_MODE_ROUTERS_ONLY = 2, + _LLDP_MODE_MAX, + _LLDP_MODE_INVALID = -1, +} LLDPMode; + struct Network { Manager *manager; @@ -137,7 +145,7 @@ struct Network { struct ether_addr *mac; unsigned mtu; - bool lldp; + LLDPMode lldp_mode; LIST_HEAD(Address, static_addresses); LIST_HEAD(Route, static_routes); @@ -181,6 +189,7 @@ int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigne int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* Legacy IPv4LL support */ int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); @@ -197,3 +206,6 @@ IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; + +const char* lldp_mode_to_string(LLDPMode m) _const_; +LLDPMode lldp_mode_from_string(const char *s) _pure_; |