udhcpd: add option for tweaking arpping
No binary (build failed)
—
(log yok)
| @@ -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); | |
| @@ -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; | |
| @@ -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"); | |
| @@ -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: | |
| @@ -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 | |
| @@ -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; | |
| } | |