diff options
author | Tom Gundersen <teg@jklm.no> | 2014-05-25 20:39:02 +0200 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-06-13 17:07:19 +0200 |
commit | bd57b45029ff25067704c9538e79f31e71c10045 (patch) | |
tree | 237af7a42df5b7309f1824831d465cf8f7e91ca7 /src | |
parent | 2dead8129f7b6fe644e17e1dc1739bebacfe1364 (diff) |
sd-dhcp-server: add basic NAK support
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd-network/sd-dhcp-server.c | 37 | ||||
-rw-r--r-- | src/libsystemd-network/test-dhcp-server.c | 6 |
2 files changed, 36 insertions, 7 deletions
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index e170cfabf1..75f4316550 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; @@ -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; } diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 10fc2368cf..f738b3b427 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); } |