xref: /csrg-svn/usr.sbin/arp/arp.c (revision 16255)
1*16255Skarels #ifndef lint
2*16255Skarels static	char *sccsid = "@(#)arp.c	1.1 (Berkeley) 03/30/84";
3*16255Skarels #endif
4*16255Skarels 
5*16255Skarels /*
6*16255Skarels  * arp - display, set, and delete arp table entries
7*16255Skarels  */
8*16255Skarels 
9*16255Skarels #include <stdio.h>
10*16255Skarels #include <sys/types.h>
11*16255Skarels #include <sys/socket.h>
12*16255Skarels #include <netinet/in.h>
13*16255Skarels #include <sys/ioctl.h>
14*16255Skarels #include <errno.h>
15*16255Skarels #include <netdb.h>
16*16255Skarels #include <nlist.h>
17*16255Skarels #include <net/if.h>
18*16255Skarels #include <netinet/if_ether.h>
19*16255Skarels 
20*16255Skarels extern int errno;
21*16255Skarels 
22*16255Skarels main(argc, argv)
23*16255Skarels 	char **argv;
24*16255Skarels {
25*16255Skarels 	if (argc >= 2 && strcmp(argv[1], "-a") == 0) {
26*16255Skarels 		char *kernel = "/vmunix", *mem = "/dev/kmem";
27*16255Skarels 
28*16255Skarels 		if (argc >= 3)
29*16255Skarels 			kernel = argv[2];
30*16255Skarels 		if (argc >= 4)
31*16255Skarels 			mem = argv[3];
32*16255Skarels 		dump(kernel, mem);
33*16255Skarels 		exit(0);
34*16255Skarels 	}
35*16255Skarels 	if (argc == 2) {
36*16255Skarels 		get(argv[1]);
37*16255Skarels 		exit(0);
38*16255Skarels 	}
39*16255Skarels 	if (argc >= 4 && strcmp(argv[1], "-s") == 0) {
40*16255Skarels 		set(argc-2, &argv[2]);
41*16255Skarels 		exit(0);
42*16255Skarels 	}
43*16255Skarels 	if (argc == 3 && strcmp(argv[1], "-d") == 0) {
44*16255Skarels 		delete(argv[2]);
45*16255Skarels 		exit(0);
46*16255Skarels 	}
47*16255Skarels 	if (argc == 3 && strcmp(argv[1], "-f") == 0) {
48*16255Skarels 		file(argv[2]);
49*16255Skarels 		exit(0);
50*16255Skarels 	}
51*16255Skarels 	usage();
52*16255Skarels 	exit(1);
53*16255Skarels }
54*16255Skarels 
55*16255Skarels /*
56*16255Skarels  * Process a file to set standard arp entries
57*16255Skarels  */
58*16255Skarels file(name)
59*16255Skarels 	char *name;
60*16255Skarels {
61*16255Skarels 	FILE *fp;
62*16255Skarels 	int i;
63*16255Skarels 	char line[100], arg[4][50], *args[4];
64*16255Skarels 
65*16255Skarels 	if ((fp = fopen(name, "r")) == NULL) {
66*16255Skarels 		fprintf(stderr, "arp: cannot open %s\n", name);
67*16255Skarels 		exit(1);
68*16255Skarels 	}
69*16255Skarels 	args[0] = &arg[0][0];
70*16255Skarels 	args[1] = &arg[1][0];
71*16255Skarels 	args[2] = &arg[2][0];
72*16255Skarels 	args[3] = &arg[3][0];
73*16255Skarels 	while(fgets(line, 100, fp) != NULL) {
74*16255Skarels 		i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3]);
75*16255Skarels 		if (i < 2) {
76*16255Skarels 			fprintf(stderr, "arp: bad line: %s\n", line);
77*16255Skarels 			continue;
78*16255Skarels 		}
79*16255Skarels 		set(i, args);
80*16255Skarels 	}
81*16255Skarels 	fclose(fp);
82*16255Skarels }
83*16255Skarels 
84*16255Skarels /*
85*16255Skarels  * Set an individual arp entry
86*16255Skarels  */
87*16255Skarels set(argc, argv)
88*16255Skarels 	char **argv;
89*16255Skarels {
90*16255Skarels 	struct arpreq ar;
91*16255Skarels 	struct hostent *hp;
92*16255Skarels 	struct sockaddr_in *sin;
93*16255Skarels 	struct ether_addr *ea;
94*16255Skarels 	int s;
95*16255Skarels 	char *host = argv[0], *eaddr = argv[1];
96*16255Skarels 
97*16255Skarels 	argc -= 2;
98*16255Skarels 	argv += 2;
99*16255Skarels 	hp = gethostbyname(host);
100*16255Skarels 	if (hp == NULL) {
101*16255Skarels 		fprintf(stderr, "arp: %s: unknown host\n", host);
102*16255Skarels 		return (1);
103*16255Skarels 	}
104*16255Skarels 	bzero((caddr_t)&ar, sizeof ar);
105*16255Skarels 	ar.arp_pa.sa_family = AF_INET;
106*16255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
107*16255Skarels 	sin->sin_addr = *(struct in_addr *)hp->h_addr;
108*16255Skarels 	ea = (struct ether_addr *)ar.arp_ha.sa_data;
109*16255Skarels 	if (ether_aton(eaddr, ea))
110*16255Skarels 		return;
111*16255Skarels 	ar.arp_flags = ATF_PERM;
112*16255Skarels 	while(argc-- > 0) {
113*16255Skarels 		if (strncmp(argv[0], "temp", 4) == 0)
114*16255Skarels 			ar.arp_flags &= ~ATF_PERM;
115*16255Skarels 		if (strncmp(argv[0], "pub", 3) == 0)
116*16255Skarels 			ar.arp_flags |= ATF_PUBL;
117*16255Skarels 		argv++;
118*16255Skarels 	}
119*16255Skarels 
120*16255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
121*16255Skarels 	if (s < 0) {
122*16255Skarels                 perror("arp: socket");
123*16255Skarels                 exit(1);
124*16255Skarels         }
125*16255Skarels 	if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
126*16255Skarels 		perror(host);
127*16255Skarels 		exit(1);
128*16255Skarels 	}
129*16255Skarels 	close(s);
130*16255Skarels }
131*16255Skarels 
132*16255Skarels 
133*16255Skarels /*
134*16255Skarels  * Display an individual arp entry
135*16255Skarels  */
136*16255Skarels get(host)
137*16255Skarels 	char *host;
138*16255Skarels {
139*16255Skarels 	struct arpreq ar;
140*16255Skarels 	struct hostent *hp;
141*16255Skarels 	struct sockaddr_in *sin;
142*16255Skarels 	struct ether_addr *ea;
143*16255Skarels 	int s;
144*16255Skarels 
145*16255Skarels 	hp = gethostbyname(host);
146*16255Skarels 	if (hp == NULL) {
147*16255Skarels 		fprintf(stderr, "arp: %s: unknown host\n", host);
148*16255Skarels 		exit(1);
149*16255Skarels 	}
150*16255Skarels 	bzero((caddr_t)&ar, sizeof ar);
151*16255Skarels 	ar.arp_pa.sa_family = AF_INET;
152*16255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
153*16255Skarels 	sin->sin_addr = *(struct in_addr *)hp->h_addr;
154*16255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
155*16255Skarels 	if (s < 0) {
156*16255Skarels                 perror("arp: socket");
157*16255Skarels                 exit(1);
158*16255Skarels         }
159*16255Skarels 	if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
160*16255Skarels 		if (errno == ENXIO)
161*16255Skarels 			printf("%s (%s) -- no entry\n",
162*16255Skarels 			    host, inet_ntoa(sin->sin_addr));
163*16255Skarels 		else
164*16255Skarels 			perror("SIOCGARP");
165*16255Skarels 		exit(1);
166*16255Skarels 	}
167*16255Skarels 	close(s);
168*16255Skarels 	ea = (struct ether_addr *)ar.arp_ha.sa_data;
169*16255Skarels 	printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
170*16255Skarels 	if (ar.arp_flags & ATF_COM)
171*16255Skarels 		ether_print(ea);
172*16255Skarels 	else
173*16255Skarels 		printf("(incomplete)");
174*16255Skarels 	if (!(ar.arp_flags & ATF_PERM)) printf(" temporary");
175*16255Skarels 	if (ar.arp_flags & ATF_PUBL) printf(" published");
176*16255Skarels 	printf("\n");
177*16255Skarels }
178*16255Skarels 
179*16255Skarels /*
180*16255Skarels  * Delete an arp entry
181*16255Skarels  */
182*16255Skarels delete(host)
183*16255Skarels 	char *host;
184*16255Skarels {
185*16255Skarels 	struct arpreq ar;
186*16255Skarels 	struct hostent *hp;
187*16255Skarels 	struct sockaddr_in *sin;
188*16255Skarels 	int s;
189*16255Skarels 
190*16255Skarels 	hp = gethostbyname(host);
191*16255Skarels 	if (hp == NULL) {
192*16255Skarels 		fprintf(stderr, "arp: %s: unknown host\n", host);
193*16255Skarels 		exit(1);
194*16255Skarels 	}
195*16255Skarels 	bzero((caddr_t)&ar, sizeof ar);
196*16255Skarels 	ar.arp_pa.sa_family = AF_INET;
197*16255Skarels 	sin = (struct sockaddr_in *)&ar.arp_pa;
198*16255Skarels 	sin->sin_addr = *(struct in_addr *)hp->h_addr;
199*16255Skarels 	s = socket(AF_INET, SOCK_DGRAM, 0);
200*16255Skarels 	if (s < 0) {
201*16255Skarels                 perror("arp: socket");
202*16255Skarels                 exit(1);
203*16255Skarels         }
204*16255Skarels 	if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
205*16255Skarels 		if (errno == ENXIO)
206*16255Skarels 			printf("%s (%s) -- no entry\n",
207*16255Skarels 			    host, inet_ntoa(sin->sin_addr));
208*16255Skarels 		else
209*16255Skarels 			perror("SIOCDARP");
210*16255Skarels 		exit(1);
211*16255Skarels 	}
212*16255Skarels 	close(s);
213*16255Skarels 	printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
214*16255Skarels }
215*16255Skarels 
216*16255Skarels struct nlist nl[] = {
217*16255Skarels #define	X_ARPTAB	0
218*16255Skarels 	{ "_arptab" },
219*16255Skarels #define	X_ARPTAB_SIZE	1
220*16255Skarels 	{ "_arptab_size" },
221*16255Skarels 	{ "" },
222*16255Skarels };
223*16255Skarels 
224*16255Skarels /*
225*16255Skarels  * Dump the entire arp table
226*16255Skarels  */
227*16255Skarels dump(kernel, mem)
228*16255Skarels 	char *kernel, *mem;
229*16255Skarels {
230*16255Skarels 	int mf, arptab_size, sz;
231*16255Skarels 	struct arptab *at;
232*16255Skarels 	struct hostent *hp;
233*16255Skarels 	char *host;
234*16255Skarels 
235*16255Skarels 	nlist(kernel, nl);
236*16255Skarels 	if(nl[X_ARPTAB_SIZE].n_type == 0) {
237*16255Skarels 		fprintf(stderr, "arp: %s: bad namelist\n", kernel);
238*16255Skarels 		exit(1);
239*16255Skarels 	}
240*16255Skarels 	mf = open(mem, 0);
241*16255Skarels 	if(mf < 0) {
242*16255Skarels 		fprintf(fprintf, "arp: cannot open %s\n", mem);
243*16255Skarels 		exit(1);
244*16255Skarels 	}
245*16255Skarels 	lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0);
246*16255Skarels 	read(mf, &arptab_size, sizeof arptab_size);
247*16255Skarels 	if (arptab_size <=0 || arptab_size > 1000) {
248*16255Skarels 		fprintf(stderr, "arp: %s: namelist wrong\n", kernel);
249*16255Skarels 		exit(1);
250*16255Skarels 	}
251*16255Skarels 	sz = arptab_size * sizeof (struct arptab);
252*16255Skarels 	at = (struct arptab *)malloc(sz);
253*16255Skarels 	if (at == NULL) {
254*16255Skarels 		fprintf(stderr, "arp: can't get memory for arptab\n");
255*16255Skarels 		exit(1);
256*16255Skarels 	}
257*16255Skarels 	lseek(mf, (long)nl[X_ARPTAB].n_value, 0);
258*16255Skarels 	if (read(mf, (char *)at, sz) != sz) {
259*16255Skarels 		perror("arp: error reading arptab");
260*16255Skarels 		exit(1);
261*16255Skarels 	}
262*16255Skarels 	close(mf);
263*16255Skarels 	for (; arptab_size-- > 0; at++) {
264*16255Skarels 		if (at->at_iaddr.s_addr == 0 || at->at_flags == 0)
265*16255Skarels 			continue;
266*16255Skarels 		hp = gethostbyaddr((caddr_t)&at->at_iaddr, sizeof at->at_iaddr,
267*16255Skarels 			AF_INET);
268*16255Skarels 		if (hp)
269*16255Skarels 			host = hp->h_name;
270*16255Skarels 		else
271*16255Skarels 			host = "?";
272*16255Skarels 		printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr));
273*16255Skarels 		if (at->at_flags & ATF_COM)
274*16255Skarels 			ether_print(&at->at_enaddr);
275*16255Skarels 		else
276*16255Skarels 			printf("(incomplete)");
277*16255Skarels 		if (!(at->at_flags & ATF_PERM)) printf(" temporary");
278*16255Skarels 		if (at->at_flags & ATF_PUBL) printf(" published");
279*16255Skarels 		printf("\n");
280*16255Skarels 	}
281*16255Skarels }
282*16255Skarels 
283*16255Skarels ether_print(ea)
284*16255Skarels 	struct ether_addr *ea;
285*16255Skarels {
286*16255Skarels 	u_char *cp = &ea->ether_addr_octet[0];
287*16255Skarels 
288*16255Skarels 	printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
289*16255Skarels }
290*16255Skarels 
291*16255Skarels ether_aton(a, n)
292*16255Skarels 	char *a;
293*16255Skarels 	struct ether_addr *n;
294*16255Skarels {
295*16255Skarels 	int i, o[6];
296*16255Skarels 
297*16255Skarels 	i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
298*16255Skarels 					   &o[3], &o[4], &o[5]);
299*16255Skarels 	if (i != 6) {
300*16255Skarels 		fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
301*16255Skarels 		return (1);
302*16255Skarels 	}
303*16255Skarels 	for (i=0; i<6; i++)
304*16255Skarels 		n->ether_addr_octet[i] = o[i];
305*16255Skarels 	return (0);
306*16255Skarels }
307*16255Skarels 
308*16255Skarels usage()
309*16255Skarels {
310*16255Skarels 	printf("Usage: arp hostname\n");
311*16255Skarels 	printf("       arp -a [/vmunix] [/dev/kmem]\n");
312*16255Skarels 	printf("       arp -d hostname\n");
313*16255Skarels 	printf("       arp -s hostname ether_addr [temp] [pub]\n");
314*16255Skarels 	printf("       arp -f filename\n");
315*16255Skarels }
316