diff options
Diffstat (limited to 'networking/arping.c')
-rw-r--r-- | networking/arping.c | 83 |
1 files changed, 41 insertions, 42 deletions
diff --git a/networking/arping.c b/networking/arping.c index a022e70ea..7a9fbc2f4 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -33,18 +33,17 @@ enum { | |||
33 | BCAST_ONLY = 32, | 33 | BCAST_ONLY = 32, |
34 | UNICASTING = 64 | 34 | UNICASTING = 64 |
35 | }; | 35 | }; |
36 | static int cfg; | ||
37 | 36 | ||
38 | static int s; | 37 | static int sock; |
39 | static unsigned count = UINT_MAX; | 38 | static unsigned count = UINT_MAX; |
40 | static unsigned timeout_us; | 39 | static unsigned timeout_us; |
41 | static int sent; | 40 | static unsigned sent; |
42 | static int brd_sent; | 41 | static unsigned brd_sent; |
43 | static int received; | 42 | static unsigned received; |
44 | static int brd_recv; | 43 | static unsigned brd_recv; |
45 | static int req_recv; | 44 | static unsigned req_recv; |
46 | 45 | ||
47 | static int send_pack(int sock, struct in_addr *src_addr, | 46 | static int send_pack(struct in_addr *src_addr, |
48 | struct in_addr *dst_addr, struct sockaddr_ll *ME, | 47 | struct in_addr *dst_addr, struct sockaddr_ll *ME, |
49 | struct sockaddr_ll *HE) | 48 | struct sockaddr_ll *HE) |
50 | { | 49 | { |
@@ -59,7 +58,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
59 | ah->ar_pro = htons(ETH_P_IP); | 58 | ah->ar_pro = htons(ETH_P_IP); |
60 | ah->ar_hln = ME->sll_halen; | 59 | ah->ar_hln = ME->sll_halen; |
61 | ah->ar_pln = 4; | 60 | ah->ar_pln = 4; |
62 | ah->ar_op = cfg & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); | 61 | ah->ar_op = option_mask32 & ADVERT ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); |
63 | 62 | ||
64 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 63 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
65 | p += ME->sll_halen; | 64 | p += ME->sll_halen; |
@@ -67,7 +66,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
67 | memcpy(p, src_addr, 4); | 66 | memcpy(p, src_addr, 4); |
68 | p += 4; | 67 | p += 4; |
69 | 68 | ||
70 | if (cfg & ADVERT) | 69 | if (option_mask32 & ADVERT) |
71 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 70 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
72 | else | 71 | else |
73 | memcpy(p, &HE->sll_addr, ah->ar_hln); | 72 | memcpy(p, &HE->sll_addr, ah->ar_hln); |
@@ -81,7 +80,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
81 | if (err == p - buf) { | 80 | if (err == p - buf) { |
82 | last = now; | 81 | last = now; |
83 | sent++; | 82 | sent++; |
84 | if (!(cfg & UNICASTING)) | 83 | if (!(option_mask32 & UNICASTING)) |
85 | brd_sent++; | 84 | brd_sent++; |
86 | } | 85 | } |
87 | return err; | 86 | return err; |
@@ -90,17 +89,17 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
90 | static void finish(void) ATTRIBUTE_NORETURN; | 89 | static void finish(void) ATTRIBUTE_NORETURN; |
91 | static void finish(void) | 90 | static void finish(void) |
92 | { | 91 | { |
93 | if (!(cfg & QUIET)) { | 92 | if (!(option_mask32 & QUIET)) { |
94 | printf("Sent %d probe(s) (%d broadcast(s))\n" | 93 | printf("Sent %u probe(s) (%u broadcast(s))\n" |
95 | "Received %d repl%s" | 94 | "Received %u repl%s" |
96 | " (%d request(s), %d broadcast(s))\n", | 95 | " (%u request(s), %u broadcast(s))\n", |
97 | sent, brd_sent, | 96 | sent, brd_sent, |
98 | received, (received == 1) ? "ies" : "y", | 97 | received, (received == 1) ? "ies" : "y", |
99 | req_recv, brd_recv); | 98 | req_recv, brd_recv); |
100 | } | 99 | } |
101 | if (cfg & DAD) | 100 | if (option_mask32 & DAD) |
102 | exit(!!received); | 101 | exit(!!received); |
103 | if (cfg & UNSOLICITED) | 102 | if (option_mask32 & UNSOLICITED) |
104 | exit(0); | 103 | exit(0); |
105 | exit(!received); | 104 | exit(!received); |
106 | } | 105 | } |
@@ -121,8 +120,8 @@ static void catcher(void) | |||
121 | count--; | 120 | count--; |
122 | 121 | ||
123 | if (last == 0 || (now - last) > 500000) { | 122 | if (last == 0 || (now - last) > 500000) { |
124 | send_pack(s, &src, &dst, &me, &he); | 123 | send_pack(&src, &dst, &me, &he); |
125 | if (count == 0 && (cfg & UNSOLICITED)) | 124 | if (count == 0 && (option_mask32 & UNSOLICITED)) |
126 | finish(); | 125 | finish(); |
127 | } | 126 | } |
128 | alarm(1); | 127 | alarm(1); |
@@ -160,7 +159,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
160 | return 0; | 159 | return 0; |
161 | memcpy(&src_ip, p + ah->ar_hln, 4); | 160 | memcpy(&src_ip, p + ah->ar_hln, 4); |
162 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); | 161 | memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); |
163 | if (!(cfg & DAD)) { | 162 | if (!(option_mask32 & DAD)) { |
164 | if (src_ip.s_addr != dst.s_addr) | 163 | if (src_ip.s_addr != dst.s_addr) |
165 | return 0; | 164 | return 0; |
166 | if (src.s_addr != dst_ip.s_addr) | 165 | if (src.s_addr != dst_ip.s_addr) |
@@ -188,7 +187,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
188 | if (src.s_addr && src.s_addr != dst_ip.s_addr) | 187 | if (src.s_addr && src.s_addr != dst_ip.s_addr) |
189 | return 0; | 188 | return 0; |
190 | } | 189 | } |
191 | if (!(cfg & QUIET)) { | 190 | if (!(option_mask32 & QUIET)) { |
192 | int s_printed = 0; | 191 | int s_printed = 0; |
193 | 192 | ||
194 | printf("%scast re%s from %s [%s]", | 193 | printf("%scast re%s from %s [%s]", |
@@ -219,11 +218,11 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
219 | brd_recv++; | 218 | brd_recv++; |
220 | if (ah->ar_op == htons(ARPOP_REQUEST)) | 219 | if (ah->ar_op == htons(ARPOP_REQUEST)) |
221 | req_recv++; | 220 | req_recv++; |
222 | if (cfg & QUIT_ON_REPLY) | 221 | if (option_mask32 & QUIT_ON_REPLY) |
223 | finish(); | 222 | finish(); |
224 | if (!(cfg & BCAST_ONLY)) { | 223 | if (!(option_mask32 & BCAST_ONLY)) { |
225 | memcpy(he.sll_addr, p, me.sll_halen); | 224 | memcpy(he.sll_addr, p, me.sll_halen); |
226 | cfg |= UNICASTING; | 225 | option_mask32 |= UNICASTING; |
227 | } | 226 | } |
228 | return 1; | 227 | return 1; |
229 | } | 228 | } |
@@ -237,32 +236,32 @@ int arping_main(int argc, char **argv) | |||
237 | char *target; | 236 | char *target; |
238 | unsigned char *packet; | 237 | unsigned char *packet; |
239 | 238 | ||
240 | s = xsocket(PF_PACKET, SOCK_DGRAM, 0); | 239 | sock = xsocket(PF_PACKET, SOCK_DGRAM, 0); |
241 | 240 | ||
242 | // Drop suid root privileges | 241 | // Drop suid root privileges |
243 | xsetuid(getuid()); | 242 | xsetuid(getuid()); |
244 | 243 | ||
245 | { | 244 | { |
246 | unsigned opt; | 245 | unsigned opt; |
247 | char *_count, *_timeout; | 246 | char *str_count, *str_timeout; |
248 | 247 | ||
249 | /* Dad also sets quit_on_reply. | 248 | /* Dad also sets quit_on_reply. |
250 | * Advert also sets unsolicited. | 249 | * Advert also sets unsolicited. |
251 | */ | 250 | */ |
252 | opt_complementary = "=1:Df:AU"; | 251 | opt_complementary = "=1:Df:AU"; |
253 | opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", | 252 | opt = getopt32(argc, argv, "DUAqfbc:w:I:s:", |
254 | &_count, &_timeout, &device, &source); | 253 | &str_count, &str_timeout, &device, &source); |
255 | cfg |= opt & 0x3f; /* set respective flags */ | ||
256 | if (opt & 0x40) /* -c: count */ | 254 | if (opt & 0x40) /* -c: count */ |
257 | count = xatou(_count); | 255 | count = xatou(str_count); |
258 | if (opt & 0x80) /* -w: timeout */ | 256 | if (opt & 0x80) /* -w: timeout */ |
259 | timeout_us = xatou_range(_timeout, 0, INT_MAX/2000000) * 1000000; | 257 | timeout_us = xatou_range(str_timeout, 0, INT_MAX/2000000) * 1000000; |
260 | //if (opt & 0x100) /* -I: interface */ | 258 | //if (opt & 0x100) /* -I: interface */ |
261 | if (strlen(device) >= IF_NAMESIZE) { | 259 | if (strlen(device) >= IF_NAMESIZE) { |
262 | bb_error_msg_and_die("interface name '%s' is too long", | 260 | bb_error_msg_and_die("interface name '%s' is too long", |
263 | device); | 261 | device); |
264 | } | 262 | } |
265 | //if (opt & 0x200) /* -s: source */ | 263 | //if (opt & 0x200) /* -s: source */ |
264 | option_mask32 &= 0x3f; /* set respective flags */ | ||
266 | } | 265 | } |
267 | 266 | ||
268 | target = argv[optind]; | 267 | target = argv[optind]; |
@@ -274,12 +273,12 @@ int arping_main(int argc, char **argv) | |||
274 | 273 | ||
275 | memset(&ifr, 0, sizeof(ifr)); | 274 | memset(&ifr, 0, sizeof(ifr)); |
276 | strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); | 275 | strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); |
277 | if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { | 276 | if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { |
278 | bb_error_msg_and_die("interface %s not found", device); | 277 | bb_error_msg_and_die("interface %s not found", device); |
279 | } | 278 | } |
280 | ifindex = ifr.ifr_ifindex; | 279 | ifindex = ifr.ifr_ifindex; |
281 | 280 | ||
282 | if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { | 281 | if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifr)) { |
283 | bb_error_msg_and_die("SIOCGIFFLAGS"); | 282 | bb_error_msg_and_die("SIOCGIFFLAGS"); |
284 | } | 283 | } |
285 | if (!(ifr.ifr_flags & IFF_UP)) { | 284 | if (!(ifr.ifr_flags & IFF_UP)) { |
@@ -287,7 +286,7 @@ int arping_main(int argc, char **argv) | |||
287 | } | 286 | } |
288 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { | 287 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { |
289 | bb_error_msg("interface %s is not ARPable", device); | 288 | bb_error_msg("interface %s is not ARPable", device); |
290 | return (cfg & DAD ? 0 : 2); | 289 | return (option_mask32 & DAD ? 0 : 2); |
291 | } | 290 | } |
292 | } | 291 | } |
293 | 292 | ||
@@ -303,10 +302,10 @@ int arping_main(int argc, char **argv) | |||
303 | bb_error_msg_and_die("invalid source address %s", source); | 302 | bb_error_msg_and_die("invalid source address %s", source); |
304 | } | 303 | } |
305 | 304 | ||
306 | if (!(cfg & DAD) && (cfg & UNSOLICITED) && src.s_addr == 0) | 305 | if (!(option_mask32 & DAD) && (option_mask32 & UNSOLICITED) && src.s_addr == 0) |
307 | src = dst; | 306 | src = dst; |
308 | 307 | ||
309 | if (!(cfg & DAD) || src.s_addr) { | 308 | if (!(option_mask32 & DAD) || src.s_addr) { |
310 | struct sockaddr_in saddr; | 309 | struct sockaddr_in saddr; |
311 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); | 310 | int probe_fd = xsocket(AF_INET, SOCK_DGRAM, 0); |
312 | 311 | ||
@@ -319,7 +318,7 @@ int arping_main(int argc, char **argv) | |||
319 | if (src.s_addr) { | 318 | if (src.s_addr) { |
320 | saddr.sin_addr = src; | 319 | saddr.sin_addr = src; |
321 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); | 320 | xbind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
322 | } else if (!(cfg & DAD)) { | 321 | } else if (!(option_mask32 & DAD)) { |
323 | socklen_t alen = sizeof(saddr); | 322 | socklen_t alen = sizeof(saddr); |
324 | 323 | ||
325 | saddr.sin_port = htons(1025); | 324 | saddr.sin_port = htons(1025); |
@@ -339,29 +338,29 @@ int arping_main(int argc, char **argv) | |||
339 | me.sll_family = AF_PACKET; | 338 | me.sll_family = AF_PACKET; |
340 | me.sll_ifindex = ifindex; | 339 | me.sll_ifindex = ifindex; |
341 | me.sll_protocol = htons(ETH_P_ARP); | 340 | me.sll_protocol = htons(ETH_P_ARP); |
342 | xbind(s, (struct sockaddr *) &me, sizeof(me)); | 341 | xbind(sock, (struct sockaddr *) &me, sizeof(me)); |
343 | 342 | ||
344 | { | 343 | { |
345 | socklen_t alen = sizeof(me); | 344 | socklen_t alen = sizeof(me); |
346 | 345 | ||
347 | if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) { | 346 | if (getsockname(sock, (struct sockaddr *) &me, &alen) == -1) { |
348 | bb_error_msg_and_die("getsockname"); | 347 | bb_error_msg_and_die("getsockname"); |
349 | } | 348 | } |
350 | } | 349 | } |
351 | if (me.sll_halen == 0) { | 350 | if (me.sll_halen == 0) { |
352 | bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); | 351 | bb_error_msg("interface \"%s\" is not ARPable (no ll address)", device); |
353 | return (cfg & DAD ? 0 : 2); | 352 | return (option_mask32 & DAD ? 0 : 2); |
354 | } | 353 | } |
355 | he = me; | 354 | he = me; |
356 | memset(he.sll_addr, -1, he.sll_halen); | 355 | memset(he.sll_addr, -1, he.sll_halen); |
357 | 356 | ||
358 | if (!(cfg & QUIET)) { | 357 | if (!(option_mask32 & QUIET)) { |
359 | printf("ARPING to %s from %s via %s\n", | 358 | printf("ARPING to %s from %s via %s\n", |
360 | inet_ntoa(dst), inet_ntoa(src), | 359 | inet_ntoa(dst), inet_ntoa(src), |
361 | device ? device : "unknown"); | 360 | device ? device : "unknown"); |
362 | } | 361 | } |
363 | 362 | ||
364 | if (!src.s_addr && !(cfg & DAD)) { | 363 | if (!src.s_addr && !(option_mask32 & DAD)) { |
365 | bb_error_msg_and_die("no src address in the non-DAD mode"); | 364 | bb_error_msg_and_die("no src address in the non-DAD mode"); |
366 | } | 365 | } |
367 | 366 | ||
@@ -387,7 +386,7 @@ int arping_main(int argc, char **argv) | |||
387 | socklen_t alen = sizeof(from); | 386 | socklen_t alen = sizeof(from); |
388 | int cc; | 387 | int cc; |
389 | 388 | ||
390 | cc = recvfrom(s, packet, 4096, 0, (struct sockaddr *) &from, &alen); | 389 | cc = recvfrom(sock, packet, 4096, 0, (struct sockaddr *) &from, &alen); |
391 | if (cc < 0) { | 390 | if (cc < 0) { |
392 | bb_perror_msg("recvfrom"); | 391 | bb_perror_msg("recvfrom"); |
393 | continue; | 392 | continue; |