134918Sbostic /* 234918Sbostic * Copyright (c) 1984 Regents of the University of California. 334918Sbostic * All rights reserved. 434918Sbostic * 534918Sbostic * This code is derived from software contributed to Berkeley by 634918Sbostic * Sun Microsystems, Inc. 734918Sbostic * 834918Sbostic * Redistribution and use in source and binary forms are permitted 934918Sbostic * provided that the above copyright notice and this paragraph are 1034918Sbostic * duplicated in all such forms and that any documentation, 1134918Sbostic * advertising materials, and other materials related to such 1234918Sbostic * distribution and use acknowledge that the software was developed 1334918Sbostic * by the University of California, Berkeley. The name of the 1434918Sbostic * University may not be used to endorse or promote products derived 1534918Sbostic * from this software without specific prior written permission. 1634918Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1734918Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1834918Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1934918Sbostic */ 2034918Sbostic 2116255Skarels #ifndef lint 2234918Sbostic char copyright[] = 2334918Sbostic "@(#) Copyright (c) 1984 Regents of the University of California.\n\ 2434918Sbostic All rights reserved.\n"; 2534918Sbostic #endif /* not lint */ 2616255Skarels 2734918Sbostic #ifndef lint 28*35778Sbostic static char sccsid[] = "@(#)arp.c 5.8 (Berkeley) 10/10/88"; 2934918Sbostic #endif /* not lint */ 3034918Sbostic 3116255Skarels /* 3216255Skarels * arp - display, set, and delete arp table entries 3316255Skarels */ 3416255Skarels 3533624Sbostic #include <machine/pte.h> 3633624Sbostic 3733624Sbostic #include <sys/param.h> 3833624Sbostic #include <sys/vmmac.h> 3933624Sbostic #include <sys/file.h> 4016255Skarels #include <sys/socket.h> 4116255Skarels #include <sys/ioctl.h> 4233624Sbostic 4316255Skarels #include <netdb.h> 4433624Sbostic #include <netinet/in.h> 4516255Skarels #include <net/if.h> 4616255Skarels #include <netinet/if_ether.h> 4716255Skarels 4833624Sbostic #include <errno.h> 4933624Sbostic #include <nlist.h> 5033624Sbostic #include <stdio.h> 5133624Sbostic 5216255Skarels extern int errno; 5333624Sbostic static int kflag; 5416255Skarels 5516255Skarels main(argc, argv) 5633624Sbostic int argc; 5716255Skarels char **argv; 5816255Skarels { 5933624Sbostic int ch; 6016255Skarels 6133624Sbostic while ((ch = getopt(argc, argv, "adsf")) != EOF) 6233624Sbostic switch((char)ch) { 6333624Sbostic case 'a': { 6433624Sbostic char *mem; 6533624Sbostic 6633624Sbostic if (argc > 4) 6733624Sbostic usage(); 6833624Sbostic if (argc == 4) { 6933624Sbostic kflag = 1; 7033624Sbostic mem = argv[3]; 7133624Sbostic } 7233624Sbostic else 7333624Sbostic mem = "/dev/kmem"; 7433624Sbostic dump((argc >= 3) ? argv[2] : "/vmunix", mem); 7533624Sbostic exit(0); 7633624Sbostic } 7733624Sbostic case 'd': 7833624Sbostic if (argc != 3) 7933624Sbostic usage(); 8033624Sbostic delete(argv[2]); 8133624Sbostic exit(0); 8233624Sbostic case 's': 8333624Sbostic if (argc < 4 || argc > 7) 8433624Sbostic usage(); 8533624Sbostic exit(set(argc-2, &argv[2]) ? 1 : 0); 8633624Sbostic case 'f': 8733624Sbostic if (argc != 3) 8833624Sbostic usage(); 8933624Sbostic exit (file(argv[2]) ? 1 : 0); 9033624Sbostic case '?': 9133624Sbostic default: 9233624Sbostic usage(); 9333624Sbostic } 9433624Sbostic if (argc != 2) 9533624Sbostic usage(); 9633624Sbostic get(argv[1]); 9733624Sbostic exit(0); 9816255Skarels } 9916255Skarels 10016255Skarels /* 10116255Skarels * Process a file to set standard arp entries 10216255Skarels */ 10316255Skarels file(name) 10416255Skarels char *name; 10516255Skarels { 10616255Skarels FILE *fp; 10733624Sbostic int i, retval; 10825788Skarels char line[100], arg[5][50], *args[5]; 10916255Skarels 11016255Skarels if ((fp = fopen(name, "r")) == NULL) { 11116255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 11216255Skarels exit(1); 11316255Skarels } 11416255Skarels args[0] = &arg[0][0]; 11516255Skarels args[1] = &arg[1][0]; 11616255Skarels args[2] = &arg[2][0]; 11716255Skarels args[3] = &arg[3][0]; 11825788Skarels args[4] = &arg[4][0]; 11932643Smckusick retval = 0; 12016255Skarels while(fgets(line, 100, fp) != NULL) { 12132643Smckusick i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 12232643Smckusick arg[3], arg[4]); 12316255Skarels if (i < 2) { 12416255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 12532643Smckusick retval = 1; 12616255Skarels continue; 12716255Skarels } 12832643Smckusick if (set(i, args)) 12932643Smckusick retval = 1; 13016255Skarels } 13116255Skarels fclose(fp); 13232643Smckusick return (retval); 13316255Skarels } 13416255Skarels 13516255Skarels /* 13616255Skarels * Set an individual arp entry 13716255Skarels */ 13816255Skarels set(argc, argv) 13933624Sbostic int argc; 14016255Skarels char **argv; 14116255Skarels { 14216255Skarels struct arpreq ar; 14316255Skarels struct hostent *hp; 14416255Skarels struct sockaddr_in *sin; 14521393Skarels u_char *ea; 14616255Skarels int s; 14716255Skarels char *host = argv[0], *eaddr = argv[1]; 14816255Skarels 14916255Skarels argc -= 2; 15016255Skarels argv += 2; 15116255Skarels bzero((caddr_t)&ar, sizeof ar); 15216255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 15326314Skarels sin->sin_family = AF_INET; 15426314Skarels sin->sin_addr.s_addr = inet_addr(host); 15526314Skarels if (sin->sin_addr.s_addr == -1) { 156*35778Sbostic if (!(hp = gethostbyname(host))) { 157*35778Sbostic fprintf(stderr, "arp: %s: ", host); 158*35778Sbostic herror((char *)NULL); 15932643Smckusick return (1); 16026314Skarels } 16126314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 16226314Skarels sizeof sin->sin_addr); 16326314Skarels } 16421393Skarels ea = (u_char *)ar.arp_ha.sa_data; 16516255Skarels if (ether_aton(eaddr, ea)) 16632643Smckusick return (1); 16716255Skarels ar.arp_flags = ATF_PERM; 16826314Skarels while (argc-- > 0) { 16916255Skarels if (strncmp(argv[0], "temp", 4) == 0) 17016255Skarels ar.arp_flags &= ~ATF_PERM; 17133624Sbostic else if (strncmp(argv[0], "pub", 3) == 0) 17216255Skarels ar.arp_flags |= ATF_PUBL; 17333624Sbostic else if (strncmp(argv[0], "trail", 5) == 0) 17425788Skarels ar.arp_flags |= ATF_USETRAILERS; 17516255Skarels argv++; 17616255Skarels } 17716255Skarels 17816255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 17916255Skarels if (s < 0) { 18033624Sbostic perror("arp: socket"); 18133624Sbostic exit(1); 18233624Sbostic } 18316255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 18416255Skarels perror(host); 18516255Skarels exit(1); 18616255Skarels } 18716255Skarels close(s); 18832643Smckusick return (0); 18916255Skarels } 19016255Skarels 19116255Skarels /* 19216255Skarels * Display an individual arp entry 19316255Skarels */ 19416255Skarels get(host) 19516255Skarels char *host; 19616255Skarels { 19716255Skarels struct arpreq ar; 19816255Skarels struct hostent *hp; 19916255Skarels struct sockaddr_in *sin; 20021393Skarels u_char *ea; 20116255Skarels int s; 20233624Sbostic char *inet_ntoa(); 20316255Skarels 20416255Skarels bzero((caddr_t)&ar, sizeof ar); 20516255Skarels ar.arp_pa.sa_family = AF_INET; 20616255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 20726314Skarels sin->sin_family = AF_INET; 20826314Skarels sin->sin_addr.s_addr = inet_addr(host); 20926314Skarels if (sin->sin_addr.s_addr == -1) { 210*35778Sbostic if (!(hp = gethostbyname(host))) { 211*35778Sbostic fprintf(stderr, "arp: %s: ", host); 212*35778Sbostic herror((char *)NULL); 21326314Skarels exit(1); 21426314Skarels } 21526314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 21626314Skarels sizeof sin->sin_addr); 21726314Skarels } 21816255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 21916255Skarels if (s < 0) { 22033624Sbostic perror("arp: socket"); 22133624Sbostic exit(1); 22233624Sbostic } 22316255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 22416255Skarels if (errno == ENXIO) 22516255Skarels printf("%s (%s) -- no entry\n", 22616255Skarels host, inet_ntoa(sin->sin_addr)); 22716255Skarels else 22816255Skarels perror("SIOCGARP"); 22916255Skarels exit(1); 23016255Skarels } 23116255Skarels close(s); 23221393Skarels ea = (u_char *)ar.arp_ha.sa_data; 23316255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 23416255Skarels if (ar.arp_flags & ATF_COM) 23516255Skarels ether_print(ea); 23616255Skarels else 23716255Skarels printf("(incomplete)"); 23833624Sbostic if (ar.arp_flags & ATF_PERM) 23933624Sbostic printf(" permanent"); 24033624Sbostic if (ar.arp_flags & ATF_PUBL) 24133624Sbostic printf(" published"); 24233624Sbostic if (ar.arp_flags & ATF_USETRAILERS) 24333624Sbostic printf(" trailers"); 24416255Skarels printf("\n"); 24516255Skarels } 24616255Skarels 24716255Skarels /* 24816255Skarels * Delete an arp entry 24916255Skarels */ 25016255Skarels delete(host) 25116255Skarels char *host; 25216255Skarels { 25316255Skarels struct arpreq ar; 25416255Skarels struct hostent *hp; 25516255Skarels struct sockaddr_in *sin; 25616255Skarels int s; 25716255Skarels 25816255Skarels bzero((caddr_t)&ar, sizeof ar); 25916255Skarels ar.arp_pa.sa_family = AF_INET; 26016255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 26126314Skarels sin->sin_family = AF_INET; 26226314Skarels sin->sin_addr.s_addr = inet_addr(host); 26326314Skarels if (sin->sin_addr.s_addr == -1) { 264*35778Sbostic if (!(hp = gethostbyname(host))) { 265*35778Sbostic fprintf(stderr, "arp: %s: ", host); 266*35778Sbostic herror((char *)NULL); 26726314Skarels exit(1); 26826314Skarels } 26926314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 27026314Skarels sizeof sin->sin_addr); 27126314Skarels } 27216255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 27316255Skarels if (s < 0) { 27433624Sbostic perror("arp: socket"); 27533624Sbostic exit(1); 27633624Sbostic } 27716255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 27816255Skarels if (errno == ENXIO) 27916255Skarels printf("%s (%s) -- no entry\n", 28016255Skarels host, inet_ntoa(sin->sin_addr)); 28116255Skarels else 28216255Skarels perror("SIOCDARP"); 28316255Skarels exit(1); 28416255Skarels } 28516255Skarels close(s); 28616255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 28716255Skarels } 28816255Skarels 28916255Skarels struct nlist nl[] = { 29016255Skarels #define X_ARPTAB 0 29116255Skarels { "_arptab" }, 29216255Skarels #define X_ARPTAB_SIZE 1 29316255Skarels { "_arptab_size" }, 29433624Sbostic #define N_SYSMAP 2 29533624Sbostic { "_Sysmap" }, 29633624Sbostic #define N_SYSSIZE 3 29733624Sbostic { "_Syssize" }, 29816255Skarels { "" }, 29916255Skarels }; 30016255Skarels 30133624Sbostic static struct pte *Sysmap; 30233624Sbostic 30316255Skarels /* 30416255Skarels * Dump the entire arp table 30516255Skarels */ 30616255Skarels dump(kernel, mem) 30716255Skarels char *kernel, *mem; 30816255Skarels { 30933624Sbostic extern int h_errno; 31016255Skarels struct arptab *at; 31116255Skarels struct hostent *hp; 31233624Sbostic int bynumber, mf, arptab_size, sz; 31333624Sbostic char *host, *malloc(); 31433624Sbostic off_t lseek(); 31516255Skarels 31633624Sbostic if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) { 31716255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 31816255Skarels exit(1); 31916255Skarels } 32033624Sbostic mf = open(mem, O_RDONLY); 32133624Sbostic if (mf < 0) { 32235377Sbostic fprintf(stderr, "arp: cannot open %s\n", mem); 32316255Skarels exit(1); 32416255Skarels } 32533624Sbostic if (kflag) { 32633624Sbostic off_t off; 32733624Sbostic 32833624Sbostic Sysmap = (struct pte *) 32933624Sbostic malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 33033624Sbostic if (!Sysmap) { 33133624Sbostic fputs("arp: can't get memory for Sysmap.\n", stderr); 33233624Sbostic exit(1); 33333624Sbostic } 33433624Sbostic off = nl[N_SYSMAP].n_value & ~KERNBASE; 33533624Sbostic (void)lseek(mf, off, L_SET); 33633624Sbostic (void)read(mf, (char *)Sysmap, 33733624Sbostic (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 33833624Sbostic } 33933624Sbostic klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET); 34016255Skarels read(mf, &arptab_size, sizeof arptab_size); 34133624Sbostic if (arptab_size <= 0 || arptab_size > 1000) { 34216255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 34316255Skarels exit(1); 34416255Skarels } 34516255Skarels sz = arptab_size * sizeof (struct arptab); 34633624Sbostic at = (struct arptab *)malloc((u_int)sz); 34716255Skarels if (at == NULL) { 34833624Sbostic fputs("arp: can't get memory for arptab.\n", stderr); 34916255Skarels exit(1); 35016255Skarels } 35133624Sbostic klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET); 35216255Skarels if (read(mf, (char *)at, sz) != sz) { 35316255Skarels perror("arp: error reading arptab"); 35416255Skarels exit(1); 35516255Skarels } 35616255Skarels close(mf); 35733624Sbostic for (bynumber = 0; arptab_size-- > 0; at++) { 35816255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 35916255Skarels continue; 36026314Skarels if (bynumber == 0) 36126314Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, 36226314Skarels sizeof at->at_iaddr, AF_INET); 36326314Skarels else 36426314Skarels hp = 0; 36516255Skarels if (hp) 36616255Skarels host = hp->h_name; 36726314Skarels else { 36816255Skarels host = "?"; 36926314Skarels if (h_errno == TRY_AGAIN) 37026314Skarels bynumber = 1; 37126314Skarels } 37216255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 37316255Skarels if (at->at_flags & ATF_COM) 37421393Skarels ether_print(at->at_enaddr); 37516255Skarels else 37616255Skarels printf("(incomplete)"); 37733624Sbostic if (at->at_flags & ATF_PERM) 37833624Sbostic printf(" permanent"); 37933624Sbostic if (at->at_flags & ATF_PUBL) 38033624Sbostic printf(" published"); 38133624Sbostic if (at->at_flags & ATF_USETRAILERS) 38233624Sbostic printf(" trailers"); 38316255Skarels printf("\n"); 38416255Skarels } 38516255Skarels } 38616255Skarels 38733624Sbostic /* 38833624Sbostic * Seek into the kernel for a value. 38933624Sbostic */ 39033624Sbostic klseek(fd, base, off) 39133624Sbostic int fd, off; 39233624Sbostic off_t base; 39333624Sbostic { 39433624Sbostic off_t lseek(); 39533624Sbostic 39633624Sbostic if (kflag) { /* get kernel pte */ 39733624Sbostic base &= ~KERNBASE; 39833624Sbostic base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 39933624Sbostic } 40033624Sbostic (void)lseek(fd, base, off); 40133624Sbostic } 40233624Sbostic 40321393Skarels ether_print(cp) 40421393Skarels u_char *cp; 40516255Skarels { 40616255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 40716255Skarels } 40816255Skarels 40916255Skarels ether_aton(a, n) 41016255Skarels char *a; 41121393Skarels u_char *n; 41216255Skarels { 41316255Skarels int i, o[6]; 41416255Skarels 41516255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 41616255Skarels &o[3], &o[4], &o[5]); 41716255Skarels if (i != 6) { 41816255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 41916255Skarels return (1); 42016255Skarels } 42116255Skarels for (i=0; i<6; i++) 42221393Skarels n[i] = o[i]; 42316255Skarels return (0); 42416255Skarels } 42516255Skarels 42616255Skarels usage() 42716255Skarels { 42833624Sbostic printf("usage: arp hostname\n"); 42916255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 43016255Skarels printf(" arp -d hostname\n"); 43132643Smckusick printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n"); 43216255Skarels printf(" arp -f filename\n"); 43333624Sbostic exit(1); 43416255Skarels } 435