aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEivind Versvik <versvikeivind@gmail.com>2019-08-24 17:23:48 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-08-24 17:24:40 +0200
commit22a633962786a7bc97870ced913fc237143cfd68 (patch)
tree9a00b6a91a22f6c868220d57d3550aa3939a64a6
parentac78f2ac96b3efd6551a08e7dc609efa1fb69481 (diff)
downloadbusybox-w32-22a633962786a7bc97870ced913fc237143cfd68.tar.gz
busybox-w32-22a633962786a7bc97870ced913fc237143cfd68.tar.bz2
busybox-w32-22a633962786a7bc97870ced913fc237143cfd68.zip
udhcpc6: support stateless DHCPv6
-l will send Information-Request to request configuration parameters function old new delta packed_usage 33114 33180 +66 send_d6_info_request - 62 +62 udhcpc6_main 2534 2593 +59 udhcpc6_longopts 199 211 +12 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/0 up/down: 199/0) Total: 199 bytes Signed-off-by: Eivind Versvik <versvikeivind@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/d6_dhcpc.c81
1 files changed, 72 insertions, 9 deletions
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 9d8e17c51..a426b9933 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -123,6 +123,7 @@ static const char udhcpc6_longopts[] ALIGN1 =
123 "request-option\0" Required_argument "O" 123 "request-option\0" Required_argument "O"
124 "no-default-options\0" No_argument "o" 124 "no-default-options\0" No_argument "o"
125 "foreground\0" No_argument "f" 125 "foreground\0" No_argument "f"
126 "stateless\0" No_argument "l"
126 USE_FOR_MMU( 127 USE_FOR_MMU(
127 "background\0" No_argument "b" 128 "background\0" No_argument "b"
128 ) 129 )
@@ -147,9 +148,10 @@ enum {
147 OPT_o = 1 << 12, 148 OPT_o = 1 << 12,
148 OPT_x = 1 << 13, 149 OPT_x = 1 << 13,
149 OPT_f = 1 << 14, 150 OPT_f = 1 << 14,
150 OPT_d = 1 << 15, 151 OPT_l = 1 << 15,
152 OPT_d = 1 << 16,
151/* The rest has variable bit positions, need to be clever */ 153/* The rest has variable bit positions, need to be clever */
152 OPTBIT_d = 15, 154 OPTBIT_d = 16,
153 USE_FOR_MMU( OPTBIT_b,) 155 USE_FOR_MMU( OPTBIT_b,)
154 ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 156 ///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
155 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 157 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
@@ -544,6 +546,46 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *
544 ); 546 );
545} 547}
546 548
549/* RFC 3315 18.1.5. Creation and Transmission of Information-request Messages
550 *
551 * The client uses an Information-request message to obtain
552 * configuration information without having addresses assigned to it.
553 *
554 * The client sets the "msg-type" field to INFORMATION-REQUEST. The
555 * client generates a transaction ID and inserts this value in the
556 * "transaction-id" field.
557 *
558 * The client SHOULD include a Client Identifier option to identify
559 * itself to the server. If the client does not include a Client
560 * Identifier option, the server will not be able to return any client-
561 * specific options to the client, or the server may choose not to
562 * respond to the message at all. The client MUST include a Client
563 * Identifier option if the Information-Request message will be
564 * authenticated.
565 *
566 * The client MUST include an Option Request option (see section 22.7)
567 * to indicate the options the client is interested in receiving. The
568 * client MAY include options with data values as hints to the server
569 * about parameter values the client would like to have returned.
570 */
571/* NOINLINE: limit stack usage in caller */
572static NOINLINE int send_d6_info_request(uint32_t xid)
573{
574 struct d6_packet packet;
575 uint8_t *opt_ptr;
576
577 /* Fill in: msg type, client id */
578 opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid);
579
580 /* Add options:
581 * "param req" option according to -O, options specified with -x
582 */
583 opt_ptr = add_d6_client_options(opt_ptr);
584
585 bb_error_msg("sending %s", "info request");
586 return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
587}
588
547/* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP. 589/* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
548 * 590 *
549 * RFC 3315 17.1.1. Creation of Solicit Messages 591 * RFC 3315 17.1.1. Creation of Solicit Messages
@@ -1129,6 +1171,8 @@ static void client_background(void)
1129//usage: "\n -o Don't request any options (unless -O is given)" 1171//usage: "\n -o Don't request any options (unless -O is given)"
1130//usage: "\n -r IPv6 Request this address ('no' to not request any IP)" 1172//usage: "\n -r IPv6 Request this address ('no' to not request any IP)"
1131//usage: "\n -d Request prefix" 1173//usage: "\n -d Request prefix"
1174//usage: "\n -l Send 'information request' instead of 'solicit'"
1175//usage: "\n (used for servers which do not assign IPv6 addresses)"
1132//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" 1176//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
1133//usage: "\n Examples of string, numeric, and hex byte opts:" 1177//usage: "\n Examples of string, numeric, and hex byte opts:"
1134//usage: "\n -x hostname:bbox - option 12" 1178//usage: "\n -x hostname:bbox - option 12"
@@ -1181,7 +1225,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1181 /* Parse command line */ 1225 /* Parse command line */
1182 opt = getopt32long(argv, "^" 1226 opt = getopt32long(argv, "^"
1183 /* O,x: list; -T,-t,-A take numeric param */ 1227 /* O,x: list; -T,-t,-A take numeric param */
1184 "i:np:qRr:s:T:+t:+SA:+O:*ox:*fd" 1228 "i:np:qRr:s:T:+t:+SA:+O:*ox:*fld"
1185 USE_FOR_MMU("b") 1229 USE_FOR_MMU("b")
1186 ///IF_FEATURE_UDHCPC_ARPING("a") 1230 ///IF_FEATURE_UDHCPC_ARPING("a")
1187 IF_FEATURE_UDHCP_PORT("P:") 1231 IF_FEATURE_UDHCP_PORT("P:")
@@ -1198,15 +1242,20 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1198 ); 1242 );
1199 requested_ipv6 = NULL; 1243 requested_ipv6 = NULL;
1200 option_mask32 |= OPT_r; 1244 option_mask32 |= OPT_r;
1201 if (opt & OPT_r) { 1245 if (opt & OPT_l) {
1246 /* for -l, do not require IPv6 assignment from server */
1247 option_mask32 &= ~OPT_r;
1248 } else if (opt & OPT_r) {
1249 /* explicit "-r ARG" given */
1202 if (strcmp(str_r, "no") == 0) { 1250 if (strcmp(str_r, "no") == 0) {
1203 option_mask32 -= OPT_r; 1251 option_mask32 &= ~OPT_r;
1204 } else { 1252 } else {
1205 if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0) 1253 if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
1206 bb_error_msg_and_die("bad IPv6 address '%s'", str_r); 1254 bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
1207 requested_ipv6 = &ipv6_buf; 1255 requested_ipv6 = &ipv6_buf;
1208 } 1256 }
1209 } 1257 }
1258
1210#if ENABLE_FEATURE_UDHCP_PORT 1259#if ENABLE_FEATURE_UDHCP_PORT
1211 if (opt & OPT_P) { 1260 if (opt & OPT_P) {
1212 CLIENT_PORT6 = xatou16(str_P); 1261 CLIENT_PORT6 = xatou16(str_P);
@@ -1353,7 +1402,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1353 if (packet_num == 0) 1402 if (packet_num == 0)
1354 xid = random_xid(); 1403 xid = random_xid();
1355 /* multicast */ 1404 /* multicast */
1356 send_d6_discover(xid, requested_ipv6); 1405 if (opt & OPT_l)
1406 send_d6_info_request(xid);
1407 else
1408 send_d6_discover(xid, requested_ipv6);
1357 timeout = discover_timeout; 1409 timeout = discover_timeout;
1358 packet_num++; 1410 packet_num++;
1359 continue; 1411 continue;
@@ -1418,7 +1470,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1418 * Anyway, it does recover by eventually failing through 1470 * Anyway, it does recover by eventually failing through
1419 * into INIT_SELECTING state. 1471 * into INIT_SELECTING state.
1420 */ 1472 */
1421 send_d6_renew(xid, &srv6_buf, requested_ipv6); 1473 if (opt & OPT_l)
1474 send_d6_info_request(xid);
1475 else
1476 send_d6_renew(xid, &srv6_buf, requested_ipv6);
1422 timeout >>= 1; 1477 timeout >>= 1;
1423 continue; 1478 continue;
1424 } 1479 }
@@ -1432,8 +1487,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1432 /* Lease is *really* about to run out, 1487 /* Lease is *really* about to run out,
1433 * try to find DHCP server using broadcast */ 1488 * try to find DHCP server using broadcast */
1434 if (timeout > 0) { 1489 if (timeout > 0) {
1435 /* send a broadcast renew request */ 1490 if (opt & OPT_l)
1436 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); 1491 send_d6_info_request(xid);
1492 else /* send a broadcast renew request */
1493 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
1437 timeout >>= 1; 1494 timeout >>= 1;
1438 continue; 1495 continue;
1439 } 1496 }
@@ -1740,6 +1797,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1740 prefix_timeout = address_timeout; 1797 prefix_timeout = address_timeout;
1741 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ 1798 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */
1742 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; 1799 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2;
1800 if (opt & OPT_l) {
1801 /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32)
1802 * and use its value instead of the default 1 day.
1803 */
1804 timeout = 24 * 60 * 60;
1805 }
1743 /* paranoia: must not be too small */ 1806 /* paranoia: must not be too small */
1744 /* timeout > 60 - ensures at least one unicast renew attempt */ 1807 /* timeout > 60 - ensures at least one unicast renew attempt */
1745 if (timeout < 61) 1808 if (timeout < 61)