]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: add basic NAK support
authorTom Gundersen <teg@jklm.no>
Sun, 25 May 2014 18:39:02 +0000 (20:39 +0200)
committerTom Gundersen <teg@jklm.no>
Fri, 13 Jun 2014 15:07:19 +0000 (17:07 +0200)
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/test-dhcp-server.c

index e170cfabf19335df55a055a3e193d0e0f8d9e743..75f43165503402a03615e46e8b43e562cb86022d 100644 (file)
@@ -303,7 +303,7 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
         assert(server);
         assert(ret);
         assert(_optoffset);
-        assert(IN_SET(type, DHCP_OFFER, DHCP_ACK));
+        assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
 
         packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
         if (!packet)
@@ -377,6 +377,22 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, be32_t addr
         return 0;
 }
 
+static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
+        _cleanup_free_ DHCPPacket *packet = NULL;
+        size_t offset;
+        int r;
+
+        r = server_message_init(server, &packet, DHCP_NAK, &offset, req);
+        if (r < 0)
+                return r;
+
+        r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 static int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
                          void *user_data) {
         DHCPRequest *req = user_data;
@@ -515,6 +531,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
         case DHCP_REQUEST:
         {
                 be32_t address;
+                bool init_reboot = false;
 
                 /* see RFC 2131, section 4.3.2 */
 
@@ -546,8 +563,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                 /* this MUST be zero */
                                 return 0;
 
-                        /* TODO: check if requested IP is correct, NAK if not */
+                        /* TODO: check more carefully if IP is correct */
                         address = req->requested_ip;
+                        init_reboot = true;
                 } else {
                         log_dhcp_server(server, "REQUEST (rebinding/renewing) (0x%x)",
                                         be32toh(req->message->xid));
@@ -576,8 +594,19 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                                 be32toh(req->message->xid));
                                 return DHCP_ACK;
                         }
-                } else
-                        return 0;
+                } else if (init_reboot) {
+                        r = server_send_nak(server, req);
+                        if (r < 0) {
+                                /* this only fails on critical errors */
+                                log_dhcp_server(server, "could not send nak: %s",
+                                                strerror(-r));
+                                return r;
+                        } else {
+                                log_dhcp_server(server, "NAK (0x%x)",
+                                                be32toh(req->message->xid));
+                                return DHCP_NAK;
+                        }
+                }
 
                 break;
         }
index 10fc2368cf27126f8633de13ecf44a2064f0d9f5..f738b3b42787645d133a6c3bc08bfba61602cfa4 100644 (file)
@@ -150,7 +150,7 @@ static void test_message_handler(void) {
         test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
         test.option_requested_ip.length = 4;
         test.option_requested_ip.address = htobe32(0x12345678);
-        assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
+        assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
         test.option_server_id.code = DHCP_OPTION_SERVER_IDENTIFIER;
         test.option_server_id.length = 4;
         test.option_server_id.address = htobe32(INADDR_LOOPBACK);
@@ -159,8 +159,8 @@ static void test_message_handler(void) {
         test.option_server_id.address = htobe32(0x12345678);
         test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
-        test.option_server_id.address = htobe32(INADDR_LOOPBACK + 3);
-        test.option_requested_ip.address = htobe32(0x12345678);
+        test.option_server_id.address = htobe32(INADDR_LOOPBACK);
+        test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
         assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
 }