mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
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.
This commit is contained in:
1 parent
770926abd1
commit
456a4d9d3f
1 file changed
+17
-13
@@ -232,19 +232,21 @@ void ip_opt(__xdata uint8_t * ip)
|
|||||||
{
|
{
|
||||||
dhcp_state.opt_ptr++;
|
dhcp_state.opt_ptr++;
|
||||||
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
|
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
if (len >= 4)
|
||||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
memcpy(ip, &DHCP_OPT[dhcp_state.opt_ptr], 4);
|
||||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
|
||||||
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
|
|
||||||
// There may be more than one IP option, such as 2 DNS servers advertised
|
// 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++;
|
||||||
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 = DHCP_OPT[dhcp_state.opt_ptr++];
|
||||||
long_value <<= 8;
|
long_value <<= 8;
|
||||||
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
|
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 |= DHCP_OPT[dhcp_state.opt_ptr++];
|
||||||
long_value <<= 8;
|
long_value <<= 8;
|
||||||
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
|
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]);
|
ip_opt(&dhcp_state.broadcast[0]);
|
||||||
break;
|
break;
|
||||||
case DHCP_LEASE:
|
case DHCP_LEASE:
|
||||||
long_opt();
|
if (long_opt())
|
||||||
dhcp_state.lease = long_value;
|
dhcp_state.lease = long_value;
|
||||||
break;
|
break;
|
||||||
case DHCP_REBIND:
|
case DHCP_REBIND:
|
||||||
long_opt();
|
if (long_opt())
|
||||||
dhcp_state.rebind = long_value;
|
dhcp_state.rebind = long_value;
|
||||||
break;
|
break;
|
||||||
case DHCP_RENEWAL:
|
case DHCP_RENEWAL:
|
||||||
long_opt();
|
if (long_opt())
|
||||||
dhcp_state.renewal = long_value;
|
dhcp_state.renewal = long_value;
|
||||||
break;
|
break;
|
||||||
case DHCP_END:
|
case DHCP_END:
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in new issue
Block a user