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