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