aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2006-03-30 21:50:57 +0000
committerRob Landley <rob@landley.net>2006-03-30 21:50:57 +0000
commit8ea5205726e2ebcd2b12737f47b5cd1a9c1c8289 (patch)
tree7fd85ad55669b913b1ef1c0537b286f91126fd69
parent1f6dc6d35803dd1cf28653a0b521a26084ef3d43 (diff)
downloadbusybox-w32-8ea5205726e2ebcd2b12737f47b5cd1a9c1c8289.tar.gz
busybox-w32-8ea5205726e2ebcd2b12737f47b5cd1a9c1c8289.tar.bz2
busybox-w32-8ea5205726e2ebcd2b12737f47b5cd1a9c1c8289.zip
Shrink patch from Bernhard Fischer.
-rw-r--r--networking/arping.c150
1 files changed, 69 insertions, 81 deletions
diff --git a/networking/arping.c b/networking/arping.c
index b30cb535e..90a03a58e 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -1,10 +1,8 @@
1/* vi:set ts=4:*/
1/* 2/*
2 * arping.c - Ping hosts by ARP requests/replies 3 * arping.c - Ping hosts by ARP requests/replies
3 * 4 *
4 * This program is free software; you can redistribute it and/or 5 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 * 6 *
9 * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 7 * Author: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
10 * Busybox port: Nick Fedchik <nick@fedchik.org.ua> 8 * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
@@ -26,29 +24,32 @@
26 24
27#include "busybox.h" 25#include "busybox.h"
28 26
29#define APPLET_NAME "arping"
30
31static struct in_addr src; 27static struct in_addr src;
32static struct in_addr dst; 28static struct in_addr dst;
33static struct sockaddr_ll me; 29static struct sockaddr_ll me;
34static struct sockaddr_ll he; 30static struct sockaddr_ll he;
35static struct timeval last; 31static struct timeval last;
36static int dad; 32struct cfg_s {
37static int unsolicited; 33 int dad:1;
38static int advert; 34 int unsolicited:1;
39static int quiet; 35 int advert:1;
40static int quit_on_reply = 0; 36 int quiet:1;
37 int quit_on_reply:1;
38 int unicasting:1;
39 int broadcast_only:1;
40};
41static struct cfg_s cfg;
42
43static int s;
41static int count = -1; 44static int count = -1;
42static int timeout; 45static int timeout;
43static int unicasting;
44static int s;
45static int broadcast_only;
46static int sent; 46static int sent;
47static int brd_sent; 47static int brd_sent;
48static int received; 48static int received;
49static int brd_recv; 49static int brd_recv;
50static int req_recv; 50static int req_recv;
51 51
52
52#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \ 53#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
53 ((tv1).tv_usec-(tv2).tv_usec)/1000 ) 54 ((tv1).tv_usec-(tv2).tv_usec)/1000 )
54#if 0 55#if 0
@@ -69,7 +70,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
69{ 70{
70 int err; 71 int err;
71 struct timeval now; 72 struct timeval now;
72 unsigned char buf[256]; 73 RESERVE_CONFIG_UBUFFER(buf, 256);
73 struct arphdr *ah = (struct arphdr *) buf; 74 struct arphdr *ah = (struct arphdr *) buf;
74 unsigned char *p = (unsigned char *) (ah + 1); 75 unsigned char *p = (unsigned char *) (ah + 1);
75 76
@@ -78,7 +79,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
78 ah->ar_pro = htons(ETH_P_IP); 79 ah->ar_pro = htons(ETH_P_IP);
79 ah->ar_hln = ME->sll_halen; 80 ah->ar_hln = ME->sll_halen;
80 ah->ar_pln = 4; 81 ah->ar_pln = 4;
81 ah->ar_op = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); 82 ah->ar_op = cfg.advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
82 83
83 memcpy(p, &ME->sll_addr, ah->ar_hln); 84 memcpy(p, &ME->sll_addr, ah->ar_hln);
84 p += ME->sll_halen; 85 p += ME->sll_halen;
@@ -86,7 +87,7 @@ static int send_pack(int sock, struct in_addr *src_addr,
86 memcpy(p, src_addr, 4); 87 memcpy(p, src_addr, 4);
87 p += 4; 88 p += 4;
88 89
89 if (advert) 90 if (cfg.advert)
90 memcpy(p, &ME->sll_addr, ah->ar_hln); 91 memcpy(p, &ME->sll_addr, ah->ar_hln);
91 else 92 else
92 memcpy(p, &HE->sll_addr, ah->ar_hln); 93 memcpy(p, &HE->sll_addr, ah->ar_hln);
@@ -100,15 +101,16 @@ static int send_pack(int sock, struct in_addr *src_addr,
100 if (err == p - buf) { 101 if (err == p - buf) {
101 last = now; 102 last = now;
102 sent++; 103 sent++;
103 if (!unicasting) 104 if (!cfg.unicasting)
104 brd_sent++; 105 brd_sent++;
105 } 106 }
107 RELEASE_CONFIG_BUFFER(buf);
106 return err; 108 return err;
107} 109}
108 110
109static void finish(void) 111static void finish(void)
110{ 112{
111 if (!quiet) { 113 if (!cfg.quiet) {
112 printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent); 114 printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
113 printf("Received %d repl%s", received, (received > 1) ? "ies" : "y"); 115 printf("Received %d repl%s", received, (received > 1) ? "ies" : "y");
114 if (brd_recv || req_recv) { 116 if (brd_recv || req_recv) {
@@ -122,9 +124,9 @@ static void finish(void)
122 putchar('\n'); 124 putchar('\n');
123 fflush(stdout); 125 fflush(stdout);
124 } 126 }
125 if (dad) 127 if (cfg.dad)
126 exit(!!received); 128 exit(!!received);
127 if (unsolicited) 129 if (cfg.unsolicited)
128 exit(0); 130 exit(0);
129 exit(!received); 131 exit(!received);
130} 132}
@@ -145,7 +147,7 @@ static void catcher(void)
145 147
146 if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { 148 if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) {
147 send_pack(s, &src, &dst, &me, &he); 149 send_pack(s, &src, &dst, &me, &he);
148 if (count == 0 && unsolicited) 150 if (count == 0 && cfg.unsolicited)
149 finish(); 151 finish();
150 } 152 }
151 alarm(1); 153 alarm(1);
@@ -153,13 +155,10 @@ static void catcher(void)
153 155
154static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) 156static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
155{ 157{
156 struct timeval tv;
157 struct arphdr *ah = (struct arphdr *) buf; 158 struct arphdr *ah = (struct arphdr *) buf;
158 unsigned char *p = (unsigned char *) (ah + 1); 159 unsigned char *p = (unsigned char *) (ah + 1);
159 struct in_addr src_ip, dst_ip; 160 struct in_addr src_ip, dst_ip;
160 161
161 gettimeofday(&tv, NULL);
162
163 /* Filter out wild packets */ 162 /* Filter out wild packets */
164 if (FROM->sll_pkttype != PACKET_HOST && 163 if (FROM->sll_pkttype != PACKET_HOST &&
165 FROM->sll_pkttype != PACKET_BROADCAST && 164 FROM->sll_pkttype != PACKET_BROADCAST &&
@@ -187,7 +186,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
187 return 0; 186 return 0;
188 memcpy(&src_ip, p + ah->ar_hln, 4); 187 memcpy(&src_ip, p + ah->ar_hln, 4);
189 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); 188 memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
190 if (!dad) { 189 if (!cfg.dad) {
191 if (src_ip.s_addr != dst.s_addr) 190 if (src_ip.s_addr != dst.s_addr)
192 return 0; 191 return 0;
193 if (src.s_addr != dst_ip.s_addr) 192 if (src.s_addr != dst_ip.s_addr)
@@ -215,8 +214,11 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
215 if (src.s_addr && src.s_addr != dst_ip.s_addr) 214 if (src.s_addr && src.s_addr != dst_ip.s_addr)
216 return 0; 215 return 0;
217 } 216 }
218 if (!quiet) { 217 if (!cfg.quiet) {
219 int s_printed = 0; 218 int s_printed = 0;
219 struct timeval tv;
220
221 gettimeofday(&tv, NULL);
220 222
221 printf("%s ", 223 printf("%s ",
222 FROM->sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast"); 224 FROM->sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast");
@@ -234,6 +236,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
234 printf("[%s]", 236 printf("[%s]",
235 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4)); 237 ether_ntoa((struct ether_addr *) p + ah->ar_hln + 4));
236 } 238 }
239
237 if (last.tv_sec) { 240 if (last.tv_sec) {
238 long usecs = (tv.tv_sec - last.tv_sec) * 1000000 + 241 long usecs = (tv.tv_sec - last.tv_sec) * 1000000 +
239 tv.tv_usec - last.tv_usec; 242 tv.tv_usec - last.tv_usec;
@@ -251,48 +254,46 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
251 brd_recv++; 254 brd_recv++;
252 if (ah->ar_op == htons(ARPOP_REQUEST)) 255 if (ah->ar_op == htons(ARPOP_REQUEST))
253 req_recv++; 256 req_recv++;
254 if (quit_on_reply) 257 if (cfg.quit_on_reply)
255 finish(); 258 finish();
256 if (!broadcast_only) { 259 if (!cfg.broadcast_only) {
257 memcpy(he.sll_addr, p, me.sll_halen); 260 memcpy(he.sll_addr, p, me.sll_halen);
258 unicasting = 1; 261 cfg.unicasting = 1;
259 } 262 }
260 return 1; 263 return 1;
261} 264}
262 265
263int arping_main(int argc, char **argv) 266int arping_main(int argc, char **argv)
264{ 267{
265 int socket_errno;
266 int ch; 268 int ch;
267 uid_t uid = getuid();
268 char *device = "eth0"; 269 char *device = "eth0";
269 int ifindex = 0; 270 int ifindex;
270 char *source = NULL; 271 char *source = NULL;
271 char *target; 272 char *target;
272 273
273 s = socket(PF_PACKET, SOCK_DGRAM, 0); 274 s = socket(PF_PACKET, SOCK_DGRAM, 0);
274 socket_errno = errno; 275 ifindex = errno;
275 276
276 setuid(uid); 277 setuid(getuid());
277 278
278 while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:")) != EOF) { 279 while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:")) != EOF) {
279 switch (ch) { 280 switch (ch) {
280 case 'b': 281 case 'b':
281 broadcast_only = 1; 282 cfg.broadcast_only = 1;
282 break; 283 break;
283 case 'D': 284 case 'D':
284 dad++; 285 cfg.dad = 1;
285 quit_on_reply = 1; 286 cfg.quit_on_reply = 1;
286 break; 287 break;
287 case 'U': 288 case 'U':
288 unsolicited++; 289 cfg.unsolicited = 1;
289 break; 290 break;
290 case 'A': 291 case 'A':
291 advert++; 292 cfg.advert = 1;
292 unsolicited++; 293 cfg.unsolicited = 1;
293 break; 294 break;
294 case 'q': 295 case 'q':
295 quiet++; 296 cfg.quiet = 1;
296 break; 297 break;
297 case 'c': 298 case 'c':
298 count = atoi(optarg); 299 count = atoi(optarg);
@@ -304,14 +305,13 @@ int arping_main(int argc, char **argv)
304 if (optarg == NULL) 305 if (optarg == NULL)
305 bb_show_usage(); 306 bb_show_usage();
306 if (bb_strlen(optarg) > IF_NAMESIZE) { 307 if (bb_strlen(optarg) > IF_NAMESIZE) {
307 bb_error_msg("Interface name `%s' must be less than %d", optarg, 308 bb_error_msg_and_die("Interface name `%s' must be less than %d",
308 IF_NAMESIZE); 309 optarg, IF_NAMESIZE);
309 exit(2);
310 } 310 }
311 device = optarg; 311 device = optarg;
312 break; 312 break;
313 case 'f': 313 case 'f':
314 quit_on_reply = 1; 314 cfg.quit_on_reply = 1;
315 break; 315 break;
316 case 's': 316 case 's':
317 source = optarg; 317 source = optarg;
@@ -329,11 +329,11 @@ int arping_main(int argc, char **argv)
329 bb_show_usage(); 329 bb_show_usage();
330 330
331 target = *argv; 331 target = *argv;
332 332 bb_default_error_retval = 2;
333 333
334 if (s < 0) { 334 if (s < 0) {
335 bb_error_msg("socket"); 335 bb_perror_msg("socket");
336 exit(socket_errno); 336 exit(ifindex);
337 } 337 }
338 338
339 { 339 {
@@ -342,22 +342,19 @@ int arping_main(int argc, char **argv)
342 memset(&ifr, 0, sizeof(ifr)); 342 memset(&ifr, 0, sizeof(ifr));
343 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1); 343 strncpy(ifr.ifr_name, device, IFNAMSIZ - 1);
344 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 344 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
345 bb_error_msg("Interface %s not found", device); 345 bb_error_msg_and_die("Interface %s not found", device);
346 exit(2);
347 } 346 }
348 ifindex = ifr.ifr_ifindex; 347 ifindex = ifr.ifr_ifindex;
349 348
350 if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) { 349 if (ioctl(s, SIOCGIFFLAGS, (char *) &ifr)) {
351 bb_error_msg("SIOCGIFFLAGS"); 350 bb_error_msg_and_die("SIOCGIFFLAGS");
352 exit(2);
353 } 351 }
354 if (!(ifr.ifr_flags & IFF_UP)) { 352 if (!(ifr.ifr_flags & IFF_UP)) {
355 bb_error_msg("Interface %s is down", device); 353 bb_error_msg_and_die("Interface %s is down", device);
356 exit(2);
357 } 354 }
358 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { 355 if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) {
359 bb_error_msg("Interface %s is not ARPable", device); 356 bb_error_msg("Interface %s is not ARPable", device);
360 exit(dad ? 0 : 2); 357 exit(cfg.dad ? 0 : 2);
361 } 358 }
362 } 359 }
363 360
@@ -366,27 +363,24 @@ int arping_main(int argc, char **argv)
366 363
367 hp = gethostbyname2(target, AF_INET); 364 hp = gethostbyname2(target, AF_INET);
368 if (!hp) { 365 if (!hp) {
369 bb_error_msg("invalid or unknown target %s", target); 366 bb_error_msg_and_die("invalid or unknown target %s", target);
370 exit(2);
371 } 367 }
372 memcpy(&dst, hp->h_addr, 4); 368 memcpy(&dst, hp->h_addr, 4);
373 } 369 }
374 370
375 if (source && !inet_aton(source, &src)) { 371 if (source && !inet_aton(source, &src)) {
376 bb_error_msg("invalid source address %s", source); 372 bb_error_msg_and_die("invalid source address %s", source);
377 exit(2);
378 } 373 }
379 374
380 if (!dad && unsolicited && src.s_addr == 0) 375 if (!cfg.dad && cfg.unsolicited && src.s_addr == 0)
381 src = dst; 376 src = dst;
382 377
383 if (!dad || src.s_addr) { 378 if (!cfg.dad || src.s_addr) {
384 struct sockaddr_in saddr; 379 struct sockaddr_in saddr;
385 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); 380 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
386 381
387 if (probe_fd < 0) { 382 if (probe_fd < 0) {
388 bb_error_msg("socket"); 383 bb_error_msg_and_die("socket");
389 exit(2);
390 } 384 }
391 if (device) { 385 if (device) {
392 if (setsockopt 386 if (setsockopt
@@ -399,10 +393,9 @@ int arping_main(int argc, char **argv)
399 if (src.s_addr) { 393 if (src.s_addr) {
400 saddr.sin_addr = src; 394 saddr.sin_addr = src;
401 if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { 395 if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
402 bb_error_msg("bind"); 396 bb_error_msg_and_die("bind");
403 exit(2);
404 } 397 }
405 } else if (!dad) { 398 } else if (!cfg.dad) {
406 int on = 1; 399 int on = 1;
407 socklen_t alen = sizeof(saddr); 400 socklen_t alen = sizeof(saddr);
408 401
@@ -412,16 +405,14 @@ int arping_main(int argc, char **argv)
412 if (setsockopt 405 if (setsockopt
413 (probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on, 406 (probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *) &on,
414 sizeof(on)) == -1) 407 sizeof(on)) == -1)
415 perror("WARNING: setsockopt(SO_DONTROUTE)"); 408 bb_perror_msg("WARNING: setsockopt(SO_DONTROUTE)");
416 if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) 409 if (connect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr))
417 == -1) { 410 == -1) {
418 bb_error_msg("connect"); 411 bb_error_msg_and_die("connect");
419 exit(2);
420 } 412 }
421 if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == 413 if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) ==
422 -1) { 414 -1) {
423 bb_error_msg("getsockname"); 415 bb_error_msg_and_die("getsockname");
424 exit(2);
425 } 416 }
426 src = saddr.sin_addr; 417 src = saddr.sin_addr;
427 } 418 }
@@ -432,34 +423,31 @@ int arping_main(int argc, char **argv)
432 me.sll_ifindex = ifindex; 423 me.sll_ifindex = ifindex;
433 me.sll_protocol = htons(ETH_P_ARP); 424 me.sll_protocol = htons(ETH_P_ARP);
434 if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) { 425 if (bind(s, (struct sockaddr *) &me, sizeof(me)) == -1) {
435 bb_error_msg("bind"); 426 bb_error_msg_and_die("bind");
436 exit(2);
437 } 427 }
438 428
439 { 429 {
440 socklen_t alen = sizeof(me); 430 socklen_t alen = sizeof(me);
441 431
442 if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) { 432 if (getsockname(s, (struct sockaddr *) &me, &alen) == -1) {
443 bb_error_msg("getsockname"); 433 bb_error_msg_and_die("getsockname");
444 exit(2);
445 } 434 }
446 } 435 }
447 if (me.sll_halen == 0) { 436 if (me.sll_halen == 0) {
448 bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device); 437 bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device);
449 exit(dad ? 0 : 2); 438 exit(cfg.dad ? 0 : 2);
450 } 439 }
451 he = me; 440 he = me;
452 memset(he.sll_addr, -1, he.sll_halen); 441 memset(he.sll_addr, -1, he.sll_halen);
453 442
454 if (!quiet) { 443 if (!cfg.quiet) {
455 printf("ARPING to %s", inet_ntoa(dst)); 444 printf("ARPING to %s", inet_ntoa(dst));
456 printf(" from %s via %s\n", inet_ntoa(src), 445 printf(" from %s via %s\n", inet_ntoa(src),
457 device ? device : "unknown"); 446 device ? device : "unknown");
458 } 447 }
459 448
460 if (!src.s_addr && !dad) { 449 if (!src.s_addr && !cfg.dad) {
461 bb_error_msg("no src address in the non-DAD mode"); 450 bb_error_msg_and_die("no src address in the non-DAD mode");
462 exit(2);
463 } 451 }
464 452
465 { 453 {