aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/dhcpd.c56
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 */
136static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) 136static 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;
283int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 285int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
284int udhcpd_main(int argc UNUSED_PARAM, char **argv) 286int 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 ) {