25-Oct-85 16:15:29-MDT,6354;000000000001 Return-Path: Received: from BRL-TGR.ARPA by SIMTEL20.ARPA with TCP; Fri 25 Oct 85 16:15:05-MDT Received: from usenet by TGR.BRL.ARPA id a009691; 25 Oct 85 17:40 EDT From: Dennis Bednar Newsgroups: net.unix-wizards,net.sources Subject: RE: Ethernet Problems Message-ID: <809@rlgvax.UUCP> Date: 25 Oct 85 05:51:26 GMT Xref: seismo net.unix-wizards:15493 net.sources:3725 To: unix-sources@BRL-TGR.ARPA The arpdump.c program posted by Barry Shien, has been enhanced to also print Timer and Flags for the ARP entries. All of the mods I made are ifdefed by CCI and DPB. Here is the new version: -------------- arpdump.c --------------------- #define CCI /* CCI needs this because of nlist() problems */ #define DPB /* new personal mods added to the original */ #ifdef DPB /* * arpdump.c * Barry Shein, Boston University original 10 21 85 * Dennis Bednar, CCI Reston VA, added options, Timer, Flags, 10 25 85 * * usage: arpdump [-a] [-v] [seconds] * -a = print old timed-out slots too * ie slots containing non-zero etheraddr && IP addr == 0 * -v = verbose, prints every entry in the table * seconds = decimal seconds to print again * */ #else /* usage: arpdump [seconds] Newsgroups: net.unix-wizards Subject: Re: Re: Ethernet problems Re: Hedrick's suggestion that the problem may be with your ARP tables: Here's a hack I use to examine the arp tables on my systems, I think half of it or more is from something else, but it seems to do the job (4.2bsd): */ #endif #include #include #include #include #include #include char *fcore = "/dev/kmem", *fnlist = "/vmunix" ; struct nlist nl[] = { #define ARPTAB 0 { "_arptab" }, { "" }, } ; #ifdef DPB /* The arptab structure is defined in netinet/if_ether.h */ #endif struct arptab { struct in_addr at_iaddr; /* internet address */ u_char at_enaddr[6]; /* ethernet address */ struct mbuf *at_hold; /* last packet until resolved/timeout */ u_char at_timer; /* minutes since last reference */ u_char at_flags; /* flags */ }; /* at_flags field values */ #ifdef DPB /* The at_flags are defined in net/if.h */ #endif #define ATF_INUSE 1 /* entry in use */ #define ATF_COM 2 /* completed entry (enaddr valid) */ #ifdef DPB #define ATF_PERM 4 /* permanent entry */ #define ATF_PUBL 8 /* publish entry (respond for other host) */ #endif #ifdef DPB /* bucket stuff defined in netinet/if_ether.c */ #endif #define ARPTAB_BSIZ 5 /* bucket size */ #define ARPTAB_NB 19 /* number of buckets */ #define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB) struct arptab *arptab, atab ; #ifdef DPB int verbose; /* -v verbose flag */ int allflag; /* -a to print all timed out ones */ #endif main(argc,argv) int argc ; char **argv ; { int fc ; int i,j ; int secs ; char *ap ; struct hostent *gethostbyaddr(), *hp ; if((fc = open(fcore,0)) < 0) { perror(fcore) ; exit(1) ; } #ifdef CCI if (nlist(fnlist, nl) == -1) { fprintf(stderr, "arptab: nlist on %s returned error\n", fnlist); exit(1); } #else nlist(fnlist,nl) ; #endif arptab = (struct arptab *) nl[ARPTAB].n_value ; #ifdef CCI if (nl[0].n_value == 0) #else if(nl[0].n_type == 0) #endif { fprintf(stderr,"No name list %s\n",fnlist) ; exit(1) ; } #ifdef DPB secs = 0; /* primitive error checking on arguments */ for (i = 1; i < argc; ++i) if (strcmp(argv[i], "-a") == 0) ++allflag; else if (strcmp(argv[i], "-v") == 0) ++verbose; else secs = atoi(argv[i]); #else if(argc > 1) secs = atoi(argv[1]) ; else secs = 0 ; #endif printf("\t\tACTIVE ARP TABLE DUMP\n") ; loop: #ifdef DPB printf("Index\tIP Addr\t\tEthernet Interface\tHostName\tTimer\tFlags\n") ; #else printf("Index\tAddr\t\tEthernet Interface\tHostName\n") ; #endif lseek(fc,(int) arptab,0) ; #ifdef DPB ap = (char *) &atab; #else /* old way requires that at_iaddr be first */ ap = (char *) &atab.at_iaddr ; #endif for(i=0 ; i < ARPTAB_SIZE ; i++) { if(read(fc,&atab,sizeof atab) != (sizeof atab)) { fprintf(stderr,"Error reading arp table\n") ; exit(1) ; } #ifdef DPB if (verbose) goto printslot; /* print every slot it */ if (allflag) /* print old timed out "half-filled" slots */ if ( inet_netof(atab.at_iaddr) != 0 || atab.at_flags != 0 || ge_addr(&atab.at_enaddr[0]) != 0) ; /* print slot below */ else continue; else /* print only entries with IP addresses */ if (inet_netof(atab.at_iaddr) != 0) ; /* print slot below */ else continue; printslot: #else if(inet_netof(atab.at_iaddr) == 0) continue ; #endif printf("%2d:\t",i) ; printf("%s\t",ap = (char *) inet_ntoa(atab.at_iaddr)) ; #ifdef DPB /* kludgy way to align columns because IP addr is var len */ if (strlen(ap)<8) printf("\t"); #endif for(j=0 ; j < 6 ; j++) printf("%02x",atab.at_enaddr[j]) ; if((hp = gethostbyaddr(&atab.at_iaddr.s_addr, sizeof atab.at_iaddr.s_addr, AF_INET)) == NULL) #ifdef DPB /* save ptr to host name printed for strlen later */ printf(ap = "\t\t(unknown)") ; else printf("\t\t%s",ap = hp->h_name) ; #else printf("\t\t(unknown)") ; else printf("\t\t%s",hp->h_name) ; #endif #ifdef DPB /* again kludgy way to align columns because hostname var len */ if (strlen(ap)<8) printf("\t"); printf("\t%3d", atab.at_timer); printf("\t"); if (atab.at_flags & ATF_INUSE) printf("U"); if (atab.at_flags & ATF_COM) printf("C"); if (atab.at_flags & ATF_PERM) printf("P"); if (atab.at_flags & ATF_PUBL) printf("R"); /* responding */ #endif printf("\n") ; } if(secs <= 0) exit(0) ; sleep(secs) ; goto loop ; } /* -Barry Shein, Boston University */ #ifdef DPB /* * get ethernet address * returns 0 iff 6 byte ethernet address is all zeros */ ge_addr(addr) register char *addr; { register int i; for (i = 0; i < 6; ++i, ++addr) if (*addr) return 1; /* found a non-zero byte */ return 0; /* all bytes were zero */ } #endif -- Dennis Bednar Computer Consoles Inc. Reston VA 703-648-3300 {decvax,ihnp4,harpo,allegra}!seismo!rlgvax!dennis