]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-dhcp4.c
network: honor MTUBytes= setting
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
index c8eca6654582390d3b199bc14a403c54009d9acf..7907988a9bb9937c41f9c4411bee2f4df6c52987 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 
 #include "alloc-util.h"
@@ -214,10 +214,7 @@ static int dhcp_lease_lost(Link *link) {
                                 }
                         }
                 }
-        }
 
-        r = address_new(&address);
-        if (r >= 0) {
                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
                 if (r > 0 && !in4_addr_is_null(&router[0])) {
                         _cleanup_(route_freep) Route *route_gw = NULL;
@@ -241,7 +238,10 @@ static int dhcp_lease_lost(Link *link) {
                                 route_remove(route, link, NULL);
                         }
                 }
+        }
 
+        r = address_new(&address);
+        if (r >= 0) {
                 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
                 if (r >= 0) {
                         r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
@@ -308,6 +308,9 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
 
         link_set_dhcp_routes(link);
 
+        /* Add back static routes since kernel removes while DHCPv4 address is removed from when lease expires */
+        link_request_set_routes(link);
+
         if (link->dhcp4_messages == 0) {
                 link->dhcp4_configured = true;
                 link_check_ready(link);
@@ -471,7 +474,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                         if (r < 0)
                                 log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
                         if (r == 1)
-                                log_link_notice(link, "Overlong DCHP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
+                                log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
                 }
 
                 if (hostname) {
@@ -508,31 +511,76 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
 
         return 0;
 }
-static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
+
+static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
+        sd_dhcp_lease *lease;
+        struct in_addr addr;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(client);
+
+        r = sd_dhcp_client_get_lease(client, &lease);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
+
+        r = sd_dhcp_lease_get_server_identifier(lease, &addr);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
+
+        if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+                log_struct(LOG_DEBUG,
+                           LOG_LINK_INTERFACE(link),
+                           LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
+                                            ADDRESS_FMT_VAL(addr)));
+                return true;
+        }
+
+        return false;
+}
+
+static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
         Link *link = userdata;
-        int r = 0;
+        int r;
 
         assert(link);
         assert(link->network);
         assert(link->manager);
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return;
+                return 0;
 
         switch (event) {
-                case SD_DHCP_CLIENT_EVENT_EXPIRED:
                 case SD_DHCP_CLIENT_EVENT_STOP:
+
+                        if (link_ipv4ll_fallback_enabled(link)) {
+                                assert(link->ipv4ll);
+
+                                log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
+
+                                r = sd_ipv4ll_start(link->ipv4ll);
+                                if (r < 0)
+                                        return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
+                        }
+
+                        if (link->network->dhcp_send_release)
+                                (void) sd_dhcp_client_send_release(client);
+
+                        _fallthrough_;
+                case SD_DHCP_CLIENT_EVENT_EXPIRED:
                 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
+
                         if (link->network->dhcp_critical) {
                                 log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
-                                return;
+                                return 0;
                         }
 
                         if (link->dhcp_lease) {
                                 r = dhcp_lease_lost(link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -540,7 +588,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                                 r = dhcp_lease_acquired(client, link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -549,16 +597,23 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         r = dhcp_lease_renew(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
                 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
                         r = dhcp_lease_acquired(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
+                case SD_DHCP_CLIENT_EVENT_SELECTING:
+                        r = dhcp_server_is_black_listed(link, client);
+                        if (r < 0)
+                                return r;
+                        if (r != 0)
+                                return -ENOMSG;
+                        break;
                 default:
                         if (event < 0)
                                 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
@@ -567,7 +622,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         break;
         }
 
-        return;
+        return 0;
 }
 
 static int dhcp4_set_hostname(Link *link) {
@@ -814,5 +869,11 @@ int dhcp4_configure(Link *link) {
                         return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
         }
 
+        if (link->network->dhcp_max_attempts > 0) {
+                r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
+        }
+
         return dhcp4_set_client_identifier(link);
 }