diff options
-rw-r--r-- | networking/udhcp/dhcpd.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index a015cf038..ac77b511d 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -133,7 +133,10 @@ static uint32_t select_lease_time(struct dhcp_packet *packet) | |||
133 | 133 | ||
134 | /* We got a DHCP DISCOVER. Send an OFFER. */ | 134 | /* We got a DHCP DISCOVER. Send an OFFER. */ |
135 | /* NOINLINE: limit stack usage in caller */ | 135 | /* NOINLINE: limit stack usage in caller */ |
136 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) | 136 | static NOINLINE void send_offer(struct dhcp_packet *oldpacket, |
137 | uint32_t static_lease_nip, | ||
138 | struct dyn_lease *lease, | ||
139 | uint8_t *requested_ip_opt) | ||
137 | { | 140 | { |
138 | struct dhcp_packet packet; | 141 | struct dhcp_packet packet; |
139 | uint32_t lease_time_sec; | 142 | uint32_t lease_time_sec; |
@@ -147,7 +150,6 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_l | |||
147 | if (!static_lease_nip) { | 150 | if (!static_lease_nip) { |
148 | /* We have no static lease for client's chaddr */ | 151 | /* We have no static lease for client's chaddr */ |
149 | uint32_t req_nip; | 152 | uint32_t req_nip; |
150 | uint8_t *req_ip_opt; | ||
151 | const char *p_host_name; | 153 | const char *p_host_name; |
152 | 154 | ||
153 | if (lease) { | 155 | if (lease) { |
@@ -158,9 +160,9 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_l | |||
158 | packet.yiaddr = lease->lease_nip; | 160 | packet.yiaddr = lease->lease_nip; |
159 | } | 161 | } |
160 | /* Or: if client has requested an IP */ | 162 | /* Or: if client has requested an IP */ |
161 | else if ((req_ip_opt = udhcp_get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL | 163 | else if (requested_ip_opt != NULL |
162 | /* (read IP) */ | 164 | /* (read IP) */ |
163 | && (move_from_unaligned32(req_nip, req_ip_opt), 1) | 165 | && (move_from_unaligned32(req_nip, requested_ip_opt), 1) |
164 | /* and the IP is in the lease range */ | 166 | /* and the IP is in the lease range */ |
165 | && ntohl(req_nip) >= server_config.start_ip | 167 | && ntohl(req_nip) >= server_config.start_ip |
166 | && ntohl(req_nip) <= server_config.end_ip | 168 | && ntohl(req_nip) <= server_config.end_ip |
@@ -283,16 +285,12 @@ struct dyn_lease *g_leases; | |||
283 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 285 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
284 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) | 286 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) |
285 | { | 287 | { |
286 | fd_set rfds; | ||
287 | int server_socket = -1, retval, max_sock; | 288 | int server_socket = -1, retval, max_sock; |
288 | struct dhcp_packet packet; | ||
289 | uint8_t *state; | 289 | uint8_t *state; |
290 | uint32_t static_lease_nip; | ||
291 | unsigned timeout_end; | 290 | unsigned timeout_end; |
292 | unsigned num_ips; | 291 | unsigned num_ips; |
293 | unsigned opt; | 292 | unsigned opt; |
294 | struct option_set *option; | 293 | struct option_set *option; |
295 | struct dyn_lease *lease, fake_lease; | ||
296 | IF_FEATURE_UDHCP_PORT(char *str_P;) | 294 | IF_FEATURE_UDHCP_PORT(char *str_P;) |
297 | 295 | ||
298 | #if ENABLE_FEATURE_UDHCP_PORT | 296 | #if ENABLE_FEATURE_UDHCP_PORT |
@@ -372,11 +370,15 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
372 | 370 | ||
373 | timeout_end = monotonic_sec() + server_config.auto_time; | 371 | timeout_end = monotonic_sec() + server_config.auto_time; |
374 | while (1) { /* loop until universe collapses */ | 372 | while (1) { /* loop until universe collapses */ |
373 | fd_set rfds; | ||
374 | struct dhcp_packet packet; | ||
375 | int bytes; | 375 | int bytes; |
376 | struct timeval tv; | 376 | struct timeval tv; |
377 | uint8_t *server_id_opt; | 377 | uint8_t *server_id_opt; |
378 | uint8_t *requested_opt; | 378 | uint8_t *requested_ip_opt; |
379 | uint32_t requested_nip = requested_nip; /* for compiler */ | 379 | uint32_t requested_nip = requested_nip; /* for compiler */ |
380 | uint32_t static_lease_nip; | ||
381 | struct dyn_lease *lease, fake_lease; | ||
380 | 382 | ||
381 | if (server_socket < 0) { | 383 | if (server_socket < 0) { |
382 | server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, | 384 | server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT, |
@@ -443,6 +445,18 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
443 | continue; | 445 | continue; |
444 | } | 446 | } |
445 | 447 | ||
448 | /* Get SERVER_ID if present */ | ||
449 | server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); | ||
450 | if (server_id_opt) { | ||
451 | uint32_t server_id_net; | ||
452 | move_from_unaligned32(server_id_net, server_id_opt); | ||
453 | if (server_id_net != server_config.server_nip) { | ||
454 | /* client talks to somebody else */ | ||
455 | log1("server ID doesn't match, ignoring"); | ||
456 | continue; | ||
457 | } | ||
458 | } | ||
459 | |||
446 | /* Look for a static/dynamic lease */ | 460 | /* Look for a static/dynamic lease */ |
447 | static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); | 461 | static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr); |
448 | if (static_lease_nip) { | 462 | if (static_lease_nip) { |
@@ -455,20 +469,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
455 | lease = find_lease_by_mac(packet.chaddr); | 469 | lease = find_lease_by_mac(packet.chaddr); |
456 | } | 470 | } |
457 | 471 | ||
458 | /* Get REQUESTED_IP and SERVER_ID if present */ | 472 | /* Get REQUESTED_IP if present */ |
459 | server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); | 473 | requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); |
460 | if (server_id_opt) { | 474 | if (requested_ip_opt) { |
461 | uint32_t server_id_net; | 475 | move_from_unaligned32(requested_nip, requested_ip_opt); |
462 | move_from_unaligned32(server_id_net, server_id_opt); | ||
463 | if (server_id_net != server_config.server_nip) { | ||
464 | /* client talks to somebody else */ | ||
465 | log1("server ID doesn't match, ignoring"); | ||
466 | continue; | ||
467 | } | ||
468 | } | ||
469 | requested_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); | ||
470 | if (requested_opt) { | ||
471 | move_from_unaligned32(requested_nip, requested_opt); | ||
472 | } | 476 | } |
473 | 477 | ||
474 | switch (state[0]) { | 478 | switch (state[0]) { |
@@ -476,7 +480,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
476 | case DHCPDISCOVER: | 480 | case DHCPDISCOVER: |
477 | log1("Received DISCOVER"); | 481 | log1("Received DISCOVER"); |
478 | 482 | ||
479 | send_offer(&packet, static_lease_nip, lease); | 483 | send_offer(&packet, static_lease_nip, lease, requested_ip_opt); |
480 | break; | 484 | break; |
481 | 485 | ||
482 | case DHCPREQUEST: | 486 | case DHCPREQUEST: |
@@ -567,7 +571,7 @@ o DHCPREQUEST generated during REBINDING state: | |||
567 | A DHCP server MAY extend a client's lease only if it has local | 571 | A DHCP server MAY extend a client's lease only if it has local |
568 | administrative authority to do so. | 572 | administrative authority to do so. |
569 | */ | 573 | */ |
570 | if (!requested_opt) { | 574 | if (!requested_ip_opt) { |
571 | requested_nip = packet.ciaddr; | 575 | requested_nip = packet.ciaddr; |
572 | if (requested_nip == 0) { | 576 | if (requested_nip == 0) { |
573 | log1("no requested IP and no ciaddr, ignoring"); | 577 | log1("no requested IP and no ciaddr, ignoring"); |
@@ -603,7 +607,7 @@ o DHCPREQUEST generated during REBINDING state: | |||
603 | */ | 607 | */ |
604 | log1("Received DECLINE"); | 608 | log1("Received DECLINE"); |
605 | if (server_id_opt | 609 | if (server_id_opt |
606 | && requested_opt | 610 | && requested_ip_opt |
607 | && lease /* chaddr matches this lease */ | 611 | && lease /* chaddr matches this lease */ |
608 | && requested_nip == lease->lease_nip | 612 | && requested_nip == lease->lease_nip |
609 | ) { | 613 | ) { |