aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-04-04 15:31:12 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-04-04 15:31:12 +0200
commit4f3aa51f9d551fba2935e34954e0eaf404c4f013 (patch)
tree534af3d78f806e79a6e3dcaf1fa5f6e89c17809e
parent4836331924b5eb7f74e000d50c99bc12d513f8c7 (diff)
downloadbusybox-w32-4f3aa51f9d551fba2935e34954e0eaf404c4f013.tar.gz
busybox-w32-4f3aa51f9d551fba2935e34954e0eaf404c4f013.tar.bz2
busybox-w32-4f3aa51f9d551fba2935e34954e0eaf404c4f013.zip
udhcp: implement "raw" binary options. Closes bug 735
function old new delta allocate_tempopt_if_needed - 76 +76 udhcp_str2optset 351 415 +64 attach_option 380 398 +18 len_of_option_as_string 11 12 +1 dhcp_option_lengths 11 12 +1 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 160/0) Total: 160 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/common.c47
-rw-r--r--networking/udhcp/common.h9
2 files changed, 43 insertions, 13 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index fb4f8d16c..50e2c84e3 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -324,9 +324,27 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg)
324} 324}
325 325
326/* udhcp_str2optset: 326/* udhcp_str2optset:
327 * Parse string option representation to binary form 327 * Parse string option representation to binary form and add it to opt_list.
328 * and add it to opt_list 328 * Called to parse "udhcpc -x OPTNAME:OPTVAL"
329 * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives.
329 */ 330 */
331/* helper for the helper */
332static char *allocate_tempopt_if_needed(
333 const struct dhcp_optflag *optflag,
334 char *buffer,
335 int *length_p)
336{
337 char *allocated = NULL;
338 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_BIN) {
339 const char *end;
340 allocated = xstrdup(buffer); /* more than enough */
341 end = hex2bin(allocated, buffer, 255);
342 if (errno)
343 bb_error_msg_and_die("malformed hex string '%s'", buffer);
344 *length_p = end - allocated;
345 }
346 return allocated;
347}
330/* helper: add an option to the opt_list */ 348/* helper: add an option to the opt_list */
331static NOINLINE void attach_option( 349static NOINLINE void attach_option(
332 struct option_set **opt_list, 350 struct option_set **opt_list,
@@ -335,13 +353,12 @@ static NOINLINE void attach_option(
335 int length) 353 int length)
336{ 354{
337 struct option_set *existing, *new, **curr; 355 struct option_set *existing, *new, **curr;
338#if ENABLE_FEATURE_UDHCP_RFC3397
339 char *allocated = NULL; 356 char *allocated = NULL;
340#endif
341 357
342 existing = udhcp_find_option(*opt_list, optflag->code); 358 existing = udhcp_find_option(*opt_list, optflag->code);
343 if (!existing) { 359 if (!existing) {
344 log2("Attaching option %02x to list", optflag->code); 360 log2("Attaching option %02x to list", optflag->code);
361 allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
345#if ENABLE_FEATURE_UDHCP_RFC3397 362#if ENABLE_FEATURE_UDHCP_RFC3397
346 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { 363 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
347 /* reuse buffer and length for RFC1035-formatted string */ 364 /* reuse buffer and length for RFC1035-formatted string */
@@ -368,7 +385,8 @@ static NOINLINE void attach_option(
368 unsigned old_len; 385 unsigned old_len;
369 386
370 /* add it to an existing option */ 387 /* add it to an existing option */
371 log1("Attaching option %02x to existing member of list", optflag->code); 388 log2("Attaching option %02x to existing member of list", optflag->code);
389 allocated = allocate_tempopt_if_needed(optflag, buffer, &length);
372 old_len = existing->data[OPT_LEN]; 390 old_len = existing->data[OPT_LEN];
373#if ENABLE_FEATURE_UDHCP_RFC3397 391#if ENABLE_FEATURE_UDHCP_RFC3397
374 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { 392 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
@@ -390,10 +408,8 @@ static NOINLINE void attach_option(
390 } /* else, ignore the data, we could put this in a second option in the future */ 408 } /* else, ignore the data, we could put this in a second option in the future */
391 } /* else, ignore the new data */ 409 } /* else, ignore the new data */
392 410
393 ret: ; 411 ret:
394#if ENABLE_FEATURE_UDHCP_RFC3397
395 free(allocated); 412 free(allocated);
396#endif
397} 413}
398 414
399int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) 415int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
@@ -402,6 +418,8 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
402 char *opt, *val, *endptr; 418 char *opt, *val, *endptr;
403 char *str; 419 char *str;
404 const struct dhcp_optflag *optflag; 420 const struct dhcp_optflag *optflag;
421 struct dhcp_optflag bin_optflag;
422 unsigned optcode;
405 int retval, length; 423 int retval, length;
406 char buffer[8] ALIGNED(4); 424 char buffer[8] ALIGNED(4);
407 uint16_t *result_u16 = (uint16_t *) buffer; 425 uint16_t *result_u16 = (uint16_t *) buffer;
@@ -413,7 +431,15 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
413 if (!opt) 431 if (!opt)
414 return 0; 432 return 0;
415 433
416 optflag = &dhcp_optflags[udhcp_option_idx(opt)]; 434 optcode = bb_strtou(opt, NULL, 0);
435 if (!errno && optcode < 255) {
436 /* Raw (numeric) option code */
437 bin_optflag.flags = OPTION_BIN;
438 bin_optflag.code = optcode;
439 optflag = &bin_optflag;
440 } else {
441 optflag = &dhcp_optflags[udhcp_option_idx(opt)];
442 }
417 443
418 retval = 0; 444 retval = 0;
419 do { 445 do {
@@ -482,6 +508,9 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
482 retval = (endptr[0] == '\0'); 508 retval = (endptr[0] == '\0');
483 break; 509 break;
484 } 510 }
511 case OPTION_BIN: /* handled in attach_option() */
512 opt = val;
513 retval = 1;
485 default: 514 default:
486 break; 515 break;
487 } 516 }
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 7dd1f119a..c9dd0bb25 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -70,17 +70,18 @@ enum {
70 OPTION_IP = 1, 70 OPTION_IP = 1,
71 OPTION_IP_PAIR, 71 OPTION_IP_PAIR,
72 OPTION_STRING, 72 OPTION_STRING,
73#if ENABLE_FEATURE_UDHCP_RFC3397
74 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
75 OPTION_SIP_SERVERS,
76#endif
77// OPTION_BOOLEAN, 73// OPTION_BOOLEAN,
78 OPTION_U8, 74 OPTION_U8,
79 OPTION_U16, 75 OPTION_U16,
80// OPTION_S16, 76// OPTION_S16,
81 OPTION_U32, 77 OPTION_U32,
82 OPTION_S32, 78 OPTION_S32,
79 OPTION_BIN,
83 OPTION_STATIC_ROUTES, 80 OPTION_STATIC_ROUTES,
81#if ENABLE_FEATURE_UDHCP_RFC3397
82 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */
83 OPTION_SIP_SERVERS,
84#endif
84 85
85 OPTION_TYPE_MASK = 0x0f, 86 OPTION_TYPE_MASK = 0x0f,
86 /* Client requests this option by default */ 87 /* Client requests this option by default */