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>
This commit is contained in:
committed by
Denys Vlasenko
parent
ac78f2ac96
commit
22a6339627
@@ -123,6 +123,7 @@ static const char udhcpc6_longopts[] ALIGN1 =
|
|||||||
"request-option\0" Required_argument "O"
|
"request-option\0" Required_argument "O"
|
||||||
"no-default-options\0" No_argument "o"
|
"no-default-options\0" No_argument "o"
|
||||||
"foreground\0" No_argument "f"
|
"foreground\0" No_argument "f"
|
||||||
|
"stateless\0" No_argument "l"
|
||||||
USE_FOR_MMU(
|
USE_FOR_MMU(
|
||||||
"background\0" No_argument "b"
|
"background\0" No_argument "b"
|
||||||
)
|
)
|
||||||
@@ -147,9 +148,10 @@ enum {
|
|||||||
OPT_o = 1 << 12,
|
OPT_o = 1 << 12,
|
||||||
OPT_x = 1 << 13,
|
OPT_x = 1 << 13,
|
||||||
OPT_f = 1 << 14,
|
OPT_f = 1 << 14,
|
||||||
OPT_d = 1 << 15,
|
OPT_l = 1 << 15,
|
||||||
|
OPT_d = 1 << 16,
|
||||||
/* The rest has variable bit positions, need to be clever */
|
/* The rest has variable bit positions, need to be clever */
|
||||||
OPTBIT_d = 15,
|
OPTBIT_d = 16,
|
||||||
USE_FOR_MMU( OPTBIT_b,)
|
USE_FOR_MMU( OPTBIT_b,)
|
||||||
///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
|
///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
|
||||||
IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
|
IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
|
||||||
@@ -544,6 +546,46 @@ static int d6_mcast_from_client_data_ifindex(struct d6_packet *packet, uint8_t *
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RFC 3315 18.1.5. Creation and Transmission of Information-request Messages
|
||||||
|
*
|
||||||
|
* The client uses an Information-request message to obtain
|
||||||
|
* configuration information without having addresses assigned to it.
|
||||||
|
*
|
||||||
|
* The client sets the "msg-type" field to INFORMATION-REQUEST. The
|
||||||
|
* client generates a transaction ID and inserts this value in the
|
||||||
|
* "transaction-id" field.
|
||||||
|
*
|
||||||
|
* The client SHOULD include a Client Identifier option to identify
|
||||||
|
* itself to the server. If the client does not include a Client
|
||||||
|
* Identifier option, the server will not be able to return any client-
|
||||||
|
* specific options to the client, or the server may choose not to
|
||||||
|
* respond to the message at all. The client MUST include a Client
|
||||||
|
* Identifier option if the Information-Request message will be
|
||||||
|
* authenticated.
|
||||||
|
*
|
||||||
|
* The client MUST include an Option Request option (see section 22.7)
|
||||||
|
* to indicate the options the client is interested in receiving. The
|
||||||
|
* client MAY include options with data values as hints to the server
|
||||||
|
* about parameter values the client would like to have returned.
|
||||||
|
*/
|
||||||
|
/* NOINLINE: limit stack usage in caller */
|
||||||
|
static NOINLINE int send_d6_info_request(uint32_t xid)
|
||||||
|
{
|
||||||
|
struct d6_packet packet;
|
||||||
|
uint8_t *opt_ptr;
|
||||||
|
|
||||||
|
/* Fill in: msg type, client id */
|
||||||
|
opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid);
|
||||||
|
|
||||||
|
/* Add options:
|
||||||
|
* "param req" option according to -O, options specified with -x
|
||||||
|
*/
|
||||||
|
opt_ptr = add_d6_client_options(opt_ptr);
|
||||||
|
|
||||||
|
bb_error_msg("sending %s", "info request");
|
||||||
|
return d6_mcast_from_client_data_ifindex(&packet, opt_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
|
/* Milticast a DHCPv6 Solicit packet to the network, with an optionally requested IP.
|
||||||
*
|
*
|
||||||
* RFC 3315 17.1.1. Creation of Solicit Messages
|
* RFC 3315 17.1.1. Creation of Solicit Messages
|
||||||
@@ -1129,6 +1171,8 @@ static void client_background(void)
|
|||||||
//usage: "\n -o Don't request any options (unless -O is given)"
|
//usage: "\n -o Don't request any options (unless -O is given)"
|
||||||
//usage: "\n -r IPv6 Request this address ('no' to not request any IP)"
|
//usage: "\n -r IPv6 Request this address ('no' to not request any IP)"
|
||||||
//usage: "\n -d Request prefix"
|
//usage: "\n -d Request prefix"
|
||||||
|
//usage: "\n -l Send 'information request' instead of 'solicit'"
|
||||||
|
//usage: "\n (used for servers which do not assign IPv6 addresses)"
|
||||||
//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
|
//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
|
||||||
//usage: "\n Examples of string, numeric, and hex byte opts:"
|
//usage: "\n Examples of string, numeric, and hex byte opts:"
|
||||||
//usage: "\n -x hostname:bbox - option 12"
|
//usage: "\n -x hostname:bbox - option 12"
|
||||||
@@ -1181,7 +1225,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* Parse command line */
|
/* Parse command line */
|
||||||
opt = getopt32long(argv, "^"
|
opt = getopt32long(argv, "^"
|
||||||
/* O,x: list; -T,-t,-A take numeric param */
|
/* O,x: list; -T,-t,-A take numeric param */
|
||||||
"i:np:qRr:s:T:+t:+SA:+O:*ox:*fd"
|
"i:np:qRr:s:T:+t:+SA:+O:*ox:*fld"
|
||||||
USE_FOR_MMU("b")
|
USE_FOR_MMU("b")
|
||||||
///IF_FEATURE_UDHCPC_ARPING("a")
|
///IF_FEATURE_UDHCPC_ARPING("a")
|
||||||
IF_FEATURE_UDHCP_PORT("P:")
|
IF_FEATURE_UDHCP_PORT("P:")
|
||||||
@@ -1198,15 +1242,20 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
);
|
);
|
||||||
requested_ipv6 = NULL;
|
requested_ipv6 = NULL;
|
||||||
option_mask32 |= OPT_r;
|
option_mask32 |= OPT_r;
|
||||||
if (opt & OPT_r) {
|
if (opt & OPT_l) {
|
||||||
|
/* for -l, do not require IPv6 assignment from server */
|
||||||
|
option_mask32 &= ~OPT_r;
|
||||||
|
} else if (opt & OPT_r) {
|
||||||
|
/* explicit "-r ARG" given */
|
||||||
if (strcmp(str_r, "no") == 0) {
|
if (strcmp(str_r, "no") == 0) {
|
||||||
option_mask32 -= OPT_r;
|
option_mask32 &= ~OPT_r;
|
||||||
} else {
|
} else {
|
||||||
if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
|
if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
|
||||||
bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
|
bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
|
||||||
requested_ipv6 = &ipv6_buf;
|
requested_ipv6 = &ipv6_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_UDHCP_PORT
|
#if ENABLE_FEATURE_UDHCP_PORT
|
||||||
if (opt & OPT_P) {
|
if (opt & OPT_P) {
|
||||||
CLIENT_PORT6 = xatou16(str_P);
|
CLIENT_PORT6 = xatou16(str_P);
|
||||||
@@ -1353,6 +1402,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (packet_num == 0)
|
if (packet_num == 0)
|
||||||
xid = random_xid();
|
xid = random_xid();
|
||||||
/* multicast */
|
/* multicast */
|
||||||
|
if (opt & OPT_l)
|
||||||
|
send_d6_info_request(xid);
|
||||||
|
else
|
||||||
send_d6_discover(xid, requested_ipv6);
|
send_d6_discover(xid, requested_ipv6);
|
||||||
timeout = discover_timeout;
|
timeout = discover_timeout;
|
||||||
packet_num++;
|
packet_num++;
|
||||||
@@ -1418,6 +1470,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
* Anyway, it does recover by eventually failing through
|
* Anyway, it does recover by eventually failing through
|
||||||
* into INIT_SELECTING state.
|
* into INIT_SELECTING state.
|
||||||
*/
|
*/
|
||||||
|
if (opt & OPT_l)
|
||||||
|
send_d6_info_request(xid);
|
||||||
|
else
|
||||||
send_d6_renew(xid, &srv6_buf, requested_ipv6);
|
send_d6_renew(xid, &srv6_buf, requested_ipv6);
|
||||||
timeout >>= 1;
|
timeout >>= 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -1432,7 +1487,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* Lease is *really* about to run out,
|
/* Lease is *really* about to run out,
|
||||||
* try to find DHCP server using broadcast */
|
* try to find DHCP server using broadcast */
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
/* send a broadcast renew request */
|
if (opt & OPT_l)
|
||||||
|
send_d6_info_request(xid);
|
||||||
|
else /* send a broadcast renew request */
|
||||||
send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
|
send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
|
||||||
timeout >>= 1;
|
timeout >>= 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -1740,6 +1797,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
prefix_timeout = address_timeout;
|
prefix_timeout = address_timeout;
|
||||||
/* note: "int timeout" will not overflow even with 0xffffffff inputs here: */
|
/* note: "int timeout" will not overflow even with 0xffffffff inputs here: */
|
||||||
timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2;
|
timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2;
|
||||||
|
if (opt & OPT_l) {
|
||||||
|
/* TODO: request OPTION_INFORMATION_REFRESH_TIME (32)
|
||||||
|
* and use its value instead of the default 1 day.
|
||||||
|
*/
|
||||||
|
timeout = 24 * 60 * 60;
|
||||||
|
}
|
||||||
/* paranoia: must not be too small */
|
/* paranoia: must not be too small */
|
||||||
/* timeout > 60 - ensures at least one unicast renew attempt */
|
/* timeout > 60 - ensures at least one unicast renew attempt */
|
||||||
if (timeout < 61)
|
if (timeout < 61)
|
||||||
|
Reference in New Issue
Block a user