diff options
-rw-r--r-- | networking/arping.c | 141 |
1 files changed, 65 insertions, 76 deletions
diff --git a/networking/arping.c b/networking/arping.c index 90a03a58e..782b61b64 100644 --- a/networking/arping.c +++ b/networking/arping.c | |||
@@ -29,16 +29,17 @@ static struct in_addr dst; | |||
29 | static struct sockaddr_ll me; | 29 | static struct sockaddr_ll me; |
30 | static struct sockaddr_ll he; | 30 | static struct sockaddr_ll he; |
31 | static struct timeval last; | 31 | static struct timeval last; |
32 | struct cfg_s { | 32 | |
33 | int dad:1; | 33 | enum cfg_e { |
34 | int unsolicited:1; | 34 | dad = 1, |
35 | int advert:1; | 35 | unsolicited = 2, |
36 | int quiet:1; | 36 | advert = 4, |
37 | int quit_on_reply:1; | 37 | quiet = 8, |
38 | int unicasting:1; | 38 | quit_on_reply = 16, |
39 | int broadcast_only:1; | 39 | unicasting = 32, |
40 | broadcast_only = 64 | ||
40 | }; | 41 | }; |
41 | static struct cfg_s cfg; | 42 | static int cfg; |
42 | 43 | ||
43 | static int s; | 44 | static int s; |
44 | static int count = -1; | 45 | static int count = -1; |
@@ -70,7 +71,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
70 | { | 71 | { |
71 | int err; | 72 | int err; |
72 | struct timeval now; | 73 | struct timeval now; |
73 | RESERVE_CONFIG_UBUFFER(buf, 256); | 74 | unsigned char buf[256]; |
74 | struct arphdr *ah = (struct arphdr *) buf; | 75 | struct arphdr *ah = (struct arphdr *) buf; |
75 | unsigned char *p = (unsigned char *) (ah + 1); | 76 | unsigned char *p = (unsigned char *) (ah + 1); |
76 | 77 | ||
@@ -79,7 +80,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
79 | ah->ar_pro = htons(ETH_P_IP); | 80 | ah->ar_pro = htons(ETH_P_IP); |
80 | ah->ar_hln = ME->sll_halen; | 81 | ah->ar_hln = ME->sll_halen; |
81 | ah->ar_pln = 4; | 82 | ah->ar_pln = 4; |
82 | ah->ar_op = cfg.advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); | 83 | ah->ar_op = cfg&advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST); |
83 | 84 | ||
84 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 85 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
85 | p += ME->sll_halen; | 86 | p += ME->sll_halen; |
@@ -87,7 +88,7 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
87 | memcpy(p, src_addr, 4); | 88 | memcpy(p, src_addr, 4); |
88 | p += 4; | 89 | p += 4; |
89 | 90 | ||
90 | if (cfg.advert) | 91 | if (cfg&advert) |
91 | memcpy(p, &ME->sll_addr, ah->ar_hln); | 92 | memcpy(p, &ME->sll_addr, ah->ar_hln); |
92 | else | 93 | else |
93 | memcpy(p, &HE->sll_addr, ah->ar_hln); | 94 | memcpy(p, &HE->sll_addr, ah->ar_hln); |
@@ -101,16 +102,15 @@ static int send_pack(int sock, struct in_addr *src_addr, | |||
101 | if (err == p - buf) { | 102 | if (err == p - buf) { |
102 | last = now; | 103 | last = now; |
103 | sent++; | 104 | sent++; |
104 | if (!cfg.unicasting) | 105 | if (!(cfg&unicasting)) |
105 | brd_sent++; | 106 | brd_sent++; |
106 | } | 107 | } |
107 | RELEASE_CONFIG_BUFFER(buf); | ||
108 | return err; | 108 | return err; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void finish(void) | 111 | static void finish(void) |
112 | { | 112 | { |
113 | if (!cfg.quiet) { | 113 | if (!(cfg&quiet)) { |
114 | printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent); | 114 | printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent); |
115 | printf("Received %d repl%s", received, (received > 1) ? "ies" : "y"); | 115 | printf("Received %d repl%s", received, (received > 1) ? "ies" : "y"); |
116 | if (brd_recv || req_recv) { | 116 | if (brd_recv || req_recv) { |
@@ -124,9 +124,9 @@ static void finish(void) | |||
124 | putchar('\n'); | 124 | putchar('\n'); |
125 | fflush(stdout); | 125 | fflush(stdout); |
126 | } | 126 | } |
127 | if (cfg.dad) | 127 | if (cfg&dad) |
128 | exit(!!received); | 128 | exit(!!received); |
129 | if (cfg.unsolicited) | 129 | if (cfg&unsolicited) |
130 | exit(0); | 130 | exit(0); |
131 | exit(!received); | 131 | exit(!received); |
132 | } | 132 | } |
@@ -147,7 +147,7 @@ static void catcher(void) | |||
147 | 147 | ||
148 | if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { | 148 | if (last.tv_sec == 0 || MS_TDIFF(tv, last) > 500) { |
149 | send_pack(s, &src, &dst, &me, &he); | 149 | send_pack(s, &src, &dst, &me, &he); |
150 | if (count == 0 && cfg.unsolicited) | 150 | if (count == 0 && cfg&unsolicited) |
151 | finish(); | 151 | finish(); |
152 | } | 152 | } |
153 | alarm(1); | 153 | alarm(1); |
@@ -186,7 +186,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
186 | return 0; | 186 | return 0; |
187 | memcpy(&src_ip, p + ah->ar_hln, 4); | 187 | memcpy(&src_ip, p + ah->ar_hln, 4); |
188 | 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); |
189 | if (!cfg.dad) { | 189 | if (!(cfg&dad)) { |
190 | if (src_ip.s_addr != dst.s_addr) | 190 | if (src_ip.s_addr != dst.s_addr) |
191 | return 0; | 191 | return 0; |
192 | if (src.s_addr != dst_ip.s_addr) | 192 | if (src.s_addr != dst_ip.s_addr) |
@@ -214,7 +214,7 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
214 | if (src.s_addr && src.s_addr != dst_ip.s_addr) | 214 | if (src.s_addr && src.s_addr != dst_ip.s_addr) |
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | if (!cfg.quiet) { | 217 | if (!(cfg&quiet)) { |
218 | int s_printed = 0; | 218 | int s_printed = 0; |
219 | struct timeval tv; | 219 | struct timeval tv; |
220 | 220 | ||
@@ -254,18 +254,17 @@ static int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM) | |||
254 | brd_recv++; | 254 | brd_recv++; |
255 | if (ah->ar_op == htons(ARPOP_REQUEST)) | 255 | if (ah->ar_op == htons(ARPOP_REQUEST)) |
256 | req_recv++; | 256 | req_recv++; |
257 | if (cfg.quit_on_reply) | 257 | if (cfg&quit_on_reply) |
258 | finish(); | 258 | finish(); |
259 | if (!cfg.broadcast_only) { | 259 | if (!(cfg&broadcast_only)) { |
260 | memcpy(he.sll_addr, p, me.sll_halen); | 260 | memcpy(he.sll_addr, p, me.sll_halen); |
261 | cfg.unicasting = 1; | 261 | cfg |= unicasting; |
262 | } | 262 | } |
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
265 | 265 | ||
266 | int arping_main(int argc, char **argv) | 266 | int arping_main(int argc, char **argv) |
267 | { | 267 | { |
268 | int ch; | ||
269 | char *device = "eth0"; | 268 | char *device = "eth0"; |
270 | int ifindex; | 269 | int ifindex; |
271 | char *source = NULL; | 270 | char *source = NULL; |
@@ -276,51 +275,40 @@ int arping_main(int argc, char **argv) | |||
276 | 275 | ||
277 | setuid(getuid()); | 276 | setuid(getuid()); |
278 | 277 | ||
279 | while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:")) != EOF) { | 278 | { |
280 | switch (ch) { | 279 | unsigned long opt; |
281 | case 'b': | 280 | char *_count, *_timeout, *_device; |
282 | cfg.broadcast_only = 1; | 281 | opt = bb_getopt_ulflags(argc, argv, "DUAqfbc:w:i:s:", |
283 | break; | 282 | &_count, &_timeout, &_device); |
284 | case 'D': | 283 | if (opt & 1) { /* Dad */ |
285 | cfg.dad = 1; | 284 | cfg |= dad; |
286 | cfg.quit_on_reply = 1; | 285 | cfg |= quit_on_reply; |
287 | break; | 286 | } |
288 | case 'U': | 287 | if (opt & 2) /* Unsolicited */ |
289 | cfg.unsolicited = 1; | 288 | cfg |= unsolicited; |
290 | break; | 289 | if (opt & 4) { /* Advert */ |
291 | case 'A': | 290 | cfg |= advert; |
292 | cfg.advert = 1; | 291 | cfg |= unsolicited; |
293 | cfg.unsolicited = 1; | 292 | } |
294 | break; | 293 | if (opt & 8) /* quiet */ |
295 | case 'q': | 294 | cfg |= quiet; |
296 | cfg.quiet = 1; | 295 | if (opt & 16) /* quit on reply */ |
297 | break; | 296 | cfg |= quit_on_reply; |
298 | case 'c': | 297 | if (opt & 32) /* broadcast only */ |
299 | count = atoi(optarg); | 298 | cfg |= broadcast_only; |
300 | break; | 299 | if (opt & 64) /* count */ |
301 | case 'w': | 300 | count = atoi(_count); |
302 | timeout = atoi(optarg); | 301 | if (opt & 128) /* timeout */ |
303 | break; | 302 | timeout = atoi(_timeout); |
304 | case 'I': | 303 | if (opt & 256) { /* interface */ |
305 | if (optarg == NULL) | 304 | if (bb_strlen(_device) > IF_NAMESIZE) { |
306 | bb_show_usage(); | ||
307 | if (bb_strlen(optarg) > IF_NAMESIZE) { | ||
308 | bb_error_msg_and_die("Interface name `%s' must be less than %d", | 305 | bb_error_msg_and_die("Interface name `%s' must be less than %d", |
309 | optarg, IF_NAMESIZE); | 306 | _device, IF_NAMESIZE); |
310 | } | 307 | } |
311 | device = optarg; | 308 | device = _device; |
312 | break; | ||
313 | case 'f': | ||
314 | cfg.quit_on_reply = 1; | ||
315 | break; | ||
316 | case 's': | ||
317 | source = optarg; | ||
318 | break; | ||
319 | case 'h': | ||
320 | case '?': | ||
321 | default: | ||
322 | bb_show_usage(); | ||
323 | } | 309 | } |
310 | if (opt & 512) /* source */ | ||
311 | source = optarg; | ||
324 | } | 312 | } |
325 | argc -= optind; | 313 | argc -= optind; |
326 | argv += optind; | 314 | argv += optind; |
@@ -329,12 +317,13 @@ int arping_main(int argc, char **argv) | |||
329 | bb_show_usage(); | 317 | bb_show_usage(); |
330 | 318 | ||
331 | target = *argv; | 319 | target = *argv; |
332 | bb_default_error_retval = 2; | 320 | |
333 | 321 | ||
334 | if (s < 0) { | 322 | if (s < 0) { |
335 | bb_perror_msg("socket"); | 323 | bb_default_error_retval = ifindex; |
336 | exit(ifindex); | 324 | bb_perror_msg_and_die("socket"); |
337 | } | 325 | } |
326 | bb_default_error_retval = 2; | ||
338 | 327 | ||
339 | { | 328 | { |
340 | struct ifreq ifr; | 329 | struct ifreq ifr; |
@@ -354,7 +343,7 @@ int arping_main(int argc, char **argv) | |||
354 | } | 343 | } |
355 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { | 344 | if (ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)) { |
356 | bb_error_msg("Interface %s is not ARPable", device); | 345 | bb_error_msg("Interface %s is not ARPable", device); |
357 | exit(cfg.dad ? 0 : 2); | 346 | exit(cfg&dad ? 0 : 2); |
358 | } | 347 | } |
359 | } | 348 | } |
360 | 349 | ||
@@ -372,10 +361,10 @@ int arping_main(int argc, char **argv) | |||
372 | bb_error_msg_and_die("invalid source address %s", source); | 361 | bb_error_msg_and_die("invalid source address %s", source); |
373 | } | 362 | } |
374 | 363 | ||
375 | if (!cfg.dad && cfg.unsolicited && src.s_addr == 0) | 364 | if (!(cfg&dad) && cfg&unsolicited && src.s_addr == 0) |
376 | src = dst; | 365 | src = dst; |
377 | 366 | ||
378 | if (!cfg.dad || src.s_addr) { | 367 | if (!(cfg&dad) || src.s_addr) { |
379 | struct sockaddr_in saddr; | 368 | struct sockaddr_in saddr; |
380 | int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); | 369 | int probe_fd = socket(AF_INET, SOCK_DGRAM, 0); |
381 | 370 | ||
@@ -395,7 +384,7 @@ int arping_main(int argc, char **argv) | |||
395 | if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { | 384 | if (bind(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { |
396 | bb_error_msg_and_die("bind"); | 385 | bb_error_msg_and_die("bind"); |
397 | } | 386 | } |
398 | } else if (!cfg.dad) { | 387 | } else if (!(cfg&dad)) { |
399 | int on = 1; | 388 | int on = 1; |
400 | socklen_t alen = sizeof(saddr); | 389 | socklen_t alen = sizeof(saddr); |
401 | 390 | ||
@@ -435,18 +424,18 @@ int arping_main(int argc, char **argv) | |||
435 | } | 424 | } |
436 | if (me.sll_halen == 0) { | 425 | if (me.sll_halen == 0) { |
437 | bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device); | 426 | bb_error_msg("Interface \"%s\" is not ARPable (no ll address)", device); |
438 | exit(cfg.dad ? 0 : 2); | 427 | exit(cfg&dad ? 0 : 2); |
439 | } | 428 | } |
440 | he = me; | 429 | he = me; |
441 | memset(he.sll_addr, -1, he.sll_halen); | 430 | memset(he.sll_addr, -1, he.sll_halen); |
442 | 431 | ||
443 | if (!cfg.quiet) { | 432 | if (!(cfg&quiet)) { |
444 | printf("ARPING to %s", inet_ntoa(dst)); | 433 | printf("ARPING to %s", inet_ntoa(dst)); |
445 | printf(" from %s via %s\n", inet_ntoa(src), | 434 | printf(" from %s via %s\n", inet_ntoa(src), |
446 | device ? device : "unknown"); | 435 | device ? device : "unknown"); |
447 | } | 436 | } |
448 | 437 | ||
449 | if (!src.s_addr && !cfg.dad) { | 438 | if (!src.s_addr && !(cfg&dad)) { |
450 | bb_error_msg_and_die("no src address in the non-DAD mode"); | 439 | bb_error_msg_and_die("no src address in the non-DAD mode"); |
451 | } | 440 | } |
452 | 441 | ||