summaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:52:10 +0700
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:52:10 +0700
commit8cef222175855ae08f3768a5586b00650240403d (patch)
tree224364dc08e460fea425df95fc45e1cbc9bbbd96 /networking
parent9fab97cbb70312170739e29a5fbbbe072f07bb78 (diff)
parentcbfeaac7afe31323d46c52da3b98a949232d708e (diff)
downloadbusybox-w32-8cef222175855ae08f3768a5586b00650240403d.tar.gz
busybox-w32-8cef222175855ae08f3768a5586b00650240403d.tar.bz2
busybox-w32-8cef222175855ae08f3768a5586b00650240403d.zip
Merge commit '6722737ece4b8db3e30b53aef8f981f53db1621e^'
Diffstat (limited to 'networking')
-rw-r--r--networking/nbd-client.c2
-rw-r--r--networking/ntpd.c10
-rw-r--r--networking/udhcp/common.c7
-rw-r--r--networking/udhcp/common.h6
-rw-r--r--networking/udhcp/dhcpc.c294
-rw-r--r--networking/udhcp/dhcpd.c12
-rw-r--r--networking/udhcp/packet.c8
7 files changed, 261 insertions, 78 deletions
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index 5ac190c32..8b856eda7 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -46,7 +46,9 @@ int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
46int nbdclient_main(int argc, char **argv) 46int nbdclient_main(int argc, char **argv)
47{ 47{
48 unsigned long timeout = 0; 48 unsigned long timeout = 0;
49#if BB_MMU
49 int nofork = 0; 50 int nofork = 0;
51#endif
50 char *host, *port, *device; 52 char *host, *port, *device;
51 struct nbd_header_t { 53 struct nbd_header_t {
52 uint64_t magic1; // "NBDMAGIC" 54 uint64_t magic1; // "NBDMAGIC"
diff --git a/networking/ntpd.c b/networking/ntpd.c
index ca4afa045..b7bd239b5 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -49,7 +49,7 @@
49/* High-level description of the algorithm: 49/* High-level description of the algorithm:
50 * 50 *
51 * We start running with very small poll_exp, BURSTPOLL, 51 * We start running with very small poll_exp, BURSTPOLL,
52 * in order to quickly accumulate INITIAL_SAMLPES datapoints 52 * in order to quickly accumulate INITIAL_SAMPLES datapoints
53 * for each peer. Then, time is stepped if the offset is larger 53 * for each peer. Then, time is stepped if the offset is larger
54 * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge 54 * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge
55 * poll_exp to MINPOLL and enter frequency measurement step: 55 * poll_exp to MINPOLL and enter frequency measurement step:
@@ -77,7 +77,7 @@
77 77
78#define RETRY_INTERVAL 5 /* on error, retry in N secs */ 78#define RETRY_INTERVAL 5 /* on error, retry in N secs */
79#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ 79#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */
80#define INITIAL_SAMLPES 4 /* how many samples do we want for init */ 80#define INITIAL_SAMPLES 4 /* how many samples do we want for init */
81 81
82/* Clock discipline parameters and constants */ 82/* Clock discipline parameters and constants */
83 83
@@ -1972,14 +1972,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1972 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt); 1972 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt);
1973 pfd = xzalloc(sizeof(pfd[0]) * cnt); 1973 pfd = xzalloc(sizeof(pfd[0]) * cnt);
1974 1974
1975 /* Countdown: we never sync before we sent INITIAL_SAMLPES+1 1975 /* Countdown: we never sync before we sent INITIAL_SAMPLES+1
1976 * packets to each peer. 1976 * packets to each peer.
1977 * NB: if some peer is not responding, we may end up sending 1977 * NB: if some peer is not responding, we may end up sending
1978 * fewer packets to it and more to other peers. 1978 * fewer packets to it and more to other peers.
1979 * NB2: sync usually happens using INITIAL_SAMLPES packets, 1979 * NB2: sync usually happens using INITIAL_SAMPLES packets,
1980 * since last reply does not come back instantaneously. 1980 * since last reply does not come back instantaneously.
1981 */ 1981 */
1982 cnt = G.peer_cnt * (INITIAL_SAMLPES + 1); 1982 cnt = G.peer_cnt * (INITIAL_SAMPLES + 1);
1983 1983
1984 while (!bb_got_signal) { 1984 while (!bb_got_signal) {
1985 llist_t *item; 1985 llist_t *item;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index b6b274d91..311f79e7e 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -68,9 +68,10 @@ const struct dhcp_optflag dhcp_optflags[] = {
68 { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */ 68 { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */
69 { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */ 69 { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */
70 { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */ 70 { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */
71 { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */ 71//looks like these opts will work just fine even without these defs:
72//FIXME: handling of this option is not exactly correct: 72// { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */
73 { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */ 73// /* not really a string: */
74// { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */
74 { 0, 0 } /* zeroed terminating entry */ 75 { 0, 0 } /* zeroed terminating entry */
75}; 76};
76 77
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 9020b9c96..f8f18ff01 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -63,14 +63,14 @@ struct udp_dhcp_packet {
63} PACKED; 63} PACKED;
64 64
65enum { 65enum {
66 IP_UPD_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 66 IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
67 UPD_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 67 UDP_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
68 DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 68 DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
69}; 69};
70 70
71/* Let's see whether compiler understood us right */ 71/* Let's see whether compiler understood us right */
72struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { 72struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet {
73 char c[IP_UPD_DHCP_SIZE == 576 ? 1 : -1]; 73 char c[IP_UDP_DHCP_SIZE == 576 ? 1 : -1];
74}; 74};
75 75
76 76
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 27d6ad1a8..78aabedf2 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -346,31 +346,28 @@ static ALWAYS_INLINE uint32_t random_xid(void)
346/* Initialize the packet with the proper defaults */ 346/* Initialize the packet with the proper defaults */
347static void init_packet(struct dhcp_packet *packet, char type) 347static 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);
353 if (client_config.hostname)
354 udhcp_add_binary_option(packet, client_config.hostname);
355 if (client_config.fqdn)
356 udhcp_add_binary_option(packet, client_config.fqdn);
357 if (type != DHCPDECLINE
358 && type != DHCPRELEASE
359 && client_config.vendorclass
360 ) {
361 udhcp_add_binary_option(packet, client_config.vendorclass);
362 }
363} 357}
364 358
365static void add_client_options(struct dhcp_packet *packet) 359static void add_client_options(struct dhcp_packet *packet)
366{ 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));
365
367 /* Add a "param req" option with the list of options we'd like to have 366 /* 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. 367 * 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. */ 368 * No bounds checking because it goes towards the head of the packet. */
370 uint8_t c; 369 end = udhcp_end_option(packet->options);
371 int end = udhcp_end_option(packet->options); 370 len = 0;
372 int i, len = 0;
373
374 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { 371 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) {
375 if (( (dhcp_optflags[i].flags & OPTION_REQ) 372 if (( (dhcp_optflags[i].flags & OPTION_REQ)
376 && !client_config.no_default_options 373 && !client_config.no_default_options
@@ -387,6 +384,13 @@ static void add_client_options(struct dhcp_packet *packet)
387 packet->options[end + OPT_DATA + len] = DHCP_END; 384 packet->options[end + OPT_DATA + len] = DHCP_END;
388 } 385 }
389 386
387 if (client_config.vendorclass)
388 udhcp_add_binary_option(packet, client_config.vendorclass);
389 if (client_config.hostname)
390 udhcp_add_binary_option(packet, client_config.hostname);
391 if (client_config.fqdn)
392 udhcp_add_binary_option(packet, client_config.fqdn);
393
390 /* Add -x options if any */ 394 /* Add -x options if any */
391 { 395 {
392 struct option_set *curr = client_config.options; 396 struct option_set *curr = client_config.options;
@@ -428,17 +432,25 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet)
428} 432}
429 433
430/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 434/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
431static int send_discover(uint32_t xid, uint32_t requested) 435/* NOINLINE: limit stack usage in caller */
436static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
432{ 437{
433 struct dhcp_packet packet; 438 struct dhcp_packet packet;
434 439
440 /* Fill in: op, htype, hlen, cookie, chaddr fields,
441 * random xid field (we override it below),
442 * client-id option (unless -C), message type option:
443 */
435 init_packet(&packet, DHCPDISCOVER); 444 init_packet(&packet, DHCPDISCOVER);
445
436 packet.xid = xid; 446 packet.xid = xid;
437 if (requested) 447 if (requested)
438 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 448 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
439 /* Explicitly saying that we want RFC-compliant packets helps 449
440 * some buggy DHCP servers to NOT send bigger packets */ 450 /* Add options: maxsize,
441 udhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576)); 451 * optionally: hostname, fqdn, vendorclass,
452 * "param req" option according to -O, options specified with -x
453 */
442 add_client_options(&packet); 454 add_client_options(&packet);
443 455
444 bb_info_msg("Sending discover..."); 456 bb_info_msg("Sending discover...");
@@ -449,15 +461,39 @@ static int send_discover(uint32_t xid, uint32_t requested)
449/* RFC 2131 3.1 paragraph 3: 461/* RFC 2131 3.1 paragraph 3:
450 * "The client _broadcasts_ a DHCPREQUEST message..." 462 * "The client _broadcasts_ a DHCPREQUEST message..."
451 */ 463 */
452static int send_select(uint32_t xid, uint32_t server, uint32_t requested) 464/* NOINLINE: limit stack usage in caller */
465static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested)
453{ 466{
454 struct dhcp_packet packet; 467 struct dhcp_packet packet;
455 struct in_addr addr; 468 struct in_addr addr;
456 469
470/*
471 * RFC 2131 4.3.2 DHCPREQUEST message
472 * ...
473 * If the DHCPREQUEST message contains a 'server identifier'
474 * option, the message is in response to a DHCPOFFER message.
475 * Otherwise, the message is a request to verify or extend an
476 * existing lease. If the client uses a 'client identifier'
477 * in a DHCPREQUEST message, it MUST use that same 'client identifier'
478 * in all subsequent messages. If the client included a list
479 * of requested parameters in a DHCPDISCOVER message, it MUST
480 * include that list in all subsequent messages.
481 */
482 /* Fill in: op, htype, hlen, cookie, chaddr fields,
483 * random xid field (we override it below),
484 * client-id option (unless -C), message type option:
485 */
457 init_packet(&packet, DHCPREQUEST); 486 init_packet(&packet, DHCPREQUEST);
487
458 packet.xid = xid; 488 packet.xid = xid;
459 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 489 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
490
460 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 491 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
492
493 /* Add options: maxsize,
494 * optionally: hostname, fqdn, vendorclass,
495 * "param req" option according to -O, and options specified with -x
496 */
461 add_client_options(&packet); 497 add_client_options(&packet);
462 498
463 addr.s_addr = requested; 499 addr.s_addr = requested;
@@ -466,13 +502,38 @@ static int send_select(uint32_t xid, uint32_t server, uint32_t requested)
466} 502}
467 503
468/* Unicast or broadcast a DHCP renew message */ 504/* Unicast or broadcast a DHCP renew message */
469static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 505/* NOINLINE: limit stack usage in caller */
506static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
470{ 507{
471 struct dhcp_packet packet; 508 struct dhcp_packet packet;
472 509
510/*
511 * RFC 2131 4.3.2 DHCPREQUEST message
512 * ...
513 * DHCPREQUEST generated during RENEWING state:
514 *
515 * 'server identifier' MUST NOT be filled in, 'requested IP address'
516 * option MUST NOT be filled in, 'ciaddr' MUST be filled in with
517 * client's IP address. In this situation, the client is completely
518 * configured, and is trying to extend its lease. This message will
519 * be unicast, so no relay agents will be involved in its
520 * transmission. Because 'giaddr' is therefore not filled in, the
521 * DHCP server will trust the value in 'ciaddr', and use it when
522 * replying to the client.
523 */
524 /* Fill in: op, htype, hlen, cookie, chaddr fields,
525 * random xid field (we override it below),
526 * client-id option (unless -C), message type option:
527 */
473 init_packet(&packet, DHCPREQUEST); 528 init_packet(&packet, DHCPREQUEST);
529
474 packet.xid = xid; 530 packet.xid = xid;
475 packet.ciaddr = ciaddr; 531 packet.ciaddr = ciaddr;
532
533 /* Add options: maxsize,
534 * optionally: hostname, fqdn, vendorclass,
535 * "param req" option according to -O, and options specified with -x
536 */
476 add_client_options(&packet); 537 add_client_options(&packet);
477 538
478 bb_info_msg("Sending renew..."); 539 bb_info_msg("Sending renew...");
@@ -485,13 +546,25 @@ static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
485 546
486#if ENABLE_FEATURE_UDHCPC_ARPING 547#if ENABLE_FEATURE_UDHCPC_ARPING
487/* Broadcast a DHCP decline message */ 548/* Broadcast a DHCP decline message */
488static int send_decline(uint32_t xid, uint32_t server, uint32_t requested) 549/* NOINLINE: limit stack usage in caller */
550static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t requested)
489{ 551{
490 struct dhcp_packet packet; 552 struct dhcp_packet packet;
491 553
554 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
555 * client-id option (unless -C), message type option:
556 */
492 init_packet(&packet, DHCPDECLINE); 557 init_packet(&packet, DHCPDECLINE);
558
559 /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client,
560 * but in case the server is buggy and wants DHCPDECLINE's xid
561 * to match the xid which started entire handshake,
562 * we use the same xid we used in initial DHCPDISCOVER:
563 */
493 packet.xid = xid; 564 packet.xid = xid;
565 /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */
494 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 566 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
567
495 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 568 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
496 569
497 bb_info_msg("Sending decline..."); 570 bb_info_msg("Sending decline...");
@@ -504,8 +577,12 @@ static int send_release(uint32_t server, uint32_t ciaddr)
504{ 577{
505 struct dhcp_packet packet; 578 struct dhcp_packet packet;
506 579
580 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
581 * client-id option (unless -C), message type option:
582 */
507 init_packet(&packet, DHCPRELEASE); 583 init_packet(&packet, DHCPRELEASE);
508 packet.xid = random_xid(); 584
585 /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */
509 packet.ciaddr = ciaddr; 586 packet.ciaddr = ciaddr;
510 587
511 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 588 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
@@ -515,6 +592,7 @@ static int send_release(uint32_t server, uint32_t ciaddr)
515} 592}
516 593
517/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ 594/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
595/* NOINLINE: limit stack usage in caller */
518static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) 596static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
519{ 597{
520 int bytes; 598 int bytes;
@@ -765,12 +843,97 @@ static void client_background(void)
765} 843}
766#endif 844#endif
767 845
846//usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
847//usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
848//usage:#else
849//usage:# define IF_UDHCP_VERBOSE(...)
850//usage:#endif
851//usage:#define udhcpc_trivial_usage
852//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
853//usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
854//usage:#define udhcpc_full_usage "\n"
855//usage: IF_LONG_OPTS(
856//usage: "\n -i,--interface IFACE Interface to use (default eth0)"
857//usage: "\n -p,--pidfile FILE Create pidfile"
858//usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
859//usage: "\n -t,--retries N Send up to N discover packets"
860//usage: "\n -T,--timeout N Pause between packets (default 3 seconds)"
861//usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)"
862//usage: "\n -f,--foreground Run in foreground"
863//usage: USE_FOR_MMU(
864//usage: "\n -b,--background Background if lease is not obtained"
865//usage: )
866//usage: "\n -n,--now Exit if lease is not obtained"
867//usage: "\n -q,--quit Exit after obtaining lease"
868//usage: "\n -R,--release Release IP on exit"
869//usage: "\n -S,--syslog Log to syslog too"
870//usage: IF_FEATURE_UDHCP_PORT(
871//usage: "\n -P,--client-port N Use port N (default 68)"
872//usage: )
873//usage: IF_FEATURE_UDHCPC_ARPING(
874//usage: "\n -a,--arping Use arping to validate offered address"
875//usage: )
876//usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)"
877//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)"
878//usage: "\n -r,--request IP Request this IP address"
879//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
880//usage: "\n Examples of string, numeric, and hex byte opts:"
881//usage: "\n -x hostname:bbox - option 12"
882//usage: "\n -x lease:3600 - option 51 (lease time)"
883//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
884//usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME"
885//usage: "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)"
886//usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')"
887//usage: "\n -C,--clientid-none Don't send MAC as client identifier"
888//usage: IF_UDHCP_VERBOSE(
889//usage: "\n -v Verbose"
890//usage: )
891//usage: )
892//usage: IF_NOT_LONG_OPTS(
893//usage: "\n -i IFACE Interface to use (default eth0)"
894//usage: "\n -p FILE Create pidfile"
895//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
896//usage: "\n -t N Send up to N discover packets"
897//usage: "\n -T N Pause between packets (default 3 seconds)"
898//usage: "\n -A N Wait N seconds (default 20) after failure"
899//usage: "\n -f Run in foreground"
900//usage: USE_FOR_MMU(
901//usage: "\n -b Background if lease is not obtained"
902//usage: )
903//usage: "\n -n Exit if lease is not obtained"
904//usage: "\n -q Exit after obtaining lease"
905//usage: "\n -R Release IP on exit"
906//usage: "\n -S Log to syslog too"
907//usage: IF_FEATURE_UDHCP_PORT(
908//usage: "\n -P N Use port N (default 68)"
909//usage: )
910//usage: IF_FEATURE_UDHCPC_ARPING(
911//usage: "\n -a Use arping to validate offered address"
912//usage: )
913//usage: "\n -O OPT Request option OPT from server (cumulative)"
914//usage: "\n -o Don't request any options (unless -O is given)"
915//usage: "\n -r IP Request this IP address"
916//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
917//usage: "\n Examples of string, numeric, and hex byte opts:"
918//usage: "\n -x hostname:bbox - option 12"
919//usage: "\n -x lease:3600 - option 51 (lease time)"
920//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
921//usage: "\n -F NAME Ask server to update DNS mapping for NAME"
922//usage: "\n -H,-h NAME Send NAME as client hostname (default none)"
923//usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')"
924//usage: "\n -C Don't send MAC as client identifier"
925//usage: IF_UDHCP_VERBOSE(
926//usage: "\n -v Verbose"
927//usage: )
928//usage: )
929
768int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 930int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
769int udhcpc_main(int argc UNUSED_PARAM, char **argv) 931int udhcpc_main(int argc UNUSED_PARAM, char **argv)
770{ 932{
771 uint8_t *temp, *message; 933 uint8_t *temp, *message;
772 const char *str_c, *str_V, *str_h, *str_F, *str_r; 934 const char *str_V, *str_h, *str_F, *str_r;
773 IF_FEATURE_UDHCP_PORT(char *str_P;) 935 IF_FEATURE_UDHCP_PORT(char *str_P;)
936 void *clientid_mac_ptr;
774 llist_t *list_O = NULL; 937 llist_t *list_O = NULL;
775 llist_t *list_x = NULL; 938 llist_t *list_x = NULL;
776 int tryagain_timeout = 20; 939 int tryagain_timeout = 20;
@@ -792,7 +955,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
792 955
793#if ENABLE_LONG_OPTS 956#if ENABLE_LONG_OPTS
794 static const char udhcpc_longopts[] ALIGN1 = 957 static const char udhcpc_longopts[] ALIGN1 =
795 "clientid\0" Required_argument "c"
796 "clientid-none\0" No_argument "C" 958 "clientid-none\0" No_argument "C"
797 "vendorclass\0" Required_argument "V" 959 "vendorclass\0" Required_argument "V"
798 "hostname\0" Required_argument "H" 960 "hostname\0" Required_argument "H"
@@ -818,29 +980,28 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
818 ; 980 ;
819#endif 981#endif
820 enum { 982 enum {
821 OPT_c = 1 << 0, 983 OPT_C = 1 << 0,
822 OPT_C = 1 << 1, 984 OPT_V = 1 << 1,
823 OPT_V = 1 << 2, 985 OPT_H = 1 << 2,
824 OPT_H = 1 << 3, 986 OPT_h = 1 << 3,
825 OPT_h = 1 << 4, 987 OPT_F = 1 << 4,
826 OPT_F = 1 << 5, 988 OPT_i = 1 << 5,
827 OPT_i = 1 << 6, 989 OPT_n = 1 << 6,
828 OPT_n = 1 << 7, 990 OPT_p = 1 << 7,
829 OPT_p = 1 << 8, 991 OPT_q = 1 << 8,
830 OPT_q = 1 << 9, 992 OPT_R = 1 << 9,
831 OPT_R = 1 << 10, 993 OPT_r = 1 << 10,
832 OPT_r = 1 << 11, 994 OPT_s = 1 << 11,
833 OPT_s = 1 << 12, 995 OPT_T = 1 << 12,
834 OPT_T = 1 << 13, 996 OPT_t = 1 << 13,
835 OPT_t = 1 << 14, 997 OPT_S = 1 << 14,
836 OPT_S = 1 << 15, 998 OPT_A = 1 << 15,
837 OPT_A = 1 << 16, 999 OPT_O = 1 << 16,
838 OPT_O = 1 << 17, 1000 OPT_o = 1 << 17,
839 OPT_o = 1 << 18, 1001 OPT_x = 1 << 18,
840 OPT_x = 1 << 19, 1002 OPT_f = 1 << 19,
841 OPT_f = 1 << 20,
842/* The rest has variable bit positions, need to be clever */ 1003/* The rest has variable bit positions, need to be clever */
843 OPTBIT_f = 20, 1004 OPTBIT_f = 19,
844 USE_FOR_MMU( OPTBIT_b,) 1005 USE_FOR_MMU( OPTBIT_b,)
845 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 1006 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
846 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 1007 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
@@ -849,7 +1010,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
849 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 1010 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
850 }; 1011 };
851 1012
852 /* Default options. */ 1013 /* Default options */
853 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) 1014 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
854 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) 1015 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
855 client_config.interface = "eth0"; 1016 client_config.interface = "eth0";
@@ -857,19 +1018,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
857 str_V = "udhcp "BB_VER; 1018 str_V = "udhcp "BB_VER;
858 1019
859 /* Parse command line */ 1020 /* Parse command line */
860 /* Cc: mutually exclusive; O,x: list; -T,-t,-A take numeric param */ 1021 /* O,x: list; -T,-t,-A take numeric param */
861 opt_complementary = "c--C:C--c:O::x::T+:t+:A+" 1022 opt_complementary = "O::x::T+:t+:A+"
862#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1023#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
863 ":vv" 1024 ":vv"
864#endif 1025#endif
865 ; 1026 ;
866 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1027 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
867 opt = getopt32(argv, "c:CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f" 1028 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f"
868 USE_FOR_MMU("b") 1029 USE_FOR_MMU("b")
869 IF_FEATURE_UDHCPC_ARPING("a") 1030 IF_FEATURE_UDHCPC_ARPING("a")
870 IF_FEATURE_UDHCP_PORT("P:") 1031 IF_FEATURE_UDHCP_PORT("P:")
871 "v" 1032 "v"
872 , &str_c, &str_V, &str_h, &str_h, &str_F 1033 , &str_V, &str_h, &str_h, &str_F
873 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */ 1034 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */
874 , &client_config.script /* s */ 1035 , &client_config.script /* s */
875 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ 1036 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
@@ -931,13 +1092,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
931 return 1; 1092 return 1;
932 } 1093 }
933 1094
934 if (opt & OPT_c) { 1095 clientid_mac_ptr = NULL;
935 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0); 1096 if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) {
936 } else if (!(opt & OPT_C)) { 1097 /* not suppressed and not set, set the default client ID */
937 /* not set and not suppressed, set the default client ID */
938 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); 1098 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
939 client_config.clientid[OPT_DATA] = 1; /* type: ethernet */ 1099 client_config.clientid[OPT_DATA] = 1; /* type: ethernet */
940 memcpy(client_config.clientid + OPT_DATA+1, client_config.client_mac, 6); 1100 clientid_mac_ptr = client_config.clientid + OPT_DATA+1;
1101 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
941 } 1102 }
942 if (str_V[0] != '\0') 1103 if (str_V[0] != '\0')
943 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 1104 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
@@ -1015,6 +1176,21 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1015 * resend discover/renew/whatever 1176 * resend discover/renew/whatever
1016 */ 1177 */
1017 if (retval == 0) { 1178 if (retval == 0) {
1179 /* When running on a bridge, the ifindex may have changed
1180 * (e.g. if member interfaces were added/removed
1181 * or if the status of the bridge changed).
1182 * Refresh ifindex and client_mac:
1183 */
1184 if (udhcp_read_interface(client_config.interface,
1185 &client_config.ifindex,
1186 NULL,
1187 client_config.client_mac)
1188 ) {
1189 return 1; /* iface is gone? */
1190 }
1191 if (clientid_mac_ptr)
1192 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1193
1018 /* We will restart the wait in any case */ 1194 /* We will restart the wait in any case */
1019 already_waited_sec = 0; 1195 already_waited_sec = 0;
1020 1196
@@ -1174,7 +1350,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1174 1350
1175 /* Ignore packets that aren't for us */ 1351 /* Ignore packets that aren't for us */
1176 if (packet.hlen != 6 1352 if (packet.hlen != 6
1177 || memcmp(packet.chaddr, client_config.client_mac, 6) 1353 || memcmp(packet.chaddr, client_config.client_mac, 6) != 0
1178 ) { 1354 ) {
1179//FIXME: need to also check that last 10 bytes are zero 1355//FIXME: need to also check that last 10 bytes are zero
1180 log1("chaddr does not match, ignoring packet"); // log2? 1356 log1("chaddr does not match, ignoring packet"); // log2?
@@ -1194,13 +1370,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1194 /* TODO: why we don't just fetch server's IP from IP header? */ 1370 /* TODO: why we don't just fetch server's IP from IP header? */
1195 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1371 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1196 if (!temp) { 1372 if (!temp) {
1197 bb_error_msg("no server ID in message"); 1373 bb_error_msg("no server ID, ignoring packet");
1198 continue; 1374 continue;
1199 /* still selecting - this server looks bad */ 1375 /* still selecting - this server looks bad */
1200 } 1376 }
1201 /* it IS unaligned sometimes, don't "optimize" */ 1377 /* it IS unaligned sometimes, don't "optimize" */
1202 move_from_unaligned32(server_addr, temp); 1378 move_from_unaligned32(server_addr, temp);
1203 xid = packet.xid; 1379 /*xid = packet.xid; - already is */
1204 requested_ip = packet.yiaddr; 1380 requested_ip = packet.yiaddr;
1205 1381
1206 /* enter requesting state */ 1382 /* enter requesting state */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 043220de9..f0878652c 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -132,7 +132,8 @@ static uint32_t select_lease_time(struct dhcp_packet *packet)
132} 132}
133 133
134/* We got a DHCP DISCOVER. Send an OFFER. */ 134/* We got a DHCP DISCOVER. Send an OFFER. */
135static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) 135/* NOINLINE: limit stack usage in caller */
136static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease)
136{ 137{
137 struct dhcp_packet packet; 138 struct dhcp_packet packet;
138 uint32_t lease_time_sec; 139 uint32_t lease_time_sec;
@@ -202,7 +203,8 @@ static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip,
202 send_packet(&packet, /*force_bcast:*/ 0); 203 send_packet(&packet, /*force_bcast:*/ 0);
203} 204}
204 205
205static void send_NAK(struct dhcp_packet *oldpacket) 206/* NOINLINE: limit stack usage in caller */
207static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
206{ 208{
207 struct dhcp_packet packet; 209 struct dhcp_packet packet;
208 210
@@ -212,7 +214,8 @@ static void send_NAK(struct dhcp_packet *oldpacket)
212 send_packet(&packet, /*force_bcast:*/ 1); 214 send_packet(&packet, /*force_bcast:*/ 1);
213} 215}
214 216
215static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) 217/* NOINLINE: limit stack usage in caller */
218static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
216{ 219{
217 struct dhcp_packet packet; 220 struct dhcp_packet packet;
218 uint32_t lease_time_sec; 221 uint32_t lease_time_sec;
@@ -243,7 +246,8 @@ static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
243 } 246 }
244} 247}
245 248
246static void send_inform(struct dhcp_packet *oldpacket) 249/* NOINLINE: limit stack usage in caller */
250static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
247{ 251{
248 struct dhcp_packet packet; 252 struct dhcp_packet packet;
249 253
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index d8f9c5daa..2b7528cc7 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -216,19 +216,19 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
216 packet.udp.source = htons(source_port); 216 packet.udp.source = htons(source_port);
217 packet.udp.dest = htons(dest_port); 217 packet.udp.dest = htons(dest_port);
218 /* size, excluding IP header: */ 218 /* size, excluding IP header: */
219 packet.udp.len = htons(UPD_DHCP_SIZE - padding); 219 packet.udp.len = htons(UDP_DHCP_SIZE - padding);
220 /* for UDP checksumming, ip.len is set to UDP packet len */ 220 /* for UDP checksumming, ip.len is set to UDP packet len */
221 packet.ip.tot_len = packet.udp.len; 221 packet.ip.tot_len = packet.udp.len;
222 packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE - padding); 222 packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding);
223 /* but for sending, it is set to IP packet len */ 223 /* but for sending, it is set to IP packet len */
224 packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE - padding); 224 packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
225 packet.ip.ihl = sizeof(packet.ip) >> 2; 225 packet.ip.ihl = sizeof(packet.ip) >> 2;
226 packet.ip.version = IPVERSION; 226 packet.ip.version = IPVERSION;
227 packet.ip.ttl = IPDEFTTL; 227 packet.ip.ttl = IPDEFTTL;
228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); 228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
229 229
230 udhcp_dump_packet(dhcp_pkt); 230 udhcp_dump_packet(dhcp_pkt);
231 result = sendto(fd, &packet, IP_UPD_DHCP_SIZE - padding, /*flags:*/ 0, 231 result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0,
232 (struct sockaddr *) &dest_sll, sizeof(dest_sll)); 232 (struct sockaddr *) &dest_sll, sizeof(dest_sll));
233 msg = "sendto"; 233 msg = "sendto";
234 ret_close: 234 ret_close: