aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/clientpacket.c22
-rw-r--r--networking/udhcp/common.h32
-rw-r--r--networking/udhcp/dhcpc.c23
-rw-r--r--networking/udhcp/options.h18
-rw-r--r--networking/udhcp/packet.c8
-rw-r--r--networking/udhcp/serverpacket.c2
6 files changed, 64 insertions, 41 deletions
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c
index 1ab17321d..3f9522ff8 100644
--- a/networking/udhcp/clientpacket.c
+++ b/networking/udhcp/clientpacket.c
@@ -78,6 +78,23 @@ static void add_param_req_option(struct dhcpMessage *packet)
78 } 78 }
79} 79}
80 80
81/* RFC 2131
82 * 4.4.4 Use of broadcast and unicast
83 *
84 * The DHCP client broadcasts DHCPDISCOVER, DHCPREQUEST and DHCPINFORM
85 * messages, unless the client knows the address of a DHCP server.
86 * The client unicasts DHCPRELEASE messages to the server. Because
87 * the client is declining the use of the IP address supplied by the server,
88 * the client broadcasts DHCPDECLINE messages.
89 *
90 * When the DHCP client knows the address of a DHCP server, in either
91 * INIT or REBOOTING state, the client may use that address
92 * in the DHCPDISCOVER or DHCPREQUEST rather than the IP broadcast address.
93 * The client may also use unicast to send DHCPINFORM messages
94 * to a known DHCP server. If the client receives no response to DHCP
95 * messages sent to the IP address of a known DHCP server, the DHCP
96 * client reverts to using the IP broadcast address.
97 */
81 98
82static int raw_bcast_from_client_config_ifindex(struct dhcpMessage *packet) 99static int raw_bcast_from_client_config_ifindex(struct dhcpMessage *packet)
83{ 100{
@@ -90,7 +107,6 @@ static int raw_bcast_from_client_config_ifindex(struct dhcpMessage *packet)
90 107
91#if ENABLE_FEATURE_UDHCPC_ARPING 108#if ENABLE_FEATURE_UDHCPC_ARPING
92/* Broadcast a DHCP decline message */ 109/* Broadcast a DHCP decline message */
93//FIXME: maybe it should be unicast?
94int FAST_FUNC send_decline(uint32_t xid, uint32_t server, uint32_t requested) 110int FAST_FUNC send_decline(uint32_t xid, uint32_t server, uint32_t requested)
95{ 111{
96 struct dhcpMessage packet; 112 struct dhcpMessage packet;
@@ -128,7 +144,9 @@ int FAST_FUNC send_discover(uint32_t xid, uint32_t requested)
128 144
129 145
130/* Broadcasts a DHCP request message */ 146/* Broadcasts a DHCP request message */
131//FIXME: maybe it should be unicast? 147/* RFC 2131 3.1 paragraph 3:
148 * "The client _broadcasts_ a DHCPREQUEST message..."
149 */
132int FAST_FUNC send_select(uint32_t xid, uint32_t server, uint32_t requested) 150int FAST_FUNC send_select(uint32_t xid, uint32_t server, uint32_t requested)
133{ 151{
134 struct dhcpMessage packet; 152 struct dhcpMessage packet;
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 68fa65cf5..66a0b0d8b 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -27,21 +27,23 @@ extern const uint8_t MAC_BCAST_ADDR[6]; /* six all-ones */
27#define DHCP_OPTIONS_BUFSIZE 308 27#define DHCP_OPTIONS_BUFSIZE 308
28 28
29struct dhcpMessage { 29struct dhcpMessage {
30 uint8_t op; 30 uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */
31 uint8_t htype; 31 uint8_t htype; /* hardware address type. 1 = 10mb ethernet */
32 uint8_t hlen; 32 uint8_t hlen; /* hardware address length */
33 uint8_t hops; 33 uint8_t hops; /* used by relay agents only */
34 uint32_t xid; 34 uint32_t xid; /* unique id */
35 uint16_t secs; 35 uint16_t secs; /* elapsed since client began acquisition/renewal */
36 uint16_t flags; 36 uint16_t flags; /* only one flag so far: */
37 uint32_t ciaddr; 37#define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */
38 uint32_t yiaddr; 38 uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */
39 uint32_t siaddr; 39 uint32_t yiaddr; /* 'your' (client) IP address */
40 uint32_t giaddr; 40 uint32_t siaddr; /* IP address of next server to use in bootstrap,
41 uint8_t chaddr[16]; 41 * returned in DHCPOFFER, DHCPACK by server */
42 uint8_t sname[64]; 42 uint32_t giaddr; /* relay agent IP address */
43 uint8_t file[128]; 43 uint8_t chaddr[16];/* link-layer client hardware address (MAC) */
44 uint32_t cookie; 44 uint8_t sname[64]; /* server host name (ASCIZ) */
45 uint8_t file[128]; /* boot file name (ASCIZ) */
46 uint32_t cookie; /* fixed first four option bytes (99,130,83,99 dec) */
45 uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; 47 uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS];
46} PACKED; 48} PACKED;
47 49
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 8985cc705..2d48980d9 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -452,7 +452,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
452 } 452 }
453 453
454 /* select() didn't timeout, something did happen. */ 454 /* select() didn't timeout, something did happen. */
455 /* Is is a packet? */ 455 /* Is it a packet? */
456 if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) { 456 if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
457 int len; 457 int len;
458 /* A packet is ready, read it */ 458 /* A packet is ready, read it */
@@ -474,7 +474,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
474 continue; 474 continue;
475 475
476 if (packet.xid != xid) { 476 if (packet.xid != xid) {
477 DEBUG("Ignoring XID %x (our xid is %x)", 477 DEBUG("Ignoring xid %x (our xid is %x)",
478 (unsigned)packet.xid, (unsigned)xid); 478 (unsigned)packet.xid, (unsigned)xid);
479 continue; 479 continue;
480 } 480 }
@@ -524,17 +524,24 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
524 bb_error_msg("no lease time with ACK, using 1 hour lease"); 524 bb_error_msg("no lease time with ACK, using 1 hour lease");
525 lease_seconds = 60 * 60; 525 lease_seconds = 60 * 60;
526 } else { 526 } else {
527 /* can be misaligned, thus memcpy */ 527 /* it IS unaligned sometimes, don't "optimize" */
528 memcpy(&lease_seconds, temp, 4); 528 lease_seconds = get_unaligned_u32p((uint32_t*)temp);
529 lease_seconds = ntohl(lease_seconds); 529 lease_seconds = ntohl(lease_seconds);
530 lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */ 530 lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */
531 if (lease_seconds < 10) /* and not too small */ 531 if (lease_seconds < 10) /* and not too small */
532 lease_seconds = 10; 532 lease_seconds = 10;
533 } 533 }
534//FIXME: why do we check ARP only after we've got DHCPACK?
535//Shouldn't we do it immediately after DHCPOFFER?
536#if ENABLE_FEATURE_UDHCPC_ARPING 534#if ENABLE_FEATURE_UDHCPC_ARPING
537 if (opt & OPT_a) { 535 if (opt & OPT_a) {
536/* RFC 2131 3.1 paragraph 5:
537 * "The client receives the DHCPACK message with configuration
538 * parameters. The client SHOULD perform a final check on the
539 * parameters (e.g., ARP for allocated network address), and notes
540 * the duration of the lease specified in the DHCPACK message. At this
541 * point, the client is configured. If the client detects that the
542 * address is already in use (e.g., through the use of ARP),
543 * the client MUST send a DHCPDECLINE message to the server and restarts
544 * the configuration process..." */
538 if (!arpping(packet.yiaddr, 545 if (!arpping(packet.yiaddr,
539 (uint32_t) 0, 546 (uint32_t) 0,
540 client_config.arp, 547 client_config.arp,
@@ -542,8 +549,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
542 ) { 549 ) {
543 bb_info_msg("offered address is in use " 550 bb_info_msg("offered address is in use "
544 "(got ARP reply), declining"); 551 "(got ARP reply), declining");
545//NB: not clear whether it should be unicast or bcast.
546//Currently it is a bcast. Why?
547 send_decline(xid, server_addr, packet.yiaddr); 552 send_decline(xid, server_addr, packet.yiaddr);
548 553
549 if (state != REQUESTING) 554 if (state != REQUESTING)
@@ -568,7 +573,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
568 } 573 }
569 requested_ip = packet.yiaddr; 574 requested_ip = packet.yiaddr;
570 udhcp_run_script(&packet, 575 udhcp_run_script(&packet,
571 ((state == RENEWING || state == REBINDING) ? "renew" : "bound")); 576 ((state == RENEWING || state == REBINDING) ? "renew" : "bound"));
572 577
573 state = BOUND; 578 state = BOUND;
574 change_listen_mode(LISTEN_NONE); 579 change_listen_mode(LISTEN_NONE);
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h
index 70b8704d2..fcf1c9a6d 100644
--- a/networking/udhcp/options.h
+++ b/networking/udhcp/options.h
@@ -78,16 +78,14 @@ enum {
78#define ETH_10MB 1 78#define ETH_10MB 1
79#define ETH_10MB_LEN 6 79#define ETH_10MB_LEN 6
80 80
81#define DHCPDISCOVER 1 81#define DHCPDISCOVER 1 /* client -> server */
82#define DHCPOFFER 2 82#define DHCPOFFER 2 /* client <- server */
83#define DHCPREQUEST 3 83#define DHCPREQUEST 3 /* client -> server */
84#define DHCPDECLINE 4 84#define DHCPDECLINE 4 /* client -> server */
85#define DHCPACK 5 85#define DHCPACK 5 /* client <- server */
86#define DHCPNAK 6 86#define DHCPNAK 6 /* client <- server */
87#define DHCPRELEASE 7 87#define DHCPRELEASE 7 /* client -> server */
88#define DHCPINFORM 8 88#define DHCPINFORM 8 /* client -> server */
89
90#define BROADCAST_FLAG 0x8000
91 89
92#define OPTION_FIELD 0 90#define OPTION_FIELD 0
93#define FILE_FIELD 1 91#define FILE_FIELD 1
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 4eedbb53a..1a6f7e6a0 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -18,12 +18,12 @@
18void FAST_FUNC udhcp_init_header(struct dhcpMessage *packet, char type) 18void FAST_FUNC udhcp_init_header(struct dhcpMessage *packet, char type)
19{ 19{
20 memset(packet, 0, sizeof(struct dhcpMessage)); 20 memset(packet, 0, sizeof(struct dhcpMessage));
21 packet->op = BOOTREQUEST; 21 packet->op = BOOTREQUEST; /* if client to a server */
22 switch (type) { 22 switch (type) {
23 case DHCPOFFER: 23 case DHCPOFFER:
24 case DHCPACK: 24 case DHCPACK:
25 case DHCPNAK: 25 case DHCPNAK:
26 packet->op = BOOTREPLY; 26 packet->op = BOOTREPLY; /* if server to client */
27 } 27 }
28 packet->htype = ETH_10MB; 28 packet->htype = ETH_10MB;
29 packet->hlen = ETH_10MB_LEN; 29 packet->hlen = ETH_10MB_LEN;
@@ -65,7 +65,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcpMessage *packet, int fd)
65 if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i]) 65 if (vendor[OPT_LEN - 2] == (uint8_t)strlen(broken_vendors[i])
66 && !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2]) 66 && !strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - 2])
67 ) { 67 ) {
68 DEBUG("broken client (%s), forcing broadcast", 68 DEBUG("broken client (%s), forcing broadcast replies",
69 broken_vendors[i]); 69 broken_vendors[i]);
70 packet->flags |= htons(BROADCAST_FLAG); 70 packet->flags |= htons(BROADCAST_FLAG);
71 } 71 }
@@ -74,7 +74,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcpMessage *packet, int fd)
74 if (vendor[OPT_LEN - 2] == (uint8_t)(sizeof("MSFT 98")-1) 74 if (vendor[OPT_LEN - 2] == (uint8_t)(sizeof("MSFT 98")-1)
75 && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0 75 && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0
76 ) { 76 ) {
77 DEBUG("broken client (%s), forcing broadcast", "MSFT 98"); 77 DEBUG("broken client (%s), forcing broadcast replies", "MSFT 98");
78 packet->flags |= htons(BROADCAST_FLAG); 78 packet->flags |= htons(BROADCAST_FLAG);
79 } 79 }
80#endif 80#endif
diff --git a/networking/udhcp/serverpacket.c b/networking/udhcp/serverpacket.c
index 5b1c61517..dcc234c7d 100644
--- a/networking/udhcp/serverpacket.c
+++ b/networking/udhcp/serverpacket.c
@@ -50,7 +50,7 @@ static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcas
50 DEBUG("unicasting packet to client ciaddr"); 50 DEBUG("unicasting packet to client ciaddr");
51 ciaddr = payload->ciaddr; 51 ciaddr = payload->ciaddr;
52 chaddr = payload->chaddr; 52 chaddr = payload->chaddr;
53 } else if (ntohs(payload->flags) & BROADCAST_FLAG) { 53 } else if (payload->flags & htons(BROADCAST_FLAG)) {
54 DEBUG("broadcasting packet to client (requested)"); 54 DEBUG("broadcasting packet to client (requested)");
55 ciaddr = INADDR_BROADCAST; 55 ciaddr = INADDR_BROADCAST;
56 chaddr = MAC_BCAST_ADDR; 56 chaddr = MAC_BCAST_ADDR;