aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-08-04 14:30:31 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2015-08-04 14:30:31 +0200
commite3475838354d6bba414ab8cdc2211313ad29dc9d (patch)
treed69db28b9ba48596afd2e1df8e6fe28d04c52f65
parent99e30be38bc167a3b5729154a27ccdb15bbaadb2 (diff)
downloadbusybox-w32-e3475838354d6bba414ab8cdc2211313ad29dc9d.tar.gz
busybox-w32-e3475838354d6bba414ab8cdc2211313ad29dc9d.tar.bz2
busybox-w32-e3475838354d6bba414ab8cdc2211313ad29dc9d.zip
zcip: another code shrink
function old new delta send_arp_request - 185 +185 zcip_main 1273 1272 -1 pick_nip 40 - -40 arp 185 - -185 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 0/1 up/down: 185/-226) Total: -41 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/zcip.c307
1 files changed, 148 insertions, 159 deletions
diff --git a/networking/zcip.c b/networking/zcip.c
index 5877a8317..a167c7e91 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -90,7 +90,7 @@ enum {
90 90
91struct globals { 91struct globals {
92 struct sockaddr iface_sockaddr; 92 struct sockaddr iface_sockaddr;
93 struct ether_addr eth_addr; 93 struct ether_addr our_ethaddr;
94 uint32_t localnet_ip; 94 uint32_t localnet_ip;
95} FIX_ALIASING; 95} FIX_ALIASING;
96#define G (*(struct globals*)&bb_common_bufsiz1) 96#define G (*(struct globals*)&bb_common_bufsiz1)
@@ -121,14 +121,14 @@ static const char *nip_to_a(uint32_t nip)
121/** 121/**
122 * Broadcast an ARP packet. 122 * Broadcast an ARP packet.
123 */ 123 */
124static void arp( 124static void send_arp_request(
125 /* int op, - always ARPOP_REQUEST */ 125 /* int op, - always ARPOP_REQUEST */
126 /* const struct ether_addr *source_eth, - always &G.eth_addr */ 126 /* const struct ether_addr *source_eth, - always &G.our_ethaddr */
127 uint32_t source_nip, 127 uint32_t source_nip,
128 const struct ether_addr *target_eth, uint32_t target_nip) 128 const struct ether_addr *target_eth, uint32_t target_nip)
129{ 129{
130 enum { op = ARPOP_REQUEST }; 130 enum { op = ARPOP_REQUEST };
131#define source_eth (&G.eth_addr) 131#define source_eth (&G.our_ethaddr)
132 132
133 struct arp_packet p; 133 struct arp_packet p;
134 memset(&p, 0, sizeof(p)); 134 memset(&p, 0, sizeof(p));
@@ -205,35 +205,34 @@ static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs)
205int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 205int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
206int zcip_main(int argc UNUSED_PARAM, char **argv) 206int zcip_main(int argc UNUSED_PARAM, char **argv)
207{ 207{
208 int state;
209 char *r_opt; 208 char *r_opt;
210 const char *l_opt = "169.254.0.0"; 209 const char *l_opt = "169.254.0.0";
210 int state;
211 int nsent;
211 unsigned opts; 212 unsigned opts;
212 213
213 // ugly trick, but I want these zeroed in one go 214 // Ugly trick, but I want these zeroed in one go
214 struct { 215 struct {
215 const struct ether_addr null_addr; 216 const struct ether_addr null_ethaddr;
216 struct ifreq ifr; 217 struct ifreq ifr;
217 uint32_t chosen_nip; 218 uint32_t chosen_nip;
219 int conflicts;
218 int timeout_ms; // must be signed 220 int timeout_ms; // must be signed
219 unsigned conflicts;
220 unsigned nsent;
221 int verbose; 221 int verbose;
222 } L; 222 } L;
223#define null_addr (L.null_addr ) 223#define null_ethaddr (L.null_ethaddr)
224#define ifr (L.ifr ) 224#define ifr (L.ifr )
225#define chosen_nip (L.chosen_nip) 225#define chosen_nip (L.chosen_nip )
226#define timeout_ms (L.timeout_ms) 226#define conflicts (L.conflicts )
227#define conflicts (L.conflicts ) 227#define timeout_ms (L.timeout_ms )
228#define nsent (L.nsent ) 228#define verbose (L.verbose )
229#define verbose (L.verbose )
230 229
231 memset(&L, 0, sizeof(L)); 230 memset(&L, 0, sizeof(L));
232 INIT_G(); 231 INIT_G();
233 232
234#define FOREGROUND (opts & 1) 233#define FOREGROUND (opts & 1)
235#define QUIT (opts & 2) 234#define QUIT (opts & 2)
236 // parse commandline: prog [options] ifname script 235 // Parse commandline: prog [options] ifname script
237 // exactly 2 args; -v accumulates and implies -f 236 // exactly 2 args; -v accumulates and implies -f
238 opt_complementary = "=2:vv:vf"; 237 opt_complementary = "=2:vv:vf";
239 opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose); 238 opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose);
@@ -242,7 +241,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
242 if (!FOREGROUND) 241 if (!FOREGROUND)
243 bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv); 242 bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv);
244#endif 243#endif
245 // open an ARP socket 244 // Open an ARP socket
246 // (need to do it before openlog to prevent openlog from taking 245 // (need to do it before openlog to prevent openlog from taking
247 // fd 3 (sock_fd==3)) 246 // fd 3 (sock_fd==3))
248 xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); 247 xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
@@ -282,26 +281,26 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
282 281
283 xsetenv("interface", argv_intf); 282 xsetenv("interface", argv_intf);
284 283
285 // initialize the interface (modprobe, ifup, etc) 284 // Initialize the interface (modprobe, ifup, etc)
286 if (run(argv, "init", 0)) 285 if (run(argv, "init", 0))
287 return EXIT_FAILURE; 286 return EXIT_FAILURE;
288 287
289 // initialize G.iface_sockaddr 288 // Initialize G.iface_sockaddr
290 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; } 289 // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; }
291 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr)); 290 //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr));
292 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! 291 //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
293 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data)); 292 safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data));
294 293
295 // bind to the interface's ARP socket 294 // Bind to the interface's ARP socket
296 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr)); 295 xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr));
297 296
298 // get the interface's ethernet address 297 // Get the interface's ethernet address
299 //memset(&ifr, 0, sizeof(ifr)); 298 //memset(&ifr, 0, sizeof(ifr));
300 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); 299 strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf);
301 xioctl(sock_fd, SIOCGIFHWADDR, &ifr); 300 xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
302 memcpy(&G.eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 301 memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
303 302
304 // start with some stable ip address, either a function of 303 // Start with some stable ip address, either a function of
305 // the hardware address or else the last address we used. 304 // the hardware address or else the last address we used.
306 // we are taking low-order four bytes, as top-order ones 305 // we are taking low-order four bytes, as top-order ones
307 // aren't random enough. 306 // aren't random enough.
@@ -309,17 +308,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
309 // depending on when we detect conflicts. 308 // depending on when we detect conflicts.
310 { 309 {
311 uint32_t t; 310 uint32_t t;
312 move_from_unaligned32(t, ((char *)&G.eth_addr + 2)); 311 move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2));
313 srand(t); 312 srand(t);
314 } 313 }
315 if (chosen_nip == 0)
316 chosen_nip = pick_nip();
317
318 // FIXME cases to handle: 314 // FIXME cases to handle:
319 // - zcip already running! 315 // - zcip already running!
320 // - link already has local address... just defend/update 316 // - link already has local address... just defend/update
321 317
322 // daemonize now; don't delay system startup 318 // Daemonize now; don't delay system startup
323 if (!FOREGROUND) { 319 if (!FOREGROUND) {
324#if BB_MMU 320#if BB_MMU
325 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); 321 bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/);
@@ -327,14 +323,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
327 bb_info_msg("start, interface %s", argv_intf); 323 bb_info_msg("start, interface %s", argv_intf);
328 } 324 }
329 325
330 // run the dynamic address negotiation protocol, 326 // Run the dynamic address negotiation protocol,
331 // restarting after address conflicts: 327 // restarting after address conflicts:
332 // - start with some address we want to try 328 // - start with some address we want to try
333 // - short random delay 329 // - short random delay
334 // - arp probes to see if another host uses it 330 // - arp probes to see if another host uses it
335 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 tell 0.0.0.0 331 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff: arp who-has 169.254.194.171 tell 0.0.0.0
336 // - arp announcements that we're claiming it 332 // - arp announcements that we're claiming it
337 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 333 // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff: arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171
338 // - use it 334 // - use it
339 // - defend it, within limits 335 // - defend it, within limits
340 // exit if: 336 // exit if:
@@ -342,73 +338,73 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
342 // run "<script> config", then exit with exitcode 0 338 // run "<script> config", then exit with exitcode 0
343 // - poll error (when does this happen?) 339 // - poll error (when does this happen?)
344 // - read error (when does this happen?) 340 // - read error (when does this happen?)
345 // - sendto error (in arp()) (when does this happen?) 341 // - sendto error (in send_arp_request()) (when does this happen?)
346 // - revents & POLLERR (link down). run "<script> deconfig" first 342 // - revents & POLLERR (link down). run "<script> deconfig" first
343 if (chosen_nip == 0) {
344 new_nip_and_PROBE:
345 chosen_nip = pick_nip();
346 }
347 nsent = 0;
347 state = PROBE; 348 state = PROBE;
348 while (1) { 349 while (1) {
349 struct pollfd fds[1]; 350 struct pollfd fds[1];
350 unsigned deadline_us; 351 unsigned deadline_us;
351 struct arp_packet p; 352 struct arp_packet p;
352 int ip_conflict; 353 int ip_conflict;
354 int n;
353 355
354 fds[0].fd = sock_fd; 356 fds[0].fd = sock_fd;
355 fds[0].events = POLLIN; 357 fds[0].events = POLLIN;
356 fds[0].revents = 0; 358 fds[0].revents = 0;
357 359
358 // poll, being ready to adjust current timeout 360 // Poll, being ready to adjust current timeout
359 if (!timeout_ms) { 361 if (!timeout_ms) {
360 timeout_ms = random_delay_ms(PROBE_WAIT); 362 timeout_ms = random_delay_ms(PROBE_WAIT);
361 // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to 363 // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
362 // make the kernel filter out all packets except 364 // make the kernel filter out all packets except
363 // ones we'd care about. 365 // ones we'd care about.
364 } 366 }
365 // set deadline_us to the point in time when we timeout 367 // Set deadline_us to the point in time when we timeout
366 deadline_us = MONOTONIC_US() + timeout_ms * 1000; 368 deadline_us = MONOTONIC_US() + timeout_ms * 1000;
367 369
368 VDBG("...wait %d %s nsent=%u\n", 370 VDBG("...wait %d %s nsent=%u\n",
369 timeout_ms, argv_intf, nsent); 371 timeout_ms, argv_intf, nsent);
370 372
371 switch (safe_poll(fds, 1, timeout_ms)) { 373 n = safe_poll(fds, 1, timeout_ms);
372 374 if (n < 0) {
373 default:
374 //bb_perror_msg("poll"); - done in safe_poll 375 //bb_perror_msg("poll"); - done in safe_poll
375 return EXIT_FAILURE; 376 return EXIT_FAILURE;
376 377 }
377 // timeout 378 if (n == 0) { // timed out?
378 case 0: 379 VDBG("state:%d\n", state);
379 VDBG("state = %d\n", state);
380 switch (state) { 380 switch (state) {
381 case PROBE: 381 case PROBE:
382 // timeouts in the PROBE state mean no conflicting ARP packets 382 // No conflicting ARP packets were seen:
383 // have been received, so we can progress through the states 383 // we can progress through the states
384 if (nsent < PROBE_NUM) { 384 if (nsent < PROBE_NUM) {
385 nsent++; 385 nsent++;
386 VDBG("probe/%u %s@%s\n", 386 VDBG("probe/%u %s@%s\n",
387 nsent, argv_intf, nip_to_a(chosen_nip)); 387 nsent, argv_intf, nip_to_a(chosen_nip));
388 timeout_ms = PROBE_MIN * 1000; 388 timeout_ms = PROBE_MIN * 1000;
389 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); 389 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
390 arp(/* ARPOP_REQUEST, */ 390 send_arp_request(0, &null_ethaddr, chosen_nip);
391 /* &G.eth_addr, */ 0, 391 continue;
392 &null_addr, chosen_nip);
393 break;
394 } 392 }
395 // Switch to announce state 393 // Switch to announce state
396 nsent = 0; 394 nsent = 0;
397 state = ANNOUNCE; 395 state = ANNOUNCE;
398 goto send_announce; 396 goto send_announce;
399 case ANNOUNCE: 397 case ANNOUNCE:
400 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 398 // No conflicting ARP packets were seen:
401 // have been received, so we can progress through the states 399 // we can progress through the states
402 if (nsent < ANNOUNCE_NUM) { 400 if (nsent < ANNOUNCE_NUM) {
403 send_announce: 401 send_announce:
404 nsent++; 402 nsent++;
405 VDBG("announce/%u %s@%s\n", 403 VDBG("announce/%u %s@%s\n",
406 nsent, argv_intf, nip_to_a(chosen_nip)); 404 nsent, argv_intf, nip_to_a(chosen_nip));
407 timeout_ms = ANNOUNCE_INTERVAL * 1000; 405 timeout_ms = ANNOUNCE_INTERVAL * 1000;
408 arp(/* ARPOP_REQUEST, */ 406 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
409 /* &G.eth_addr, */ chosen_nip, 407 continue;
410 &G.eth_addr, chosen_nip);
411 break;
412 } 408 }
413 // Switch to monitor state 409 // Switch to monitor state
414 // FIXME update filters 410 // FIXME update filters
@@ -416,124 +412,117 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
416 // NOTE: all other exit paths should deconfig... 412 // NOTE: all other exit paths should deconfig...
417 if (QUIT) 413 if (QUIT)
418 return EXIT_SUCCESS; 414 return EXIT_SUCCESS;
419 conflicts = 0; 415 // fall through: switch_to_MONITOR
420 timeout_ms = -1; // Never timeout in the monitor state. 416 default:
421 state = MONITOR; 417 // case DEFEND:
422 break; 418 // case MONITOR: (shouldn't happen, MONITOR timeout is infinite)
423 case DEFEND:
424 // Defend period ended with no ARP replies - we won 419 // Defend period ended with no ARP replies - we won
425 conflicts = 0; 420 timeout_ms = -1; // never timeout in monitor state
426 timeout_ms = -1;
427 state = MONITOR; 421 state = MONITOR;
428 break;
429 } // switch (state)
430 break; // case 0 (timeout)
431
432 // packets arriving, or link went down
433 case 1:
434 // We need to adjust the timeout in case we didn't receive
435 // a conflicting packet.
436 if (timeout_ms > 0) {
437 unsigned diff = deadline_us - MONOTONIC_US();
438 if ((int)(diff) < 0) {
439 // Current time is greater than the expected timeout time.
440 diff = 0;
441 }
442 VDBG("adjusting timeout\n");
443 timeout_ms = (diff / 1000) | 1; // never 0
444 }
445
446 if ((fds[0].revents & POLLIN) == 0) {
447 if (fds[0].revents & POLLERR) {
448 // FIXME: links routinely go down;
449 // this shouldn't necessarily exit.
450 bb_error_msg("iface %s is down", argv_intf);
451 if (state >= MONITOR) {
452 // only if we are in MONITOR or DEFEND
453 run(argv, "deconfig", chosen_nip);
454 }
455 return EXIT_FAILURE;
456 }
457 continue; 422 continue;
458 } 423 }
424 }
459 425
460 // read ARP packet 426 // Packet arrived, or link went down.
461 if (safe_read(sock_fd, &p, sizeof(p)) < 0) { 427 // We need to adjust the timeout in case we didn't receive
462 bb_perror_msg_and_die(bb_msg_read_error); 428 // a conflicting packet.
429 if (timeout_ms > 0) {
430 unsigned diff = deadline_us - MONOTONIC_US();
431 if ((int)(diff) < 0) {
432 // Current time is greater than the expected timeout time.
433 diff = 0;
463 } 434 }
435 VDBG("adjusting timeout\n");
436 timeout_ms = (diff / 1000) | 1; // never 0
437 }
464 438
465 if (p.eth.ether_type != htons(ETHERTYPE_ARP)) 439 if ((fds[0].revents & POLLIN) == 0) {
466 continue; 440 if (fds[0].revents & POLLERR) {
467 if (p.arp.arp_op != htons(ARPOP_REQUEST) 441 // FIXME: links routinely go down;
468 && p.arp.arp_op != htons(ARPOP_REPLY) 442 // this shouldn't necessarily exit.
469 ) { 443 bb_error_msg("iface %s is down", argv_intf);
470 continue; 444 if (state >= MONITOR) {
445 // Only if we are in MONITOR or DEFEND
446 run(argv, "deconfig", chosen_nip);
447 }
448 return EXIT_FAILURE;
471 } 449 }
450 continue;
451 }
452
453 // Read ARP packet
454 if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
455 bb_perror_msg_and_die(bb_msg_read_error);
456 }
457
458 if (p.eth.ether_type != htons(ETHERTYPE_ARP))
459 continue;
460 if (p.arp.arp_op != htons(ARPOP_REQUEST)
461 && p.arp.arp_op != htons(ARPOP_REPLY)
462 ) {
463 continue;
464 }
472#ifdef DEBUG 465#ifdef DEBUG
473 { 466 {
474 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; 467 struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
475 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; 468 struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
476 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; 469 struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
477 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; 470 struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
478 VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa)); 471 VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa));
479 VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa)); 472 VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa));
480 } 473 }
481#endif 474#endif
482 ip_conflict = 0; 475 ip_conflict = 0;
483 if (memcmp(&p.arp.arp_sha, &G.eth_addr, ETH_ALEN) != 0) { 476 if (memcmp(&p.arp.arp_sha, &G.our_ethaddr, ETH_ALEN) != 0) {
484 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) { 477 if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) {
485 // A probe or reply with source_ip == chosen ip 478 // A probe or reply with source_ip == chosen ip
486 ip_conflict = 1; 479 ip_conflict = 1;
487 }
488 if (p.arp.arp_op == htons(ARPOP_REQUEST)
489 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
490 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
491 ) {
492 // A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
493 // another host trying to claim this ip!
494 ip_conflict |= 2;
495 }
496 } 480 }
497 VDBG("state:%d ip_conflict:%d\n", state, ip_conflict); 481 if (p.arp.arp_op == htons(ARPOP_REQUEST)
498 if (!ip_conflict) 482 && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0
499 break; 483 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0
500 484 ) {
501 // Either src or target IP conflict exists 485 // A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
502 if (state <= ANNOUNCE) { 486 // another host trying to claim this ip!
503 // PROBE or ANNOUNCE 487 ip_conflict |= 2;
504 conflicts++;
505 timeout_ms = PROBE_MIN * 1000
506 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
507 chosen_nip = pick_nip();
508 nsent = 0;
509 state = PROBE;
510 break;
511 } 488 }
512 // MONITOR or DEFEND: only src IP conflict is a problem 489 }
513 if (ip_conflict & 1) { 490 VDBG("state:%d ip_conflict:%d\n", state, ip_conflict);
514 if (state == MONITOR) { 491 if (!ip_conflict)
515 // Src IP conflict, defend with a single ARP probe 492 continue;
516 VDBG("monitor conflict - defending\n"); 493
517 timeout_ms = DEFEND_INTERVAL * 1000; 494 // Either src or target IP conflict exists
518 state = DEFEND; 495 if (state <= ANNOUNCE) {
519 arp(/* ARPOP_REQUEST, */ 496 // PROBE or ANNOUNCE
520 /* &G.eth_addr, */ chosen_nip, 497 conflicts++;
521 &G.eth_addr, chosen_nip); 498 timeout_ms = PROBE_MIN * 1000
522 break; 499 + CONFLICT_MULTIPLIER * random_delay_ms(conflicts);
523 } 500 goto new_nip_and_PROBE;
524 // state == DEFEND 501 }
525 // Another src IP conflict, start over 502
526 VDBG("defend conflict - starting over\n"); 503 // MONITOR or DEFEND: only src IP conflict is a problem
527 run(argv, "deconfig", chosen_nip); 504 if (ip_conflict & 1) {
528 505 if (state == MONITOR) {
529 // restart the whole protocol 506 // Src IP conflict, defend with a single ARP probe
530 timeout_ms = 0; 507 VDBG("monitor conflict - defending\n");
531 chosen_nip = pick_nip(); 508 timeout_ms = DEFEND_INTERVAL * 1000;
532 nsent = 0; 509 state = DEFEND;
533 state = PROBE; 510 send_arp_request(chosen_nip, &G.our_ethaddr, chosen_nip);
511 continue;
534 } 512 }
535 break; // case 1 (packet arrived) 513 // state == DEFEND
536 } // switch (poll) 514 // Another src IP conflict, start over
515 VDBG("defend conflict - starting over\n");
516 run(argv, "deconfig", chosen_nip);
517 conflicts = 0;
518 timeout_ms = 0;
519 goto new_nip_and_PROBE;
520 }
521 // Note: if we only have a target IP conflict here (ip_conflict & 2),
522 // IOW: if we just saw this sort of ARP packet:
523 // aa:bb:cc:dd:ee:ff > xx:xx:xx:xx:xx:xx: arp who-has <chosen_nip> tell 0.0.0.0
524 // we expect _kernel_ to respond to that, because <chosen_nip>
525 // is (expected to be) configured on this iface.
537 } // while (1) 526 } // while (1)
538#undef argv_intf 527#undef argv_intf
539} 528}