summaryrefslogtreecommitdiff
path: root/src/network/networkd-link.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-08-27 16:45:24 +0200
committerLennart Poettering <lennart@poettering.net>2015-08-27 16:45:24 +0200
commit4f5f911e81ae6377ab925c1dd133013c640ab32e (patch)
treef0da3484c737997027a89945e76c047e7de16846 /src/network/networkd-link.c
parent1a04db0fc9d08fffe80d6d7b5b60459295922b11 (diff)
networkd: propagate DNS/NTP server from uplink to dhcp server
When handing out DHCP leases, try to propagate DNS/NTP server information from "uplink". The "uplink" is automatically determined as the network interface with the highest priority default route on it.
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r--src/network/networkd-link.c129
1 files changed, 119 insertions, 10 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0d85005c8c..ff693ed0fd 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -616,6 +616,96 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
return 1;
}
+static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ char **a;
+
+ log_debug("Copying DNS server information from %s", link->ifname);
+
+ if (!link->network)
+ return 0;
+
+ STRV_FOREACH(a, link->network->dns) {
+ struct in_addr ia;
+
+ /* Only look for IPv4 addresses */
+ if (inet_pton(AF_INET, *a, &ia) <= 0)
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia;
+ }
+
+ if (link->network->dhcp_dns &&
+ link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int n;
+
+ n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
+ n_addresses += n;
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_dns(s, addresses, n_addresses);
+}
+
+static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ char **a;
+
+ if (!link->network)
+ return 0;
+
+ log_debug("Copying NTP server information from %s", link->ifname);
+
+ STRV_FOREACH(a, link->network->ntp) {
+ struct in_addr ia;
+
+ /* Only look for IPv4 addresses */
+ if (inet_pton(AF_INET, *a, &ia) <= 0)
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia;
+ }
+
+ if (link->network->dhcp_ntp &&
+ link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int n;
+
+ n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
+ n_addresses += n;
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
+}
+
static int link_enter_set_addresses(Link *link) {
Address *ad;
int r;
@@ -642,6 +732,8 @@ static int link_enter_set_addresses(Link *link) {
if (link_dhcp4_server_enabled(link)) {
struct in_addr pool_start;
Address *address;
+ Link *uplink = NULL;
+ bool acquired_uplink = false;
address = link_find_dhcp_server_address(link);
if (!address) {
@@ -693,23 +785,40 @@ static int link_enter_set_addresses(Link *link) {
if (link->network->dhcp_server_emit_dns) {
- if (link->network->n_dhcp_server_dns > 0) {
+ if (link->network->n_dhcp_server_dns > 0)
r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
- } else
- log_link_warning_errno(link, r, "DNS server emitting enabled, but no DNS servers set, ignoring: %m");
+ else {
+ uplink = manager_find_uplink(link->manager, link);
+ acquired_uplink = true;
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
}
if (link->network->dhcp_server_emit_ntp) {
- if (link->network->n_dhcp_server_ntp > 0) {
+ if (link->network->n_dhcp_server_ntp > 0)
r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
- } else
- log_link_warning_errno(link, r, "NTP server emitting enabled, but no NTP servers set, ignoring: %m");
+ else {
+ if (!acquired_uplink)
+ uplink = manager_find_uplink(link->manager, link);
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
+
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
}
if (link->network->dhcp_server_emit_timezone) {