udhcpc: fix OPTION_IP_PAIR parsing

http://git.busybox.net/busybox/commit/?id=7d3a48a003cd645edfae2b404493688022
revealed incorrect OPTION_IP_PAIR implementation, which doesn't respect
option length and causes erroneous classful routes, composed from garbage
or first bytes from the next DHCP packet option.

Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Vladislav Grishenko 2010-10-17 12:27:50 +02:00 committed by Denys Vlasenko
parent cfe114c4f3
commit ad8def2d8a

View File

@ -89,6 +89,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
/* option points to OPT_DATA, need to go back and get OPT_LEN */ /* option points to OPT_DATA, need to go back and get OPT_LEN */
len = option[OPT_LEN - OPT_DATA]; len = option[OPT_LEN - OPT_DATA];
type = optflag->flags & OPTION_TYPE_MASK; type = optflag->flags & OPTION_TYPE_MASK;
optlen = dhcp_option_lengths[type]; optlen = dhcp_option_lengths[type];
upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen);
@ -97,17 +98,16 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
dest += sprintf(ret, "%s=", opt_name); dest += sprintf(ret, "%s=", opt_name);
while (len >= optlen) { while (len >= optlen) {
unsigned ip_ofs = 0;
switch (type) { switch (type) {
case OPTION_IP_PAIR: case OPTION_IP_PAIR:
dest += sprint_nip(dest, "", option); dest += sprint_nip(dest, "", option);
*dest++ = '/'; *dest++ = '/';
option += 4; ip_ofs = 4;
optlen = 4; /* fall through */
case OPTION_IP: case OPTION_IP:
dest += sprint_nip(dest, "", option); dest += sprint_nip(dest, "", option + ip_ofs);
// TODO: it can be a list only if (optflag->flags & OPTION_LIST).
// Should we bail out/warn if we see multi-ip option which is
// not allowed to be such? For example, DHCP_BROADCAST...
break; break;
// case OPTION_BOOLEAN: // case OPTION_BOOLEAN:
// dest += sprintf(dest, *option ? "yes" : "no"); // dest += sprintf(dest, *option ? "yes" : "no");
@ -218,7 +218,10 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_
} /* switch */ } /* switch */
option += optlen; option += optlen;
len -= optlen; len -= optlen;
if (len <= 0) // TODO: it can be a list only if (optflag->flags & OPTION_LIST).
// Should we bail out/warn if we see multi-ip option which is
// not allowed to be such (for example, DHCP_BROADCAST)? -
if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */)
break; break;
*dest++ = ' '; *dest++ = ' ';
*dest = '\0'; *dest = '\0';