diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-20 21:37:23 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-20 21:37:23 +0200 |
| commit | b3af65b95de883e9be403e065f57b867d8ea8d43 (patch) | |
| tree | de97dc31567c54d53848be8d136eeb19e71c8085 | |
| parent | 2c3b71a0d2e6e94d8fb75c6879b1b8203cea9e5a (diff) | |
| download | busybox-w32-b3af65b95de883e9be403e065f57b867d8ea8d43.tar.gz busybox-w32-b3af65b95de883e9be403e065f57b867d8ea8d43.tar.bz2 busybox-w32-b3af65b95de883e9be403e065f57b867d8ea8d43.zip | |
udhcpc: emit maxsize option in all non-NAK type packets
Before, we were sending them only in DISCOVER packets.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/udhcp/dhcpc.c | 108 |
1 files changed, 90 insertions, 18 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 9713e817e..f685a1d22 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
| @@ -346,31 +346,34 @@ static ALWAYS_INLINE uint32_t random_xid(void) | |||
| 346 | /* Initialize the packet with the proper defaults */ | 346 | /* Initialize the packet with the proper defaults */ |
| 347 | static void init_packet(struct dhcp_packet *packet, char type) | 347 | static void init_packet(struct dhcp_packet *packet, char type) |
| 348 | { | 348 | { |
| 349 | /* Fill in: op, htype, hlen, cookie fields; message type option: */ | ||
| 349 | udhcp_init_header(packet, type); | 350 | udhcp_init_header(packet, type); |
| 351 | |||
| 352 | packet->xid = random_xid(); | ||
| 353 | |||
| 350 | memcpy(packet->chaddr, client_config.client_mac, 6); | 354 | memcpy(packet->chaddr, client_config.client_mac, 6); |
| 351 | if (client_config.clientid) | 355 | if (client_config.clientid) |
| 352 | udhcp_add_binary_option(packet, client_config.clientid); | 356 | udhcp_add_binary_option(packet, client_config.clientid); |
| 357 | } | ||
| 358 | |||
| 359 | static void add_client_options(struct dhcp_packet *packet) | ||
| 360 | { | ||
| 361 | uint8_t c; | ||
| 362 | int i, end, len; | ||
| 363 | |||
| 364 | udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE)); | ||
| 353 | if (client_config.hostname) | 365 | if (client_config.hostname) |
| 354 | udhcp_add_binary_option(packet, client_config.hostname); | 366 | udhcp_add_binary_option(packet, client_config.hostname); |
| 355 | if (client_config.fqdn) | 367 | if (client_config.fqdn) |
| 356 | udhcp_add_binary_option(packet, client_config.fqdn); | 368 | udhcp_add_binary_option(packet, client_config.fqdn); |
| 357 | if (type != DHCPDECLINE | 369 | if (client_config.vendorclass) |
| 358 | && type != DHCPRELEASE | ||
| 359 | && client_config.vendorclass | ||
| 360 | ) { | ||
| 361 | udhcp_add_binary_option(packet, client_config.vendorclass); | 370 | udhcp_add_binary_option(packet, client_config.vendorclass); |
| 362 | } | ||
| 363 | } | ||
| 364 | 371 | ||
| 365 | static void add_client_options(struct dhcp_packet *packet) | ||
| 366 | { | ||
| 367 | /* Add a "param req" option with the list of options we'd like to have | 372 | /* Add a "param req" option with the list of options we'd like to have |
| 368 | * from stubborn DHCP servers. Pull the data from the struct in common.c. | 373 | * from stubborn DHCP servers. Pull the data from the struct in common.c. |
| 369 | * No bounds checking because it goes towards the head of the packet. */ | 374 | * No bounds checking because it goes towards the head of the packet. */ |
| 370 | uint8_t c; | 375 | end = udhcp_end_option(packet->options); |
| 371 | int end = udhcp_end_option(packet->options); | 376 | len = 0; |
| 372 | int i, len = 0; | ||
| 373 | |||
| 374 | for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { | 377 | for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { |
| 375 | if (( (dhcp_optflags[i].flags & OPTION_REQ) | 378 | if (( (dhcp_optflags[i].flags & OPTION_REQ) |
| 376 | && !client_config.no_default_options | 379 | && !client_config.no_default_options |
| @@ -432,13 +435,20 @@ static int send_discover(uint32_t xid, uint32_t requested) | |||
| 432 | { | 435 | { |
| 433 | struct dhcp_packet packet; | 436 | struct dhcp_packet packet; |
| 434 | 437 | ||
| 438 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | ||
| 439 | * random xid field (we override it below), | ||
| 440 | * client-id option (unless -C), message type option: | ||
| 441 | */ | ||
| 435 | init_packet(&packet, DHCPDISCOVER); | 442 | init_packet(&packet, DHCPDISCOVER); |
| 443 | |||
| 436 | packet.xid = xid; | 444 | packet.xid = xid; |
| 437 | if (requested) | 445 | if (requested) |
| 438 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 446 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
| 439 | /* Explicitly saying that we want RFC-compliant packets helps | 447 | |
| 440 | * some buggy DHCP servers to NOT send bigger packets */ | 448 | /* Add options: maxsize, |
| 441 | udhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576)); | 449 | * optionally: hostname, fqdn, vendorclass, |
| 450 | * "param req" option according to -O, options specified with -x | ||
| 451 | */ | ||
| 442 | add_client_options(&packet); | 452 | add_client_options(&packet); |
| 443 | 453 | ||
| 444 | bb_info_msg("Sending discover..."); | 454 | bb_info_msg("Sending discover..."); |
| @@ -454,10 +464,33 @@ static int send_select(uint32_t xid, uint32_t server, uint32_t requested) | |||
| 454 | struct dhcp_packet packet; | 464 | struct dhcp_packet packet; |
| 455 | struct in_addr addr; | 465 | struct in_addr addr; |
| 456 | 466 | ||
| 467 | /* | ||
| 468 | * RFC 2131 4.3.2 DHCPREQUEST message | ||
| 469 | * ... | ||
| 470 | * If the DHCPREQUEST message contains a 'server identifier' | ||
| 471 | * option, the message is in response to a DHCPOFFER message. | ||
| 472 | * Otherwise, the message is a request to verify or extend an | ||
| 473 | * existing lease. If the client uses a 'client identifier' | ||
| 474 | * in a DHCPREQUEST message, it MUST use that same 'client identifier' | ||
| 475 | * in all subsequent messages. If the client included a list | ||
| 476 | * of requested parameters in a DHCPDISCOVER message, it MUST | ||
| 477 | * include that list in all subsequent messages. | ||
| 478 | */ | ||
| 479 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | ||
| 480 | * random xid field (we override it below), | ||
| 481 | * client-id option (unless -C), message type option: | ||
| 482 | */ | ||
| 457 | init_packet(&packet, DHCPREQUEST); | 483 | init_packet(&packet, DHCPREQUEST); |
| 484 | |||
| 458 | packet.xid = xid; | 485 | packet.xid = xid; |
| 459 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 486 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
| 487 | |||
| 460 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 488 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
| 489 | |||
| 490 | /* Add options: maxsize, | ||
| 491 | * optionally: hostname, fqdn, vendorclass, | ||
| 492 | * "param req" option according to -O, and options specified with -x | ||
| 493 | */ | ||
| 461 | add_client_options(&packet); | 494 | add_client_options(&packet); |
| 462 | 495 | ||
| 463 | addr.s_addr = requested; | 496 | addr.s_addr = requested; |
| @@ -470,9 +503,33 @@ static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) | |||
| 470 | { | 503 | { |
| 471 | struct dhcp_packet packet; | 504 | struct dhcp_packet packet; |
| 472 | 505 | ||
| 506 | /* | ||
| 507 | * RFC 2131 4.3.2 DHCPREQUEST message | ||
| 508 | * ... | ||
| 509 | * DHCPREQUEST generated during RENEWING state: | ||
| 510 | * | ||
| 511 | * 'server identifier' MUST NOT be filled in, 'requested IP address' | ||
| 512 | * option MUST NOT be filled in, 'ciaddr' MUST be filled in with | ||
| 513 | * client's IP address. In this situation, the client is completely | ||
| 514 | * configured, and is trying to extend its lease. This message will | ||
| 515 | * be unicast, so no relay agents will be involved in its | ||
| 516 | * transmission. Because 'giaddr' is therefore not filled in, the | ||
| 517 | * DHCP server will trust the value in 'ciaddr', and use it when | ||
| 518 | * replying to the client. | ||
| 519 | */ | ||
| 520 | /* Fill in: op, htype, hlen, cookie, chaddr fields, | ||
| 521 | * random xid field (we override it below), | ||
| 522 | * client-id option (unless -C), message type option: | ||
| 523 | */ | ||
| 473 | init_packet(&packet, DHCPREQUEST); | 524 | init_packet(&packet, DHCPREQUEST); |
| 525 | |||
| 474 | packet.xid = xid; | 526 | packet.xid = xid; |
| 475 | packet.ciaddr = ciaddr; | 527 | packet.ciaddr = ciaddr; |
| 528 | |||
| 529 | /* Add options: maxsize, | ||
| 530 | * optionally: hostname, fqdn, vendorclass, | ||
| 531 | * "param req" option according to -O, and options specified with -x | ||
| 532 | */ | ||
| 476 | add_client_options(&packet); | 533 | add_client_options(&packet); |
| 477 | 534 | ||
| 478 | bb_info_msg("Sending renew..."); | 535 | bb_info_msg("Sending renew..."); |
| @@ -489,9 +546,20 @@ static int send_decline(uint32_t xid, uint32_t server, uint32_t requested) | |||
| 489 | { | 546 | { |
| 490 | struct dhcp_packet packet; | 547 | struct dhcp_packet packet; |
| 491 | 548 | ||
| 549 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | ||
| 550 | * client-id option (unless -C), message type option: | ||
| 551 | */ | ||
| 492 | init_packet(&packet, DHCPDECLINE); | 552 | init_packet(&packet, DHCPDECLINE); |
| 553 | |||
| 554 | /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, | ||
| 555 | * but in case the server is buggy and wants DHCPDECLINE's xid | ||
| 556 | * to match the xid which started entire handshake, | ||
| 557 | * we use the same xid we used in initial DHCPDISCOVER: | ||
| 558 | */ | ||
| 493 | packet.xid = xid; | 559 | packet.xid = xid; |
| 560 | /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ | ||
| 494 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); | 561 | udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); |
| 562 | |||
| 495 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 563 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
| 496 | 564 | ||
| 497 | bb_info_msg("Sending decline..."); | 565 | bb_info_msg("Sending decline..."); |
| @@ -504,8 +572,12 @@ static int send_release(uint32_t server, uint32_t ciaddr) | |||
| 504 | { | 572 | { |
| 505 | struct dhcp_packet packet; | 573 | struct dhcp_packet packet; |
| 506 | 574 | ||
| 575 | /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, | ||
| 576 | * client-id option (unless -C), message type option: | ||
| 577 | */ | ||
| 507 | init_packet(&packet, DHCPRELEASE); | 578 | init_packet(&packet, DHCPRELEASE); |
| 508 | packet.xid = random_xid(); | 579 | |
| 580 | /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */ | ||
| 509 | packet.ciaddr = ciaddr; | 581 | packet.ciaddr = ciaddr; |
| 510 | 582 | ||
| 511 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); | 583 | udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); |
| @@ -1254,7 +1326,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
| 1254 | 1326 | ||
| 1255 | /* Ignore packets that aren't for us */ | 1327 | /* Ignore packets that aren't for us */ |
| 1256 | if (packet.hlen != 6 | 1328 | if (packet.hlen != 6 |
| 1257 | || memcmp(packet.chaddr, client_config.client_mac, 6) | 1329 | || memcmp(packet.chaddr, client_config.client_mac, 6) != 0 |
| 1258 | ) { | 1330 | ) { |
| 1259 | //FIXME: need to also check that last 10 bytes are zero | 1331 | //FIXME: need to also check that last 10 bytes are zero |
| 1260 | log1("chaddr does not match, ignoring packet"); // log2? | 1332 | log1("chaddr does not match, ignoring packet"); // log2? |
| @@ -1280,7 +1352,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
| 1280 | } | 1352 | } |
| 1281 | /* it IS unaligned sometimes, don't "optimize" */ | 1353 | /* it IS unaligned sometimes, don't "optimize" */ |
| 1282 | move_from_unaligned32(server_addr, temp); | 1354 | move_from_unaligned32(server_addr, temp); |
| 1283 | xid = packet.xid; | 1355 | /*xid = packet.xid; - already is */ |
| 1284 | requested_ip = packet.yiaddr; | 1356 | requested_ip = packet.yiaddr; |
| 1285 | 1357 | ||
| 1286 | /* enter requesting state */ | 1358 | /* enter requesting state */ |
