udhcpc: an option to perform ARP check (Jonas Danielsson <jonas.danielsson@axis.com>)
configurable, ~+300 bytes when on.
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index c6f9fe4..b3b8945 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -145,6 +145,13 @@
{
uint8_t *temp, *message;
char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_A, *str_t;
+ int tryagain_timeout = 60;
+ int discover_timeout = 3;
+ int discover_retries = 3;
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ int decline_wait = 10;
+ char *str_W;
+#endif
uint32_t xid = 0;
uint32_t lease = 0; /* can be given as 32-bit quantity */
unsigned t1 = 0, t2 = 0; /* what a wonderful names */
@@ -180,6 +187,10 @@
OPT_v = 1 << 17,
OPT_S = 1 << 18,
OPT_A = 1 << 19,
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ OPT_a = 1 << 20,
+ OPT_W = 1 << 21,
+#endif
};
#if ENABLE_GETOPT_LONG
static const char udhcpc_longopts[] ALIGN1 =
@@ -203,14 +214,15 @@
"retries\0" Required_argument "t"
"tryagain\0" Required_argument "A"
"syslog\0" No_argument "S"
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ "arping\0" No_argument "a"
+ "wait\0" Required_argument "W"
+#endif
;
#endif
/* Default options. */
client_config.interface = "eth0";
client_config.script = DEFAULT_SCRIPT;
- client_config.retries = 3;
- client_config.timeout = 3;
- client_config.tryagain = 60;
/* Parse command line */
opt_complementary = "c--C:C--c" // mutually exclusive
@@ -218,10 +230,12 @@
#if ENABLE_GETOPT_LONG
applet_long_options = udhcpc_longopts;
#endif
- opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:",
- &str_c, &str_V, &str_h, &str_h, &str_F,
+ opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:"
+ USE_FEATURE_UDHCPC_ARPING("aW:")
+ , &str_c, &str_V, &str_h, &str_h, &str_F,
&client_config.interface, &client_config.pidfile, &str_r,
&client_config.script, &str_T, &str_t, &str_A
+ USE_FEATURE_UDHCPC_ARPING(, &str_W)
);
if (opt & OPT_c)
@@ -259,11 +273,11 @@
requested_ip = inet_addr(str_r);
// if (opt & OPT_s) client_config.script = ...
if (opt & OPT_T)
- client_config.timeout = xatoi_u(str_T);
+ discover_timeout = xatoi_u(str_T);
if (opt & OPT_t)
- client_config.retries = xatoi_u(str_t);
+ discover_retries = xatoi_u(str_t);
if (opt & OPT_A)
- client_config.tryagain = xatoi_u(str_A);
+ tryagain_timeout = xatoi_u(str_A);
if (opt & OPT_v) {
puts("version "BB_VER);
return 0;
@@ -274,6 +288,11 @@
logmode |= LOGMODE_SYSLOG;
}
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ if (opt & OPT_W)
+ decline_wait = xatou_range(str_W, 10, INT_MAX);
+#endif
+
if (read_interface(client_config.interface, &client_config.ifindex,
NULL, client_config.arp))
return 1;
@@ -339,14 +358,14 @@
/* timeout dropped to zero */
switch (state) {
case INIT_SELECTING:
- if (packet_num < client_config.retries) {
+ if (packet_num < discover_retries) {
if (packet_num == 0)
xid = random_xid();
/* send discover packet */
send_discover(xid, requested_ip); /* broadcast */
- timeout = now + client_config.timeout;
+ timeout = now + discover_timeout;
packet_num++;
} else {
udhcp_run_script(NULL, "leasefail");
@@ -360,12 +379,12 @@
}
/* wait to try again */
packet_num = 0;
- timeout = now + client_config.tryagain;
+ timeout = now + tryagain_timeout;
}
break;
case RENEW_REQUESTED:
case REQUESTING:
- if (packet_num < client_config.retries) {
+ if (packet_num < discover_retries) {
/* send request packet */
if (state == RENEW_REQUESTED)
send_renew(xid, server_addr, requested_ip); /* unicast */
@@ -491,6 +510,28 @@
lease = ntohl(lease);
}
+#if ENABLE_FEATURE_UDHCPC_ARPING
+ if (opt & OPT_a) {
+ if (!arpping(packet.yiaddr,
+ (uint32_t) 0,
+ client_config.arp,
+ client_config.interface)
+ ) {
+ bb_info_msg("offered address is in use,"
+ " declining");
+ send_decline(xid, server_addr);
+
+ if (state != REQUESTING)
+ udhcp_run_script(NULL, "deconfig");
+ state = INIT_SELECTING;
+ requested_ip = 0;
+ packet_num = 0;
+ change_mode(LISTEN_RAW);
+ timeout = now + decline_wait;
+ break;
+ }
+ }
+#endif
/* enter bound state */
t1 = lease / 2;