From 34437b4f9c9c51b0a6f93788bdb9a105b8e46b66 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Feb 2016 17:58:52 +0100 Subject: sd-lldp: rework sd-lldp API This reworks the sd-lldp substantially, simplifying things on one hand, and extending the logic a bit on the other. Specifically: - Besides the sd_lldp object only one other object is maintained now, sd_lldp_neighbor. It's used both as storage for literal LLDP packets, and for maintainging info about peers in the database. Separation between packet, TLV and chassis data is not maintained anymore. This should be a major simplification. - The sd-lldp API has been extended so that a couple of per-neighbor fields may be queried directly, without iterating through the object. Other fields that may appear multiple times, OTOH have to be iterated through. - The maximum number of entries in the neighbor database is now configurable during runtime. - The generation of callbacks from sd_lldp objects is more restricted: callbacks are only invoked when actual data changed. - The TTL information is now hooked with a timer event, so that removals from the neighbor database due to TTLs now result in a callback event. - Querying LLDP neighbor database will now return a strictly ordered array, to guarantee stability. - A "capabilities" mask may now be configured, that selects what type of LLDP neighbor data is collected. This may be used to restrict collection of LLDP info about routers instead of all neighbors. This is now exposed via networkd's LLDP= setting. - sd-lldp's API to serialize the collected data to text files has been removed. Instead, there's now an API to extract the raw binary data from LLDP neighbor objects, as well as one to convert this raw binary data back to an LLDP neighbor object. networkd will save this raw binary data to /run now, and the client side can simply parse the information. - support for parsing the more exotic TLVs has been removed, since we are not using that. Instead there are now APIs to extract the raw data from TLVs. Given how easy it is to parse the TLVs clients should do so now directly instead of relying on our APIs for that. - A lot of the APIs that parse out LLDP strings have been simplified so that they actually return strings, instead of char arrays with a length. To deal with possibly dangerous characters the strings are escaped if needed. - APIs to extract and format the chassis and port IDs as strings has been added. - lldp.h has been simplified a lot. The enums are anonymous now, since they were never used as enums, but simply as constants. Most definitions we don't actually use ourselves have eben removed. --- src/libsystemd/sd-network/sd-network.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'src/libsystemd/sd-network') diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 62051992ef..26b283f60d 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -187,32 +187,7 @@ _public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char return network_link_get_strv(ifindex, "DNSSEC_NTA", nta); } -_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) { - _cleanup_free_ char *s = NULL, *p = NULL; - size_t size; - int r; - - assert_return(ifindex > 0, -EINVAL); - assert_return(lldp, -EINVAL); - - if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0) - return -ENOMEM; - - r = read_full_file(p, &s, &size); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; - if (size <= 0) - return -ENODATA; - - *lldp = s; - s = NULL; - - return 0; -} - -int sd_network_link_get_timezone(int ifindex, char **ret) { +_public_ int sd_network_link_get_timezone(int ifindex, char **ret) { return network_link_get_string(ifindex, "TIMEZONE", ret); } -- cgit v1.2.3-54-g00ecf From b295beea88a7f2c48897b2887acbe99937335c8f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Feb 2016 20:43:03 +0100 Subject: networkd: rework how carrier bindings are serialized Instead of serializing the interface name, expose the interface index, since that's the only stable identifier. --- src/libsystemd/sd-network/sd-network.c | 62 +++++++++++++++++++++++++++++++--- src/network/networkctl.c | 31 ++++++++++++++--- src/network/networkd-link.c | 52 ++++++++++++++-------------- src/systemd/sd-network.h | 10 +++--- 4 files changed, 117 insertions(+), 38 deletions(-) (limited to 'src/libsystemd/sd-network') diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 26b283f60d..037ffb6e75 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -207,12 +207,66 @@ _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret); } -_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) { - return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret); +static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { + _cleanup_free_ char *p = NULL, *s = NULL; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ int *ifis = NULL; + size_t allocated = 0, c = 0; + const char *x; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(ret, -EINVAL); + + if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) + return -ENOMEM; + + r = parse_env_file(p, NEWLINE, key, &s, NULL); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) { + *ret = NULL; + return 0; + } + + x = s; + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&x, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + r = parse_ifindex(word, &ifindex); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(ifis, allocated, c + 1)) + return -ENOMEM; + + ifis[c++] = ifindex; + } + + if (!GREEDY_REALLOC(ifis, allocated, c + 1)) + return -ENOMEM; + ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice*/ + + *ret = ifis; + ifis = NULL; + + return c; +} + +_public_ int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) { + return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret); } -_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) { - return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret); +_public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) { + return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret); } static inline int MONITOR_TO_FD(sd_network_monitor *m) { diff --git a/src/network/networkctl.c b/src/network/networkctl.c index c5da24e75b..8abb1eff9a 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -662,6 +662,30 @@ static int dump_lldp_neighbors(const char *prefix, int ifindex) { return c; } +static void dump_ifindexes(const char *prefix, const int *ifindexes) { + unsigned c; + + assert(prefix); + + if (!ifindexes || ifindexes[0] <= 0) + return; + + for (c = 0; ifindexes[c] > 0; c++) { + char name[IF_NAMESIZE+1]; + + printf("%*s", + (int) strlen(prefix), + c == 0 ? prefix : ""); + + if (if_indextoname(ifindexes[c], name)) + fputs(name, stdout); + else + printf("%i", ifindexes[c]); + + fputc('\n', stdout); + } +} + static void dump_list(const char *prefix, char **l) { char **i; @@ -689,8 +713,7 @@ static int link_status_one( const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; - _cleanup_strv_free_ char **carrier_bound_to = NULL; - _cleanup_strv_free_ char **carrier_bound_by = NULL; + _cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL; int r; assert(rtnl); @@ -777,8 +800,8 @@ static int link_status_one( dump_list(" NTP: ", ntp); - dump_list("Carrier Bound To: ", carrier_bound_to); - dump_list("Carrier Bound By: ", carrier_bound_by); + dump_ifindexes("Carrier Bound To: ", carrier_bound_to); + dump_ifindexes("Carrier Bound By: ", carrier_bound_by); (void) sd_network_link_get_timezone(info->ifindex, &tz); if (tz) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 02fb04e0cb..32437d2195 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1622,7 +1622,7 @@ static int link_new_bound_by_list(Link *link) { m = link->manager; - HASHMAP_FOREACH (carrier, m->links, i) { + HASHMAP_FOREACH(carrier, m->links, i) { if (!carrier->network) continue; @@ -1641,7 +1641,7 @@ static int link_new_bound_by_list(Link *link) { if (list_updated) link_dirty(link); - HASHMAP_FOREACH (carrier, link->bound_by_links, i) { + HASHMAP_FOREACH(carrier, link->bound_by_links, i) { r = link_put_carrier(carrier, link, &carrier->bound_to_links); if (r < 0) return r; @@ -2631,7 +2631,6 @@ int link_carrier_reset(Link *link) { return 0; } - int link_update(Link *link, sd_netlink_message *m) { struct ether_addr mac; const char *ifname; @@ -2752,12 +2751,34 @@ int link_update(Link *link, sd_netlink_message *m) { r = link_carrier_lost(link); if (r < 0) return r; - } return 0; } +static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { + bool space = false; + Iterator i; + Link *link; + + assert(f); + assert(prefix); + + if (hashmap_isempty(h)) + return; + + fputs(prefix, f); + HASHMAP_FOREACH(link, h, i) { + if (space) + fputc(' ', f); + + fprintf(f, "%i", link->ifindex); + space = true; + } + + fputc('\n', f); +} + int link_save(Link *link) { _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; @@ -2958,27 +2979,8 @@ int link_save(Link *link) { fputc('\n', f); } - if (!hashmap_isempty(link->bound_to_links)) { - Link *carrier; - bool space = false; - - fputs("CARRIER_BOUND_TO=", f); - HASHMAP_FOREACH(carrier, link->bound_to_links, i) - fputs_with_space(f, carrier->ifname, NULL, &space); - - fputc('\n', f); - } - - if (!hashmap_isempty(link->bound_by_links)) { - Link *carrier; - bool space = false; - - fputs("CARRIER_BOUND_BY=", f); - HASHMAP_FOREACH(carrier, link->bound_by_links, i) - fputs_with_space(f, carrier->ifname, NULL, &space); - - fputc('\n', f); - } + print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links); + print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links); if (link->dhcp_lease) { struct in_addr address; diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index 56986c984d..0f13e2bae7 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -99,11 +99,11 @@ int sd_network_link_get_network_file(int ifindex, char **filename); /* Get DNS entries for a given link. These are string representations of * IP addresses */ -int sd_network_link_get_dns(int ifindex, char ***addr); +int sd_network_link_get_dns(int ifindex, char ***ret); /* Get NTP entries for a given link. These are domain names or string * representations of IP addresses */ -int sd_network_link_get_ntp(int ifindex, char ***addr); +int sd_network_link_get_ntp(int ifindex, char ***ret); /* Indicates whether or not LLMNR should be enabled for the link * Possible levels of support: yes, no, resolve @@ -139,11 +139,11 @@ int sd_network_link_get_search_domains(int ifindex, char ***domains); /* Get the route DNS domain names for a given link. */ int sd_network_link_get_route_domains(int ifindex, char ***domains); -/* Get the CARRIERS to which current link is bound to. */ -int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers); +/* Get the carrier interface indexes to which current link is bound to. */ +int sd_network_link_get_carrier_bound_to(int ifindex, int **ifindexes); /* Get the CARRIERS that are bound to current link. */ -int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers); +int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes); /* Get the timezone that was learnt on a specific link. */ int sd_network_link_get_timezone(int ifindex, char **timezone); -- cgit v1.2.3-54-g00ecf From 5f02f341c08c2a1cd05cc5066ca94bc6aa43243c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 20 Feb 2016 22:06:12 +0100 Subject: sd-network: use xsprintf() instead of asprintf() where we can --- src/libsystemd/sd-network/sd-network.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'src/libsystemd/sd-network') diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 037ffb6e75..580047d3ab 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -31,6 +31,7 @@ #include "fs-util.h" #include "macro.h" #include "parse-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "util.h" @@ -102,16 +103,16 @@ _public_ int sd_network_get_route_domains(char ***ret) { } static int network_link_get_string(int ifindex, const char *field, char **ret) { - _cleanup_free_ char *s = NULL, *p = NULL; + char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + _cleanup_free_ char *s = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); - if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0) - return -ENOMEM; + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); - r = parse_env_file(p, NEWLINE, field, &s, NULL); + r = parse_env_file(path, NEWLINE, field, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) @@ -126,17 +127,16 @@ static int network_link_get_string(int ifindex, const char *field, char **ret) { } static int network_link_get_strv(int ifindex, const char *key, char ***ret) { - _cleanup_free_ char *p = NULL, *s = NULL; + char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ char *s = NULL; int r; assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, key, &s, NULL); + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + r = parse_env_file(path, NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) @@ -208,9 +208,10 @@ _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) { } static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { - _cleanup_free_ char *p = NULL, *s = NULL; + char path[strlen("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; _cleanup_strv_free_ char **a = NULL; _cleanup_free_ int *ifis = NULL; + _cleanup_free_ char *s = NULL; size_t allocated = 0, c = 0; const char *x; int r; @@ -218,10 +219,8 @@ static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { assert_return(ifindex > 0, -EINVAL); assert_return(ret, -EINVAL); - if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) - return -ENOMEM; - - r = parse_env_file(p, NEWLINE, key, &s, NULL); + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + r = parse_env_file(path, NEWLINE, key, &s, NULL); if (r == -ENOENT) return -ENODATA; if (r < 0) -- cgit v1.2.3-54-g00ecf