diff options
-rw-r--r-- | networking/udhcp/clientpacket.c | 22 | ||||
-rw-r--r-- | networking/udhcp/common.h | 32 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 23 | ||||
-rw-r--r-- | networking/udhcp/options.h | 18 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 8 | ||||
-rw-r--r-- | networking/udhcp/serverpacket.c | 2 |
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 | ||
82 | static int raw_bcast_from_client_config_ifindex(struct dhcpMessage *packet) | 99 | static 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? | ||
94 | int FAST_FUNC send_decline(uint32_t xid, uint32_t server, uint32_t requested) | 110 | int 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 | */ | ||
132 | int FAST_FUNC send_select(uint32_t xid, uint32_t server, uint32_t requested) | 150 | int 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 | ||
29 | struct dhcpMessage { | 29 | struct 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 @@ | |||
18 | void FAST_FUNC udhcp_init_header(struct dhcpMessage *packet, char type) | 18 | void 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; |