Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 144526
Collapse All | Expand All

(-)arping.c (-126 / +113 lines)
Lines 7-15 Link Here
7
 *		2 of the License, or (at your option) any later version.
7
 *		2 of the License, or (at your option) any later version.
8
 *
8
 *
9
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9
 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10
 *		2006.08.18	erik quanstrom <quanstro@quanstro.net>
11
 *				use select instead of signals so timeouts will work.
12
 *				
13
 */
10
 */
14
11
15
#include <stdlib.h>
12
#include <stdlib.h>
Lines 18-23 Link Here
18
#include <linux/sockios.h>
15
#include <linux/sockios.h>
19
#include <sys/file.h>
16
#include <sys/file.h>
20
#include <sys/time.h>
17
#include <sys/time.h>
18
#include <sys/signal.h>
21
#include <sys/ioctl.h>
19
#include <sys/ioctl.h>
22
#include <linux/if.h>
20
#include <linux/if.h>
23
#include <linux/if_arp.h>
21
#include <linux/if_arp.h>
Lines 31-42 Link Here
31
#include <string.h>
29
#include <string.h>
32
#include <netinet/in.h>
30
#include <netinet/in.h>
33
#include <arpa/inet.h>
31
#include <arpa/inet.h>
34
#include <stdarg.h>
35
32
36
#include "SNAPSHOT.h"
33
#include "SNAPSHOT.h"
37
34
38
static void usage(void) __attribute__((noreturn));
35
static void usage(void) __attribute__((noreturn));
39
36
37
int quit_on_reply=0;
40
char *device="eth0";
38
char *device="eth0";
41
int ifindex;
39
int ifindex;
42
char *source;
40
char *source;
Lines 45-54 Link Here
45
int dad, unsolicited, advert;
43
int dad, unsolicited, advert;
46
int quiet;
44
int quiet;
47
int count=-1;
45
int count=-1;
48
int ntosend=-1;
49
int ntorecv=-1;
50
int timeout;
46
int timeout;
51
struct timeval timeouttv;
52
int unicasting;
47
int unicasting;
53
int s;
48
int s;
54
int broadcast_only;
49
int broadcast_only;
Lines 64-82 Link Here
64
#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
59
#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + \
65
			   ((tv1).tv_usec-(tv2).tv_usec)/1000 )
60
			   ((tv1).tv_usec-(tv2).tv_usec)/1000 )
66
61
67
#define pkttrace(...)	/* fprintf(stderr, __VA_ARGS__) */
68
69
void
70
errexit(int err, const char* fmt, ...)
71
{
72
	va_list ap;
73
74
	va_start(ap, fmt);
75
	vfprintf(stderr, fmt, ap);
76
	va_end(ap);
77
	exit(err);
78
}
79
	
80
void usage(void)
62
void usage(void)
81
{
63
{
82
	fprintf(stderr,
64
	fprintf(stderr,
Lines 97-102 Link Here
97
	exit(2);
79
	exit(2);
98
}
80
}
99
81
82
void set_signal(int signo, void (*handler)(void))
83
{
84
	struct sigaction sa;
85
86
	memset(&sa, 0, sizeof(sa));
87
	sa.sa_handler = (void (*)(int))handler;
88
	sa.sa_flags = SA_RESTART;
89
	sigaction(signo, &sa, NULL);
90
}
91
100
int send_pack(int s, struct in_addr src, struct in_addr dst,
92
int send_pack(int s, struct in_addr src, struct in_addr dst,
101
	      struct sockaddr_ll *ME, struct sockaddr_ll *HE)
93
	      struct sockaddr_ll *ME, struct sockaddr_ll *HE)
102
{
94
{
Lines 130-138 Link Here
130
	p+=4;
122
	p+=4;
131
123
132
	gettimeofday(&now, NULL);
124
	gettimeofday(&now, NULL);
133
	pkttrace("sendto->\n");
134
	err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE));
125
	err = sendto(s, buf, p-buf, 0, (struct sockaddr*)HE, sizeof(*HE));
135
	pkttrace("sendto<-\n");
136
	if (err == p-buf) {
126
	if (err == p-buf) {
137
		last = now;
127
		last = now;
138
		sent++;
128
		sent++;
Lines 145-164 Link Here
145
void finish(void)
135
void finish(void)
146
{
136
{
147
	if (!quiet) {
137
	if (!quiet) {
148
		fflush(stdout);
138
		printf("Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
149
		fprintf(stderr, "Sent %d probes (%d broadcast(s))\n", sent, brd_sent);
139
		printf("Received %d response(s)", received);
150
		fprintf(stderr, "Received %d response(s)", received);
151
		if (brd_recv || req_recv) {
140
		if (brd_recv || req_recv) {
152
			fprintf(stderr, " (");
141
			printf(" (");
153
			if (req_recv)
142
			if (req_recv)
154
				fprintf(stderr, "%d request(s)", req_recv);
143
				printf("%d request(s)", req_recv);
155
			if (brd_recv)
144
			if (brd_recv)
156
				fprintf(stderr, "%s%d broadcast(s)",
145
				printf("%s%d broadcast(s)",
157
				       req_recv ? ", " : "",
146
				       req_recv ? ", " : "",
158
				       brd_recv);
147
				       brd_recv);
159
			fprintf(stderr, ")");
148
			printf(")");
160
		}
149
		}
161
		fprintf(stderr, "\n");
150
		printf("\n");
151
		fflush(stdout);
162
	}
152
	}
163
	if (dad)
153
	if (dad)
164
		exit(!!received);
154
		exit(!!received);
Lines 167-179 Link Here
167
	exit(!received);
157
	exit(!received);
168
}
158
}
169
159
160
void catcher(void)
161
{
162
	struct timeval tv;
163
164
	gettimeofday(&tv, NULL);
165
166
	if (start.tv_sec==0)
167
		start = tv;
168
169
	if (count-- == 0 || (timeout && MS_TDIFF(tv,start) > timeout*1000 + 500))
170
		finish();
171
172
	if (last.tv_sec==0 || MS_TDIFF(tv,last) > 500) {
173
		send_pack(s, src, dst, &me, &he);
174
		if (count == 0 && unsolicited)
175
			finish();
176
	}
177
	alarm(1);
178
}
179
170
void print_hex(unsigned char *p, int len)
180
void print_hex(unsigned char *p, int len)
171
{
181
{
172
	int i;
182
	int i;
173
	for (i=0; i<len-1; i++)
183
	for (i=0; i<len; i++) {
174
		printf("%02X:", p[i]);
175
	if(len)
176
		printf("%02X", p[i]);
184
		printf("%02X", p[i]);
185
		if (i != len-1)
186
			printf(":");
187
	}
177
}
188
}
178
189
179
int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
190
int recv_pack(unsigned char *buf, int len, struct sockaddr_ll *FROM)
Lines 274-279 Link Here
274
		brd_recv++;
285
		brd_recv++;
275
	if (ah->ar_op == htons(ARPOP_REQUEST))
286
	if (ah->ar_op == htons(ARPOP_REQUEST))
276
		req_recv++;
287
		req_recv++;
288
	if (quit_on_reply)
289
		finish();
277
	if(!broadcast_only) {
290
	if(!broadcast_only) {
278
		memcpy(he.sll_addr, p, me.sll_halen);
291
		memcpy(he.sll_addr, p, me.sll_halen);
279
		unicasting=1;
292
		unicasting=1;
Lines 281-355 Link Here
281
	return 1;
294
	return 1;
282
}
295
}
283
296
284
285
unsigned char packet[4096];		// too big for stack on some arch.
286
287
void
288
pktloop(void)
289
{
290
	struct sockaddr_ll from;
291
	socklen_t alen = sizeof(from);
292
	fd_set rset;
293
	struct timeval tmo;
294
	int cc, i;
295
296
	for(;;){
297
		if(ntosend-- == 0)
298
			break;
299
		send_pack(s, src, dst, &me, &he);
300
301
  		gettimeofday(&tmo, 0);
302
		if(timeout)
303
			i = MS_TDIFF(timeouttv, tmo) ;
304
		else
305
			i = 1000;
306
		if(i < 0)
307
			break;
308
		if(i > 1000)
309
			i = 1000;		// maximum select 1s.
310
		tmo.tv_sec = i/1000;
311
		tmo.tv_usec = (i%1000)*1000;
312
313
		FD_ZERO(&rset);
314
		FD_SET(s, &rset);
315
		pkttrace("select %d ; %d\n", (int)tmo.tv_sec, (int)tmo.tv_usec);
316
		i = select(s+1, &rset, 0, 0, &tmo);
317
		pkttrace("<- select\n");
318
		if(i == -1){
319
			perror("arping: select");
320
			exit(1);
321
		}
322
		if(i == 0){
323
			gettimeofday(&tmo, 0);
324
			i =  MS_TDIFF(timeouttv, tmo);
325
			if(timeout && i <= 0)
326
				break;
327
			continue;
328
		}
329
		if ((cc = recvfrom(s, packet, sizeof(packet), 0,
330
				   (struct sockaddr *)&from, &alen)) < 0) {
331
			perror("arping: recvfrom");
332
			continue;
333
		}
334
		if(recv_pack(packet, cc, &from))
335
			if(--ntorecv == 0)
336
				break;
337
	}
338
}
339
340
int
297
int
341
main(int argc, char **argv)
298
main(int argc, char **argv)
342
{
299
{
343
	int ch, onereply;
300
	int socket_errno;
301
	int ch;
302
	uid_t uid = getuid();
303
304
	s = socket(PF_PACKET, SOCK_DGRAM, 0);
305
	socket_errno = errno;
306
307
	setuid(uid);
344
308
345
	while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
309
	while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
346
		switch(ch) {
310
		switch(ch) {
347
		case 'b':
311
		case 'b':
348
			broadcast_only = 1;
312
			broadcast_only=1;
349
			break;
313
			break;
350
		case 'D':
314
		case 'D':
351
			dad++;
315
			dad++;
352
			onereply = 1;
316
			quit_on_reply=1;
353
			break;
317
			break;
354
		case 'U':
318
		case 'U':
355
			unsolicited++;
319
			unsolicited++;
Lines 365-379 Link Here
365
			count = atoi(optarg);
329
			count = atoi(optarg);
366
			break;
330
			break;
367
		case 'w':
331
		case 'w':
368
			gettimeofday(&timeouttv, 0);
332
			timeout = atoi(optarg);
369
			timeouttv.tv_sec += atoi(optarg);
370
			timeout = 1;
371
			break;
333
			break;
372
		case 'I':
334
		case 'I':
373
 			device = optarg;
335
 			device = optarg;
374
 			break;
336
 			break;
375
 		case 'f':
337
 		case 'f':
376
 			onereply = 1;
338
 			quit_on_reply=1;
377
			break;
339
			break;
378
		case 's':
340
		case 's':
379
			source = optarg;
341
			source = optarg;
Lines 392-417 Link Here
392
354
393
	if (argc != 1)
355
	if (argc != 1)
394
		usage();
356
		usage();
395
	target = *argv;
396
357
397
	if(onereply)
358
	target = *argv;
398
		ntorecv = 1;
399
	if(timeout)			// strange ping compatability.
400
		ntorecv = count;
401
	else
402
		ntosend = count;
403
359
404
	if (device == 0) {
360
	if (device == NULL) {
405
		fprintf(stderr, "arping: device (option -I) is required\n");
361
		fprintf(stderr, "arping: device (option -I) is required\n");
406
		usage();
362
		usage();
407
	}
363
	}
408
364
409
	s = socket(PF_PACKET, SOCK_DGRAM, 0);
410
	if (s < 0) {
365
	if (s < 0) {
366
		errno = socket_errno;
411
		perror("arping: socket");
367
		perror("arping: socket");
412
		exit(2);
368
		exit(2);
413
	}
369
	}
414
	setuid(getuid());
415
370
416
	if (1) {
371
	if (1) {
417
		struct ifreq ifr;
372
		struct ifreq ifr;
Lines 424-436 Link Here
424
		ifindex = ifr.ifr_ifindex;
379
		ifindex = ifr.ifr_ifindex;
425
380
426
		if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) {
381
		if (ioctl(s, SIOCGIFFLAGS, (char*)&ifr)) {
427
			perror("arping: ioctl(SIOCGIFFLAGS)");
382
			perror("ioctl(SIOCGIFFLAGS)");
428
			exit(2);
383
			exit(2);
429
		}
384
		}
430
		if (!(ifr.ifr_flags&IFF_UP))
385
		if (!(ifr.ifr_flags&IFF_UP)) {
431
			errexit(2, "Interface \"%s\" is down\n", device);
386
			if (!quiet)
432
		if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK))
387
				printf("Interface \"%s\" is down\n", device);
433
			errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable\n", device);
388
			exit(2);
389
		}
390
		if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) {
391
			if (!quiet)
392
				printf("Interface \"%s\" is not ARPable\n", device);
393
			exit(dad?0:2);
394
		}
434
	}
395
	}
435
396
436
	if (inet_aton(target, &dst) != 1) {
397
	if (inet_aton(target, &dst) != 1) {
Lines 456-462 Link Here
456
		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
417
		int probe_fd = socket(AF_INET, SOCK_DGRAM, 0);
457
418
458
		if (probe_fd < 0) {
419
		if (probe_fd < 0) {
459
			perror("arping: socket");
420
			perror("socket");
460
			exit(2);
421
			exit(2);
461
		}
422
		}
462
		if (device) {
423
		if (device) {
Lines 468-474 Link Here
468
		if (src.s_addr) {
429
		if (src.s_addr) {
469
			saddr.sin_addr = src;
430
			saddr.sin_addr = src;
470
			if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
431
			if (bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
471
				perror("arping: bind");
432
				perror("bind");
472
				exit(2);
433
				exit(2);
473
			}
434
			}
474
		} else if (!dad) {
435
		} else if (!dad) {
Lines 481-491 Link Here
481
			if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1)
442
			if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1)
482
				perror("WARNING: setsockopt(SO_DONTROUTE)");
443
				perror("WARNING: setsockopt(SO_DONTROUTE)");
483
			if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
444
			if (connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
484
				perror("arping: connect");
445
				perror("connect");
485
				exit(2);
446
				exit(2);
486
			}
447
			}
487
			if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
448
			if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
488
				perror("arping: getsockname");
449
				perror("getsockname");
489
				exit(2);
450
				exit(2);
490
			}
451
			}
491
			src = saddr.sin_addr;
452
			src = saddr.sin_addr;
Lines 497-530 Link Here
497
	me.sll_ifindex = ifindex;
458
	me.sll_ifindex = ifindex;
498
	me.sll_protocol = htons(ETH_P_ARP);
459
	me.sll_protocol = htons(ETH_P_ARP);
499
	if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
460
	if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
500
		perror("arping: bind");
461
		perror("bind");
501
		exit(2);
462
		exit(2);
502
	}
463
	}
503
464
504
	if (1) {
465
	if (1) {
505
		socklen_t alen = sizeof(me);
466
		socklen_t alen = sizeof(me);
506
		if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
467
		if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
507
			perror("arping: getsockname");
468
			perror("getsockname");
508
			exit(2);
469
			exit(2);
509
		}
470
		}
510
	}
471
	}
511
	if (me.sll_halen == 0)
472
	if (me.sll_halen == 0) {
512
		errexit(dad ? 0 : 2, "Interface \"%s\" is not ARPable (no ll address)\n", device);
473
		if (!quiet)
474
			printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
475
		exit(dad?0:2);
476
	}
513
477
514
	he = me;
478
	he = me;
515
	memset(he.sll_addr, -1, he.sll_halen);
479
	memset(he.sll_addr, -1, he.sll_halen);
516
480
517
	if (!quiet) {
481
	if (!quiet) {
518
		fprintf(stderr, "ARPING %s ", inet_ntoa(dst));
482
		printf("ARPING %s ", inet_ntoa(dst));
519
		fprintf(stderr, "from %s %s\n",  inet_ntoa(src), device ? : "");
483
		printf("from %s %s\n",  inet_ntoa(src), device ? : "");
520
	}
484
	}
521
485
522
	if (!src.s_addr && !dad)
486
	if (!src.s_addr && !dad) {
523
		errexit(2, "arping: no source address in not-DAD mode\n");
487
		fprintf(stderr, "arping: no source address in not-DAD mode\n");
488
		exit(2);
489
	}
490
491
	set_signal(SIGINT, finish);
492
	set_signal(SIGALRM, catcher);
493
494
	catcher();
524
495
525
	pktloop();
496
	while(1) {
526
	finish();
497
		sigset_t sset, osset;
527
	return 1;		// shut up gcc.
498
		unsigned char packet[4096];
499
		struct sockaddr_ll from;
500
		socklen_t alen = sizeof(from);
501
		int cc;
502
503
		if ((cc = recvfrom(s, packet, sizeof(packet), 0,
504
				   (struct sockaddr *)&from, &alen)) < 0) {
505
			perror("arping: recvfrom");
506
			continue;
507
		}
508
		sigemptyset(&sset);
509
		sigaddset(&sset, SIGALRM);
510
		sigaddset(&sset, SIGINT);
511
		sigprocmask(SIG_BLOCK, &sset, &osset);
512
		recv_pack(packet, cc, &from);
513
		sigprocmask(SIG_SETMASK, &osset, NULL);
514
	}
528
}
515
}
529
516
530
517

Return to bug 144526