aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-04-13 13:18:34 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-13 13:27:52 +0200
commit266f6f19732f9b35487a87a346e58c1c3a0af43d (patch)
tree10489c89deea2665170fd4006c11b951dc284ee9 /networking/udhcp
parent46158dc833ca48a63a2547bb26eee133aa19dccf (diff)
downloadbusybox-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.c71
-rw-r--r--networking/udhcp/d6_dhcpc.c11
-rw-r--r--networking/udhcp/dhcpc.c11
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 */
382static char *allocate_tempopt_if_needed( 382static 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 */
399static 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(
463int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings) 453int 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;
515case_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,