When the code for generating resolv.conf was moved from networkd to resolved the DHCP domain name code was dropped. ---
This is a refresh of the patch on recent master with a little bit of cleanup from the last. Regarding the robustness/correctness/etc of setting the "domain" resolv.conf attribute from DNS, I don't think that is practical to address in this patch. The implementation is already clearly incomplete because networkd doesn't handle "search" domains which is actually an entirely different option. My goal here is to just fix the regression from when resolved was first introduced. The most common setup is for "domain" to correspond to the domain suffix for the local host name. If you are concerned about which interface's domain attribute wins and lands in resolv.conf, there is a related issue of which interface's host name winds up being applied as the host's transient host name. What ever interface wins the two should probably match but this is complicated significantly by the two being handled by different daemons, resolved vs hostnamed, with two different integration points with networkd, reading state files in /run vs dbus method calls. I don't have a good recommendation to make sense of any of this right now. src/network/networkd-link.c | 9 +++++++++ src/network/sd-network.c | 24 ++++++++++++++++++++++++ src/resolve/resolved-link.c | 20 ++++++++++++++++++++ src/resolve/resolved-link.h | 2 ++ src/resolve/resolved-manager.c | 10 +++++++++- src/systemd/sd-network.h | 3 +++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 172be64..42d528f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2385,6 +2385,15 @@ int link_save(Link *link) { (address + 1 ? " " : "")); fputs("\n", f); + + if (link->network->dhcp_domainname && + link->dhcp_lease) { + const char *domainname; + + r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); + if (r >= 0) + fprintf(f, "DOMAINNAME=%s\n", domainname); + } } if (link->dhcp_lease) { diff --git a/src/network/sd-network.c b/src/network/sd-network.c index bfb8321..a427a27 100644 --- a/src/network/sd-network.c +++ b/src/network/sd-network.c @@ -175,6 +175,30 @@ _public_ int sd_network_get_ntp(int ifindex, char ***ret) { return network_get_strv("NTP", ifindex, ret); } +_public_ int sd_network_get_domainname(int ifindex, char **domainname) { + _cleanup_free_ char *s = NULL, *p = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(domainname, -EINVAL); + + if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) + return -ENOMEM; + + r = parse_env_file(p, NEWLINE, "DOMAINNAME", &s, NULL); + if (r == -ENOENT) + return -ENODATA; + else if (r < 0) + return r; + else if (!s) + return -EIO; + + *domainname = s; + s = NULL; + + return 0; +} + static inline int MONITOR_TO_FD(sd_network_monitor *m) { return (int) (unsigned long) m - 1; } diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 2c02f09..9d582e4 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -74,6 +74,7 @@ Link *link_free(Link *l) { while (l->dns_servers) dns_server_free(l->dns_servers); + free(l->domainname); free(l); return NULL; } @@ -188,10 +189,29 @@ clear: return r; } +static int link_update_domainname(Link *l) { + char *domainname = NULL; + int r; + + assert(l); + + free(l->domainname); + l->domainname = NULL; + + r = sd_network_get_domainname(l->ifindex, &domainname); + if (r < 0) + return r; + + l->domainname = domainname; + + return 0; +} + int link_update_monitor(Link *l) { assert(l); link_update_dns_servers(l); + link_update_domainname(l); link_allocate_scopes(l); link_add_rrs(l, false); diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 38bb392..eed9f42 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -68,6 +68,8 @@ struct Link { RateLimit mdns_ratelimit; RateLimit llmnr_ratelimit; + + char *domainname; }; int link_new(Manager *m, Link **ret, int ifindex); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 1b6dc8a..8f28eaf 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -648,6 +648,7 @@ int manager_write_resolv_conf(Manager *m) { static const char path[] = "/run/systemd/resolve/resolv.conf"; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; + const char *domainname = NULL; unsigned count = 0; DnsServer *s; Iterator i; @@ -674,15 +675,22 @@ int manager_write_resolv_conf(Manager *m) { LIST_FOREACH(servers, s, m->dns_servers) write_resolve_conf_server(s, f, &count); - HASHMAP_FOREACH(l, m->links, i) + HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(servers, s, l->dns_servers) write_resolve_conf_server(s, f, &count); + if (!domainname && l->domainname) + domainname = l->domainname; + } + if (count == 0) { LIST_FOREACH(servers, s, m->fallback_dns_servers) write_resolve_conf_server(s, f, &count); } + if (domainname) + fprintf(f, "domain %s\n", domainname); + r = fflush_and_check(f); if (r < 0) goto fail; diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index ec01e07..06f147d 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -84,6 +84,9 @@ int sd_network_get_dns(int ifindex, char ***addr); * reperesentations of IP addresses */ int sd_network_get_ntp(int ifindex, char ***addr); +/* Get the DNS domain name for a given link. */ +int sd_network_get_domainname(int ifindex, char **domainname); + /* Monitor object */ typedef struct sd_network_monitor sd_network_monitor; -- 1.8.5.5 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel