From 3df9bec57c3e2d96f7e2a25961585cfa609b61eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 19:46:00 +0100 Subject: networkd: rework Domains= setting Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was the "DNS domain" for the network connection, without specifying what that means. With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains=" setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups), while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already implemented before using the "wildcard" domain concept. This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not used by resolved yet, this will be added in a later commit. --- src/basic/strv.c | 31 +++++++++++++++++++++++++++++++ src/basic/strv.h | 2 ++ 2 files changed, 33 insertions(+) (limited to 'src/basic') diff --git a/src/basic/strv.c b/src/basic/strv.c index 0a3d15706f..dc5bafcf24 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -871,3 +871,34 @@ rollback: nl[k] = NULL; return -ENOMEM; } + +int fputstrv(FILE *f, char **l, const char *separator, bool *space) { + bool b = false; + char **s; + int r; + + /* Like fputs(), but for strv, and with a less stupid argument order */ + + if (!f) + f = stdout; + if (!separator) + separator = " "; + if (!space) + space = &b; + + STRV_FOREACH(s, l) { + if (*space) { + r = fputs(separator, f); + if (r < 0) + return r; + } + + r = fputs(*s, f); + if (r < 0) + return r; + + *space = true; + } + + return 0; +} diff --git a/src/basic/strv.h b/src/basic/strv.h index bb61db2638..560f90115c 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -169,3 +169,5 @@ char ***strv_free_free(char ***l); char **strv_skip(char **l, size_t n); int strv_extend_n(char ***l, const char *value, size_t n); + +int fputstrv(FILE *f, char **l, const char *separator, bool *space); -- cgit v1.2.3-54-g00ecf From 0061695507e889069c0c974cf85cd570f7ec9a88 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 20:31:11 +0100 Subject: networkd: use an OrderedSet instead of Set to collect link domains For the search domain logic the order is highly relevant, hence make sure when collecting the various search domains to add them to an ordered set, so that the order between search domains of a specific link is retained. --- Makefile.am | 1 + src/basic/ordered-set.c | 64 ++++++++++++++++++++++++++++++++++++++++++ src/basic/ordered-set.h | 6 ++++ src/network/networkd-manager.c | 39 ++++++++++++------------- 4 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 src/basic/ordered-set.c (limited to 'src/basic') diff --git a/Makefile.am b/Makefile.am index 1f204b826c..f933b5228e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -840,6 +840,7 @@ libbasic_la_SOURCES = \ src/basic/siphash24.h \ src/basic/set.h \ src/basic/ordered-set.h \ + src/basic/ordered-set.c \ src/basic/bitmap.c \ src/basic/bitmap.h \ src/basic/fdset.c \ diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c new file mode 100644 index 0000000000..2e0bdf6488 --- /dev/null +++ b/src/basic/ordered-set.c @@ -0,0 +1,64 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "ordered-set.h" +#include "strv.h" + +int ordered_set_consume(OrderedSet *s, void *p) { + int r; + + r = ordered_set_put(s, p); + if (r <= 0) + free(p); + + return r; +} + +int ordered_set_put_strdup(OrderedSet *s, const char *p) { + char *c; + int r; + + assert(s); + assert(p); + + c = strdup(p); + if (!c) + return -ENOMEM; + + r = ordered_set_consume(s, c); + if (r == -EEXIST) + return 0; + + return r; +} + +int ordered_set_put_strdupv(OrderedSet *s, char **l) { + int n = 0, r; + char **i; + + STRV_FOREACH(i, l) { + r = ordered_set_put_strdup(s, *i); + if (r < 0) + return r; + + n += r; + } + + return n; +} diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h index da10e90ff2..ab185c11aa 100644 --- a/src/basic/ordered-set.h +++ b/src/basic/ordered-set.h @@ -62,9 +62,15 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL); } +int ordered_set_consume(OrderedSet *s, void *p); +int ordered_set_put_strdup(OrderedSet *s, const char *p); +int ordered_set_put_strdupv(OrderedSet *s, char **l); + #define ORDERED_SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); #define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep) +#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 7392f4758d..7b801ae6c9 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -35,6 +35,7 @@ #include "local-addresses.h" #include "netlink-util.h" #include "networkd.h" +#include "ordered-set.h" #include "path-util.h" #include "set.h" #include "udev-util.h" @@ -776,7 +777,7 @@ static int manager_connect_rtnl(Manager *m) { return 0; } -static int set_put_in_addr(Set *s, const struct in_addr *address) { +static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) { char *p; int r; @@ -786,21 +787,21 @@ static int set_put_in_addr(Set *s, const struct in_addr *address) { if (r < 0) return r; - r = set_consume(s, p); + r = ordered_set_consume(s, p); if (r == -EEXIST) return 0; return r; } -static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) { +static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) { int r, i, c = 0; assert(s); assert(n <= 0 || addresses); for (i = 0; i < n; i++) { - r = set_put_in_addr(s, addresses+i); + r = ordered_set_put_in_addr(s, addresses+i); if (r < 0) return r; @@ -810,17 +811,17 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) { return c; } -static void print_string_set(FILE *f, const char *field, Set *s) { +static void print_string_set(FILE *f, const char *field, OrderedSet *s) { bool space = false; Iterator i; char *p; - if (set_isempty(s)) + if (ordered_set_isempty(s)) return; fputs(field, f); - SET_FOREACH(p, s, i) { + ORDERED_SET_FOREACH(p, s, i) { if (space) fputc(' ', f); fputs(p, f); @@ -830,7 +831,7 @@ static void print_string_set(FILE *f, const char *field, Set *s) { } static int manager_save(Manager *m) { - _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; + _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; Link *link; Iterator i; _cleanup_free_ char *temp_path = NULL; @@ -843,19 +844,19 @@ static int manager_save(Manager *m) { assert(m->state_file); /* We add all NTP and DNS server to a set, to filter out duplicates */ - dns = set_new(&string_hash_ops); + dns = ordered_set_new(&string_hash_ops); if (!dns) return -ENOMEM; - ntp = set_new(&string_hash_ops); + ntp = ordered_set_new(&string_hash_ops); if (!ntp) return -ENOMEM; - search_domains = set_new(&string_hash_ops); + search_domains = ordered_set_new(&string_hash_ops); if (!search_domains) return -ENOMEM; - route_domains = set_new(&string_hash_ops); + route_domains = ordered_set_new(&string_hash_ops); if (!route_domains) return -ENOMEM; @@ -870,19 +871,19 @@ static int manager_save(Manager *m) { continue; /* First add the static configured entries */ - r = set_put_strdupv(dns, link->network->dns); + r = ordered_set_put_strdupv(dns, link->network->dns); if (r < 0) return r; - r = set_put_strdupv(ntp, link->network->ntp); + r = ordered_set_put_strdupv(ntp, link->network->ntp); if (r < 0) return r; - r = set_put_strdupv(search_domains, link->network->search_domains); + r = ordered_set_put_strdupv(search_domains, link->network->search_domains); if (r < 0) return r; - r = set_put_strdupv(route_domains, link->network->route_domains); + r = ordered_set_put_strdupv(route_domains, link->network->route_domains); if (r < 0) return r; @@ -895,7 +896,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { - r = set_put_in_addrv(dns, addresses, r); + r = ordered_set_put_in_addrv(dns, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -907,7 +908,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { - r = set_put_in_addrv(ntp, addresses, r); + r = ordered_set_put_in_addrv(ntp, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -919,7 +920,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); if (r >= 0) { - r = set_put_strdup(search_domains, domainname); + r = ordered_set_put_strdup(search_domains, domainname); if (r < 0) return r; } else if (r != -ENODATA) -- cgit v1.2.3-54-g00ecf From d390f8ef2dc0cd041914d3c2fd3e1081605cbfc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 22:42:36 +0100 Subject: util: introduce fputs_with_space() and make use of it at various places The call combines outputing a string with prefixing it with a space, optionally. This is useful to shorten the logic for outputing lists of strings, that are space separated. --- src/basic/fileio.c | 29 +++++++++++++++++++++++++++++ src/basic/fileio.h | 2 ++ src/basic/strv.c | 15 ++------------- src/network/networkd-link.c | 40 ++++++++++------------------------------ src/network/networkd-manager.c | 9 +++------ 5 files changed, 46 insertions(+), 49 deletions(-) (limited to 'src/basic') diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 5ed5460904..3ff70310e1 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1251,3 +1251,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) { *ret = (usec_t) t; return 0; } + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { + int r; + + assert(s); + + /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter + * when specified shall initially point to a boolean variable initialized to false. It is set to true after the + * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each + * element, but not before the first one. */ + + if (!f) + f = stdout; + + if (space) { + if (!separator) + separator = " "; + + if (*space) { + r = fputs(separator, f); + if (r < 0) + return r; + } + + *space = true; + } + + return fputs(s, f); +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 95e8698941..9e09574133 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -82,3 +82,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret); int write_timestamp_file_atomic(const char *fn, usec_t n); int read_timestamp_file(const char *fn, usec_t *ret); + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); diff --git a/src/basic/strv.c b/src/basic/strv.c index dc5bafcf24..5532c53ad1 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -29,6 +29,7 @@ #include "alloc-util.h" #include "escape.h" #include "extract-word.h" +#include "fileio.h" #include "string-util.h" #include "strv.h" #include "util.h" @@ -879,25 +880,13 @@ int fputstrv(FILE *f, char **l, const char *separator, bool *space) { /* Like fputs(), but for strv, and with a less stupid argument order */ - if (!f) - f = stdout; - if (!separator) - separator = " "; if (!space) space = &b; STRV_FOREACH(s, l) { - if (*space) { - r = fputs(separator, f); - if (r < 0) - return r; - } - - r = fputs(*s, f); + r = fputs_with_space(f, *s, separator, space); if (r < 0) return r; - - *space = true; } return 0; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index bf13544dbc..a2f0eceb6d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2820,12 +2820,8 @@ int link_save(Link *link) { fputs("DOMAINS=", f); fputstrv(f, link->network->search_domains, NULL, &space); - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) { - if (space) - fputc(' ', f); - fputs(dhcp_domainname, f); - space = true; - } + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); @@ -2835,12 +2831,8 @@ int link_save(Link *link) { fputs("ROUTE_DOMAINS=", f); fputstrv(f, link->network->route_domains, NULL, NULL); - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) { - if (space) - fputc(' ', f); - fputs(dhcp_domainname, f); - space = true; - } + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); @@ -2861,12 +2853,8 @@ int link_save(Link *link) { fputs("DNSSEC_NTA=", f); space = false; - SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) { - if (space) - fputc(' ', f); - fputs(n, f); - space = true; - } + SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) + fputs_with_space(f, n, NULL, &space); fputc('\n', f); } @@ -2906,12 +2894,8 @@ int link_save(Link *link) { bool space = false; fputs("CARRIER_BOUND_TO=", f); - HASHMAP_FOREACH(carrier, link->bound_to_links, i) { - if (space) - fputc(' ', f); - fputs(carrier->ifname, f); - space = true; - } + HASHMAP_FOREACH(carrier, link->bound_to_links, i) + fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } @@ -2921,12 +2905,8 @@ int link_save(Link *link) { bool space = false; fputs("CARRIER_BOUND_BY=", f); - HASHMAP_FOREACH(carrier, link->bound_by_links, i) { - if (space) - fputc(' ', f); - fputs(carrier->ifname, f); - space = true; - } + HASHMAP_FOREACH(carrier, link->bound_by_links, i) + fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 723a92b5b8..c10635d202 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -822,12 +822,9 @@ static void print_string_set(FILE *f, const char *field, OrderedSet *s) { fputs(field, f); - ORDERED_SET_FOREACH(p, s, i) { - if (space) - fputc(' ', f); - fputs(p, f); - space = true; - } + ORDERED_SET_FOREACH(p, s, i) + fputs_with_space(f, p, NULL, &space); + fputc('\n', f); } -- cgit v1.2.3-54-g00ecf