* Copyright (C) 2003 by Arthur van Hoff (avh@strangeberry.com)
* Copyright (C) 2004 by David Brownell
*
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
/*
// - avoid silent script failures, especially under load...
// - link status monitoring (restart on link-up; stop on link-down)
+//usage:#define zcip_trivial_usage
+//usage: "[OPTIONS] IFACE SCRIPT"
+//usage:#define zcip_full_usage "\n\n"
+//usage: "Manage a ZeroConf IPv4 link-local address\n"
+//usage: "\n -f Run in foreground"
+//usage: "\n -q Quit after obtaining address"
+//usage: "\n -r 169.254.x.x Request this address first"
+//usage: "\n -v Verbose"
+//usage: "\n"
+//usage: "\nWith no -q, runs continuously monitoring for ARP conflicts,"
+//usage: "\nexits only on I/O errors (link down etc)"
+
+#include "libbb.h"
#include <netinet/ether.h>
-#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
-#include <linux/if_packet.h>
#include <linux/sockios.h>
-#include "libbb.h"
#include <syslog.h>
/* We don't need more than 32 bits of the counter */
#define G (*(struct globals*)&bb_common_bufsiz1)
#define saddr (G.saddr )
#define eth_addr (G.eth_addr)
+#define INIT_G() do { } while (0)
/**
#define verbose (L.verbose )
memset(&L, 0, sizeof(L));
+ INIT_G();
#define FOREGROUND (opts & 1)
#define QUIT (opts & 2)
nprobes++;
VDBG("probe/%u %s@%s\n",
nprobes, argv_intf, inet_ntoa(ip));
+ timeout_ms = PROBE_MIN * 1000;
+ timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
arp(/* ARPOP_REQUEST, */
/* ð_addr, */ null_ip,
&null_addr, ip);
- timeout_ms = PROBE_MIN * 1000;
- timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
}
else {
// Switch to announce state.
nclaims = 0;
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
+ timeout_ms = ANNOUNCE_INTERVAL * 1000;
arp(/* ARPOP_REQUEST, */
/* ð_addr, */ ip,
ð_addr, ip);
- timeout_ms = ANNOUNCE_INTERVAL * 1000;
}
break;
case RATE_LIMIT_PROBE:
nclaims = 0;
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
+ timeout_ms = ANNOUNCE_INTERVAL * 1000;
arp(/* ARPOP_REQUEST, */
/* ð_addr, */ ip,
ð_addr, ip);
- timeout_ms = ANNOUNCE_INTERVAL * 1000;
break;
case ANNOUNCE:
// timeouts in the ANNOUNCE state mean no conflicting ARP packets
nclaims++;
VDBG("announce/%u %s@%s\n",
nclaims, argv_intf, inet_ntoa(ip));
+ timeout_ms = ANNOUNCE_INTERVAL * 1000;
arp(/* ARPOP_REQUEST, */
/* ð_addr, */ ip,
ð_addr, ip);
- timeout_ms = ANNOUNCE_INTERVAL * 1000;
}
else {
// Switch to monitor state.
}
#endif
if (p.arp.arp_op != htons(ARPOP_REQUEST)
- && p.arp.arp_op != htons(ARPOP_REPLY))
+ && p.arp.arp_op != htons(ARPOP_REPLY)
+ ) {
continue;
+ }
source_ip_conflict = 0;
target_ip_conflict = 0;
- if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0
- && memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0
- ) {
- source_ip_conflict = 1;
- }
- if (p.arp.arp_op == htons(ARPOP_REQUEST)
- && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
- && memcmp(&p.arp.arp_tha, ð_addr, ETH_ALEN) != 0
- ) {
- target_ip_conflict = 1;
+ if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) {
+ if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr))) {
+ /* A probe or reply with source_ip == chosen ip */
+ source_ip_conflict = 1;
+ }
+ if (p.arp.arp_op == htons(ARPOP_REQUEST)
+ && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0
+ && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
+ ) {
+ /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip:
+ * another host trying to claim this ip!
+ */
+ target_ip_conflict = 1;
+ }
}
VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n",