*/
//config:config UDHCPC6
-//config: bool "udhcp client for DHCPv6 (udhcpc6)"
-//config: default n # not yet ready
-//config: help
-//config: udhcpc6 is a DHCPv6 client
+//config: bool "udhcp client for DHCPv6 (udhcpc6)"
+//config: default n # not yet ready
+//config: depends on FEATURE_IPV6
+//config: help
+//config: udhcpc6 is a DHCPv6 client
//applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP))
-//kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o
+//kbuild:lib-$(CONFIG_UDHCPC6) += d6_dhcpc.o d6_packet.o d6_socket.o common.o socket.o signalpipe.o
#include <syslog.h>
#if ENABLE_LONG_OPTS
-static const char udhcpc_longopts[] ALIGN1 =
+static const char udhcpc6_longopts[] ALIGN1 =
"interface\0" Required_argument "i"
"now\0" No_argument "n"
"pidfile\0" Required_argument "p"
"request\0" Required_argument "r"
"script\0" Required_argument "s"
"timeout\0" Required_argument "T"
- "version\0" No_argument "v"
"retries\0" Required_argument "t"
"tryagain\0" Required_argument "A"
"syslog\0" No_argument "S"
"no-default-options\0" No_argument "o"
"foreground\0" No_argument "f"
"background\0" No_argument "b"
- "broadcast\0" No_argument "B"
/// IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
;
OPT_o = 1 << 12,
OPT_x = 1 << 13,
OPT_f = 1 << 14,
- OPT_B = 1 << 15,
/* The rest has variable bit positions, need to be clever */
- OPTBIT_B = 15,
+ OPTBIT_f = 14,
USE_FOR_MMU( OPTBIT_b,)
///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
/*** 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;
- curr = envp = xzalloc(sizeof(envp[0]) * envc);
+ client6_data.env_ptr = NULL;
+ client6_data.env_idx = 0;
- *curr = xasprintf("interface=%s", client_config.interface);
- putenv(*curr++);
+ *new_env() = xasprintf("interface=%s", client_config.interface);
+
+ if (packet)
+ option_to_env(packet->d6_options, packet->d6_options + sizeof(packet->d6_options));
+
+ envp = curr = client6_data.env_ptr;
+ while (*curr)
+ putenv(*curr++);
return envp;
}
//usage:# define IF_UDHCP_VERBOSE(...)
//usage:#endif
//usage:#define udhcpc6_trivial_usage
-//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
+//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
//usage: " [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
//usage:#define udhcpc6_full_usage "\n"
//usage: IF_LONG_OPTS(
//usage: "\n -R,--release Release IP on exit"
//usage: "\n -S,--syslog Log to syslog too"
//usage: IF_FEATURE_UDHCP_PORT(
-//usage: "\n -P,--client-port N Use port N (default 68)"
+//usage: "\n -P,--client-port N Use port N (default 546)"
//usage: )
////usage: IF_FEATURE_UDHCPC_ARPING(
////usage: "\n -a,--arping Use arping to validate offered address"
//usage: "\n -R Release IP on exit"
//usage: "\n -S Log to syslog too"
//usage: IF_FEATURE_UDHCP_PORT(
-//usage: "\n -P N Use port N (default 68)"
+//usage: "\n -P N Use port N (default 546)"
//usage: )
////usage: IF_FEATURE_UDHCPC_ARPING(
////usage: "\n -a Use arping to validate offered address"
/* Parse command line */
/* O,x: list; -T,-t,-A take numeric param */
opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ;
- IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
- opt = getopt32(argv, "i:np:qRr:s:T:t:SA:O:ox:fB"
+ IF_LONG_OPTS(applet_long_options = udhcpc6_longopts;)
+ opt = getopt32(argv, "i:np:qRr:s:T:t:SA:O:ox:f"
USE_FOR_MMU("b")
///IF_FEATURE_UDHCPC_ARPING("a")
IF_FEATURE_UDHCP_PORT("P:")
, &list_x
IF_FEATURE_UDHCP_PORT(, &str_P)
IF_UDHCP_VERBOSE(, &dhcp_verbose)
- );
+ );
requested_ipv6 = NULL;
if (opt & OPT_r) {
if (inet_pton(AF_INET6, str_r, &ipv6_buf) <= 0)
retval = 0;
/* If we already timed out, fall through with retval = 0, else... */
if ((int)tv.tv_sec > 0) {
+ log1("Waiting on select %u seconds", (int)tv.tv_sec);
timestamp_before_wait = (unsigned)monotonic_sec();
- log1("Waiting on select...");
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
if (retval < 0) {
/* EINTR? A signal was caught, don't panic */
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)) {