diff options
Diffstat (limited to 'networking/udhcp/common.c')
-rw-r--r-- | networking/udhcp/common.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index e5fd74f91..fc4de5716 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c | |||
@@ -272,6 +272,15 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | |||
272 | goto complain; /* complain and return NULL */ | 272 | goto complain; /* complain and return NULL */ |
273 | 273 | ||
274 | if (optionptr[OPT_CODE] == code) { | 274 | if (optionptr[OPT_CODE] == code) { |
275 | if (optionptr[OPT_LEN] == 0) { | ||
276 | /* So far no valid option with length 0 known. | ||
277 | * Having this check means that searching | ||
278 | * for DHCP_MESSAGE_TYPE need not worry | ||
279 | * that returned pointer might be unsafe | ||
280 | * to dereference. | ||
281 | */ | ||
282 | goto complain; /* complain and return NULL */ | ||
283 | } | ||
275 | log_option("option found", optionptr); | 284 | log_option("option found", optionptr); |
276 | return optionptr + OPT_DATA; | 285 | return optionptr + OPT_DATA; |
277 | } | 286 | } |
@@ -289,6 +298,16 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code) | |||
289 | return NULL; | 298 | return NULL; |
290 | } | 299 | } |
291 | 300 | ||
301 | uint8_t* FAST_FUNC udhcp_get_option32(struct dhcp_packet *packet, int code) | ||
302 | { | ||
303 | uint8_t *r = udhcp_get_option(packet, code); | ||
304 | if (r) { | ||
305 | if (r[-OPT_DATA + OPT_LEN] != 4) | ||
306 | r = NULL; | ||
307 | } | ||
308 | return r; | ||
309 | } | ||
310 | |||
292 | /* Return the position of the 'end' option (no bounds checking) */ | 311 | /* Return the position of the 'end' option (no bounds checking) */ |
293 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) | 312 | int FAST_FUNC udhcp_end_option(uint8_t *optionptr) |
294 | { | 313 | { |
@@ -403,6 +422,7 @@ static NOINLINE void attach_option( | |||
403 | if (errno) | 422 | if (errno) |
404 | bb_error_msg_and_die("malformed hex string '%s'", buffer); | 423 | bb_error_msg_and_die("malformed hex string '%s'", buffer); |
405 | length = end - allocated; | 424 | length = end - allocated; |
425 | buffer = allocated; | ||
406 | } | 426 | } |
407 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 427 | #if ENABLE_FEATURE_UDHCP_RFC3397 |
408 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { | 428 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { |
@@ -422,15 +442,14 @@ static NOINLINE void attach_option( | |||
422 | new->data = xmalloc(length + OPT_DATA); | 442 | new->data = xmalloc(length + OPT_DATA); |
423 | new->data[OPT_CODE] = optflag->code; | 443 | new->data[OPT_CODE] = optflag->code; |
424 | new->data[OPT_LEN] = length; | 444 | new->data[OPT_LEN] = length; |
425 | memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), | 445 | memcpy(new->data + OPT_DATA, buffer, length); |
426 | length); | ||
427 | } else { | 446 | } else { |
428 | new->data = xmalloc(length + D6_OPT_DATA); | 447 | new->data = xmalloc(length + D6_OPT_DATA); |
429 | new->data[D6_OPT_CODE] = optflag->code >> 8; | 448 | new->data[D6_OPT_CODE] = optflag->code >> 8; |
430 | new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; | 449 | new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; |
431 | new->data[D6_OPT_LEN] = length >> 8; | 450 | new->data[D6_OPT_LEN] = length >> 8; |
432 | new->data[D6_OPT_LEN + 1] = length & 0xff; | 451 | new->data[D6_OPT_LEN + 1] = length & 0xff; |
433 | memcpy(new->data + D6_OPT_DATA, (allocated ? allocated : buffer), | 452 | memcpy(new->data + D6_OPT_DATA, buffer, |
434 | length); | 453 | length); |
435 | } | 454 | } |
436 | 455 | ||
@@ -453,6 +472,8 @@ static NOINLINE void attach_option( | |||
453 | /* actually 255 is ok too, but adding a space can overlow it */ | 472 | /* actually 255 is ok too, but adding a space can overlow it */ |
454 | 473 | ||
455 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); | 474 | existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); |
475 | // So far dhcp_optflags[] has no OPTION_STRING[_HOST] | OPTION_LIST items | ||
476 | #if 0 | ||
456 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING | 477 | if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING |
457 | || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST | 478 | || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST |
458 | ) { | 479 | ) { |
@@ -460,7 +481,9 @@ static NOINLINE void attach_option( | |||
460 | existing->data[OPT_DATA + old_len] = ' '; | 481 | existing->data[OPT_DATA + old_len] = ' '; |
461 | old_len++; | 482 | old_len++; |
462 | } | 483 | } |
463 | memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length); | 484 | #endif |
485 | |||
486 | memcpy(existing->data + OPT_DATA + old_len, buffer, length); | ||
464 | existing->data[OPT_LEN] = old_len + length; | 487 | existing->data[OPT_LEN] = old_len + length; |
465 | } /* else, ignore the data, we could put this in a second option in the future */ | 488 | } /* else, ignore the data, we could put this in a second option in the future */ |
466 | } /* else, ignore the new data */ | 489 | } /* else, ignore the new data */ |
@@ -534,7 +557,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, | |||
534 | if (retval) | 557 | if (retval) |
535 | retval = udhcp_str2nip(val, buffer + 4); | 558 | retval = udhcp_str2nip(val, buffer + 4); |
536 | break; | 559 | break; |
537 | case_OPTION_STRING: | 560 | case_OPTION_STRING: |
538 | case OPTION_STRING: | 561 | case OPTION_STRING: |
539 | case OPTION_STRING_HOST: | 562 | case OPTION_STRING_HOST: |
540 | #if ENABLE_FEATURE_UDHCP_RFC3397 | 563 | #if ENABLE_FEATURE_UDHCP_RFC3397 |