summaryrefslogtreecommitdiff
path: root/src/network/networkd-link.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r--src/network/networkd-link.c294
1 files changed, 168 insertions, 126 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 363602e962..0a363b2547 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -410,175 +410,217 @@ static int link_set_mtu(Link *link, uint32_t mtu) {
return 0;
}
-static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
- Link *link = userdata;
- struct in_addr address;
- struct in_addr netmask;
- struct in_addr gateway;
- unsigned prefixlen;
+static int dhcp_lease_lost(sd_dhcp_client *client, Link *link) {
int r;
+ assert(client);
assert(link);
- assert(link->network);
- assert(link->manager);
- if (link->state == LINK_STATE_FAILED)
- return;
+ if (link->dhcp_address) {
+ address_drop(link->dhcp_address, link, address_drop_handler);
- if (event < 0) {
- log_warning_link(link, "DHCP error: %s", strerror(-event));
- link_enter_failed(link);
- return;
+ address_free(link->dhcp_address);
+ link->dhcp_address = NULL;
}
- if (event == DHCP_EVENT_NO_LEASE)
- log_debug_link(link, "IP address in use.");
-
- if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
- event == DHCP_EVENT_STOP) {
- if (link->network->dhcp_critical) {
- log_warning_link(link, "DHCPv4 connection considered system critical, "
- "ignoring request to reconfigure it down.");
- return;
- }
+ if (link->dhcp_route) {
+ route_free(link->dhcp_route);
+ link->dhcp_route = NULL;
+ }
- if (link->dhcp_address) {
- address_drop(link->dhcp_address, link, address_drop_handler);
+ if (link->network->dhcp_mtu) {
+ uint16_t mtu;
- address_free(link->dhcp_address);
- link->dhcp_address = NULL;
+ r = sd_dhcp_client_get_mtu(client, &mtu);
+ if (r >= 0 && link->original_mtu != mtu) {
+ r = link_set_mtu(link, link->original_mtu);
+ if (r < 0) {
+ log_warning_link(link, "DHCP error: could not reset MTU");
+ link_enter_failed(link);
+ return r;
+ }
}
+ }
- if (link->dhcp_route) {
- route_free(link->dhcp_route);
- link->dhcp_route = NULL;
- }
+ if (link->network->dhcp_hostname) {
+ r = set_hostname(link->manager->bus, "");
+ if (r < 0)
+ log_error("Failed to reset transient hostname");
+ }
- if (link->network->dhcp_mtu) {
- uint16_t mtu;
+ return 0;
+}
- r = sd_dhcp_client_get_mtu(client, &mtu);
- if (r >= 0 && link->original_mtu != mtu) {
- r = link_set_mtu(link, link->original_mtu);
- if (r < 0) {
- log_warning_link(link, "DHCP error: could not reset MTU");
- link_enter_failed(link);
- return;
- }
- }
- }
+static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
+ struct in_addr address;
+ struct in_addr netmask;
+ struct in_addr gateway;
+ unsigned prefixlen;
+ _cleanup_address_free_ Address *addr = NULL;
+ _cleanup_route_free_ Route *rt = NULL;
+ struct in_addr *nameservers;
+ size_t nameservers_size;
+ int r;
- if (link->network->dhcp_hostname) {
- r = set_hostname(link->manager->bus, "");
- if (r < 0)
- log_error("Failed to reset transient hostname");
- }
- }
+ assert(client);
+ assert(link);
r = sd_dhcp_client_get_address(client, &address);
if (r < 0) {
- log_warning_link(link, "DHCP error: no address");
- link_enter_failed(link);
- return;
+ log_warning_link(link, "DHCP error: no address: %s",
+ strerror(-r));
+ return r;
}
r = sd_dhcp_client_get_netmask(client, &netmask);
if (r < 0) {
- log_warning_link(link, "DHCP error: no netmask");
- link_enter_failed(link);
- return;
+ log_warning_link(link, "DHCP error: no netmask: %s",
+ strerror(-r));
+ return r;
}
prefixlen = net_netmask_to_prefixlen(&netmask);
r = sd_dhcp_client_get_router(client, &gateway);
if (r < 0) {
- log_warning_link(link, "DHCP error: no router");
- link_enter_failed(link);
- return;
+ log_warning_link(link, "DHCP error: no router: %s",
+ strerror(-r));
+ return r;
}
- if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
- _cleanup_address_free_ Address *addr = NULL;
- _cleanup_route_free_ Route *rt = NULL;
- struct in_addr *nameservers;
- size_t nameservers_size;
-
- log_struct_link(LOG_INFO, link,
- "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
- link->ifname,
- ADDRESS_FMT_VAL(address),
- prefixlen,
- ADDRESS_FMT_VAL(gateway),
- "ADDRESS=%u.%u.%u.%u",
- ADDRESS_FMT_VAL(address),
- "PREFIXLEN=%u",
- prefixlen,
- "GATEWAY=%u.%u.%u.%u",
- ADDRESS_FMT_VAL(gateway),
- NULL);
- r = address_new_dynamic(&addr);
- if (r < 0) {
- log_error_link(link, "Could not allocate address");
- link_enter_failed(link);
- return;
- }
+ log_struct_link(LOG_INFO, link,
+ "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
+ link->ifname,
+ ADDRESS_FMT_VAL(address),
+ prefixlen,
+ ADDRESS_FMT_VAL(gateway),
+ "ADDRESS=%u.%u.%u.%u",
+ ADDRESS_FMT_VAL(address),
+ "PREFIXLEN=%u",
+ prefixlen,
+ "GATEWAY=%u.%u.%u.%u",
+ ADDRESS_FMT_VAL(gateway),
+ NULL);
- addr->family = AF_INET;
- addr->in_addr.in = address;
- addr->prefixlen = prefixlen;
- addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
+ r = address_new_dynamic(&addr);
+ if (r < 0) {
+ log_error_link(link, "Could not allocate address: %s",
+ strerror(-r));
+ return r;
+ }
- r = route_new_dynamic(&rt);
- if (r < 0) {
- log_error_link(link, "Could not allocate route");
- link_enter_failed(link);
- return;
+ addr->family = AF_INET;
+ addr->in_addr.in = address;
+ addr->prefixlen = prefixlen;
+ addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
+
+ r = route_new_dynamic(&rt);
+ if (r < 0) {
+ log_error_link(link, "Could not allocate route: %s",
+ strerror(-r));
+ return r;
+ }
+
+ rt->family = AF_INET;
+ rt->in_addr.in = gateway;
+
+ link->dhcp_address = addr;
+ link->dhcp_route = rt;
+ addr = NULL;
+ rt = NULL;
+
+ if (link->network->dhcp_dns) {
+ r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
+ if (r >= 0) {
+ r = manager_update_resolv_conf(link->manager);
+ if (r < 0)
+ log_error("Failed to update resolv.conf");
}
+ }
+
+ if (link->network->dhcp_mtu) {
+ uint16_t mtu;
- rt->family = AF_INET;
- rt->in_addr.in = gateway;
+ r = sd_dhcp_client_get_mtu(client, &mtu);
+ if (r >= 0) {
+ r = link_set_mtu(link, mtu);
+ if (r < 0)
+ log_error_link(link, "Failed to set MTU "
+ "to %" PRIu16, mtu);
+ }
+ }
- link->dhcp_address = addr;
- link->dhcp_route = rt;
- addr = NULL;
- rt = NULL;
+ if (link->network->dhcp_hostname) {
+ const char *hostname;
- if (link->network->dhcp_dns) {
- r = sd_dhcp_client_get_dns(client, &nameservers, &nameservers_size);
- if (r >= 0) {
- r = manager_update_resolv_conf(link->manager);
- if (r < 0)
- log_error("Failed to update resolv.conf");
- }
+ r = sd_dhcp_client_get_hostname(client, &hostname);
+ if (r >= 0) {
+ r = set_hostname(link->manager->bus, hostname);
+ if (r < 0)
+ log_error("Failed to set transient hostname "
+ "to '%s'", hostname);
}
+ }
- if (link->network->dhcp_mtu) {
- uint16_t mtu;
-
- r = sd_dhcp_client_get_mtu(client, &mtu);
- if (r >= 0) {
- r = link_set_mtu(link, mtu);
- if (r < 0)
- log_error_link(link, "Failed to set MTU "
- "to %" PRIu16, mtu);
+ link_enter_set_addresses(link);
+
+ return 0;
+}
+
+static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
+ Link *link = userdata;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+
+ if (link->state == LINK_STATE_FAILED)
+ return;
+
+ switch (event) {
+ case DHCP_EVENT_NO_LEASE:
+ log_debug_link(link, "IP address in use.");
+ break;
+ case DHCP_EVENT_EXPIRED:
+ case DHCP_EVENT_STOP:
+ case DHCP_EVENT_IP_CHANGE:
+ if (link->network->dhcp_critical) {
+ log_error_link(link, "DHCPv4 connection considered system critical, "
+ "ignoring request to reconfigure it.");
+ return;
}
- }
- if (link->network->dhcp_hostname) {
- const char *hostname;
+ r = dhcp_lease_lost(client, link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return;
+ }
- r = sd_dhcp_client_get_hostname(client, &hostname);
- if (r >= 0) {
- r = set_hostname(link->manager->bus, hostname);
- if (r < 0)
- log_error("Failed to set transient hostname "
- "to '%s'", hostname);
+ if (event == DHCP_EVENT_IP_CHANGE) {
+ r = dhcp_lease_acquired(client, link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return;
+ }
}
- }
- link_enter_set_addresses(link);
+ break;
+ case DHCP_EVENT_IP_ACQUIRE:
+ r = dhcp_lease_acquired(client, link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return;
+ }
+ break;
+ default:
+ if (event < 0)
+ log_warning_link(link, "DHCP error: %s", strerror(-event));
+ else
+ log_warning_link(link, "DHCP unknown event: %d", event);
+ link_enter_failed(link);
+ break;
}
return;