summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-dhcp4.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-05-24 09:47:47 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-05-28 15:21:23 +0200
commit7fa472f9b71b6cfa8503d45674a062d69966b11d (patch)
treeee6603acc672b867783de0003718f9181ebbc361 /src/network/networkd-dhcp4.c
parentnetwork: set dhcp4_configured flag false before configuring address (diff)
downloadsystemd-7fa472f9b71b6cfa8503d45674a062d69966b11d.tar.xz
systemd-7fa472f9b71b6cfa8503d45674a062d69966b11d.zip
network: split dhcp_lease_lost() into small pieces
Diffstat (limited to 'src/network/networkd-dhcp4.c')
-rw-r--r--src/network/networkd-dhcp4.c269
1 files changed, 167 insertions, 102 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index ae74508c87..42d8c43248 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -181,131 +181,196 @@ static int link_set_dhcp_routes(Link *link) {
return 0;
}
-static int dhcp_lease_lost(Link *link) {
- struct in_addr address = {};
- int r;
+static int dhcp_remove_routes(Link *link, struct in_addr *address) {
+ _cleanup_free_ sd_dhcp_route **routes = NULL;
+ uint32_t table;
+ int n, i, r;
assert(link);
- assert(link->dhcp_lease);
+ assert(address);
- log_link_warning(link, "DHCP lease lost");
+ if (!link->network->dhcp_use_routes)
+ return 0;
- link->dhcp4_configured = false;
+ n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
+ if (IN_SET(n, 0, -ENODATA)) {
+ log_link_debug(link, "DHCP: No routes received from DHCP server: %m");
+ return 0;
+ } else if (n < 0)
+ return log_link_error_errno(link, n, "DHCP error: could not get routes: %m");
- (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+ table = link_get_dhcp_route_table(link);
- if (link->network->dhcp_use_routes) {
- _cleanup_free_ sd_dhcp_route **routes = NULL;
- const struct in_addr *router;
- uint32_t table;
- int n, i;
-
- table = link_get_dhcp_route_table(link);
-
- n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
- if (n >= 0) {
- for (i = 0; i < n; i++) {
- _cleanup_(route_freep) Route *route = NULL;
-
- r = route_new(&route);
- if (r >= 0) {
- route->family = AF_INET;
- assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
- assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
- assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
- route->priority = link->network->dhcp_route_metric;
- route->table = table;
- route->scope = route_scope_from_address(route, &address);
-
- route_remove(route, link, NULL);
- }
- }
- }
+ for (i = 0; i < n; i++) {
+ _cleanup_(route_freep) Route *route = NULL;
- r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
- if (r > 0 && !in4_addr_is_null(&router[0]) && !in4_addr_is_null(&address)) {
- _cleanup_(route_freep) Route *route_gw = NULL;
- _cleanup_(route_freep) Route *route = NULL;
-
- r = route_new(&route_gw);
- if (r >= 0) {
- route_gw->family = AF_INET;
- route_gw->dst.in = router[0];
- route_gw->dst_prefixlen = 32;
- route_gw->prefsrc.in = address;
- route_gw->scope = RT_SCOPE_LINK;
- route_gw->protocol = RTPROT_DHCP;
- route_gw->priority = link->network->dhcp_route_metric;
- route_gw->table = table;
-
- route_remove(route_gw, link, NULL);
- }
+ r = route_new(&route);
+ if (r < 0)
+ return log_oom();
- r = route_new(&route);
- if (r >= 0) {
- route->family = AF_INET;
- route->gw.in = router[0];
- route->prefsrc.in = address;
- route->protocol = RTPROT_DHCP;
- route->priority = link->network->dhcp_route_metric;
- route->table = table;
+ route->family = AF_INET;
+ assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
+ assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
+ assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
+ route->priority = link->network->dhcp_route_metric;
+ route->table = table;
+ route->scope = route_scope_from_address(route, address);
- route_remove(route, link, NULL);
- }
- }
+ (void) route_remove(route, link, NULL);
}
- if (!in4_addr_is_null(&address)) {
- _cleanup_(address_freep) Address *a = NULL;
+ return n;
+}
- r = address_new(&a);
- if (r >= 0) {
- struct in_addr netmask;
- unsigned prefixlen = 0;
+static int dhcp_remove_router(Link *link, struct in_addr *address) {
+ _cleanup_(route_freep) Route *route_gw = NULL, *route = NULL;
+ const struct in_addr *router;
+ uint32_t table;
+ int r;
- r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
- if (r >= 0)
- prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+ assert(link);
+ assert(address);
- a->family = AF_INET;
- a->in_addr.in = address;
- a->prefixlen = prefixlen;
+ if (!link->network->dhcp_use_routes)
+ return 0;
- address_remove(a, link, NULL);
- }
+ r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
+ if (IN_SET(r, 0, -ENODATA)) {
+ log_link_debug(link, "DHCP: No gateway received from DHCP server.");
+ return 0;
+ } else if (r < 0)
+ return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
+ else if (in4_addr_is_null(&router[0])) {
+ log_link_info(link, "DHCP: Received gateway is null, ignoring.");
+ return 0;
}
- if (link->network->dhcp_use_mtu) {
- uint16_t mtu;
+ table = link_get_dhcp_route_table(link);
- r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
- if (r >= 0 && link->original_mtu != mtu) {
- r = link_set_mtu(link, link->original_mtu);
- if (r < 0) {
- log_link_warning(link,
- "DHCP error: could not reset MTU");
- link_enter_failed(link);
- return r;
- }
- }
- }
+ r = route_new(&route_gw);
+ if (r < 0)
+ return log_oom();
- if (link->network->dhcp_use_hostname) {
- const char *hostname = NULL;
+ route_gw->family = AF_INET;
+ route_gw->dst.in = router[0];
+ route_gw->dst_prefixlen = 32;
+ route_gw->prefsrc.in = *address;
+ route_gw->scope = RT_SCOPE_LINK;
+ route_gw->protocol = RTPROT_DHCP;
+ route_gw->priority = link->network->dhcp_route_metric;
+ route_gw->table = table;
- if (link->network->dhcp_hostname)
- hostname = link->network->dhcp_hostname;
- else
- (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
+ (void) route_remove(route_gw, link, NULL);
- if (hostname) {
- /* If a hostname was set due to the lease, then unset it now. */
- r = manager_set_hostname(link->manager, NULL);
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
- }
+ r = route_new(&route);
+ if (r < 0)
+ return log_oom();
+
+ route->family = AF_INET;
+ route->gw.in = router[0];
+ route->prefsrc.in = *address;
+ route->protocol = RTPROT_DHCP;
+ route->priority = link->network->dhcp_route_metric;
+ route->table = table;
+
+ (void) route_remove(route, link, NULL);
+
+ return 0;
+}
+
+static int dhcp_remove_address(Link *link, struct in_addr *address) {
+ _cleanup_(address_freep) Address *a = NULL;
+ struct in_addr netmask;
+ int r;
+
+ assert(link);
+ assert(address);
+
+ if (in4_addr_is_null(address))
+ return 0;
+
+ r = address_new(&a);
+ if (r < 0)
+ return log_oom();
+
+ a->family = AF_INET;
+ a->in_addr.in = *address;
+
+ if (sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask) >= 0)
+ a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
+
+ (void) address_remove(a, link, NULL);
+
+ return 0;
+}
+
+static int dhcp_reset_mtu(Link *link) {
+ uint16_t mtu;
+ int r;
+
+ assert(link);
+
+ if (!link->network->dhcp_use_mtu)
+ return 0;
+
+ r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
+ if (r < 0)
+ return r;
+
+ if (link->original_mtu == mtu)
+ return 0;
+
+ r = link_set_mtu(link, link->original_mtu);
+ if (r < 0) {
+ log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m");
+ link_enter_failed(link);
+ return r;
}
+ return 0;
+}
+
+static int dhcp_reset_hostname(Link *link) {
+ const char *hostname;
+ int r;
+
+ assert(link);
+
+ if (!link->network->dhcp_use_hostname)
+ return 0;
+
+ hostname = link->network->dhcp_hostname;
+ if (!hostname)
+ (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
+
+ if (!hostname)
+ return 0;
+
+ /* If a hostname was set due to the lease, then unset it now. */
+ r = manager_set_hostname(link->manager, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP error: Failed to reset transient hostname: %m");
+
+ return 0;
+}
+
+static int dhcp_lease_lost(Link *link) {
+ struct in_addr address = {};
+
+ assert(link);
+ assert(link->dhcp_lease);
+
+ log_link_warning(link, "DHCP lease lost");
+
+ link->dhcp4_configured = false;
+
+ (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
+ (void) dhcp_remove_routes(link, &address);
+ (void) dhcp_remove_router(link, &address);
+ (void) dhcp_remove_address(link, &address);
+ (void) dhcp_reset_mtu(link);
+ (void) dhcp_reset_hostname(link);
+
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link_dirty(link);