[git commit] udhcpc6: rudimentary code to export data to script; fix IAADDR parsing

Denys Vlasenko vda.linux at googlemail.com
Wed Nov 16 19:17:12 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=a092a89d8f052072e562861f2968573d89e10dd5
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/udhcp/common.c    |   19 ++++++
 networking/udhcp/common.h    |    3 +
 networking/udhcp/d6_common.h |    5 ++
 networking/udhcp/d6_dhcpc.c  |  126 ++++++++++++++++++++++++++++++++++-------
 networking/udhcp/dhcpc.c     |   18 ------
 5 files changed, 131 insertions(+), 40 deletions(-)

diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 2e61136..a89dce3 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -539,3 +539,22 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg)
 
 	return retval;
 }
+
+/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
+int FAST_FUNC sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
+{
+	char hexstrbuf[16 * 2];
+	bin2hex(hexstrbuf, (void*)ip, 16);
+	return sprintf(dest, /* "%s" */
+		"%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
+		/* pre, */
+		hexstrbuf + 0 * 4,
+		hexstrbuf + 1 * 4,
+		hexstrbuf + 2 * 4,
+		hexstrbuf + 3 * 4,
+		hexstrbuf + 4 * 4,
+		hexstrbuf + 5 * 4,
+		hexstrbuf + 6 * 4,
+		hexstrbuf + 7 * 4
+	);
+}
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index a7f9395..479ae49 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -308,6 +308,9 @@ int arpping(uint32_t test_nip,
 		uint8_t *from_mac,
 		const char *interface) FAST_FUNC;
 
+/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
+int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC;
+
 POP_SAVED_FUNCTION_VISIBILITY
 
 #endif
diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h
index 36d822f..4dd7e62 100644
--- a/networking/udhcp/d6_common.h
+++ b/networking/udhcp/d6_common.h
@@ -81,11 +81,16 @@ struct d6_option {
 #define D6_OPT_RECONF_MSG    19
 #define D6_OPT_RECONF_ACCEPT 20
 
+#define D6_OPT_IA_PD         25
+#define D6_OPT_IAPREFIX      26
+
 /*** Other shared functions ***/
 
 struct client6_data_t {
 	struct d6_option *server_id;
 	struct d6_option *ia_na;
+	char **env_ptr;
+	unsigned env_idx;
 };
 
 #define client6_data (*(struct client6_data_t*)(&bb_common_bufsiz1[COMMON_BUFSIZE - sizeof(struct client6_data_t)]))
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 5c98e82..23e6862 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -129,32 +129,114 @@ static void *d6_store_blob(void *dst, const void *src, unsigned len)
 
 /*** Script execution code ***/
 
+static char** new_env(void)
+{
+	client6_data.env_ptr = xrealloc_vector(client6_data.env_ptr, 3, client6_data.env_idx);
+	return &client6_data.env_ptr[client6_data.env_idx++];
+}
+
 /* put all the parameters into the environment */
-static char **fill_envp(struct d6_packet *packet
-    UNUSED_PARAM
-)
+static void option_to_env(uint8_t *option, uint8_t *option_end)
 {
-	int envc;
-	char **envp, **curr;
+	/* "length minus 4" */
+	int len_m4 = option_end - option - 4;
+	while (len_m4 >= 0) {
+		uint32_t v32;
+		char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
 
-#define BITMAP unsigned
-#define BBITS (sizeof(BITMAP) * 8)
-#define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1)))
-#define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS])
-	///BITMAP found_opts[256 / BBITS];
+		if (option[0] != 0 || option[2] != 0)
+			break;
+
+		switch (option[1]) {
+		//case D6_OPT_CLIENTID:
+		//case D6_OPT_SERVERID:
+		case D6_OPT_IA_NA:
+		case D6_OPT_IA_PD:
+			option_to_env(option + 16, option + 4 + option[3]);
+			break;
+		//case D6_OPT_IA_TA:
+		case D6_OPT_IAADDR:
+/*   0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |          OPTION_IAADDR        |          option-len           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                                                               |
+ * |                         IPv6 address                          |
+ * |                                                               |
+ * |                                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      preferred-lifetime                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                        valid-lifetime                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+			sprint_nip6(ipv6str, option + 4);
+			*new_env() = xasprintf("ipv6=%s", ipv6str);
+
+			move_from_unaligned32(v32, option + 4 + 16 + 4);
+			*new_env() = xasprintf("lease=%u", (unsigned)v32);
+			break;
+
+		//case D6_OPT_ORO:
+		//case D6_OPT_PREFERENCE:
+		//case D6_OPT_ELAPSED_TIME:
+		//case D6_OPT_RELAY_MSG:
+		//case D6_OPT_AUTH:
+		//case D6_OPT_UNICAST:
+		//case D6_OPT_STATUS_CODE:
+		//case D6_OPT_RAPID_COMMIT:
+		//case D6_OPT_USER_CLASS:
+		//case D6_OPT_VENDOR_CLASS:
+		//case D6_OPT_VENDOR_OPTS:
+		//case D6_OPT_INTERFACE_ID:
+		//case D6_OPT_RECONF_MSG:
+		//case D6_OPT_RECONF_ACCEPT:
+
+		case D6_OPT_IAPREFIX:
+/*  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |        OPTION_IAPREFIX        |         option-length         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      preferred-lifetime                       |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                        valid-lifetime                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | prefix-length |                                               |
+ * +-+-+-+-+-+-+-+-+          IPv6 prefix                          |
+ * |                           (16 octets)                         |
+ * |                                                               |
+ * |               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |               |
+ * +-+-+-+-+-+-+-+-+
+ */
+			//move_from_unaligned32(v32, option + 4 + 4);
+			//*new_env() = xasprintf("lease=%u", (unsigned)v32);
 
-	///memset(found_opts, 0, sizeof(found_opts));
+			sprint_nip6(ipv6str, option + 4 + 4 + 1);
+			*new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
+		}
+		option += 4 + option[3];
+		len_m4 -= 4 + option[3];
+	}
+}
 
-	/* We need 2 elements for:
-	 * "interface=IFACE"
-	 * terminating NULL
-	 */
-	envc = 2;
+static char **fill_envp(struct d6_packet *packet)
+{
+	char **envp, **curr;
+
+	client6_data.env_ptr = NULL;
+	client6_data.env_idx = 0;
+
+	*new_env() = xasprintf("interface=%s", client_config.interface);
 
-	curr = envp = xzalloc(sizeof(envp[0]) * envc);
+	if (packet)
+		option_to_env(packet->d6_options, packet->d6_options + sizeof(packet->d6_options));
 
-	*curr = xasprintf("interface=%s", client_config.interface);
-	putenv(*curr++);
+	envp = curr = client6_data.env_ptr;
+	while (*curr)
+		putenv(*curr++);
 
 	return envp;
 }
@@ -1329,19 +1411,19 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				free(client6_data.ia_na);
 				client6_data.ia_na = d6_copy_option(packet.d6_options, packet_end, D6_OPT_IA_NA);
 				if (!client6_data.ia_na) {
-					bb_error_msg("no lease time, ignoring packet");
+					bb_error_msg("no %s option, ignoring packet", "IA_NA");
 					continue;
 				}
 				if (client6_data.ia_na->len < (4 + 4 + 4) + (2 + 2 + 16 + 4 + 4)) {
 					bb_error_msg("IA_NA option is too short:%d bytes", client6_data.ia_na->len);
 					continue;
 				}
-				iaaddr = d6_find_option(client6_data.ia_na->data,
+				iaaddr = d6_find_option(client6_data.ia_na->data + 4 + 4 + 4,
 						client6_data.ia_na->data + client6_data.ia_na->len,
 						D6_OPT_IAADDR
 				);
 				if (!iaaddr) {
-					bb_error_msg("no lease time, ignoring packet");
+					bb_error_msg("no %s option, ignoring packet", "IAADDR");
 					continue;
 				}
 				if (iaaddr->len < (16 + 4 + 4)) {
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 3c4e8de..43d6823 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -123,24 +123,6 @@ static int sprint_nip(char *dest, const char *pre, const uint8_t *ip)
 	return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]);
 }
 
-static int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip)
-{
-	char hexstrbuf[16 * 2];
-	bin2hex(hexstrbuf, (void*)ip, 16);
-	return sprintf(dest, /* "%s" */
-		"%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s",
-		/* pre, */
-		hexstrbuf + 0 * 4,
-		hexstrbuf + 1 * 4,
-		hexstrbuf + 2 * 4,
-		hexstrbuf + 3 * 4,
-		hexstrbuf + 4 * 4,
-		hexstrbuf + 5 * 4,
-		hexstrbuf + 6 * 4,
-		hexstrbuf + 7 * 4
-	);
-}
-
 /* really simple implementation, just count the bits */
 static int mton(uint32_t mask)
 {


More information about the busybox-cvs mailing list