1 /*
2 * arping.c
3 *
4 * This program is free software; you can redistribute it and/or
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 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
11 */
12
13 #include <stdlib.h>
14 #include <sys/param.h>
15 #include <sys/socket.h>
16 #include <linux/sockios.h>
17 #include <sys/file.h>
18 #include <sys/time.h>
19 #include <sys/signal.h>
20 #include <sys/ioctl.h>
21 #include <net/if.h>
22 #include <linux/if_packet.h>
23 #include <linux/if_ether.h>
24 #include <net/if_arp.h>
25 #include <sys/uio.h>
26 #ifdef CAPABILITIES
27 #include <sys/prctl.h>
28 #include <sys/capability.h>
29 #endif
30
31 #include <netdb.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39
40 #ifdef USE_SYSFS
41 #include <sysfs/libsysfs.h>
42 struct sysfs_devattr_values;
43 #endif
44
45 #ifndef WITHOUT_IFADDRS
46 #include <ifaddrs.h>
47 #endif
48
49 #ifdef USE_IDN
50 #include <idna.h>
51 #include <locale.h>
52 #endif
53
54 #include "SNAPSHOT.h"
55
56 static void usage(void) __attribute__((noreturn));
57
58 #ifdef DEFAULT_DEVICE
59 # define DEFAULT_DEVICE_STR DEFAULT_DEVICE
60 #else
61 # define DEFAULT_DEVICE NULL
62 #endif
63
64 struct device {
65 char *name;
66 int ifindex;
67 #ifndef WITHOUT_IFADDRS
68 struct ifaddrs *ifa;
69 #endif
70 #ifdef USE_SYSFS
71 struct sysfs_devattr_values *sysfs;
72 #endif
73 };
74
75 int quit_on_reply=0;
76 struct device device = {
77 .name = DEFAULT_DEVICE,
78 };
79 char *source;
80 struct in_addr src, dst;
81 char *target;
82 int dad, unsolicited, advert;
83 int quiet;
84 int count=-1;
85 int timeout;
86 int unicasting;
87 int s;
88 int broadcast_only;
89
90 struct sockaddr_storage me;
91 struct sockaddr_storage he;
92
93 struct timeval start, last;
94
95 int sent, brd_sent;
96 int received, brd_recv, req_recv;
97
98 #ifndef CAPABILITIES
99 static uid_t euid;
100 #endif
101
102 #define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
103 ((tv1).tv_usec-(tv2).tv_usec)/1000 )
104
105 #define OFFSET_OF(name,ele) ((size_t)(((name *)0)->ele))
106
sll_len(size_t halen)107 static inline socklen_t sll_len(size_t halen)
108 {
109 socklen_t len = OFFSET_OF(struct sockaddr_ll, sll_addr) + halen;
110 if (len < sizeof(struct sockaddr_ll))
111 len = sizeof(struct sockaddr_ll);
112 return len;
113 }
114
115 #define SLL_LEN(hln) sll_len(hln)
116
usage(void)117 void usage(void)
118 {
119 fprintf(stderr,
120 "Usage: arping [-fqbDUAV] [-c count] [-w timeout] [-I device] [-s source] destination\n"
121 " -f : quit on first reply\n"
122 " -q : be quiet\n"
123 " -b : keep broadcasting, don't go unicast\n"
124 " -D : duplicate address detection mode\n"
125 " -U : Unsolicited ARP mode, update your neighbours\n"
126 " -A : ARP answer mode, update your neighbours\n"
127 " -V : print version and exit\n"
128 " -c count : how many packets to send\n"
129 " -w timeout : how long to wait for a reply\n"
130 " -I device : which ethernet device to use"
131 #ifdef DEFAULT_DEVICE_STR
132 " (" DEFAULT_DEVICE_STR ")"
133 #endif
134 "\n"
135 " -s source : source ip address\n"
136 " destination : ask for what ip address\n"
137 );
138 exit(2);
139 }
140
set_signal(int signo,void (* handler)(void))141 void set_signal(int signo, void (*handler)(void))
142 {
143 struct sigaction sa;
144
145 memset(&sa, 0, sizeof(sa));
146 sa.sa_handler = (void (*)(int))handler;
147 sa.sa_flags = SA_RESTART;
148 sigaction(signo, &sa, NULL);
149 }
150
151 #ifdef CAPABILITIES
152 static const cap_value_t caps[] = { CAP_NET_RAW, };
153 static cap_flag_value_t cap_raw = CAP_CLEAR;
154 #endif
155
limit_capabilities(void)156 void limit_capabilities(void)
157 {
158 #ifdef CAPABILITIES
159 cap_t cap_p;
160
161 cap_p = cap_get_proc();
162 if (!cap_p) {
163 perror("arping: cap_get_proc");
164 exit(-1);
165 }
166
167 cap_get_flag(cap_p, CAP_NET_RAW, CAP_PERMITTED, &cap_raw);
168
169 if (cap_raw != CAP_CLEAR) {
170 if (cap_clear(cap_p) < 0) {
171 perror("arping: cap_clear");
172 exit(-1);
173 }
174
175 cap_set_flag(cap_p, CAP_PERMITTED, 1, caps, CAP_SET);
176
177 if (cap_set_proc(cap_p) < 0) {
178 perror("arping: cap_set_proc");
179 if (errno != EPERM)
180 exit(-1);
181 }
182 }
183
184 if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
185 perror("arping: prctl");
186 exit(-1);
187 }
188
189 if (setuid(getuid()) < 0) {
190 perror("arping: setuid");
191 exit(-1);
192 }
193
194 if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
195 perror("arping: prctl");
196 exit(-1);
197 }
198
199 cap_free(cap_p);
200 #else
201 euid = geteuid();
202 #endif
203 }
204
modify_capability_raw(int on)205 int modify_capability_raw(int on)
206 {
207 #ifdef CAPABILITIES
208 cap_t cap_p;
209
210 if (cap_raw != CAP_SET)
211 return on ? -1 : 0;
212
213 cap_p = cap_get_proc();
214 if (!cap_p) {
215 perror("arping: cap_get_proc");
216 return -1;
217 }
218
219 cap_set_flag(cap_p, CAP_EFFECTIVE, 1, caps, on ? CAP_SET : CAP_CLEAR);
220
221 if (cap_set_proc(cap_p) < 0) {
222 perror("arping: cap_set_proc");
223 return -1;
224 }
225
226 cap_free(cap_p);
227 #else
228 if (setuid(on ? euid : getuid())) {
229 perror("arping: setuid");
230 return -1;
231 }
232 #endif
233 return 0;
234 }
235
enable_capability_raw(void)236 static inline int enable_capability_raw(void)
237 {
238 return modify_capability_raw(1);
239 }
240
disable_capability_raw(void)241 static inline int disable_capability_raw(void)
242 {
243 return modify_capability_raw(0);
244 }
245
drop_capabilities(void)246 void drop_capabilities(void)
247 {
248 #ifdef CAPABILITIES
249 cap_t cap_p = cap_init();
250
251 if (!cap_p) {
252 perror("arping: cap_init");
253 exit(-1);
254 }
255
256 if (cap_set_proc(cap_p) < 0) {
257 perror("arping: cap_set_proc");
258 exit(-1);
259 }
260
261 cap_free(cap_p);
262 #else
263 if (setuid(getuid()) < 0) {
264 perror("arping: setuid");
265 exit(-1);
266 }
267 #endif
268 }
269
send_pack(int s,struct in_addr src,struct in_addr dst,struct sockaddr_ll * ME,struct sockaddr_ll * HE)270 int send_pack(int s, struct in_addr src, struct in_addr dst,
271 struct sockaddr_ll *ME, struct sockaddr_ll *HE)
272 {
273 int err;
274 struct timeval now;
275 unsigned char buf[256];
276 struct arphdr *ah = (struct arphdr*)buf;
277 unsigned char *p = (unsigned char *)(ah+1);
278
279 ah->ar_hrd = htons(ME->sll_hatype);
280 if (ah->ar_hrd == htons(ARPHRD_FDDI))
281 ah->ar_hrd = htons(ARPHRD_ETHER);
282 ah->ar_pro = htons(ETH_P_IP);
283 ah->ar_hln = ME->sll_halen;
284 ah->ar_pln = 4;
285 ah->ar_op = advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST);
286
287 memcpy(p, &ME->sll_addr, ah->ar_hln);
288 p+=ME->sll_halen;
289
290 memcpy(p, &src, 4);
291 p+=4;
292
293 if (advert)
294 memcpy(p, &ME->sll_addr, ah->ar_hln);
295 else
296 memcpy(p, &HE->sll_addr, ah->ar_hln);
297 p+=ah->ar_hln;
298
299 memcpy(p, &dst, 4);
300 p+=4;
301
302 gettimeofday(&now, NULL);
303 err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, SLL_LEN(ah->ar_hln));
304 if (err == p-buf) {
305 last = now;
306 sent++;
307 if (!unicasting)
308 brd_sent++;
309 }
310 return err;
311 }
312
finish(void)313 void finish(void)
314 {
315 if (!quiet) {
316 printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
317 printf("Received %d response(s)", received);
318 if (brd_recv || req_recv) {
319 printf(" (");
320 if (req_recv)
321 printf("%d request(s)", req_recv);
322 if (brd_recv)
323 printf("%s%d broadcast(s)",
324 req_recv ? ", " : "",
325 brd_recv);
326 printf(")");
327 }
328 printf("\n");
329 fflush(stdout);
330 }
331 if (dad)
332 exit(!!received);
333 if (unsolicited)
334 exit(0);
335 exit(!received);
336 }
337
catcher(void)338 void catcher(void)
339 {
340 struct timeval tv, tv_s, tv_o;
341
342 gettimeofday(&tv, NULL);
343
344 if (start.tv_sec==0)
345 start = tv;
346
347 timersub(&tv, &start, &tv_s);
348 tv_o.tv_sec = timeout;
349 tv_o.tv_usec = 500 * 1000;
350
351 if (count-- == 0 || (timeout && timercmp(&tv_s, &tv_o, >)))
352 finish();
353
354 timersub(&tv, &last, &tv_s);
355 tv_o.tv_sec = 0;
356
357 if (last.tv_sec==0 || timercmp(&tv_s, &tv_o, >)) {
358 send_pack(s, src, dst,
359 (struct sockaddr_ll *)&me, (struct sockaddr_ll *)&he);
360 if (count == 0 && unsolicited)
361 finish();
362 }
363 alarm(1);
364 }
365
print_hex(unsigned char * p,int len)366 void print_hex(unsigned char *p, int len)
367 {
368 int i;
369 for (i=0; i<len; i++) {
370 printf("%02X", p[i]);
371 if (i != len-1)
372 printf(":");
373 }
374 }
375
recv_pack(unsigned char * buf,int len,struct sockaddr_ll * FROM)376 int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
377 {
378 struct timeval tv;
379 struct arphdr *ah = (struct arphdr*)buf;
380 unsigned char *p = (unsigned char *)(ah+1);
381 struct in_addr src_ip, dst_ip;
382
383 gettimeofday(&tv, NULL);
384
385 /* Filter out wild packets */
386 if (FROM->sll_pkttype != PACKET_HOST &&
387 FROM->sll_pkttype != PACKET_BROADCAST &&
388 FROM->sll_pkttype != PACKET_MULTICAST)
389 return 0;
390
391 /* Only these types are recognised */
392 if (ah->ar_op != htons(ARPOP_REQUEST) &&
393 ah->ar_op != htons(ARPOP_REPLY))
394 return 0;
395
396 /* ARPHRD check and this darned FDDI hack here :-( */
397 if (ah->ar_hrd != htons(FROM->sll_hatype) &&
398 (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER)))
399 return 0;
400
401 /* Protocol must be IP. */
402 if (ah->ar_pro != htons(ETH_P_IP))
403 return 0;
404 if (ah->ar_pln != 4)
405 return 0;
406 if (ah->ar_hln != ((struct sockaddr_ll *)&me)->sll_halen)
407 return 0;
408 if (len < sizeof(*ah) + 2*(4 + ah->ar_hln))
409 return 0;
410 memcpy(&src_ip, p+ah->ar_hln, 4);
411 memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4);
412 if (!dad) {
413 if (src_ip.s_addr != dst.s_addr)
414 return 0;
415 if (src.s_addr != dst_ip.s_addr)
416 return 0;
417 if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln))
418 return 0;
419 } else {
420 /* DAD packet was:
421 src_ip = 0 (or some src)
422 src_hw = ME
423 dst_ip = tested address
424 dst_hw = <unspec>
425
426 We fail, if receive request/reply with:
427 src_ip = tested_address
428 src_hw != ME
429 if src_ip in request was not zero, check
430 also that it matches to dst_ip, otherwise
431 dst_ip/dst_hw do not matter.
432 */
433 if (src_ip.s_addr != dst.s_addr)
434 return 0;
435 if (memcmp(p, ((struct sockaddr_ll *)&me)->sll_addr, ((struct sockaddr_ll *)&me)->sll_halen) == 0)
436 return 0;
437 if (src.s_addr && src.s_addr != dst_ip.s_addr)
438 return 0;
439 }
440 if (!quiet) {
441 int s_printed = 0;
442 printf("%s ", FROM->sll_pkttype==PACKET_HOST ? "Unicast" : "Broadcast");
443 printf("%s from ", ah->ar_op == htons(ARPOP_REPLY) ? "reply" : "request");
444 printf("%s [", inet_ntoa(src_ip));
445 print_hex(p, ah->ar_hln);
446 printf("] ");
447 if (dst_ip.s_addr != src.s_addr) {
448 printf("for %s ", inet_ntoa(dst_ip));
449 s_printed = 1;
450 }
451 if (memcmp(p+ah->ar_hln+4, ((struct sockaddr_ll *)&me)->sll_addr, ah->ar_hln)) {
452 if (!s_printed)
453 printf("for ");
454 printf("[");
455 print_hex(p+ah->ar_hln+4, ah->ar_hln);
456 printf("]");
457 }
458 if (last.tv_sec) {
459 long usecs = (tv.tv_sec-last.tv_sec) * 1000000 +
460 tv.tv_usec-last.tv_usec;
461 long msecs = (usecs+500)/1000;
462 usecs -= msecs*1000 - 500;
463 printf(" %ld.%03ldms\n", msecs, usecs);
464 } else {
465 printf(" UNSOLICITED?\n");
466 }
467 fflush(stdout);
468 }
469 received++;
470 if (FROM->sll_pkttype != PACKET_HOST)
471 brd_recv++;
472 if (ah->ar_op == htons(ARPOP_REQUEST))
473 req_recv++;
474 if (quit_on_reply)
475 finish();
476 if(!broadcast_only) {
477 memcpy(((struct sockaddr_ll *)&he)->sll_addr, p, ((struct sockaddr_ll *)&me)->sll_halen);
478 unicasting=1;
479 }
480 return 1;
481 }
482
483 #ifdef USE_SYSFS
484 union sysfs_devattr_value {
485 unsigned long ulong;
486 void *ptr;
487 };
488
489 enum {
490 SYSFS_DEVATTR_IFINDEX,
491 SYSFS_DEVATTR_FLAGS,
492 SYSFS_DEVATTR_ADDR_LEN,
493 #if 0
494 SYSFS_DEVATTR_TYPE,
495 SYSFS_DEVATTR_ADDRESS,
496 #endif
497 SYSFS_DEVATTR_BROADCAST,
498 SYSFS_DEVATTR_NUM
499 };
500
501 struct sysfs_devattr_values
502 {
503 char *ifname;
504 union sysfs_devattr_value value[SYSFS_DEVATTR_NUM];
505 };
506
507 static int sysfs_devattr_ulong_dec(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
508 static int sysfs_devattr_ulong_hex(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
509 static int sysfs_devattr_macaddr(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
510
511 struct sysfs_devattrs {
512 const char *name;
513 int (*handler)(char *ptr, struct sysfs_devattr_values *v, unsigned int idx);
514 int free;
515 } sysfs_devattrs[SYSFS_DEVATTR_NUM] = {
516 [SYSFS_DEVATTR_IFINDEX] = {
517 .name = "ifindex",
518 .handler = sysfs_devattr_ulong_dec,
519 },
520 [SYSFS_DEVATTR_ADDR_LEN] = {
521 .name = "addr_len",
522 .handler = sysfs_devattr_ulong_dec,
523 },
524 [SYSFS_DEVATTR_FLAGS] = {
525 .name = "flags",
526 .handler = sysfs_devattr_ulong_hex,
527 },
528 #if 0
529 [SYSFS_DEVATTR_TYPE] = {
530 .name = "type",
531 .handler = sysfs_devattr_ulong_dec,
532 },
533 [SYSFS_DEVATTR_ADDRESS] = {
534 .name = "address",
535 .handler = sysfs_devattr_macaddr,
536 .free = 1,
537 },
538 #endif
539 [SYSFS_DEVATTR_BROADCAST] = {
540 .name = "broadcast",
541 .handler = sysfs_devattr_macaddr,
542 .free = 1,
543 },
544 };
545 #endif
546
547 /*
548 * find_device()
549 *
550 * This function checks 1) if the device (if given) is okay for ARP,
551 * or 2) find fist appropriate device on the system.
552 *
553 * Return value:
554 * >0 : Succeeded, and appropriate device not found.
555 * device.ifindex remains 0.
556 * 0 : Succeeded, and approptiate device found.
557 * device.ifindex is set.
558 * <0 : Failed. Support not found, or other
559 * : system error. Try other method.
560 *
561 * If an appropriate device found, it is recorded inside the
562 * "device" variable for later reference.
563 *
564 * We have several implementations for this.
565 * by_ifaddrs(): requires getifaddr() in glibc, and rtnetlink in
566 * kernel. default and recommended for recent systems.
567 * by_sysfs(): requires libsysfs , and sysfs in kernel.
568 * by_ioctl(): unable to list devices without ipv4 address; this
569 * means, you need to supply the device name for
570 * DAD purpose.
571 */
572 /* Common check for ifa->ifa_flags */
check_ifflags(unsigned int ifflags,int fatal)573 static int check_ifflags(unsigned int ifflags, int fatal)
574 {
575 if (!(ifflags & IFF_UP)) {
576 if (fatal) {
577 if (!quiet)
578 printf("Interface \"%s\" is down\n", device.name);
579 exit(2);
580 }
581 return -1;
582 }
583 if (ifflags & (IFF_NOARP | IFF_LOOPBACK)) {
584 if (fatal) {
585 if (!quiet)
586 printf("Interface \"%s\" is not ARPable\n", device.name);
587 exit(dad ? 0 : 2);
588 }
589 return -1;
590 }
591 return 0;
592 }
593
find_device_by_ifaddrs(void)594 static int find_device_by_ifaddrs(void)
595 {
596 #ifndef WITHOUT_IFADDRS
597 int rc;
598 struct ifaddrs *ifa0, *ifa;
599 int count = 0;
600
601 rc = getifaddrs(&ifa0);
602 if (rc) {
603 perror("getifaddrs");
604 return -1;
605 }
606
607 for (ifa = ifa0; ifa; ifa = ifa->ifa_next) {
608 if (!ifa->ifa_addr)
609 continue;
610 if (ifa->ifa_addr->sa_family != AF_PACKET)
611 continue;
612 if (device.name && ifa->ifa_name && strcmp(ifa->ifa_name, device.name))
613 continue;
614
615 if (check_ifflags(ifa->ifa_flags, device.name != NULL) < 0)
616 continue;
617
618 if (!((struct sockaddr_ll *)ifa->ifa_addr)->sll_halen)
619 continue;
620 if (!ifa->ifa_broadaddr)
621 continue;
622
623 device.ifa = ifa;
624
625 if (count++)
626 break;
627 }
628
629 if (count == 1 && device.ifa) {
630 device.ifindex = if_nametoindex(device.ifa->ifa_name);
631 if (!device.ifindex) {
632 perror("arping: if_nametoindex");
633 freeifaddrs(ifa0);
634 return -1;
635 }
636 device.name = device.ifa->ifa_name;
637 return 0;
638 }
639 return 1;
640 #else
641 return -1;
642 #endif
643 }
644
645 #ifdef USE_SYSFS
sysfs_devattr_values_init(struct sysfs_devattr_values * v,int do_free)646 static void sysfs_devattr_values_init(struct sysfs_devattr_values *v, int do_free)
647 {
648 int i;
649 if (do_free) {
650 free(v->ifname);
651 for (i = 0; i < SYSFS_DEVATTR_NUM; i++) {
652 if (sysfs_devattrs[i].free)
653 free(v->value[i].ptr);
654 }
655 }
656 memset(v, 0, sizeof(*v));
657 }
658
sysfs_devattr_ulong(char * ptr,struct sysfs_devattr_values * v,unsigned int idx,unsigned int base)659 static int sysfs_devattr_ulong(char *ptr, struct sysfs_devattr_values *v, unsigned int idx,
660 unsigned int base)
661 {
662 unsigned long *p;
663 char *ep;
664
665 if (!ptr || !v)
666 return -1;
667
668 p = &v->value[idx].ulong;
669 errno = 0;
670 *p = strtoul(ptr, &ep, base);
671 if ((*ptr && isspace(*ptr & 0xff)) || errno || (*ep != '\0' && *ep != '\n'))
672 goto out;
673
674 return 0;
675 out:
676 return -1;
677 }
678
sysfs_devattr_ulong_dec(char * ptr,struct sysfs_devattr_values * v,unsigned int idx)679 static int sysfs_devattr_ulong_dec(char *ptr, struct sysfs_devattr_values *v, unsigned int idx)
680 {
681 int rc = sysfs_devattr_ulong(ptr, v, idx, 10);
682 return rc;
683 }
684
sysfs_devattr_ulong_hex(char * ptr,struct sysfs_devattr_values * v,unsigned int idx)685 static int sysfs_devattr_ulong_hex(char *ptr, struct sysfs_devattr_values *v, unsigned int idx)
686 {
687 int rc = sysfs_devattr_ulong(ptr, v, idx, 16);
688 return rc;
689 }
690
sysfs_devattr_macaddr(char * ptr,struct sysfs_devattr_values * v,unsigned int idx)691 static int sysfs_devattr_macaddr(char *ptr, struct sysfs_devattr_values *v, unsigned int idx)
692 {
693 unsigned char *m;
694 int i;
695 unsigned int addrlen;
696
697 if (!ptr || !v)
698 return -1;
699
700 addrlen = v->value[SYSFS_DEVATTR_ADDR_LEN].ulong;
701 m = malloc(addrlen);
702
703 for (i = 0; i < addrlen; i++) {
704 if (i && *(ptr + i * 3 - 1) != ':')
705 goto out;
706 if (sscanf(ptr + i * 3, "%02hhx", &m[i]) != 1)
707 goto out;
708 }
709
710 v->value[idx].ptr = m;
711 return 0;
712 out:
713 free(m);
714 return -1;
715 }
716 #endif
717
find_device_by_sysfs(void)718 int find_device_by_sysfs(void)
719 {
720 int rc = -1;
721 #ifdef USE_SYSFS
722 struct sysfs_class *cls_net;
723 struct dlist *dev_list;
724 struct sysfs_class_device *dev;
725 struct sysfs_attribute *dev_attr;
726 struct sysfs_devattr_values sysfs_devattr_values;
727 int count = 0;
728
729 if (!device.sysfs) {
730 device.sysfs = malloc(sizeof(*device.sysfs));
731 sysfs_devattr_values_init(device.sysfs, 0);
732 }
733
734 cls_net = sysfs_open_class("net");
735 if (!cls_net) {
736 perror("sysfs_open_class");
737 return -1;
738 }
739
740 dev_list = sysfs_get_class_devices(cls_net);
741 if (!dev_list) {
742 perror("sysfs_get_class_devices");
743 goto out;
744 }
745
746 sysfs_devattr_values_init(&sysfs_devattr_values, 0);
747
748 dlist_for_each_data(dev_list, dev, struct sysfs_class_device) {
749 int i;
750 int rc = -1;
751
752 if (device.name && strcmp(dev->name, device.name))
753 goto do_next;
754
755 sysfs_devattr_values_init(&sysfs_devattr_values, 1);
756
757 for (i = 0; i < SYSFS_DEVATTR_NUM; i++) {
758
759 dev_attr = sysfs_get_classdev_attr(dev, sysfs_devattrs[i].name);
760 if (!dev_attr) {
761 perror("sysfs_get_classdev_attr");
762 rc = -1;
763 break;
764 }
765 if (sysfs_read_attribute(dev_attr)) {
766 perror("sysfs_read_attribute");
767 rc = -1;
768 break;
769 }
770 rc = sysfs_devattrs[i].handler(dev_attr->value, &sysfs_devattr_values, i);
771
772 if (rc < 0)
773 break;
774 }
775
776 if (rc < 0)
777 goto do_next;
778
779 if (check_ifflags(sysfs_devattr_values.value[SYSFS_DEVATTR_FLAGS].ulong,
780 device.name != NULL) < 0)
781 goto do_next;
782
783 if (!sysfs_devattr_values.value[SYSFS_DEVATTR_ADDR_LEN].ulong)
784 goto do_next;
785
786 if (device.sysfs->value[SYSFS_DEVATTR_IFINDEX].ulong) {
787 if (device.sysfs->value[SYSFS_DEVATTR_FLAGS].ulong & IFF_RUNNING)
788 goto do_next;
789 }
790
791 sysfs_devattr_values.ifname = strdup(dev->name);
792 if (!sysfs_devattr_values.ifname) {
793 perror("malloc");
794 goto out;
795 }
796
797 sysfs_devattr_values_init(device.sysfs, 1);
798 memcpy(device.sysfs, &sysfs_devattr_values, sizeof(*device.sysfs));
799 sysfs_devattr_values_init(&sysfs_devattr_values, 0);
800
801 if (count++)
802 break;
803
804 continue;
805 do_next:
806 sysfs_devattr_values_init(&sysfs_devattr_values, 1);
807 }
808
809 if (count == 1) {
810 device.ifindex = device.sysfs->value[SYSFS_DEVATTR_IFINDEX].ulong;
811 device.name = device.sysfs->ifname;
812 }
813 rc = !device.ifindex;
814 out:
815 sysfs_close_class(cls_net);
816 #endif
817 return rc;
818 }
819
check_device_by_ioctl(int s,struct ifreq * ifr)820 static int check_device_by_ioctl(int s, struct ifreq *ifr)
821 {
822 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
823 perror("ioctl(SIOCGIFINDEX");
824 return -1;
825 }
826
827 if (check_ifflags(ifr->ifr_flags, device.name != NULL) < 0)
828 return 1;
829
830 if (ioctl(s, SIOCGIFINDEX, ifr) < 0) {
831 perror("ioctl(SIOCGIFINDEX");
832 return -1;
833 }
834
835 return 0;
836 }
837
find_device_by_ioctl(void)838 static int find_device_by_ioctl(void)
839 {
840 int s;
841 struct ifreq *ifr0, *ifr, *ifr_end;
842 size_t ifrsize = sizeof(*ifr);
843 struct ifconf ifc;
844 static struct ifreq ifrbuf;
845 int count = 0;
846
847 s = socket(AF_INET, SOCK_DGRAM, 0);
848 if (s < 0) {
849 perror("socket");
850 return -1;
851 }
852
853 memset(&ifrbuf, 0, sizeof(ifrbuf));
854
855 if (device.name) {
856 strncpy(ifrbuf.ifr_name, device.name, sizeof(ifrbuf.ifr_name) - 1);
857 if (check_device_by_ioctl(s, &ifrbuf))
858 goto out;
859 count++;
860 } else {
861 do {
862 int rc;
863 ifr0 = malloc(ifrsize);
864 if (!ifr0) {
865 perror("malloc");
866 goto out;
867 }
868
869 ifc.ifc_buf = (char *)ifr0;
870 ifc.ifc_len = ifrsize;
871
872 rc = ioctl(s, SIOCGIFCONF, &ifc);
873 if (rc < 0) {
874 perror("ioctl(SIOCFIFCONF");
875 goto out;
876 }
877
878 if (ifc.ifc_len + sizeof(*ifr0) + sizeof(struct sockaddr_storage) - sizeof(struct sockaddr) <= ifrsize)
879 break;
880 ifrsize *= 2;
881 free(ifr0);
882 ifr0 = NULL;
883 } while(ifrsize < INT_MAX / 2);
884
885 if (!ifr0) {
886 fprintf(stderr, "arping: too many interfaces!?\n");
887 goto out;
888 }
889
890 ifr_end = (struct ifreq *)(((char *)ifr0) + ifc.ifc_len - sizeof(*ifr0));
891 for (ifr = ifr0; ifr <= ifr_end; ifr++) {
892 if (check_device_by_ioctl(s, &ifrbuf))
893 continue;
894 memcpy(&ifrbuf.ifr_name, ifr->ifr_name, sizeof(ifrbuf.ifr_name));
895 if (count++)
896 break;
897 }
898 }
899
900 close(s);
901
902 if (count == 1) {
903 device.ifindex = ifrbuf.ifr_ifindex;
904 device.name = ifrbuf.ifr_name;
905 }
906 return !device.ifindex;
907 out:
908 close(s);
909 return -1;
910 }
911
find_device(void)912 static int find_device(void)
913 {
914 int rc;
915 rc = find_device_by_ifaddrs();
916 if (rc >= 0)
917 goto out;
918 rc = find_device_by_sysfs();
919 if (rc >= 0)
920 goto out;
921 rc = find_device_by_ioctl();
922 out:
923 return rc;
924 }
925
926 /*
927 * set_device_broadcast()
928 *
929 * This fills the device "broadcast address"
930 * based on information found by find_device() funcion.
931 */
set_device_broadcast_ifaddrs_one(struct device * device,unsigned char * ba,size_t balen,int fatal)932 static int set_device_broadcast_ifaddrs_one(struct device *device, unsigned char *ba, size_t balen, int fatal)
933 {
934 #ifndef WITHOUT_IFADDRS
935 struct ifaddrs *ifa;
936 struct sockaddr_ll *sll;
937
938 if (!device)
939 return -1;
940
941 ifa = device->ifa;
942 if (!ifa)
943 return -1;
944
945 sll = (struct sockaddr_ll *)ifa->ifa_broadaddr;
946
947 if (sll->sll_halen != balen) {
948 if (fatal) {
949 if (!quiet)
950 printf("Address length does not match...\n");
951 exit(2);
952 }
953 return -1;
954 }
955 memcpy(ba, sll->sll_addr, sll->sll_halen);
956 return 0;
957 #else
958 return -1;
959 #endif
960 }
set_device_broadcast_sysfs(struct device * device,unsigned char * ba,size_t balen)961 int set_device_broadcast_sysfs(struct device *device, unsigned char *ba, size_t balen)
962 {
963 #ifdef USE_SYSFS
964 struct sysfs_devattr_values *v;
965 if (!device)
966 return -1;
967 v = device->sysfs;
968 if (!v)
969 return -1;
970 if (v->value[SYSFS_DEVATTR_ADDR_LEN].ulong != balen)
971 return -1;
972 memcpy(ba, v->value[SYSFS_DEVATTR_BROADCAST].ptr, balen);
973 return 0;
974 #else
975 return -1;
976 #endif
977 }
978
set_device_broadcast_fallback(struct device * device,unsigned char * ba,size_t balen)979 static int set_device_broadcast_fallback(struct device *device, unsigned char *ba, size_t balen)
980 {
981 if (!quiet)
982 fprintf(stderr, "WARNING: using default broadcast address.\n");
983 memset(ba, -1, balen);
984 return 0;
985 }
986
set_device_broadcast(struct device * dev,unsigned char * ba,size_t balen)987 static void set_device_broadcast(struct device *dev, unsigned char *ba, size_t balen)
988 {
989 if (!set_device_broadcast_ifaddrs_one(dev, ba, balen, 0))
990 return;
991 if (!set_device_broadcast_sysfs(dev, ba, balen))
992 return;
993 set_device_broadcast_fallback(dev, ba, balen);
994 }
995
996 int
main(int argc,char ** argv)997 main(int argc, char **argv)
998 {
999 int socket_errno;
1000 int ch;
1001
1002 limit_capabilities();
1003
1004 #ifdef USE_IDN
1005 setlocale(LC_ALL, "");
1006 #endif
1007
1008 enable_capability_raw();
1009
1010 s = socket(PF_PACKET, SOCK_DGRAM, 0);
1011 socket_errno = errno;
1012
1013 disable_capability_raw();
1014
1015 while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
1016 switch(ch) {
1017 case 'b':
1018 broadcast_only=1;
1019 break;
1020 case 'D':
1021 dad++;
1022 quit_on_reply=1;
1023 break;
1024 case 'U':
1025 unsolicited++;
1026 break;
1027 case 'A':
1028 advert++;
1029 unsolicited++;
1030 break;
1031 case 'q':
1032 quiet++;
1033 break;
1034 case 'c':
1035 count = atoi(optarg);
1036 break;
1037 case 'w':
1038 timeout = atoi(optarg);
1039 break;
1040 case 'I':
1041 device.name = optarg;
1042 break;
1043 case 'f':
1044 quit_on_reply=1;
1045 break;
1046 case 's':
1047 source = optarg;
1048 break;
1049 case 'V':
1050 printf("arping utility, iputils-%s\n", SNAPSHOT);
1051 exit(0);
1052 case 'h':
1053 case '?':
1054 default:
1055 usage();
1056 }
1057 }
1058 argc -= optind;
1059 argv += optind;
1060
1061 if (argc != 1)
1062 usage();
1063
1064 target = *argv;
1065
1066 if (device.name && !*device.name)
1067 device.name = NULL;
1068
1069 if (s < 0) {
1070 errno = socket_errno;
1071 perror("arping: socket");
1072 exit(2);
1073 }
1074
1075 if (find_device() < 0)
1076 exit(2);
1077
1078 if (!device.ifindex) {
1079 if (device.name) {
1080 fprintf(stderr, "arping: Device %s not available.\n", device.name);
1081 exit(2);
1082 }
1083 fprintf(stderr, "arping: device (option -I) is required.\n");
1084 usage();
1085 }
1086
1087 if (inet_aton(target, &dst) != 1) {
1088 struct hostent *hp;
1089 char *idn = target;
1090 #ifdef USE_IDN
1091 int rc;
1092
1093 rc = idna_to_ascii_lz(target, &idn, 0);
1094
1095 if (rc != IDNA_SUCCESS) {
1096 fprintf(stderr, "arping: IDN encoding failed: %s\n", idna_strerror(rc));
1097 exit(2);
1098 }
1099 #endif
1100
1101 hp = gethostbyname2(idn, AF_INET);
1102 if (!hp) {
1103 fprintf(stderr, "arping: unknown host %s\n", target);
1104 exit(2);
1105 }
1106
1107 #ifdef USE_IDN
1108 free(idn);
1109 #endif
1110
1111 memcpy(&dst, hp->h_addr, 4);
1112 }
1113
1114 if (source && inet_aton(source, &src) != 1) {
1115 fprintf(stderr, "arping: invalid source %s\n", source);
1116 exit(2);
1117 }
1118
1119 if (!dad && unsolicited && src.s_addr == 0)
1120 src = dst;
1121
1122 if (!dad || src.s_addr) {
1123 struct sockaddr_in saddr;
1124 int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
1125
1126 if (probe_fd < 0) {
1127 perror("socket");
1128 exit(2);
1129 }
1130 if (device.name) {
1131 enable_capability_raw();
1132
1133 if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device.name, strlen(device.name)+1) == -1)
1134 perror("WARNING: interface is ignored");
1135
1136 disable_capability_raw();
1137 }
1138 memset(&saddr, 0, sizeof(saddr));
1139 saddr.sin_family = AF_INET;
1140 if (src.s_addr) {
1141 saddr.sin_addr = src;
1142 if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
1143 perror("bind");
1144 exit(2);
1145 }
1146 } else if (!dad) {
1147 int on = 1;
1148 socklen_t alen = sizeof(saddr);
1149
1150 saddr.sin_port = htons(1025);
1151 saddr.sin_addr = dst;
1152
1153 if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1)
1154 perror("WARNING: setsockopt(SO_DONTROUTE)");
1155 if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
1156 perror("connect");
1157 exit(2);
1158 }
1159 if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
1160 perror("getsockname");
1161 exit(2);
1162 }
1163 src = saddr.sin_addr;
1164 }
1165 close(probe_fd);
1166 };
1167
1168 ((struct sockaddr_ll *)&me)->sll_family = AF_PACKET;
1169 ((struct sockaddr_ll *)&me)->sll_ifindex = device.ifindex;
1170 ((struct sockaddr_ll *)&me)->sll_protocol = htons(ETH_P_ARP);
1171 if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
1172 perror("bind");
1173 exit(2);
1174 }
1175
1176 if (1) {
1177 socklen_t alen = sizeof(me);
1178 if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
1179 perror("getsockname");
1180 exit(2);
1181 }
1182 }
1183 if (((struct sockaddr_ll *)&me)->sll_halen == 0) {
1184 if (!quiet)
1185 printf("Interface \"%s\" is not ARPable (no ll address)\n", device.name);
1186 exit(dad?0:2);
1187 }
1188
1189 he = me;
1190
1191 set_device_broadcast(&device, ((struct sockaddr_ll *)&he)->sll_addr,
1192 ((struct sockaddr_ll *)&he)->sll_halen);
1193
1194 if (!quiet) {
1195 printf("ARPING %s ", inet_ntoa(dst));
1196 printf("from %s %s\n", inet_ntoa(src), device.name ? : "");
1197 }
1198
1199 if (!src.s_addr && !dad) {
1200 fprintf(stderr, "arping: no source address in not-DAD mode\n");
1201 exit(2);
1202 }
1203
1204 drop_capabilities();
1205
1206 set_signal(SIGINT, finish);
1207 set_signal(SIGALRM, catcher);
1208
1209 catcher();
1210
1211 while(1) {
1212 sigset_t sset, osset;
1213 unsigned char packet[4096];
1214 struct sockaddr_storage from;
1215 socklen_t alen = sizeof(from);
1216 int cc;
1217
1218 if ((cc = recvfrom(s, packet, sizeof(packet), 0,
1219 (struct sockaddr *)&from, &alen)) < 0) {
1220 perror("arping: recvfrom");
1221 continue;
1222 }
1223
1224 sigemptyset(&sset);
1225 sigaddset(&sset, SIGALRM);
1226 sigaddset(&sset, SIGINT);
1227 sigprocmask(SIG_BLOCK, &sset, &osset);
1228 recv_pack(packet, cc, (struct sockaddr_ll *)&from);
1229 sigprocmask(SIG_SETMASK, &osset, NULL);
1230 }
1231 }
1232
1233
1234