[PATCH 1/3] udhcpd: add option for tweaking arpping

Stam, Michel [FINT] M.Stam at fugro.nl
Wed Oct 15 06:46:09 UTC 2014


Does anyone have time to look at this?

Kind regards,

Michel Stam
-----Original Message-----
From: Michel Stam [mailto:m.stam at fugro.nl] 
Sent: Wednesday, October 08, 2014 14:45 PM
To: busybox at busybox.net
Cc: Stam, Michel [FINT]
Subject: [PATCH 1/3] udhcpd: add option for tweaking arpping

Some clients have a very short timeout for sending the DHCP DISCOVER,
shorter than the arpping timeout of 2000 milliseconds that udhcpd uses
by default.

This patch allows tweaking the timeout, or disabling of arpping
altogether, at the risk of handing out addresses which are already in
use.

Signed-off-by: Michel Stam <m.stam at fugro.nl>
---
 networking/udhcp/arpping.c | 10 +++++++---  networking/udhcp/common.h
|  3 ++-
 networking/udhcp/dhcpc.c   | 17 +++++++++++++----
 networking/udhcp/dhcpd.c   | 19 ++++++++++++++-----
 networking/udhcp/dhcpd.h   |  2 +-
 networking/udhcp/leases.c  | 11 ++++++-----
 6 files changed, 43 insertions(+), 19 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..82268b1 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
@@ -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,--arping [MSEC]	Validate offered address
(default 2000)"
 //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)"
@@ -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(char *str_a = NULL;)
 	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)
 	);
@@ -1722,11 +1725,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char
**argv)
  * address is already in use (e.g., through the use of ARP),
  * the client MUST send a DHCPDECLINE message to the server and
restarts
  * the configuration process..." */
+					if (str_a == NULL )
+						arpping_ms = 2000; //
Default timeout is 2000 msec
+					else
+						arpping_ms =
xatou(str_a);
+
 					if (!arpping(packet.yiaddr,
 							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..e6a9161 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  change the timeout for arpping (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) {
@@ -300,10 +302,12 @@ int udhcpd_main(int argc UNUSED_PARAM, char
**argv)
 	int server_socket = -1, retval, max_sock;
 	uint8_t *state;
 	unsigned timeout_end;
+	unsigned arpping_ms = 2000; /* Default arpping timeout */
 	unsigned num_ips;
 	unsigned opt;
 	struct option_set *option;
 	char *str_I = str_I;
+	char *str_a = NULL;
 	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,15 @@ 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
+	if ((opt & 16) && ( str_a != NULL )) {
+		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
+507,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;
 	}
--
1.7.12.1



More information about the busybox mailing list