diff options
author | Rob Landley <rob@landley.net> | 2005-05-01 00:22:03 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2005-05-01 00:22:03 +0000 |
commit | 8445a9ff99f04cad8845a1aed6ab17737f2d985a (patch) | |
tree | f31c09bf14817ee84ae6fbc247f0c62152fff7e7 /networking/zcip.c | |
parent | 6624daeb4d040a39ad7d6b66ff11339c710d0f3d (diff) | |
download | busybox-w32-8445a9ff99f04cad8845a1aed6ab17737f2d985a.tar.gz busybox-w32-8445a9ff99f04cad8845a1aed6ab17737f2d985a.tar.bz2 busybox-w32-8445a9ff99f04cad8845a1aed6ab17737f2d985a.zip |
On Tuesday 19 April 2005 21:10, Tito wrote and today added:
> Hi,
> this is a first attempt of size optimization for zcip taking into account all
> the hints given so far on the list.
> I've applied just the more obvious busyboxifications so maybe it could be
> optimized more.
BTW: I've ripped out a lot of debug code and changed c++ // comments to /* */
as both were rather confusing for a newbie like me. ;-)
Sorry to the author for that.
I know that this makes mantaining the code easier, but I'm simple minded....
Diffstat (limited to 'networking/zcip.c')
-rw-r--r-- | networking/zcip.c | 295 |
1 files changed, 109 insertions, 186 deletions
diff --git a/networking/zcip.c b/networking/zcip.c index ccf399bb7..de9ea7675 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -31,14 +31,12 @@ | |||
31 | * certainly be used. Its naming is built over multicast DNS. | 31 | * certainly be used. Its naming is built over multicast DNS. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | // #define DEBUG | 34 | /* TODO: |
35 | 35 | - more real-world usage/testing, especially daemon mode | |
36 | // TODO: | 36 | - kernel packet filters to reduce scheduling noise |
37 | // - more real-world usage/testing, especially daemon mode | 37 | - avoid silent script failures, especially under load... |
38 | // - kernel packet filters to reduce scheduling noise | 38 | - link status monitoring (restart on link-up; stop on link-down) |
39 | // - avoid silent script failures, especially under load... | 39 | */ |
40 | // - link status monitoring (restart on link-up; stop on link-down) | ||
41 | |||
42 | #include <errno.h> | 40 | #include <errno.h> |
43 | #include <stdlib.h> | 41 | #include <stdlib.h> |
44 | #include <stdio.h> | 42 | #include <stdio.h> |
@@ -63,11 +61,12 @@ | |||
63 | 61 | ||
64 | #include <linux/if_packet.h> | 62 | #include <linux/if_packet.h> |
65 | #include <linux/sockios.h> | 63 | #include <linux/sockios.h> |
66 | 64 | #include "busybox.h" | |
65 | #include "libbb.h" | ||
67 | 66 | ||
68 | struct arp_packet { | 67 | struct arp_packet { |
69 | struct ether_header hdr; | 68 | struct ether_header hdr; |
70 | // FIXME this part is netinet/if_ether.h "struct ether_arp" | 69 | /* FIXME this part is netinet/if_ether.h "struct ether_arp" */ |
71 | struct arphdr arp; | 70 | struct arphdr arp; |
72 | struct ether_addr source_addr; | 71 | struct ether_addr source_addr; |
73 | struct in_addr source_ip; | 72 | struct in_addr source_ip; |
@@ -90,29 +89,13 @@ static const unsigned ANNOUNCE_NUM = 2; | |||
90 | static const unsigned ANNOUNCE_INTERVAL = 2; | 89 | static const unsigned ANNOUNCE_INTERVAL = 2; |
91 | static const time_t DEFEND_INTERVAL = 10; | 90 | static const time_t DEFEND_INTERVAL = 10; |
92 | 91 | ||
93 | static const unsigned char ZCIP_VERSION[] = "0.75 (18 April 2005)"; | 92 | #define ZCIP_VERSION "0.75 (18 April 2005)" |
94 | static char *prog; | ||
95 | 93 | ||
96 | static const struct in_addr null_ip = { 0 }; | 94 | static const struct in_addr null_ip = { 0 }; |
97 | static const struct ether_addr null_addr = { {0, 0, 0, 0, 0, 0} }; | 95 | static const struct ether_addr null_addr = { {0, 0, 0, 0, 0, 0} }; |
98 | 96 | ||
99 | static int verbose = 0; | ||
100 | |||
101 | #ifdef DEBUG | ||
102 | |||
103 | #define DBG(fmt,args...) \ | ||
104 | fprintf(stderr, "%s: " fmt , prog , ## args) | ||
105 | #define VDBG(fmt,args...) do { \ | ||
106 | if (verbose) fprintf(stderr, "%s: " fmt , prog ,## args); \ | ||
107 | } while (0) | ||
108 | #else | ||
109 | |||
110 | #define DBG(fmt,args...) \ | ||
111 | do { } while (0) | ||
112 | #define VDBG DBG | ||
113 | #endif /* DEBUG */ | ||
114 | 97 | ||
115 | /** | 98 | /* |
116 | * Pick a random link local IP address on 169.254/16, except that | 99 | * Pick a random link local IP address on 169.254/16, except that |
117 | * the first and last 256 addresses are reserved. | 100 | * the first and last 256 addresses are reserved. |
118 | */ | 101 | */ |
@@ -128,7 +111,7 @@ pick(struct in_addr *ip) | |||
128 | ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp); | 111 | ip->s_addr = htonl((LINKLOCAL_ADDR + 0x0100) + tmp); |
129 | } | 112 | } |
130 | 113 | ||
131 | /** | 114 | /* |
132 | * Broadcast an ARP packet. | 115 | * Broadcast an ARP packet. |
133 | */ | 116 | */ |
134 | static int | 117 | static int |
@@ -138,12 +121,12 @@ arp(int fd, struct sockaddr *saddr, int op, | |||
138 | { | 121 | { |
139 | struct arp_packet p; | 122 | struct arp_packet p; |
140 | 123 | ||
141 | // ether header | 124 | /* ether header */ |
142 | p.hdr.ether_type = htons(ETHERTYPE_ARP); | 125 | p.hdr.ether_type = htons(ETHERTYPE_ARP); |
143 | memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN); | 126 | memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN); |
144 | memset(p.hdr.ether_dhost, 0xff, ETH_ALEN); | 127 | memset(p.hdr.ether_dhost, 0xff, ETH_ALEN); |
145 | 128 | ||
146 | // arp request | 129 | /* arp request */ |
147 | p.arp.ar_hrd = htons(ARPHRD_ETHER); | 130 | p.arp.ar_hrd = htons(ARPHRD_ETHER); |
148 | p.arp.ar_pro = htons(ETHERTYPE_IP); | 131 | p.arp.ar_pro = htons(ETHERTYPE_IP); |
149 | p.arp.ar_hln = ETH_ALEN; | 132 | p.arp.ar_hln = ETH_ALEN; |
@@ -154,15 +137,15 @@ arp(int fd, struct sockaddr *saddr, int op, | |||
154 | memcpy(&p.target_addr, target_addr, ETH_ALEN); | 137 | memcpy(&p.target_addr, target_addr, ETH_ALEN); |
155 | memcpy(&p.target_ip, &target_ip, sizeof (p.target_ip)); | 138 | memcpy(&p.target_ip, &target_ip, sizeof (p.target_ip)); |
156 | 139 | ||
157 | // send it | 140 | /* send it */ |
158 | if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) { | 141 | if (sendto(fd, &p, sizeof (p), 0, saddr, sizeof (*saddr)) < 0) { |
159 | perror("sendto"); | 142 | bb_perror_msg("sendto"); |
160 | return -errno; | 143 | return -errno; |
161 | } | 144 | } |
162 | return 0; | 145 | return 0; |
163 | } | 146 | } |
164 | 147 | ||
165 | /** | 148 | /* |
166 | * Run a script. | 149 | * Run a script. |
167 | */ | 150 | */ |
168 | static int | 151 | static int |
@@ -172,21 +155,19 @@ run(char *script, char *arg, char *intf, struct in_addr *ip) | |||
172 | char *why; | 155 | char *why; |
173 | 156 | ||
174 | if (script != NULL) { | 157 | if (script != NULL) { |
175 | VDBG("%s run %s %s\n", intf, script, arg); | ||
176 | if (ip != NULL) { | 158 | if (ip != NULL) { |
177 | char *addr = inet_ntoa(*ip); | 159 | char *addr = inet_ntoa(*ip); |
178 | setenv("ip", addr, 1); | 160 | xsetenv("ip", addr); |
179 | syslog(LOG_INFO, "%s %s %s", arg, intf, addr); | 161 | syslog(LOG_INFO, "%s %s %s", arg, intf, addr); |
180 | } | 162 | } |
181 | 163 | ||
182 | pid = vfork(); | 164 | pid = vfork(); |
183 | if (pid < 0) { // error | 165 | if (pid < 0) { /* error */ |
184 | why = "vfork"; | 166 | why = "vfork"; |
185 | goto bad; | 167 | goto bad; |
186 | } else if (pid == 0) { // child | 168 | } else if (pid == 0) { /* child */ |
187 | execl(script, script, arg, NULL); | 169 | execl(script, script, arg, NULL); |
188 | perror("execl"); | 170 | bb_perror_msg_and_die("execl"); |
189 | _exit(EXIT_FAILURE); | ||
190 | } | 171 | } |
191 | 172 | ||
192 | if (waitpid(pid, &status, 0) <= 0) { | 173 | if (waitpid(pid, &status, 0) <= 0) { |
@@ -194,8 +175,7 @@ run(char *script, char *arg, char *intf, struct in_addr *ip) | |||
194 | goto bad; | 175 | goto bad; |
195 | } | 176 | } |
196 | if (WEXITSTATUS(status) != 0) { | 177 | if (WEXITSTATUS(status) != 0) { |
197 | fprintf(stderr, "%s: script %s failed, exit=%d\n", | 178 | bb_perror_msg("script %s failed, exit=%d", script, WEXITSTATUS(status)); |
198 | prog, script, WEXITSTATUS(status)); | ||
199 | return -errno; | 179 | return -errno; |
200 | } | 180 | } |
201 | } | 181 | } |
@@ -207,31 +187,7 @@ bad: | |||
207 | return status; | 187 | return status; |
208 | } | 188 | } |
209 | 189 | ||
210 | #ifndef NO_BUSYBOX | 190 | /* |
211 | #include "busybox.h" | ||
212 | #endif | ||
213 | |||
214 | /** | ||
215 | * Print usage information. | ||
216 | */ | ||
217 | static void __attribute__ ((noreturn)) | ||
218 | usage(const char *msg) | ||
219 | { | ||
220 | fprintf(stderr, "%s: %s\n", prog, msg); | ||
221 | #ifdef NO_BUSYBOX | ||
222 | fprintf(stderr, "Usage: %s [OPTIONS] ifname script\n" | ||
223 | "\t-f foreground mode (implied by -v)\n" | ||
224 | "\t-q quit after address (no daemon)\n" | ||
225 | "\t-r 169.254.x.x request this address first\n" | ||
226 | "\t-v verbose; show version\n", | ||
227 | prog); | ||
228 | exit(0); | ||
229 | #else | ||
230 | bb_show_usage(); | ||
231 | #endif | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * Return milliseconds of random delay, up to "secs" seconds. | 191 | * Return milliseconds of random delay, up to "secs" seconds. |
236 | */ | 192 | */ |
237 | static inline unsigned | 193 | static inline unsigned |
@@ -240,85 +196,72 @@ ms_rdelay(unsigned secs) | |||
240 | return lrand48() % (secs * 1000); | 196 | return lrand48() % (secs * 1000); |
241 | } | 197 | } |
242 | 198 | ||
243 | /** | 199 | /* |
244 | * main program | 200 | * main program |
245 | */ | 201 | */ |
246 | int | 202 | |
247 | main(int argc, char *argv[]) | 203 | #define FOREGROUND 1 |
248 | __attribute__ ((weak, alias ("zcip_main"))); | 204 | #define QUIT 2 |
205 | #define REQUEST 4 | ||
206 | #define VERBOSE 8 | ||
249 | 207 | ||
250 | int zcip_main(int argc, char *argv[]) | 208 | int zcip_main(int argc, char *argv[]) |
251 | { | 209 | { |
252 | char *intf = NULL; | 210 | char *intf = NULL; |
253 | char *script = NULL; | 211 | char *script = NULL; |
254 | int quit = 0; | ||
255 | int foreground = 0; | ||
256 | |||
257 | char *why; | 212 | char *why; |
258 | struct sockaddr saddr; | 213 | struct sockaddr saddr; |
259 | struct ether_addr addr; | 214 | struct ether_addr addr; |
260 | struct in_addr ip = { 0 }; | 215 | struct in_addr ip = { 0 }; |
261 | int fd; | 216 | int fd; |
262 | int ready = 0; | 217 | int ready = 0; |
263 | suseconds_t timeout = 0; // milliseconds | 218 | suseconds_t timeout = 0; /* milliseconds */ |
264 | time_t defend = 0; | 219 | time_t defend = 0; |
265 | unsigned conflicts = 0; | 220 | unsigned conflicts = 0; |
266 | unsigned nprobes = 0; | 221 | unsigned nprobes = 0; |
267 | unsigned nclaims = 0; | 222 | unsigned nclaims = 0; |
268 | int t; | 223 | unsigned long t; |
269 | 224 | ||
270 | // parse commandline: prog [options] ifname script | 225 | bb_opt_complementaly = "vf"; |
271 | prog = argv[0]; | 226 | /* parse commandline: prog [options] ifname script */ |
272 | while ((t = getopt(argc, argv, "fqr:v")) != EOF) { | 227 | t = bb_getopt_ulflags(argc, argv, "fqr:v", &why); /* reuse char* why */ |
273 | switch (t) { | 228 | |
274 | case 'f': | 229 | argc -= optind; |
275 | foreground = 1; | 230 | argv += optind; |
276 | continue; | 231 | |
277 | case 'q': | 232 | if ((t & 0x80000000UL) || (argc < 1) || (argc > 2)) { |
278 | quit = 1; | 233 | bb_show_usage(); |
279 | continue; | ||
280 | case 'r': | ||
281 | if (inet_aton(optarg, &ip) == 0 | ||
282 | || (ntohl(ip.s_addr) & IN_CLASSB_NET) | ||
283 | != LINKLOCAL_ADDR) { | ||
284 | usage("invalid link address"); | ||
285 | } | ||
286 | continue; | ||
287 | case 'v': | ||
288 | if (!verbose) | ||
289 | printf("%s: version %s\n", prog, ZCIP_VERSION); | ||
290 | verbose++; | ||
291 | foreground = 1; | ||
292 | continue; | ||
293 | default: | ||
294 | usage("bad option"); | ||
295 | } | ||
296 | } | 234 | } |
297 | if (optind < argc - 1) { | 235 | |
298 | intf = argv[optind++]; | 236 | if (t & VERBOSE) { |
299 | setenv("interface", intf, 1); | 237 | bb_printf("%s: version %s\n", bb_applet_name, ZCIP_VERSION); |
300 | script = argv[optind++]; | ||
301 | } | 238 | } |
302 | if (optind != argc || !intf) | 239 | if ((t & REQUEST) && (inet_aton(why, &ip) == 0 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != LINKLOCAL_ADDR)) { |
303 | usage("wrong number of arguments"); | 240 | bb_perror_msg_and_die("invalid link address"); |
304 | openlog(prog, 0, LOG_DAEMON); | 241 | } |
305 | 242 | ||
306 | // initialize the interface (modprobe, ifup, etc) | 243 | intf = argv[0]; |
244 | xsetenv("interface", intf); | ||
245 | script = argv[1]; /* Could be NULL ? */ | ||
246 | |||
247 | openlog(bb_applet_name, 0, LOG_DAEMON); | ||
248 | |||
249 | /* initialize the interface (modprobe, ifup, etc) */ | ||
307 | if (run(script, "init", intf, NULL) < 0) | 250 | if (run(script, "init", intf, NULL) < 0) |
308 | return EXIT_FAILURE; | 251 | return EXIT_FAILURE; |
309 | 252 | ||
310 | // initialize saddr | 253 | /* initialize saddr */ |
311 | memset(&saddr, 0, sizeof (saddr)); | 254 | memset(&saddr, 0, sizeof (saddr)); |
312 | strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data)); | 255 | strncpy(saddr.sa_data, intf, sizeof (saddr.sa_data)); |
313 | 256 | ||
314 | // open an ARP socket | 257 | /* open an ARP socket */ |
315 | if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) { | 258 | if ((fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) { |
316 | why = "open"; | 259 | why = "open"; |
317 | fail: | 260 | fail: |
318 | foreground = 1; | 261 | t |= FOREGROUND; |
319 | goto bad; | 262 | goto bad; |
320 | } | 263 | } |
321 | // bind to the interface's ARP socket | 264 | /* bind to the interface's ARP socket */ |
322 | if (bind(fd, &saddr, sizeof (saddr)) < 0) { | 265 | if (bind(fd, &saddr, sizeof (saddr)) < 0) { |
323 | why = "bind"; | 266 | why = "bind"; |
324 | goto fail; | 267 | goto fail; |
@@ -326,7 +269,7 @@ fail: | |||
326 | struct ifreq ifr; | 269 | struct ifreq ifr; |
327 | short seed[3]; | 270 | short seed[3]; |
328 | 271 | ||
329 | // get the interface's ethernet address | 272 | /* get the interface's ethernet address */ |
330 | memset(&ifr, 0, sizeof (ifr)); | 273 | memset(&ifr, 0, sizeof (ifr)); |
331 | strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name)); | 274 | strncpy(ifr.ifr_name, intf, sizeof (ifr.ifr_name)); |
332 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { | 275 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { |
@@ -335,37 +278,37 @@ fail: | |||
335 | } | 278 | } |
336 | memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); | 279 | memcpy(&addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); |
337 | 280 | ||
338 | // start with some stable ip address, either a function of | 281 | /* start with some stable ip address, either a function of |
339 | // the hardware address or else the last address we used. | 282 | the hardware address or else the last address we used. |
340 | // NOTE: the sequence of addresses we try changes only | 283 | NOTE: the sequence of addresses we try changes only |
341 | // depending on when we detect conflicts. | 284 | depending on when we detect conflicts. */ |
342 | memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); | 285 | memcpy(seed, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); |
343 | seed48(seed); | 286 | seed48(seed); |
344 | if (ip.s_addr == 0) | 287 | if (ip.s_addr == 0) |
345 | pick(&ip); | 288 | pick(&ip); |
346 | } | 289 | } |
347 | 290 | ||
348 | // FIXME cases to handle: | 291 | /* FIXME cases to handle: |
349 | // - zcip already running! | 292 | - zcip already running! |
350 | // - link already has local address... just defend/update | 293 | - link already has local address... just defend/update */ |
351 | 294 | ||
352 | // daemonize now; don't delay system startup | 295 | /* daemonize now; don't delay system startup */ |
353 | if (!foreground) { | 296 | if (!(t & FOREGROUND)) { |
354 | if (daemon(0, verbose) < 0) { | 297 | if (daemon(0, (t & VERBOSE)) < 0) { |
355 | why = "daemon"; | 298 | why = "daemon"; |
356 | goto bad; | 299 | goto bad; |
357 | } | 300 | } |
358 | syslog(LOG_INFO, "start, interface %s", intf); | 301 | syslog(LOG_INFO, "start, interface %s", intf); |
359 | } | 302 | } |
360 | 303 | ||
361 | // run the dynamic address negotiation protocol, | 304 | /* run the dynamic address negotiation protocol, |
362 | // restarting after address conflicts: | 305 | restarting after address conflicts: |
363 | // - start with some address we want to try | 306 | - start with some address we want to try |
364 | // - short random delay | 307 | - short random delay |
365 | // - arp probes to see if another host else uses it | 308 | - arp probes to see if another host else uses it |
366 | // - arp announcements that we're claiming it | 309 | - arp announcements that we're claiming it |
367 | // - use it | 310 | - use it |
368 | // - defend it, within limits | 311 | - defend it, within limits */ |
369 | while (1) { | 312 | while (1) { |
370 | struct pollfd fds[1]; | 313 | struct pollfd fds[1]; |
371 | struct timeval tv1; | 314 | struct timeval tv1; |
@@ -375,7 +318,7 @@ fail: | |||
375 | fds[0].events = POLLIN; | 318 | fds[0].events = POLLIN; |
376 | fds[0].revents = 0; | 319 | fds[0].revents = 0; |
377 | 320 | ||
378 | // poll, being ready to adjust current timeout | 321 | /* poll, being ready to adjust current timeout */ |
379 | if (timeout > 0) { | 322 | if (timeout > 0) { |
380 | gettimeofday(&tv1, NULL); | 323 | gettimeofday(&tv1, NULL); |
381 | tv1.tv_usec += (timeout % 1000) * 1000; | 324 | tv1.tv_usec += (timeout % 1000) * 1000; |
@@ -386,21 +329,17 @@ fail: | |||
386 | tv1.tv_sec += timeout / 1000; | 329 | tv1.tv_sec += timeout / 1000; |
387 | } else if (timeout == 0) { | 330 | } else if (timeout == 0) { |
388 | timeout = ms_rdelay(PROBE_WAIT); | 331 | timeout = ms_rdelay(PROBE_WAIT); |
389 | // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to | 332 | /* FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to |
390 | // make the kernel filter out all packets except | 333 | make the kernel filter out all packets except |
391 | // ones we'd care about. | 334 | ones we'd care about. */ |
392 | } | 335 | } |
393 | VDBG("...wait %ld %s nprobes=%d, nclaims=%d\n", | ||
394 | timeout, intf, nprobes, nclaims); | ||
395 | switch (poll(fds, 1, timeout)) { | 336 | switch (poll(fds, 1, timeout)) { |
396 | 337 | ||
397 | // timeouts trigger protocol transitions | 338 | /* timeouts trigger protocol transitions */ |
398 | case 0: | 339 | case 0: |
399 | // probes | 340 | /* probes */ |
400 | if (nprobes < PROBE_NUM) { | 341 | if (nprobes < PROBE_NUM) { |
401 | nprobes++; | 342 | nprobes++; |
402 | VDBG("probe/%d %s@%s\n", | ||
403 | nprobes, intf, inet_ntoa(ip)); | ||
404 | (void)arp(fd, &saddr, ARPOP_REQUEST, | 343 | (void)arp(fd, &saddr, ARPOP_REQUEST, |
405 | &addr, null_ip, | 344 | &addr, null_ip, |
406 | &null_addr, ip); | 345 | &null_addr, ip); |
@@ -411,38 +350,36 @@ fail: | |||
411 | } else | 350 | } else |
412 | timeout = ANNOUNCE_WAIT * 1000; | 351 | timeout = ANNOUNCE_WAIT * 1000; |
413 | } | 352 | } |
414 | // then announcements | 353 | /* then announcements */ |
415 | else if (nclaims < ANNOUNCE_NUM) { | 354 | else if (nclaims < ANNOUNCE_NUM) { |
416 | nclaims++; | 355 | nclaims++; |
417 | VDBG("announce/%d %s@%s\n", | ||
418 | nclaims, intf, inet_ntoa(ip)); | ||
419 | (void)arp(fd, &saddr, ARPOP_REQUEST, | 356 | (void)arp(fd, &saddr, ARPOP_REQUEST, |
420 | &addr, ip, | 357 | &addr, ip, |
421 | &addr, ip); | 358 | &addr, ip); |
422 | if (nclaims < ANNOUNCE_NUM) { | 359 | if (nclaims < ANNOUNCE_NUM) { |
423 | timeout = ANNOUNCE_INTERVAL * 1000; | 360 | timeout = ANNOUNCE_INTERVAL * 1000; |
424 | } else { | 361 | } else { |
425 | // link is ok to use earlier | 362 | /* link is ok to use earlier */ |
426 | run(script, "config", intf, &ip); | 363 | run(script, "config", intf, &ip); |
427 | ready = 1; | 364 | ready = 1; |
428 | conflicts = 0; | 365 | conflicts = 0; |
429 | timeout = -1; | 366 | timeout = -1; |
430 | 367 | ||
431 | // NOTE: all other exit paths | 368 | /* NOTE: all other exit paths |
432 | // should deconfig ... | 369 | should deconfig ... */ |
433 | if (quit) | 370 | if (t & QUIT) |
434 | return EXIT_SUCCESS; | 371 | return EXIT_SUCCESS; |
435 | // FIXME update filters | 372 | /* FIXME update filters */ |
436 | } | 373 | } |
437 | } | 374 | } |
438 | break; | 375 | break; |
439 | 376 | ||
440 | // packets arriving | 377 | /* packets arriving */ |
441 | case 1: | 378 | case 1: |
442 | // maybe adjust timeout | 379 | /* maybe adjust timeout */ |
443 | if (timeout > 0) { | 380 | if (timeout > 0) { |
444 | struct timeval tv2; | 381 | struct timeval tv2; |
445 | 382 | ||
446 | gettimeofday(&tv2, NULL); | 383 | gettimeofday(&tv2, NULL); |
447 | if (timercmp(&tv1, &tv2, <)) { | 384 | if (timercmp(&tv1, &tv2, <)) { |
448 | timeout = -1; | 385 | timeout = -1; |
@@ -454,46 +391,33 @@ fail: | |||
454 | } | 391 | } |
455 | if ((fds[0].revents & POLLIN) == 0) { | 392 | if ((fds[0].revents & POLLIN) == 0) { |
456 | if (fds[0].revents & POLLERR) { | 393 | if (fds[0].revents & POLLERR) { |
457 | // FIXME: links routinely go down; | 394 | /* FIXME: links routinely go down; |
458 | // this shouldn't necessarily exit. | 395 | this shouldn't necessarily exit. */ |
459 | fprintf(stderr, "%s %s: poll error\n", | 396 | bb_perror_msg("%s: poll error", intf); |
460 | prog, intf); | ||
461 | if (ready) { | 397 | if (ready) { |
462 | run(script, "deconfig", | 398 | run(script, "deconfig", intf, &ip); |
463 | intf, &ip); | ||
464 | } | 399 | } |
465 | return EXIT_FAILURE; | 400 | return EXIT_FAILURE; |
466 | } | 401 | } |
467 | continue; | 402 | continue; |
468 | } | 403 | } |
469 | // read ARP packet | 404 | /* read ARP packet */ |
470 | if (recv(fd, &p, sizeof (p), 0) < 0) { | 405 | if (recv(fd, &p, sizeof (p), 0) < 0) { |
471 | why = "recv"; | 406 | why = "recv"; |
472 | goto bad; | 407 | goto bad; |
473 | } | 408 | } |
474 | if (p.hdr.ether_type != htons(ETHERTYPE_ARP)) | 409 | if (p.hdr.ether_type != htons(ETHERTYPE_ARP)) |
475 | continue; | 410 | continue; |
476 | 411 | ||
477 | VDBG("%s recv arp type=%d, op=%d,\n", | ||
478 | intf, ntohs(p.hdr.ether_type), | ||
479 | ntohs(p.arp.ar_op)); | ||
480 | VDBG("\tsource=%s %s\n", | ||
481 | ether_ntoa(&p.source_addr), | ||
482 | inet_ntoa(p.source_ip)); | ||
483 | VDBG("\ttarget=%s %s\n", | ||
484 | ether_ntoa(&p.target_addr), | ||
485 | inet_ntoa(p.target_ip)); | ||
486 | if (p.arp.ar_op != htons(ARPOP_REQUEST) | 412 | if (p.arp.ar_op != htons(ARPOP_REQUEST) |
487 | && p.arp.ar_op != htons(ARPOP_REPLY)) | 413 | && p.arp.ar_op != htons(ARPOP_REPLY)) |
488 | continue; | 414 | continue; |
489 | 415 | ||
490 | // some cases are always conflicts | 416 | /* some cases are always conflicts */ |
491 | if ((p.source_ip.s_addr == ip.s_addr) | 417 | if ((p.source_ip.s_addr == ip.s_addr) |
492 | && (memcmp(&addr, &p.source_addr, | 418 | && (memcmp(&addr, &p.source_addr, |
493 | ETH_ALEN) != 0)) { | 419 | ETH_ALEN) != 0)) { |
494 | collision: | 420 | collision: |
495 | VDBG("%s ARP conflict from %s\n", intf, | ||
496 | ether_ntoa(&p.source_addr)); | ||
497 | if (ready) { | 421 | if (ready) { |
498 | time_t now = time(0); | 422 | time_t now = time(0); |
499 | 423 | ||
@@ -504,28 +428,26 @@ collision: | |||
504 | ARPOP_REQUEST, | 428 | ARPOP_REQUEST, |
505 | &addr, ip, | 429 | &addr, ip, |
506 | &addr, ip); | 430 | &addr, ip); |
507 | VDBG("%s defend\n", intf); | ||
508 | timeout = -1; | 431 | timeout = -1; |
509 | continue; | 432 | continue; |
510 | } | 433 | } |
511 | defend = now; | 434 | defend = now; |
512 | ready = 0; | 435 | ready = 0; |
513 | run(script, "deconfig", intf, &ip); | 436 | run(script, "deconfig", intf, &ip); |
514 | // FIXME rm filters: setsockopt(fd, | 437 | /* FIXME rm filters: setsockopt(fd, |
515 | // SO_DETACH_FILTER, ...) | 438 | SO_DETACH_FILTER, ...) */ |
516 | } | 439 | } |
517 | conflicts++; | 440 | conflicts++; |
518 | if (conflicts >= MAX_CONFLICTS) { | 441 | if (conflicts >= MAX_CONFLICTS) { |
519 | VDBG("%s ratelimit\n", intf); | ||
520 | sleep(RATE_LIMIT_INTERVAL); | 442 | sleep(RATE_LIMIT_INTERVAL); |
521 | } | 443 | } |
522 | // restart the whole protocol | 444 | /* restart the whole protocol */ |
523 | pick(&ip); | 445 | pick(&ip); |
524 | timeout = 0; | 446 | timeout = 0; |
525 | nprobes = 0; | 447 | nprobes = 0; |
526 | nclaims = 0; | 448 | nclaims = 0; |
527 | } | 449 | } |
528 | // two hosts probing one address is a collision too | 450 | /* two hosts probing one address is a collision too */ |
529 | else if (p.target_ip.s_addr == ip.s_addr | 451 | else if (p.target_ip.s_addr == ip.s_addr |
530 | && nclaims == 0 | 452 | && nclaims == 0 |
531 | && p.arp.ar_op == htons(ARPOP_REQUEST) | 453 | && p.arp.ar_op == htons(ARPOP_REQUEST) |
@@ -541,10 +463,11 @@ collision: | |||
541 | } | 463 | } |
542 | } | 464 | } |
543 | bad: | 465 | bad: |
544 | if (foreground) | 466 | if ( t & FOREGROUND) { |
545 | perror(why); | 467 | bb_perror_msg(why); |
546 | else | 468 | } else { |
547 | syslog(LOG_ERR, "%s %s, %s error: %s", | 469 | syslog(LOG_ERR, "%s %s, %s error: %s", |
548 | prog, intf, why, strerror(errno)); | 470 | bb_applet_name, intf, why, strerror(errno)); |
471 | } | ||
549 | return EXIT_FAILURE; | 472 | return EXIT_FAILURE; |
550 | } | 473 | } |