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