mirror of
https://github.com/sheumann/hush.git
synced 2025-01-03 00:31:16 +00:00
zcip: use low-order 4 bytes of MAC as random seed, not 4 high-order
arping: fix wrong roundtrip calculation arping,zcip: cleanups and code shrink run 389 402 +13 arp 195 188 -7 zcip_main 1524 1495 -29 arping_main 1874 1823 -51 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 13/-87) Total: -74 bytes text data bss dec hex filename 776587 929 9100 786616 c00b8 busybox_old 776499 929 9100 786528 c0060 busybox_unstripped
This commit is contained in:
parent
7c9d533a85
commit
a09300a88c
@ -33,7 +33,7 @@ struct globals {
|
|||||||
struct in_addr dst;
|
struct in_addr dst;
|
||||||
struct sockaddr_ll me;
|
struct sockaddr_ll me;
|
||||||
struct sockaddr_ll he;
|
struct sockaddr_ll he;
|
||||||
int sock;
|
int sock_fd;
|
||||||
|
|
||||||
int count; // = -1;
|
int count; // = -1;
|
||||||
unsigned last;
|
unsigned last;
|
||||||
@ -51,7 +51,7 @@ struct globals {
|
|||||||
#define dst (G.dst )
|
#define dst (G.dst )
|
||||||
#define me (G.me )
|
#define me (G.me )
|
||||||
#define he (G.he )
|
#define he (G.he )
|
||||||
#define sock (G.sock )
|
#define sock_fd (G.sock_fd )
|
||||||
#define count (G.count )
|
#define count (G.count )
|
||||||
#define last (G.last )
|
#define last (G.last )
|
||||||
#define timeout_us (G.timeout_us)
|
#define timeout_us (G.timeout_us)
|
||||||
@ -71,7 +71,6 @@ static int send_pack(struct in_addr *src_addr,
|
|||||||
struct sockaddr_ll *HE)
|
struct sockaddr_ll *HE)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
unsigned now;
|
|
||||||
unsigned char buf[256];
|
unsigned char buf[256];
|
||||||
struct arphdr *ah = (struct arphdr *) buf;
|
struct arphdr *ah = (struct arphdr *) buf;
|
||||||
unsigned char *p = (unsigned char *) (ah + 1);
|
unsigned char *p = (unsigned char *) (ah + 1);
|
||||||
@ -98,10 +97,9 @@ static int send_pack(struct in_addr *src_addr,
|
|||||||
memcpy(p, dst_addr, 4);
|
memcpy(p, dst_addr, 4);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
now = MONOTONIC_US();
|
err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
|
||||||
err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE));
|
|
||||||
if (err == p - buf) {
|
if (err == p - buf) {
|
||||||
last = now;
|
last = MONOTONIC_US();
|
||||||
sent++;
|
sent++;
|
||||||
if (!(option_mask32 & UNICASTING))
|
if (!(option_mask32 & UNICASTING))
|
||||||
brd_sent++;
|
brd_sent++;
|
||||||
@ -135,7 +133,7 @@ static void catcher(void)
|
|||||||
if (start == 0)
|
if (start == 0)
|
||||||
start = now;
|
start = now;
|
||||||
|
|
||||||
if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000)))
|
if (count == 0 || (timeout_us && (now - start) > timeout_us))
|
||||||
finish();
|
finish();
|
||||||
|
|
||||||
/* count < 0 means "infinite count" */
|
/* count < 0 means "infinite count" */
|
||||||
@ -183,7 +181,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
|
|||||||
memcpy(&src_ip, p + ah->ar_hln, 4);
|
memcpy(&src_ip, p + ah->ar_hln, 4);
|
||||||
memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
|
memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
|
||||||
if (!(option_mask32 & DAD)) {
|
if (!(option_mask32 & DAD)) {
|
||||||
if (src_ip.s_addr != dst.s_addr)
|
if (dst.s_addr != src_ip.s_addr)
|
||||||
return 0;
|
return 0;
|
||||||
if (src.s_addr != dst_ip.s_addr)
|
if (src.s_addr != dst_ip.s_addr)
|
||||||
return 0;
|
return 0;
|
||||||
@ -230,7 +228,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
printf(" %u.%03ums\n", last / 1000, last % 1000);
|
unsigned diff = MONOTONIC_US() - last;
|
||||||
|
printf(" %u.%03ums\n", diff / 1000, diff % 1000);
|
||||||
} else {
|
} else {
|
||||||
printf(" UNSOLICITED?\n");
|
printf(" UNSOLICITED?\n");
|
||||||
}
|
}
|
||||||
@ -254,17 +253,17 @@ int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|||||||
int arping_main(int argc, char **argv)
|
int arping_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *device = "eth0";
|
const char *device = "eth0";
|
||||||
int ifindex;
|
|
||||||
char *source = NULL;
|
char *source = NULL;
|
||||||
char *target;
|
char *target;
|
||||||
unsigned char *packet;
|
unsigned char *packet;
|
||||||
|
|
||||||
INIT_G();
|
INIT_G();
|
||||||
|
|
||||||
sock = xsocket(PF_PACKET, SOCK_DGRAM, 0);
|
sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
// Drop suid root privileges
|
// Drop suid root privileges
|
||||||
xsetuid(getuid());
|
// Need to remove SUID_NEVER from applets.h for this to work
|
||||||
|
//xsetuid(getuid());
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned opt;
|
unsigned opt;
|
||||||
@ -279,7 +278,7 @@ int arping_main(int argc, char **argv)
|
|||||||
if (opt & 0x40) /* -c: count */
|
if (opt & 0x40) /* -c: count */
|
||||||
count = xatoi_u(str_count);
|
count = xatoi_u(str_count);
|
||||||
if (opt & 0x80) /* -w: timeout */
|
if (opt & 0x80) /* -w: timeout */
|
||||||
timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000;
|
timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000;
|
||||||
//if (opt & 0x200) /* -s: source */
|
//if (opt & 0x200) /* -s: source */
|
||||||
option_mask32 &= 0x3f; /* set respective flags */
|
option_mask32 &= 0x3f; /* set respective flags */
|
||||||
}
|
}
|
||||||
@ -295,10 +294,10 @@ int arping_main(int argc, char **argv)
|
|||||||
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
|
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
|
||||||
/* We use ifr.ifr_name in error msg so that problem
|
/* We use ifr.ifr_name in error msg so that problem
|
||||||
* with truncated name will be visible */
|
* with truncated name will be visible */
|
||||||
ioctl_or_perror_and_die(sock, SIOCGIFINDEX, &ifr, "interface %s not found", ifr.ifr_name);
|
ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, "interface %s not found", ifr.ifr_name);
|
||||||
ifindex = ifr.ifr_ifindex;
|
me.sll_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
xioctl(sock, SIOCGIFFLAGS, (char *) &ifr);
|
xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr);
|
||||||
|
|
||||||
if (!(ifr.ifr_flags & IFF_UP)) {
|
if (!(ifr.ifr_flags & IFF_UP)) {
|
||||||
bb_error_msg_and_die("interface %s is down", device);
|
bb_error_msg_and_die("interface %s is down", device);
|
||||||
@ -309,7 +308,7 @@ int arping_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inet_aton(target, &dst)) {
|
/* if (!inet_aton(target, &dst)) - not needed */ {
|
||||||
len_and_sockaddr *lsa;
|
len_and_sockaddr *lsa;
|
||||||
lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
|
lsa = xhost_and_af2sockaddr(target, 0, AF_INET);
|
||||||
memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4);
|
memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4);
|
||||||
@ -321,23 +320,23 @@ int arping_main(int argc, char **argv)
|
|||||||
bb_error_msg_and_die("invalid source address %s", source);
|
bb_error_msg_and_die("invalid source address %s", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(option_mask32 & DAD) && (option_mask32 & UNSOLICITED) && src.s_addr == 0)
|
if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0)
|
||||||
src = dst;
|
src = dst;
|
||||||
|
|
||||||
if (!(option_mask32 & DAD) || src.s_addr) {
|
if (!(option_mask32 & DAD) || src.s_addr) {
|
||||||
struct sockaddr_in saddr;
|
struct sockaddr_in saddr;
|
||||||
int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
|
int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
if (device) {
|
|
||||||
if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)
|
if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)
|
||||||
bb_perror_msg("cannot bind to device %s", device);
|
bb_perror_msg("cannot bind to device %s", device);
|
||||||
}
|
|
||||||
memset(&saddr, 0, sizeof(saddr));
|
memset(&saddr, 0, sizeof(saddr));
|
||||||
saddr.sin_family = AF_INET;
|
saddr.sin_family = AF_INET;
|
||||||
if (src.s_addr) {
|
if (src.s_addr) {
|
||||||
|
/* Check that this is indeed our IP */
|
||||||
saddr.sin_addr = src;
|
saddr.sin_addr = src;
|
||||||
xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
|
xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
|
||||||
} else if (!(option_mask32 & DAD)) {
|
} else { /* !(option_mask32 & DAD) case */
|
||||||
|
/* Find IP address on this iface */
|
||||||
socklen_t alen = sizeof(saddr);
|
socklen_t alen = sizeof(saddr);
|
||||||
|
|
||||||
saddr.sin_port = htons(1025);
|
saddr.sin_port = htons(1025);
|
||||||
@ -347,23 +346,25 @@ int arping_main(int argc, char **argv)
|
|||||||
bb_perror_msg("setsockopt(SO_DONTROUTE)");
|
bb_perror_msg("setsockopt(SO_DONTROUTE)");
|
||||||
xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
|
xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr));
|
||||||
if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {
|
if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) {
|
||||||
bb_error_msg_and_die("getsockname");
|
bb_perror_msg_and_die("getsockname");
|
||||||
}
|
}
|
||||||
|
if (saddr.sin_family != AF_INET)
|
||||||
|
bb_error_msg_and_die("no IP address configured");
|
||||||
src = saddr.sin_addr;
|
src = saddr.sin_addr;
|
||||||
}
|
}
|
||||||
close(probe_fd);
|
close(probe_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
me.sll_family = AF_PACKET;
|
me.sll_family = AF_PACKET;
|
||||||
me.sll_ifindex = ifindex;
|
//me.sll_ifindex = ifindex; - done before
|
||||||
me.sll_protocol = htons(ETH_P_ARP);
|
me.sll_protocol = htons(ETH_P_ARP);
|
||||||
xbind(sock, (struct sockaddr *) &me, sizeof(me));
|
xbind(sock_fd, (struct sockaddr *) &me, sizeof(me));
|
||||||
|
|
||||||
{
|
{
|
||||||
socklen_t alen = sizeof(me);
|
socklen_t alen = sizeof(me);
|
||||||
|
|
||||||
if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) {
|
if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) {
|
||||||
bb_error_msg_and_die("getsockname");
|
bb_perror_msg_and_die("getsockname");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (me.sll_halen == 0) {
|
if (me.sll_halen == 0) {
|
||||||
@ -373,14 +374,10 @@ int arping_main(int argc, char **argv)
|
|||||||
he = me;
|
he = me;
|
||||||
memset(he.sll_addr, -1, he.sll_halen);
|
memset(he.sll_addr, -1, he.sll_halen);
|
||||||
|
|
||||||
if (!src.s_addr && !(option_mask32 & DAD)) {
|
|
||||||
bb_error_msg_and_die("no src address in the non-DAD mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(option_mask32 & QUIET)) {
|
if (!(option_mask32 & QUIET)) {
|
||||||
printf("ARPING to %s from %s via %s\n",
|
/* inet_ntoa uses static storage, can't use in same printf */
|
||||||
inet_ntoa(dst), inet_ntoa(src),
|
printf("ARPING to %s", inet_ntoa(dst));
|
||||||
device ? device : "unknown");
|
printf(" from %s via %s\n", inet_ntoa(src), device);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -405,7 +402,7 @@ int arping_main(int argc, char **argv)
|
|||||||
socklen_t alen = sizeof(from);
|
socklen_t alen = sizeof(from);
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
cc = recvfrom(sock, packet, 4096, 0, (struct sockaddr *) &from, &alen);
|
cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen);
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
bb_perror_msg("recvfrom");
|
bb_perror_msg("recvfrom");
|
||||||
continue;
|
continue;
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#define MONOTONIC_US() ((unsigned)monotonic_us())
|
#define MONOTONIC_US() ((unsigned)monotonic_us())
|
||||||
|
|
||||||
struct arp_packet {
|
struct arp_packet {
|
||||||
struct ether_header hdr;
|
struct ether_header eth;
|
||||||
struct ether_arp arp;
|
struct ether_arp arp;
|
||||||
} ATTRIBUTE_PACKED;
|
} ATTRIBUTE_PACKED;
|
||||||
|
|
||||||
@ -69,8 +69,21 @@ enum {
|
|||||||
DEFEND
|
DEFEND
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VDBG(fmt,args...) \
|
#define VDBG(...) do { } while (0)
|
||||||
do { } while (0)
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sock_fd = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct globals {
|
||||||
|
char *intf;
|
||||||
|
struct sockaddr saddr;
|
||||||
|
};
|
||||||
|
#define G (*(struct globals*)&bb_common_bufsiz1)
|
||||||
|
#define intf (G.intf )
|
||||||
|
#define saddr (G.saddr)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick a random link local IP address on 169.254/16, except that
|
* Pick a random link local IP address on 169.254/16, except that
|
||||||
@ -89,17 +102,17 @@ static void pick(struct in_addr *ip)
|
|||||||
/**
|
/**
|
||||||
* Broadcast an ARP packet.
|
* Broadcast an ARP packet.
|
||||||
*/
|
*/
|
||||||
static void arp(int fd, struct sockaddr *saddr, int op,
|
static void arp(int op,
|
||||||
const struct ether_addr *source_addr, struct in_addr source_ip,
|
const struct ether_addr *source_eth, struct in_addr source_ip,
|
||||||
const struct ether_addr *target_addr, struct in_addr target_ip)
|
const struct ether_addr *target_eth, struct in_addr target_ip)
|
||||||
{
|
{
|
||||||
struct arp_packet p;
|
struct arp_packet p;
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&p, 0, sizeof(p));
|
||||||
|
|
||||||
// ether header
|
// ether header
|
||||||
p.hdr.ether_type = htons(ETHERTYPE_ARP);
|
p.eth.ether_type = htons(ETHERTYPE_ARP);
|
||||||
memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN);
|
memcpy(p.eth.ether_shost, source_eth, ETH_ALEN);
|
||||||
memset(p.hdr.ether_dhost, 0xff, ETH_ALEN);
|
memset(p.eth.ether_dhost, 0xff, ETH_ALEN);
|
||||||
|
|
||||||
// arp request
|
// arp request
|
||||||
p.arp.arp_hrd = htons(ARPHRD_ETHER);
|
p.arp.arp_hrd = htons(ARPHRD_ETHER);
|
||||||
@ -107,13 +120,13 @@ static void arp(int fd, struct sockaddr *saddr, int op,
|
|||||||
p.arp.arp_hln = ETH_ALEN;
|
p.arp.arp_hln = ETH_ALEN;
|
||||||
p.arp.arp_pln = 4;
|
p.arp.arp_pln = 4;
|
||||||
p.arp.arp_op = htons(op);
|
p.arp.arp_op = htons(op);
|
||||||
memcpy(&p.arp.arp_sha, source_addr, ETH_ALEN);
|
memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN);
|
||||||
memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
|
memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa));
|
||||||
memcpy(&p.arp.arp_tha, target_addr, ETH_ALEN);
|
memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN);
|
||||||
memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
|
memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa));
|
||||||
|
|
||||||
// send it
|
// send it
|
||||||
xsendto(fd, &p, sizeof(p), saddr, sizeof(*saddr));
|
xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr));
|
||||||
|
|
||||||
// Currently all callers ignore errors, that's why returns are
|
// Currently all callers ignore errors, that's why returns are
|
||||||
// commented out...
|
// commented out...
|
||||||
@ -123,21 +136,24 @@ static void arp(int fd, struct sockaddr *saddr, int op,
|
|||||||
/**
|
/**
|
||||||
* Run a script. argv[2] is already NULL.
|
* Run a script. argv[2] is already NULL.
|
||||||
*/
|
*/
|
||||||
static int run(char *argv[3], const char *intf, struct in_addr *ip)
|
static int run(char *argv[3], struct in_addr *ip)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
char *addr = addr; /* for gcc */
|
||||||
|
const char *fmt = "%s %s %s" + 3;
|
||||||
|
|
||||||
VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
|
VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
|
||||||
|
|
||||||
if (ip) {
|
if (ip) {
|
||||||
char *addr = inet_ntoa(*ip);
|
addr = inet_ntoa(*ip);
|
||||||
setenv("ip", addr, 1);
|
setenv("ip", addr, 1);
|
||||||
bb_info_msg("%s %s %s", argv[1], intf, addr);
|
fmt -= 3;
|
||||||
}
|
}
|
||||||
|
bb_info_msg(fmt, argv[1], intf, addr);
|
||||||
|
|
||||||
status = wait4pid(spawn(argv));
|
status = wait4pid(spawn(argv));
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
bb_perror_msg("%s %s", argv[1], intf);
|
bb_perror_msg("%s %s %s" + 3, argv[1], intf);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
@ -148,7 +164,7 @@ static int run(char *argv[3], const char *intf, struct in_addr *ip)
|
|||||||
/**
|
/**
|
||||||
* Return milliseconds of random delay, up to "secs" seconds.
|
* Return milliseconds of random delay, up to "secs" seconds.
|
||||||
*/
|
*/
|
||||||
static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs)
|
static unsigned ALWAYS_INLINE random_delay_ms(unsigned secs)
|
||||||
{
|
{
|
||||||
return rand() % (secs * 1000);
|
return rand() % (secs * 1000);
|
||||||
}
|
}
|
||||||
@ -160,10 +176,8 @@ int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|||||||
int zcip_main(int argc, char **argv)
|
int zcip_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int state = PROBE;
|
int state = PROBE;
|
||||||
/* Prevent unaligned traps for ARM (see srand() below) */
|
struct ether_addr eth_addr;
|
||||||
struct ether_addr eth_addr __attribute__(( aligned(sizeof(unsigned)) ));
|
|
||||||
const char *why;
|
const char *why;
|
||||||
int fd;
|
|
||||||
char *r_opt;
|
char *r_opt;
|
||||||
unsigned opts;
|
unsigned opts;
|
||||||
|
|
||||||
@ -171,10 +185,8 @@ int zcip_main(int argc, char **argv)
|
|||||||
struct {
|
struct {
|
||||||
const struct in_addr null_ip;
|
const struct in_addr null_ip;
|
||||||
const struct ether_addr null_addr;
|
const struct ether_addr null_addr;
|
||||||
struct sockaddr saddr;
|
|
||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
char *intf;
|
|
||||||
char *script_av[3];
|
char *script_av[3];
|
||||||
int timeout_ms; /* must be signed */
|
int timeout_ms; /* must be signed */
|
||||||
unsigned conflicts;
|
unsigned conflicts;
|
||||||
@ -185,10 +197,8 @@ int zcip_main(int argc, char **argv)
|
|||||||
} L;
|
} L;
|
||||||
#define null_ip (L.null_ip )
|
#define null_ip (L.null_ip )
|
||||||
#define null_addr (L.null_addr )
|
#define null_addr (L.null_addr )
|
||||||
#define saddr (L.saddr )
|
|
||||||
#define ip (L.ip )
|
#define ip (L.ip )
|
||||||
#define ifr (L.ifr )
|
#define ifr (L.ifr )
|
||||||
#define intf (L.intf )
|
|
||||||
#define script_av (L.script_av )
|
#define script_av (L.script_av )
|
||||||
#define timeout_ms (L.timeout_ms)
|
#define timeout_ms (L.timeout_ms)
|
||||||
#define conflicts (L.conflicts )
|
#define conflicts (L.conflicts )
|
||||||
@ -231,29 +241,37 @@ int zcip_main(int argc, char **argv)
|
|||||||
|
|
||||||
// initialize the interface (modprobe, ifup, etc)
|
// initialize the interface (modprobe, ifup, etc)
|
||||||
script_av[1] = (char*)"init";
|
script_av[1] = (char*)"init";
|
||||||
if (run(script_av, intf, NULL))
|
if (run(script_av, NULL))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
// initialize saddr
|
// initialize saddr
|
||||||
|
// saddr is: { u16 sa_family; u8 sa_data[14]; }
|
||||||
//memset(&saddr, 0, sizeof(saddr));
|
//memset(&saddr, 0, sizeof(saddr));
|
||||||
|
//TODO: are we leaving sa_family == 0 (AF_UNSPEC)?!
|
||||||
safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data));
|
safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data));
|
||||||
|
|
||||||
// open an ARP socket
|
// open an ARP socket
|
||||||
fd = xsocket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd);
|
||||||
// bind to the interface's ARP socket
|
// bind to the interface's ARP socket
|
||||||
xbind(fd, &saddr, sizeof(saddr));
|
xbind(sock_fd, &saddr, sizeof(saddr));
|
||||||
|
|
||||||
// get the interface's ethernet address
|
// get the interface's ethernet address
|
||||||
//memset(&ifr, 0, sizeof(ifr));
|
//memset(&ifr, 0, sizeof(ifr));
|
||||||
strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
|
strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
|
||||||
xioctl(fd, SIOCGIFHWADDR, &ifr);
|
xioctl(sock_fd, SIOCGIFHWADDR, &ifr);
|
||||||
memcpy(ð_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
memcpy(ð_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||||
|
|
||||||
// start with some stable ip address, either a function of
|
// start with some stable ip address, either a function of
|
||||||
// the hardware address or else the last address we used.
|
// the hardware address or else the last address we used.
|
||||||
|
// we are taking low-order four bytes, as top-order ones
|
||||||
|
// aren't random enough.
|
||||||
// NOTE: the sequence of addresses we try changes only
|
// NOTE: the sequence of addresses we try changes only
|
||||||
// depending on when we detect conflicts.
|
// depending on when we detect conflicts.
|
||||||
srand(*(unsigned*)ð_addr);
|
{
|
||||||
|
uint32_t t;
|
||||||
|
memcpy(&t, (char*)ð_addr + 2, 4);
|
||||||
|
srand(t);
|
||||||
|
}
|
||||||
if (ip.s_addr == 0)
|
if (ip.s_addr == 0)
|
||||||
pick(&ip);
|
pick(&ip);
|
||||||
|
|
||||||
@ -281,18 +299,17 @@ int zcip_main(int argc, char **argv)
|
|||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
unsigned deadline_us;
|
unsigned deadline_us;
|
||||||
struct arp_packet p;
|
struct arp_packet p;
|
||||||
|
int source_ip_conflict;
|
||||||
|
int target_ip_conflict;
|
||||||
|
|
||||||
int source_ip_conflict = 0;
|
fds[0].fd = sock_fd;
|
||||||
int target_ip_conflict = 0;
|
|
||||||
|
|
||||||
fds[0].fd = fd;
|
|
||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
fds[0].revents = 0;
|
fds[0].revents = 0;
|
||||||
|
|
||||||
// poll, being ready to adjust current timeout
|
// poll, being ready to adjust current timeout
|
||||||
if (!timeout_ms) {
|
if (!timeout_ms) {
|
||||||
timeout_ms = ms_rdelay(PROBE_WAIT);
|
timeout_ms = random_delay_ms(PROBE_WAIT);
|
||||||
// FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to
|
// FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to
|
||||||
// make the kernel filter out all packets except
|
// make the kernel filter out all packets except
|
||||||
// ones we'd care about.
|
// ones we'd care about.
|
||||||
}
|
}
|
||||||
@ -302,6 +319,8 @@ int zcip_main(int argc, char **argv)
|
|||||||
VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
|
VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
|
||||||
timeout_ms, intf, nprobes, nclaims);
|
timeout_ms, intf, nprobes, nclaims);
|
||||||
|
|
||||||
|
// FIXME: do we really receive ALL packets here??
|
||||||
|
// if yes, set up filtering to get ARPs only!!! (see arping)
|
||||||
switch (safe_poll(fds, 1, timeout_ms)) {
|
switch (safe_poll(fds, 1, timeout_ms)) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -319,11 +338,11 @@ int zcip_main(int argc, char **argv)
|
|||||||
nprobes++;
|
nprobes++;
|
||||||
VDBG("probe/%u %s@%s\n",
|
VDBG("probe/%u %s@%s\n",
|
||||||
nprobes, intf, inet_ntoa(ip));
|
nprobes, intf, inet_ntoa(ip));
|
||||||
arp(fd, &saddr, ARPOP_REQUEST,
|
arp(ARPOP_REQUEST,
|
||||||
ð_addr, null_ip,
|
ð_addr, null_ip,
|
||||||
&null_addr, ip);
|
&null_addr, ip);
|
||||||
timeout_ms = PROBE_MIN * 1000;
|
timeout_ms = PROBE_MIN * 1000;
|
||||||
timeout_ms += ms_rdelay(PROBE_MAX - PROBE_MIN);
|
timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Switch to announce state.
|
// Switch to announce state.
|
||||||
@ -331,7 +350,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
nclaims = 0;
|
nclaims = 0;
|
||||||
VDBG("announce/%u %s@%s\n",
|
VDBG("announce/%u %s@%s\n",
|
||||||
nclaims, intf, inet_ntoa(ip));
|
nclaims, intf, inet_ntoa(ip));
|
||||||
arp(fd, &saddr, ARPOP_REQUEST,
|
arp(ARPOP_REQUEST,
|
||||||
ð_addr, ip,
|
ð_addr, ip,
|
||||||
ð_addr, ip);
|
ð_addr, ip);
|
||||||
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
||||||
@ -344,7 +363,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
nclaims = 0;
|
nclaims = 0;
|
||||||
VDBG("announce/%u %s@%s\n",
|
VDBG("announce/%u %s@%s\n",
|
||||||
nclaims, intf, inet_ntoa(ip));
|
nclaims, intf, inet_ntoa(ip));
|
||||||
arp(fd, &saddr, ARPOP_REQUEST,
|
arp(ARPOP_REQUEST,
|
||||||
ð_addr, ip,
|
ð_addr, ip,
|
||||||
ð_addr, ip);
|
ð_addr, ip);
|
||||||
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
||||||
@ -356,7 +375,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
nclaims++;
|
nclaims++;
|
||||||
VDBG("announce/%u %s@%s\n",
|
VDBG("announce/%u %s@%s\n",
|
||||||
nclaims, intf, inet_ntoa(ip));
|
nclaims, intf, inet_ntoa(ip));
|
||||||
arp(fd, &saddr, ARPOP_REQUEST,
|
arp(ARPOP_REQUEST,
|
||||||
ð_addr, ip,
|
ð_addr, ip,
|
||||||
ð_addr, ip);
|
ð_addr, ip);
|
||||||
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
timeout_ms = ANNOUNCE_INTERVAL * 1000;
|
||||||
@ -367,7 +386,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
// link is ok to use earlier
|
// link is ok to use earlier
|
||||||
// FIXME update filters
|
// FIXME update filters
|
||||||
script_av[1] = (char*)"config";
|
script_av[1] = (char*)"config";
|
||||||
run(script_av, intf, &ip);
|
run(script_av, &ip);
|
||||||
ready = 1;
|
ready = 1;
|
||||||
conflicts = 0;
|
conflicts = 0;
|
||||||
timeout_ms = -1; // Never timeout in the monitor state.
|
timeout_ms = -1; // Never timeout in the monitor state.
|
||||||
@ -395,7 +414,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
} // switch (state)
|
} // switch (state)
|
||||||
break; // case 0 (timeout)
|
break; // case 0 (timeout)
|
||||||
|
|
||||||
// packets arriving
|
// packets arriving, or link went down
|
||||||
case 1:
|
case 1:
|
||||||
// We need to adjust the timeout in case we didn't receive
|
// We need to adjust the timeout in case we didn't receive
|
||||||
// a conflicting packet.
|
// a conflicting packet.
|
||||||
@ -408,8 +427,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
timeout_ms = 0;
|
timeout_ms = 0;
|
||||||
} else {
|
} else {
|
||||||
VDBG("adjusting timeout\n");
|
VDBG("adjusting timeout\n");
|
||||||
timeout_ms = diff / 1000;
|
timeout_ms = (diff / 1000) | 1; /* never 0 */
|
||||||
if (!timeout_ms) timeout_ms = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,10 +435,10 @@ int zcip_main(int argc, char **argv)
|
|||||||
if (fds[0].revents & POLLERR) {
|
if (fds[0].revents & POLLERR) {
|
||||||
// FIXME: links routinely go down;
|
// FIXME: links routinely go down;
|
||||||
// this shouldn't necessarily exit.
|
// this shouldn't necessarily exit.
|
||||||
bb_error_msg("%s: poll error", intf);
|
bb_error_msg("iface %s is down", intf);
|
||||||
if (ready) {
|
if (ready) {
|
||||||
script_av[1] = (char*)"deconfig";
|
script_av[1] = (char*)"deconfig";
|
||||||
run(script_av, intf, &ip);
|
run(script_av, &ip);
|
||||||
}
|
}
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -428,21 +446,20 @@ int zcip_main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read ARP packet
|
// read ARP packet
|
||||||
if (recv(fd, &p, sizeof(p), 0) < 0) {
|
if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
|
||||||
why = "recv";
|
why = "recv";
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (p.hdr.ether_type != htons(ETHERTYPE_ARP))
|
if (p.eth.ether_type != htons(ETHERTYPE_ARP))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{
|
{
|
||||||
struct ether_addr * sha = (struct ether_addr *) p.arp.arp_sha;
|
struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha;
|
||||||
struct ether_addr * tha = (struct ether_addr *) p.arp.arp_tha;
|
struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha;
|
||||||
struct in_addr * spa = (struct in_addr *) p.arp.arp_spa;
|
struct in_addr *spa = (struct in_addr *) p.arp.arp_spa;
|
||||||
struct in_addr * tpa = (struct in_addr *) p.arp.arp_tpa;
|
struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa;
|
||||||
VDBG("%s recv arp type=%d, op=%d,\n",
|
VDBG("%s recv arp type=%d, op=%d,\n",
|
||||||
intf, ntohs(p.hdr.ether_type),
|
intf, ntohs(p.eth.ether_type),
|
||||||
ntohs(p.arp.arp_op));
|
ntohs(p.arp.arp_op));
|
||||||
VDBG("\tsource=%s %s\n",
|
VDBG("\tsource=%s %s\n",
|
||||||
ether_ntoa(sha),
|
ether_ntoa(sha),
|
||||||
@ -456,13 +473,18 @@ int zcip_main(int argc, char **argv)
|
|||||||
&& p.arp.arp_op != htons(ARPOP_REPLY))
|
&& p.arp.arp_op != htons(ARPOP_REPLY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
|
source_ip_conflict = 0;
|
||||||
memcmp(ð_addr, &p.arp.arp_sha, ETH_ALEN) != 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;
|
source_ip_conflict = 1;
|
||||||
}
|
}
|
||||||
if (memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 &&
|
if (p.arp.arp_op == htons(ARPOP_REQUEST)
|
||||||
p.arp.arp_op == htons(ARPOP_REQUEST) &&
|
&& memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0
|
||||||
memcmp(ð_addr, &p.arp.arp_tha, ETH_ALEN) != 0) {
|
&& memcmp(&p.arp.arp_tha, ð_addr, ETH_ALEN) != 0
|
||||||
|
) {
|
||||||
target_ip_conflict = 1;
|
target_ip_conflict = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,8 +516,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
VDBG("monitor conflict -- defending\n");
|
VDBG("monitor conflict -- defending\n");
|
||||||
state = DEFEND;
|
state = DEFEND;
|
||||||
timeout_ms = DEFEND_INTERVAL * 1000;
|
timeout_ms = DEFEND_INTERVAL * 1000;
|
||||||
arp(fd, &saddr,
|
arp(ARPOP_REQUEST,
|
||||||
ARPOP_REQUEST,
|
|
||||||
ð_addr, ip,
|
ð_addr, ip,
|
||||||
ð_addr, ip);
|
ð_addr, ip);
|
||||||
}
|
}
|
||||||
@ -507,7 +528,7 @@ int zcip_main(int argc, char **argv)
|
|||||||
VDBG("defend conflict -- starting over\n");
|
VDBG("defend conflict -- starting over\n");
|
||||||
ready = 0;
|
ready = 0;
|
||||||
script_av[1] = (char*)"deconfig";
|
script_av[1] = (char*)"deconfig";
|
||||||
run(script_av, intf, &ip);
|
run(script_av, &ip);
|
||||||
|
|
||||||
// restart the whole protocol
|
// restart the whole protocol
|
||||||
pick(&ip);
|
pick(&ip);
|
||||||
@ -530,6 +551,6 @@ int zcip_main(int argc, char **argv)
|
|||||||
} // switch poll
|
} // switch poll
|
||||||
} // while (1)
|
} // while (1)
|
||||||
bad:
|
bad:
|
||||||
bb_perror_msg("%s, %s", intf, why);
|
bb_perror_msg("%s: %s", intf, why);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user