xref: /freebsd/contrib/tcpdump/addrtoname.c (revision 4edb46e9a85ca35d3bed523171d11a748861ce82)
14edb46e9SPaul Traina /*
24edb46e9SPaul Traina  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
204edb46e9SPaul Traina  *
214edb46e9SPaul Traina  *  Internet, ethernet, port, and protocol string to address
224edb46e9SPaul Traina  *  and address to string conversion routines
234edb46e9SPaul Traina  */
244edb46e9SPaul Traina #ifndef lint
254edb46e9SPaul Traina static char rcsid[] =
264edb46e9SPaul Traina     "@(#) $Header: addrtoname.c,v 1.49 96/07/02 00:19:35 leres Exp $ (LBL)";
274edb46e9SPaul Traina #endif
284edb46e9SPaul Traina 
294edb46e9SPaul Traina #include <sys/types.h>
304edb46e9SPaul Traina #include <sys/socket.h>
314edb46e9SPaul Traina #include <sys/time.h>
324edb46e9SPaul Traina 
334edb46e9SPaul Traina #if __STDC__
344edb46e9SPaul Traina struct mbuf;
354edb46e9SPaul Traina struct rtentry;
364edb46e9SPaul Traina #endif
374edb46e9SPaul Traina #include <net/if.h>
384edb46e9SPaul Traina 
394edb46e9SPaul Traina #include <netinet/in.h>
404edb46e9SPaul Traina #include <netinet/if_ether.h>
414edb46e9SPaul Traina 
424edb46e9SPaul Traina #include <arpa/inet.h>
434edb46e9SPaul Traina 
444edb46e9SPaul Traina #include <ctype.h>
454edb46e9SPaul Traina #include <netdb.h>
464edb46e9SPaul Traina #include <pcap.h>
474edb46e9SPaul Traina #include <pcap-namedb.h>
484edb46e9SPaul Traina #include <signal.h>
494edb46e9SPaul Traina #include <stdio.h>
504edb46e9SPaul Traina #include <string.h>
514edb46e9SPaul Traina #include <stdlib.h>
524edb46e9SPaul Traina #include <unistd.h>
534edb46e9SPaul Traina 
544edb46e9SPaul Traina #include "interface.h"
554edb46e9SPaul Traina #include "addrtoname.h"
564edb46e9SPaul Traina #include "llc.h"
574edb46e9SPaul Traina 
584edb46e9SPaul Traina /* Forwards */
594edb46e9SPaul Traina static RETSIGTYPE nohostname(int);
604edb46e9SPaul Traina 
614edb46e9SPaul Traina /*
624edb46e9SPaul Traina  * hash tables for whatever-to-name translations
634edb46e9SPaul Traina  */
644edb46e9SPaul Traina 
654edb46e9SPaul Traina #define HASHNAMESIZE 4096
664edb46e9SPaul Traina 
674edb46e9SPaul Traina struct hnamemem {
684edb46e9SPaul Traina 	u_int32_t addr;
694edb46e9SPaul Traina 	char *name;
704edb46e9SPaul Traina 	struct hnamemem *nxt;
714edb46e9SPaul Traina };
724edb46e9SPaul Traina 
734edb46e9SPaul Traina struct hnamemem hnametable[HASHNAMESIZE];
744edb46e9SPaul Traina struct hnamemem tporttable[HASHNAMESIZE];
754edb46e9SPaul Traina struct hnamemem uporttable[HASHNAMESIZE];
764edb46e9SPaul Traina struct hnamemem eprototable[HASHNAMESIZE];
774edb46e9SPaul Traina struct hnamemem dnaddrtable[HASHNAMESIZE];
784edb46e9SPaul Traina struct hnamemem llcsaptable[HASHNAMESIZE];
794edb46e9SPaul Traina 
804edb46e9SPaul Traina struct enamemem {
814edb46e9SPaul Traina 	u_short e_addr0;
824edb46e9SPaul Traina 	u_short e_addr1;
834edb46e9SPaul Traina 	u_short e_addr2;
844edb46e9SPaul Traina 	char *e_name;
854edb46e9SPaul Traina 	u_char *e_nsap;			/* used only for nsaptable[] */
864edb46e9SPaul Traina 	struct enamemem *e_nxt;
874edb46e9SPaul Traina };
884edb46e9SPaul Traina 
894edb46e9SPaul Traina struct enamemem enametable[HASHNAMESIZE];
904edb46e9SPaul Traina struct enamemem nsaptable[HASHNAMESIZE];
914edb46e9SPaul Traina 
924edb46e9SPaul Traina struct protoidmem {
934edb46e9SPaul Traina 	u_int32_t p_oui;
944edb46e9SPaul Traina 	u_short p_proto;
954edb46e9SPaul Traina 	char *p_name;
964edb46e9SPaul Traina 	struct protoidmem *p_nxt;
974edb46e9SPaul Traina };
984edb46e9SPaul Traina 
994edb46e9SPaul Traina struct protoidmem protoidtable[HASHNAMESIZE];
1004edb46e9SPaul Traina 
1014edb46e9SPaul Traina /*
1024edb46e9SPaul Traina  * A faster replacement for inet_ntoa().
1034edb46e9SPaul Traina  */
1044edb46e9SPaul Traina char *
1054edb46e9SPaul Traina intoa(u_int32_t addr)
1064edb46e9SPaul Traina {
1074edb46e9SPaul Traina 	register char *cp;
1084edb46e9SPaul Traina 	register u_int byte;
1094edb46e9SPaul Traina 	register int n;
1104edb46e9SPaul Traina 	static char buf[sizeof(".xxx.xxx.xxx.xxx")];
1114edb46e9SPaul Traina 
1124edb46e9SPaul Traina 	NTOHL(addr);
1134edb46e9SPaul Traina 	cp = &buf[sizeof buf];
1144edb46e9SPaul Traina 	*--cp = '\0';
1154edb46e9SPaul Traina 
1164edb46e9SPaul Traina 	n = 4;
1174edb46e9SPaul Traina 	do {
1184edb46e9SPaul Traina 		byte = addr & 0xff;
1194edb46e9SPaul Traina 		*--cp = byte % 10 + '0';
1204edb46e9SPaul Traina 		byte /= 10;
1214edb46e9SPaul Traina 		if (byte > 0) {
1224edb46e9SPaul Traina 			*--cp = byte % 10 + '0';
1234edb46e9SPaul Traina 			byte /= 10;
1244edb46e9SPaul Traina 			if (byte > 0)
1254edb46e9SPaul Traina 				*--cp = byte + '0';
1264edb46e9SPaul Traina 		}
1274edb46e9SPaul Traina 		*--cp = '.';
1284edb46e9SPaul Traina 		addr >>= 8;
1294edb46e9SPaul Traina 	} while (--n > 0);
1304edb46e9SPaul Traina 
1314edb46e9SPaul Traina 	return cp + 1;
1324edb46e9SPaul Traina }
1334edb46e9SPaul Traina 
1344edb46e9SPaul Traina static u_int32_t f_netmask;
1354edb46e9SPaul Traina static u_int32_t f_localnet;
1364edb46e9SPaul Traina static u_int32_t netmask;
1374edb46e9SPaul Traina 
1384edb46e9SPaul Traina /*
1394edb46e9SPaul Traina  * "getname" is written in this atrocious way to make sure we don't
1404edb46e9SPaul Traina  * wait forever while trying to get hostnames from yp.
1414edb46e9SPaul Traina  */
1424edb46e9SPaul Traina #include <setjmp.h>
1434edb46e9SPaul Traina 
1444edb46e9SPaul Traina jmp_buf getname_env;
1454edb46e9SPaul Traina 
1464edb46e9SPaul Traina static RETSIGTYPE
1474edb46e9SPaul Traina nohostname(int signo)
1484edb46e9SPaul Traina {
1494edb46e9SPaul Traina 	longjmp(getname_env, 1);
1504edb46e9SPaul Traina }
1514edb46e9SPaul Traina 
1524edb46e9SPaul Traina /*
1534edb46e9SPaul Traina  * Return a name for the IP address pointed to by ap.  This address
1544edb46e9SPaul Traina  * is assumed to be in network byte order.
1554edb46e9SPaul Traina  */
1564edb46e9SPaul Traina char *
1574edb46e9SPaul Traina getname(const u_char *ap)
1584edb46e9SPaul Traina {
1594edb46e9SPaul Traina 	register struct hostent *hp;
1604edb46e9SPaul Traina 	u_int32_t addr;
1614edb46e9SPaul Traina 	static struct hnamemem *p;		/* static for longjmp() */
1624edb46e9SPaul Traina 
1634edb46e9SPaul Traina #ifndef LBL_ALIGN
1644edb46e9SPaul Traina 	addr = *(const u_int32_t *)ap;
1654edb46e9SPaul Traina #else
1664edb46e9SPaul Traina 	/*
1674edb46e9SPaul Traina 	 * Deal with alignment.
1684edb46e9SPaul Traina 	 */
1694edb46e9SPaul Traina 	switch ((long)ap & 3) {
1704edb46e9SPaul Traina 
1714edb46e9SPaul Traina 	case 0:
1724edb46e9SPaul Traina 		addr = *(u_int32_t *)ap;
1734edb46e9SPaul Traina 		break;
1744edb46e9SPaul Traina 
1754edb46e9SPaul Traina 	case 2:
1764edb46e9SPaul Traina #if BYTE_ORDER == LITTLE_ENDIAN
1774edb46e9SPaul Traina 		addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
1784edb46e9SPaul Traina 			(u_int32_t)*(u_short *)ap;
1794edb46e9SPaul Traina #else
1804edb46e9SPaul Traina 		addr = ((u_int32_t)*(u_short *)ap << 16) |
1814edb46e9SPaul Traina 			(u_int32_t)*(u_short *)(ap + 2);
1824edb46e9SPaul Traina #endif
1834edb46e9SPaul Traina 		break;
1844edb46e9SPaul Traina 
1854edb46e9SPaul Traina 	default:
1864edb46e9SPaul Traina #if BYTE_ORDER == LITTLE_ENDIAN
1874edb46e9SPaul Traina 		addr = ((u_int32_t)ap[3] << 24) |
1884edb46e9SPaul Traina 			((u_int32_t)ap[2] << 16) |
1894edb46e9SPaul Traina 			((u_int32_t)ap[1] << 8) |
1904edb46e9SPaul Traina 			(u_int32_t)ap[0];
1914edb46e9SPaul Traina #else
1924edb46e9SPaul Traina 		addr = ((u_int32_t)ap[0] << 24) |
1934edb46e9SPaul Traina 			((u_int32_t)ap[1] << 16) |
1944edb46e9SPaul Traina 			((u_int32_t)ap[2] << 8) |
1954edb46e9SPaul Traina 			(u_int32_t)ap[3];
1964edb46e9SPaul Traina #endif
1974edb46e9SPaul Traina 		break;
1984edb46e9SPaul Traina 	}
1994edb46e9SPaul Traina #endif
2004edb46e9SPaul Traina 	p = &hnametable[addr & (HASHNAMESIZE-1)];
2014edb46e9SPaul Traina 	for (; p->nxt; p = p->nxt) {
2024edb46e9SPaul Traina 		if (p->addr == addr)
2034edb46e9SPaul Traina 			return (p->name);
2044edb46e9SPaul Traina 	}
2054edb46e9SPaul Traina 	p->addr = addr;
2064edb46e9SPaul Traina 	p->nxt = newhnamemem();
2074edb46e9SPaul Traina 
2084edb46e9SPaul Traina 	/*
2094edb46e9SPaul Traina 	 * Only print names when:
2104edb46e9SPaul Traina 	 *	(1) -n was not given.
2114edb46e9SPaul Traina 	 *	(2) Address is foreign and -f was given.  If -f was not
2124edb46e9SPaul Traina 	 *	    present, f_netmask and f_local are 0 and the second
2134edb46e9SPaul Traina 	 *	    test will succeed.
2144edb46e9SPaul Traina 	 *	(3) The host portion is not 0 (i.e., a network address).
2154edb46e9SPaul Traina 	 *	(4) The host portion is not broadcast.
2164edb46e9SPaul Traina 	 */
2174edb46e9SPaul Traina 	if (!nflag && (addr & f_netmask) == f_localnet
2184edb46e9SPaul Traina 	    && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
2194edb46e9SPaul Traina 		if (!setjmp(getname_env)) {
2204edb46e9SPaul Traina 			(void)signal(SIGALRM, nohostname);
2214edb46e9SPaul Traina 			(void)alarm(20);
2224edb46e9SPaul Traina 			hp = gethostbyaddr((char *)&addr, 4, AF_INET);
2234edb46e9SPaul Traina 			(void)alarm(0);
2244edb46e9SPaul Traina 			if (hp) {
2254edb46e9SPaul Traina 				char *dotp;
2264edb46e9SPaul Traina 
2274edb46e9SPaul Traina 				p->name = savestr(hp->h_name);
2284edb46e9SPaul Traina 				if (Nflag) {
2294edb46e9SPaul Traina 					/* Remove domain qualifications */
2304edb46e9SPaul Traina 					dotp = strchr(p->name, '.');
2314edb46e9SPaul Traina 					if (dotp)
2324edb46e9SPaul Traina 						*dotp = '\0';
2334edb46e9SPaul Traina 				}
2344edb46e9SPaul Traina 				return (p->name);
2354edb46e9SPaul Traina 			}
2364edb46e9SPaul Traina 		}
2374edb46e9SPaul Traina 	}
2384edb46e9SPaul Traina 	p->name = savestr(intoa(addr));
2394edb46e9SPaul Traina 	return (p->name);
2404edb46e9SPaul Traina }
2414edb46e9SPaul Traina 
2424edb46e9SPaul Traina static char hex[] = "0123456789abcdef";
2434edb46e9SPaul Traina 
2444edb46e9SPaul Traina 
2454edb46e9SPaul Traina /* Find the hash node that corresponds the ether address 'ep' */
2464edb46e9SPaul Traina 
2474edb46e9SPaul Traina static inline struct enamemem *
2484edb46e9SPaul Traina lookup_emem(const u_char *ep)
2494edb46e9SPaul Traina {
2504edb46e9SPaul Traina 	register u_int i, j, k;
2514edb46e9SPaul Traina 	struct enamemem *tp;
2524edb46e9SPaul Traina 
2534edb46e9SPaul Traina 	k = (ep[0] << 8) | ep[1];
2544edb46e9SPaul Traina 	j = (ep[2] << 8) | ep[3];
2554edb46e9SPaul Traina 	i = (ep[4] << 8) | ep[5];
2564edb46e9SPaul Traina 
2574edb46e9SPaul Traina 	tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
2584edb46e9SPaul Traina 	while (tp->e_nxt)
2594edb46e9SPaul Traina 		if (tp->e_addr0 == i &&
2604edb46e9SPaul Traina 		    tp->e_addr1 == j &&
2614edb46e9SPaul Traina 		    tp->e_addr2 == k)
2624edb46e9SPaul Traina 			return tp;
2634edb46e9SPaul Traina 		else
2644edb46e9SPaul Traina 			tp = tp->e_nxt;
2654edb46e9SPaul Traina 	tp->e_addr0 = i;
2664edb46e9SPaul Traina 	tp->e_addr1 = j;
2674edb46e9SPaul Traina 	tp->e_addr2 = k;
2684edb46e9SPaul Traina 	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
2694edb46e9SPaul Traina 	if (tp->e_nxt == NULL)
2704edb46e9SPaul Traina 		error("lookup_emem: calloc");
2714edb46e9SPaul Traina 
2724edb46e9SPaul Traina 	return tp;
2734edb46e9SPaul Traina }
2744edb46e9SPaul Traina 
2754edb46e9SPaul Traina /* Find the hash node that corresponds the NSAP 'nsap' */
2764edb46e9SPaul Traina 
2774edb46e9SPaul Traina static inline struct enamemem *
2784edb46e9SPaul Traina lookup_nsap(register const u_char *nsap)
2794edb46e9SPaul Traina {
2804edb46e9SPaul Traina 	register u_int i, j, k;
2814edb46e9SPaul Traina 	int nlen = *nsap;
2824edb46e9SPaul Traina 	struct enamemem *tp;
2834edb46e9SPaul Traina 	const u_char *ensap = nsap + nlen - 6;
2844edb46e9SPaul Traina 
2854edb46e9SPaul Traina 	if (nlen > 6) {
2864edb46e9SPaul Traina 		k = (ensap[0] << 8) | ensap[1];
2874edb46e9SPaul Traina 		j = (ensap[2] << 8) | ensap[3];
2884edb46e9SPaul Traina 		i = (ensap[4] << 8) | ensap[5];
2894edb46e9SPaul Traina 	}
2904edb46e9SPaul Traina 	else
2914edb46e9SPaul Traina 		i = j = k = 0;
2924edb46e9SPaul Traina 
2934edb46e9SPaul Traina 	tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
2944edb46e9SPaul Traina 	while (tp->e_nxt)
2954edb46e9SPaul Traina 		if (tp->e_addr0 == i &&
2964edb46e9SPaul Traina 		    tp->e_addr1 == j &&
2974edb46e9SPaul Traina 		    tp->e_addr2 == k &&
2984edb46e9SPaul Traina 		    tp->e_nsap[0] == nlen &&
2994edb46e9SPaul Traina 		    memcmp((char *)&(nsap[1]),
3004edb46e9SPaul Traina 			(char *)&(tp->e_nsap[1]), nlen) == 0)
3014edb46e9SPaul Traina 			return tp;
3024edb46e9SPaul Traina 		else
3034edb46e9SPaul Traina 			tp = tp->e_nxt;
3044edb46e9SPaul Traina 	tp->e_addr0 = i;
3054edb46e9SPaul Traina 	tp->e_addr1 = j;
3064edb46e9SPaul Traina 	tp->e_addr2 = k;
3074edb46e9SPaul Traina 	tp->e_nsap = (u_char *)malloc(nlen + 1);
3084edb46e9SPaul Traina 	if (tp->e_nsap == NULL)
3094edb46e9SPaul Traina 		error("lookup_nsap: malloc");
3104edb46e9SPaul Traina 	memcpy(tp->e_nsap, nsap, nlen + 1);
3114edb46e9SPaul Traina 	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
3124edb46e9SPaul Traina 	if (tp->e_nxt == NULL)
3134edb46e9SPaul Traina 		error("lookup_nsap: calloc");
3144edb46e9SPaul Traina 
3154edb46e9SPaul Traina 	return tp;
3164edb46e9SPaul Traina }
3174edb46e9SPaul Traina 
3184edb46e9SPaul Traina /* Find the hash node that corresponds the protoid 'pi'. */
3194edb46e9SPaul Traina 
3204edb46e9SPaul Traina static inline struct protoidmem *
3214edb46e9SPaul Traina lookup_protoid(const u_char *pi)
3224edb46e9SPaul Traina {
3234edb46e9SPaul Traina 	register u_int i, j;
3244edb46e9SPaul Traina 	struct protoidmem *tp;
3254edb46e9SPaul Traina 
3264edb46e9SPaul Traina 	/* 5 octets won't be aligned */
3274edb46e9SPaul Traina 	i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
3284edb46e9SPaul Traina 	j =   (pi[3] << 8) + pi[4];
3294edb46e9SPaul Traina 	/* XXX should be endian-insensitive, but do big-endian testing  XXX */
3304edb46e9SPaul Traina 
3314edb46e9SPaul Traina 	tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
3324edb46e9SPaul Traina 	while (tp->p_nxt)
3334edb46e9SPaul Traina 		if (tp->p_oui == i && tp->p_proto == j)
3344edb46e9SPaul Traina 			return tp;
3354edb46e9SPaul Traina 		else
3364edb46e9SPaul Traina 			tp = tp->p_nxt;
3374edb46e9SPaul Traina 	tp->p_oui = i;
3384edb46e9SPaul Traina 	tp->p_proto = j;
3394edb46e9SPaul Traina 	tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
3404edb46e9SPaul Traina 	if (tp->p_nxt == NULL)
3414edb46e9SPaul Traina 		error("lookup_protoid: calloc");
3424edb46e9SPaul Traina 
3434edb46e9SPaul Traina 	return tp;
3444edb46e9SPaul Traina }
3454edb46e9SPaul Traina 
3464edb46e9SPaul Traina char *
3474edb46e9SPaul Traina etheraddr_string(register const u_char *ep)
3484edb46e9SPaul Traina {
3494edb46e9SPaul Traina 	register u_int i, j;
3504edb46e9SPaul Traina 	register char *cp;
3514edb46e9SPaul Traina 	register struct enamemem *tp;
3524edb46e9SPaul Traina 	char buf[sizeof("00:00:00:00:00:00")];
3534edb46e9SPaul Traina 
3544edb46e9SPaul Traina 	tp = lookup_emem(ep);
3554edb46e9SPaul Traina 	if (tp->e_name)
3564edb46e9SPaul Traina 		return (tp->e_name);
3574edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST
3584edb46e9SPaul Traina 	if (!nflag) {
3594edb46e9SPaul Traina 		char buf[128];
3604edb46e9SPaul Traina 		if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
3614edb46e9SPaul Traina 			tp->e_name = savestr(buf);
3624edb46e9SPaul Traina 			return (tp->e_name);
3634edb46e9SPaul Traina 		}
3644edb46e9SPaul Traina 	}
3654edb46e9SPaul Traina #endif
3664edb46e9SPaul Traina 	cp = buf;
3674edb46e9SPaul Traina 	if ((j = *ep >> 4) != 0)
3684edb46e9SPaul Traina 		*cp++ = hex[j];
3694edb46e9SPaul Traina 	*cp++ = hex[*ep++ & 0xf];
3704edb46e9SPaul Traina 	for (i = 5; (int)--i >= 0;) {
3714edb46e9SPaul Traina 		*cp++ = ':';
3724edb46e9SPaul Traina 		if ((j = *ep >> 4) != 0)
3734edb46e9SPaul Traina 			*cp++ = hex[j];
3744edb46e9SPaul Traina 		*cp++ = hex[*ep++ & 0xf];
3754edb46e9SPaul Traina 	}
3764edb46e9SPaul Traina 	*cp = '\0';
3774edb46e9SPaul Traina 	tp->e_name = savestr(buf);
3784edb46e9SPaul Traina 	return (tp->e_name);
3794edb46e9SPaul Traina }
3804edb46e9SPaul Traina 
3814edb46e9SPaul Traina char *
3824edb46e9SPaul Traina etherproto_string(u_short port)
3834edb46e9SPaul Traina {
3844edb46e9SPaul Traina 	register char *cp;
3854edb46e9SPaul Traina 	register struct hnamemem *tp;
3864edb46e9SPaul Traina 	register u_int32_t i = port;
3874edb46e9SPaul Traina 	char buf[sizeof("0000")];
3884edb46e9SPaul Traina 
3894edb46e9SPaul Traina 	for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
3904edb46e9SPaul Traina 		if (tp->addr == i)
3914edb46e9SPaul Traina 			return (tp->name);
3924edb46e9SPaul Traina 
3934edb46e9SPaul Traina 	tp->addr = i;
3944edb46e9SPaul Traina 	tp->nxt = newhnamemem();
3954edb46e9SPaul Traina 
3964edb46e9SPaul Traina 	cp = buf;
3974edb46e9SPaul Traina 	NTOHS(port);
3984edb46e9SPaul Traina 	*cp++ = hex[port >> 12 & 0xf];
3994edb46e9SPaul Traina 	*cp++ = hex[port >> 8 & 0xf];
4004edb46e9SPaul Traina 	*cp++ = hex[port >> 4 & 0xf];
4014edb46e9SPaul Traina 	*cp++ = hex[port & 0xf];
4024edb46e9SPaul Traina 	*cp++ = '\0';
4034edb46e9SPaul Traina 	tp->name = savestr(buf);
4044edb46e9SPaul Traina 	return (tp->name);
4054edb46e9SPaul Traina }
4064edb46e9SPaul Traina 
4074edb46e9SPaul Traina char *
4084edb46e9SPaul Traina protoid_string(register const u_char *pi)
4094edb46e9SPaul Traina {
4104edb46e9SPaul Traina 	register u_int i, j;
4114edb46e9SPaul Traina 	register char *cp;
4124edb46e9SPaul Traina 	register struct protoidmem *tp;
4134edb46e9SPaul Traina 	char buf[sizeof("00:00:00:00:00")];
4144edb46e9SPaul Traina 
4154edb46e9SPaul Traina 	tp = lookup_protoid(pi);
4164edb46e9SPaul Traina 	if (tp->p_name)
4174edb46e9SPaul Traina 		return tp->p_name;
4184edb46e9SPaul Traina 
4194edb46e9SPaul Traina 	cp = buf;
4204edb46e9SPaul Traina 	if ((j = *pi >> 4) != 0)
4214edb46e9SPaul Traina 		*cp++ = hex[j];
4224edb46e9SPaul Traina 	*cp++ = hex[*pi++ & 0xf];
4234edb46e9SPaul Traina 	for (i = 4; (int)--i >= 0;) {
4244edb46e9SPaul Traina 		*cp++ = ':';
4254edb46e9SPaul Traina 		if ((j = *pi >> 4) != 0)
4264edb46e9SPaul Traina 			*cp++ = hex[j];
4274edb46e9SPaul Traina 		*cp++ = hex[*pi++ & 0xf];
4284edb46e9SPaul Traina 	}
4294edb46e9SPaul Traina 	*cp = '\0';
4304edb46e9SPaul Traina 	tp->p_name = savestr(buf);
4314edb46e9SPaul Traina 	return (tp->p_name);
4324edb46e9SPaul Traina }
4334edb46e9SPaul Traina 
4344edb46e9SPaul Traina char *
4354edb46e9SPaul Traina llcsap_string(u_char sap)
4364edb46e9SPaul Traina {
4374edb46e9SPaul Traina 	register char *cp;
4384edb46e9SPaul Traina 	register struct hnamemem *tp;
4394edb46e9SPaul Traina 	register u_int32_t i = sap;
4404edb46e9SPaul Traina 	char buf[sizeof("sap 00")];
4414edb46e9SPaul Traina 
4424edb46e9SPaul Traina 	for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
4434edb46e9SPaul Traina 		if (tp->addr == i)
4444edb46e9SPaul Traina 			return (tp->name);
4454edb46e9SPaul Traina 
4464edb46e9SPaul Traina 	tp->addr = i;
4474edb46e9SPaul Traina 	tp->nxt = newhnamemem();
4484edb46e9SPaul Traina 
4494edb46e9SPaul Traina 	cp = buf;
4504edb46e9SPaul Traina 	(void)strcpy(cp, "sap ");
4514edb46e9SPaul Traina 	cp += strlen(cp);
4524edb46e9SPaul Traina 	*cp++ = hex[sap >> 4 & 0xf];
4534edb46e9SPaul Traina 	*cp++ = hex[sap & 0xf];
4544edb46e9SPaul Traina 	*cp++ = '\0';
4554edb46e9SPaul Traina 	tp->name = savestr(buf);
4564edb46e9SPaul Traina 	return (tp->name);
4574edb46e9SPaul Traina }
4584edb46e9SPaul Traina 
4594edb46e9SPaul Traina char *
4604edb46e9SPaul Traina isonsap_string(const u_char *nsap)
4614edb46e9SPaul Traina {
4624edb46e9SPaul Traina 	register u_int i, nlen = nsap[0];
4634edb46e9SPaul Traina 	register char *cp;
4644edb46e9SPaul Traina 	register struct enamemem *tp;
4654edb46e9SPaul Traina 
4664edb46e9SPaul Traina 	tp = lookup_nsap(nsap);
4674edb46e9SPaul Traina 	if (tp->e_name)
4684edb46e9SPaul Traina 		return tp->e_name;
4694edb46e9SPaul Traina 
4704edb46e9SPaul Traina 	tp->e_name = cp = (char *)malloc(nlen * 2 + 2);
4714edb46e9SPaul Traina 	if (cp == NULL)
4724edb46e9SPaul Traina 		error("isonsap_string: malloc");
4734edb46e9SPaul Traina 
4744edb46e9SPaul Traina 	nsap++;
4754edb46e9SPaul Traina 	*cp++ = '/';
4764edb46e9SPaul Traina 	for (i = nlen; (int)--i >= 0;) {
4774edb46e9SPaul Traina 		*cp++ = hex[*nsap >> 4];
4784edb46e9SPaul Traina 		*cp++ = hex[*nsap++ & 0xf];
4794edb46e9SPaul Traina 	}
4804edb46e9SPaul Traina 	*cp = '\0';
4814edb46e9SPaul Traina 	return (tp->e_name);
4824edb46e9SPaul Traina }
4834edb46e9SPaul Traina 
4844edb46e9SPaul Traina char *
4854edb46e9SPaul Traina tcpport_string(u_short port)
4864edb46e9SPaul Traina {
4874edb46e9SPaul Traina 	register struct hnamemem *tp;
4884edb46e9SPaul Traina 	register u_int32_t i = port;
4894edb46e9SPaul Traina 	char buf[sizeof("00000")];
4904edb46e9SPaul Traina 
4914edb46e9SPaul Traina 	for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
4924edb46e9SPaul Traina 		if (tp->addr == i)
4934edb46e9SPaul Traina 			return (tp->name);
4944edb46e9SPaul Traina 
4954edb46e9SPaul Traina 	tp->addr = i;
4964edb46e9SPaul Traina 	tp->nxt = newhnamemem();
4974edb46e9SPaul Traina 
4984edb46e9SPaul Traina 	(void)sprintf(buf, "%u", i);
4994edb46e9SPaul Traina 	tp->name = savestr(buf);
5004edb46e9SPaul Traina 	return (tp->name);
5014edb46e9SPaul Traina }
5024edb46e9SPaul Traina 
5034edb46e9SPaul Traina char *
5044edb46e9SPaul Traina udpport_string(register u_short port)
5054edb46e9SPaul Traina {
5064edb46e9SPaul Traina 	register struct hnamemem *tp;
5074edb46e9SPaul Traina 	register u_int32_t i = port;
5084edb46e9SPaul Traina 	char buf[sizeof("00000")];
5094edb46e9SPaul Traina 
5104edb46e9SPaul Traina 	for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
5114edb46e9SPaul Traina 		if (tp->addr == i)
5124edb46e9SPaul Traina 			return (tp->name);
5134edb46e9SPaul Traina 
5144edb46e9SPaul Traina 	tp->addr = i;
5154edb46e9SPaul Traina 	tp->nxt = newhnamemem();
5164edb46e9SPaul Traina 
5174edb46e9SPaul Traina 	(void)sprintf(buf, "%u", i);
5184edb46e9SPaul Traina 	tp->name = savestr(buf);
5194edb46e9SPaul Traina 	return (tp->name);
5204edb46e9SPaul Traina }
5214edb46e9SPaul Traina 
5224edb46e9SPaul Traina static void
5234edb46e9SPaul Traina init_servarray(void)
5244edb46e9SPaul Traina {
5254edb46e9SPaul Traina 	struct servent *sv;
5264edb46e9SPaul Traina 	register struct hnamemem *table;
5274edb46e9SPaul Traina 	register int i;
5284edb46e9SPaul Traina 	char buf[sizeof("0000000000")];
5294edb46e9SPaul Traina 
5304edb46e9SPaul Traina 	while ((sv = getservent()) != NULL) {
5314edb46e9SPaul Traina 		int port = ntohs(sv->s_port);
5324edb46e9SPaul Traina 		i = port & (HASHNAMESIZE-1);
5334edb46e9SPaul Traina 		if (strcmp(sv->s_proto, "tcp") == 0)
5344edb46e9SPaul Traina 			table = &tporttable[i];
5354edb46e9SPaul Traina 		else if (strcmp(sv->s_proto, "udp") == 0)
5364edb46e9SPaul Traina 			table = &uporttable[i];
5374edb46e9SPaul Traina 		else
5384edb46e9SPaul Traina 			continue;
5394edb46e9SPaul Traina 
5404edb46e9SPaul Traina 		while (table->name)
5414edb46e9SPaul Traina 			table = table->nxt;
5424edb46e9SPaul Traina 		if (nflag) {
5434edb46e9SPaul Traina 			(void)sprintf(buf, "%d", port);
5444edb46e9SPaul Traina 			table->name = savestr(buf);
5454edb46e9SPaul Traina 		} else
5464edb46e9SPaul Traina 			table->name = savestr(sv->s_name);
5474edb46e9SPaul Traina 		table->addr = port;
5484edb46e9SPaul Traina 		table->nxt = newhnamemem();
5494edb46e9SPaul Traina 	}
5504edb46e9SPaul Traina 	endservent();
5514edb46e9SPaul Traina }
5524edb46e9SPaul Traina 
5534edb46e9SPaul Traina /*XXX from libbpfc.a */
5544edb46e9SPaul Traina extern struct eproto {
5554edb46e9SPaul Traina 	char *s;
5564edb46e9SPaul Traina 	u_short p;
5574edb46e9SPaul Traina } eproto_db[];
5584edb46e9SPaul Traina 
5594edb46e9SPaul Traina static void
5604edb46e9SPaul Traina init_eprotoarray(void)
5614edb46e9SPaul Traina {
5624edb46e9SPaul Traina 	register int i;
5634edb46e9SPaul Traina 	register struct hnamemem *table;
5644edb46e9SPaul Traina 
5654edb46e9SPaul Traina 	for (i = 0; eproto_db[i].s; i++) {
5664edb46e9SPaul Traina 		int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
5674edb46e9SPaul Traina 		table = &eprototable[j];
5684edb46e9SPaul Traina 		while (table->name)
5694edb46e9SPaul Traina 			table = table->nxt;
5704edb46e9SPaul Traina 		table->name = eproto_db[i].s;
5714edb46e9SPaul Traina 		table->addr = ntohs(eproto_db[i].p);
5724edb46e9SPaul Traina 		table->nxt = newhnamemem();
5734edb46e9SPaul Traina 	}
5744edb46e9SPaul Traina }
5754edb46e9SPaul Traina 
5764edb46e9SPaul Traina /*
5774edb46e9SPaul Traina  * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
5784edb46e9SPaul Traina  * types.
5794edb46e9SPaul Traina  */
5804edb46e9SPaul Traina static void
5814edb46e9SPaul Traina init_protoidarray(void)
5824edb46e9SPaul Traina {
5834edb46e9SPaul Traina 	register int i;
5844edb46e9SPaul Traina 	register struct protoidmem *tp;
5854edb46e9SPaul Traina 	u_char protoid[5];
5864edb46e9SPaul Traina 
5874edb46e9SPaul Traina 	protoid[0] = 0;
5884edb46e9SPaul Traina 	protoid[1] = 0;
5894edb46e9SPaul Traina 	protoid[2] = 0;
5904edb46e9SPaul Traina 	for (i = 0; eproto_db[i].s; i++) {
5914edb46e9SPaul Traina 		u_short etype = htons(eproto_db[i].p);
5924edb46e9SPaul Traina 
5934edb46e9SPaul Traina 		memcpy((char *)&protoid[3], (char *)&etype, 2);
5944edb46e9SPaul Traina 		tp = lookup_protoid(protoid);
5954edb46e9SPaul Traina 		tp->p_name = savestr(eproto_db[i].s);
5964edb46e9SPaul Traina 	}
5974edb46e9SPaul Traina }
5984edb46e9SPaul Traina 
5994edb46e9SPaul Traina static struct etherlist {
6004edb46e9SPaul Traina 	u_char addr[6];
6014edb46e9SPaul Traina 	char *name;
6024edb46e9SPaul Traina } etherlist[] = {
6034edb46e9SPaul Traina 	{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
6044edb46e9SPaul Traina 	{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
6054edb46e9SPaul Traina };
6064edb46e9SPaul Traina 
6074edb46e9SPaul Traina /*
6084edb46e9SPaul Traina  * Initialize the ethers hash table.  We take two different approaches
6094edb46e9SPaul Traina  * depending on whether or not the system provides the ethers name
6104edb46e9SPaul Traina  * service.  If it does, we just wire in a few names at startup,
6114edb46e9SPaul Traina  * and etheraddr_string() fills in the table on demand.  If it doesn't,
6124edb46e9SPaul Traina  * then we suck in the entire /etc/ethers file at startup.  The idea
6134edb46e9SPaul Traina  * is that parsing the local file will be fast, but spinning through
6144edb46e9SPaul Traina  * all the ethers entries via NIS & next_etherent might be very slow.
6154edb46e9SPaul Traina  *
6164edb46e9SPaul Traina  * XXX pcap_next_etherent doesn't belong in the pcap interface, but
6174edb46e9SPaul Traina  * since the pcap module already does name-to-address translation,
6184edb46e9SPaul Traina  * it's already does most of the work for the ethernet address-to-name
6194edb46e9SPaul Traina  * translation, so we just pcap_next_etherent as a convenience.
6204edb46e9SPaul Traina  */
6214edb46e9SPaul Traina static void
6224edb46e9SPaul Traina init_etherarray(void)
6234edb46e9SPaul Traina {
6244edb46e9SPaul Traina 	register struct etherlist *el;
6254edb46e9SPaul Traina 	register struct enamemem *tp;
6264edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST
6274edb46e9SPaul Traina 	char name[256];
6284edb46e9SPaul Traina #else
6294edb46e9SPaul Traina 	register struct pcap_etherent *ep;
6304edb46e9SPaul Traina 	register FILE *fp;
6314edb46e9SPaul Traina 
6324edb46e9SPaul Traina 	/* Suck in entire ethers file */
6334edb46e9SPaul Traina 	fp = fopen(PCAP_ETHERS_FILE, "r");
6344edb46e9SPaul Traina 	if (fp != NULL) {
6354edb46e9SPaul Traina 		while ((ep = pcap_next_etherent(fp)) != NULL) {
6364edb46e9SPaul Traina 			tp = lookup_emem(ep->addr);
6374edb46e9SPaul Traina 			tp->e_name = savestr(ep->name);
6384edb46e9SPaul Traina 		}
6394edb46e9SPaul Traina 		(void)fclose(fp);
6404edb46e9SPaul Traina 	}
6414edb46e9SPaul Traina #endif
6424edb46e9SPaul Traina 
6434edb46e9SPaul Traina 	/* Hardwire some ethernet names */
6444edb46e9SPaul Traina 	for (el = etherlist; el->name != NULL; ++el) {
6454edb46e9SPaul Traina 		tp = lookup_emem(el->addr);
6464edb46e9SPaul Traina 		/* Don't override existing name */
6474edb46e9SPaul Traina 		if (tp->e_name != NULL)
6484edb46e9SPaul Traina 			continue;
6494edb46e9SPaul Traina 
6504edb46e9SPaul Traina #ifdef HAVE_ETHER_NTOHOST
6514edb46e9SPaul Traina                 /* Use yp/nis version of name if available */
6524edb46e9SPaul Traina                 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
6534edb46e9SPaul Traina                         tp->e_name = savestr(name);
6544edb46e9SPaul Traina 			continue;
6554edb46e9SPaul Traina 		}
6564edb46e9SPaul Traina #endif
6574edb46e9SPaul Traina 		tp->e_name = el->name;
6584edb46e9SPaul Traina 	}
6594edb46e9SPaul Traina }
6604edb46e9SPaul Traina 
6614edb46e9SPaul Traina static struct tok llcsap_db[] = {
6624edb46e9SPaul Traina 	{ LLCSAP_NULL,		"null" },
6634edb46e9SPaul Traina 	{ LLCSAP_8021B_I,	"802.1b-gsap" },
6644edb46e9SPaul Traina 	{ LLCSAP_8021B_G,	"802.1b-isap" },
6654edb46e9SPaul Traina 	{ LLCSAP_IP,		"ip-sap" },
6664edb46e9SPaul Traina 	{ LLCSAP_PROWAYNM,	"proway-nm" },
6674edb46e9SPaul Traina 	{ LLCSAP_8021D,		"802.1d" },
6684edb46e9SPaul Traina 	{ LLCSAP_RS511,		"eia-rs511" },
6694edb46e9SPaul Traina 	{ LLCSAP_ISO8208,	"x.25/llc2" },
6704edb46e9SPaul Traina 	{ LLCSAP_PROWAY,	"proway" },
6714edb46e9SPaul Traina 	{ LLCSAP_ISONS,		"iso-clns" },
6724edb46e9SPaul Traina 	{ LLCSAP_GLOBAL,	"global" },
6734edb46e9SPaul Traina 	{ 0,			NULL }
6744edb46e9SPaul Traina };
6754edb46e9SPaul Traina 
6764edb46e9SPaul Traina static void
6774edb46e9SPaul Traina init_llcsaparray(void)
6784edb46e9SPaul Traina {
6794edb46e9SPaul Traina 	register int i;
6804edb46e9SPaul Traina 	register struct hnamemem *table;
6814edb46e9SPaul Traina 
6824edb46e9SPaul Traina 	for (i = 0; llcsap_db[i].s != NULL; i++) {
6834edb46e9SPaul Traina 		table = &llcsaptable[llcsap_db[i].v];
6844edb46e9SPaul Traina 		while (table->name)
6854edb46e9SPaul Traina 			table = table->nxt;
6864edb46e9SPaul Traina 		table->name = llcsap_db[i].s;
6874edb46e9SPaul Traina 		table->addr = llcsap_db[i].v;
6884edb46e9SPaul Traina 		table->nxt = newhnamemem();
6894edb46e9SPaul Traina 	}
6904edb46e9SPaul Traina }
6914edb46e9SPaul Traina 
6924edb46e9SPaul Traina /*
6934edb46e9SPaul Traina  * Initialize the address to name translation machinery.  We map all
6944edb46e9SPaul Traina  * non-local IP addresses to numeric addresses if fflag is true (i.e.,
6954edb46e9SPaul Traina  * to prevent blocking on the nameserver).  localnet is the IP address
6964edb46e9SPaul Traina  * of the local network.  mask is its subnet mask.
6974edb46e9SPaul Traina  */
6984edb46e9SPaul Traina void
6994edb46e9SPaul Traina init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask)
7004edb46e9SPaul Traina {
7014edb46e9SPaul Traina 	netmask = mask;
7024edb46e9SPaul Traina 	if (fflag) {
7034edb46e9SPaul Traina 		f_localnet = localnet;
7044edb46e9SPaul Traina 		f_netmask = mask;
7054edb46e9SPaul Traina 	}
7064edb46e9SPaul Traina 	if (nflag)
7074edb46e9SPaul Traina 		/*
7084edb46e9SPaul Traina 		 * Simplest way to suppress names.
7094edb46e9SPaul Traina 		 */
7104edb46e9SPaul Traina 		return;
7114edb46e9SPaul Traina 
7124edb46e9SPaul Traina 	init_etherarray();
7134edb46e9SPaul Traina 	init_servarray();
7144edb46e9SPaul Traina 	init_eprotoarray();
7154edb46e9SPaul Traina 	init_llcsaparray();
7164edb46e9SPaul Traina 	init_protoidarray();
7174edb46e9SPaul Traina }
7184edb46e9SPaul Traina 
7194edb46e9SPaul Traina char *
7204edb46e9SPaul Traina dnaddr_string(u_short dnaddr)
7214edb46e9SPaul Traina {
7224edb46e9SPaul Traina 	register struct hnamemem *tp;
7234edb46e9SPaul Traina 
7244edb46e9SPaul Traina 	for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
7254edb46e9SPaul Traina 	     tp = tp->nxt)
7264edb46e9SPaul Traina 		if (tp->addr == dnaddr)
7274edb46e9SPaul Traina 			return (tp->name);
7284edb46e9SPaul Traina 
7294edb46e9SPaul Traina 	tp->addr = dnaddr;
7304edb46e9SPaul Traina 	tp->nxt = newhnamemem();
7314edb46e9SPaul Traina 	if (nflag)
7324edb46e9SPaul Traina 		tp->name = dnnum_string(dnaddr);
7334edb46e9SPaul Traina 	else
7344edb46e9SPaul Traina 		tp->name = dnname_string(dnaddr);
7354edb46e9SPaul Traina 
7364edb46e9SPaul Traina 	return(tp->name);
7374edb46e9SPaul Traina }
7384edb46e9SPaul Traina 
7394edb46e9SPaul Traina /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
7404edb46e9SPaul Traina struct hnamemem *
7414edb46e9SPaul Traina newhnamemem()
7424edb46e9SPaul Traina {
7434edb46e9SPaul Traina 	register struct hnamemem *p;
7444edb46e9SPaul Traina 	static struct hnamemem *ptr = NULL;
7454edb46e9SPaul Traina 	static u_int num = 0;
7464edb46e9SPaul Traina 
7474edb46e9SPaul Traina 	if (num  <= 0) {
7484edb46e9SPaul Traina 		num = 64;
7494edb46e9SPaul Traina 		ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
7504edb46e9SPaul Traina 		if (ptr == NULL)
7514edb46e9SPaul Traina 			error("newhnamemem: calloc");
7524edb46e9SPaul Traina 	}
7534edb46e9SPaul Traina 	--num;
7544edb46e9SPaul Traina 	p = ptr++;
7554edb46e9SPaul Traina 	return (p);
7564edb46e9SPaul Traina }
757