summaryrefslogtreecommitdiff
path: root/networking/udhcp
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp')
-rw-r--r--networking/udhcp/arpping.c10
-rw-r--r--networking/udhcp/common.h3
-rw-r--r--networking/udhcp/dhcpc.c17
-rw-r--r--networking/udhcp/dhcpd.c17
-rw-r--r--networking/udhcp/dhcpd.h2
-rw-r--r--networking/udhcp/leases.c11
6 files changed, 39 insertions, 21 deletions
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index b43e52e..fad2283 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -39,7 +39,8 @@ int FAST_FUNC arpping(uint32_t test_nip,
const uint8_t *safe_mac,
uint32_t from_ip,
uint8_t *from_mac,
- const char *interface)
+ const char *interface,
+ unsigned timeo)
{
int timeout_ms;
struct pollfd pfd[1];
@@ -48,6 +49,9 @@ int FAST_FUNC arpping(uint32_t test_nip,
struct sockaddr addr; /* for interface name */
struct arpMsg arp;
+ if (!timeo)
+ return 1;
+
s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
if (s == -1) {
bb_perror_msg(bb_msg_can_not_create_raw_socket);
@@ -83,7 +87,7 @@ int FAST_FUNC arpping(uint32_t test_nip,
}
/* wait for arp reply, and check it */
- timeout_ms = 2000;
+ timeout_ms = (int)timeo;
do {
typedef uint32_t aliased_uint32_t FIX_ALIASING;
int r;
@@ -124,7 +128,7 @@ int FAST_FUNC arpping(uint32_t test_nip,
* this is more under/overflow-resistant
* (people did see overflows here when system time jumps):
*/
- } while ((unsigned)timeout_ms <= 2000);
+ } while ((unsigned)timeout_ms <= timeo);
ret:
close(s);
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index e5e0f25..d20659e 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -311,7 +311,8 @@ int arpping(uint32_t test_nip,
const uint8_t *safe_mac,
uint32_t from_ip,
uint8_t *from_mac,
- const char *interface) FAST_FUNC;
+ const char *interface,
+ unsigned timeo) 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;
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index e468b7b..35e7c20 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -54,7 +54,7 @@ static const char udhcpc_longopts[] ALIGN1 =
"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_UDHCPC_ARPING("arping\0" Optional_argument "a")
IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
;
#endif
@@ -1150,7 +1150,7 @@ static void client_background(void)
//usage:# define IF_UDHCP_VERBOSE(...)
//usage:#endif
//usage:#define udhcpc_trivial_usage
-//usage: "[-fbq"IF_UDHCP_VERBOSE("v")IF_FEATURE_UDHCPC_ARPING("a")"RB] [-t N] [-T SEC] [-A SEC/-n]\n"
+//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n"
//usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n"
//usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..."
//usage:#define udhcpc_full_usage "\n"
@@ -1174,7 +1174,7 @@ static void client_background(void)
//usage: )
//usage: "\n -S,--syslog Log to syslog too"
//usage: IF_FEATURE_UDHCPC_ARPING(
-//usage: "\n -a,--arping Use arping to validate offered address"
+//usage: "\n -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping"
//usage: )
//usage: "\n -r,--request IP Request this IP address"
//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)"
@@ -1211,7 +1211,7 @@ static void client_background(void)
//usage: )
//usage: "\n -S Log to syslog too"
//usage: IF_FEATURE_UDHCPC_ARPING(
-//usage: "\n -a Use arping to validate offered address"
+//usage: "\n -a[MSEC] Validate offered address with ARP ping"
//usage: )
//usage: "\n -r IP Request this IP address"
//usage: "\n -o Don't request any options (unless -O is given)"
@@ -1238,6 +1238,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
{
uint8_t *message;
const char *str_V, *str_h, *str_F, *str_r;
+ IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";)
IF_FEATURE_UDHCP_PORT(char *str_P;)
void *clientid_mac_ptr;
llist_t *list_O = NULL;
@@ -1252,6 +1253,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
int timeout; /* must be signed */
unsigned already_waited_sec;
unsigned opt;
+ IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
int max_fd;
int retval;
fd_set rfds;
@@ -1269,7 +1271,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
USE_FOR_MMU("b")
- IF_FEATURE_UDHCPC_ARPING("a")
+ IF_FEATURE_UDHCPC_ARPING("a::")
IF_FEATURE_UDHCP_PORT("P:")
"v"
, &str_V, &str_h, &str_h, &str_F
@@ -1278,6 +1280,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
, &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
, &list_O
, &list_x
+ IF_FEATURE_UDHCPC_ARPING(, &str_a)
IF_FEATURE_UDHCP_PORT(, &str_P)
IF_UDHCP_VERBOSE(, &dhcp_verbose)
);
@@ -1309,6 +1312,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
SERVER_PORT = CLIENT_PORT - 1;
}
#endif
+ IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);)
while (list_O) {
char *optstr = llist_pop(&list_O);
unsigned n = bb_strtou(optstr, NULL, 0);
@@ -1726,7 +1730,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
NULL,
(uint32_t) 0,
client_config.client_mac,
- client_config.interface)
+ client_config.interface,
+ arpping_ms)
) {
bb_info_msg("Offered address is in use "
"(got ARP reply), declining");
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index a1a7f6b..4b3ed24 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -28,6 +28,7 @@
//usage: "\n -f Run in foreground"
//usage: "\n -S Log to syslog too"
//usage: "\n -I ADDR Local address"
+//usage: "\n -a MSEC Timeout for ARP ping (default 2000)"
//usage: IF_FEATURE_UDHCP_PORT(
//usage: "\n -P N Use port N (default 67)"
//usage: )
@@ -148,7 +149,8 @@ static uint32_t select_lease_time(struct dhcp_packet *packet)
static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
uint32_t static_lease_nip,
struct dyn_lease *lease,
- uint8_t *requested_ip_opt)
+ uint8_t *requested_ip_opt,
+ unsigned arpping_ms)
{
struct dhcp_packet packet;
uint32_t lease_time_sec;
@@ -187,7 +189,7 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
}
else {
/* Otherwise, find a free IP */
- packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr);
+ packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms);
}
if (!packet.yiaddr) {
@@ -304,6 +306,8 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
struct option_set *option;
char *str_I = str_I;
+ const char *str_a = "2000";
+ unsigned arpping_ms;
IF_FEATURE_UDHCP_PORT(char *str_P;)
#if ENABLE_FEATURE_UDHCP_PORT
@@ -314,9 +318,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
opt_complementary = "vv";
#endif
- opt = getopt32(argv, "fSI:v"
+ opt = getopt32(argv, "fSI:va:"
IF_FEATURE_UDHCP_PORT("P:")
, &str_I
+ , &str_a
IF_FEATURE_UDHCP_PORT(, &str_P)
IF_UDHCP_VERBOSE(, &dhcp_verbose)
);
@@ -336,11 +341,13 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
free(lsa);
}
#if ENABLE_FEATURE_UDHCP_PORT
- if (opt & 16) { /* -P */
+ if (opt & 32) { /* -P */
SERVER_PORT = xatou16(str_P);
CLIENT_PORT = SERVER_PORT + 1;
}
#endif
+ arpping_ms = xatou(str_a);
+
/* Would rather not do read_config before daemonization -
* otherwise NOMMU machines will parse config twice */
read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
@@ -498,7 +505,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
case DHCPDISCOVER:
log1("Received DISCOVER");
- send_offer(&packet, static_lease_nip, lease, requested_ip_opt);
+ send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms);
break;
case DHCPREQUEST:
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index a77724f..183e7e2 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -100,7 +100,7 @@ struct dyn_lease *add_lease(
int is_expired_lease(struct dyn_lease *lease) FAST_FUNC;
struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC;
struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC;
-uint32_t find_free_or_expired_nip(const uint8_t *safe_mac) FAST_FUNC;
+uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC;
/* Config file parser will pass static lease info to this function
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index c5b60b1..745340a 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -112,7 +112,7 @@ struct dyn_lease* FAST_FUNC find_lease_by_nip(uint32_t nip)
}
/* Check if the IP is taken; if it is, add it to the lease table */
-static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
+static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
{
struct in_addr temp;
int r;
@@ -120,7 +120,8 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
r = arpping(nip, safe_mac,
server_config.server_nip,
server_config.server_mac,
- server_config.interface);
+ server_config.interface,
+ arpping_ms);
if (r)
return r;
@@ -132,7 +133,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
}
/* Find a new usable (we think) address */
-uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
+uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
{
uint32_t addr;
struct dyn_lease *oldest_lease = NULL;
@@ -177,7 +178,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
lease = find_lease_by_nip(nip);
if (!lease) {
//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
- if (nobody_responds_to_arp(nip, safe_mac))
+ if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
return nip;
} else {
if (!oldest_lease || lease->expires < oldest_lease->expires)
@@ -194,7 +195,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
if (oldest_lease
&& is_expired_lease(oldest_lease)
- && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac)
+ && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
) {
return oldest_lease->lease_nip;
}