aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@ni.com>2014-07-20 14:01:49 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-07-20 14:01:49 +0200
commita4d564ad7c24df2da1d8e03a7dd016f0a3d5edbd (patch)
treeeb814c511e7325f9f258e9a70bfef6385b3deadc
parentb8ffd11e65734f90ebdaedb0ce32196fb150db01 (diff)
downloadbusybox-w32-a4d564ad7c24df2da1d8e03a7dd016f0a3d5edbd.tar.gz
busybox-w32-a4d564ad7c24df2da1d8e03a7dd016f0a3d5edbd.tar.bz2
busybox-w32-a4d564ad7c24df2da1d8e03a7dd016f0a3d5edbd.zip
zcip: fix link-local IP conflict detection
During link-local IP resolution, if a regular ARP request is received during the ARP probe period, it will incorrectly cause a target IP conflict. This then leads to a new IP being picked unnecessarily. Per RFC 3927, section 2.2.1, we should flag a target IP conflict only if the source IP is null, the target IP matches our IP, and the source hw addr does not match our hw addr. function old new delta zcip_main 1354 1322 -32 Signed-off-by: Ken Sharp <ken.sharp@ni.com> Signed-off-by: Ben Shelton <ben.shelton@ni.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/zcip.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/networking/zcip.c b/networking/zcip.c
index 7314ff8db..45d1f7c1c 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -366,11 +366,11 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
366 nprobes++; 366 nprobes++;
367 VDBG("probe/%u %s@%s\n", 367 VDBG("probe/%u %s@%s\n",
368 nprobes, argv_intf, inet_ntoa(ip)); 368 nprobes, argv_intf, inet_ntoa(ip));
369 timeout_ms = PROBE_MIN * 1000;
370 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
369 arp(/* ARPOP_REQUEST, */ 371 arp(/* ARPOP_REQUEST, */
370 /* &eth_addr, */ null_ip, 372 /* &eth_addr, */ null_ip,
371 &null_addr, ip); 373 &null_addr, ip);
372 timeout_ms = PROBE_MIN * 1000;
373 timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
374 } 374 }
375 else { 375 else {
376 // Switch to announce state. 376 // Switch to announce state.
@@ -378,10 +378,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
378 nclaims = 0; 378 nclaims = 0;
379 VDBG("announce/%u %s@%s\n", 379 VDBG("announce/%u %s@%s\n",
380 nclaims, argv_intf, inet_ntoa(ip)); 380 nclaims, argv_intf, inet_ntoa(ip));
381 timeout_ms = ANNOUNCE_INTERVAL * 1000;
381 arp(/* ARPOP_REQUEST, */ 382 arp(/* ARPOP_REQUEST, */
382 /* &eth_addr, */ ip, 383 /* &eth_addr, */ ip,
383 &eth_addr, ip); 384 &eth_addr, ip);
384 timeout_ms = ANNOUNCE_INTERVAL * 1000;
385 } 385 }
386 break; 386 break;
387 case RATE_LIMIT_PROBE: 387 case RATE_LIMIT_PROBE:
@@ -391,10 +391,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
391 nclaims = 0; 391 nclaims = 0;
392 VDBG("announce/%u %s@%s\n", 392 VDBG("announce/%u %s@%s\n",
393 nclaims, argv_intf, inet_ntoa(ip)); 393 nclaims, argv_intf, inet_ntoa(ip));
394 timeout_ms = ANNOUNCE_INTERVAL * 1000;
394 arp(/* ARPOP_REQUEST, */ 395 arp(/* ARPOP_REQUEST, */
395 /* &eth_addr, */ ip, 396 /* &eth_addr, */ ip,
396 &eth_addr, ip); 397 &eth_addr, ip);
397 timeout_ms = ANNOUNCE_INTERVAL * 1000;
398 break; 398 break;
399 case ANNOUNCE: 399 case ANNOUNCE:
400 // timeouts in the ANNOUNCE state mean no conflicting ARP packets 400 // timeouts in the ANNOUNCE state mean no conflicting ARP packets
@@ -403,10 +403,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
403 nclaims++; 403 nclaims++;
404 VDBG("announce/%u %s@%s\n", 404 VDBG("announce/%u %s@%s\n",
405 nclaims, argv_intf, inet_ntoa(ip)); 405 nclaims, argv_intf, inet_ntoa(ip));
406 timeout_ms = ANNOUNCE_INTERVAL * 1000;
406 arp(/* ARPOP_REQUEST, */ 407 arp(/* ARPOP_REQUEST, */
407 /* &eth_addr, */ ip, 408 /* &eth_addr, */ ip,
408 &eth_addr, ip); 409 &eth_addr, ip);
409 timeout_ms = ANNOUNCE_INTERVAL * 1000;
410 } 410 }
411 else { 411 else {
412 // Switch to monitor state. 412 // Switch to monitor state.
@@ -495,22 +495,28 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
495 } 495 }
496#endif 496#endif
497 if (p.arp.arp_op != htons(ARPOP_REQUEST) 497 if (p.arp.arp_op != htons(ARPOP_REQUEST)
498 && p.arp.arp_op != htons(ARPOP_REPLY)) 498 && p.arp.arp_op != htons(ARPOP_REPLY)
499 ) {
499 continue; 500 continue;
501 }
500 502
501 source_ip_conflict = 0; 503 source_ip_conflict = 0;
502 target_ip_conflict = 0; 504 target_ip_conflict = 0;
503 505
504 if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 506 if (memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0) {
505 && memcmp(&p.arp.arp_sha, &eth_addr, ETH_ALEN) != 0 507 if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr))) {
506 ) { 508 /* A probe or reply with source_ip == chosen ip */
507 source_ip_conflict = 1; 509 source_ip_conflict = 1;
508 } 510 }
509 if (p.arp.arp_op == htons(ARPOP_REQUEST) 511 if (p.arp.arp_op == htons(ARPOP_REQUEST)
510 && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 512 && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0
511 && memcmp(&p.arp.arp_tha, &eth_addr, ETH_ALEN) != 0 513 && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
512 ) { 514 ) {
513 target_ip_conflict = 1; 515 /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
516 * another host trying to claim this ip!
517 */
518 target_ip_conflict = 1;
519 }
514 } 520 }
515 521
516 VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", 522 VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",