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.

function                                             old     new   delta
udhcpd_main                                         1460    1501     +41
udhcpc_main                                         2814    2851     +37
packed_usage                                       29957   29974     +17
arpping                                              477     493     +16
find_free_or_expired_nip                             161     174     +13
send_offer                                           285     292      +7
nobody_responds_to_arp                                85      89      +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 7/0 up/down: 135/0)             Total: 135 bytes

Signed-off-by: Michel Stam <m.stam@fugro.nl>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
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 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 @@
 		}
 		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 @@
 	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 @@
 #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 @@
 		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 @@
 		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: