blob: 35408c1c0771215192d5fde2455e919f2a5cc5e0 [file] [log] [blame]
Lorenzo Colitti313379e2013-07-11 01:07:11 +09001/*
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>
42struct 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
56static 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
64struct 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
75int quit_on_reply=0;
76struct device device = {
77 .name = DEFAULT_DEVICE,
78};
79char *source;
80struct in_addr src, dst;
81char *target;
82int dad, unsolicited, advert;
83int quiet;
84int count=-1;
85int timeout;
86int unicasting;
87int s;
88int broadcast_only;
89
90struct sockaddr_storage me;
91struct sockaddr_storage he;
92
93struct timeval start, last;
94
95int sent, brd_sent;
96int received, brd_recv, req_recv;
97
98#ifndef CAPABILITIES
99static 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
107static 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
117void 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
141void 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
152static const cap_value_t caps[] = { CAP_NET_RAW, };
153static cap_flag_value_t cap_raw = CAP_CLEAR;
154#endif
155
156void 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
205int 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
236static inline int enable_capability_raw(void)
237{
238 return modify_capability_raw(1);
239}
240
241static inline int disable_capability_raw(void)
242{
243 return modify_capability_raw(0);
244}
245
246void 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
270int 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
313void 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
338void 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
366void 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
376int 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
484union sysfs_devattr_value {
485 unsigned long ulong;
486 void *ptr;
487};
488
489enum {
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
501struct sysfs_devattr_values
502{
503 char *ifname;
504 union sysfs_devattr_value value[SYSFS_DEVATTR_NUM];
505};
506
507static int sysfs_devattr_ulong_dec(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
508static int sysfs_devattr_ulong_hex(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
509static int sysfs_devattr_macaddr(char *ptr, struct sysfs_devattr_values *v, unsigned idx);
510
511struct 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 */
573static 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
594static 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
646static 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
659static 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;
675out:
676 return -1;
677}
678
679static 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
685static 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
691static 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;
712out:
713 free(m);
714 return -1;
715}
716#endif
717
718int 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;
805do_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;
814out:
815 sysfs_close_class(cls_net);
816#endif
817 return rc;
818}
819
820static 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
838static 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;
907out:
908 close(s);
909 return -1;
910}
911
912static 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();
922out:
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 */
932static 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}
961int 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
979static 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
987static 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
996int
997main(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