Merge pull request #2437 from poettering/dnssec19

nineteenth dnssec patch
This commit is contained in:
Tom Gundersen
2016-01-26 18:07:19 +01:00
39 changed files with 723 additions and 464 deletions
+29
View File
@@ -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);
}
+2
View File
@@ -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);
+64
View File
@@ -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 <http://www.gnu.org/licenses/>.
***/
#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;
}
+6
View File
@@ -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)
+20
View File
@@ -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"
@@ -871,3 +872,22 @@ 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 (!space)
space = &b;
STRV_FOREACH(s, l) {
r = fputs_with_space(f, *s, separator, space);
if (r < 0)
return r;
}
return 0;
}
+2
View File
@@ -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);
+2
View File
@@ -794,6 +794,8 @@ int main(int argc, char* argv[]) {
IOVEC_SET_STRING(iovec[j++], core_timestamp);
IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
assert_cc(2 == LOG_CRIT);
IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
/* Vacuum before we write anything again */
+1
View File
@@ -372,6 +372,7 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
xsprintf(error, "ERRNO=%i", _saved_errno_);
assert_cc(3 == LOG_ERR);
IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
IOVEC_SET_STRING(iov[skip+1], buffer);
IOVEC_SET_STRING(iov[skip+2], error);
+2 -2
View File
@@ -397,8 +397,8 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
IOVEC_SET_STRING(iov[n_iov++], id_field);
assert_cc(32 == LOG_AUTH);
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=32");
assert_cc(4 == LOG_FAC(LOG_AUTH));
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=4");
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_IDENTIFIER=audit");
type_name = audit_type_name_alloca(type);
+2
View File
@@ -866,10 +866,12 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
assert(s);
assert(format);
assert_cc(3 == LOG_FAC(LOG_DAEMON));
IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3");
IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald");
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
assert_cc(6 == LOG_INFO);
IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
+36 -40
View File
@@ -353,6 +353,38 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
return 0;
}
static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
_cleanup_free_ char *name = NULL, *normalized = NULL;
int r;
assert(option);
assert(ret);
r = lease_parse_string(option, len, &name);
if (r < 0)
return r;
if (!name) {
*ret = mfree(*ret);
return 0;
}
r = dns_name_normalize(name, &normalized);
if (r < 0)
return r;
if (is_localhost(normalized))
return -EINVAL;
if (dns_name_is_root(normalized))
return -EINVAL;
free(*ret);
*ret = normalized;
normalized = NULL;
return 0;
}
static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
@@ -547,59 +579,23 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
break;
case SD_DHCP_OPTION_DOMAIN_NAME: {
_cleanup_free_ char *domainname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &domainname);
case SD_DHCP_OPTION_DOMAIN_NAME:
r = lease_parse_domain(option, len, &lease->domainname);
if (r < 0) {
log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
return 0;
}
r = dns_name_normalize(domainname, &normalized);
if (r < 0) {
log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
return 0;
}
if (is_localhost(normalized)) {
log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
break;
}
free(lease->domainname);
lease->domainname = normalized;
normalized = NULL;
break;
}
case SD_DHCP_OPTION_HOST_NAME: {
_cleanup_free_ char *hostname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &hostname);
case SD_DHCP_OPTION_HOST_NAME:
r = lease_parse_domain(option, len, &lease->hostname);
if (r < 0) {
log_debug_errno(r, "Failed to parse host name, ignoring: %m");
return 0;
}
r = dns_name_normalize(hostname, &normalized);
if (r < 0) {
log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
return 0;
}
if (is_localhost(normalized)) {
log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
return 0;
}
free(lease->hostname);
lease->hostname = normalized;
normalized = NULL;
break;
}
case SD_DHCP_OPTION_ROOT_PATH:
r = lease_parse_string(option, len, &lease->root_path);
+10 -22
View File
@@ -95,10 +95,14 @@ _public_ int sd_network_get_ntp(char ***ret) {
return network_get_strv("NTP", ret);
}
_public_ int sd_network_get_domains(char ***ret) {
_public_ int sd_network_get_search_domains(char ***ret) {
return network_get_strv("DOMAINS", ret);
}
_public_ int sd_network_get_route_domains(char ***ret) {
return network_get_strv("ROUTE_DOMAINS", ret);
}
static int network_link_get_string(int ifindex, const char *field, char **ret) {
_cleanup_free_ char *s = NULL, *p = NULL;
int r;
@@ -222,10 +226,14 @@ _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "NTP", ret);
}
_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "DOMAINS", ret);
}
_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);
}
@@ -234,26 +242,6 @@ _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_wildcard_domain(int ifindex) {
_cleanup_free_ char *p = NULL, *s = NULL;
int r;
assert_return(ifindex > 0, -EINVAL);
if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
return -ENOMEM;
r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
return r;
if (isempty(s))
return -ENODATA;
return parse_boolean(s);
}
static inline int MONITOR_TO_FD(sd_network_monitor *m) {
return (int) (unsigned long) m - 1;
}
+34 -47
View File
@@ -490,6 +490,9 @@ static int dump_addresses(
static void dump_list(const char *prefix, char **l) {
char **i;
if (strv_isempty(l))
return;
STRV_FOREACH(i, l) {
printf("%*s%s\n",
(int) strlen(prefix),
@@ -502,7 +505,7 @@ static int link_status_one(
sd_netlink *rtnl,
sd_hwdb *hwdb,
const char *name) {
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
@@ -552,7 +555,6 @@ static int link_status_one(
return rtnl_log_parse_error(r);
have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
if (have_mac) {
const uint8_t *p;
bool all_zeroes = true;
@@ -567,44 +569,35 @@ static int link_status_one(
have_mac = false;
}
sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
(void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
sd_network_link_get_operational_state(ifindex, &operational_state);
(void) sd_network_link_get_operational_state(ifindex, &operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
sd_network_link_get_setup_state(ifindex, &setup_state);
(void) sd_network_link_get_setup_state(ifindex, &setup_state);
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
sd_network_link_get_dns(ifindex, &dns);
sd_network_link_get_domains(ifindex, &domains);
r = sd_network_link_get_wildcard_domain(ifindex);
if (r > 0) {
char *wildcard;
wildcard = strdup("*");
if (!wildcard)
return log_oom();
if (strv_consume(&domains, wildcard) < 0)
return log_oom();
}
(void) sd_network_link_get_dns(ifindex, &dns);
(void) sd_network_link_get_search_domains(ifindex, &search_domains);
(void) sd_network_link_get_route_domains(ifindex, &route_domains);
(void) sd_network_link_get_ntp(ifindex, &ntp);
sprintf(devid, "n%i", ifindex);
(void)sd_device_new_from_device_id(&d, devid);
(void) sd_device_new_from_device_id(&d, devid);
if (d) {
(void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
(void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
(void)sd_device_get_property_value(d, "ID_PATH", &path);
(void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
(void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
(void) sd_device_get_property_value(d, "ID_PATH", &path);
r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor);
if (r < 0)
(void)sd_device_get_property_value(d, "ID_VENDOR", &vendor);
(void) sd_device_get_property_value(d, "ID_VENDOR", &vendor);
r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model);
if (r < 0)
(void)sd_device_get_property_value(d, "ID_MODEL", &model);
(void) sd_device_get_property_value(d, "ID_MODEL", &model);
}
link_get_type_string(iftype, d, &t);
@@ -653,20 +646,14 @@ static int link_status_one(
dump_addresses(rtnl, " Address: ", ifindex);
dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
if (!strv_isempty(dns))
dump_list(" DNS: ", dns);
if (!strv_isempty(domains))
dump_list(" Domain: ", domains);
dump_list(" DNS: ", dns);
dump_list(" Search Domains: ", search_domains);
dump_list(" Route Domains: ", route_domains);
(void) sd_network_link_get_ntp(ifindex, &ntp);
if (!strv_isempty(ntp))
dump_list(" NTP: ", ntp);
dump_list(" NTP: ", ntp);
if (!strv_isempty(carrier_bound_to))
dump_list("Carrier Bound To: ", carrier_bound_to);
if (!strv_isempty(carrier_bound_by))
dump_list("Carrier Bound By: ", carrier_bound_by);
dump_list("Carrier Bound To: ", carrier_bound_to);
dump_list("Carrier Bound By: ", carrier_bound_by);
(void) sd_network_link_get_timezone(ifindex, &tz);
if (tz)
@@ -691,30 +678,30 @@ static int link_status(int argc, char *argv[], void *userdata) {
if (argc <= 1 && !arg_all) {
_cleanup_free_ char *operational_state = NULL;
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains;
const char *on_color_operational, *off_color_operational;
sd_network_get_operational_state(&operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
printf("%s%s%s State: %s%s%s\n",
printf("%s%s%s State: %s%s%s\n",
on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational,
on_color_operational, strna(operational_state), off_color_operational);
dump_addresses(rtnl, " Address: ", 0);
dump_gateways(rtnl, hwdb, " Gateway: ", 0);
dump_addresses(rtnl, " Address: ", 0);
dump_gateways(rtnl, hwdb, " Gateway: ", 0);
sd_network_get_dns(&dns);
if (!strv_isempty(dns))
dump_list(" DNS: ", dns);
dump_list(" DNS: ", dns);
sd_network_get_domains(&domains);
if (!strv_isempty(domains))
dump_list(" Domain: ", domains);
sd_network_get_search_domains(&search_domains);
dump_list("Search Domains: ", search_domains);
sd_network_get_route_domains(&route_domains);
dump_list(" Route Domains: ", route_domains);
sd_network_get_ntp(&ntp);
if (!strv_isempty(ntp))
dump_list(" NTP: ", ntp);
dump_list(" NTP: ", ntp);
return 0;
}
+16 -16
View File
@@ -158,7 +158,7 @@ static int dhcp_lease_lost(Link *link) {
log_link_warning(link, "DHCP lease lost");
if (link->network->dhcp_routes) {
if (link->network->dhcp_use_routes) {
_cleanup_free_ sd_dhcp_route **routes = NULL;
int n, i;
@@ -223,7 +223,7 @@ static int dhcp_lease_lost(Link *link) {
}
}
if (link->network->dhcp_mtu) {
if (link->network->dhcp_use_mtu) {
uint16_t mtu;
r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
@@ -238,11 +238,11 @@ static int dhcp_lease_lost(Link *link) {
}
}
if (link->network->dhcp_hostname) {
if (link->network->dhcp_use_hostname) {
const char *hostname = NULL;
if (link->network->hostname)
hostname = link->network->hostname;
if (link->network->dhcp_hostname)
hostname = link->network->dhcp_hostname;
else
(void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
@@ -412,7 +412,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link);
if (link->network->dhcp_mtu) {
if (link->network->dhcp_use_mtu) {
uint16_t mtu;
r = sd_dhcp_lease_get_mtu(lease, &mtu);
@@ -423,11 +423,11 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
}
}
if (link->network->dhcp_hostname) {
if (link->network->dhcp_use_hostname) {
const char *hostname = NULL;
if (link->network->hostname)
hostname = link->network->hostname;
if (link->network->dhcp_hostname)
hostname = link->network->dhcp_hostname;
else
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
@@ -438,7 +438,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
}
}
if (link->network->dhcp_timezone) {
if (link->network->dhcp_use_timezone) {
const char *tz = NULL;
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
@@ -571,14 +571,14 @@ int dhcp4_configure(Link *link) {
return r;
}
if (link->network->dhcp_mtu) {
if (link->network->dhcp_use_mtu) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
SD_DHCP_OPTION_INTERFACE_MTU);
if (r < 0)
return r;
}
if (link->network->dhcp_routes) {
if (link->network->dhcp_use_routes) {
r = sd_dhcp_client_set_request_option(link->dhcp_client,
SD_DHCP_OPTION_STATIC_ROUTE);
if (r < 0)
@@ -589,7 +589,7 @@ int dhcp4_configure(Link *link) {
return r;
}
/* Always acquire the timezone and NTP*/
/* Always acquire the timezone and NTP */
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
if (r < 0)
return r;
@@ -598,18 +598,18 @@ int dhcp4_configure(Link *link) {
if (r < 0)
return r;
if (link->network->dhcp_sendhost) {
if (link->network->dhcp_send_hostname) {
_cleanup_free_ char *hostname = NULL;
const char *hn = NULL;
if (!link->network->hostname) {
if (!link->network->dhcp_hostname) {
hostname = gethostname_malloc();
if (!hostname)
return -ENOMEM;
hn = hostname;
} else
hn = link->network->hostname;
hn = link->network->dhcp_hostname;
if (!is_localhost(hn)) {
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
+41 -80
View File
@@ -767,7 +767,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
addresses[n_addresses++] = ia;
}
if (link->network->dhcp_dns &&
if (link->network->dhcp_use_dns &&
link->dhcp_lease) {
const struct in_addr *da = NULL;
int n;
@@ -812,7 +812,7 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
addresses[n_addresses++] = ia;
}
if (link->network->dhcp_ntp &&
if (link->network->dhcp_use_ntp &&
link->dhcp_lease) {
const struct in_addr *da = NULL;
int n;
@@ -2729,9 +2729,10 @@ int link_save(Link *link) {
admin_state, oper_state);
if (link->network) {
char **address, **domain;
bool space;
sd_dhcp6_lease *dhcp6_lease = NULL;
const char *dhcp_domainname = NULL;
char **dhcp6_domains = NULL;
if (link->dhcp6_client) {
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
@@ -2743,14 +2744,9 @@ int link_save(Link *link) {
fputs("DNS=", f);
space = false;
STRV_FOREACH(address, link->network->dns) {
if (space)
fputc(' ', f);
fputs(*address, f);
space = true;
}
fputstrv(f, link->network->dns, NULL, &space);
if (link->network->dhcp_dns &&
if (link->network->dhcp_use_dns &&
link->dhcp_lease) {
const struct in_addr *addresses;
@@ -2763,7 +2759,7 @@ int link_save(Link *link) {
}
}
if (link->network->dhcp_dns && dhcp6_lease) {
if (link->network->dhcp_use_dns && dhcp6_lease) {
struct in6_addr *in6_addrs;
r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
@@ -2778,14 +2774,9 @@ int link_save(Link *link) {
fputs("NTP=", f);
space = false;
STRV_FOREACH(address, link->network->ntp) {
if (space)
fputc(' ', f);
fputs(*address, f);
space = true;
}
fputstrv(f, link->network->ntp, NULL, &space);
if (link->network->dhcp_ntp &&
if (link->network->dhcp_use_ntp &&
link->dhcp_lease) {
const struct in_addr *addresses;
@@ -2798,10 +2789,9 @@ int link_save(Link *link) {
}
}
if (link->network->dhcp_ntp && dhcp6_lease) {
if (link->network->dhcp_use_ntp && dhcp6_lease) {
struct in6_addr *in6_addrs;
char **hosts;
char **hostname;
r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
&in6_addrs);
@@ -2813,58 +2803,41 @@ int link_save(Link *link) {
}
r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
if (r > 0) {
STRV_FOREACH(hostname, hosts) {
if (space)
fputc(' ', f);
fputs(*hostname, f);
space = true;
}
}
if (r > 0)
fputstrv(f, hosts, NULL, &space);
}
fputc('\n', f);
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
if (link->dhcp_lease)
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
if (dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
}
fputs("DOMAINS=", f);
space = false;
STRV_FOREACH(domain, link->network->domains) {
if (space)
fputc(' ', f);
fputs(*domain, f);
space = true;
}
fputstrv(f, link->network->search_domains, NULL, &space);
if (link->network->dhcp_domains &&
link->dhcp_lease) {
const char *domainname;
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname)
fputs_with_space(f, dhcp_domainname, NULL, &space);
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
if (r >= 0) {
if (space)
fputc(' ', f);
fputs(domainname, f);
space = true;
}
}
if (link->network->dhcp_domains && dhcp6_lease) {
char **domains;
r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
if (r >= 0) {
STRV_FOREACH(domain, domains) {
if (space)
fputc(' ', f);
fputs(*domain, f);
space = true;
}
}
}
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains)
fputstrv(f, dhcp6_domains, NULL, &space);
fputc('\n', f);
fprintf(f, "WILDCARD_DOMAIN=%s\n",
yes_no(link->network->wildcard_domain));
fputs("ROUTE_DOMAINS=", f);
fputstrv(f, link->network->route_domains, NULL, NULL);
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);
fputc('\n', f);
fprintf(f, "LLMNR=%s\n",
resolve_support_to_string(link->network->llmnr));
@@ -2880,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);
}
@@ -2925,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);
}
@@ -2940,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);
}
+40 -27
View File
@@ -29,12 +29,14 @@
#include "bus-util.h"
#include "conf-parser.h"
#include "def.h"
#include "dns-domain.h"
#include "fd-util.h"
#include "fileio.h"
#include "libudev-private.h"
#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 +778,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 +788,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,27 +812,24 @@ 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) {
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);
}
static int manager_save(Manager *m) {
_cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *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,16 +842,20 @@ 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;
domains = set_new(&string_hash_ops);
if (!domains)
search_domains = ordered_set_new(&dns_name_hash_ops);
if (!search_domains)
return -ENOMEM;
route_domains = ordered_set_new(&dns_name_hash_ops);
if (!route_domains)
return -ENOMEM;
HASHMAP_FOREACH(link, m->links, i) {
@@ -866,15 +869,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(domains, link->network->domains);
r = ordered_set_put_strdupv(search_domains, link->network->search_domains);
if (r < 0)
return r;
r = ordered_set_put_strdupv(route_domains, link->network->route_domains);
if (r < 0)
return r;
@@ -882,36 +889,41 @@ static int manager_save(Manager *m) {
continue;
/* Secondly, add the entries acquired via DHCP */
if (link->network->dhcp_dns) {
if (link->network->dhcp_use_dns) {
const struct in_addr *addresses;
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)
return r;
}
if (link->network->dhcp_ntp) {
if (link->network->dhcp_use_ntp) {
const struct in_addr *addresses;
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)
return r;
}
if (link->network->dhcp_domains) {
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
const char *domainname;
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
if (r >= 0) {
r = set_put_strdup(domains, domainname);
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES)
r = ordered_set_put_strdup(search_domains, domainname);
else
r = ordered_set_put_strdup(route_domains, domainname);
if (r < 0)
return r;
} else if (r != -ENODATA)
@@ -934,7 +946,8 @@ static int manager_save(Manager *m) {
print_string_set(f, "DNS=", dns);
print_string_set(f, "NTP=", ntp);
print_string_set(f, "DOMAINS=", domains);
print_string_set(f, "DOMAINS=", search_domains);
print_string_set(f, "ROUTE_DOMAINS=", route_domains);
r = fflush_and_check(f);
if (r < 0)
+15 -15
View File
@@ -43,7 +43,7 @@ Network.IPv6Token, config_parse_ipv6token,
Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
Network.Address, config_parse_address, 0, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
Network.Domains, config_parse_domains, 0, 0
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
@@ -68,19 +68,19 @@ Route.Metric, config_parse_route_priority,
Route.Scope, config_parse_route_scope, 0, 0
Route.PreferredSource, config_parse_preferred_src, 0, 0
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname)
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp)
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes)
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname)
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone)
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
@@ -101,9 +101,9 @@ BridgeFDB.MACAddress, config_parse_fdb_hwaddr,
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
+92 -42
View File
@@ -105,11 +105,11 @@ static int network_load_one(Manager *manager, const char *filename) {
*d = '\0';
network->dhcp = ADDRESS_FAMILY_NO;
network->dhcp_ntp = true;
network->dhcp_dns = true;
network->dhcp_hostname = true;
network->dhcp_routes = true;
network->dhcp_sendhost = true;
network->dhcp_use_ntp = true;
network->dhcp_use_dns = true;
network->dhcp_use_hostname = true;
network->dhcp_use_routes = true;
network->dhcp_send_hostname = true;
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
@@ -227,13 +227,14 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
free(network->hostname);
free(network->dhcp_hostname);
free(network->mac);
strv_free(network->ntp);
strv_free(network->dns);
strv_free(network->domains);
strv_free(network->search_domains);
strv_free(network->route_domains);
strv_free(network->bind_carrier);
netdev_unref(network->bridge);
@@ -384,7 +385,10 @@ int network_apply(Manager *manager, Network *network, Link *link) {
route->protocol = RTPROT_STATIC;
}
if (network->dns || network->ntp || network->domains) {
if (!strv_isempty(network->dns) ||
!strv_isempty(network->ntp) ||
!strv_isempty(network->search_domains) ||
!strv_isempty(network->route_domains)) {
manager_dirty(manager);
link_dirty(link);
}
@@ -469,49 +473,85 @@ int config_parse_netdev(const char *unit,
return 0;
}
int config_parse_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) {
Network *network = userdata;
char ***domains = data;
char **domain;
int config_parse_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) {
const char *p;
Network *n = data;
int r;
r = config_parse_strv(unit, filename, line, section, section_line,
lvalue, ltype, rvalue, domains, userdata);
if (r < 0)
return r;
assert(n);
assert(lvalue);
assert(rvalue);
strv_uniq(*domains);
network->wildcard_domain = !!strv_find(*domains, "*");
if (isempty(rvalue)) {
n->search_domains = strv_free(n->search_domains);
n->route_domains = strv_free(n->route_domains);
return 0;
}
STRV_FOREACH(domain, *domains) {
if (is_localhost(*domain))
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
else {
r = dns_name_is_valid(*domain);
if (r <= 0 && !streq(*domain, "*")) {
if (r < 0)
log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
if (r == 0)
log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
} else
p = rvalue;
for (;;) {
_cleanup_free_ char *w = NULL, *normalized = NULL;
const char *domain;
bool is_route;
r = extract_first_word(&p, &w, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
break;
}
if (r == 0)
break;
is_route = w[0] == '~';
domain = is_route ? w + 1 : w;
if (dns_name_is_root(domain) || streq(domain, "*")) {
/* If the root domain appears as is, or the special token "*" is found, we'll consider this as
* routing domain, unconditionally. */
is_route = true;
domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
} else {
r = dns_name_normalize(domain, &normalized);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
continue;
}
domain = normalized;
if (is_localhost(domain)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
continue;
}
}
strv_remove(*domains, *domain);
if (is_route) {
r = strv_extend(&n->route_domains, domain);
if (r < 0)
return log_oom();
/* We removed one entry, make sure we don't skip the next one */
domain--;
} else {
r = strv_extend(&n->search_domains, domain);
if (r < 0)
return log_oom();
}
}
strv_uniq(n->route_domains);
strv_uniq(n->search_domains);
return 0;
}
@@ -930,7 +970,7 @@ int config_parse_dnssec_negative_trust_anchors(
Network *n = data;
int r;
assert(filename);
assert(n);
assert(lvalue);
assert(rvalue);
@@ -965,3 +1005,13 @@ int config_parse_dnssec_negative_trust_anchors(
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
[DHCP_USE_DOMAINS_NO] = "no",
[DHCP_USE_DOMAINS_ROUTE] = "route",
[DHCP_USE_DOMAINS_YES] = "yes",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
+22 -11
View File
@@ -52,6 +52,14 @@ typedef enum IPv6PrivacyExtensions {
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
} IPv6PrivacyExtensions;
typedef enum DHCPUseDomains {
DHCP_USE_DOMAINS_NO,
DHCP_USE_DOMAINS_YES,
DHCP_USE_DOMAINS_ROUTE,
_DHCP_USE_DOMAINS_MAX,
_DHCP_USE_DOMAINS_INVALID = -1,
} DHCPUseDomains;
struct Network {
Manager *manager;
@@ -79,17 +87,17 @@ struct Network {
AddressFamilyBoolean dhcp;
DCHPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
char *hostname;
bool dhcp_dns;
bool dhcp_ntp;
bool dhcp_mtu;
bool dhcp_hostname;
bool dhcp_domains;
bool dhcp_sendhost;
char *dhcp_hostname;
bool dhcp_use_dns;
bool dhcp_use_ntp;
bool dhcp_use_mtu;
bool dhcp_use_hostname;
DHCPUseDomains dhcp_use_domains;
bool dhcp_send_hostname;
bool dhcp_broadcast;
bool dhcp_critical;
bool dhcp_routes;
bool dhcp_timezone;
bool dhcp_use_routes;
bool dhcp_use_timezone;
unsigned dhcp_route_metric;
/* DHCP Server Support */
@@ -141,8 +149,7 @@ struct Network {
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
bool wildcard_domain;
char **domains, **dns, **ntp, **bind_carrier;
char **search_domains, **route_domains, **dns, **ntp, **bind_carrier;
ResolveSupport llmnr;
ResolveSupport mdns;
@@ -175,6 +182,7 @@ int config_parse_timezone(const char *unit, const char *filename, unsigned line,
int config_parse_dhcp_server_dns(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_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);
/* 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);
@@ -188,3 +196,6 @@ int network_object_find(sd_bus *bus, const char *path, const char *interface, vo
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
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_;
+5 -5
View File
@@ -1217,19 +1217,19 @@ static int bus_property_get_search_domains(
assert(reply);
assert(m);
r = sd_bus_message_open_container(reply, 'a', "(is)");
r = sd_bus_message_open_container(reply, 'a', "(isb)");
if (r < 0)
return r;
LIST_FOREACH(domains, d, m->search_domains) {
r = sd_bus_message_append(reply, "(is)", 0, d->name);
r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
if (r < 0)
return r;
}
HASHMAP_FOREACH(l, m->links, i) {
LIST_FOREACH(domains, d, l->search_domains) {
r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
if (r < 0)
return r;
}
@@ -1450,7 +1450,7 @@ static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
SD_BUS_PROPERTY("Domains", "a(is)", bus_property_get_search_domains, 0, 0),
SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0),
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
@@ -1463,7 +1463,7 @@ static const sd_bus_vtable resolve_vtable[] = {
SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0),
SD_BUS_METHOD("SetLinkDomains", "ias", NULL, bus_method_set_link_search_domains, 0),
SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0),
SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
+17 -3
View File
@@ -80,20 +80,34 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con
int manager_add_search_domain_by_string(Manager *m, const char *domain) {
DnsSearchDomain *d;
bool route_only;
int r;
assert(m);
assert(domain);
route_only = *domain == '~';
if (route_only)
domain++;
if (dns_name_is_root(domain) || streq(domain, "*")) {
route_only = true;
domain = ".";
}
r = dns_search_domain_find(m->search_domains, domain, &d);
if (r < 0)
return r;
if (r > 0) {
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
return 0;
else {
r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
if (r < 0)
return r;
}
return dns_search_domain_new(m, NULL, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
d->route_only = route_only;
return 0;
}
int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
-12
View File
@@ -28,18 +28,6 @@
#include "resolved-dns-packet.h"
#include "string-table.h"
/* Open question:
*
* How does the DNSSEC canonical form of a hostname with a label
* containing a dot look like, the way DNS-SD does it?
*
* TODO:
*
* - enable by default
* - Allow clients to request DNSSEC even if DNSSEC is off
* - make sure when getting an NXDOMAIN response through CNAME, we still process the first CNAMEs in the packet
* */
#define VERIFY_RRS_MAX 256
#define MAX_KEY_SIZE (32*1024)
+8 -5
View File
@@ -93,17 +93,20 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
assert(c);
if (c->search_domain && c->search_domain->linked) {
if (c->search_domain && c->search_domain->linked)
next = c->search_domain->domains_next;
else
next = dns_scope_get_search_domains(c->scope);
for (;;) {
if (!next) /* We hit the end of the list */
return 0;
} else {
next = dns_scope_get_search_domains(c->scope);
if (!next->route_only)
break;
if (!next) /* OK, there's nothing. */
return 0;
/* Skip over route-only domains */
next = next->domains_next;
}
dns_search_domain_unref(c->search_domain);
-3
View File
@@ -42,9 +42,6 @@ int dns_search_domain_new(
if (r < 0)
return r;
if (dns_name_is_root(normalized))
return -EINVAL;
if (l) {
if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
return -E2BIG;
+1
View File
@@ -44,6 +44,7 @@ struct DnsSearchDomain {
char *name;
bool marked:1;
bool route_only:1;
bool linked:1;
LIST_FIELDS(DnsSearchDomain, domains);
+53 -19
View File
@@ -732,6 +732,55 @@ fail:
dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
}
static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
int r;
assert(t);
/* Checks whether the answer is positive, i.e. either a direct
* answer to the question, or a CNAME/DNAME for it */
r = dns_answer_match_key(t->answer, t->key, flags);
if (r != 0)
return r;
r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
if (r != 0)
return r;
return false;
}
static int dns_transaction_fix_rcode(DnsTransaction *t) {
int r;
assert(t);
/* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the
* DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a
* CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first
* one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when
* using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle
* on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a
* CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server
* incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an
* incomplete CNAME/DNAME chain.
*
* Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS,
* and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new
* lookup. */
if (t->answer_rcode != DNS_RCODE_NXDOMAIN)
return 0;
r = dns_transaction_has_positive_answer(t, NULL);
if (r <= 0)
return r;
t->answer_rcode = DNS_RCODE_SUCCESS;
return 0;
}
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
usec_t ts;
int r;
@@ -923,6 +972,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
t->answer_authenticated = false;
r = dns_transaction_fix_rcode(t);
if (r < 0)
goto fail;
/* Block GC while starting requests for additional DNSSEC RRs */
t->block_gc++;
r = dns_transaction_request_dnssec_keys(t);
@@ -1635,25 +1688,6 @@ static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *
return 1;
}
static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
int r;
assert(t);
/* Checks whether the answer is positive, i.e. either a direct
* answer to the question, or a CNAME/DNAME for it */
r = dns_answer_match_key(t->answer, t->key, flags);
if (r != 0)
return r;
r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
if (r != 0)
return r;
return false;
}
static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
int r;
+39 -15
View File
@@ -75,12 +75,12 @@ static int property_get_domains(
assert(reply);
assert(l);
r = sd_bus_message_open_container(reply, 'a', "s");
r = sd_bus_message_open_container(reply, 'a', "(sb)");
if (r < 0)
return r;
LIST_FOREACH(domains, d, l->search_domains) {
r = sd_bus_message_append(reply, "s", d->name);
r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
if (r < 0)
return r;
}
@@ -242,47 +242,71 @@ clear:
}
int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char **domains = NULL;
Link *l = userdata;
char **i;
int r;
assert(message);
assert(l);
r = sd_bus_message_read_strv(message, &domains);
r = sd_bus_message_enter_container(message, 'a', "(sb)");
if (r < 0)
return r;
STRV_FOREACH(i, domains) {
for (;;) {
const char *name;
int route_only;
r = dns_name_is_valid(*i);
r = sd_bus_message_read(message, "(sb)", &name, &route_only);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", *i);
if (dns_name_is_root(*i))
break;
r = dns_name_is_valid(name);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
if (!route_only && dns_name_is_root(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
}
dns_search_domain_mark_all(l->search_domains);
STRV_FOREACH(i, domains) {
DnsSearchDomain *d;
r = sd_bus_message_rewind(message, false);
if (r < 0)
return r;
r = dns_search_domain_find(l->search_domains, *i, &d);
for (;;) {
DnsSearchDomain *d;
const char *name;
int route_only;
r = sd_bus_message_read(message, "(sb)", &name, &route_only);
if (r < 0)
goto clear;
if (r == 0)
break;
r = dns_search_domain_find(l->search_domains, name, &d);
if (r < 0)
goto clear;
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
if (r < 0)
goto clear;
}
d->route_only = route_only;
}
r = sd_bus_message_exit_container(message);
if (r < 0)
goto clear;
dns_search_domain_unlink_marked(l->search_domains);
return sd_bus_reply_method_return(message, NULL);
@@ -430,7 +454,7 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
SD_BUS_PROPERTY("Domains", "as", property_get_domains, 0, 0),
SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0),
@@ -438,7 +462,7 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0),
SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0),
SD_BUS_METHOD("SetDomains", "as", NULL, bus_link_method_set_search_domains, 0),
SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_search_domains, 0),
SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0),
SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0),
SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0),
+40 -18
View File
@@ -377,38 +377,60 @@ clear:
return r;
}
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **domains = NULL;
char **i;
static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
DnsSearchDomain *d;
int r;
r = dns_search_domain_find(l->search_domains, name, &d);
if (r < 0)
return r;
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
if (r < 0)
return r;
}
d->route_only = route_only;
return 0;
}
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
char **i;
int r, q;
assert(l);
r = sd_network_link_get_domains(l->ifindex, &domains);
if (r == -ENODATA) {
r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
if (r < 0 && r != -ENODATA)
goto clear;
q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
if (q < 0 && q != -ENODATA) {
r = q;
goto clear;
}
if (r == -ENODATA && q == -ENODATA) {
/* networkd knows nothing about this interface, and that's fine. */
r = 0;
goto clear;
}
if (r < 0)
goto clear;
dns_search_domain_mark_all(l->search_domains);
STRV_FOREACH(i, domains) {
DnsSearchDomain *d;
r = dns_search_domain_find(l->search_domains, *i, &d);
STRV_FOREACH(i, sdomains) {
r = link_update_search_domain_one(l, *i, false);
if (r < 0)
goto clear;
}
if (r > 0)
dns_search_domain_move_back_and_unmark(d);
else {
r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
if (r < 0)
goto clear;
}
STRV_FOREACH(i, rdomains) {
r = link_update_search_domain_one(l, *i, true);
if (r < 0)
goto clear;
}
dns_search_domain_unlink_marked(l->search_domains);
+5 -1
View File
@@ -206,7 +206,7 @@ static int manager_rtnl_listen(Manager *m) {
if (r < 0)
return r;
r = sd_netlink_attach_event(m->rtnl, m->event, 0);
r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
if (r < 0)
return r;
@@ -314,6 +314,10 @@ static int manager_network_monitor_listen(Manager *m) {
if (r < 0)
return r;
r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5);
if (r < 0)
return r;
(void) sd_event_source_set_description(m->network_event_source, "network-monitor");
return 0;
+1
View File
@@ -74,6 +74,7 @@ struct Manager {
LIST_HEAD(DnsSearchDomain, search_domains);
unsigned n_search_domains;
bool permit_domain_search;
bool need_builtin_fallbacks:1;
+19 -4
View File
@@ -405,11 +405,17 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
int dns_name_concat(const char *a, const char *b, char **_ret) {
_cleanup_free_ char *ret = NULL;
size_t n = 0, allocated = 0;
const char *p = a;
const char *p;
bool first = true;
int r;
assert(a);
if (a)
p = a;
else if (b) {
p = b;
b = NULL;
} else
goto finish;
for (;;) {
char label[DNS_LABEL_MAX];
@@ -457,12 +463,21 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
n += r;
}
finish:
if (n > DNS_HOSTNAME_MAX)
return -EINVAL;
if (_ret) {
if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM;
if (n == 0) {
/* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
if (!GREEDY_REALLOC(ret, allocated, 2))
return -ENOMEM;
ret[n++] = '.';
} else {
if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM;
}
ret[n] = 0;
*_ret = ret;
+10 -8
View File
@@ -64,8 +64,11 @@ int sd_network_get_dns(char ***dns);
* representations of IP addresses */
int sd_network_get_ntp(char ***ntp);
/* Get the search/routing domains for all links. */
int sd_network_get_domains(char ***domains);
/* Get the search domains for all links. */
int sd_network_get_search_domains(char ***domains);
/* Get the search domains for all links. */
int sd_network_get_route_domains(char ***domains);
/* Get setup state from ifindex.
* Possible states:
@@ -134,8 +137,11 @@ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta);
int sd_network_link_get_lldp(int ifindex, char **lldp);
/* Get the DNS domain names for a given link. */
int sd_network_link_get_domains(int ifindex, char ***domains);
/* Get the search DNS domain names for a given link. */
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);
@@ -146,10 +152,6 @@ int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
/* Get the timezone that was learnt on a specific link. */
int sd_network_link_get_timezone(int ifindex, char **timezone);
/* Returns whether or not domains that don't match any link should be resolved
* on this link. 1 for yes, 0 for no and negative value for error */
int sd_network_link_get_wildcard_domain(int ifindex);
/* Monitor object */
typedef struct sd_network_monitor sd_network_monitor;
+17 -9
View File
@@ -186,7 +186,7 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
}
static void test_dns_name_normalize(void) {
test_dns_name_normalize_one("", "", 0);
test_dns_name_normalize_one("", ".", 0);
test_dns_name_normalize_one("f", "f", 0);
test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
@@ -194,7 +194,7 @@ static void test_dns_name_normalize(void) {
test_dns_name_normalize_one("..", NULL, -EINVAL);
test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
test_dns_name_normalize_one("foobar.", "foobar", 0);
test_dns_name_normalize_one(".", "", 0);
test_dns_name_normalize_one(".", ".", 0);
}
static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
@@ -340,10 +340,18 @@ static void test_dns_name_concat_one(const char *a, const char *b, int r, const
}
static void test_dns_name_concat(void) {
test_dns_name_concat_one("", "", 0, ".");
test_dns_name_concat_one(".", "", 0, ".");
test_dns_name_concat_one("", ".", 0, ".");
test_dns_name_concat_one(".", ".", 0, ".");
test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
test_dns_name_concat_one("foo", NULL, 0, "foo");
test_dns_name_concat_one("foo", ".", 0, "foo");
test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
test_dns_name_concat_one(NULL, NULL, 0, ".");
test_dns_name_concat_one(NULL, ".", 0, ".");
test_dns_name_concat_one(NULL, "foo", 0, "foo");
}
static void test_dns_name_is_valid_one(const char *s, int ret) {
@@ -429,7 +437,7 @@ static void test_dns_service_join_one(const char *a, const char *b, const char *
assert_se(dns_service_split(t, &x, &y, &z) >= 0);
assert_se(streq_ptr(a, x));
assert_se(streq_ptr(b, y));
assert_se(streq_ptr(c, z));
assert_se(dns_name_equal(c, z) > 0);
}
static void test_dns_service_join(void) {
@@ -460,18 +468,18 @@ static void test_dns_service_split_one(const char *joined, const char *a, const
if (y) {
assert_se(dns_service_join(x, y, z, &t) == 0);
assert_se(streq_ptr(joined, t));
assert_se(dns_name_equal(joined, t) > 0);
} else
assert_se(!x && streq_ptr(z, joined));
assert_se(!x && dns_name_equal(z, joined) > 0);
}
static void test_dns_service_split(void) {
test_dns_service_split_one("", NULL, NULL, "", 0);
test_dns_service_split_one("", NULL, NULL, ".", 0);
test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", "", 0);
test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", "", 0);
test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
}
@@ -490,7 +498,7 @@ static void test_dns_name_change_suffix(void) {
test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
test_dns_name_change_suffix_one("", "", "", 1, "");
test_dns_name_change_suffix_one("", "", "", 1, ".");
test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
}