[systemd-devel] [PATCH 12/17] sd-dhcp-server: add basic NAK support

Tom Gundersen teg at jklm.no
Mon May 26 12:39:41 PDT 2014


---
 src/libsystemd-network/sd-dhcp-server.c   | 36 +++++++++++++++++++++++++++----
 src/libsystemd-network/test-dhcp-server.c |  6 +++---
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 01cd8be..b82bef8 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -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;
@@ -514,6 +530,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 */
 
@@ -545,8 +562,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));
@@ -574,8 +592,18 @@ 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) {
+                                log_dhcp_server(server, "could not send nak: %s",
+                                                strerror(-r));
+                                return 0;
+                        } else {
+                                log_dhcp_server(server, "NAK (0x%x)",
+                                                be32toh(req->message->xid));
+                                return DHCP_NAK;
+                        }
+                }
 
                 break;
         }
diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
index 7255a69..ea256b9 100644
--- a/src/libsystemd-network/test-dhcp-server.c
+++ b/src/libsystemd-network/test-dhcp-server.c
@@ -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);
 }
 
-- 
1.9.0



More information about the systemd-devel mailing list