diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-04 15:31:12 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-04-04 15:31:12 +0200 |
commit | 4f3aa51f9d551fba2935e34954e0eaf404c4f013 (patch) | |
tree | 534af3d78f806e79a6e3dcaf1fa5f6e89c17809e | |
parent | 4836331924b5eb7f74e000d50c99bc12d513f8c7 (diff) | |
download | busybox-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.c | 47 | ||||
-rw-r--r-- | networking/udhcp/common.h | 9 |
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 */ | ||
332 | static 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 */ |
331 | static NOINLINE void attach_option( | 349 | static 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 | ||
399 | int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg) | 415 | int 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 */ |