diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-21 06:46:09 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-21 06:46:09 +0100 |
commit | 53f72bb3f0bd81b1d3af8939a16ec730c7e750c3 (patch) | |
tree | 0d3f302f7692b5cbd473a76eeb28a506c5d9cf5f | |
parent | c7dc79e71ddbc1498736a2bbf65a3da179557f83 (diff) | |
download | busybox-w32-53f72bb3f0bd81b1d3af8939a16ec730c7e750c3.tar.gz busybox-w32-53f72bb3f0bd81b1d3af8939a16ec730c7e750c3.tar.bz2 busybox-w32-53f72bb3f0bd81b1d3af8939a16ec730c7e750c3.zip |
dhcpd: apparently, sometimes IP is in ciaddr, not requested_ip...
also revert the part which appempted to "fix" that in client
function old new delta
udhcpd_main 1949 1964 +15
send_renew 142 105 -37
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 15/-37) Total: -22 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/clientpacket.c | 13 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 101 |
2 files changed, 93 insertions, 21 deletions
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c index a0be42885..b4a75be02 100644 --- a/networking/udhcp/clientpacket.c +++ b/networking/udhcp/clientpacket.c | |||
@@ -156,20 +156,7 @@ int FAST_FUNC send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
156 | 156 | ||
157 | init_packet(&packet, DHCPREQUEST); | 157 | init_packet(&packet, DHCPREQUEST); |
158 | packet.xid = xid; | 158 | packet.xid = xid; |
159 | /* RFC 2131: | ||
160 | * "3.2 Client-server interaction - reusing a previously | ||
161 | * allocated network address"... | ||
162 | * The client broadcasts a DHCPREQUEST message on its local subnet. | ||
163 | * The message includes the client's network address in the | ||
164 | * REQUESTED_IP option. As the client has not received its | ||
165 | * network address, it MUST NOT fill in the 'ciaddr' field." | ||
166 | * | ||
167 | * FIXME: we seem to not follow this, we do set ciaddr. | ||
168 | */ | ||
169 | packet.ciaddr = ciaddr; | 159 | packet.ciaddr = ciaddr; |
170 | add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr); | ||
171 | if (server) | ||
172 | add_simple_option(packet.options, DHCP_SERVER_ID, server); | ||
173 | add_param_req_option(&packet); | 160 | add_param_req_option(&packet); |
174 | 161 | ||
175 | bb_info_msg("Sending renew..."); | 162 | bb_info_msg("Sending renew..."); |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index a529e1b58..d6e90cd03 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -48,7 +48,7 @@ static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadc | |||
48 | 48 | ||
49 | if (force_broadcast | 49 | if (force_broadcast |
50 | || (dhcp_pkt->flags & htons(BROADCAST_FLAG)) | 50 | || (dhcp_pkt->flags & htons(BROADCAST_FLAG)) |
51 | || !dhcp_pkt->ciaddr | 51 | || dhcp_pkt->ciaddr == 0 |
52 | ) { | 52 | ) { |
53 | log1("Broadcasting packet to client"); | 53 | log1("Broadcasting packet to client"); |
54 | ciaddr = INADDR_BROADCAST; | 54 | ciaddr = INADDR_BROADCAST; |
@@ -466,16 +466,101 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
466 | 466 | ||
467 | case DHCPREQUEST: | 467 | case DHCPREQUEST: |
468 | log1("Received REQUEST"); | 468 | log1("Received REQUEST"); |
469 | 469 | /* RFC 2131: | |
470 | /* RFC 2131: "The REQUESTED_IP option MUST be set | 470 | |
471 | * to the value of 'yiaddr' in the DHCPOFFER message | 471 | o DHCPREQUEST generated during SELECTING state: |
472 | * from the server." */ | 472 | |
473 | Client inserts the address of the selected server in 'server | ||
474 | identifier', 'ciaddr' MUST be zero, 'requested IP address' MUST be | ||
475 | filled in with the yiaddr value from the chosen DHCPOFFER. | ||
476 | |||
477 | Note that the client may choose to collect several DHCPOFFER | ||
478 | messages and select the "best" offer. The client indicates its | ||
479 | selection by identifying the offering server in the DHCPREQUEST | ||
480 | message. If the client receives no acceptable offers, the client | ||
481 | may choose to try another DHCPDISCOVER message. Therefore, the | ||
482 | servers may not receive a specific DHCPREQUEST from which they can | ||
483 | decide whether or not the client has accepted the offer. | ||
484 | |||
485 | o DHCPREQUEST generated during INIT-REBOOT state: | ||
486 | |||
487 | 'server identifier' MUST NOT be filled in, 'requested IP address' | ||
488 | option MUST be filled in with client's notion of its previously | ||
489 | assigned address. 'ciaddr' MUST be zero. The client is seeking to | ||
490 | verify a previously allocated, cached configuration. Server SHOULD | ||
491 | send a DHCPNAK message to the client if the 'requested IP address' | ||
492 | is incorrect, or is on the wrong network. | ||
493 | |||
494 | Determining whether a client in the INIT-REBOOT state is on the | ||
495 | correct network is done by examining the contents of 'giaddr', the | ||
496 | 'requested IP address' option, and a database lookup. If the DHCP | ||
497 | server detects that the client is on the wrong net (i.e., the | ||
498 | result of applying the local subnet mask or remote subnet mask (if | ||
499 | 'giaddr' is not zero) to 'requested IP address' option value | ||
500 | doesn't match reality), then the server SHOULD send a DHCPNAK | ||
501 | message to the client. | ||
502 | |||
503 | If the network is correct, then the DHCP server should check if | ||
504 | the client's notion of its IP address is correct. If not, then the | ||
505 | server SHOULD send a DHCPNAK message to the client. If the DHCP | ||
506 | server has no record of this client, then it MUST remain silent, | ||
507 | and MAY output a warning to the network administrator. This | ||
508 | behavior is necessary for peaceful coexistence of non- | ||
509 | communicating DHCP servers on the same wire. | ||
510 | |||
511 | If 'giaddr' is 0x0 in the DHCPREQUEST message, the client is on | ||
512 | the same subnet as the server. The server MUST broadcast the | ||
513 | DHCPNAK message to the 0xffffffff broadcast address because the | ||
514 | client may not have a correct network address or subnet mask, and | ||
515 | the client may not be answering ARP requests. | ||
516 | |||
517 | If 'giaddr' is set in the DHCPREQUEST message, the client is on a | ||
518 | different subnet. The server MUST set the broadcast bit in the | ||
519 | DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the | ||
520 | client, because the client may not have a correct network address | ||
521 | or subnet mask, and the client may not be answering ARP requests. | ||
522 | |||
523 | o DHCPREQUEST generated during RENEWING state: | ||
524 | |||
525 | 'server identifier' MUST NOT be filled in, 'requested IP address' | ||
526 | option MUST NOT be filled in, 'ciaddr' MUST be filled in with | ||
527 | client's IP address. In this situation, the client is completely | ||
528 | configured, and is trying to extend its lease. This message will | ||
529 | be unicast, so no relay agents will be involved in its | ||
530 | transmission. Because 'giaddr' is therefore not filled in, the | ||
531 | DHCP server will trust the value in 'ciaddr', and use it when | ||
532 | replying to the client. | ||
533 | |||
534 | A client MAY choose to renew or extend its lease prior to T1. The | ||
535 | server may choose not to extend the lease (as a policy decision by | ||
536 | the network administrator), but should return a DHCPACK message | ||
537 | regardless. | ||
538 | |||
539 | o DHCPREQUEST generated during REBINDING state: | ||
540 | |||
541 | 'server identifier' MUST NOT be filled in, 'requested IP address' | ||
542 | option MUST NOT be filled in, 'ciaddr' MUST be filled in with | ||
543 | client's IP address. In this situation, the client is completely | ||
544 | configured, and is trying to extend its lease. This message MUST | ||
545 | be broadcast to the 0xffffffff IP broadcast address. The DHCP | ||
546 | server SHOULD check 'ciaddr' for correctness before replying to | ||
547 | the DHCPREQUEST. | ||
548 | |||
549 | The DHCPREQUEST from a REBINDING client is intended to accommodate | ||
550 | sites that have multiple DHCP servers and a mechanism for | ||
551 | maintaining consistency among leases managed by multiple servers. | ||
552 | A DHCP server MAY extend a client's lease only if it has local | ||
553 | administrative authority to do so. | ||
554 | */ | ||
473 | if (!requested_opt) { | 555 | if (!requested_opt) { |
474 | log1("no requested IP, ignoring"); | 556 | requested_nip = packet.ciaddr; |
475 | break; | 557 | if (requested_nip == 0) { |
558 | log1("no requested IP and no ciaddr, ignoring"); | ||
559 | break; | ||
560 | } | ||
476 | } | 561 | } |
477 | if (lease && requested_nip == lease->lease_nip) { | 562 | if (lease && requested_nip == lease->lease_nip) { |
478 | /* client requests IP which matches the lease. | 563 | /* client requested or configured IP matches the lease. |
479 | * ACK it, and bump lease expiration time. */ | 564 | * ACK it, and bump lease expiration time. */ |
480 | send_ACK(&packet, lease->lease_nip); | 565 | send_ACK(&packet, lease->lease_nip); |
481 | break; | 566 | break; |