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"
 | 
			
		||||
	"no-default-options\0" No_argument   "o"
 | 
			
		||||
	"foreground\0"     No_argument       "f"
 | 
			
		||||
	"stateless\0"      No_argument       "l"
 | 
			
		||||
	USE_FOR_MMU(
 | 
			
		||||
	"background\0"     No_argument       "b"
 | 
			
		||||
	)
 | 
			
		||||
@@ -147,9 +148,10 @@ enum {
 | 
			
		||||
	OPT_o = 1 << 12,
 | 
			
		||||
	OPT_x = 1 << 13,
 | 
			
		||||
	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 */
 | 
			
		||||
	OPTBIT_d = 15,
 | 
			
		||||
	OPTBIT_d = 16,
 | 
			
		||||
	USE_FOR_MMU(             OPTBIT_b,)
 | 
			
		||||
	///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
 | 
			
		||||
	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.
 | 
			
		||||
 *
 | 
			
		||||
 * 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	-r IPv6		Request this address ('no' to not request any IP)"
 | 
			
		||||
//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			Examples of string, numeric, and hex byte opts:"
 | 
			
		||||
//usage:     "\n			-x hostname:bbox - option 12"
 | 
			
		||||
@@ -1181,7 +1225,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
	/* Parse command line */
 | 
			
		||||
	opt = getopt32long(argv, "^"
 | 
			
		||||
		/* 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")
 | 
			
		||||
		///IF_FEATURE_UDHCPC_ARPING("a")
 | 
			
		||||
		IF_FEATURE_UDHCP_PORT("P:")
 | 
			
		||||
@@ -1198,15 +1242,20 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
	);
 | 
			
		||||
	requested_ipv6 = NULL;
 | 
			
		||||
	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) {
 | 
			
		||||
			option_mask32 -= OPT_r;
 | 
			
		||||
			option_mask32 &= ~OPT_r;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
 | 
			
		||||
				bb_error_msg_and_die("bad IPv6 address '%s'", str_r);
 | 
			
		||||
			requested_ipv6 = &ipv6_buf;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if ENABLE_FEATURE_UDHCP_PORT
 | 
			
		||||
	if (opt & OPT_P) {
 | 
			
		||||
		CLIENT_PORT6 = xatou16(str_P);
 | 
			
		||||
@@ -1353,6 +1402,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
					if (packet_num == 0)
 | 
			
		||||
						xid = random_xid();
 | 
			
		||||
					/* multicast */
 | 
			
		||||
					if (opt & OPT_l)
 | 
			
		||||
						send_d6_info_request(xid);
 | 
			
		||||
					else
 | 
			
		||||
						send_d6_discover(xid, requested_ipv6);
 | 
			
		||||
					timeout = discover_timeout;
 | 
			
		||||
					packet_num++;
 | 
			
		||||
@@ -1418,6 +1470,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
			 * Anyway, it does recover by eventually failing through
 | 
			
		||||
			 * into INIT_SELECTING state.
 | 
			
		||||
			 */
 | 
			
		||||
					if (opt & OPT_l)
 | 
			
		||||
						send_d6_info_request(xid);
 | 
			
		||||
					else
 | 
			
		||||
						send_d6_renew(xid, &srv6_buf, requested_ipv6);
 | 
			
		||||
					timeout >>= 1;
 | 
			
		||||
					continue;
 | 
			
		||||
@@ -1432,7 +1487,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
				/* Lease is *really* about to run out,
 | 
			
		||||
				 * try to find DHCP server using broadcast */
 | 
			
		||||
				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);
 | 
			
		||||
					timeout >>= 1;
 | 
			
		||||
					continue;
 | 
			
		||||
@@ -1740,6 +1797,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
					prefix_timeout = address_timeout;
 | 
			
		||||
				/* note: "int timeout" will not overflow even with 0xffffffff inputs here: */
 | 
			
		||||
				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 */
 | 
			
		||||
				/* timeout > 60 - ensures at least one unicast renew attempt */
 | 
			
		||||
				if (timeout < 61)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user