diff options
Diffstat (limited to 'usr.sbin/tcpdump/tcpdump/addrtoname.c')
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/addrtoname.c | 486 |
1 files changed, 365 insertions, 121 deletions
diff --git a/usr.sbin/tcpdump/tcpdump/addrtoname.c b/usr.sbin/tcpdump/tcpdump/addrtoname.c index 5c70865..11a1098 100644 --- a/usr.sbin/tcpdump/tcpdump/addrtoname.c +++ b/usr.sbin/tcpdump/tcpdump/addrtoname.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 1988, 1990 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1990, 1991, 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions @@ -23,25 +23,41 @@ */ #ifndef lint static char rcsid[] = - "@(#) $Header: addrtoname.c,v 1.14 92/05/25 14:29:07 mccanne Exp $ (LBL)"; + "@(#) $Header: addrtoname.c,v 1.37 94/06/16 00:42:28 mccanne Exp $ (LBL)"; #endif -#include <stdio.h> -#include <strings.h> -#include <ctype.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/time.h> + #include <net/if.h> -#include <netdb.h> + #include <netinet/in.h> #include <netinet/if_ether.h> + #include <arpa/inet.h> + +#include <ctype.h> +#include <netdb.h> +#include <pcap.h> +#include <pcap-namedb.h> #include <signal.h> +#include <stdio.h> +#include <string.h> +#ifdef __STDC__ +#include <stdlib.h> +#endif +#include <unistd.h> #include "interface.h" #include "addrtoname.h" -#include "nametoaddr.h" -#include "etherent.h" +#include "llc.h" + +static SIGRET nohostname(int); +#ifdef ETHER_SERVICE +struct ether_addr; +extern int ether_ntohost(char *, struct ether_addr *); +#endif /* * hash tables for whatever-to-name translations @@ -50,7 +66,7 @@ static char rcsid[] = #define HASHNAMESIZE 4096 struct hnamemem { - u_long addr; + u_int32 addr; char *name; struct hnamemem *nxt; }; @@ -59,24 +75,35 @@ struct hnamemem hnametable[HASHNAMESIZE]; struct hnamemem tporttable[HASHNAMESIZE]; struct hnamemem uporttable[HASHNAMESIZE]; struct hnamemem eprototable[HASHNAMESIZE]; +struct hnamemem dnaddrtable[HASHNAMESIZE]; +struct hnamemem llcsaptable[HASHNAMESIZE]; struct enamemem { u_short e_addr0; u_short e_addr1; u_short e_addr2; char *e_name; + u_char *e_nsap; /* used only for nsaptable[] */ struct enamemem *e_nxt; }; struct enamemem enametable[HASHNAMESIZE]; +struct enamemem nsaptable[HASHNAMESIZE]; +struct protoidmem { + u_long p_oui; + u_short p_proto; + char *p_name; + struct protoidmem *p_nxt; +}; + +struct protoidmem protoidtable[HASHNAMESIZE]; /* * A faster replacement for inet_ntoa(). */ char * -intoa(addr) - u_long addr; +intoa(u_int32 addr) { register char *cp; register u_int byte; @@ -105,9 +132,9 @@ intoa(addr) return cp + 1; } -static u_long f_netmask; -static u_long f_localnet; -static u_long netmask; +static u_int32 f_netmask; +static u_int32 f_localnet; +static u_int32 netmask; /* * "getname" is written in this atrocious way to make sure we don't @@ -117,8 +144,8 @@ static u_long netmask; jmp_buf getname_env; -static void -nohostname() +static SIGRET +nohostname(int signo) { longjmp(getname_env, 1); } @@ -128,16 +155,15 @@ nohostname() * is assumed to be in network byte order. */ char * -getname(ap) - u_char *ap; +getname(const u_char *ap) { - register struct hnamemem *p; register struct hostent *hp; register char *cp; - u_long addr; + u_int32 addr; + static struct hnamemem *p; /* static for longjmp() */ #ifndef TCPDUMP_ALIGN - addr = *(u_long *)ap; + addr = *(const u_int32 *)ap; #else /* * Deal with alignment. @@ -145,35 +171,35 @@ getname(ap) switch ((int)ap & 3) { case 0: - addr = *(u_long *)ap; + addr = *(u_int32 *)ap; break; case 2: #if BYTE_ORDER == LITTLE_ENDIAN - addr = ((u_long)*(u_short *)(ap + 2) << 16) | - (u_long)*(u_short *)ap; + addr = ((u_int32)*(u_short *)(ap + 2) << 16) | + (u_int32)*(u_short *)ap; #else - addr = ((u_long)*(u_short *)ap << 16) | - (u_long)*(u_short *)(ap + 2); + addr = ((u_int32)*(u_short *)ap << 16) | + (u_int32)*(u_short *)(ap + 2); #endif break; default: #if BYTE_ORDER == LITTLE_ENDIAN - addr = ((u_long)ap[0] << 24) | - ((u_long)ap[1] << 16) | - ((u_long)ap[2] << 8) | - (u_long)ap[3]; + addr = ((u_int32)ap[0] << 24) | + ((u_int32)ap[1] << 16) | + ((u_int32)ap[2] << 8) | + (u_int32)ap[3]; #else - addr = ((u_long)ap[3] << 24) | - ((u_long)ap[2] << 16) | - ((u_long)ap[1] << 8) | - (u_long)ap[0]; + addr = ((u_int32)ap[3] << 24) | + ((u_int32)ap[2] << 16) | + ((u_int32)ap[1] << 8) | + (u_int32)ap[0]; #endif break; } #endif - p = &hnametable[addr & (HASHNAMESIZE-1)]; + p = &hnametable[addr & (HASHNAMESIZE-1)]; for (; p->nxt; p = p->nxt) { if (p->addr == addr) return (p->name); @@ -183,8 +209,8 @@ getname(ap) /* * Only print names when: - * (1) -n was not given. - * (2) Address is foreign and -f was given. If -f was not + * (1) -n was not given. + * (2) Address is foreign and -f was given. If -f was not * present, f_netmask and f_local are 0 and the second * test will succeed. * (3) The host portion is not 0 (i.e., a network address). @@ -198,14 +224,12 @@ getname(ap) hp = gethostbyaddr((char *)&addr, 4, AF_INET); (void)alarm(0); if (hp) { - char *index(); - char *dotp; - u_int len = strlen(hp->h_name) + 1; - p->name = (char *)malloc(len); - (void)strcpy(p->name, hp->h_name); + char *dotp; + + p->name = savestr(hp->h_name); if (Nflag) { /* Remove domain qualifications */ - dotp = index(p->name, '.'); + dotp = strchr(p->name, '.'); if (dotp) *dotp = 0; } @@ -214,8 +238,7 @@ getname(ap) } } cp = intoa(addr); - p->name = (char *)malloc((unsigned)(strlen(cp) + 1)); - (void)strcpy(p->name, cp); + p->name = savestr(cp); return (p->name); } @@ -225,8 +248,7 @@ static char hex[] = "0123456789abcdef"; /* Find the hash node that corresponds the ether address 'ep'. */ static inline struct enamemem * -lookup_emem(ep) - u_char *ep; +lookup_emem(const u_char *ep) { register u_int i, j, k; struct enamemem *tp; @@ -251,9 +273,73 @@ lookup_emem(ep) return tp; } +/* Find the hash node that corresponds the NSAP 'nsap'. */ + +static inline struct enamemem * +lookup_nsap(register const u_char *nsap) +{ + register u_int i, j, k; + int nlen = *nsap; + struct enamemem *tp; + const u_char *ensap = nsap + nlen - 6; + + if (nlen > 6) { + k = (ensap[0] << 8) | ensap[1]; + j = (ensap[2] << 8) | ensap[3]; + i = (ensap[4] << 8) | ensap[5]; + } + else + i = j = k = 0; + + tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->e_nxt) + if (tp->e_addr0 == i && + tp->e_addr1 == j && + tp->e_addr2 == k && + tp->e_nsap[0] == nlen && + bcmp((char *)&(nsap[1]), + (char *)&(tp->e_nsap[1]), nlen) == 0) + return tp; + else + tp = tp->e_nxt; + tp->e_addr0 = i; + tp->e_addr1 = j; + tp->e_addr2 = k; + tp->e_nsap = (u_char *) calloc(1, nlen + 1); + bcopy(nsap, tp->e_nsap, nlen + 1); + tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); + + return tp; +} + +/* Find the hash node that corresponds the protoid 'pi'. */ + +static inline struct protoidmem * +lookup_protoid(const u_char *pi) +{ + register u_int i, j; + struct protoidmem *tp; + + /* 5 octets won't be aligned */ + i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; + j = (pi[3] << 8) + pi[4]; + /* XXX should be endian-insensitive, but do big-endian testing XXX */ + + tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->p_nxt) + if (tp->p_oui == i && tp->p_proto == j) + return tp; + else + tp = tp->p_nxt; + tp->p_oui = i; + tp->p_proto = j; + tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); + + return tp; +} + char * -etheraddr_string(ep) - register u_char *ep; +etheraddr_string(register const u_char *ep) { register u_int i, j; register char *cp; @@ -261,25 +347,24 @@ etheraddr_string(ep) tp = lookup_emem(ep); if (tp->e_name) - return tp->e_name; - + return (tp->e_name); #ifdef ETHER_SERVICE if (!nflag) { - cp = ETHER_ntohost(ep); - if (cp) { - tp->e_name = cp; - return cp; + char buf[128]; + if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { + tp->e_name = savestr(buf); + return (buf); } } -#endif +#endif tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00")); - if (j = *ep >> 4) + if ((j = *ep >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*ep++ & 0xf]; for (i = 5; (int)--i >= 0;) { *cp++ = ':'; - if (j = *ep >> 4) + if ((j = *ep >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*ep++ & 0xf]; } @@ -288,8 +373,7 @@ etheraddr_string(ep) } char * -etherproto_string(port) - u_short port; +etherproto_string(u_short port) { register char *cp; register struct hnamemem *tp; @@ -313,11 +397,82 @@ etherproto_string(port) } char * -tcpport_string(port) - u_short port; +protoid_string(register const u_char *pi) +{ + register u_int i, j; + register char *cp; + register struct protoidmem *tp; + + tp = lookup_protoid(pi); + if (tp->p_name) + return tp->p_name; + + tp->p_name = cp = (char *)malloc(sizeof("00:00:00:00:00")); + + if ((j = *pi >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*pi++ & 0xf]; + for (i = 4; (int)--i >= 0;) { + *cp++ = ':'; + if ((j = *pi >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*pi++ & 0xf]; + } + *cp = '\0'; + return (tp->p_name); +} + +char * +llcsap_string(u_char sap) +{ + register char *cp; + register struct hnamemem *tp; + register u_long i = sap; + + for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->name = cp = (char *)malloc(sizeof("sap 00")); + tp->addr = i; + tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); + + (void)strcpy(cp, "sap "); + cp += strlen(cp); + *cp++ = hex[sap >> 4 & 0xf]; + *cp++ = hex[sap & 0xf]; + *cp++ = '\0'; + return (tp->name); +} + +char * +isonsap_string(const u_char *nsap) +{ + register u_int i, nlen = nsap[0]; + register char *cp; + register struct enamemem *tp; + + tp = lookup_nsap(nsap); + if (tp->e_name) + return tp->e_name; + + tp->e_name = cp = (char *)malloc(nlen * 2 + 2); + + nsap++; + *cp++ = '/'; + for (i = nlen; (int)--i >= 0;) { + *cp++ = hex[*nsap >> 4]; + *cp++ = hex[*nsap++ & 0xf]; + } + *cp = '\0'; + return (tp->e_name); +} + +char * +tcpport_string(u_short port) { register struct hnamemem *tp; - register int i = port; + register u_long i = port; for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) @@ -332,11 +487,10 @@ tcpport_string(port) } char * -udpport_string(port) - register u_short port; +udpport_string(register u_short port) { register struct hnamemem *tp; - register int i = port; + register u_long i = port; for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) @@ -352,15 +506,15 @@ udpport_string(port) } static void -init_servarray() +init_servarray(void) { struct servent *sv; register struct hnamemem *table; register int i; - while (sv = getservent()) { - NTOHS(sv->s_port); - i = sv->s_port & (HASHNAMESIZE-1); + while ((sv = getservent()) != NULL) { + int port = ntohs(sv->s_port); + i = port & (HASHNAMESIZE-1); if (strcmp(sv->s_proto, "tcp") == 0) table = &tporttable[i]; else if (strcmp(sv->s_proto, "udp") == 0) @@ -373,45 +527,24 @@ init_servarray() if (nflag) { char buf[32]; - (void)sprintf(buf, "%d", sv->s_port); - table->name = (char *)malloc((unsigned)strlen(buf)+1); - (void)strcpy(table->name, buf); - } else { - table->name = - (char *)malloc((unsigned)strlen(sv->s_name)+1); - (void)strcpy(table->name, sv->s_name); - } - table->addr = sv->s_port; + (void)sprintf(buf, "%d", port); + table->name = savestr(buf); + } else + table->name = savestr(sv->s_name); + table->addr = port; table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); } endservent(); } -#include "etherproto.h" - -/* Static data base of ether protocol types. */ -struct eproto eproto_db[] = { - { "pup", ETHERTYPE_PUP }, - { "xns", ETHERTYPE_NS }, - { "ip", ETHERTYPE_IP }, - { "arp", ETHERTYPE_ARP }, - { "rarp", ETHERTYPE_REVARP }, - { "sprite", ETHERTYPE_SPRITE }, - { "mopdl", ETHERTYPE_MOPDL }, - { "moprc", ETHERTYPE_MOPRC }, - { "decnet", ETHERTYPE_DN }, - { "lat", ETHERTYPE_LAT }, - { "lanbridge", ETHERTYPE_LANBRIDGE }, - { "vexp", ETHERTYPE_VEXP }, - { "vprod", ETHERTYPE_VPROD }, - { "atalk", ETHERTYPE_ATALK }, - { "atalkarp", ETHERTYPE_AARP }, - { "loopback", ETHERTYPE_LOOPBACK }, - { (char *)0, 0 } -}; +/*XXX from libbpfc.a */ +extern struct eproto { + char *s; + u_short p; +} eproto_db[]; static void -init_eprotoarray() +init_eprotoarray(void) { register int i; register struct hnamemem *table; @@ -427,26 +560,118 @@ init_eprotoarray() } } +/* + * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet + * types. + */ static void -init_etherarray() +init_protoidarray(void) { -#ifndef ETHER_SERVICE - FILE *fp; - struct etherent *ep; - struct enamemem *tp; + register int i; + register struct protoidmem *tp; + u_char protoid[5]; - fp = fopen(ETHERS_FILE, "r"); - if (fp == 0) - /* No data base; will have to settle for - numeric addresses. */ - return; + protoid[0] = 0; + protoid[1] = 0; + protoid[2] = 0; + for (i = 0; eproto_db[i].s; i++) { + u_short etype = htons(eproto_db[i].p); + bcopy((char *)&etype, (char *)&protoid[3], 2); + tp = lookup_protoid(protoid); + tp->p_name = savestr(eproto_db[i].s); + } +} - while (ep = next_etherent(fp)) { - tp = lookup_emem(ep->addr); - tp->e_name = (char *)malloc((unsigned)strlen(ep->name)+1); - strcpy(tp->e_name, ep->name); +static struct etherlist { + u_char addr[6]; + char *name; +} etherlist[] = { + {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } +}; + +/* + * Initialize the ethers hash table. We take two different approaches + * depending on whether or not the system provides the ethers name + * service. If it does, we just wire in a few names at startup, + * and etheraddr_string() fills in the table on demand. If it doesn't, + * then we suck in the entire /etc/ethers file at startup. The idea + * is that parsing the local file will be fast, but spinning through + * all the ethers entries via NIS & next_etherent might be very slow. + * + * XXX pcap_next_etherent doesn't belong in the pcap interface, but + * since the pcap module already does name-to-address translation, + * it's already does most of the work for the ethernet address-to-name + * translation, so we just pcap_next_etherent as a convenience. + */ +static void +init_etherarray(void) +{ + register struct etherlist *el; + register struct enamemem *tp; +#ifndef ETHER_SERVICE + register struct pcap_etherent *ep; + register FILE *fp; + + /* Suck in entire ethers file */ + fp = fopen(PCAP_ETHERS_FILE, "r"); + if (fp != NULL) { + while ((ep = pcap_next_etherent(fp)) != NULL) { + tp = lookup_emem(ep->addr); + tp->e_name = savestr(ep->name); + } + (void)fclose(fp); } #endif + + /* Hardwire some ethernet names */ + for (el = etherlist; el->name != NULL; ++el) { +#ifdef ETHER_SERVICE + /* Use yp/nis version of name if available */ + char wrk[256]; + if (ether_ntohost(wrk, (struct ether_addr *)el->addr) == 0) { + tp = lookup_emem(el->addr); + tp->e_name = savestr(wrk); + } +#else + /* install if not already present */ + tp = lookup_emem(el->addr); + if (tp->e_name == NULL) + tp->e_name = el->name; +#endif + + } +} + +static struct token llcsap_db[] = { + { LLCSAP_NULL, "null" }, + { LLCSAP_8021B_I, "802.1b-gsap" }, + { LLCSAP_8021B_G, "802.1b-isap" }, + { LLCSAP_IP, "ip-sap" }, + { LLCSAP_PROWAYNM, "proway-nm" }, + { LLCSAP_8021D, "802.1d" }, + { LLCSAP_RS511, "eia-rs511" }, + { LLCSAP_ISO8208, "x.25/llc2" }, + { LLCSAP_PROWAY, "proway" }, + { LLCSAP_ISONS, "iso-clns" }, + { LLCSAP_GLOBAL, "global" }, + { 0, NULL } +}; + +static void +init_llcsaparray(void) +{ + register int i; + register struct hnamemem *table; + + for (i = 0; llcsap_db[i].s != NULL; i++) { + table = &llcsaptable[llcsap_db[i].v]; + while (table->name) + table = table->nxt; + table->name = llcsap_db[i].s; + table->addr = llcsap_db[i].v; + table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); + } } /* @@ -456,10 +681,7 @@ init_etherarray() * of the local network. mask is its subnet mask. */ void -init_addrtoname(fflag, localnet, mask) - int fflag; - u_long localnet; - u_long mask; +init_addrtoname(int fflag, u_int32 localnet, u_int32 mask) { netmask = mask; if (fflag) { @@ -475,4 +697,26 @@ init_addrtoname(fflag, localnet, mask) init_etherarray(); init_servarray(); init_eprotoarray(); + init_llcsaparray(); + init_protoidarray(); +} + +char * +dnaddr_string(u_short dnaddr) +{ + register struct hnamemem *tp; + + for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; + tp = tp->nxt) + if (tp->addr == dnaddr) + return (tp->name); + + tp->addr = dnaddr; + tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); + if (nflag) + tp->name = dnnum_string(dnaddr); + else + tp->name = dnname_string(dnaddr); + + return(tp->name); } |