about summary refs log tree commit diff
path: root/src/n-dhcp4
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
committerSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
commit1e636d8e5e986b9f2260c36bb87fb499d724085c (patch)
treeac613b9372adf622496a7d616050d7e1c09b4fba /src/n-dhcp4
parentf4966e573c855d4667e6c236d8197d9949020e21 (diff)
parent1a31bc3c63474ca02c83b02add85ea4e740e5597 (diff)
Merge remote-tracking branch 'debian/debian/master' into ubuntu/master
Diffstat (limited to 'src/n-dhcp4')
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-connection.c36
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-probe.c3
-rw-r--r--src/n-dhcp4/src/n-dhcp4-private.h10
3 files changed, 32 insertions, 17 deletions
diff --git a/src/n-dhcp4/src/n-dhcp4-c-connection.c b/src/n-dhcp4/src/n-dhcp4-c-connection.c
index 4aba9739..65328286 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-connection.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-connection.c
@@ -705,6 +705,7 @@ int n_dhcp4_c_connection_select_new(NDhcp4CConnection *connection,
         message->userdata.start_time = offer->userdata.start_time;
         message->userdata.base_time = offer->userdata.base_time;
         message->userdata.client_addr = client.s_addr;
+        message->userdata.server_id = server.s_addr;
         n_dhcp4_incoming_get_xid(offer, &xid);
         n_dhcp4_outgoing_set_xid(message, xid);
 
@@ -1146,16 +1147,21 @@ int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection,
 int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
                                      NDhcp4Incoming **messagep) {
         _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL;
+        _c_cleanup_(c_freep) uint8_t *buffer = NULL;
         char serv_addr[INET_ADDRSTRLEN];
         char client_addr[INET_ADDRSTRLEN];
         uint8_t type = 0;
         int r;
 
+        buffer = malloc(UINT16_MAX);
+        if (!buffer)
+                return -ENOMEM;
+
         switch (connection->state) {
         case N_DHCP4_C_CONNECTION_STATE_PACKET:
                 r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
-                                                 connection->scratch_buffer,
-                                                 sizeof(connection->scratch_buffer),
+                                                 buffer,
+                                                 UINT16_MAX,
                                                  &message);
                 if (!r)
                         break;
@@ -1164,8 +1170,8 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
                 return N_DHCP4_E_AGAIN;
         case N_DHCP4_C_CONNECTION_STATE_DRAINING:
                 r = n_dhcp4_c_socket_packet_recv(connection->fd_packet,
-                                                 connection->scratch_buffer,
-                                                 sizeof(connection->scratch_buffer),
+                                                 buffer,
+                                                 UINT16_MAX,
                                                  &message);
                 if (!r)
                         break;
@@ -1187,8 +1193,8 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
                 /* fall-through */
         case N_DHCP4_C_CONNECTION_STATE_UDP:
                 r = n_dhcp4_c_socket_udp_recv(connection->fd_udp,
-                                              connection->scratch_buffer,
-                                              sizeof(connection->scratch_buffer),
+                                              buffer,
+                                              UINT16_MAX,
                                               &message);
                 if (!r)
                         break;
@@ -1224,6 +1230,24 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,
                                       serv_addr, sizeof(serv_addr)));
         }
 
+        if (type == N_DHCP4_MESSAGE_NAK &&
+            connection->request->userdata.server_id != INADDR_ANY) {
+                struct in_addr server;
+
+                r = n_dhcp4_incoming_query_server_identifier(message, &server);
+                if (r)
+                        return N_DHCP4_E_AGAIN;
+
+                if (connection->request->userdata.server_id != server.s_addr) {
+                        n_dhcp4_log(connection->log_queue,
+                                    LOG_DEBUG,
+                                    "discarded NAK with wrong server-id %s",
+                                    inet_ntop(AF_INET, &server,
+                                              serv_addr, sizeof(serv_addr)));
+                        return N_DHCP4_E_AGAIN;
+                }
+        }
+
         switch (type) {
         case N_DHCP4_MESSAGE_OFFER:
         case N_DHCP4_MESSAGE_ACK:
diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c
index 7f20ac05..283c1693 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c
@@ -995,14 +995,13 @@ static int n_dhcp4_client_probe_transition_nak(NDhcp4ClientProbe *probe) {
         case N_DHCP4_CLIENT_PROBE_STATE_RENEWING:
         case N_DHCP4_CLIENT_PROBE_STATE_REBINDING:
 
-                /* XXX */
-
                 r = n_dhcp4_client_probe_raise(probe,
                                                NULL,
                                                N_DHCP4_CLIENT_EVENT_RETRACTED);
                 if (r)
                         return r;
 
+                probe->current_lease = n_dhcp4_client_lease_unref(probe->current_lease);
                 probe->state = N_DHCP4_CLIENT_PROBE_STATE_INIT;
                 probe->ns_deferred = n_dhcp4_gettime(CLOCK_BOOTTIME) + probe->ns_nak_restart_delay;
                 probe->ns_nak_restart_delay = C_CLAMP(probe->ns_nak_restart_delay * 2u,
diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h
index db7b24ff..858c3d3a 100644
--- a/src/n-dhcp4/src/n-dhcp4-private.h
+++ b/src/n-dhcp4/src/n-dhcp4-private.h
@@ -202,6 +202,7 @@ struct NDhcp4Outgoing {
                 uint8_t type;
                 uint8_t message_type;
                 uint32_t client_addr;
+                uint32_t server_id;
                 uint64_t start_time;
                 uint64_t base_time;
                 uint64_t send_time;
@@ -333,15 +334,6 @@ struct NDhcp4CConnection {
         uint32_t client_ip;             /* client IP address, or 0 */
         uint32_t server_ip;             /* server IP address, or 0 */
         uint16_t mtu;                   /* client mtu, or 0 */
-
-        /*
-         * When we get DHCP packets from the kernel, we need a buffer to read
-         * the data into. Since UDP packets can be up to 2^16 bytes in size, we
-         * avoid placing it on the stack and instead read into this scratch
-         * buffer. It is purely meant as stack replacement, no data is returned
-         * through this buffer.
-         */
-        uint8_t scratch_buffer[UINT16_MAX];
 };
 
 #define N_DHCP4_C_CONNECTION_NULL(_x) {                                         \