aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Stam <m.stam@fugro.nl>2014-10-30 11:59:04 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2014-10-30 11:59:04 +0100
commit9f41271f3ce82e0f7196c2442614ef4e9d360928 (patch)
tree98dd2becad3478ada376dff4e7a02af50e84e78a
parent760d035699c4a878f9109544c1d35ea0d5f6b76c (diff)
downloadbusybox-w32-9f41271f3ce82e0f7196c2442614ef4e9d360928.tar.gz
busybox-w32-9f41271f3ce82e0f7196c2442614ef4e9d360928.tar.bz2
busybox-w32-9f41271f3ce82e0f7196c2442614ef4e9d360928.zip
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>
-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 b43e52e96..fad2283c3 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -39,7 +39,8 @@ int FAST_FUNC arpping(uint32_t test_nip,
39 const uint8_t *safe_mac, 39 const uint8_t *safe_mac,
40 uint32_t from_ip, 40 uint32_t from_ip,
41 uint8_t *from_mac, 41 uint8_t *from_mac,
42 const char *interface) 42 const char *interface,
43 unsigned timeo)
43{ 44{
44 int timeout_ms; 45 int timeout_ms;
45 struct pollfd pfd[1]; 46 struct pollfd pfd[1];
@@ -48,6 +49,9 @@ int FAST_FUNC arpping(uint32_t test_nip,
48 struct sockaddr addr; /* for interface name */ 49 struct sockaddr addr; /* for interface name */
49 struct arpMsg arp; 50 struct arpMsg arp;
50 51
52 if (!timeo)
53 return 1;
54
51 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); 55 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
52 if (s == -1) { 56 if (s == -1) {
53 bb_perror_msg(bb_msg_can_not_create_raw_socket); 57 bb_perror_msg(bb_msg_can_not_create_raw_socket);
@@ -83,7 +87,7 @@ int FAST_FUNC arpping(uint32_t test_nip,
83 } 87 }
84 88
85 /* wait for arp reply, and check it */ 89 /* wait for arp reply, and check it */
86 timeout_ms = 2000; 90 timeout_ms = (int)timeo;
87 do { 91 do {
88 typedef uint32_t aliased_uint32_t FIX_ALIASING; 92 typedef uint32_t aliased_uint32_t FIX_ALIASING;
89 int r; 93 int r;
@@ -124,7 +128,7 @@ int FAST_FUNC arpping(uint32_t test_nip,
124 * this is more under/overflow-resistant 128 * this is more under/overflow-resistant
125 * (people did see overflows here when system time jumps): 129 * (people did see overflows here when system time jumps):
126 */ 130 */
127 } while ((unsigned)timeout_ms <= 2000); 131 } while ((unsigned)timeout_ms <= timeo);
128 132
129 ret: 133 ret:
130 close(s); 134 close(s);
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index e5e0f2599..d20659e2f 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -311,7 +311,8 @@ int arpping(uint32_t test_nip,
311 const uint8_t *safe_mac, 311 const uint8_t *safe_mac,
312 uint32_t from_ip, 312 uint32_t from_ip,
313 uint8_t *from_mac, 313 uint8_t *from_mac,
314 const char *interface) FAST_FUNC; 314 const char *interface,
315 unsigned timeo) FAST_FUNC;
315 316
316/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ 317/* note: ip is a pointer to an IPv6 in network order, possibly misaliged */
317int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC; 318int 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 e468b7bbb..35e7c2070 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -54,7 +54,7 @@ static const char udhcpc_longopts[] ALIGN1 =
54 "foreground\0" No_argument "f" 54 "foreground\0" No_argument "f"
55 "background\0" No_argument "b" 55 "background\0" No_argument "b"
56 "broadcast\0" No_argument "B" 56 "broadcast\0" No_argument "B"
57 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") 57 IF_FEATURE_UDHCPC_ARPING("arping\0" Optional_argument "a")
58 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 58 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
59 ; 59 ;
60#endif 60#endif
@@ -1150,7 +1150,7 @@ static void client_background(void)
1150//usage:# define IF_UDHCP_VERBOSE(...) 1150//usage:# define IF_UDHCP_VERBOSE(...)
1151//usage:#endif 1151//usage:#endif
1152//usage:#define udhcpc_trivial_usage 1152//usage:#define udhcpc_trivial_usage
1153//usage: "[-fbq"IF_UDHCP_VERBOSE("v")IF_FEATURE_UDHCPC_ARPING("a")"RB] [-t N] [-T SEC] [-A SEC/-n]\n" 1153//usage: "[-fbq"IF_UDHCP_VERBOSE("v")"RB]"IF_FEATURE_UDHCPC_ARPING(" [-a[MSEC]]")" [-t N] [-T SEC] [-A SEC/-n]\n"
1154//usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n" 1154//usage: " [-i IFACE]"IF_FEATURE_UDHCP_PORT(" [-P PORT]")" [-s PROG] [-p PIDFILE]\n"
1155//usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..." 1155//usage: " [-oC] [-r IP] [-V VENDOR] [-F NAME] [-x OPT:VAL]... [-O OPT]..."
1156//usage:#define udhcpc_full_usage "\n" 1156//usage:#define udhcpc_full_usage "\n"
@@ -1174,7 +1174,7 @@ static void client_background(void)
1174//usage: ) 1174//usage: )
1175//usage: "\n -S,--syslog Log to syslog too" 1175//usage: "\n -S,--syslog Log to syslog too"
1176//usage: IF_FEATURE_UDHCPC_ARPING( 1176//usage: IF_FEATURE_UDHCPC_ARPING(
1177//usage: "\n -a,--arping Use arping to validate offered address" 1177//usage: "\n -a[MSEC],--arping[=MSEC] Validate offered address with ARP ping"
1178//usage: ) 1178//usage: )
1179//usage: "\n -r,--request IP Request this IP address" 1179//usage: "\n -r,--request IP Request this IP address"
1180//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)" 1180//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)"
@@ -1211,7 +1211,7 @@ static void client_background(void)
1211//usage: ) 1211//usage: )
1212//usage: "\n -S Log to syslog too" 1212//usage: "\n -S Log to syslog too"
1213//usage: IF_FEATURE_UDHCPC_ARPING( 1213//usage: IF_FEATURE_UDHCPC_ARPING(
1214//usage: "\n -a Use arping to validate offered address" 1214//usage: "\n -a[MSEC] Validate offered address with ARP ping"
1215//usage: ) 1215//usage: )
1216//usage: "\n -r IP Request this IP address" 1216//usage: "\n -r IP Request this IP address"
1217//usage: "\n -o Don't request any options (unless -O is given)" 1217//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)
1238{ 1238{
1239 uint8_t *message; 1239 uint8_t *message;
1240 const char *str_V, *str_h, *str_F, *str_r; 1240 const char *str_V, *str_h, *str_F, *str_r;
1241 IF_FEATURE_UDHCPC_ARPING(const char *str_a = "2000";)
1241 IF_FEATURE_UDHCP_PORT(char *str_P;) 1242 IF_FEATURE_UDHCP_PORT(char *str_P;)
1242 void *clientid_mac_ptr; 1243 void *clientid_mac_ptr;
1243 llist_t *list_O = NULL; 1244 llist_t *list_O = NULL;
@@ -1252,6 +1253,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1252 int timeout; /* must be signed */ 1253 int timeout; /* must be signed */
1253 unsigned already_waited_sec; 1254 unsigned already_waited_sec;
1254 unsigned opt; 1255 unsigned opt;
1256 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1255 int max_fd; 1257 int max_fd;
1256 int retval; 1258 int retval;
1257 fd_set rfds; 1259 fd_set rfds;
@@ -1269,7 +1271,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1269 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1271 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
1270 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1272 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
1271 USE_FOR_MMU("b") 1273 USE_FOR_MMU("b")
1272 IF_FEATURE_UDHCPC_ARPING("a") 1274 IF_FEATURE_UDHCPC_ARPING("a::")
1273 IF_FEATURE_UDHCP_PORT("P:") 1275 IF_FEATURE_UDHCP_PORT("P:")
1274 "v" 1276 "v"
1275 , &str_V, &str_h, &str_h, &str_F 1277 , &str_V, &str_h, &str_h, &str_F
@@ -1278,6 +1280,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1278 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ 1280 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
1279 , &list_O 1281 , &list_O
1280 , &list_x 1282 , &list_x
1283 IF_FEATURE_UDHCPC_ARPING(, &str_a)
1281 IF_FEATURE_UDHCP_PORT(, &str_P) 1284 IF_FEATURE_UDHCP_PORT(, &str_P)
1282 IF_UDHCP_VERBOSE(, &dhcp_verbose) 1285 IF_UDHCP_VERBOSE(, &dhcp_verbose)
1283 ); 1286 );
@@ -1309,6 +1312,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1309 SERVER_PORT = CLIENT_PORT - 1; 1312 SERVER_PORT = CLIENT_PORT - 1;
1310 } 1313 }
1311#endif 1314#endif
1315 IF_FEATURE_UDHCPC_ARPING(arpping_ms = xatou(str_a);)
1312 while (list_O) { 1316 while (list_O) {
1313 char *optstr = llist_pop(&list_O); 1317 char *optstr = llist_pop(&list_O);
1314 unsigned n = bb_strtou(optstr, NULL, 0); 1318 unsigned n = bb_strtou(optstr, NULL, 0);
@@ -1726,7 +1730,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1726 NULL, 1730 NULL,
1727 (uint32_t) 0, 1731 (uint32_t) 0,
1728 client_config.client_mac, 1732 client_config.client_mac,
1729 client_config.interface) 1733 client_config.interface,
1734 arpping_ms)
1730 ) { 1735 ) {
1731 bb_info_msg("Offered address is in use " 1736 bb_info_msg("Offered address is in use "
1732 "(got ARP reply), declining"); 1737 "(got ARP reply), declining");
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index a1a7f6b57..4b3ed240c 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -28,6 +28,7 @@
28//usage: "\n -f Run in foreground" 28//usage: "\n -f Run in foreground"
29//usage: "\n -S Log to syslog too" 29//usage: "\n -S Log to syslog too"
30//usage: "\n -I ADDR Local address" 30//usage: "\n -I ADDR Local address"
31//usage: "\n -a MSEC Timeout for ARP ping (default 2000)"
31//usage: IF_FEATURE_UDHCP_PORT( 32//usage: IF_FEATURE_UDHCP_PORT(
32//usage: "\n -P N Use port N (default 67)" 33//usage: "\n -P N Use port N (default 67)"
33//usage: ) 34//usage: )
@@ -148,7 +149,8 @@ static uint32_t select_lease_time(struct dhcp_packet *packet)
148static NOINLINE void send_offer(struct dhcp_packet *oldpacket, 149static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
149 uint32_t static_lease_nip, 150 uint32_t static_lease_nip,
150 struct dyn_lease *lease, 151 struct dyn_lease *lease,
151 uint8_t *requested_ip_opt) 152 uint8_t *requested_ip_opt,
153 unsigned arpping_ms)
152{ 154{
153 struct dhcp_packet packet; 155 struct dhcp_packet packet;
154 uint32_t lease_time_sec; 156 uint32_t lease_time_sec;
@@ -187,7 +189,7 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
187 } 189 }
188 else { 190 else {
189 /* Otherwise, find a free IP */ 191 /* Otherwise, find a free IP */
190 packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr); 192 packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms);
191 } 193 }
192 194
193 if (!packet.yiaddr) { 195 if (!packet.yiaddr) {
@@ -304,6 +306,8 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
304 unsigned opt; 306 unsigned opt;
305 struct option_set *option; 307 struct option_set *option;
306 char *str_I = str_I; 308 char *str_I = str_I;
309 const char *str_a = "2000";
310 unsigned arpping_ms;
307 IF_FEATURE_UDHCP_PORT(char *str_P;) 311 IF_FEATURE_UDHCP_PORT(char *str_P;)
308 312
309#if ENABLE_FEATURE_UDHCP_PORT 313#if ENABLE_FEATURE_UDHCP_PORT
@@ -314,9 +318,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
314#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 318#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
315 opt_complementary = "vv"; 319 opt_complementary = "vv";
316#endif 320#endif
317 opt = getopt32(argv, "fSI:v" 321 opt = getopt32(argv, "fSI:va:"
318 IF_FEATURE_UDHCP_PORT("P:") 322 IF_FEATURE_UDHCP_PORT("P:")
319 , &str_I 323 , &str_I
324 , &str_a
320 IF_FEATURE_UDHCP_PORT(, &str_P) 325 IF_FEATURE_UDHCP_PORT(, &str_P)
321 IF_UDHCP_VERBOSE(, &dhcp_verbose) 326 IF_UDHCP_VERBOSE(, &dhcp_verbose)
322 ); 327 );
@@ -336,11 +341,13 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
336 free(lsa); 341 free(lsa);
337 } 342 }
338#if ENABLE_FEATURE_UDHCP_PORT 343#if ENABLE_FEATURE_UDHCP_PORT
339 if (opt & 16) { /* -P */ 344 if (opt & 32) { /* -P */
340 SERVER_PORT = xatou16(str_P); 345 SERVER_PORT = xatou16(str_P);
341 CLIENT_PORT = SERVER_PORT + 1; 346 CLIENT_PORT = SERVER_PORT + 1;
342 } 347 }
343#endif 348#endif
349 arpping_ms = xatou(str_a);
350
344 /* Would rather not do read_config before daemonization - 351 /* Would rather not do read_config before daemonization -
345 * otherwise NOMMU machines will parse config twice */ 352 * otherwise NOMMU machines will parse config twice */
346 read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); 353 read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
@@ -498,7 +505,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
498 case DHCPDISCOVER: 505 case DHCPDISCOVER:
499 log1("Received DISCOVER"); 506 log1("Received DISCOVER");
500 507
501 send_offer(&packet, static_lease_nip, lease, requested_ip_opt); 508 send_offer(&packet, static_lease_nip, lease, requested_ip_opt, arpping_ms);
502 break; 509 break;
503 510
504 case DHCPREQUEST: 511 case DHCPREQUEST:
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h
index a77724f20..183e7e24c 100644
--- a/networking/udhcp/dhcpd.h
+++ b/networking/udhcp/dhcpd.h
@@ -100,7 +100,7 @@ struct dyn_lease *add_lease(
100int is_expired_lease(struct dyn_lease *lease) FAST_FUNC; 100int is_expired_lease(struct dyn_lease *lease) FAST_FUNC;
101struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC; 101struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC;
102struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC; 102struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC;
103uint32_t find_free_or_expired_nip(const uint8_t *safe_mac) FAST_FUNC; 103uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC;
104 104
105 105
106/* Config file parser will pass static lease info to this function 106/* Config file parser will pass static lease info to this function
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index c5b60b108..745340ad3 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)
112} 112}
113 113
114/* Check if the IP is taken; if it is, add it to the lease table */ 114/* Check if the IP is taken; if it is, add it to the lease table */
115static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac) 115static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
116{ 116{
117 struct in_addr temp; 117 struct in_addr temp;
118 int r; 118 int r;
@@ -120,7 +120,8 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
120 r = arpping(nip, safe_mac, 120 r = arpping(nip, safe_mac,
121 server_config.server_nip, 121 server_config.server_nip,
122 server_config.server_mac, 122 server_config.server_mac,
123 server_config.interface); 123 server_config.interface,
124 arpping_ms);
124 if (r) 125 if (r)
125 return r; 126 return r;
126 127
@@ -132,7 +133,7 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
132} 133}
133 134
134/* Find a new usable (we think) address */ 135/* Find a new usable (we think) address */
135uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) 136uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
136{ 137{
137 uint32_t addr; 138 uint32_t addr;
138 struct dyn_lease *oldest_lease = NULL; 139 struct dyn_lease *oldest_lease = NULL;
@@ -177,7 +178,7 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
177 lease = find_lease_by_nip(nip); 178 lease = find_lease_by_nip(nip);
178 if (!lease) { 179 if (!lease) {
179//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping! 180//TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
180 if (nobody_responds_to_arp(nip, safe_mac)) 181 if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
181 return nip; 182 return nip;
182 } else { 183 } else {
183 if (!oldest_lease || lease->expires < oldest_lease->expires) 184 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)
194 195
195 if (oldest_lease 196 if (oldest_lease
196 && is_expired_lease(oldest_lease) 197 && is_expired_lease(oldest_lease)
197 && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac) 198 && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
198 ) { 199 ) {
199 return oldest_lease->lease_nip; 200 return oldest_lease->lease_nip;
200 } 201 }