[git commit] udhcpc: ignore zero-length DHCP options

Denys Vlasenko vda.linux at googlemail.com
Tue Mar 16 10:40:19 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=1c461df70ab357dc9e1e064540731c58e7859a45
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

Discovered that the DHCP server on a TrendNet router (unknown model)
provides a zero-length option 12 (Host Name) in the DHCP ACK message. This
has the effect of causing udhcpc to drop the rest of the options, including
option 51 (IP Address Lease Time), 3 (Router), and 6 (Domain Name Server),
most importantly leaving the OpenWrt device with no default gateway.

The TrendNet behavior violates RFC 2132, which in Section 3.14 declares that
option 12 has a minimum length of 1 octet. It is perhaps not a cosmic coincidence
that I found this behavior on Pi Day.

This patch allows zero length options without bailing out, by simply skipping them.

function                                             old     new   delta
udhcp_scan_options                                   183     172     -11

Signed-off-by: Russell Senior <russell at personaltelco.net>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/udhcp/common.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 4bc719001..99ecb7aa6 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -273,17 +273,27 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc
 			break;
 		}
 
-		if (scan_state->rem <= OPT_LEN)
-			goto complain; /* complain and return NULL */
-		len = 2 + scan_state->optionptr[OPT_LEN];
+		if (scan_state->rem <= OPT_LEN) /* [len] byte exists? */
+			goto complain; /* no, complain and return NULL */
+		len = scan_state->optionptr[OPT_LEN];
+		/* Skip options with zero length.
+		 * Users report that DHCP server on a TrendNet router (unknown model)
+		 * provides a zero-length option 12 (Host Name)
+		 * (this violates RFC 2132 section 3.14).
+		 */
+		if (len == 0) {
+			scan_state->rem -= OPT_LEN;
+			scan_state->optionptr += OPT_LEN;
+			continue;
+		}
+		len += OPT_LEN;
 		scan_state->rem -= len;
-		/* So far no valid option with length 0 known. */
-		if (scan_state->rem < 0 || scan_state->optionptr[OPT_LEN] == 0)
-			goto complain; /* complain and return NULL */
+		if (scan_state->rem < 0) /* option is longer than options field? */
+			goto complain; /* yes, complain and return NULL */
 
 		if (scan_state->optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) {
-			if (len >= 3)
-				scan_state->overload |= scan_state->optionptr[OPT_DATA];
+			/* len is known to be >= 3 now, [data] byte exists */
+			scan_state->overload |= scan_state->optionptr[OPT_DATA];
 		} else {
 			uint8_t *return_ptr = scan_state->optionptr;
 			scan_state->optionptr += len;


More information about the busybox-cvs mailing list