Several small improvements to udhcpc6.
- Remove usage text for the nonexistent -B option.
- Fix a segfault when renewing an IA_PD lease without IA_NA (which means
the client hasn't been assigned an ip, so we cannot locally bind to it).
- Fix NAK management: check the option length, and print the status code
and status message
- Print the text of short IA_PD options, which may contain useful
information
- Add a -m option to always send renew requests as multicast.
These last two changes are useful to deal with hopelessly broken DHCPv6
servers such as the one from the Orange Livebox (one of the main French
ISPs) which I'm currently having the displeasure to have to talk to,
hence the patch.
bloat-o-meter: I don't know, I don't have Python. But these changes are
very small. They potentially add 4 bytes of stack usage, oh no.
---
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 79cef1999..f690fb356 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -148,10 +148,11 @@ enum {
OPT_o = 1 << 12,
OPT_x = 1 << 13,
OPT_f = 1 << 14,
- OPT_l = 1 << 15,
- OPT_d = 1 << 16,
+ OPT_m = 1 << 15,
+ OPT_l = 1 << 16,
+ OPT_d = 1 << 17,
/* The rest has variable bit positions, need to be clever */
- OPTBIT_d = 16,
+ OPTBIT_d = 17,
USE_FOR_MMU( OPTBIT_b,)
///IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
@@ -1131,12 +1132,11 @@ static void client_background(void)
//usage:#endif
//usage:#define udhcpc6_trivial_usage
//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"R] [-t N] [-T SEC] [-A
SEC|-n] [-i IFACE] [-s PROG]\n"
-//usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P
PORT]")" [-ldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..."
+//usage: " [-p PIDFILE]"IF_FEATURE_UDHCP_PORT(" [-P
PORT]")" [-mldo] [-r IPv6] [-x OPT:VAL]... [-O OPT]..."
//usage:#define udhcpc6_full_usage "\n"
//usage: "\n -i IFACE Interface to use (default
"CONFIG_UDHCPC_DEFAULT_INTERFACE")"
//usage: "\n -p FILE Create pidfile"
//usage: "\n -s PROG Run PROG at DHCP events (default
"CONFIG_UDHCPC6_DEFAULT_SCRIPT")"
-//usage: "\n -B Request broadcast replies"
//usage: "\n -t N Send up to N discover packets"
//usage: "\n -T SEC Pause between packets (default
3)"
//usage: "\n -A SEC Wait if lease is not obtained
(default 20)"
@@ -1154,6 +1154,7 @@ static void client_background(void)
////usage: IF_FEATURE_UDHCPC_ARPING(
////usage: "\n -a Use arping to validate offered
address"
////usage: )
+//usage: "\n -m Send multicast renew requests
rather than unicast ones"
//usage: "\n -l Send 'information request'
instead of 'solicit'"
//usage: "\n (used for servers which do not
assign IPv6 addresses)"
//usage: "\n -r IPv6 Request this address ('no' to
not request any IP)"
@@ -1211,7 +1212,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:*fld"
+ "i:np:qRr:s:T:+t:+SA:+O:*ox:*fmld"
USE_FOR_MMU("b")
///IF_FEATURE_UDHCPC_ARPING("a")
IF_FEATURE_UDHCP_PORT("P:")
@@ -1464,7 +1465,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char
**argv)
if (opt & OPT_l)
send_d6_info_request();
else
- send_d6_renew(&srv6_buf,
requested_ipv6);
+ send_d6_renew(OPT_m ?
NULL : &srv6_buf, requested_ipv6);
timeout = discover_timeout;
packet_num++;
continue;
@@ -1618,20 +1619,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char
**argv)
prefix_timeout = 0;
option =
d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
if (option && (option->data[0] |
option->data[1]) != 0) {
-///FIXME:
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | OPTION_STATUS_CODE | option-len |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | status-code | |
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
-// . status-message .
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// so why do we think it's NAK if data[0] is zero but data[1] is not?
That's wrong...
-// we should also check that option->len is ok (i.e. not 0), right?
/* return to init state */
- bb_info_msg("received DHCP NAK
(%u)", option->data[4]);
- d6_run_script(packet.d6_options,
- packet_end,
"nak");
+ uint16_t len, status;
+ len = ((uint16_t)option->len_hi
<< 8) + option->len;
+ if (len < 2) {
+ bb_error_msg("invalid
OPTION_STATUS_CODE, ignoring packet");
+ continue;
+ }
+ status =
((uint16_t)option->data[0] << 8) + option->data[1];
+ bb_info_msg("received DHCP NAK:
%hu %.*s", status, (int)len-2, option->data + 2);
+ d6_run_script(packet.d6_options,
packet_end, "nak");
if (client_data.state !=
REQUESTING)
d6_run_script_no_option("deconfig");
sleep(3); /* avoid excessive
network traffic */
@@ -1795,8 +1792,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char
**argv)
continue ;
}
if (client6_data.ia_pd->len < (4
+ 4 + 4) + (2 + 2 + 4 + 4 + 1 + 16)) {
- bb_info_msg("%s option
is too short:%d bytes",
- "IA_PD",
client6_data.ia_pd->len);
+ bb_info_msg("%s option
is too short: %d bytes: %.*s",
+ "IA_PD",
client6_data.ia_pd->len,
+
client6_data.ia_pd->len, client6_data.ia_pd->data);
continue;
}
iaprefix =
d6_find_option(client6_data.ia_pd->data + 4 + 4 + 4,
diff --git a/networking/udhcp/d6_packet.c b/networking/udhcp/d6_packet.c
index 142de9b43..53658cb63 100644
--- a/networking/udhcp/d6_packet.c
+++ b/networking/udhcp/d6_packet.c
@@ -153,13 +153,16 @@ int FAST_FUNC
d6_send_kernel_packet_from_client_data_ifindex(
}
setsockopt_reuseaddr(fd);
- memset(&sa, 0, sizeof(sa));
- sa.sin6_family = AF_INET6;
- sa.sin6_port = htons(source_port);
- sa.sin6_addr = *src_ipv6; /* struct copy */
- if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
- msg = "bind(%s)";
- goto ret_close;
+ if (src_ipv6)
+ {
+ memset(&sa, 0, sizeof(sa));
+ sa.sin6_family = AF_INET6;
+ sa.sin6_port = htons(source_port);
+ sa.sin6_addr = *src_ipv6; /* struct copy */
+ if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
{
+ msg = "bind(%s)";
+ goto ret_close;
+ }
}
memset(&sa, 0, sizeof(sa));
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox