diff options
-rw-r--r-- | networking/arping.c | 69 | ||||
-rw-r--r-- | networking/zcip.c | 153 |
2 files changed, 120 insertions, 102 deletions
diff --git a/networking/arping.c b/networking/arping.c index 771c3bccd..6383f9a88 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -33,7 +33,7 @@ struct globals { | |||
33 | struct in_addr dst; | 33 | struct in_addr dst; |
34 | struct sockaddr_ll me; | 34 | struct sockaddr_ll me; |
35 | struct sockaddr_ll he; | 35 | struct sockaddr_ll he; |
36 | int sock; | 36 | int sock_fd; |
37 | 37 | ||
38 | int count; // = -1; | 38 | int count; // = -1; |
39 | unsigned last; | 39 | unsigned last; |
@@ -51,7 +51,7 @@ struct globals { | |||
51 | #define dst (G.dst ) | 51 | #define dst (G.dst ) |
52 | #define me (G.me ) | 52 | #define me (G.me ) |
53 | #define he (G.he ) | 53 | #define he (G.he ) |
54 | #define sock (G.sock ) | 54 | #define sock_fd (G.sock_fd ) |
55 | #define count (G.count ) | 55 | #define count (G.count ) |
56 | #define last (G.last ) | 56 | #define last (G.last ) |
57 | #define timeout_us (G.timeout_us) | 57 | #define timeout_us (G.timeout_us) |
@@ -71,7 +71,6 @@ static int send_pack(struct in_addr *src_addr, | |||
71 | struct sockaddr_ll *HE) | 71 | struct sockaddr_ll *HE) |
72 | { | 72 | { |
73 | int err; | 73 | int err; |
74 | unsigned now; | ||
75 | unsigned char buf[256]; | 74 | unsigned char buf[256]; |
76 | struct arphdr *ah = (struct arphdr *) buf; | 75 | struct arphdr *ah = (struct arphdr *) buf; |
77 | unsigned char *p = (unsigned char *) (ah + 1); | 76 | unsigned char *p = (unsigned char *) (ah + 1); |
@@ -98,10 +97,9 @@ static int send_pack(struct in_addr *src_addr, | |||
98 | memcpy(p, dst_addr, 4); | 97 | memcpy(p, dst_addr, 4); |
99 | p += 4; | 98 | p += 4; |
100 | 99 | ||
101 | now = MONOTONIC_US(); | 100 | err = sendto(sock_fd, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); |
102 | err = sendto(sock, buf, p - buf, 0, (struct sockaddr *) HE, sizeof(*HE)); | ||
103 | if (err == p - buf) { | 101 | if (err == p - buf) { |
104 | last = now; | 102 | last = MONOTONIC_US(); |
105 | sent++; | 103 | sent++; |
106 | if (!(option_mask32 & UNICASTING)) | 104 | if (!(option_mask32 & UNICASTING)) |
107 | brd_sent++; | 105 | brd_sent++; |
@@ -135,7 +133,7 @@ static void catcher(void) | |||
135 | if (start == 0) | 133 | if (start == 0) |
136 | start = now; | 134 | start = now; |
137 | 135 | ||
138 | if (count == 0 || (timeout_us && (now - start) > (timeout_us + 500000))) | 136 | if (count == 0 || (timeout_us && (now - start) > timeout_us)) |
139 | finish(); | 137 | finish(); |
140 | 138 | ||
141 | /* count < 0 means "infinite count" */ | 139 | /* count < 0 means "infinite count" */ |
@@ -183,7 +181,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
183 | memcpy(&src_ip, p + ah->ar_hln, 4); | 181 | memcpy(&src_ip, p + ah->ar_hln, 4); |
184 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); | 182 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); |
185 | if (!(option_mask32 & DAD)) { | 183 | if (!(option_mask32 & DAD)) { |
186 | if (src_ip.s_addr != dst.s_addr) | 184 | if (dst.s_addr != src_ip.s_addr) |
187 | return 0; | 185 | return 0; |
188 | if (src.s_addr != dst_ip.s_addr) | 186 | if (src.s_addr != dst_ip.s_addr) |
189 | return 0; | 187 | return 0; |
@@ -230,7 +228,8 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
230 | } | 228 | } |
231 | 229 | ||
232 | if (last) { | 230 | if (last) { |
233 | printf(" %u.%03ums\n", last / 1000, last % 1000); | 231 | unsigned diff = MONOTONIC_US() - last; |
232 | printf(" %u.%03ums\n", diff / 1000, diff % 1000); | ||
234 | } else { | 233 | } else { |
235 | printf(" UNSOLICITED?\n"); | 234 | printf(" UNSOLICITED?\n"); |
236 | } | 235 | } |
@@ -254,17 +253,17 @@ int arping_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
254 | int arping_main(int argc, char **argv) | 253 | int arping_main(int argc, char **argv) |
255 | { | 254 | { |
256 | const char *device = "eth0"; | 255 | const char *device = "eth0"; |
257 | int ifindex; | ||
258 | char *source = NULL; | 256 | char *source = NULL; |
259 | char *target; | 257 | char *target; |
260 | unsigned char *packet; | 258 | unsigned char *packet; |
261 | 259 | ||
262 | INIT_G(); | 260 | INIT_G(); |
263 | 261 | ||
264 | sock = xsocket(PF_PACKET, SOCK_DGRAM, 0); | 262 | sock_fd = xsocket(AF_PACKET, SOCK_DGRAM, 0); |
265 | 263 | ||
266 | // Drop suid root privileges | 264 | // Drop suid root privileges |
267 | xsetuid(getuid()); | 265 | // Need to remove SUID_NEVER from applets.h for this to work |
266 | //xsetuid(getuid()); | ||
268 | 267 | ||
269 | { | 268 | { |
270 | unsigned opt; | 269 | unsigned opt; |
@@ -279,7 +278,7 @@ int arping_main(int argc, char **argv) | |||
279 | if (opt & 0x40) /* -c: count */ | 278 | if (opt & 0x40) /* -c: count */ |
280 | count = xatoi_u(str_count); | 279 | count = xatoi_u(str_count); |
281 | if (opt & 0x80) /* -w: timeout */ | 280 | if (opt & 0x80) /* -w: timeout */ |
282 | timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000; | 281 | timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000 + 500000; |
283 | //if (opt & 0x200) /* -s: source */ | 282 | //if (opt & 0x200) /* -s: source */ |
284 | option_mask32 &= 0x3f; /* set respective flags */ | 283 | option_mask32 &= 0x3f; /* set respective flags */ |
285 | } | 284 | } |
@@ -295,10 +294,10 @@ int arping_main(int argc, char **argv) | |||
295 | strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1); | 294 | strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1); |
296 | /* We use ifr.ifr_name in error msg so that problem | 295 | /* We use ifr.ifr_name in error msg so that problem |
297 | * with truncated name will be visible */ | 296 | * with truncated name will be visible */ |
298 | ioctl_or_perror_and_die(sock, SIOCGIFINDEX, &ifr, "interface %s not found", ifr.ifr_name); | 297 | ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, "interface %s not found", ifr.ifr_name); |
299 | ifindex = ifr.ifr_ifindex; | 298 | me.sll_ifindex = ifr.ifr_ifindex; |
300 | 299 | ||
301 | xioctl(sock, SIOCGIFFLAGS, (char *) &ifr); | 300 | xioctl(sock_fd, SIOCGIFFLAGS, (char *) &ifr); |
302 | 301 | ||
303 | if (!(ifr.ifr_flags & IFF_UP)) { | 302 | if (!(ifr.ifr_flags & IFF_UP)) { |
304 | bb_error_msg_and_die("interface %s is down", device); | 303 | bb_error_msg_and_die("interface %s is down", device); |
@@ -309,7 +308,7 @@ int arping_main(int argc, char **argv) | |||
309 | } | 308 | } |
310 | } | 309 | } |
311 | 310 | ||
312 | if (!inet_aton(target, &dst)) { | 311 | /* if (!inet_aton(target, &dst)) - not needed */ { |
313 | len_and_sockaddr *lsa; | 312 | len_and_sockaddr *lsa; |
314 | lsa = xhost_and_af2sockaddr(target, 0, AF_INET); | 313 | lsa = xhost_and_af2sockaddr(target, 0, AF_INET); |
315 | memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4); | 314 | memcpy(&dst, &lsa->sin.sin_addr.s_addr, 4); |
@@ -321,23 +320,23 @@ int arping_main(int argc, char **argv) | |||
321 | bb_error_msg_and_die("invalid source address %s", source); | 320 | bb_error_msg_and_die("invalid source address %s", source); |
322 | } | 321 | } |
323 | 322 | ||
324 | if (!(option_mask32 & DAD) && (option_mask32 & UNSOLICITED) && src.s_addr == 0) | 323 | if ((option_mask32 & (DAD|UNSOLICITED)) == UNSOLICITED && src.s_addr == 0) |
325 | src = dst; | 324 | src = dst; |
326 | 325 | ||
327 | if (!(option_mask32 & DAD) || src.s_addr) { | 326 | if (!(option_mask32 & DAD) || src.s_addr) { |
328 | struct sockaddr_in saddr; | 327 | struct sockaddr_in saddr; |
329 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); | 328 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); |
330 | 329 | ||
331 | if (device) { | 330 | if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) |
332 | if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1) | 331 | bb_perror_msg("cannot bind to device %s", device); |
333 | bb_perror_msg("cannot bind to device %s", device); | ||
334 | } | ||
335 | memset(&saddr, 0, sizeof(saddr)); | 332 | memset(&saddr, 0, sizeof(saddr)); |
336 | saddr.sin_family = AF_INET; | 333 | saddr.sin_family = AF_INET; |
337 | if (src.s_addr) { | 334 | if (src.s_addr) { |
335 | /* Check that this is indeed our IP */ | ||
338 | saddr.sin_addr = src; | 336 | saddr.sin_addr = src; |
339 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); | 337 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
340 | } else if (!(option_mask32 & DAD)) { | 338 | } else { /* !(option_mask32 & DAD) case */ |
339 | /* Find IP address on this iface */ | ||
341 | socklen_t alen = sizeof(saddr); | 340 | socklen_t alen = sizeof(saddr); |
342 | 341 | ||
343 | saddr.sin_port = htons(1025); | 342 | saddr.sin_port = htons(1025); |
@@ -347,23 +346,25 @@ int arping_main(int argc, char **argv) | |||
347 | bb_perror_msg("setsockopt(SO_DONTROUTE)"); | 346 | bb_perror_msg("setsockopt(SO_DONTROUTE)"); |
348 | xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); | 347 | xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
349 | if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { | 348 | if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { |
350 | bb_error_msg_and_die("getsockname"); | 349 | bb_perror_msg_and_die("getsockname"); |
351 | } | 350 | } |
351 | if (saddr.sin_family != AF_INET) | ||
352 | bb_error_msg_and_die("no IP address configured"); | ||
352 | src = saddr.sin_addr; | 353 | src = saddr.sin_addr; |
353 | } | 354 | } |
354 | close(probe_fd); | 355 | close(probe_fd); |
355 | } | 356 | } |
356 | 357 | ||
357 | me.sll_family = AF_PACKET; | 358 | me.sll_family = AF_PACKET; |
358 | me.sll_ifindex = ifindex; | 359 | //me.sll_ifindex = ifindex; - done before |
359 | me.sll_protocol = htons(ETH_P_ARP); | 360 | me.sll_protocol = htons(ETH_P_ARP); |
360 | xbind(sock, (struct sockaddr *) &me, sizeof(me)); | 361 | xbind(sock_fd, (struct sockaddr *) &me, sizeof(me)); |
361 | 362 | ||
362 | { | 363 | { |
363 | socklen_t alen = sizeof(me); | 364 | socklen_t alen = sizeof(me); |
364 | 365 | ||
365 | if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) { | 366 | if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) { |
366 | bb_error_msg_and_die("getsockname"); | 367 | bb_perror_msg_and_die("getsockname"); |
367 | } | 368 | } |
368 | } | 369 | } |
369 | if (me.sll_halen == 0) { | 370 | if (me.sll_halen == 0) { |
@@ -373,14 +374,10 @@ int arping_main(int argc, char **argv) | |||
373 | he = me; | 374 | he = me; |
374 | memset(he.sll_addr, -1, he.sll_halen); | 375 | memset(he.sll_addr, -1, he.sll_halen); |
375 | 376 | ||
376 | if (!src.s_addr && !(option_mask32 & DAD)) { | ||
377 | bb_error_msg_and_die("no src address in the non-DAD mode"); | ||
378 | } | ||
379 | |||
380 | if (!(option_mask32 & QUIET)) { | 377 | if (!(option_mask32 & QUIET)) { |
381 | printf("ARPING to %s from %s via %s\n", | 378 | /* inet_ntoa uses static storage, can't use in same printf */ |
382 | inet_ntoa(dst), inet_ntoa(src), | 379 | printf("ARPING to %s", inet_ntoa(dst)); |
383 | device ? device : "unknown"); | 380 | printf(" from %s via %s\n", inet_ntoa(src), device); |
384 | } | 381 | } |
385 | 382 | ||
386 | { | 383 | { |
@@ -405,7 +402,7 @@ int arping_main(int argc, char **argv) | |||
405 | socklen_t alen = sizeof(from); | 402 | socklen_t alen = sizeof(from); |
406 | int cc; | 403 | int cc; |
407 | 404 | ||
408 | cc = recvfrom(sock, packet, 4096, 0, (struct sockaddr *) &from, &alen); | 405 | cc = recvfrom(sock_fd, packet, 4096, 0, (struct sockaddr *) &from, &alen); |
409 | if (cc < 0) { | 406 | if (cc < 0) { |
410 | bb_perror_msg("recvfrom"); | 407 | bb_perror_msg("recvfrom"); |
411 | continue; | 408 | continue; |
diff --git a/networking/zcip.c b/networking/zcip.c index a16a6420c..129155fe5 100644 --- a/networking/zcip.c +++ b/networking/zcip.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #define MONOTONIC_US() ((unsigned)monotonic_us()) | 39 | #define MONOTONIC_US() ((unsigned)monotonic_us()) |
40 | 40 | ||
41 | struct arp_packet { | 41 | struct arp_packet { |
42 | struct ether_header hdr; | 42 | struct ether_header eth; |
43 | struct ether_arp arp; | 43 | struct ether_arp arp; |
44 | } ATTRIBUTE_PACKED; | 44 | } ATTRIBUTE_PACKED; |
45 | 45 | ||
@@ -69,8 +69,21 @@ enum { | |||
69 | DEFEND | 69 | DEFEND |
70 | }; | 70 | }; |
71 | 71 | ||
72 | #define VDBG(fmt,args...) \ | 72 | #define VDBG(...) do { } while (0) |
73 | do { } while (0) | 73 | |
74 | |||
75 | enum { | ||
76 | sock_fd = 3 | ||
77 | }; | ||
78 | |||
79 | struct globals { | ||
80 | char *intf; | ||
81 | struct sockaddr saddr; | ||
82 | }; | ||
83 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
84 | #define intf (G.intf ) | ||
85 | #define saddr (G.saddr) | ||
86 | |||
74 | 87 | ||
75 | /** | 88 | /** |
76 | * Pick a random link local IP address on 169.254/16, except that | 89 | * Pick a random link local IP address on 169.254/16, except that |
@@ -89,17 +102,17 @@ static void pick(struct in_addr *ip) | |||
89 | /** | 102 | /** |
90 | * Broadcast an ARP packet. | 103 | * Broadcast an ARP packet. |
91 | */ | 104 | */ |
92 | static void arp(int fd, struct sockaddr *saddr, int op, | 105 | static void arp(int op, |
93 | const struct ether_addr *source_addr, struct in_addr source_ip, | 106 | const struct ether_addr *source_eth, struct in_addr source_ip, |
94 | const struct ether_addr *target_addr, struct in_addr target_ip) | 107 | const struct ether_addr *target_eth, struct in_addr target_ip) |
95 | { | 108 | { |
96 | struct arp_packet p; | 109 | struct arp_packet p; |
97 | memset(&p, 0, sizeof(p)); | 110 | memset(&p, 0, sizeof(p)); |
98 | 111 | ||
99 | // ether header | 112 | // ether header |
100 | p.hdr.ether_type = htons(ETHERTYPE_ARP); | 113 | p.eth.ether_type = htons(ETHERTYPE_ARP); |
101 | memcpy(p.hdr.ether_shost, source_addr, ETH_ALEN); | 114 | memcpy(p.eth.ether_shost, source_eth, ETH_ALEN); |
102 | memset(p.hdr.ether_dhost, 0xff, ETH_ALEN); | 115 | memset(p.eth.ether_dhost, 0xff, ETH_ALEN); |
103 | 116 | ||
104 | // arp request | 117 | // arp request |
105 | p.arp.arp_hrd = htons(ARPHRD_ETHER); | 118 | p.arp.arp_hrd = htons(ARPHRD_ETHER); |
@@ -107,13 +120,13 @@ static void arp(int fd, struct sockaddr *saddr, int op, | |||
107 | p.arp.arp_hln = ETH_ALEN; | 120 | p.arp.arp_hln = ETH_ALEN; |
108 | p.arp.arp_pln = 4; | 121 | p.arp.arp_pln = 4; |
109 | p.arp.arp_op = htons(op); | 122 | p.arp.arp_op = htons(op); |
110 | memcpy(&p.arp.arp_sha, source_addr, ETH_ALEN); | 123 | memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); |
111 | memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); | 124 | memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); |
112 | memcpy(&p.arp.arp_tha, target_addr, ETH_ALEN); | 125 | memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); |
113 | memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); | 126 | memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); |
114 | 127 | ||
115 | // send it | 128 | // send it |
116 | xsendto(fd, &p, sizeof(p), saddr, sizeof(*saddr)); | 129 | xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); |
117 | 130 | ||
118 | // Currently all callers ignore errors, that's why returns are | 131 | // Currently all callers ignore errors, that's why returns are |
119 | // commented out... | 132 | // commented out... |
@@ -123,21 +136,24 @@ static void arp(int fd, struct sockaddr *saddr, int op, | |||
123 | /** | 136 | /** |
124 | * Run a script. argv[2] is already NULL. | 137 | * Run a script. argv[2] is already NULL. |
125 | */ | 138 | */ |
126 | static int run(char *argv[3], const char *intf, struct in_addr *ip) | 139 | static int run(char *argv[3], struct in_addr *ip) |
127 | { | 140 | { |
128 | int status; | 141 | int status; |
142 | char *addr = addr; /* for gcc */ | ||
143 | const char *fmt = "%s %s %s" + 3; | ||
129 | 144 | ||
130 | VDBG("%s run %s %s\n", intf, argv[0], argv[1]); | 145 | VDBG("%s run %s %s\n", intf, argv[0], argv[1]); |
131 | 146 | ||
132 | if (ip) { | 147 | if (ip) { |
133 | char *addr = inet_ntoa(*ip); | 148 | addr = inet_ntoa(*ip); |
134 | setenv("ip", addr, 1); | 149 | setenv("ip", addr, 1); |
135 | bb_info_msg("%s %s %s", argv[1], intf, addr); | 150 | fmt -= 3; |
136 | } | 151 | } |
152 | bb_info_msg(fmt, argv[1], intf, addr); | ||
137 | 153 | ||
138 | status = wait4pid(spawn(argv)); | 154 | status = wait4pid(spawn(argv)); |
139 | if (status < 0) { | 155 | if (status < 0) { |
140 | bb_perror_msg("%s %s", argv[1], intf); | 156 | bb_perror_msg("%s %s %s" + 3, argv[1], intf); |
141 | return -errno; | 157 | return -errno; |
142 | } | 158 | } |
143 | if (status != 0) | 159 | if (status != 0) |
@@ -148,7 +164,7 @@ static int run(char *argv[3], const char *intf, struct in_addr *ip) | |||
148 | /** | 164 | /** |
149 | * Return milliseconds of random delay, up to "secs" seconds. | 165 | * Return milliseconds of random delay, up to "secs" seconds. |
150 | */ | 166 | */ |
151 | static unsigned ALWAYS_INLINE ms_rdelay(unsigned secs) | 167 | static unsigned ALWAYS_INLINE random_delay_ms(unsigned secs) |
152 | { | 168 | { |
153 | return rand() % (secs * 1000); | 169 | return rand() % (secs * 1000); |
154 | } | 170 | } |
@@ -160,10 +176,8 @@ int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
160 | int zcip_main(int argc, char **argv) | 176 | int zcip_main(int argc, char **argv) |
161 | { | 177 | { |
162 | int state = PROBE; | 178 | int state = PROBE; |
163 | /* Prevent unaligned traps for ARM (see srand() below) */ | 179 | struct ether_addr eth_addr; |
164 | struct ether_addr eth_addr __attribute__(( aligned(sizeof(unsigned)) )); | ||
165 | const char *why; | 180 | const char *why; |
166 | int fd; | ||
167 | char *r_opt; | 181 | char *r_opt; |
168 | unsigned opts; | 182 | unsigned opts; |
169 | 183 | ||
@@ -171,10 +185,8 @@ int zcip_main(int argc, char **argv) | |||
171 | struct { | 185 | struct { |
172 | const struct in_addr null_ip; | 186 | const struct in_addr null_ip; |
173 | const struct ether_addr null_addr; | 187 | const struct ether_addr null_addr; |
174 | struct sockaddr saddr; | ||
175 | struct in_addr ip; | 188 | struct in_addr ip; |
176 | struct ifreq ifr; | 189 | struct ifreq ifr; |
177 | char *intf; | ||
178 | char *script_av[3]; | 190 | char *script_av[3]; |
179 | int timeout_ms; /* must be signed */ | 191 | int timeout_ms; /* must be signed */ |
180 | unsigned conflicts; | 192 | unsigned conflicts; |
@@ -185,10 +197,8 @@ int zcip_main(int argc, char **argv) | |||
185 | } L; | 197 | } L; |
186 | #define null_ip (L.null_ip ) | 198 | #define null_ip (L.null_ip ) |
187 | #define null_addr (L.null_addr ) | 199 | #define null_addr (L.null_addr ) |
188 | #define saddr (L.saddr ) | ||
189 | #define ip (L.ip ) | 200 | #define ip (L.ip ) |
190 | #define ifr (L.ifr ) | 201 | #define ifr (L.ifr ) |
191 | #define intf (L.intf ) | ||
192 | #define script_av (L.script_av ) | 202 | #define script_av (L.script_av ) |
193 | #define timeout_ms (L.timeout_ms) | 203 | #define timeout_ms (L.timeout_ms) |
194 | #define conflicts (L.conflicts ) | 204 | #define conflicts (L.conflicts ) |
@@ -231,29 +241,37 @@ int zcip_main(int argc, char **argv) | |||
231 | 241 | ||
232 | // initialize the interface (modprobe, ifup, etc) | 242 | // initialize the interface (modprobe, ifup, etc) |
233 | script_av[1] = (char*)"init"; | 243 | script_av[1] = (char*)"init"; |
234 | if (run(script_av, intf, NULL)) | 244 | if (run(script_av, NULL)) |
235 | return EXIT_FAILURE; | 245 | return EXIT_FAILURE; |
236 | 246 | ||
237 | // initialize saddr | 247 | // initialize saddr |
248 | // saddr is: { u16 sa_family; u8 sa_data[14]; } | ||
238 | //memset(&saddr, 0, sizeof(saddr)); | 249 | //memset(&saddr, 0, sizeof(saddr)); |
250 | //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! | ||
239 | safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data)); | 251 | safe_strncpy(saddr.sa_data, intf, sizeof(saddr.sa_data)); |
240 | 252 | ||
241 | // open an ARP socket | 253 | // open an ARP socket |
242 | fd = xsocket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); | 254 | xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); |
243 | // bind to the interface's ARP socket | 255 | // bind to the interface's ARP socket |
244 | xbind(fd, &saddr, sizeof(saddr)); | 256 | xbind(sock_fd, &saddr, sizeof(saddr)); |
245 | 257 | ||
246 | // get the interface's ethernet address | 258 | // get the interface's ethernet address |
247 | //memset(&ifr, 0, sizeof(ifr)); | 259 | //memset(&ifr, 0, sizeof(ifr)); |
248 | strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name)); | 260 | strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name)); |
249 | xioctl(fd, SIOCGIFHWADDR, &ifr); | 261 | xioctl(sock_fd, SIOCGIFHWADDR, &ifr); |
250 | memcpy(ð_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); | 262 | memcpy(ð_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); |
251 | 263 | ||
252 | // start with some stable ip address, either a function of | 264 | // start with some stable ip address, either a function of |
253 | // the hardware address or else the last address we used. | 265 | // the hardware address or else the last address we used. |
266 | // we are taking low-order four bytes, as top-order ones | ||
267 | // aren't random enough. | ||
254 | // NOTE: the sequence of addresses we try changes only | 268 | // NOTE: the sequence of addresses we try changes only |
255 | // depending on when we detect conflicts. | 269 | // depending on when we detect conflicts. |
256 | srand(*(unsigned*)ð_addr); | 270 | { |
271 | uint32_t t; | ||
272 | memcpy(&t, (char*)ð_addr + 2, 4); | ||
273 | srand(t); | ||
274 | } | ||
257 | if (ip.s_addr == 0) | 275 | if (ip.s_addr == 0) |
258 | pick(&ip); | 276 | pick(&ip); |
259 | 277 | ||
@@ -281,18 +299,17 @@ int zcip_main(int argc, char **argv) | |||
281 | struct pollfd fds[1]; | 299 | struct pollfd fds[1]; |
282 | unsigned deadline_us; | 300 | unsigned deadline_us; |
283 | struct arp_packet p; | 301 | struct arp_packet p; |
302 | int source_ip_conflict; | ||
303 | int target_ip_conflict; | ||
284 | 304 | ||
285 | int source_ip_conflict = 0; | 305 | fds[0].fd = sock_fd; |
286 | int target_ip_conflict = 0; | ||
287 | |||
288 | fds[0].fd = fd; | ||
289 | fds[0].events = POLLIN; | 306 | fds[0].events = POLLIN; |
290 | fds[0].revents = 0; | 307 | fds[0].revents = 0; |
291 | 308 | ||
292 | // poll, being ready to adjust current timeout | 309 | // poll, being ready to adjust current timeout |
293 | if (!timeout_ms) { | 310 | if (!timeout_ms) { |
294 | timeout_ms = ms_rdelay(PROBE_WAIT); | 311 | timeout_ms = random_delay_ms(PROBE_WAIT); |
295 | // FIXME setsockopt(fd, SO_ATTACH_FILTER, ...) to | 312 | // FIXME setsockopt(sock_fd, SO_ATTACH_FILTER, ...) to |
296 | // make the kernel filter out all packets except | 313 | // make the kernel filter out all packets except |
297 | // ones we'd care about. | 314 | // ones we'd care about. |
298 | } | 315 | } |
@@ -302,6 +319,8 @@ int zcip_main(int argc, char **argv) | |||
302 | VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", | 319 | VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", |
303 | timeout_ms, intf, nprobes, nclaims); | 320 | timeout_ms, intf, nprobes, nclaims); |
304 | 321 | ||
322 | // FIXME: do we really receive ALL packets here?? | ||
323 | // if yes, set up filtering to get ARPs only!!! (see arping) | ||
305 | switch (safe_poll(fds, 1, timeout_ms)) { | 324 | switch (safe_poll(fds, 1, timeout_ms)) { |
306 | 325 | ||
307 | default: | 326 | default: |
@@ -319,11 +338,11 @@ int zcip_main(int argc, char **argv) | |||
319 | nprobes++; | 338 | nprobes++; |
320 | VDBG("probe/%u %s@%s\n", | 339 | VDBG("probe/%u %s@%s\n", |
321 | nprobes, intf, inet_ntoa(ip)); | 340 | nprobes, intf, inet_ntoa(ip)); |
322 | arp(fd, &saddr, ARPOP_REQUEST, | 341 | arp(ARPOP_REQUEST, |
323 | ð_addr, null_ip, | 342 | ð_addr, null_ip, |
324 | &null_addr, ip); | 343 | &null_addr, ip); |
325 | timeout_ms = PROBE_MIN * 1000; | 344 | timeout_ms = PROBE_MIN * 1000; |
326 | timeout_ms += ms_rdelay(PROBE_MAX - PROBE_MIN); | 345 | timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); |
327 | } | 346 | } |
328 | else { | 347 | else { |
329 | // Switch to announce state. | 348 | // Switch to announce state. |
@@ -331,7 +350,7 @@ int zcip_main(int argc, char **argv) | |||
331 | nclaims = 0; | 350 | nclaims = 0; |
332 | VDBG("announce/%u %s@%s\n", | 351 | VDBG("announce/%u %s@%s\n", |
333 | nclaims, intf, inet_ntoa(ip)); | 352 | nclaims, intf, inet_ntoa(ip)); |
334 | arp(fd, &saddr, ARPOP_REQUEST, | 353 | arp(ARPOP_REQUEST, |
335 | ð_addr, ip, | 354 | ð_addr, ip, |
336 | ð_addr, ip); | 355 | ð_addr, ip); |
337 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | 356 | timeout_ms = ANNOUNCE_INTERVAL * 1000; |
@@ -344,7 +363,7 @@ int zcip_main(int argc, char **argv) | |||
344 | nclaims = 0; | 363 | nclaims = 0; |
345 | VDBG("announce/%u %s@%s\n", | 364 | VDBG("announce/%u %s@%s\n", |
346 | nclaims, intf, inet_ntoa(ip)); | 365 | nclaims, intf, inet_ntoa(ip)); |
347 | arp(fd, &saddr, ARPOP_REQUEST, | 366 | arp(ARPOP_REQUEST, |
348 | ð_addr, ip, | 367 | ð_addr, ip, |
349 | ð_addr, ip); | 368 | ð_addr, ip); |
350 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | 369 | timeout_ms = ANNOUNCE_INTERVAL * 1000; |
@@ -356,7 +375,7 @@ int zcip_main(int argc, char **argv) | |||
356 | nclaims++; | 375 | nclaims++; |
357 | VDBG("announce/%u %s@%s\n", | 376 | VDBG("announce/%u %s@%s\n", |
358 | nclaims, intf, inet_ntoa(ip)); | 377 | nclaims, intf, inet_ntoa(ip)); |
359 | arp(fd, &saddr, ARPOP_REQUEST, | 378 | arp(ARPOP_REQUEST, |
360 | ð_addr, ip, | 379 | ð_addr, ip, |
361 | ð_addr, ip); | 380 | ð_addr, ip); |
362 | timeout_ms = ANNOUNCE_INTERVAL * 1000; | 381 | timeout_ms = ANNOUNCE_INTERVAL * 1000; |
@@ -367,7 +386,7 @@ int zcip_main(int argc, char **argv) | |||
367 | // link is ok to use earlier | 386 | // link is ok to use earlier |
368 | // FIXME update filters | 387 | // FIXME update filters |
369 | script_av[1] = (char*)"config"; | 388 | script_av[1] = (char*)"config"; |
370 | run(script_av, intf, &ip); | 389 | run(script_av, &ip); |
371 | ready = 1; | 390 | ready = 1; |
372 | conflicts = 0; | 391 | conflicts = 0; |
373 | timeout_ms = -1; // Never timeout in the monitor state. | 392 | timeout_ms = -1; // Never timeout in the monitor state. |
@@ -395,7 +414,7 @@ int zcip_main(int argc, char **argv) | |||
395 | } // switch (state) | 414 | } // switch (state) |
396 | break; // case 0 (timeout) | 415 | break; // case 0 (timeout) |
397 | 416 | ||
398 | // packets arriving | 417 | // packets arriving, or link went down |
399 | case 1: | 418 | case 1: |
400 | // We need to adjust the timeout in case we didn't receive | 419 | // We need to adjust the timeout in case we didn't receive |
401 | // a conflicting packet. | 420 | // a conflicting packet. |
@@ -408,8 +427,7 @@ int zcip_main(int argc, char **argv) | |||
408 | timeout_ms = 0; | 427 | timeout_ms = 0; |
409 | } else { | 428 | } else { |
410 | VDBG("adjusting timeout\n"); | 429 | VDBG("adjusting timeout\n"); |
411 | timeout_ms = diff / 1000; | 430 | timeout_ms = (diff / 1000) | 1; /* never 0 */ |
412 | if (!timeout_ms) timeout_ms = 1; | ||
413 | } | 431 | } |
414 | } | 432 | } |
415 | 433 | ||
@@ -417,10 +435,10 @@ int zcip_main(int argc, char **argv) | |||
417 | if (fds[0].revents & POLLERR) { | 435 | if (fds[0].revents & POLLERR) { |
418 | // FIXME: links routinely go down; | 436 | // FIXME: links routinely go down; |
419 | // this shouldn't necessarily exit. | 437 | // this shouldn't necessarily exit. |
420 | bb_error_msg("%s: poll error", intf); | 438 | bb_error_msg("iface %s is down", intf); |
421 | if (ready) { | 439 | if (ready) { |
422 | script_av[1] = (char*)"deconfig"; | 440 | script_av[1] = (char*)"deconfig"; |
423 | run(script_av, intf, &ip); | 441 | run(script_av, &ip); |
424 | } | 442 | } |
425 | return EXIT_FAILURE; | 443 | return EXIT_FAILURE; |
426 | } | 444 | } |
@@ -428,21 +446,20 @@ int zcip_main(int argc, char **argv) | |||
428 | } | 446 | } |
429 | 447 | ||
430 | // read ARP packet | 448 | // read ARP packet |
431 | if (recv(fd, &p, sizeof(p), 0) < 0) { | 449 | if (safe_read(sock_fd, &p, sizeof(p)) < 0) { |
432 | why = "recv"; | 450 | why = "recv"; |
433 | goto bad; | 451 | goto bad; |
434 | } | 452 | } |
435 | if (p.hdr.ether_type != htons(ETHERTYPE_ARP)) | 453 | if (p.eth.ether_type != htons(ETHERTYPE_ARP)) |
436 | continue; | 454 | continue; |
437 | |||
438 | #ifdef DEBUG | 455 | #ifdef DEBUG |
439 | { | 456 | { |
440 | struct ether_addr * sha = (struct ether_addr *) p.arp.arp_sha; | 457 | struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; |
441 | struct ether_addr * tha = (struct ether_addr *) p.arp.arp_tha; | 458 | struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; |
442 | struct in_addr * spa = (struct in_addr *) p.arp.arp_spa; | 459 | struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; |
443 | struct in_addr * tpa = (struct in_addr *) p.arp.arp_tpa; | 460 | struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; |
444 | VDBG("%s recv arp type=%d, op=%d,\n", | 461 | VDBG("%s recv arp type=%d, op=%d,\n", |
445 | intf, ntohs(p.hdr.ether_type), | 462 | intf, ntohs(p.eth.ether_type), |
446 | ntohs(p.arp.arp_op)); | 463 | ntohs(p.arp.arp_op)); |
447 | VDBG("\tsource=%s %s\n", | 464 | VDBG("\tsource=%s %s\n", |
448 | ether_ntoa(sha), | 465 | ether_ntoa(sha), |
@@ -453,16 +470,21 @@ int zcip_main(int argc, char **argv) | |||
453 | } | 470 | } |
454 | #endif | 471 | #endif |
455 | if (p.arp.arp_op != htons(ARPOP_REQUEST) | 472 | if (p.arp.arp_op != htons(ARPOP_REQUEST) |
456 | && p.arp.arp_op != htons(ARPOP_REPLY)) | 473 | && p.arp.arp_op != htons(ARPOP_REPLY)) |
457 | continue; | 474 | continue; |
458 | 475 | ||
459 | if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 && | 476 | source_ip_conflict = 0; |
460 | memcmp(ð_addr, &p.arp.arp_sha, ETH_ALEN) != 0) { | 477 | target_ip_conflict = 0; |
478 | |||
479 | if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 | ||
480 | && memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0 | ||
481 | ) { | ||
461 | source_ip_conflict = 1; | 482 | source_ip_conflict = 1; |
462 | } | 483 | } |
463 | if (memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 && | 484 | if (p.arp.arp_op == htons(ARPOP_REQUEST) |
464 | p.arp.arp_op == htons(ARPOP_REQUEST) && | 485 | && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 |
465 | memcmp(ð_addr, &p.arp.arp_tha, ETH_ALEN) != 0) { | 486 | && memcmp(&p.arp.arp_tha, ð_addr, ETH_ALEN) != 0 |
487 | ) { | ||
466 | target_ip_conflict = 1; | 488 | target_ip_conflict = 1; |
467 | } | 489 | } |
468 | 490 | ||
@@ -494,10 +516,9 @@ int zcip_main(int argc, char **argv) | |||
494 | VDBG("monitor conflict -- defending\n"); | 516 | VDBG("monitor conflict -- defending\n"); |
495 | state = DEFEND; | 517 | state = DEFEND; |
496 | timeout_ms = DEFEND_INTERVAL * 1000; | 518 | timeout_ms = DEFEND_INTERVAL * 1000; |
497 | arp(fd, &saddr, | 519 | arp(ARPOP_REQUEST, |
498 | ARPOP_REQUEST, | 520 | ð_addr, ip, |
499 | ð_addr, ip, | 521 | ð_addr, ip); |
500 | ð_addr, ip); | ||
501 | } | 522 | } |
502 | break; | 523 | break; |
503 | case DEFEND: | 524 | case DEFEND: |
@@ -507,7 +528,7 @@ int zcip_main(int argc, char **argv) | |||
507 | VDBG("defend conflict -- starting over\n"); | 528 | VDBG("defend conflict -- starting over\n"); |
508 | ready = 0; | 529 | ready = 0; |
509 | script_av[1] = (char*)"deconfig"; | 530 | script_av[1] = (char*)"deconfig"; |
510 | run(script_av, intf, &ip); | 531 | run(script_av, &ip); |
511 | 532 | ||
512 | // restart the whole protocol | 533 | // restart the whole protocol |
513 | pick(&ip); | 534 | pick(&ip); |
@@ -530,6 +551,6 @@ int zcip_main(int argc, char **argv) | |||
530 | } // switch poll | 551 | } // switch poll |
531 | } // while (1) | 552 | } // while (1) |
532 | bad: | 553 | bad: |
533 | bb_perror_msg("%s, %s", intf, why); | 554 | bb_perror_msg("%s: %s", intf, why); |
534 | return EXIT_FAILURE; | 555 | return EXIT_FAILURE; |
535 | } | 556 | } |