xref: /csrg-svn/usr.sbin/arp/arp.c (revision 42791)
134918Sbostic /*
234918Sbostic  * Copyright (c) 1984 Regents of the University of California.
334918Sbostic  * All rights reserved.
434918Sbostic  *
534918Sbostic  * This code is derived from software contributed to Berkeley by
634918Sbostic  * Sun Microsystems, Inc.
734918Sbostic  *
8*42791Sbostic  * %sccs.include.redist.c%
934918Sbostic  */
1034918Sbostic 
1116255Skarels #ifndef lint
1234918Sbostic char copyright[] =
1334918Sbostic "@(#) Copyright (c) 1984 Regents of the University of California.\n\
1434918Sbostic  All rights reserved.\n";
1534918Sbostic #endif /* not lint */
1616255Skarels 
1734918Sbostic #ifndef lint
18*42791Sbostic static char sccsid[] = "@(#)arp.c	5.11 (Berkeley) 06/01/90";
1934918Sbostic #endif /* not lint */
2034918Sbostic 
2116255Skarels /*
2216255Skarels  * arp - display, set, and delete arp table entries
2316255Skarels  */
2416255Skarels 
2533624Sbostic #include <machine/pte.h>
2633624Sbostic 
2733624Sbostic #include <sys/param.h>
2833624Sbostic #include <sys/vmmac.h>
2933624Sbostic #include <sys/file.h>
3016255Skarels #include <sys/socket.h>
3116255Skarels #include <sys/ioctl.h>
3233624Sbostic 
3316255Skarels #include <netdb.h>
3433624Sbostic #include <netinet/in.h>
3516255Skarels #include <net/if.h>
3616255Skarels #include <netinet/if_ether.h>
3716255Skarels 
3833624Sbostic #include <errno.h>
3933624Sbostic #include <nlist.h>
4033624Sbostic #include <stdio.h>
4137961Sbostic #include <paths.h>
4233624Sbostic 
4316255Skarels extern int errno;
4433624Sbostic static int kflag;
4516255Skarels 
4616255Skarels main(argc, argv)
4733624Sbostic 	int argc;
4816255Skarels 	char **argv;
4916255Skarels {
5033624Sbostic 	int ch;
5116255Skarels 
5233624Sbostic 	while ((ch = getopt(argc, argv, "adsf")) != EOF)
5333624Sbostic 		switch((char)ch) {
5433624Sbostic 		case 'a': {
5533624Sbostic 			char *mem;
5633624Sbostic 
5733624Sbostic 			if (argc > 4)
5833624Sbostic 				usage();
5933624Sbostic 			if (argc == 4) {
6033624Sbostic 				kflag = 1;
6133624Sbostic 				mem = argv[3];
6233624Sbostic 			}
6333624Sbostic 			else
6437255Sbostic 				mem = _PATH_KMEM;
6537961Sbostic 			dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem);
6633624Sbostic 			exit(0);
6733624Sbostic 		}
6833624Sbostic 		case 'd':
6933624Sbostic 			if (argc != 3)
7033624Sbostic 				usage();
7133624Sbostic 			delete(argv[2]);
7233624Sbostic 			exit(0);
7333624Sbostic 		case 's':
7433624Sbostic 			if (argc < 4 || argc > 7)
7533624Sbostic 				usage();
7633624Sbostic 			exit(set(argc-2, &argv[2]) ? 1 : 0);
7733624Sbostic 		case 'f':
7833624Sbostic 			if (argc != 3)
7933624Sbostic 				usage();
8033624Sbostic 			exit (file(argv[2]) ? 1 : 0);
8133624Sbostic 		case '?':
8233624Sbostic 		default:
8333624Sbostic 			usage();
8433624Sbostic 		}
8533624Sbostic 	if (argc != 2)
8633624Sbostic 		usage();
8733624Sbostic 	get(argv[1]);
8833624Sbostic 	exit(0);
8916255Skarels }
9016255Skarels 
9116255Skarels /*
9216255Skarels  * Process a file to set standard arp entries
9316255Skarels  */
9416255Skarels file(name)
9516255Skarels 	char *name;
9616255Skarels {
9716255Skarels 	FILE *fp;
9833624Sbostic 	int i, retval;
9925788Skarels 	char line[100], arg[5][50], *args[5];
10016255Skarels 
10116255Skarels 	if ((fp = fopen(name, "r")) == NULL) {
10216255Skarels 		fprintf(stderr, "arp: cannot open %s\n", name);
10316255Skarels 		exit(1);
10416255Skarels 	}
10516255Skarels 	args[0] = &arg[0][0];
10616255Skarels 	args[1] = &arg[1][0];
10716255Skarels 	args[2] = &arg[2][0];
10816255Skarels 	args[3] = &arg[3][0];
10925788Skarels 	args[4] = &arg[4][0];
11032643Smckusick 	retval = 0;
11116255Skarels 	while(fgets(line, 100, fp) != NULL) {
11232643Smckusick 		i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
11332643Smckusick 		    arg[3], arg[4]);
11416255Skarels 		if (i < 2) {
11516255Skarels 			fprintf(stderr, "arp: bad line: %s\n", line);
11632643Smckusick 			retval = 1;
11716255Skarels 			continue;
11816255Skarels 		}
11932643Smckusick 		if (set(i, args))
12032643Smckusick 			retval = 1;
12116255Skarels 	}
12216255Skarels 	fclose(fp);
12332643Smckusick 	return (retval);
12416255Skarels }
12516255Skarels 
12616255Skarels /*
12716255Skarels  * Set an individual arp entry
12816255Skarels  */
12916255Skarels set(argc, argv)
13033624Sbostic 	int argc;
13116255Skarels 	char **argv;
13216255Skarels {
13316255Skarels 	struct arpreq ar;
13416255Skarels 	struct hostent *hp;
13516255Skarels 	struct sockaddr_in *sin;
13621393Skarels 	u_char *ea;
13716255Skarels 	int s;
13816255Skarels 	char *host = argv[0], *eaddr = argv[1];
13916255Skarels 
14016255Skarels 	argc -= 2;
14116255Skarels 	argv += 2;
14216255Skarels 	bzero((caddr_t)&ar, sizeof ar);
14316255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
14426314Skarels 	sin->sin_family = AF_INET;
14526314Skarels 	sin->sin_addr.s_addr = inet_addr(host);
14626314Skarels 	if (sin->sin_addr.s_addr == -1) {
14735778Sbostic 		if (!(hp = gethostbyname(host))) {
14835778Sbostic 			fprintf(stderr, "arp: %s: ", host);
14935778Sbostic 			herror((char *)NULL);
15032643Smckusick 			return (1);
15126314Skarels 		}
15226314Skarels 		bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
15326314Skarels 		    sizeof sin->sin_addr);
15426314Skarels 	}
15521393Skarels 	ea = (u_char *)ar.arp_ha.sa_data;
15616255Skarels 	if (ether_aton(eaddr, ea))
15732643Smckusick 		return (1);
15816255Skarels 	ar.arp_flags = ATF_PERM;
15926314Skarels 	while (argc-- > 0) {
16016255Skarels 		if (strncmp(argv[0], "temp", 4) == 0)
16116255Skarels 			ar.arp_flags &= ~ATF_PERM;
16233624Sbostic 		else if (strncmp(argv[0], "pub", 3) == 0)
16316255Skarels 			ar.arp_flags |= ATF_PUBL;
16433624Sbostic 		else if (strncmp(argv[0], "trail", 5) == 0)
16525788Skarels 			ar.arp_flags |= ATF_USETRAILERS;
16616255Skarels 		argv++;
16716255Skarels 	}
16816255Skarels 
16916255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
17016255Skarels 	if (s < 0) {
17133624Sbostic 		perror("arp: socket");
17233624Sbostic 		exit(1);
17333624Sbostic 	}
17416255Skarels 	if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
17516255Skarels 		perror(host);
17616255Skarels 		exit(1);
17716255Skarels 	}
17816255Skarels 	close(s);
17932643Smckusick 	return (0);
18016255Skarels }
18116255Skarels 
18216255Skarels /*
18316255Skarels  * Display an individual arp entry
18416255Skarels  */
18516255Skarels get(host)
18616255Skarels 	char *host;
18716255Skarels {
18816255Skarels 	struct arpreq ar;
18916255Skarels 	struct hostent *hp;
19016255Skarels 	struct sockaddr_in *sin;
19121393Skarels 	u_char *ea;
19216255Skarels 	int s;
19333624Sbostic 	char *inet_ntoa();
19416255Skarels 
19516255Skarels 	bzero((caddr_t)&ar, sizeof ar);
19616255Skarels 	ar.arp_pa.sa_family = AF_INET;
19716255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
19826314Skarels 	sin->sin_family = AF_INET;
19926314Skarels 	sin->sin_addr.s_addr = inet_addr(host);
20026314Skarels 	if (sin->sin_addr.s_addr == -1) {
20135778Sbostic 		if (!(hp = gethostbyname(host))) {
20235778Sbostic 			fprintf(stderr, "arp: %s: ", host);
20335778Sbostic 			herror((char *)NULL);
20426314Skarels 			exit(1);
20526314Skarels 		}
20626314Skarels 		bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
20726314Skarels 		    sizeof sin->sin_addr);
20826314Skarels 	}
20916255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
21016255Skarels 	if (s < 0) {
21133624Sbostic 		perror("arp: socket");
21233624Sbostic 		exit(1);
21333624Sbostic 	}
21416255Skarels 	if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
21516255Skarels 		if (errno == ENXIO)
21616255Skarels 			printf("%s (%s) -- no entry\n",
21716255Skarels 			    host, inet_ntoa(sin->sin_addr));
21816255Skarels 		else
21916255Skarels 			perror("SIOCGARP");
22016255Skarels 		exit(1);
22116255Skarels 	}
22216255Skarels 	close(s);
22321393Skarels 	ea = (u_char *)ar.arp_ha.sa_data;
22416255Skarels 	printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
22516255Skarels 	if (ar.arp_flags & ATF_COM)
22616255Skarels 		ether_print(ea);
22716255Skarels 	else
22816255Skarels 		printf("(incomplete)");
22933624Sbostic 	if (ar.arp_flags & ATF_PERM)
23033624Sbostic 		printf(" permanent");
23133624Sbostic 	if (ar.arp_flags & ATF_PUBL)
23233624Sbostic 		printf(" published");
23333624Sbostic 	if (ar.arp_flags & ATF_USETRAILERS)
23433624Sbostic 		printf(" trailers");
23516255Skarels 	printf("\n");
23616255Skarels }
23716255Skarels 
23816255Skarels /*
23916255Skarels  * Delete an arp entry
24016255Skarels  */
24116255Skarels delete(host)
24216255Skarels 	char *host;
24316255Skarels {
24416255Skarels 	struct arpreq ar;
24516255Skarels 	struct hostent *hp;
24616255Skarels 	struct sockaddr_in *sin;
24716255Skarels 	int s;
24816255Skarels 
24916255Skarels 	bzero((caddr_t)&ar, sizeof ar);
25016255Skarels 	ar.arp_pa.sa_family = AF_INET;
25116255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
25226314Skarels 	sin->sin_family = AF_INET;
25326314Skarels 	sin->sin_addr.s_addr = inet_addr(host);
25426314Skarels 	if (sin->sin_addr.s_addr == -1) {
25535778Sbostic 		if (!(hp = gethostbyname(host))) {
25635778Sbostic 			fprintf(stderr, "arp: %s: ", host);
25735778Sbostic 			herror((char *)NULL);
25826314Skarels 			exit(1);
25926314Skarels 		}
26026314Skarels 		bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
26126314Skarels 		    sizeof sin->sin_addr);
26226314Skarels 	}
26316255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
26416255Skarels 	if (s < 0) {
26533624Sbostic 		perror("arp: socket");
26633624Sbostic 		exit(1);
26733624Sbostic 	}
26816255Skarels 	if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
26916255Skarels 		if (errno == ENXIO)
27016255Skarels 			printf("%s (%s) -- no entry\n",
27116255Skarels 			    host, inet_ntoa(sin->sin_addr));
27216255Skarels 		else
27316255Skarels 			perror("SIOCDARP");
27416255Skarels 		exit(1);
27516255Skarels 	}
27616255Skarels 	close(s);
27716255Skarels 	printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
27816255Skarels }
27916255Skarels 
28016255Skarels struct nlist nl[] = {
28116255Skarels #define	X_ARPTAB	0
28216255Skarels 	{ "_arptab" },
28316255Skarels #define	X_ARPTAB_SIZE	1
28416255Skarels 	{ "_arptab_size" },
28533624Sbostic #define	N_SYSMAP	2
28633624Sbostic 	{ "_Sysmap" },
28733624Sbostic #define	N_SYSSIZE	3
28833624Sbostic 	{ "_Syssize" },
28916255Skarels 	{ "" },
29016255Skarels };
29116255Skarels 
29233624Sbostic static struct pte *Sysmap;
29333624Sbostic 
29416255Skarels /*
29516255Skarels  * Dump the entire arp table
29616255Skarels  */
29716255Skarels dump(kernel, mem)
29816255Skarels 	char *kernel, *mem;
29916255Skarels {
30033624Sbostic 	extern int h_errno;
30116255Skarels 	struct arptab *at;
30216255Skarels 	struct hostent *hp;
30333624Sbostic 	int bynumber, mf, arptab_size, sz;
30433624Sbostic 	char *host, *malloc();
30533624Sbostic 	off_t lseek();
30616255Skarels 
30733624Sbostic 	if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) {
30816255Skarels 		fprintf(stderr, "arp: %s: bad namelist\n", kernel);
30916255Skarels 		exit(1);
31016255Skarels 	}
31133624Sbostic 	mf = open(mem, O_RDONLY);
31233624Sbostic 	if (mf < 0) {
31335377Sbostic 		fprintf(stderr, "arp: cannot open %s\n", mem);
31416255Skarels 		exit(1);
31516255Skarels 	}
31633624Sbostic 	if (kflag) {
31733624Sbostic 		off_t off;
31833624Sbostic 
31933624Sbostic 		Sysmap = (struct pte *)
32033624Sbostic 		   malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
32133624Sbostic 		if (!Sysmap) {
32233624Sbostic 			fputs("arp: can't get memory for Sysmap.\n", stderr);
32333624Sbostic 			exit(1);
32433624Sbostic 		}
32533624Sbostic 		off = nl[N_SYSMAP].n_value & ~KERNBASE;
32633624Sbostic 		(void)lseek(mf, off, L_SET);
32733624Sbostic 		(void)read(mf, (char *)Sysmap,
32833624Sbostic 		    (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
32933624Sbostic 	}
33033624Sbostic 	klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET);
33116255Skarels 	read(mf, &arptab_size, sizeof arptab_size);
33233624Sbostic 	if (arptab_size <= 0 || arptab_size > 1000) {
33316255Skarels 		fprintf(stderr, "arp: %s: namelist wrong\n", kernel);
33416255Skarels 		exit(1);
33516255Skarels 	}
33616255Skarels 	sz = arptab_size * sizeof (struct arptab);
33733624Sbostic 	at = (struct arptab *)malloc((u_int)sz);
33816255Skarels 	if (at == NULL) {
33933624Sbostic 		fputs("arp: can't get memory for arptab.\n", stderr);
34016255Skarels 		exit(1);
34116255Skarels 	}
34233624Sbostic 	klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET);
34316255Skarels 	if (read(mf, (char *)at, sz) != sz) {
34416255Skarels 		perror("arp: error reading arptab");
34516255Skarels 		exit(1);
34616255Skarels 	}
34716255Skarels 	close(mf);
34833624Sbostic 	for (bynumber = 0; arptab_size-- > 0; at++) {
34916255Skarels 		if (at->at_iaddr.s_addr == 0 || at->at_flags == 0)
35016255Skarels 			continue;
35126314Skarels 		if (bynumber == 0)
35226314Skarels 			hp = gethostbyaddr((caddr_t)&at->at_iaddr,
35326314Skarels 			    sizeof at->at_iaddr, AF_INET);
35426314Skarels 		else
35526314Skarels 			hp = 0;
35616255Skarels 		if (hp)
35716255Skarels 			host = hp->h_name;
35826314Skarels 		else {
35916255Skarels 			host = "?";
36026314Skarels 			if (h_errno == TRY_AGAIN)
36126314Skarels 				bynumber = 1;
36226314Skarels 		}
36316255Skarels 		printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr));
36416255Skarels 		if (at->at_flags & ATF_COM)
36521393Skarels 			ether_print(at->at_enaddr);
36616255Skarels 		else
36716255Skarels 			printf("(incomplete)");
36833624Sbostic 		if (at->at_flags & ATF_PERM)
36933624Sbostic 			printf(" permanent");
37033624Sbostic 		if (at->at_flags & ATF_PUBL)
37133624Sbostic 			printf(" published");
37233624Sbostic 		if (at->at_flags & ATF_USETRAILERS)
37333624Sbostic 			printf(" trailers");
37416255Skarels 		printf("\n");
37516255Skarels 	}
37616255Skarels }
37716255Skarels 
37833624Sbostic /*
37933624Sbostic  * Seek into the kernel for a value.
38033624Sbostic  */
38133624Sbostic klseek(fd, base, off)
38233624Sbostic 	int fd, off;
38333624Sbostic 	off_t base;
38433624Sbostic {
38533624Sbostic 	off_t lseek();
38633624Sbostic 
38733624Sbostic 	if (kflag) {	/* get kernel pte */
38833624Sbostic 		base &= ~KERNBASE;
38933624Sbostic 		base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
39033624Sbostic 	}
39133624Sbostic 	(void)lseek(fd, base, off);
39233624Sbostic }
39333624Sbostic 
39421393Skarels ether_print(cp)
39521393Skarels 	u_char *cp;
39616255Skarels {
39716255Skarels 	printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
39816255Skarels }
39916255Skarels 
40016255Skarels ether_aton(a, n)
40116255Skarels 	char *a;
40221393Skarels 	u_char *n;
40316255Skarels {
40416255Skarels 	int i, o[6];
40516255Skarels 
40616255Skarels 	i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
40716255Skarels 					   &o[3], &o[4], &o[5]);
40816255Skarels 	if (i != 6) {
40916255Skarels 		fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
41016255Skarels 		return (1);
41116255Skarels 	}
41216255Skarels 	for (i=0; i<6; i++)
41321393Skarels 		n[i] = o[i];
41416255Skarels 	return (0);
41516255Skarels }
41616255Skarels 
41716255Skarels usage()
41816255Skarels {
41933624Sbostic 	printf("usage: arp hostname\n");
42037961Sbostic 	printf("       arp -a [kernel] [kernel_memory]\n");
42116255Skarels 	printf("       arp -d hostname\n");
42232643Smckusick 	printf("       arp -s hostname ether_addr [temp] [pub] [trail]\n");
42316255Skarels 	printf("       arp -f filename\n");
42433624Sbostic 	exit(1);
42516255Skarels }
426