diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-12-12 17:13:54 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-12-12 17:13:54 +0100 |
commit | e67b80f4739c4075b51b0a575701b73928fe0bf1 (patch) | |
tree | 20c9163f50db185493b7fa7d6e778742c51a3b37 | |
parent | 9b678807198611308cfd8b10427f9e08c62f7bec (diff) | |
download | busybox-w32-e67b80f4739c4075b51b0a575701b73928fe0bf1.tar.gz busybox-w32-e67b80f4739c4075b51b0a575701b73928fe0bf1.tar.bz2 busybox-w32-e67b80f4739c4075b51b0a575701b73928fe0bf1.zip |
udhcpc6: fix udhcp_find_option to actually find DHCP6 options
udhcp_insert_new_option treats code for IPv6 as follows:
new->data[D6_OPT_CODE] = code >> 8;
new->data[D6_OPT_CODE + 1] = code & 0xff;
udhcp_find_option tests the code as follows:
while (opt_list && opt_list->data[OPT_CODE] < code)
...
if (opt_list && opt_list->data[OPT_CODE] == code)
So yes, OPT_CODE and D6_OPT_CODE are both 0, but the D6_OPT_CLIENTID =
1 value means that the 1 is in the seconds byte, and udhcp_find_option
is only looking at the first byte, So the send_d6_release can never
find it the created option.
function old new delta
udhcp_find_option 28 53 +25
attach_option 276 284 +8
udhcpc6_main 2602 2607 +5
perform_d6_release 262 267 +5
udhcpd_main 1518 1520 +2
udhcpc_main 2542 2544 +2
add_serverid_and_clientid_options 46 48 +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 7/0 up/down: 49/0) Total: 49 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/common.c | 29 | ||||
-rw-r--r-- | networking/udhcp/common.h | 6 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 5 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 6 | ||||
-rw-r--r-- | networking/udhcp/dhcpd.c | 2 |
5 files changed, 34 insertions, 14 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 31e525cb0..8e9b93655 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -404,14 +404,29 @@ void FAST_FUNC udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, | |||
404 | #endif | 404 | #endif |
405 | 405 | ||
406 | /* Find option 'code' in opt_list */ | 406 | /* Find option 'code' in opt_list */ |
407 | struct option_set* FAST_FUNC udhcp_find_option(struct option_set *opt_list, uint8_t code) | 407 | struct option_set* FAST_FUNC udhcp_find_option(struct option_set *opt_list, uint8_t code, bool dhcpv6) |
408 | { | 408 | { |
409 | while (opt_list && opt_list->data[OPT_CODE] < code) | 409 | IF_NOT_UDHCPC6(bool dhcpv6 = 0;) |
410 | opt_list = opt_list->next; | 410 | uint8_t cur_code; |
411 | 411 | ||
412 | if (opt_list && opt_list->data[OPT_CODE] == code) | 412 | for (;;) { |
413 | return opt_list; | 413 | if (!opt_list) |
414 | return NULL; | 414 | return opt_list; /* NULL */ |
415 | if (!dhcpv6) { | ||
416 | cur_code = opt_list->data[OPT_CODE]; | ||
417 | } else { | ||
418 | //FIXME: add support for code > 0xff | ||
419 | if (opt_list->data[D6_OPT_CODE] != 0) | ||
420 | return NULL; | ||
421 | cur_code = opt_list->data[D6_OPT_CODE + 1]; | ||
422 | } | ||
423 | if (cur_code >= code) { | ||
424 | if (cur_code == code) | ||
425 | return opt_list; | ||
426 | return NULL; | ||
427 | } | ||
428 | opt_list = opt_list->next; | ||
429 | } | ||
415 | } | 430 | } |
416 | 431 | ||
417 | /* Parse string to IP in network order */ | 432 | /* Parse string to IP in network order */ |
@@ -499,7 +514,7 @@ static NOINLINE void attach_option( | |||
499 | } | 514 | } |
500 | #endif | 515 | #endif |
501 | 516 | ||
502 | existing = udhcp_find_option(*opt_list, optflag->code); | 517 | existing = udhcp_find_option(*opt_list, optflag->code, dhcpv6); |
503 | if (!existing) { | 518 | if (!existing) { |
504 | /* make a new option */ | 519 | /* make a new option */ |
505 | uint8_t *p = udhcp_insert_new_option(opt_list, optflag->code, length, dhcpv6); | 520 | uint8_t *p = udhcp_insert_new_option(opt_list, optflag->code, length, dhcpv6); |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index e374771cb..5882238e3 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -245,7 +245,11 @@ void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t | |||
245 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; | 245 | char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; |
246 | uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; | 246 | uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; |
247 | #endif | 247 | #endif |
248 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC; | 248 | #if !ENABLE_UDHCPC6 |
249 | #define udhcp_find_option(opt_list, code, dhcpv6) \ | ||
250 | udhcp_find_option(opt_list, code) | ||
251 | #endif | ||
252 | struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code, bool dhcpv6) FAST_FUNC; | ||
249 | 253 | ||
250 | // RFC 2131 Table 5: Fields and options used by DHCP clients | 254 | // RFC 2131 Table 5: Fields and options used by DHCP clients |
251 | // | 255 | // |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 8d11a7539..9d2a8f5d3 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -888,7 +888,8 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) | |||
888 | if (client6_data.ia_pd) | 888 | if (client6_data.ia_pd) |
889 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); | 889 | opt_ptr = mempcpy(opt_ptr, client6_data.ia_pd, client6_data.ia_pd->len + 2+2); |
890 | /* Client-id */ | 890 | /* Client-id */ |
891 | ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID); | 891 | ///vda |
892 | ci = udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1); | ||
892 | if (ci) | 893 | if (ci) |
893 | opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6); | 894 | opt_ptr = mempcpy(opt_ptr, ci->data, D6_OPT_DATA + 2+2 + 6); |
894 | 895 | ||
@@ -1272,7 +1273,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1272 | } | 1273 | } |
1273 | 1274 | ||
1274 | clientid_mac_ptr = NULL; | 1275 | clientid_mac_ptr = NULL; |
1275 | if (!udhcp_find_option(client_data.options, D6_OPT_CLIENTID)) { | 1276 | if (!udhcp_find_option(client_data.options, D6_OPT_CLIENTID, /*dhcpv6:*/ 1)) { |
1276 | /* not set, set the default client ID */ | 1277 | /* not set, set the default client ID */ |
1277 | clientid_mac_ptr = udhcp_insert_new_option( | 1278 | clientid_mac_ptr = udhcp_insert_new_option( |
1278 | &client_data.options, D6_OPT_CLIENTID, | 1279 | &client_data.options, D6_OPT_CLIENTID, |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 331f13a8c..c757fb37c 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -658,7 +658,7 @@ static void add_client_options(struct dhcp_packet *packet) | |||
658 | 658 | ||
659 | // This will be needed if we remove -V VENDOR_STR in favor of | 659 | // This will be needed if we remove -V VENDOR_STR in favor of |
660 | // -x vendor:VENDOR_STR | 660 | // -x vendor:VENDOR_STR |
661 | //if (!udhcp_find_option(packet.options, DHCP_VENDOR)) | 661 | //if (!udhcp_find_option(packet.options, DHCP_VENDOR, /*dhcpv6:*/ 0)) |
662 | // /* not set, set the default vendor ID */ | 662 | // /* not set, set the default vendor ID */ |
663 | // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... | 663 | // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... |
664 | } | 664 | } |
@@ -676,7 +676,7 @@ static void add_serverid_and_clientid_options(struct dhcp_packet *packet, uint32 | |||
676 | * If the client used a 'client identifier' when it obtained the lease, | 676 | * If the client used a 'client identifier' when it obtained the lease, |
677 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. | 677 | * it MUST use the same 'client identifier' in the DHCPRELEASE message. |
678 | */ | 678 | */ |
679 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID); | 679 | ci = udhcp_find_option(client_data.options, DHCP_CLIENT_ID, /*dhcpv6:*/ 0); |
680 | if (ci) | 680 | if (ci) |
681 | udhcp_add_binary_option(packet, ci->data); | 681 | udhcp_add_binary_option(packet, ci->data); |
682 | } | 682 | } |
@@ -1328,7 +1328,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | clientid_mac_ptr = NULL; | 1330 | clientid_mac_ptr = NULL; |
1331 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { | 1331 | if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID, /*dhcpv6:*/ 0)) { |
1332 | /* not suppressed and not set, create default client ID */ | 1332 | /* not suppressed and not set, create default client ID */ |
1333 | clientid_mac_ptr = udhcp_insert_new_option( | 1333 | clientid_mac_ptr = udhcp_insert_new_option( |
1334 | &client_data.options, DHCP_CLIENT_ID, | 1334 | &client_data.options, DHCP_CLIENT_ID, |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 0f5edb75c..66750e2e6 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -935,7 +935,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
935 | 935 | ||
936 | bb_simple_info_msg("started, v"BB_VER); | 936 | bb_simple_info_msg("started, v"BB_VER); |
937 | 937 | ||
938 | option = udhcp_find_option(server_data.options, DHCP_LEASE_TIME); | 938 | option = udhcp_find_option(server_data.options, DHCP_LEASE_TIME, /*dhcpv6:*/ 0); |
939 | server_data.max_lease_sec = DEFAULT_LEASE_TIME; | 939 | server_data.max_lease_sec = DEFAULT_LEASE_TIME; |
940 | if (option) { | 940 | if (option) { |
941 | move_from_unaligned32(server_data.max_lease_sec, option->data + OPT_DATA); | 941 | move_from_unaligned32(server_data.max_lease_sec, option->data + OPT_DATA); |