summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-07-17 02:30:56 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-07-19 01:44:44 +0900
commit854a1ccfc2dbb175fee1e9e4a16cd09bd879c1b7 (patch)
tree8b1843f01a0403932ffa2cc347bd142eec7e2901 /src/network
parentd4c52ee5b546670b6f16c88a389df0428cc9d1dd (diff)
downloadsystemd-854a1ccfc2dbb175fee1e9e4a16cd09bd879c1b7.tar.gz
network: set routes to dns servers provided by DHCPv4
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-dhcp4.c96
1 files changed, 95 insertions, 1 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 6ebc19db1a..e5ea6b702e 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -17,6 +17,7 @@
static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
+static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address);
void dhcp4_release_old_lease(Link *link) {
@@ -34,6 +35,7 @@ void dhcp4_release_old_lease(Link *link) {
(void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false);
(void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false);
+ (void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false);
if (!in4_addr_equal(&address_old, &address))
(void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old);
@@ -107,6 +109,52 @@ static int dhcp_route_configure(Route **route, Link *link) {
return 0;
}
+static int link_set_dns_routes(Link *link, const struct in_addr *address) {
+ const struct in_addr *dns;
+ uint32_t table;
+ int i, n, r;
+
+ assert(link);
+ assert(link->dhcp_lease);
+ assert(link->network);
+
+ if (!link->network->dhcp_use_dns)
+ return 0;
+
+ n = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
+ if (IN_SET(n, 0, -ENODATA))
+ return 0;
+ if (n < 0)
+ return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
+
+ table = link_get_dhcp_route_table(link);
+
+ for (i = 0; i < n; i ++) {
+ _cleanup_(route_freep) Route *route = NULL;
+
+ r = route_new(&route);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate route: %m");
+
+ /* Set routes to DNS servers. */
+
+ route->family = AF_INET;
+ route->dst.in = dns[i];
+ route->dst_prefixlen = 32;
+ route->prefsrc.in = *address;
+ route->scope = RT_SCOPE_LINK;
+ route->protocol = RTPROT_DHCP;
+ route->priority = link->network->dhcp_route_metric;
+ route->table = table;
+
+ r = dhcp_route_configure(&route, link);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set route to DNS server: %m");
+ }
+
+ return 0;
+}
+
static int link_set_dhcp_routes(Link *link) {
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
bool classless_route = false, static_route = false;
@@ -245,7 +293,7 @@ static int link_set_dhcp_routes(Link *link) {
return log_link_error_errno(link, r, "Could not set router: %m");
}
- return 0;
+ return link_set_dns_routes(link, &address);
}
static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
@@ -351,6 +399,51 @@ static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_
return 0;
}
+static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
+ const struct in_addr *dns;
+ uint32_t table;
+ int i, n, r;
+
+ assert(link);
+ assert(lease);
+ assert(link->network);
+
+ if (!link->network->dhcp_use_dns)
+ return 0;
+
+ n = sd_dhcp_lease_get_dns(lease, &dns);
+ if (IN_SET(n, 0, -ENODATA))
+ return 0;
+ if (n < 0)
+ return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
+
+ table = link_get_dhcp_route_table(link);
+
+ for (i = 0; i < n; i ++) {
+ _cleanup_(route_freep) Route *route = NULL;
+
+ r = route_new(&route);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate route: %m");
+
+ route->family = AF_INET;
+ route->dst.in = dns[i];
+ route->dst_prefixlen = 32;
+ route->prefsrc.in = *address;
+ route->scope = RT_SCOPE_LINK;
+ route->protocol = RTPROT_DHCP;
+ route->priority = link->network->dhcp_route_metric;
+ route->table = table;
+
+ if (!remove_all && set_contains(link->dhcp_routes, route))
+ continue;
+
+ (void) route_remove(route, link, NULL);
+ }
+
+ return 0;
+}
+
static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address) {
_cleanup_(address_freep) Address *a = NULL;
struct in_addr netmask;
@@ -440,6 +533,7 @@ static int dhcp_lease_lost(Link *link) {
(void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
(void) dhcp_remove_routes(link, link->dhcp_lease, &address, true);
(void) dhcp_remove_router(link, link->dhcp_lease, &address, true);
+ (void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true);
(void) dhcp_remove_address(link, link->dhcp_lease, &address);
(void) dhcp_reset_mtu(link);
(void) dhcp_reset_hostname(link);