[PATCH] Implemented support for stateless DHCPv6. Udhcpc6 will send Information-Request to request configuration parameters without IP address if using 'l' option.

Eivind Versvik versvikeivind at gmail.com
Tue Aug 20 07:53:32 UTC 2019


---
 networking/udhcp/d6_dhcpc.c | 79 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 71 insertions(+), 8 deletions(-)

diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 3c61292..d0f8593 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -125,6 +125,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"
 	)
@@ -149,9 +150,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,)
@@ -841,6 +843,45 @@ int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
 	);
 }
 
+/* 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(uint32_t xid)
+{
+	struct d6_packet packet;
+	uint8_t *opt_ptr;
+	unsigned len;
+
+	/* Fill in: msg type, client id */
+	opt_ptr = init_d6_packet(&packet, D6_MSG_INFORMATION_REQUEST, xid);
+
+	opt_ptr = add_d6_client_options(opt_ptr);
+
+	bb_error_msg("sending %s", "info");
+	return d6_mcast_from_client_config_ifindex(&packet, opt_ptr);
+}
+
 /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
 /* NOINLINE: limit stack usage in caller */
 static NOINLINE int d6_recv_raw_packet(struct in6_addr *peer_ipv6, struct d6_packet *d6_pkt, int fd)
@@ -1117,6 +1158,7 @@ static void client_background(void)
 //usage:     "\n	-T N		Pause between packets (default 3 seconds)"
 //usage:     "\n	-A N		Wait N seconds (default 20) after failure"
 //usage:     "\n	-f		Run in foreground"
+//usage:     "\n	-l		Use stateless mode, only send informational request and dont request ip"
 //usage:	USE_FOR_MMU(
 //usage:     "\n	-b		Background if lease is not obtained"
 //usage:	)
@@ -1159,6 +1201,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 	int tryagain_timeout = 20;
 	int discover_timeout = 3;
 	int discover_retries = 3;
+	int stateless_timeout = 86400;
 	struct in6_addr srv6_buf;
 	struct in6_addr ipv6_buf;
 	struct in6_addr *requested_ipv6;
@@ -1182,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:")
@@ -1208,6 +1251,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 			requested_ipv6 = &ipv6_buf;
 		}
 	}
+
+	if (opt & OPT_l) {
+		/* no ip request when stateless */
+		option_mask32 = option_mask32 & ~OPT_r;
+	}
 #if ENABLE_FEATURE_UDHCP_PORT
 	if (opt & OPT_P) {
 		CLIENT_PORT6 = xatou16(str_P);
@@ -1358,7 +1406,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 					if (packet_num == 0)
 						xid = random_xid();
 					/* multicast */
-					send_d6_discover(xid, requested_ipv6);
+					if(opt & OPT_l)
+						send_d6_info(xid);
+					else
+						send_d6_discover(xid, requested_ipv6);
 					timeout = discover_timeout;
 					packet_num++;
 					continue;
@@ -1401,7 +1452,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				/* 1/2 lease passed, enter renewing state */
 				state = RENEWING;
 				client_config.first_secs = 0; /* make secs field count from 0 */
-				change_listen_mode(LISTEN_KERNEL);
+				if(opt & OPT_l)
+					change_listen_mode(LISTEN_RAW);
+				else
+					change_listen_mode(LISTEN_KERNEL);
 				log1("entering renew state");
 				/* fall right through */
 			case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
@@ -1417,7 +1471,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 			 * Anyway, it does recover by eventually failing through
 			 * into INIT_SELECTING state.
 			 */
-					send_d6_renew(xid, &srv6_buf, requested_ipv6);
+					if(opt & OPT_l)
+						send_d6_info(xid);
+					else
+						send_d6_renew(xid, &srv6_buf, requested_ipv6);
 					timeout >>= 1;
 					continue;
 				}
@@ -1431,8 +1488,10 @@ 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 */
-					send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
+					if(opt & OPT_l)
+						send_d6_info(xid);
+					else /* send a broadcast renew request */
+						send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
 					timeout >>= 1;
 					continue;
 				}
@@ -1739,6 +1798,10 @@ 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) /* no lease timeout will be received, use stateless timeout */
+					timeout = stateless_timeout;
+
 				/* paranoia: must not be too small */
 				/* timeout > 60 - ensures at least one unicast renew attempt */
 				if (timeout < 61)
-- 
2.7.4



More information about the busybox mailing list