Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/cmd-inet/usr.sbin/arp.c
+++ new/usr/src/cmd/cmd-inet/usr.sbin/arp.c
1 1 /*
2 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5 /*
6 6 * Copyright (c) 1984 Regents of the University of California.
7 7 * All rights reserved.
8 8 *
9 9 * This code is derived from software contributed to Berkeley by
10 10 * Sun Microsystems, Inc.
11 11 *
12 12 * Redistribution and use in source and binary forms, with or without
13 13 * modification, are permitted provided that the following conditions
14 14 * are met:
15 15 * 1. Redistributions of source code must retain the above copyright
16 16 * notice, this list of conditions and the following disclaimer.
17 17 * 2. Redistributions in binary form must reproduce the above copyright
18 18 * notice, this list of conditions and the following disclaimer in the
19 19 * documentation and/or other materials provided with the distribution.
20 20 * 3. All advertising materials mentioning features or use of this software
21 21 * must display the following acknowledgement:
22 22 * This product includes software developed by the University of
23 23 * California, Berkeley and its contributors.
24 24 * 4. Neither the name of the University nor the names of its contributors
25 25 * may be used to endorse or promote products derived from this software
26 26 * without specific prior written permission.
27 27 *
28 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 38 * SUCH DAMAGE.
39 39 */
40 40
41 41
42 42 /*
43 43 * arp - display, set, and delete arp table entries
44 44 */
45 45
46 46 #include <stdio.h>
47 47 #include <sys/types.h>
48 48 #include <sys/socket.h>
49 49 #include <netinet/in.h>
50 50 #include <sys/ioctl.h>
51 51 #include <errno.h>
52 52 #include <netdb.h>
53 53 #include <net/if.h>
54 54 #include <net/if_arp.h>
55 55 #include <stdlib.h>
56 56 #include <unistd.h>
57 57 #include <string.h>
58 58 #include <arpa/inet.h>
59 59 #include <net/if_types.h>
60 60 #include <net/if_dl.h>
61 61 #include <zone.h>
62 62
63 63 static int file(char *);
64 64 static int set(int, char *[]);
65 65 static void get(char *);
66 66 static void delete(char *);
67 67 static void usage(void);
68 68
69 69 int
70 70 main(int argc, char *argv[])
71 71 {
72 72 int c, nflags = 0, argsleft;
73 73 int n_flag, a_flag, d_flag, f_flag, s_flag;
74 74
75 75 n_flag = a_flag = d_flag = f_flag = s_flag = 0;
76 76
77 77 #define CASE(x, y) \
78 78 case x: \
79 79 if (nflags > 0) { \
80 80 usage(); \
81 81 exit(1); \
82 82 } else \
83 83 y##_flag = 1; \
84 84 nflags++; \
85 85 break
86 86
87 87 while ((c = getopt(argc, argv, "nadfs")) != EOF) {
88 88 switch (c) {
89 89 case '?':
90 90 usage();
91 91 exit(1);
92 92 /* NOTREACHED */
93 93 break;
94 94 case 'n':
95 95 n_flag = 1;
96 96 break;
97 97 CASE('a', a);
98 98 CASE('d', d);
99 99 CASE('f', f);
100 100 CASE('s', s);
101 101 }
102 102 }
103 103
104 104 #undef CASE
105 105
106 106 /*
107 107 * -n only allowed with -a
108 108 */
109 109 if (n_flag && !a_flag) {
110 110 usage();
111 111 exit(1);
112 112 }
113 113
114 114 argsleft = argc - optind;
115 115
116 116 if (a_flag && (argsleft == 0)) {
117 117 /*
118 118 * the easiest way to get the complete arp table
|
↓ open down ↓ |
118 lines elided |
↑ open up ↑ |
119 119 * is to let netstat, which prints it as part of
120 120 * the MIB statistics, do it.
121 121 */
122 122 char netstat_path[MAXPATHLEN];
123 123 const char *zroot = zone_get_nroot();
124 124 (void) snprintf(netstat_path, sizeof (netstat_path), "%s%s", zroot != NULL ?
125 125 zroot : "", "/usr/bin/netstat");
126 126 (void) execl(netstat_path, "netstat",
127 127 (n_flag ? "-np" : "-p"),
128 128 "-f", "inet", (char *)0);
129 - (void) fprintf(stderr, "failed to exec netstat: %s\n",
130 - strerror(errno));
129 + (void) fprintf(stderr, "failed to exec %s: %s\n",
130 + netstat_path, strerror(errno));
131 131 exit(1);
132 132
133 133 } else if (s_flag && (argsleft >= 2)) {
134 134 if (set(argsleft, &argv[optind]) != 0)
135 135 exit(1);
136 136
137 137 } else if (d_flag && (argsleft == 1)) {
138 138 delete(argv[optind]);
139 139
140 140 } else if (f_flag && (argsleft == 1)) {
141 141 if (file(argv[optind]) != 0)
142 142 exit(1);
143 143
144 144 } else if ((nflags == 0) && (argsleft == 1)) {
145 145 get(argv[optind]);
146 146
147 147 } else {
148 148 usage();
149 149 exit(1);
150 150 }
151 151 return (0);
152 152 }
153 153
154 154 /*
155 155 * Process a file to set standard arp entries
156 156 */
157 157 static int
158 158 file(char *name)
159 159 {
160 160 /*
161 161 * A line of input can be:
162 162 * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] ["permanent"]
163 163 */
164 164 #define MAX_LINE_LEN (MAXHOSTNAMELEN + \
165 165 sizeof (" xx:xx:xx:xx:xx:xx temp pub trail permanent\n"))
166 166 #define MIN_ARGS 2
167 167 #define MAX_ARGS 5
168 168
169 169 FILE *fp;
170 170 char line[MAX_LINE_LEN];
171 171 int retval;
172 172
173 173 if ((fp = fopen(name, "r")) == NULL) {
174 174 (void) fprintf(stderr, "arp: cannot open %s\n", name);
175 175 exit(1);
176 176 }
177 177
178 178 retval = 0;
179 179 while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
180 180 char line_copy[MAX_LINE_LEN];
181 181 char *args[MAX_ARGS];
182 182 char *start;
183 183 int i;
184 184
185 185 /*
186 186 * Keep a copy of the un-altered line for error
187 187 * reporting.
188 188 */
189 189 (void) strlcpy(line_copy, line, MAX_LINE_LEN);
190 190
191 191 start = line_copy;
192 192 for (i = 0; i < MAX_ARGS; i++) {
193 193 if ((args[i] = strtok(start, " \t\n")) == NULL)
194 194 break;
195 195
196 196 start = NULL;
197 197 }
198 198
199 199 if (i < MIN_ARGS) {
200 200 (void) fprintf(stderr, "arp: bad line: %s\n",
201 201 line);
202 202 retval = 1;
203 203 continue;
204 204 }
205 205
206 206 if (set(i, args) != 0)
207 207 retval = 1;
208 208 }
209 209
210 210 #undef MAX_LINE_LEN
211 211 #undef MIN_ARGS
212 212 #undef MAX_ARGS
213 213
214 214 (void) fclose(fp);
215 215 return (retval);
216 216 }
217 217
218 218 /*
219 219 * Set an individual arp entry
220 220 */
221 221 static int
222 222 set(int argc, char *argv[])
223 223 {
224 224 struct xarpreq ar;
225 225 struct hostent *hp;
226 226 struct sockaddr_in *sin;
227 227 uchar_t *ea;
228 228 int s;
229 229 char *host = argv[0], *eaddr = argv[1];
230 230
231 231 argc -= 2;
232 232 argv += 2;
233 233 (void) memset(&ar, 0, sizeof (ar));
234 234 sin = (struct sockaddr_in *)&ar.xarp_pa;
235 235 sin->sin_family = AF_INET;
236 236 sin->sin_addr.s_addr = inet_addr(host);
237 237 if (sin->sin_addr.s_addr == (in_addr_t)-1) {
238 238 hp = gethostbyname(host);
239 239 if (hp == NULL) {
240 240 (void) fprintf(stderr, "arp: %s: unknown host\n",
241 241 host);
242 242 return (1);
243 243 }
244 244 (void) memcpy(&sin->sin_addr, hp->h_addr,
245 245 sizeof (sin->sin_addr));
246 246 }
247 247 ea = _link_aton(eaddr, &s);
248 248 if (ea == NULL) {
249 249 if (s == -1) {
250 250 (void) fprintf(stderr,
251 251 "arp: invalid link layer address '%s'\n", eaddr);
252 252 return (1);
253 253 }
254 254 perror("arp: nomem");
255 255 exit(1);
256 256 }
257 257 ar.xarp_ha.sdl_alen = s;
258 258 (void) memcpy(LLADDR(&ar.xarp_ha), ea, ar.xarp_ha.sdl_alen);
259 259 free(ea);
260 260 ar.xarp_ha.sdl_family = AF_LINK;
261 261 ar.xarp_flags = ATF_PERM;
262 262 while (argc-- > 0) {
263 263 if (strncmp(argv[0], "temp", 4) == 0) {
264 264 ar.xarp_flags &= ~ATF_PERM;
265 265 } else if (strncmp(argv[0], "pub", 3) == 0) {
266 266 ar.xarp_flags |= ATF_PUBL;
267 267 } else if (strncmp(argv[0], "trail", 5) == 0) {
268 268 ar.xarp_flags |= ATF_USETRAILERS;
269 269 } else if (strcmp(argv[0], "permanent") == 0) {
270 270 ar.xarp_flags |= ATF_AUTHORITY;
271 271 } else {
272 272 (void) fprintf(stderr,
273 273 "arp: unknown keyword '%s'\n", argv[0]);
274 274 return (1);
275 275 }
276 276 argv++;
277 277 }
278 278
279 279 if ((ar.xarp_flags & (ATF_PERM|ATF_AUTHORITY)) == ATF_AUTHORITY) {
280 280 (void) fprintf(stderr, "arp: 'temp' and 'permanent' flags are "
281 281 "not usable together.\n");
282 282 return (1);
283 283 }
284 284
285 285 s = socket(AF_INET, SOCK_DGRAM, 0);
286 286 if (s < 0) {
287 287 perror("arp: socket");
288 288 exit(1);
289 289 }
290 290 if (ioctl(s, SIOCSXARP, (caddr_t)&ar) < 0) {
291 291 perror(host);
292 292 exit(1);
293 293 }
294 294 (void) close(s);
295 295 return (0);
296 296 }
297 297
298 298 /*
299 299 * Display an individual arp entry
300 300 */
301 301 static void
302 302 get(char *host)
303 303 {
304 304 struct xarpreq ar;
305 305 struct hostent *hp;
306 306 struct sockaddr_in *sin;
307 307 uchar_t *ea;
308 308 int s;
309 309 char *str = NULL;
310 310
311 311 (void) memset(&ar, 0, sizeof (ar));
312 312 sin = (struct sockaddr_in *)&ar.xarp_pa;
313 313 sin->sin_family = AF_INET;
314 314 sin->sin_addr.s_addr = inet_addr(host);
315 315 if (sin->sin_addr.s_addr == (in_addr_t)-1) {
316 316 hp = gethostbyname(host);
317 317 if (hp == NULL) {
318 318 (void) fprintf(stderr, "arp: %s: unknown host\n",
319 319 host);
320 320 exit(1);
321 321 }
322 322 (void) memcpy(&sin->sin_addr, hp->h_addr,
323 323 sizeof (sin->sin_addr));
324 324 }
325 325 s = socket(AF_INET, SOCK_DGRAM, 0);
326 326 if (s < 0) {
327 327 perror("arp: socket");
328 328 exit(1);
329 329 }
330 330 ar.xarp_ha.sdl_family = AF_LINK;
331 331 if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) {
332 332 if (errno == ENXIO)
333 333 (void) printf("%s (%s) -- no entry\n",
334 334 host, inet_ntoa(sin->sin_addr));
335 335 else
336 336 perror("SIOCGXARP");
337 337 exit(1);
338 338 }
339 339 (void) close(s);
340 340 ea = (uchar_t *)LLADDR(&ar.xarp_ha);
341 341 if (ar.xarp_flags & ATF_COM) {
342 342 str = _link_ntoa(ea, str, ar.xarp_ha.sdl_alen, IFT_OTHER);
343 343 if (str != NULL) {
344 344 (void) printf("%s (%s) at %s", host,
345 345 inet_ntoa(sin->sin_addr), str);
346 346 free(str);
347 347 } else {
348 348 perror("arp: nomem");
349 349 exit(1);
350 350 }
351 351 } else {
352 352 (void) printf("%s (%s) at (incomplete)", host,
353 353 inet_ntoa(sin->sin_addr));
354 354 }
355 355 if (!(ar.xarp_flags & ATF_PERM))
356 356 (void) printf(" temp");
357 357 if (ar.xarp_flags & ATF_PUBL)
358 358 (void) printf(" pub");
359 359 if (ar.xarp_flags & ATF_USETRAILERS)
360 360 (void) printf(" trail");
361 361 if (ar.xarp_flags & ATF_AUTHORITY)
362 362 (void) printf(" permanent");
363 363 (void) printf("\n");
364 364 }
365 365
366 366 /*
367 367 * Delete an arp entry
368 368 */
369 369 static void
370 370 delete(char *host)
371 371 {
372 372 struct xarpreq ar;
373 373 struct hostent *hp;
374 374 struct sockaddr_in *sin;
375 375 int s;
376 376
377 377 (void) memset(&ar, 0, sizeof (ar));
378 378 sin = (struct sockaddr_in *)&ar.xarp_pa;
379 379 sin->sin_family = AF_INET;
380 380 sin->sin_addr.s_addr = inet_addr(host);
381 381 if (sin->sin_addr.s_addr == (in_addr_t)-1) {
382 382 hp = gethostbyname(host);
383 383 if (hp == NULL) {
384 384 (void) fprintf(stderr, "arp: %s: unknown host\n",
385 385 host);
386 386 exit(1);
387 387 }
388 388 (void) memcpy(&sin->sin_addr, hp->h_addr,
389 389 sizeof (sin->sin_addr));
390 390 }
391 391 s = socket(AF_INET, SOCK_DGRAM, 0);
392 392 if (s < 0) {
393 393 perror("arp: socket");
394 394 exit(1);
395 395 }
396 396 ar.xarp_ha.sdl_family = AF_LINK;
397 397 if (ioctl(s, SIOCDXARP, (caddr_t)&ar) < 0) {
398 398 if (errno == ENXIO)
399 399 (void) printf("%s (%s) -- no entry\n",
400 400 host, inet_ntoa(sin->sin_addr));
401 401 else
402 402 perror("SIOCDXARP");
403 403 exit(1);
404 404 }
405 405 (void) close(s);
406 406 (void) printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
407 407 }
408 408
409 409 static void
410 410 usage(void)
411 411 {
412 412 (void) printf("Usage: arp hostname\n");
413 413 (void) printf(" arp -a [-n]\n");
414 414 (void) printf(" arp -d hostname\n");
415 415 (void) printf(" arp -s hostname ether_addr "
416 416 "[temp] [pub] [trail] [permanent]\n");
417 417 (void) printf(" arp -f filename\n");
418 418 }
|
↓ open down ↓ |
278 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX