diff options
author | Vladislav Grishenko <themiron@mail.ru> | 2010-10-17 12:27:50 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-17 12:27:50 +0200 |
commit | ad8def2d8ad980a5b759c32a220828ea1248e5b6 (patch) | |
tree | fdb7ed18d48a2957fc5f7481a07e60b78efab042 /networking/udhcp | |
parent | cfe114c4f3d4e1dfc00196d8df316874eaf2d2b8 (diff) | |
download | busybox-w32-ad8def2d8ad980a5b759c32a220828ea1248e5b6.tar.gz busybox-w32-ad8def2d8ad980a5b759c32a220828ea1248e5b6.tar.bz2 busybox-w32-ad8def2d8ad980a5b759c32a220828ea1248e5b6.zip |
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>
Diffstat (limited to 'networking/udhcp')
-rw-r--r-- | networking/udhcp/dhcpc.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index de1b79844..27d6ad1a8 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -89,6 +89,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
89 | 89 | ||
90 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ | 90 | /* option points to OPT_DATA, need to go back and get OPT_LEN */ |
91 | len = option[OPT_LEN - OPT_DATA]; | 91 | len = option[OPT_LEN - OPT_DATA]; |
92 | |||
92 | type = optflag->flags & OPTION_TYPE_MASK; | 93 | type = optflag->flags & OPTION_TYPE_MASK; |
93 | optlen = dhcp_option_lengths[type]; | 94 | optlen = dhcp_option_lengths[type]; |
94 | upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); | 95 | 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_ | |||
97 | dest += sprintf(ret, "%s=", opt_name); | 98 | dest += sprintf(ret, "%s=", opt_name); |
98 | 99 | ||
99 | while (len >= optlen) { | 100 | while (len >= optlen) { |
101 | unsigned ip_ofs = 0; | ||
102 | |||
100 | switch (type) { | 103 | switch (type) { |
101 | case OPTION_IP_PAIR: | 104 | case OPTION_IP_PAIR: |
102 | dest += sprint_nip(dest, "", option); | 105 | dest += sprint_nip(dest, "", option); |
103 | *dest++ = '/'; | 106 | *dest++ = '/'; |
104 | option += 4; | 107 | ip_ofs = 4; |
105 | optlen = 4; | 108 | /* fall through */ |
106 | case OPTION_IP: | 109 | case OPTION_IP: |
107 | dest += sprint_nip(dest, "", option); | 110 | dest += sprint_nip(dest, "", option + ip_ofs); |
108 | // TODO: it can be a list only if (optflag->flags & OPTION_LIST). | ||
109 | // Should we bail out/warn if we see multi-ip option which is | ||
110 | // not allowed to be such? For example, DHCP_BROADCAST... | ||
111 | break; | 111 | break; |
112 | // case OPTION_BOOLEAN: | 112 | // case OPTION_BOOLEAN: |
113 | // dest += sprintf(dest, *option ? "yes" : "no"); | 113 | // dest += sprintf(dest, *option ? "yes" : "no"); |
@@ -218,7 +218,10 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ | |||
218 | } /* switch */ | 218 | } /* switch */ |
219 | option += optlen; | 219 | option += optlen; |
220 | len -= optlen; | 220 | len -= optlen; |
221 | if (len <= 0) | 221 | // TODO: it can be a list only if (optflag->flags & OPTION_LIST). |
222 | // Should we bail out/warn if we see multi-ip option which is | ||
223 | // not allowed to be such (for example, DHCP_BROADCAST)? - | ||
224 | if (len <= 0 /* || !(optflag->flags & OPTION_LIST) */) | ||
222 | break; | 225 | break; |
223 | *dest++ = ' '; | 226 | *dest++ = ' '; |
224 | *dest = '\0'; | 227 | *dest = '\0'; |