aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/udhcp/Config.src7
-rw-r--r--networking/udhcp/common.c10
-rw-r--r--networking/udhcp/common.h14
-rw-r--r--networking/udhcp/dhcpc.c2
-rw-r--r--networking/udhcp/dhcpd.c49
-rw-r--r--networking/udhcp/packet.c9
6 files changed, 76 insertions, 15 deletions
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 7ba7f48fc..d9c501c18 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -10,6 +10,13 @@ config UDHCPD
10 udhcpd is a DHCP server geared primarily toward embedded systems, 10 udhcpd is a DHCP server geared primarily toward embedded systems,
11 while striving to be fully functional and RFC compliant. 11 while striving to be fully functional and RFC compliant.
12 12
13config FEATURE_UDHCPD_BOOTP
14 bool "Answer to BOOTP requests as well"
15 default y
16 depends on UDHCPD
17 help
18 Support old BOOTP protocol too.
19
13config FEATURE_UDHCPD_BASE_IP_ON_MAC 20config FEATURE_UDHCPD_BASE_IP_ON_MAC
14 bool "Select IP address based on client MAC" 21 bool "Select IP address based on client MAC"
15 default n 22 default n
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index ae818db05..ad580f38d 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -252,6 +252,14 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc
252 /* option bytes: [code][len][data1][data2]..[dataLEN] */ 252 /* option bytes: [code][len][data1][data2]..[dataLEN] */
253 while (1) { 253 while (1) {
254 if (scan_state->rem <= 0) { 254 if (scan_state->rem <= 0) {
255 if (ENABLE_FEATURE_UDHCPD_BOOTP && scan_state->rem == 0) {
256 /* DHCP requires END option to be present.
257 * We are here if packet fails this condition
258 * (options[] are zero-padded to the end).
259 * Assume BOOTP packet without further checks.
260 */
261 break; /* return NULL */
262 }
255 complain: 263 complain:
256 bb_simple_error_msg("bad packet, malformed option field"); 264 bb_simple_error_msg("bad packet, malformed option field");
257 return NULL; 265 return NULL;
@@ -278,7 +286,7 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc
278 scan_state->rem = sizeof(packet->sname); 286 scan_state->rem = sizeof(packet->sname);
279 continue; 287 continue;
280 } 288 }
281 break; 289 break; /* return NULL */
282 } 290 }
283 291
284 if (scan_state->rem <= OPT_LEN) /* [len] byte exists? */ 292 if (scan_state->rem <= OPT_LEN) /* [len] byte exists? */
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 49a0b593d..3ef371a7c 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -20,8 +20,11 @@ extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */
20 20
21/*** DHCP packet ***/ 21/*** DHCP packet ***/
22 22
23#define RFC1048_MAGIC 0x63825363
24/* RFC 1048 still uses BOOTP's small buffer (4 byte cookie + 60 the rest) */
25#define RFC1048_OPTIONS_BUFSIZE 60
26
23/* DHCP protocol. See RFC 2131 */ 27/* DHCP protocol. See RFC 2131 */
24#define DHCP_MAGIC 0x63825363
25#define DHCP_OPTIONS_BUFSIZE 308 28#define DHCP_OPTIONS_BUFSIZE 308
26#define BOOTREQUEST 1 29#define BOOTREQUEST 1
27#define BOOTREPLY 2 30#define BOOTREPLY 2
@@ -57,8 +60,10 @@ struct dhcp_packet {
57 * such as 'unix' or 'gateway'; this means 'boot the named program 60 * such as 'unix' or 'gateway'; this means 'boot the named program
58 * configured for my machine'" 61 * configured for my machine'"
59 */ 62 */
60 /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows */ 63 /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows. */
61 uint32_t cookie; /* DHCP magic bytes: 99,130,83,99 decimal */ 64 /* RFC 1048 defined this cookie value and options 0-12 and 255. */
65 /* DHCP extended it and required option 255 (END) to be always present. */
66 uint32_t cookie; /* RFC 1048 magic bytes: 99,130,83,99 decimal */
62 uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; 67 uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS];
63}; 68};
64#define DHCP_PKT_SNAME_LEN 64 69#define DHCP_PKT_SNAME_LEN 64
@@ -200,6 +205,9 @@ struct dhcp_scan_state {
200#define SNAME_FIELD 2 205#define SNAME_FIELD 2
201 206
202/* DHCP_MESSAGE_TYPE values */ 207/* DHCP_MESSAGE_TYPE values */
208#if ENABLE_FEATURE_UDHCPD_BOOTP
209#define MSGTYPE_BOOTP 0 /* there was no TYPE option in client's packet, assuming BOOTP */
210#endif
203#define DHCPDISCOVER 1 /* client -> server */ 211#define DHCPDISCOVER 1 /* client -> server */
204#define DHCPOFFER 2 /* client <- server */ 212#define DHCPOFFER 2 /* client <- server */
205#define DHCPREQUEST 3 /* client -> server */ 213#define DHCPREQUEST 3 /* client -> server */
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index c757fb37c..200a2fb8a 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -971,7 +971,7 @@ static NOINLINE int d4_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
971 } 971 }
972 skip_udp_sum_check: 972 skip_udp_sum_check:
973 973
974 if (packet.data.cookie != htonl(DHCP_MAGIC)) { 974 if (packet.data.cookie != htonl(RFC1048_MAGIC)) {
975 log1s("packet with bad magic, ignoring"); 975 log1s("packet with bad magic, ignoring");
976 return -2; 976 return -2;
977 } 977 }
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 66750e2e6..2904119e5 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -649,7 +649,8 @@ static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacke
649 packet->flags = oldpacket->flags; 649 packet->flags = oldpacket->flags;
650 packet->gateway_nip = oldpacket->gateway_nip; 650 packet->gateway_nip = oldpacket->gateway_nip;
651 packet->ciaddr = oldpacket->ciaddr; 651 packet->ciaddr = oldpacket->ciaddr;
652 udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_data.server_nip); 652 IF_FEATURE_UDHCPD_BOOTP(if (type != MSGTYPE_BOOTP))
653 udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_data.server_nip);
653} 654}
654 655
655/* Fill options field, siaddr_nip, and sname and boot_file fields. 656/* Fill options field, siaddr_nip, and sname and boot_file fields.
@@ -725,7 +726,12 @@ static uint32_t select_lease_time(struct dhcp_packet *packet)
725 726
726/* We got a DHCP DISCOVER. Send an OFFER. */ 727/* We got a DHCP DISCOVER. Send an OFFER. */
727/* NOINLINE: limit stack usage in caller */ 728/* NOINLINE: limit stack usage in caller */
728static NOINLINE void send_offer(struct dhcp_packet *oldpacket, 729#if !ENABLE_FEATURE_UDHCPD_BOOTP
730#define send_offer(is_dhcp_client, ...) \
731 send_offer(__VA_ARGS__)
732#endif
733static NOINLINE void send_offer(void *is_dhcp_client,
734 struct dhcp_packet *oldpacket,
729 uint32_t static_lease_nip, 735 uint32_t static_lease_nip,
730 struct dyn_lease *lease, 736 struct dyn_lease *lease,
731 uint32_t requested_nip, 737 uint32_t requested_nip,
@@ -734,7 +740,12 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
734 struct dhcp_packet packet; 740 struct dhcp_packet packet;
735 uint32_t lease_time_sec; 741 uint32_t lease_time_sec;
736 742
743#if ENABLE_FEATURE_UDHCPD_BOOTP
744 init_packet(&packet, oldpacket, is_dhcp_client ? DHCPOFFER : MSGTYPE_BOOTP);
745#else
746 enum { is_dhcp_client = 1 };
737 init_packet(&packet, oldpacket, DHCPOFFER); 747 init_packet(&packet, oldpacket, DHCPOFFER);
748#endif
738 749
739 /* If it is a static lease, use its IP */ 750 /* If it is a static lease, use its IP */
740 packet.yiaddr = static_lease_nip; 751 packet.yiaddr = static_lease_nip;
@@ -784,9 +795,16 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
784 } 795 }
785 } 796 }
786 797
787 lease_time_sec = select_lease_time(oldpacket); 798 if (is_dhcp_client) {
788 udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); 799 lease_time_sec = select_lease_time(oldpacket);
800 udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
801 }
802/* TODO: pass "is_dhcp_client" to add_server_options(), avoid adding confusing options to BOOTP clients? */
789 add_server_options(&packet); 803 add_server_options(&packet);
804 if (!is_dhcp_client && udhcp_end_option(packet.options) >= RFC1048_OPTIONS_BUFSIZE) {
805 bb_simple_error_msg("BOOTP reply too large, not sending");
806 return;
807 }
790 808
791 /* send_packet emits error message itself if it detects failure */ 809 /* send_packet emits error message itself if it detects failure */
792 send_packet_verbose(&packet, "sending OFFER to %s"); 810 send_packet_verbose(&packet, "sending OFFER to %s");
@@ -1050,8 +1068,12 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
1050 continue; 1068 continue;
1051 } 1069 }
1052 msg_type = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); 1070 msg_type = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
1053 if (!msg_type || msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE) { 1071 if (
1054 bb_info_msg("no or bad message type option%s", ", ignoring packet"); 1072 IF_FEATURE_UDHCPD_BOOTP( msg_type && )
1073 IF_NOT_FEATURE_UDHCPD_BOOTP( !msg_type || )
1074 (msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE)
1075 ) {
1076 bb_info_msg("bad message type option%s", ", ignoring packet");
1055 continue; 1077 continue;
1056 } 1078 }
1057 1079
@@ -1086,12 +1108,25 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
1086 move_from_unaligned32(requested_nip, requested_ip_opt); 1108 move_from_unaligned32(requested_nip, requested_ip_opt);
1087 } 1109 }
1088 1110
1111#if ENABLE_FEATURE_UDHCPD_BOOTP
1112 /* Handle old BOOTP clients */
1113 if (!msg_type) {
1114 log1("received %s", "BOOTP BOOTREQUEST");
1115 if (!static_lease_nip) {
1116 bb_info_msg("no static lease for BOOTP client%s", ", ignoring packet");
1117 continue;
1118 }
1119 send_offer(msg_type, &packet, static_lease_nip, lease, requested_nip, arpping_ms);
1120 continue;
1121 }
1122#endif
1123
1089 switch (msg_type[0]) { 1124 switch (msg_type[0]) {
1090 1125
1091 case DHCPDISCOVER: 1126 case DHCPDISCOVER:
1092 log1("received %s", "DISCOVER"); 1127 log1("received %s", "DISCOVER");
1093 1128
1094 send_offer(&packet, static_lease_nip, lease, requested_nip, arpping_ms); 1129 send_offer(msg_type, &packet, static_lease_nip, lease, requested_nip, arpping_ms);
1095 break; 1130 break;
1096 1131
1097 case DHCPREQUEST: 1132 case DHCPREQUEST:
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index 529978189..f9dc11d01 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -18,6 +18,8 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type)
18 memset(packet, 0, sizeof(*packet)); 18 memset(packet, 0, sizeof(*packet));
19 packet->op = BOOTREQUEST; /* if client to a server */ 19 packet->op = BOOTREQUEST; /* if client to a server */
20 switch (type) { 20 switch (type) {
21 IF_FEATURE_UDHCPD_BOOTP(case MSGTYPE_BOOTP:)
22 /* reply to a BOOTP (not DHCP) client */
21 case DHCPOFFER: 23 case DHCPOFFER:
22 case DHCPACK: 24 case DHCPACK:
23 case DHCPNAK: 25 case DHCPNAK:
@@ -25,10 +27,11 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type)
25 } 27 }
26 packet->htype = 1; /* ethernet */ 28 packet->htype = 1; /* ethernet */
27 packet->hlen = 6; 29 packet->hlen = 6;
28 packet->cookie = htonl(DHCP_MAGIC); 30 packet->cookie = htonl(RFC1048_MAGIC);
29 if (DHCP_END != 0) 31 if (DHCP_END != 0)
30 packet->options[0] = DHCP_END; 32 packet->options[0] = DHCP_END;
31 udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type); 33 IF_FEATURE_UDHCPD_BOOTP(if (type != MSGTYPE_BOOTP))
34 udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type);
32} 35}
33#endif 36#endif
34 37
@@ -90,7 +93,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd)
90 } 93 }
91 94
92 if (bytes < offsetof(struct dhcp_packet, options) 95 if (bytes < offsetof(struct dhcp_packet, options)
93 || packet->cookie != htonl(DHCP_MAGIC) 96 || packet->cookie != htonl(RFC1048_MAGIC)
94 ) { 97 ) {
95 bb_simple_info_msg("packet with bad magic, ignoring"); 98 bb_simple_info_msg("packet with bad magic, ignoring");
96 return -2; 99 return -2;