• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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