1 /* 2 * Copyright (c) 1984 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Sun Microsystems, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 char copyright[] = 39 "@(#) Copyright (c) 1984 Regents of the University of California.\n\ 40 All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 static char sccsid[] = "@(#)arp.c 5.11.1.1 (Berkeley) 7/22/91"; 45 #endif /* not lint */ 46 47 /* 48 * arp - display, set, and delete arp table entries 49 */ 50 51 #include <sys/param.h> 52 #include <sys/file.h> 53 #include <sys/socket.h> 54 #include <sys/ioctl.h> 55 56 #include <netdb.h> 57 #include <netinet/in.h> 58 #include <net/if.h> 59 #include <netinet/if_ether.h> 60 #include <arpa/inet.h> 61 62 #include <errno.h> 63 #include <nlist.h> 64 #include <kvm.h> 65 #include <stdio.h> 66 #include <paths.h> 67 68 extern int errno; 69 70 main(argc, argv) 71 int argc; 72 char **argv; 73 { 74 int ch; 75 76 while ((ch = getopt(argc, argv, "adsf")) != EOF) 77 switch((char)ch) { 78 case 'a': { 79 char *mem = 0; 80 81 if (argc > 4) 82 usage(); 83 if (argc == 4) { 84 mem = argv[3]; 85 } 86 dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem); 87 exit(0); 88 } 89 case 'd': 90 if (argc != 3) 91 usage(); 92 delete(argv[2]); 93 exit(0); 94 case 's': 95 if (argc < 4 || argc > 7) 96 usage(); 97 exit(set(argc-2, &argv[2]) ? 1 : 0); 98 case 'f': 99 if (argc != 3) 100 usage(); 101 exit (file(argv[2]) ? 1 : 0); 102 case '?': 103 default: 104 usage(); 105 } 106 if (argc != 2) 107 usage(); 108 get(argv[1]); 109 exit(0); 110 } 111 112 /* 113 * Process a file to set standard arp entries 114 */ 115 file(name) 116 char *name; 117 { 118 FILE *fp; 119 int i, retval; 120 char line[100], arg[5][50], *args[5]; 121 122 if ((fp = fopen(name, "r")) == NULL) { 123 fprintf(stderr, "arp: cannot open %s\n", name); 124 exit(1); 125 } 126 args[0] = &arg[0][0]; 127 args[1] = &arg[1][0]; 128 args[2] = &arg[2][0]; 129 args[3] = &arg[3][0]; 130 args[4] = &arg[4][0]; 131 retval = 0; 132 while(fgets(line, 100, fp) != NULL) { 133 i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 134 arg[3], arg[4]); 135 if (i < 2) { 136 fprintf(stderr, "arp: bad line: %s\n", line); 137 retval = 1; 138 continue; 139 } 140 if (set(i, args)) 141 retval = 1; 142 } 143 fclose(fp); 144 return (retval); 145 } 146 147 /* 148 * Set an individual arp entry 149 */ 150 set(argc, argv) 151 int argc; 152 char **argv; 153 { 154 struct arpreq ar; 155 struct hostent *hp; 156 struct sockaddr_in *sin; 157 u_char *ea; 158 int s; 159 char *host = argv[0], *eaddr = argv[1]; 160 161 argc -= 2; 162 argv += 2; 163 bzero((caddr_t)&ar, sizeof ar); 164 sin = (struct sockaddr_in *)&ar.arp_pa; 165 sin->sin_family = AF_INET; 166 sin->sin_addr.s_addr = inet_addr(host); 167 if (sin->sin_addr.s_addr == -1) { 168 if (!(hp = gethostbyname(host))) { 169 fprintf(stderr, "arp: %s: ", host); 170 herror((char *)NULL); 171 return (1); 172 } 173 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 174 sizeof sin->sin_addr); 175 } 176 ea = (u_char *)ar.arp_ha.sa_data; 177 if (ether_aton(eaddr, ea)) 178 return (1); 179 ar.arp_flags = ATF_PERM; 180 while (argc-- > 0) { 181 if (strncmp(argv[0], "temp", 4) == 0) 182 ar.arp_flags &= ~ATF_PERM; 183 else if (strncmp(argv[0], "pub", 3) == 0) 184 ar.arp_flags |= ATF_PUBL; 185 else if (strncmp(argv[0], "trail", 5) == 0) 186 ar.arp_flags |= ATF_USETRAILERS; 187 argv++; 188 } 189 190 s = socket(AF_INET, SOCK_DGRAM, 0); 191 if (s < 0) { 192 perror("arp: socket"); 193 exit(1); 194 } 195 if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 196 perror(host); 197 exit(1); 198 } 199 close(s); 200 return (0); 201 } 202 203 /* 204 * Display an individual arp entry 205 */ 206 get(host) 207 char *host; 208 { 209 struct arpreq ar; 210 struct hostent *hp; 211 struct sockaddr_in *sin; 212 u_char *ea; 213 int s; 214 215 bzero((caddr_t)&ar, sizeof ar); 216 ar.arp_pa.sa_family = AF_INET; 217 sin = (struct sockaddr_in *)&ar.arp_pa; 218 sin->sin_family = AF_INET; 219 sin->sin_addr.s_addr = inet_addr(host); 220 if (sin->sin_addr.s_addr == -1) { 221 if (!(hp = gethostbyname(host))) { 222 fprintf(stderr, "arp: %s: ", host); 223 herror((char *)NULL); 224 exit(1); 225 } 226 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 227 sizeof sin->sin_addr); 228 } 229 s = socket(AF_INET, SOCK_DGRAM, 0); 230 if (s < 0) { 231 perror("arp: socket"); 232 exit(1); 233 } 234 if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 235 if (errno == ENXIO) 236 printf("%s (%s) -- no entry\n", 237 host, inet_ntoa(sin->sin_addr)); 238 else 239 perror("SIOCGARP"); 240 exit(1); 241 } 242 close(s); 243 ea = (u_char *)ar.arp_ha.sa_data; 244 printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 245 if (ar.arp_flags & ATF_COM) 246 ether_print(ea); 247 else 248 printf("(incomplete)"); 249 if (ar.arp_flags & ATF_PERM) 250 printf(" permanent"); 251 if (ar.arp_flags & ATF_PUBL) 252 printf(" published"); 253 if (ar.arp_flags & ATF_USETRAILERS) 254 printf(" trailers"); 255 printf("\n"); 256 } 257 258 /* 259 * Delete an arp entry 260 */ 261 delete(host) 262 char *host; 263 { 264 struct arpreq ar; 265 struct hostent *hp; 266 struct sockaddr_in *sin; 267 int s; 268 269 bzero((caddr_t)&ar, sizeof ar); 270 ar.arp_pa.sa_family = AF_INET; 271 sin = (struct sockaddr_in *)&ar.arp_pa; 272 sin->sin_family = AF_INET; 273 sin->sin_addr.s_addr = inet_addr(host); 274 if (sin->sin_addr.s_addr == -1) { 275 if (!(hp = gethostbyname(host))) { 276 fprintf(stderr, "arp: %s: ", host); 277 herror((char *)NULL); 278 exit(1); 279 } 280 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 281 sizeof sin->sin_addr); 282 } 283 s = socket(AF_INET, SOCK_DGRAM, 0); 284 if (s < 0) { 285 perror("arp: socket"); 286 exit(1); 287 } 288 if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 289 if (errno == ENXIO) 290 printf("%s (%s) -- no entry\n", 291 host, inet_ntoa(sin->sin_addr)); 292 else 293 perror("SIOCDARP"); 294 exit(1); 295 } 296 close(s); 297 printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 298 } 299 300 struct nlist nl[] = { 301 #define X_ARPTAB 0 302 { "_arptab" }, 303 #define X_ARPTAB_SIZE 1 304 { "_arptab_size" }, 305 { "" }, 306 }; 307 308 /* 309 * Dump the entire arp table 310 */ 311 dump(kernel, mem) 312 char *kernel, *mem; 313 { 314 extern int h_errno; 315 struct arptab *at; 316 struct hostent *hp; 317 int bynumber, mf, arptab_size, sz; 318 char *host, *malloc(); 319 off_t lseek(); 320 321 if (kvm_openfiles(kernel, mem, NULL) == -1) { 322 fprintf(stderr, "arp: kvm_openfiles: %s\n", kvm_geterr()); 323 exit(1); 324 } 325 if (kvm_nlist(nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) { 326 fprintf(stderr, "arp: %s: bad namelist\n", kernel); 327 exit(1); 328 } 329 if (kvm_read((void *)(nl[X_ARPTAB_SIZE].n_value), 330 &arptab_size, sizeof arptab_size) == -1 || 331 arptab_size <= 0 || arptab_size > 1000) { 332 fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 333 exit(1); 334 } 335 sz = arptab_size * sizeof (struct arptab); 336 at = (struct arptab *)malloc((u_int)sz); 337 if (at == NULL) { 338 fputs("arp: can't get memory for arptab.\n", stderr); 339 exit(1); 340 } 341 if (kvm_read((void *)(nl[X_ARPTAB].n_value), (char *)at, sz) == -1) { 342 perror("arp: error reading arptab"); 343 exit(1); 344 } 345 for (bynumber = 0; arptab_size-- > 0; at++) { 346 if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 347 continue; 348 if (bynumber == 0) 349 hp = gethostbyaddr((caddr_t)&at->at_iaddr, 350 sizeof at->at_iaddr, AF_INET); 351 else 352 hp = 0; 353 if (hp) 354 host = hp->h_name; 355 else { 356 host = "?"; 357 if (h_errno == TRY_AGAIN) 358 bynumber = 1; 359 } 360 printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 361 if (at->at_flags & ATF_COM) 362 ether_print(at->at_enaddr); 363 else 364 printf("(incomplete)"); 365 if (at->at_flags & ATF_PERM) 366 printf(" permanent"); 367 if (at->at_flags & ATF_PUBL) 368 printf(" published"); 369 if (at->at_flags & ATF_USETRAILERS) 370 printf(" trailers"); 371 printf("\n"); 372 } 373 } 374 375 ether_print(cp) 376 u_char *cp; 377 { 378 printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 379 } 380 381 ether_aton(a, n) 382 char *a; 383 u_char *n; 384 { 385 int i, o[6]; 386 387 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 388 &o[3], &o[4], &o[5]); 389 if (i != 6) { 390 fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 391 return (1); 392 } 393 for (i=0; i<6; i++) 394 n[i] = o[i]; 395 return (0); 396 } 397 398 usage() 399 { 400 printf("usage: arp hostname\n"); 401 printf(" arp -a [kernel] [kernel_memory]\n"); 402 printf(" arp -d hostname\n"); 403 printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n"); 404 printf(" arp -f filename\n"); 405 exit(1); 406 } 407