diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-13 13:18:34 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-13 13:27:52 +0200 |
commit | 266f6f19732f9b35487a87a346e58c1c3a0af43d (patch) | |
tree | 10489c89deea2665170fd4006c11b951dc284ee9 /networking/udhcp | |
parent | 46158dc833ca48a63a2547bb26eee133aa19dccf (diff) | |
download | busybox-w32-266f6f19732f9b35487a87a346e58c1c3a0af43d.tar.gz busybox-w32-266f6f19732f9b35487a87a346e58c1c3a0af43d.tar.bz2 busybox-w32-266f6f19732f9b35487a87a346e58c1c3a0af43d.zip |
udhcp: support string user options, closes 10946
function old new delta
udhcp_str2optset 536 628 +92
packed_usage 32757 32760 +3
udhcpc_main 2708 2692 -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 95/-16) Total: 79 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/udhcp')
-rw-r--r-- | networking/udhcp/common.c | 71 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 11 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 11 |
3 files changed, 50 insertions, 43 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index d3eea5def..fbf9c6878 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -378,34 +378,24 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) | |||
378 | * Called to parse "udhcpc -x OPTNAME:OPTVAL" | 378 | * Called to parse "udhcpc -x OPTNAME:OPTVAL" |
379 | * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives. | 379 | * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives. |
380 | */ | 380 | */ |
381 | /* helper for the helper */ | 381 | /* helper: add an option to the opt_list */ |
382 | static char *allocate_tempopt_if_needed( | 382 | static NOINLINE void attach_option( |
383 | struct option_set **opt_list, | ||
383 | const struct dhcp_optflag *optflag, | 384 | const struct dhcp_optflag *optflag, |
384 | char *buffer, | 385 | char *buffer, |
385 | int *length_p) | 386 | int length) |
386 | { | 387 | { |
388 | struct option_set *existing; | ||
387 | char *allocated = NULL; | 389 | char *allocated = NULL; |
390 | |||
388 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_BIN) { | 391 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_BIN) { |
389 | const char *end; | 392 | const char *end; |
390 | allocated = xstrdup(buffer); /* more than enough */ | 393 | allocated = xstrdup(buffer); /* more than enough */ |
391 | end = hex2bin(allocated, buffer, 255); | 394 | end = hex2bin(allocated, buffer, 255); |
392 | if (errno) | 395 | if (errno) |
393 | bb_error_msg_and_die("malformed hex string '%s'", buffer); | 396 | bb_error_msg_and_die("malformed hex string '%s'", buffer); |
394 | *length_p = end - allocated; | 397 | length = end - allocated; |
395 | } | 398 | } |
396 | return allocated; | ||
397 | } | ||
398 | /* helper: add an option to the opt_list */ | ||
399 | static NOINLINE void attach_option( | ||
400 | struct option_set **opt_list, | ||
401 | const struct dhcp_optflag *optflag, | ||
402 | char *buffer, | ||
403 | int length) | ||
404 | { | ||
405 | struct option_set *existing; | ||
406 | char *allocated; | ||
407 | |||
408 | allocated = allocate_tempopt_if_needed(optflag, buffer, &length); | ||
409 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 399 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
410 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | 400 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
411 | /* reuse buffer and length for RFC1035-formatted string */ | 401 | /* reuse buffer and length for RFC1035-formatted string */ |
@@ -463,12 +453,12 @@ static NOINLINE void attach_option( | |||
463 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings) | 453 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings) |
464 | { | 454 | { |
465 | struct option_set **opt_list = arg; | 455 | struct option_set **opt_list = arg; |
466 | char *opt, *val; | 456 | char *opt; |
467 | char *str; | 457 | char *str; |
468 | const struct dhcp_optflag *optflag; | 458 | const struct dhcp_optflag *optflag; |
469 | struct dhcp_optflag bin_optflag; | 459 | struct dhcp_optflag userdef_optflag; |
470 | unsigned optcode; | 460 | unsigned optcode; |
471 | int retval, length; | 461 | int retval; |
472 | /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ | 462 | /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ |
473 | char buffer[9] ALIGNED(4); | 463 | char buffer[9] ALIGNED(4); |
474 | uint16_t *result_u16 = (uint16_t *) buffer; | 464 | uint16_t *result_u16 = (uint16_t *) buffer; |
@@ -476,28 +466,40 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh | |||
476 | 466 | ||
477 | /* Cheat, the only *const* str possible is "" */ | 467 | /* Cheat, the only *const* str possible is "" */ |
478 | str = (char *) const_str; | 468 | str = (char *) const_str; |
479 | opt = strtok(str, " \t="); | 469 | opt = strtok(str, " \t=:"); |
480 | if (!opt) | 470 | if (!opt) |
481 | return 0; | 471 | return 0; |
482 | 472 | ||
483 | optcode = bb_strtou(opt, NULL, 0); | 473 | optcode = bb_strtou(opt, NULL, 0); |
484 | if (!errno && optcode < 255) { | 474 | if (!errno && optcode < 255) { |
485 | /* Raw (numeric) option code */ | 475 | /* Raw (numeric) option code. |
486 | bin_optflag.flags = OPTION_BIN; | 476 | * Initially assume binary (hex-str), but if "str" or 'str' |
487 | bin_optflag.code = optcode; | 477 | * is seen later, switch to STRING. |
488 | optflag = &bin_optflag; | 478 | */ |
479 | userdef_optflag.flags = OPTION_BIN; | ||
480 | userdef_optflag.code = optcode; | ||
481 | optflag = &userdef_optflag; | ||
489 | } else { | 482 | } else { |
490 | optflag = &optflags[udhcp_option_idx(opt, option_strings)]; | 483 | optflag = &optflags[udhcp_option_idx(opt, option_strings)]; |
491 | } | 484 | } |
492 | 485 | ||
486 | /* Loop to handle OPTION_LIST case, else execute just once */ | ||
493 | retval = 0; | 487 | retval = 0; |
494 | do { | 488 | do { |
495 | val = strtok(NULL, ", \t"); | 489 | int length; |
490 | char *val; | ||
491 | |||
492 | if (optflag->flags == OPTION_BIN) | ||
493 | val = trim(strtok(NULL, "")); /* do not split "'q w e'" */ | ||
494 | else | ||
495 | val = strtok(NULL, ", \t"); | ||
496 | if (!val) | 496 | if (!val) |
497 | break; | 497 | break; |
498 | |||
498 | length = dhcp_option_lengths[optflag->flags & OPTION_TYPE_MASK]; | 499 | length = dhcp_option_lengths[optflag->flags & OPTION_TYPE_MASK]; |
499 | retval = 0; | 500 | retval = 0; |
500 | opt = buffer; /* new meaning for variable opt */ | 501 | opt = buffer; /* new meaning for variable opt */ |
502 | |||
501 | switch (optflag->flags & OPTION_TYPE_MASK) { | 503 | switch (optflag->flags & OPTION_TYPE_MASK) { |
502 | case OPTION_IP: | 504 | case OPTION_IP: |
503 | retval = udhcp_str2nip(val, buffer); | 505 | retval = udhcp_str2nip(val, buffer); |
@@ -510,6 +512,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh | |||
510 | if (retval) | 512 | if (retval) |
511 | retval = udhcp_str2nip(val, buffer + 4); | 513 | retval = udhcp_str2nip(val, buffer + 4); |
512 | break; | 514 | break; |
515 | case_OPTION_STRING: | ||
513 | case OPTION_STRING: | 516 | case OPTION_STRING: |
514 | case OPTION_STRING_HOST: | 517 | case OPTION_STRING_HOST: |
515 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 518 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
@@ -577,12 +580,26 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh | |||
577 | } | 580 | } |
578 | break; | 581 | break; |
579 | } | 582 | } |
580 | case OPTION_BIN: /* handled in attach_option() */ | 583 | case OPTION_BIN: |
584 | /* Raw (numeric) option code. Is it a string? */ | ||
585 | if (val[0] == '"' || val[0] == '\'') { | ||
586 | char delim = val[0]; | ||
587 | char *end = last_char_is(val + 1, delim); | ||
588 | if (end) { | ||
589 | *end = '\0'; | ||
590 | val++; | ||
591 | userdef_optflag.flags = OPTION_STRING; | ||
592 | goto case_OPTION_STRING; | ||
593 | } | ||
594 | } | ||
595 | /* No: hex-str option, handled in attach_option() */ | ||
581 | opt = val; | 596 | opt = val; |
582 | retval = 1; | 597 | retval = 1; |
598 | break; | ||
583 | default: | 599 | default: |
584 | break; | 600 | break; |
585 | } | 601 | } |
602 | |||
586 | if (retval) | 603 | if (retval) |
587 | attach_option(opt_list, optflag, opt, length); | 604 | attach_option(opt_list, optflag, opt, length); |
588 | } while (retval && (optflag->flags & OPTION_LIST)); | 605 | } while (retval && (optflag->flags & OPTION_LIST)); |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 289df66ee..85d9da724 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -1063,6 +1063,7 @@ static void client_background(void) | |||
1063 | //usage: "\n -x hostname:bbox - option 12" | 1063 | //usage: "\n -x hostname:bbox - option 12" |
1064 | //usage: "\n -x lease:3600 - option 51 (lease time)" | 1064 | //usage: "\n -x lease:3600 - option 51 (lease time)" |
1065 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" | 1065 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" |
1066 | //usage: "\n -x 14:'\"dumpfile\"' - option 14 (shell-quoted)" | ||
1066 | //usage: IF_UDHCP_VERBOSE( | 1067 | //usage: IF_UDHCP_VERBOSE( |
1067 | //usage: "\n -v Verbose" | 1068 | //usage: "\n -v Verbose" |
1068 | //usage: ) | 1069 | //usage: ) |
@@ -1155,15 +1156,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1155 | } | 1156 | } |
1156 | } | 1157 | } |
1157 | while (list_x) { | 1158 | while (list_x) { |
1158 | char *optstr = llist_pop(&list_x); | 1159 | char *optstr = xstrdup(llist_pop(&list_x)); |
1159 | char *colon = strchr(optstr, ':'); | ||
1160 | if (colon) | ||
1161 | *colon = ' '; | ||
1162 | /* now it looks similar to udhcpd's config file line: | ||
1163 | * "optname optval", using the common routine: */ | ||
1164 | udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings); | 1160 | udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings); |
1165 | if (colon) | 1161 | free(optstr); |
1166 | *colon = ':'; /* restore it for NOMMU reexec */ | ||
1167 | } | 1162 | } |
1168 | 1163 | ||
1169 | if (d6_read_interface(client_config.interface, | 1164 | if (d6_read_interface(client_config.interface, |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 90b07bf4b..bd9e8fdc2 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -1224,6 +1224,7 @@ static void client_background(void) | |||
1224 | //usage: "\n -x hostname:bbox - option 12" | 1224 | //usage: "\n -x hostname:bbox - option 12" |
1225 | //usage: "\n -x lease:3600 - option 51 (lease time)" | 1225 | //usage: "\n -x lease:3600 - option 51 (lease time)" |
1226 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" | 1226 | //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" |
1227 | //usage: "\n -x 14:'\"dumpfile\"' - option 14 (shell-quoted)" | ||
1227 | //usage: "\n -F NAME Ask server to update DNS mapping for NAME" | 1228 | //usage: "\n -F NAME Ask server to update DNS mapping for NAME" |
1228 | //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" | 1229 | //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" |
1229 | //usage: "\n -C Don't send MAC as client identifier" | 1230 | //usage: "\n -C Don't send MAC as client identifier" |
@@ -1335,15 +1336,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1335 | } | 1336 | } |
1336 | } | 1337 | } |
1337 | while (list_x) { | 1338 | while (list_x) { |
1338 | char *optstr = llist_pop(&list_x); | 1339 | char *optstr = xstrdup(llist_pop(&list_x)); |
1339 | char *colon = strchr(optstr, ':'); | ||
1340 | if (colon) | ||
1341 | *colon = ' '; | ||
1342 | /* now it looks similar to udhcpd's config file line: | ||
1343 | * "optname optval", using the common routine: */ | ||
1344 | udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings); | 1340 | udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings); |
1345 | if (colon) | 1341 | free(optstr); |
1346 | *colon = ':'; /* restore it for NOMMU reexec */ | ||
1347 | } | 1342 | } |
1348 | 1343 | ||
1349 | if (udhcp_read_interface(client_config.interface, | 1344 | if (udhcp_read_interface(client_config.interface, |