diff options
author | Eivind Versvik <versvikeivind@gmail.com> | 2019-08-24 17:23:48 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-08-24 17:24:40 +0200 |
commit | 22a633962786a7bc97870ced913fc237143cfd68 (patch) | |
tree | 9a00b6a91a22f6c868220d57d3550aa3939a64a6 | |
parent | ac78f2ac96b3efd6551a08e7dc609efa1fb69481 (diff) | |
download | busybox-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.c | 81 |
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 */ | ||
572 | static 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) |