1303 files changed, 32187 insertions, 57138 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index fe322db..1aaf525 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -63,6 +63,7 @@ const struct dhcp_optflag dhcp_optflags[] = { { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ #endif { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ + { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ @@ -130,6 +131,7 @@ const char dhcp_option_strings[] ALIGN1 = "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ #endif "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ + "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ "ip6rd" "\0" /* DHCP_6RD */ "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ "wpad" "\0" /* DHCP_WPAD */ @@ -140,7 +142,7 @@ const char dhcp_option_strings[] ALIGN1 = * udhcp_str2optset: to determine how many bytes to allocate. * xmalloc_optname_optval: to estimate string length * from binary option length: (option[LEN] / dhcp_option_lengths[opt_type]) - * is the number of elements, multiply in by one element's string width + * is the number of elements, multiply it by one element's string width * (len_of_option_as_string[opt_type]) and you know how wide string you need. */ const uint8_t dhcp_option_lengths[] ALIGN1 = { @@ -160,7 +162,18 @@ const uint8_t dhcp_option_lengths[] ALIGN1 = { [OPTION_S32] = 4, /* Just like OPTION_STRING, we use minimum length here */ [OPTION_STATIC_ROUTES] = 5, - [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */ + [OPTION_6RD] = 12, /* ignored by udhcp_str2optset */ + /* The above value was chosen as follows: + * len_of_option_as_string[] for this option is >60: it's a string of the form + * "32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 ". + * Each additional ipv4 address takes 4 bytes in binary option and appends + * another "255.255.255.255 " 16-byte string. We can set [OPTION_6RD] = 4 + * but this severely overestimates string length: instead of 16 bytes, + * it adds >60 for every 4 bytes in binary option. + * We cheat and declare here that option is in units of 12 bytes. + * This adds more than 60 bytes for every three ipv4 addresses - more than enough. + * (Even 16 instead of 12 should work, but let's be paranoid). + */ }; @@ -170,7 +183,7 @@ static void log_option(const char *pfx, const uint8_t *opt) if (dhcp_verbose >= 2) { char buf[256 * 2 + 2]; *bin2hex(buf, (void*) (opt + OPT_DATA), opt[OPT_LEN]) = '\0'; - bb_info_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); + bb_error_msg("%s: 0x%02x %s", pfx, opt[OPT_CODE], buf); } } #else @@ -213,9 +226,12 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) rem = sizeof(packet->options); while (1) { if (rem <= 0) { + complain: bb_error_msg("bad packet, malformed option field"); return NULL; } + + /* DHCP_PADDING and DHCP_END have no [len] byte */ if (optionptr[OPT_CODE] == DHCP_PADDING) { rem--; optionptr++; @@ -238,25 +254,29 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) } break; } + + if (rem <= OPT_LEN) + goto complain; /* complain and return NULL */ len = 2 + optionptr[OPT_LEN]; rem -= len; if (rem < 0) - continue; /* complain and return NULL */ + goto complain; /* complain and return NULL */ if (optionptr[OPT_CODE] == code) { - log_option("Option found", optionptr); + log_option("option found", optionptr); return optionptr + OPT_DATA; } if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { - overload |= optionptr[OPT_DATA]; + if (len >= 3) + overload |= optionptr[OPT_DATA]; /* fall through */ } optionptr += len; } /* log3 because udhcpc uses it a lot - very noisy */ - log3("Option 0x%02x not found", code); + log3("option 0x%02x not found", code); return NULL; } @@ -290,7 +310,7 @@ void FAST_FUNC udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addo addopt[OPT_CODE]); return; } - log_option("Adding option", addopt); + log_option("adding option", addopt); memcpy(optionptr + end, addopt, len); optionptr[end + len] = DHCP_END; } @@ -389,7 +409,7 @@ static NOINLINE void attach_option( struct option_set *new, **curr; /* make a new option */ - log2("Attaching option %02x to list", optflag->code); + log2("attaching option %02x to list", optflag->code); new = xmalloc(sizeof(*new)); new->data = xmalloc(length + OPT_DATA); new->data[OPT_CODE] = optflag->code; @@ -409,7 +429,7 @@ static NOINLINE void attach_option( unsigned old_len; /* add it to an existing option */ - log2("Attaching option %02x to existing member of list", optflag->code); + log2("attaching option %02x to existing member of list", optflag->code); old_len = existing->data[OPT_LEN]; if (old_len + length < 255) { /* actually 255 is ok too, but adding a space can overlow it */ |