diff options
-rw-r--r-- | include/usage.h | 48 | ||||
-rw-r--r-- | networking/udhcp/Config.in | 10 | ||||
-rw-r--r-- | networking/udhcp/Kbuild | 6 | ||||
-rw-r--r-- | networking/udhcp/arpping.c | 29 | ||||
-rw-r--r-- | networking/udhcp/clientpacket.c | 16 | ||||
-rw-r--r-- | networking/udhcp/common.h | 2 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 65 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.h | 7 | ||||
-rw-r--r-- | networking/udhcp/signalpipe.c | 2 |
9 files changed, 138 insertions, 47 deletions
diff --git a/include/usage.h b/include/usage.h index d0eecdb4a..3c8762ee1 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -2183,8 +2183,8 @@ | |||
2183 | "and * (run both after creating and before deleting). The commands run in\n" \ | 2183 | "and * (run both after creating and before deleting). The commands run in\n" \ |
2184 | "the /dev directory, and use system() which calls /bin/sh.\n\n" \ | 2184 | "the /dev directory, and use system() which calls /bin/sh.\n\n" \ |
2185 | ) \ | 2185 | ) \ |
2186 | "Config file parsing stops on the first matching line. If no config\n"\ | 2186 | "Config file parsing stops on the first matching line. If no config\n" \ |
2187 | "entry is matched, devices are created with default 0:0 660. (Make\n"\ | 2187 | "entry is matched, devices are created with default 0:0 660. (Make\n" \ |
2188 | "the last line match .* to override this.)\n\n" \ | 2188 | "the last line match .* to override this.)\n\n" \ |
2189 | ) | 2189 | ) |
2190 | 2190 | ||
@@ -3843,44 +3843,50 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when | |||
3843 | " [-p pidfile] [-r IP] [-s script]" | 3843 | " [-p pidfile] [-r IP] [-s script]" |
3844 | #define udhcpc_full_usage \ | 3844 | #define udhcpc_full_usage \ |
3845 | USE_GETOPT_LONG( \ | 3845 | USE_GETOPT_LONG( \ |
3846 | " -V,--vendorclass=CLASSID Set vendor class identifier" \ | 3846 | " -V,--vendorclass=CLASSID Vendor class identifier" \ |
3847 | "\n -i,--interface=INTERFACE Interface to use (default: eth0)" \ | 3847 | "\n -i,--interface=INTERFACE Interface to use (default eth0)" \ |
3848 | "\n -H,-h,--hostname=HOSTNAME Client hostname" \ | 3848 | "\n -H,-h,--hostname=HOSTNAME Client hostname" \ |
3849 | "\n -c,--clientid=CLIENTID Set client identifier" \ | 3849 | "\n -c,--clientid=CLIENTID Client identifier" \ |
3850 | "\n -C,--clientid-none Suppress default client identifier" \ | 3850 | "\n -C,--clientid-none Suppress default client identifier" \ |
3851 | "\n -p,--pidfile=file Store process ID of daemon in file" \ | 3851 | "\n -p,--pidfile=file Create pidfile" \ |
3852 | "\n -r,--request=IP IP address to request" \ | 3852 | "\n -r,--request=IP IP address to request" \ |
3853 | "\n -s,--script=file Run file at dhcp events (default: /usr/share/udhcpc/default.script)" \ | 3853 | "\n -s,--script=file Run file at dhcp events (default: /usr/share/udhcpc/default.script)" \ |
3854 | "\n -t,--retries=N Send up to N request packets"\ | 3854 | "\n -t,--retries=N Send up to N request packets" \ |
3855 | "\n -T,--timeout=N Try to get a lease for N seconds (default: 3)"\ | 3855 | "\n -T,--timeout=N Try to get a lease for N seconds (default 3)" \ |
3856 | "\n -A,--tryagain=N Wait N seconds (default: 60) after failure"\ | 3856 | "\n -A,--tryagain=N Wait N seconds (default 60) after failure" \ |
3857 | "\n -f,--foreground Run in foreground" \ | 3857 | "\n -f,--foreground Run in foreground" \ |
3858 | "\n -b,--background Background if lease cannot be immediately negotiated" \ | 3858 | "\n -b,--background Background if lease is not immediately obtained" \ |
3859 | "\n -S,--syslog Log to syslog too" \ | 3859 | "\n -S,--syslog Log to syslog too" \ |
3860 | "\n -n,--now Exit with failure if lease cannot be immediately negotiated" \ | 3860 | "\n -n,--now Exit with failure if lease is not immediately obtained" \ |
3861 | "\n -q,--quit Quit after obtaining lease" \ | 3861 | "\n -q,--quit Quit after obtaining lease" \ |
3862 | "\n -R,--release Release IP on quit" \ | 3862 | "\n -R,--release Release IP on quit" \ |
3863 | "\n -v,--version Display version" \ | 3863 | USE_FEATURE_UDHCPC_ARPING( \ |
3864 | "\n -a,--arping Use arping to validate offered address" \ | ||
3865 | "\n -W,--wait=N Wait N seconds after declining (default 10)" \ | ||
3866 | ) \ | ||
3864 | ) \ | 3867 | ) \ |
3865 | SKIP_GETOPT_LONG( \ | 3868 | SKIP_GETOPT_LONG( \ |
3866 | " -V CLASSID Set vendor class identifier" \ | 3869 | " -V CLASSID Vendor class identifier" \ |
3867 | "\n -i INTERFACE Interface to use (default: eth0)" \ | 3870 | "\n -i INTERFACE Interface to use (default: eth0)" \ |
3868 | "\n -H,-h HOSTNAME Client hostname" \ | 3871 | "\n -H,-h HOSTNAME Client hostname" \ |
3869 | "\n -c CLIENTID Set client identifier" \ | 3872 | "\n -c CLIENTID Client identifier" \ |
3870 | "\n -C Suppress default client identifier" \ | 3873 | "\n -C Suppress default client identifier" \ |
3871 | "\n -p file Store process ID of daemon in file" \ | 3874 | "\n -p file Create pidfile" \ |
3872 | "\n -r IP IP address to request" \ | 3875 | "\n -r IP IP address to request" \ |
3873 | "\n -s file Run file at dhcp events (default: /usr/share/udhcpc/default.script)" \ | 3876 | "\n -s file Run file at dhcp events (default: /usr/share/udhcpc/default.script)" \ |
3874 | "\n -t N Send up to N request packets"\ | 3877 | "\n -t N Send up to N request packets" \ |
3875 | "\n -T N Try to get a lease for N seconds (default: 3)"\ | 3878 | "\n -T N Try to get a lease for N seconds (default 3)" \ |
3876 | "\n -A N Wait N seconds (default: 60) after failure"\ | 3879 | "\n -A N Wait N seconds (default 60) after failure" \ |
3877 | "\n -f Run in foreground" \ | 3880 | "\n -f Run in foreground" \ |
3878 | "\n -b Background if lease cannot be immediately negotiated" \ | 3881 | "\n -b Background if lease is not immediately obtained" \ |
3879 | "\n -S Log to syslog too" \ | 3882 | "\n -S Log to syslog too" \ |
3880 | "\n -n Exit with failure if lease cannot be immediately negotiated" \ | 3883 | "\n -n Exit with failure if lease is not immediately obtained" \ |
3881 | "\n -q Quit after obtaining lease" \ | 3884 | "\n -q Quit after obtaining lease" \ |
3882 | "\n -R Release IP on quit" \ | 3885 | "\n -R Release IP on quit" \ |
3883 | "\n -v Display version" \ | 3886 | USE_FEATURE_UDHCPC_ARPING( \ |
3887 | "\n -a Use arping to validate offered address" \ | ||
3888 | "\n -W N Wait N seconds after declining (default 10)" \ | ||
3889 | ) \ | ||
3884 | ) | 3890 | ) |
3885 | 3891 | ||
3886 | #define udhcpd_trivial_usage \ | 3892 | #define udhcpd_trivial_usage \ |
diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in index 76b078001..734db65cc 100644 --- a/networking/udhcp/Config.in +++ b/networking/udhcp/Config.in | |||
@@ -54,6 +54,16 @@ config APP_UDHCPC | |||
54 | 54 | ||
55 | See http://udhcp.busybox.net for further details. | 55 | See http://udhcp.busybox.net for further details. |
56 | 56 | ||
57 | config FEATURE_UDHCPC_ARPING | ||
58 | bool "Ask udhcpc to verify that the offered address is free, using arpping" | ||
59 | default y | ||
60 | depends on APP_UDHCPC | ||
61 | help | ||
62 | If selected, udhcpc will use arpping to make sure the offered address | ||
63 | is really available. The client will DHCPDECLINE the offer if the | ||
64 | address is in use, and restart the discover process. | ||
65 | |||
66 | |||
57 | config FEATURE_UDHCP_DEBUG | 67 | config FEATURE_UDHCP_DEBUG |
58 | bool "Compile udhcp with noisy debugging messages" | 68 | bool "Compile udhcp with noisy debugging messages" |
59 | default n | 69 | default n |
diff --git a/networking/udhcp/Kbuild b/networking/udhcp/Kbuild index aed40b98c..7d4747083 100644 --- a/networking/udhcp/Kbuild +++ b/networking/udhcp/Kbuild | |||
@@ -10,10 +10,16 @@ lib-$(CONFIG_APP_UDHCPC) += common.o options.o packet.o \ | |||
10 | signalpipe.o socket.o | 10 | signalpipe.o socket.o |
11 | lib-$(CONFIG_APP_UDHCPD) += common.o options.o packet.o \ | 11 | lib-$(CONFIG_APP_UDHCPD) += common.o options.o packet.o \ |
12 | signalpipe.o socket.o | 12 | signalpipe.o socket.o |
13 | |||
13 | lib-$(CONFIG_APP_UDHCPC) += dhcpc.o clientpacket.o clientsocket.o \ | 14 | lib-$(CONFIG_APP_UDHCPC) += dhcpc.o clientpacket.o clientsocket.o \ |
14 | script.o | 15 | script.o |
16 | |||
17 | UDHCPC_NEEDS_ARPING-$(CONFIG_FEATURE_UDHCPC_ARPING) = y | ||
18 | lib-$(UDHCPC_NEEDS_ARPING) += arpping.o | ||
19 | |||
15 | lib-$(CONFIG_APP_UDHCPD) += dhcpd.o arpping.o files.o leases.o \ | 20 | lib-$(CONFIG_APP_UDHCPD) += dhcpd.o arpping.o files.o leases.o \ |
16 | serverpacket.o static_leases.o | 21 | serverpacket.o static_leases.o |
22 | |||
17 | lib-$(CONFIG_APP_DUMPLEASES) += dumpleases.o | 23 | lib-$(CONFIG_APP_DUMPLEASES) += dumpleases.o |
18 | lib-$(CONFIG_APP_DHCPRELAY) += dhcprelay.o | 24 | lib-$(CONFIG_APP_DHCPRELAY) += dhcprelay.o |
19 | lib-$(CONFIG_FEATURE_RFC3397) += domain_codec.o | 25 | lib-$(CONFIG_FEATURE_RFC3397) += domain_codec.o |
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c index 7b702d8f3..45597c04b 100644 --- a/networking/udhcp/arpping.c +++ b/networking/udhcp/arpping.c | |||
@@ -32,12 +32,16 @@ struct arpMsg { | |||
32 | uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */ | 32 | uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */ |
33 | } ATTRIBUTE_PACKED; | 33 | } ATTRIBUTE_PACKED; |
34 | 34 | ||
35 | enum { | ||
36 | ARP_MSG_SIZE = 0x2a | ||
37 | }; | ||
38 | |||
35 | 39 | ||
36 | /* Returns 1 if no reply received */ | 40 | /* Returns 1 if no reply received */ |
37 | 41 | ||
38 | int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) | 42 | int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) |
39 | { | 43 | { |
40 | int timeout_ms = 2000; | 44 | int timeout_ms; |
41 | struct pollfd pfd[1]; | 45 | struct pollfd pfd[1]; |
42 | #define s (pfd[0].fd) /* socket */ | 46 | #define s (pfd[0].fd) /* socket */ |
43 | int rv = 1; /* "no reply received" yet */ | 47 | int rv = 1; /* "no reply received" yet */ |
@@ -51,7 +55,7 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i | |||
51 | } | 55 | } |
52 | 56 | ||
53 | if (setsockopt_broadcast(s) == -1) { | 57 | if (setsockopt_broadcast(s) == -1) { |
54 | bb_perror_msg("cannot setsocketopt on raw socket"); | 58 | bb_perror_msg("cannot enable bcast on raw socket"); |
55 | goto ret; | 59 | goto ret; |
56 | } | 60 | } |
57 | 61 | ||
@@ -67,28 +71,35 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i | |||
67 | arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ | 71 | arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ |
68 | memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ | 72 | memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ |
69 | memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ | 73 | memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ |
70 | /* tHaddr */ /* target hardware address */ | 74 | /* tHaddr is zero-fiiled */ /* target hardware address */ |
71 | memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ | 75 | memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ |
72 | 76 | ||
73 | memset(&addr, 0, sizeof(addr)); | 77 | memset(&addr, 0, sizeof(addr)); |
74 | safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); | 78 | safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); |
75 | if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) | 79 | if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) { |
80 | // TODO: error message? caller didn't expect us to fail, | ||
81 | // just returning 1 "no reply received" misleads it. | ||
76 | goto ret; | 82 | goto ret; |
83 | } | ||
77 | 84 | ||
78 | /* wait for arp reply, and check it */ | 85 | /* wait for arp reply, and check it */ |
86 | timeout_ms = 2000; | ||
79 | do { | 87 | do { |
80 | int r; | 88 | int r; |
81 | unsigned prevTime = monotonic_us(); | 89 | unsigned prevTime = monotonic_us(); |
82 | 90 | ||
83 | pfd[0].events = POLLIN; | 91 | pfd[0].events = POLLIN; |
84 | r = safe_poll(pfd, 1, timeout_ms); | 92 | r = safe_poll(pfd, 1, timeout_ms); |
85 | if (r < 0) { | 93 | if (r < 0) |
86 | break; | 94 | break; |
87 | } else if (r) { | 95 | if (r) { |
88 | if (read(s, &arp, sizeof(arp)) < 0) | 96 | r = read(s, &arp, sizeof(arp)); |
97 | if (r < 0) | ||
89 | break; | 98 | break; |
90 | if (arp.operation == htons(ARPOP_REPLY) | 99 | if (r >= ARP_MSG_SIZE |
91 | && memcmp(arp.tHaddr, from_mac, 6) == 0 | 100 | && arp.operation == htons(ARPOP_REPLY) |
101 | /* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */ | ||
102 | /* && memcmp(arp.tHaddr, from_mac, 6) == 0 */ | ||
92 | && *((uint32_t *) arp.sInaddr) == test_ip | 103 | && *((uint32_t *) arp.sInaddr) == test_ip |
93 | ) { | 104 | ) { |
94 | rv = 0; | 105 | rv = 0; |
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c index 42b4895e5..e7eeb58b1 100644 --- a/networking/udhcp/clientpacket.c +++ b/networking/udhcp/clientpacket.c | |||
@@ -69,6 +69,22 @@ static void add_requests(struct dhcpMessage *packet) | |||
69 | 69 | ||
70 | } | 70 | } |
71 | 71 | ||
72 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
73 | /* Unicast a DHCP decline message */ | ||
74 | int send_decline(uint32_t xid, uint32_t server) | ||
75 | { | ||
76 | struct dhcpMessage packet; | ||
77 | |||
78 | init_packet(&packet, DHCPDECLINE); | ||
79 | packet.xid = xid; | ||
80 | add_requests(&packet); | ||
81 | |||
82 | bb_info_msg("Sending decline..."); | ||
83 | |||
84 | return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, | ||
85 | SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); | ||
86 | } | ||
87 | #endif | ||
72 | 88 | ||
73 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ | 89 | /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ |
74 | int send_discover(uint32_t xid, uint32_t requested) | 90 | int send_discover(uint32_t xid, uint32_t requested) |
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 4864c8565..179c21fdb 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h | |||
@@ -76,7 +76,7 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name); | |||
76 | 76 | ||
77 | void udhcp_sp_setup(void); | 77 | void udhcp_sp_setup(void); |
78 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); | 78 | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd); |
79 | int udhcp_sp_read(fd_set *rfds); | 79 | int udhcp_sp_read(const fd_set *rfds); |
80 | int raw_socket(int ifindex); | 80 | int raw_socket(int ifindex); |
81 | int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp); | 81 | int read_interface(const char *interface, int *ifindex, uint32_t *addr, uint8_t *arp); |
82 | int listen_socket(/*uint32_t ip,*/ int port, const char *inf); | 82 | int listen_socket(/*uint32_t ip,*/ int port, const char *inf); |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c6f9fe42d..b3b89459e 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -145,6 +145,13 @@ int udhcpc_main(int argc, char **argv) | |||
145 | { | 145 | { |
146 | uint8_t *temp, *message; | 146 | uint8_t *temp, *message; |
147 | char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_A, *str_t; | 147 | char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_A, *str_t; |
148 | int tryagain_timeout = 60; | ||
149 | int discover_timeout = 3; | ||
150 | int discover_retries = 3; | ||
151 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
152 | int decline_wait = 10; | ||
153 | char *str_W; | ||
154 | #endif | ||
148 | uint32_t xid = 0; | 155 | uint32_t xid = 0; |
149 | uint32_t lease = 0; /* can be given as 32-bit quantity */ | 156 | uint32_t lease = 0; /* can be given as 32-bit quantity */ |
150 | unsigned t1 = 0, t2 = 0; /* what a wonderful names */ | 157 | unsigned t1 = 0, t2 = 0; /* what a wonderful names */ |
@@ -180,6 +187,10 @@ int udhcpc_main(int argc, char **argv) | |||
180 | OPT_v = 1 << 17, | 187 | OPT_v = 1 << 17, |
181 | OPT_S = 1 << 18, | 188 | OPT_S = 1 << 18, |
182 | OPT_A = 1 << 19, | 189 | OPT_A = 1 << 19, |
190 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
191 | OPT_a = 1 << 20, | ||
192 | OPT_W = 1 << 21, | ||
193 | #endif | ||
183 | }; | 194 | }; |
184 | #if ENABLE_GETOPT_LONG | 195 | #if ENABLE_GETOPT_LONG |
185 | static const char udhcpc_longopts[] ALIGN1 = | 196 | static const char udhcpc_longopts[] ALIGN1 = |
@@ -203,14 +214,15 @@ int udhcpc_main(int argc, char **argv) | |||
203 | "retries\0" Required_argument "t" | 214 | "retries\0" Required_argument "t" |
204 | "tryagain\0" Required_argument "A" | 215 | "tryagain\0" Required_argument "A" |
205 | "syslog\0" No_argument "S" | 216 | "syslog\0" No_argument "S" |
217 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
218 | "arping\0" No_argument "a" | ||
219 | "wait\0" Required_argument "W" | ||
220 | #endif | ||
206 | ; | 221 | ; |
207 | #endif | 222 | #endif |
208 | /* Default options. */ | 223 | /* Default options. */ |
209 | client_config.interface = "eth0"; | 224 | client_config.interface = "eth0"; |
210 | client_config.script = DEFAULT_SCRIPT; | 225 | client_config.script = DEFAULT_SCRIPT; |
211 | client_config.retries = 3; | ||
212 | client_config.timeout = 3; | ||
213 | client_config.tryagain = 60; | ||
214 | 226 | ||
215 | /* Parse command line */ | 227 | /* Parse command line */ |
216 | opt_complementary = "c--C:C--c" // mutually exclusive | 228 | opt_complementary = "c--C:C--c" // mutually exclusive |
@@ -218,10 +230,12 @@ int udhcpc_main(int argc, char **argv) | |||
218 | #if ENABLE_GETOPT_LONG | 230 | #if ENABLE_GETOPT_LONG |
219 | applet_long_options = udhcpc_longopts; | 231 | applet_long_options = udhcpc_longopts; |
220 | #endif | 232 | #endif |
221 | opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:", | 233 | opt = getopt32(argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:vSA:" |
222 | &str_c, &str_V, &str_h, &str_h, &str_F, | 234 | USE_FEATURE_UDHCPC_ARPING("aW:") |
235 | , &str_c, &str_V, &str_h, &str_h, &str_F, | ||
223 | &client_config.interface, &client_config.pidfile, &str_r, | 236 | &client_config.interface, &client_config.pidfile, &str_r, |
224 | &client_config.script, &str_T, &str_t, &str_A | 237 | &client_config.script, &str_T, &str_t, &str_A |
238 | USE_FEATURE_UDHCPC_ARPING(, &str_W) | ||
225 | ); | 239 | ); |
226 | 240 | ||
227 | if (opt & OPT_c) | 241 | if (opt & OPT_c) |
@@ -259,11 +273,11 @@ int udhcpc_main(int argc, char **argv) | |||
259 | requested_ip = inet_addr(str_r); | 273 | requested_ip = inet_addr(str_r); |
260 | // if (opt & OPT_s) client_config.script = ... | 274 | // if (opt & OPT_s) client_config.script = ... |
261 | if (opt & OPT_T) | 275 | if (opt & OPT_T) |
262 | client_config.timeout = xatoi_u(str_T); | 276 | discover_timeout = xatoi_u(str_T); |
263 | if (opt & OPT_t) | 277 | if (opt & OPT_t) |
264 | client_config.retries = xatoi_u(str_t); | 278 | discover_retries = xatoi_u(str_t); |
265 | if (opt & OPT_A) | 279 | if (opt & OPT_A) |
266 | client_config.tryagain = xatoi_u(str_A); | 280 | tryagain_timeout = xatoi_u(str_A); |
267 | if (opt & OPT_v) { | 281 | if (opt & OPT_v) { |
268 | puts("version "BB_VER); | 282 | puts("version "BB_VER); |
269 | return 0; | 283 | return 0; |
@@ -274,6 +288,11 @@ int udhcpc_main(int argc, char **argv) | |||
274 | logmode |= LOGMODE_SYSLOG; | 288 | logmode |= LOGMODE_SYSLOG; |
275 | } | 289 | } |
276 | 290 | ||
291 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
292 | if (opt & OPT_W) | ||
293 | decline_wait = xatou_range(str_W, 10, INT_MAX); | ||
294 | #endif | ||
295 | |||
277 | if (read_interface(client_config.interface, &client_config.ifindex, | 296 | if (read_interface(client_config.interface, &client_config.ifindex, |
278 | NULL, client_config.arp)) | 297 | NULL, client_config.arp)) |
279 | return 1; | 298 | return 1; |
@@ -339,14 +358,14 @@ int udhcpc_main(int argc, char **argv) | |||
339 | /* timeout dropped to zero */ | 358 | /* timeout dropped to zero */ |
340 | switch (state) { | 359 | switch (state) { |
341 | case INIT_SELECTING: | 360 | case INIT_SELECTING: |
342 | if (packet_num < client_config.retries) { | 361 | if (packet_num < discover_retries) { |
343 | if (packet_num == 0) | 362 | if (packet_num == 0) |
344 | xid = random_xid(); | 363 | xid = random_xid(); |
345 | 364 | ||
346 | /* send discover packet */ | 365 | /* send discover packet */ |
347 | send_discover(xid, requested_ip); /* broadcast */ | 366 | send_discover(xid, requested_ip); /* broadcast */ |
348 | 367 | ||
349 | timeout = now + client_config.timeout; | 368 | timeout = now + discover_timeout; |
350 | packet_num++; | 369 | packet_num++; |
351 | } else { | 370 | } else { |
352 | udhcp_run_script(NULL, "leasefail"); | 371 | udhcp_run_script(NULL, "leasefail"); |
@@ -360,12 +379,12 @@ int udhcpc_main(int argc, char **argv) | |||
360 | } | 379 | } |
361 | /* wait to try again */ | 380 | /* wait to try again */ |
362 | packet_num = 0; | 381 | packet_num = 0; |
363 | timeout = now + client_config.tryagain; | 382 | timeout = now + tryagain_timeout; |
364 | } | 383 | } |
365 | break; | 384 | break; |
366 | case RENEW_REQUESTED: | 385 | case RENEW_REQUESTED: |
367 | case REQUESTING: | 386 | case REQUESTING: |
368 | if (packet_num < client_config.retries) { | 387 | if (packet_num < discover_retries) { |
369 | /* send request packet */ | 388 | /* send request packet */ |
370 | if (state == RENEW_REQUESTED) | 389 | if (state == RENEW_REQUESTED) |
371 | send_renew(xid, server_addr, requested_ip); /* unicast */ | 390 | send_renew(xid, server_addr, requested_ip); /* unicast */ |
@@ -491,6 +510,28 @@ int udhcpc_main(int argc, char **argv) | |||
491 | lease = ntohl(lease); | 510 | lease = ntohl(lease); |
492 | } | 511 | } |
493 | 512 | ||
513 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
514 | if (opt & OPT_a) { | ||
515 | if (!arpping(packet.yiaddr, | ||
516 | (uint32_t) 0, | ||
517 | client_config.arp, | ||
518 | client_config.interface) | ||
519 | ) { | ||
520 | bb_info_msg("offered address is in use," | ||
521 | " declining"); | ||
522 | send_decline(xid, server_addr); | ||
523 | |||
524 | if (state != REQUESTING) | ||
525 | udhcp_run_script(NULL, "deconfig"); | ||
526 | state = INIT_SELECTING; | ||
527 | requested_ip = 0; | ||
528 | packet_num = 0; | ||
529 | change_mode(LISTEN_RAW); | ||
530 | timeout = now + decline_wait; | ||
531 | break; | ||
532 | } | ||
533 | } | ||
534 | #endif | ||
494 | /* enter bound state */ | 535 | /* enter bound state */ |
495 | t1 = lease / 2; | 536 | t1 = lease / 2; |
496 | 537 | ||
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h index 72a8bd94f..c0172a84f 100644 --- a/networking/udhcp/dhcpc.h +++ b/networking/udhcp/dhcpc.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* dhcpc.h */ | 2 | /* dhcpc.h */ |
3 | |||
3 | #ifndef _DHCPC_H | 4 | #ifndef _DHCPC_H |
4 | #define _DHCPC_H | 5 | #define _DHCPC_H |
5 | 6 | ||
@@ -28,9 +29,6 @@ struct client_config_t { | |||
28 | uint8_t *hostname; /* Optional hostname to use */ | 29 | uint8_t *hostname; /* Optional hostname to use */ |
29 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ | 30 | uint8_t *fqdn; /* Optional fully qualified domain name to use */ |
30 | int ifindex; /* Index number of the interface to use */ | 31 | int ifindex; /* Index number of the interface to use */ |
31 | int retries; /* Max number of request packets */ | ||
32 | int timeout; /* Number of seconds to try to get a lease */ | ||
33 | int tryagain; /* Number of seconds to try to get a lease */ | ||
34 | uint8_t arp[6]; /* Our arp address */ | 32 | uint8_t arp[6]; /* Our arp address */ |
35 | }; | 33 | }; |
36 | 34 | ||
@@ -42,6 +40,9 @@ struct client_config_t { | |||
42 | uint32_t random_xid(void); | 40 | uint32_t random_xid(void); |
43 | int send_discover(uint32_t xid, uint32_t requested); | 41 | int send_discover(uint32_t xid, uint32_t requested); |
44 | int send_selecting(uint32_t xid, uint32_t server, uint32_t requested); | 42 | int send_selecting(uint32_t xid, uint32_t server, uint32_t requested); |
43 | #if ENABLE_FEATURE_UDHCPC_ARPING | ||
44 | int send_decline(uint32_t xid, uint32_t server); | ||
45 | #endif | ||
45 | int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); | 46 | int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); |
46 | int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); | 47 | int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr); |
47 | int send_release(uint32_t server, uint32_t ciaddr); | 48 | int send_release(uint32_t server, uint32_t ciaddr); |
diff --git a/networking/udhcp/signalpipe.c b/networking/udhcp/signalpipe.c index fafd2082a..845aa3a9a 100644 --- a/networking/udhcp/signalpipe.c +++ b/networking/udhcp/signalpipe.c | |||
@@ -66,7 +66,7 @@ int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) | |||
66 | /* Read a signal from the signal pipe. Returns 0 if there is | 66 | /* Read a signal from the signal pipe. Returns 0 if there is |
67 | * no signal, -1 on error (and sets errno appropriately), and | 67 | * no signal, -1 on error (and sets errno appropriately), and |
68 | * your signal on success */ | 68 | * your signal on success */ |
69 | int udhcp_sp_read(fd_set *rfds) | 69 | int udhcp_sp_read(const fd_set *rfds) |
70 | { | 70 | { |
71 | unsigned char sig; | 71 | unsigned char sig; |
72 | 72 | ||