From 456a4d9d3fdc38ff977f72c2e784d3eebca74061 Mon Sep 17 00:00:00 2001 From: DrDoof <8052722+DrDoof@users.noreply.github.com> Date: Fri, 25 Sep 2026 06:14:39 +0200 Subject: [PATCH] dhcp: skip IP and time options that are shorter than four bytes ip_opt() copies four bytes whatever the option length says, so a subnet, router, DNS, server id or broadcast option shorter than four bytes stores the start of the next option as the address. long_opt() does not look at the length at all and always moves on by six bytes, so a lease, renewal or rebind option of another length puts the parser out of step for the rest of the packet. Both now read the length. An address or time shorter than four bytes is skipped, a longer one is taken from its first four bytes and stepped over whole, and a skipped time leaves the previous value alone. Found in the code, not on the wire; no server here sends such options. BANK3 is 47 bytes smaller on the KP_9000_6XHML_X2. --- dhcp.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/dhcp.c b/dhcp.c index 2fbce36c..96961ea5 100644 --- a/dhcp.c +++ b/dhcp.c @@ -232,19 +232,21 @@ void ip_opt(__xdata uint8_t * ip) { dhcp_state.opt_ptr++; uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++]; - *ip++ = DHCP_OPT[dhcp_state.opt_ptr++]; - *ip++ = DHCP_OPT[dhcp_state.opt_ptr++]; - *ip++ = DHCP_OPT[dhcp_state.opt_ptr++]; - *ip++ = DHCP_OPT[dhcp_state.opt_ptr++]; + if (len >= 4) + memcpy(ip, &DHCP_OPT[dhcp_state.opt_ptr], 4); // There may be more than one IP option, such as 2 DNS servers advertised - dhcp_state.opt_ptr += len - 4; + dhcp_state.opt_ptr += len; } -void long_opt(void) +uint8_t long_opt(void) { dhcp_state.opt_ptr++; - dhcp_state.opt_ptr++; + uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++]; + if (len < 4) { + dhcp_state.opt_ptr += len; + return 0; + } long_value = DHCP_OPT[dhcp_state.opt_ptr++]; long_value <<= 8; long_value |= DHCP_OPT[dhcp_state.opt_ptr++]; @@ -252,6 +254,8 @@ void long_opt(void) long_value |= DHCP_OPT[dhcp_state.opt_ptr++]; long_value <<= 8; long_value |= DHCP_OPT[dhcp_state.opt_ptr++]; + dhcp_state.opt_ptr += len - 4; + return 1; } @@ -275,16 +279,16 @@ void parse_opts(void) ip_opt(&dhcp_state.broadcast[0]); break; case DHCP_LEASE: - long_opt(); - dhcp_state.lease = long_value; + if (long_opt()) + dhcp_state.lease = long_value; break; case DHCP_REBIND: - long_opt(); - dhcp_state.rebind = long_value; + if (long_opt()) + dhcp_state.rebind = long_value; break; case DHCP_RENEWAL: - long_opt(); - dhcp_state.renewal = long_value; + if (long_opt()) + dhcp_state.renewal = long_value; break; case DHCP_END: break;