addrtoname.c revision 66644
117680Spst/*
239300Sfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017680Spst *
2117680Spst *  Internet, ethernet, port, and protocol string to address
2217680Spst *  and address to string conversion routines
2356896Sfenner *
2456896Sfenner * $FreeBSD: head/contrib/tcpdump/addrtoname.c 66644 2000-10-05 02:49:49Z kris $
2517680Spst */
2617680Spst#ifndef lint
2726183Sfennerstatic const char rcsid[] =
2856896Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.64 1999/11/21 09:36:44 fenner Exp $ (LBL)";
2917680Spst#endif
3017680Spst
3156896Sfenner#ifdef HAVE_CONFIG_H
3256896Sfenner#include "config.h"
3356896Sfenner#endif
3456896Sfenner
3517680Spst#include <sys/types.h>
3617680Spst#include <sys/socket.h>
3717680Spst#include <sys/time.h>
3817680Spst
3917680Spst#if __STDC__
4017680Spststruct mbuf;
4117680Spststruct rtentry;
4217680Spst#endif
4317680Spst#include <net/if.h>
4417680Spst
4517680Spst#include <netinet/in.h>
4621262Swollman#include <net/ethernet.h>
4717680Spst
4856896Sfenner#ifdef INET6
4957809Sfenner#include <netinet/ip6.h>
5056896Sfenner#endif
5156896Sfenner
5217680Spst#include <arpa/inet.h>
5317680Spst
5417680Spst#include <ctype.h>
5517680Spst#include <netdb.h>
5617680Spst#include <pcap.h>
5717680Spst#include <pcap-namedb.h>
5839300Sfenner#ifdef HAVE_MALLOC_H
5939300Sfenner#include <malloc.h>
6039300Sfenner#endif
6139300Sfenner#ifdef HAVE_MEMORY_H
6239300Sfenner#include <memory.h>
6339300Sfenner#endif
6417680Spst#include <signal.h>
6517680Spst#include <stdio.h>
6617680Spst#include <string.h>
6717680Spst#include <stdlib.h>
6817680Spst#include <unistd.h>
6917680Spst
7017680Spst#include "interface.h"
7117680Spst#include "addrtoname.h"
7217680Spst#include "llc.h"
7339300Sfenner#include "savestr.h"
7439300Sfenner#include "setsignal.h"
7517680Spst
7617680Spst/* Forwards */
7717680Spststatic RETSIGTYPE nohostname(int);
7817680Spst
7917680Spst/*
8017680Spst * hash tables for whatever-to-name translations
8117680Spst */
8217680Spst
8317680Spst#define HASHNAMESIZE 4096
8417680Spst
8517680Spststruct hnamemem {
8617680Spst	u_int32_t addr;
8717680Spst	char *name;
8817680Spst	struct hnamemem *nxt;
8917680Spst};
9017680Spst
9117680Spststruct hnamemem hnametable[HASHNAMESIZE];
9217680Spststruct hnamemem tporttable[HASHNAMESIZE];
9317680Spststruct hnamemem uporttable[HASHNAMESIZE];
9417680Spststruct hnamemem eprototable[HASHNAMESIZE];
9517680Spststruct hnamemem dnaddrtable[HASHNAMESIZE];
9617680Spststruct hnamemem llcsaptable[HASHNAMESIZE];
9717680Spst
9856896Sfenner#ifdef INET6
9956896Sfennerstruct h6namemem {
10056896Sfenner	struct in6_addr addr;
10156896Sfenner	char *name;
10256896Sfenner	struct h6namemem *nxt;
10356896Sfenner};
10456896Sfenner
10556896Sfennerstruct h6namemem h6nametable[HASHNAMESIZE];
10656896Sfenner#endif /* INET6 */
10756896Sfenner
10817680Spststruct enamemem {
10917680Spst	u_short e_addr0;
11017680Spst	u_short e_addr1;
11117680Spst	u_short e_addr2;
11217680Spst	char *e_name;
11317680Spst	u_char *e_nsap;			/* used only for nsaptable[] */
11417680Spst	struct enamemem *e_nxt;
11517680Spst};
11617680Spst
11717680Spststruct enamemem enametable[HASHNAMESIZE];
11817680Spststruct enamemem nsaptable[HASHNAMESIZE];
11917680Spst
12017680Spststruct protoidmem {
12117680Spst	u_int32_t p_oui;
12217680Spst	u_short p_proto;
12317680Spst	char *p_name;
12417680Spst	struct protoidmem *p_nxt;
12517680Spst};
12617680Spst
12717680Spststruct protoidmem protoidtable[HASHNAMESIZE];
12817680Spst
12917680Spst/*
13017680Spst * A faster replacement for inet_ntoa().
13117680Spst */
13217680Spstchar *
13317680Spstintoa(u_int32_t addr)
13417680Spst{
13517680Spst	register char *cp;
13617680Spst	register u_int byte;
13717680Spst	register int n;
13817680Spst	static char buf[sizeof(".xxx.xxx.xxx.xxx")];
13917680Spst
14017680Spst	NTOHL(addr);
14117680Spst	cp = &buf[sizeof buf];
14217680Spst	*--cp = '\0';
14317680Spst
14417680Spst	n = 4;
14517680Spst	do {
14617680Spst		byte = addr & 0xff;
14717680Spst		*--cp = byte % 10 + '0';
14817680Spst		byte /= 10;
14917680Spst		if (byte > 0) {
15017680Spst			*--cp = byte % 10 + '0';
15117680Spst			byte /= 10;
15217680Spst			if (byte > 0)
15317680Spst				*--cp = byte + '0';
15417680Spst		}
15517680Spst		*--cp = '.';
15617680Spst		addr >>= 8;
15717680Spst	} while (--n > 0);
15817680Spst
15917680Spst	return cp + 1;
16017680Spst}
16117680Spst
16217680Spststatic u_int32_t f_netmask;
16317680Spststatic u_int32_t f_localnet;
16417680Spststatic u_int32_t netmask;
16517680Spst
16617680Spst/*
16717680Spst * "getname" is written in this atrocious way to make sure we don't
16817680Spst * wait forever while trying to get hostnames from yp.
16917680Spst */
17017680Spst#include <setjmp.h>
17117680Spst
17217680Spstjmp_buf getname_env;
17317680Spst
17417680Spststatic RETSIGTYPE
17517680Spstnohostname(int signo)
17617680Spst{
17717680Spst	longjmp(getname_env, 1);
17817680Spst}
17917680Spst
18017680Spst/*
18117680Spst * Return a name for the IP address pointed to by ap.  This address
18217680Spst * is assumed to be in network byte order.
18317680Spst */
18417680Spstchar *
18517680Spstgetname(const u_char *ap)
18617680Spst{
18717680Spst	register struct hostent *hp;
18817680Spst	u_int32_t addr;
18917680Spst	static struct hnamemem *p;		/* static for longjmp() */
19017680Spst
19117680Spst#ifndef LBL_ALIGN
19217680Spst	addr = *(const u_int32_t *)ap;
19317680Spst#else
19456896Sfenner	memcpy(&addr, ap, sizeof(addr));
19517680Spst#endif
19617680Spst	p = &hnametable[addr & (HASHNAMESIZE-1)];
19717680Spst	for (; p->nxt; p = p->nxt) {
19817680Spst		if (p->addr == addr)
19917680Spst			return (p->name);
20017680Spst	}
20117680Spst	p->addr = addr;
20217680Spst	p->nxt = newhnamemem();
20317680Spst
20417680Spst	/*
20517680Spst	 * Only print names when:
20617680Spst	 *	(1) -n was not given.
20739300Sfenner	 *      (2) Address is foreign and -f was given. (If -f was not
20839300Sfenner	 *	    give, f_netmask and f_local are 0 and the test
20939300Sfenner	 *	    evaluates to true)
21039300Sfenner	 *      (3) -a was given or the host portion is not all ones
21139300Sfenner	 *          nor all zeros (i.e. not a network or broadcast address)
21217680Spst	 */
21339300Sfenner	if (!nflag &&
21439300Sfenner	    (addr & f_netmask) == f_localnet &&
21539300Sfenner	    (aflag ||
21639300Sfenner	    !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) {
21717680Spst		if (!setjmp(getname_env)) {
21839300Sfenner			(void)setsignal(SIGALRM, nohostname);
21917680Spst			(void)alarm(20);
22017680Spst			hp = gethostbyaddr((char *)&addr, 4, AF_INET);
22117680Spst			(void)alarm(0);
22217680Spst			if (hp) {
22317680Spst				char *dotp;
22417680Spst
22517680Spst				p->name = savestr(hp->h_name);
22617680Spst				if (Nflag) {
22717680Spst					/* Remove domain qualifications */
22817680Spst					dotp = strchr(p->name, '.');
22917680Spst					if (dotp)
23017680Spst						*dotp = '\0';
23117680Spst				}
23217680Spst				return (p->name);
23317680Spst			}
23417680Spst		}
23517680Spst	}
23617680Spst	p->name = savestr(intoa(addr));
23717680Spst	return (p->name);
23817680Spst}
23917680Spst
24056896Sfenner#ifdef INET6
24156896Sfenner/*
24256896Sfenner * Return a name for the IP6 address pointed to by ap.  This address
24356896Sfenner * is assumed to be in network byte order.
24456896Sfenner */
24556896Sfennerchar *
24656896Sfennergetname6(const u_char *ap)
24756896Sfenner{
24856896Sfenner	register struct hostent *hp;
24956896Sfenner	struct in6_addr addr;
25056896Sfenner	static struct h6namemem *p;		/* static for longjmp() */
25156896Sfenner	register char *cp;
25256896Sfenner	char ntop_buf[INET6_ADDRSTRLEN];
25356896Sfenner
25456896Sfenner	memcpy(&addr, ap, sizeof(addr));
25556896Sfenner	p = &h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)];
25656896Sfenner	for (; p->nxt; p = p->nxt) {
25756896Sfenner		if (memcmp(&p->addr, &addr, sizeof(addr)) == 0)
25856896Sfenner			return (p->name);
25956896Sfenner	}
26056896Sfenner	p->addr = addr;
26156896Sfenner	p->nxt = newh6namemem();
26256896Sfenner
26356896Sfenner	/*
26456896Sfenner	 * Only print names when:
26556896Sfenner	 *	(1) -n was not given.
26656896Sfenner	 *      (2) Address is foreign and -f was given. (If -f was not
26756896Sfenner	 *	    give, f_netmask and f_local are 0 and the test
26856896Sfenner	 *	    evaluates to true)
26956896Sfenner	 *      (3) -a was given or the host portion is not all ones
27056896Sfenner	 *          nor all zeros (i.e. not a network or broadcast address)
27156896Sfenner	 */
27256896Sfenner	if (!nflag
27356896Sfenner#if 0
27456896Sfenner	&&
27556896Sfenner	    (addr & f_netmask) == f_localnet &&
27656896Sfenner	    (aflag ||
27756896Sfenner	    !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))
27856896Sfenner#endif
27956896Sfenner	    ) {
28056896Sfenner		if (!setjmp(getname_env)) {
28156896Sfenner			(void)setsignal(SIGALRM, nohostname);
28256896Sfenner			(void)alarm(20);
28356896Sfenner			hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);
28456896Sfenner			(void)alarm(0);
28556896Sfenner			if (hp) {
28656896Sfenner				char *dotp;
28756896Sfenner
28856896Sfenner				p->name = savestr(hp->h_name);
28956896Sfenner				if (Nflag) {
29056896Sfenner					/* Remove domain qualifications */
29156896Sfenner					dotp = strchr(p->name, '.');
29256896Sfenner					if (dotp)
29356896Sfenner						*dotp = '\0';
29456896Sfenner				}
29556896Sfenner				return (p->name);
29656896Sfenner			}
29756896Sfenner		}
29856896Sfenner	}
29956896Sfenner	cp = (char *)inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf));
30056896Sfenner	p->name = savestr(cp);
30156896Sfenner	return (p->name);
30256896Sfenner}
30356896Sfenner#endif /* INET6 */
30456896Sfenner
30517680Spststatic char hex[] = "0123456789abcdef";
30617680Spst
30717680Spst
30817680Spst/* Find the hash node that corresponds the ether address 'ep' */
30917680Spst
31017680Spststatic inline struct enamemem *
31117680Spstlookup_emem(const u_char *ep)
31217680Spst{
31317680Spst	register u_int i, j, k;
31417680Spst	struct enamemem *tp;
31517680Spst
31617680Spst	k = (ep[0] << 8) | ep[1];
31717680Spst	j = (ep[2] << 8) | ep[3];
31817680Spst	i = (ep[4] << 8) | ep[5];
31917680Spst
32017680Spst	tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
32117680Spst	while (tp->e_nxt)
32217680Spst		if (tp->e_addr0 == i &&
32317680Spst		    tp->e_addr1 == j &&
32417680Spst		    tp->e_addr2 == k)
32517680Spst			return tp;
32617680Spst		else
32717680Spst			tp = tp->e_nxt;
32817680Spst	tp->e_addr0 = i;
32917680Spst	tp->e_addr1 = j;
33017680Spst	tp->e_addr2 = k;
33117680Spst	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
33217680Spst	if (tp->e_nxt == NULL)
33317680Spst		error("lookup_emem: calloc");
33417680Spst
33517680Spst	return tp;
33617680Spst}
33717680Spst
33817680Spst/* Find the hash node that corresponds the NSAP 'nsap' */
33917680Spst
34017680Spststatic inline struct enamemem *
34117680Spstlookup_nsap(register const u_char *nsap)
34217680Spst{
34317680Spst	register u_int i, j, k;
34417680Spst	int nlen = *nsap;
34517680Spst	struct enamemem *tp;
34617680Spst	const u_char *ensap = nsap + nlen - 6;
34717680Spst
34817680Spst	if (nlen > 6) {
34917680Spst		k = (ensap[0] << 8) | ensap[1];
35017680Spst		j = (ensap[2] << 8) | ensap[3];
35117680Spst		i = (ensap[4] << 8) | ensap[5];
35217680Spst	}
35317680Spst	else
35417680Spst		i = j = k = 0;
35517680Spst
35617680Spst	tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
35717680Spst	while (tp->e_nxt)
35817680Spst		if (tp->e_addr0 == i &&
35917680Spst		    tp->e_addr1 == j &&
36017680Spst		    tp->e_addr2 == k &&
36117680Spst		    tp->e_nsap[0] == nlen &&
36217680Spst		    memcmp((char *)&(nsap[1]),
36317680Spst			(char *)&(tp->e_nsap[1]), nlen) == 0)
36417680Spst			return tp;
36517680Spst		else
36617680Spst			tp = tp->e_nxt;
36717680Spst	tp->e_addr0 = i;
36817680Spst	tp->e_addr1 = j;
36917680Spst	tp->e_addr2 = k;
37017680Spst	tp->e_nsap = (u_char *)malloc(nlen + 1);
37117680Spst	if (tp->e_nsap == NULL)
37217680Spst		error("lookup_nsap: malloc");
37339300Sfenner	memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1);
37417680Spst	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
37517680Spst	if (tp->e_nxt == NULL)
37617680Spst		error("lookup_nsap: calloc");
37717680Spst
37817680Spst	return tp;
37917680Spst}
38017680Spst
38117680Spst/* Find the hash node that corresponds the protoid 'pi'. */
38217680Spst
38317680Spststatic inline struct protoidmem *
38417680Spstlookup_protoid(const u_char *pi)
38517680Spst{
38617680Spst	register u_int i, j;
38717680Spst	struct protoidmem *tp;
38817680Spst
38917680Spst	/* 5 octets won't be aligned */
39017680Spst	i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
39117680Spst	j =   (pi[3] << 8) + pi[4];
39217680Spst	/* XXX should be endian-insensitive, but do big-endian testing  XXX */
39317680Spst
39417680Spst	tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
39517680Spst	while (tp->p_nxt)
39617680Spst		if (tp->p_oui == i && tp->p_proto == j)
39717680Spst			return tp;
39817680Spst		else
39917680Spst			tp = tp->p_nxt;
40017680Spst	tp->p_oui = i;
40117680Spst	tp->p_proto = j;
40217680Spst	tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
40317680Spst	if (tp->p_nxt == NULL)
40417680Spst		error("lookup_protoid: calloc");
40517680Spst
40617680Spst	return tp;
40717680Spst}
40817680Spst
40917680Spstchar *
41017680Spstetheraddr_string(register const u_char *ep)
41117680Spst{
41217680Spst	register u_int i, j;
41317680Spst	register char *cp;
41417680Spst	register struct enamemem *tp;
41517680Spst	char buf[sizeof("00:00:00:00:00:00")];
41617680Spst
41717680Spst	tp = lookup_emem(ep);
41817680Spst	if (tp->e_name)
41917680Spst		return (tp->e_name);
42017680Spst#ifdef HAVE_ETHER_NTOHOST
42117680Spst	if (!nflag) {
42217680Spst		char buf[128];
42317680Spst		if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
42417680Spst			tp->e_name = savestr(buf);
42517680Spst			return (tp->e_name);
42617680Spst		}
42717680Spst	}
42817680Spst#endif
42917680Spst	cp = buf;
43017680Spst	if ((j = *ep >> 4) != 0)
43117680Spst		*cp++ = hex[j];
43217680Spst	*cp++ = hex[*ep++ & 0xf];
43317680Spst	for (i = 5; (int)--i >= 0;) {
43417680Spst		*cp++ = ':';
43517680Spst		if ((j = *ep >> 4) != 0)
43617680Spst			*cp++ = hex[j];
43717680Spst		*cp++ = hex[*ep++ & 0xf];
43817680Spst	}
43917680Spst	*cp = '\0';
44017680Spst	tp->e_name = savestr(buf);
44117680Spst	return (tp->e_name);
44217680Spst}
44317680Spst
44417680Spstchar *
44517680Spstetherproto_string(u_short port)
44617680Spst{
44717680Spst	register char *cp;
44817680Spst	register struct hnamemem *tp;
44917680Spst	register u_int32_t i = port;
45017680Spst	char buf[sizeof("0000")];
45117680Spst
45217680Spst	for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
45317680Spst		if (tp->addr == i)
45417680Spst			return (tp->name);
45517680Spst
45617680Spst	tp->addr = i;
45717680Spst	tp->nxt = newhnamemem();
45817680Spst
45917680Spst	cp = buf;
46017680Spst	NTOHS(port);
46117680Spst	*cp++ = hex[port >> 12 & 0xf];
46217680Spst	*cp++ = hex[port >> 8 & 0xf];
46317680Spst	*cp++ = hex[port >> 4 & 0xf];
46417680Spst	*cp++ = hex[port & 0xf];
46517680Spst	*cp++ = '\0';
46617680Spst	tp->name = savestr(buf);
46717680Spst	return (tp->name);
46817680Spst}
46917680Spst
47017680Spstchar *
47117680Spstprotoid_string(register const u_char *pi)
47217680Spst{
47317680Spst	register u_int i, j;
47417680Spst	register char *cp;
47517680Spst	register struct protoidmem *tp;
47617680Spst	char buf[sizeof("00:00:00:00:00")];
47717680Spst
47817680Spst	tp = lookup_protoid(pi);
47917680Spst	if (tp->p_name)
48017680Spst		return tp->p_name;
48117680Spst
48217680Spst	cp = buf;
48317680Spst	if ((j = *pi >> 4) != 0)
48417680Spst		*cp++ = hex[j];
48517680Spst	*cp++ = hex[*pi++ & 0xf];
48617680Spst	for (i = 4; (int)--i >= 0;) {
48717680Spst		*cp++ = ':';
48817680Spst		if ((j = *pi >> 4) != 0)
48917680Spst			*cp++ = hex[j];
49017680Spst		*cp++ = hex[*pi++ & 0xf];
49117680Spst	}
49217680Spst	*cp = '\0';
49317680Spst	tp->p_name = savestr(buf);
49417680Spst	return (tp->p_name);
49517680Spst}
49617680Spst
49717680Spstchar *
49817680Spstllcsap_string(u_char sap)
49917680Spst{
50017680Spst	register char *cp;
50117680Spst	register struct hnamemem *tp;
50217680Spst	register u_int32_t i = sap;
50317680Spst	char buf[sizeof("sap 00")];
50417680Spst
50517680Spst	for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
50617680Spst		if (tp->addr == i)
50717680Spst			return (tp->name);
50817680Spst
50917680Spst	tp->addr = i;
51017680Spst	tp->nxt = newhnamemem();
51117680Spst
51217680Spst	cp = buf;
51317680Spst	(void)strcpy(cp, "sap ");
51417680Spst	cp += strlen(cp);
51517680Spst	*cp++ = hex[sap >> 4 & 0xf];
51617680Spst	*cp++ = hex[sap & 0xf];
51717680Spst	*cp++ = '\0';
51817680Spst	tp->name = savestr(buf);
51917680Spst	return (tp->name);
52017680Spst}
52117680Spst
52217680Spstchar *
52317680Spstisonsap_string(const u_char *nsap)
52417680Spst{
52517680Spst	register u_int i, nlen = nsap[0];
52617680Spst	register char *cp;
52717680Spst	register struct enamemem *tp;
52817680Spst
52917680Spst	tp = lookup_nsap(nsap);
53017680Spst	if (tp->e_name)
53117680Spst		return tp->e_name;
53217680Spst
53317688Spst	tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1));
53417680Spst	if (cp == NULL)
53517680Spst		error("isonsap_string: malloc");
53617680Spst
53717680Spst	nsap++;
53817688Spst	for (i = 0; i < nlen; i++) {
53917680Spst		*cp++ = hex[*nsap >> 4];
54017680Spst		*cp++ = hex[*nsap++ & 0xf];
54117688Spst		if (((i & 1) == 0) && (i + 1 < nlen))
54217688Spst			*cp++ = '.';
54317680Spst	}
54417680Spst	*cp = '\0';
54517680Spst	return (tp->e_name);
54617680Spst}
54717680Spst
54817680Spstchar *
54917680Spsttcpport_string(u_short port)
55017680Spst{
55117680Spst	register struct hnamemem *tp;
55217680Spst	register u_int32_t i = port;
55317680Spst	char buf[sizeof("00000")];
55417680Spst
55517680Spst	for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
55617680Spst		if (tp->addr == i)
55717680Spst			return (tp->name);
55817680Spst
55917680Spst	tp->addr = i;
56017680Spst	tp->nxt = newhnamemem();
56117680Spst
56266644Skris	(void)snprintf(buf, sizeof(buf), "%u", i);
56317680Spst	tp->name = savestr(buf);
56417680Spst	return (tp->name);
56517680Spst}
56617680Spst
56717680Spstchar *
56817680Spstudpport_string(register u_short port)
56917680Spst{
57017680Spst	register struct hnamemem *tp;
57117680Spst	register u_int32_t i = port;
57217680Spst	char buf[sizeof("00000")];
57317680Spst
57417680Spst	for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
57517680Spst		if (tp->addr == i)
57617680Spst			return (tp->name);
57717680Spst
57817680Spst	tp->addr = i;
57917680Spst	tp->nxt = newhnamemem();
58017680Spst
58166644Skris	(void)snprintf(buf, sizeof(buf), "%u", i);
58217680Spst	tp->name = savestr(buf);
58317680Spst	return (tp->name);
58417680Spst}
58517680Spst
58617680Spststatic void
58717680Spstinit_servarray(void)
58817680Spst{
58917680Spst	struct servent *sv;
59017680Spst	register struct hnamemem *table;
59117680Spst	register int i;
59217680Spst	char buf[sizeof("0000000000")];
59317680Spst
59417680Spst	while ((sv = getservent()) != NULL) {
59517680Spst		int port = ntohs(sv->s_port);
59617680Spst		i = port & (HASHNAMESIZE-1);
59717680Spst		if (strcmp(sv->s_proto, "tcp") == 0)
59817680Spst			table = &tporttable[i];
59917680Spst		else if (strcmp(sv->s_proto, "udp") == 0)
60017680Spst			table = &uporttable[i];
60117680Spst		else
60217680Spst			continue;
60317680Spst
60417680Spst		while (table->name)
60517680Spst			table = table->nxt;
60617680Spst		if (nflag) {
60766644Skris			(void)snprintf(buf, sizeof(buf), "%d", port);
60817680Spst			table->name = savestr(buf);
60917680Spst		} else
61017680Spst			table->name = savestr(sv->s_name);
61117680Spst		table->addr = port;
61217680Spst		table->nxt = newhnamemem();
61317680Spst	}
61417680Spst	endservent();
61517680Spst}
61617680Spst
61717680Spst/*XXX from libbpfc.a */
61817680Spstextern struct eproto {
61917680Spst	char *s;
62017680Spst	u_short p;
62117680Spst} eproto_db[];
62217680Spst
62317680Spststatic void
62417680Spstinit_eprotoarray(void)
62517680Spst{
62617680Spst	register int i;
62717680Spst	register struct hnamemem *table;
62817680Spst
62917680Spst	for (i = 0; eproto_db[i].s; i++) {
63017680Spst		int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
63117680Spst		table = &eprototable[j];
63217680Spst		while (table->name)
63317680Spst			table = table->nxt;
63417680Spst		table->name = eproto_db[i].s;
63517680Spst		table->addr = ntohs(eproto_db[i].p);
63617680Spst		table->nxt = newhnamemem();
63717680Spst	}
63817680Spst}
63917680Spst
64017680Spst/*
64117680Spst * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
64217680Spst * types.
64317680Spst */
64417680Spststatic void
64517680Spstinit_protoidarray(void)
64617680Spst{
64717680Spst	register int i;
64817680Spst	register struct protoidmem *tp;
64917680Spst	u_char protoid[5];
65017680Spst
65117680Spst	protoid[0] = 0;
65217680Spst	protoid[1] = 0;
65317680Spst	protoid[2] = 0;
65417680Spst	for (i = 0; eproto_db[i].s; i++) {
65517680Spst		u_short etype = htons(eproto_db[i].p);
65617680Spst
65717680Spst		memcpy((char *)&protoid[3], (char *)&etype, 2);
65817680Spst		tp = lookup_protoid(protoid);
65917680Spst		tp->p_name = savestr(eproto_db[i].s);
66017680Spst	}
66117680Spst}
66217680Spst
66317680Spststatic struct etherlist {
66417680Spst	u_char addr[6];
66517680Spst	char *name;
66617680Spst} etherlist[] = {
66717680Spst	{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
66817680Spst	{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
66917680Spst};
67017680Spst
67117680Spst/*
67217680Spst * Initialize the ethers hash table.  We take two different approaches
67317680Spst * depending on whether or not the system provides the ethers name
67417680Spst * service.  If it does, we just wire in a few names at startup,
67517680Spst * and etheraddr_string() fills in the table on demand.  If it doesn't,
67617680Spst * then we suck in the entire /etc/ethers file at startup.  The idea
67717680Spst * is that parsing the local file will be fast, but spinning through
67817680Spst * all the ethers entries via NIS & next_etherent might be very slow.
67917680Spst *
68017680Spst * XXX pcap_next_etherent doesn't belong in the pcap interface, but
68117680Spst * since the pcap module already does name-to-address translation,
68217680Spst * it's already does most of the work for the ethernet address-to-name
68317680Spst * translation, so we just pcap_next_etherent as a convenience.
68417680Spst */
68517680Spststatic void
68617680Spstinit_etherarray(void)
68717680Spst{
68817680Spst	register struct etherlist *el;
68917680Spst	register struct enamemem *tp;
69017680Spst#ifdef HAVE_ETHER_NTOHOST
69117680Spst	char name[256];
69217680Spst#else
69317680Spst	register struct pcap_etherent *ep;
69417680Spst	register FILE *fp;
69517680Spst
69617680Spst	/* Suck in entire ethers file */
69717680Spst	fp = fopen(PCAP_ETHERS_FILE, "r");
69817680Spst	if (fp != NULL) {
69917680Spst		while ((ep = pcap_next_etherent(fp)) != NULL) {
70017680Spst			tp = lookup_emem(ep->addr);
70117680Spst			tp->e_name = savestr(ep->name);
70217680Spst		}
70317680Spst		(void)fclose(fp);
70417680Spst	}
70517680Spst#endif
70617680Spst
70717680Spst	/* Hardwire some ethernet names */
70817680Spst	for (el = etherlist; el->name != NULL; ++el) {
70917680Spst		tp = lookup_emem(el->addr);
71017680Spst		/* Don't override existing name */
71117680Spst		if (tp->e_name != NULL)
71217680Spst			continue;
71317680Spst
71417680Spst#ifdef HAVE_ETHER_NTOHOST
71517680Spst                /* Use yp/nis version of name if available */
71617680Spst                if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
71717680Spst                        tp->e_name = savestr(name);
71817680Spst			continue;
71917680Spst		}
72017680Spst#endif
72117680Spst		tp->e_name = el->name;
72217680Spst	}
72317680Spst}
72417680Spst
72517680Spststatic struct tok llcsap_db[] = {
72617680Spst	{ LLCSAP_NULL,		"null" },
72717680Spst	{ LLCSAP_8021B_I,	"802.1b-gsap" },
72817680Spst	{ LLCSAP_8021B_G,	"802.1b-isap" },
72917680Spst	{ LLCSAP_IP,		"ip-sap" },
73017680Spst	{ LLCSAP_PROWAYNM,	"proway-nm" },
73117680Spst	{ LLCSAP_8021D,		"802.1d" },
73217680Spst	{ LLCSAP_RS511,		"eia-rs511" },
73317680Spst	{ LLCSAP_ISO8208,	"x.25/llc2" },
73417680Spst	{ LLCSAP_PROWAY,	"proway" },
73517680Spst	{ LLCSAP_ISONS,		"iso-clns" },
73617680Spst	{ LLCSAP_GLOBAL,	"global" },
73717680Spst	{ 0,			NULL }
73817680Spst};
73917680Spst
74017680Spststatic void
74117680Spstinit_llcsaparray(void)
74217680Spst{
74317680Spst	register int i;
74417680Spst	register struct hnamemem *table;
74517680Spst
74617680Spst	for (i = 0; llcsap_db[i].s != NULL; i++) {
74717680Spst		table = &llcsaptable[llcsap_db[i].v];
74817680Spst		while (table->name)
74917680Spst			table = table->nxt;
75017680Spst		table->name = llcsap_db[i].s;
75117680Spst		table->addr = llcsap_db[i].v;
75217680Spst		table->nxt = newhnamemem();
75317680Spst	}
75417680Spst}
75517680Spst
75617680Spst/*
75717680Spst * Initialize the address to name translation machinery.  We map all
75817680Spst * non-local IP addresses to numeric addresses if fflag is true (i.e.,
75917680Spst * to prevent blocking on the nameserver).  localnet is the IP address
76017680Spst * of the local network.  mask is its subnet mask.
76117680Spst */
76217680Spstvoid
76339300Sfennerinit_addrtoname(u_int32_t localnet, u_int32_t mask)
76417680Spst{
76517680Spst	netmask = mask;
76617680Spst	if (fflag) {
76717680Spst		f_localnet = localnet;
76817680Spst		f_netmask = mask;
76917680Spst	}
77017680Spst	if (nflag)
77117680Spst		/*
77217680Spst		 * Simplest way to suppress names.
77317680Spst		 */
77417680Spst		return;
77517680Spst
77617680Spst	init_etherarray();
77717680Spst	init_servarray();
77817680Spst	init_eprotoarray();
77917680Spst	init_llcsaparray();
78017680Spst	init_protoidarray();
78117680Spst}
78217680Spst
78317680Spstchar *
78417680Spstdnaddr_string(u_short dnaddr)
78517680Spst{
78617680Spst	register struct hnamemem *tp;
78717680Spst
78817680Spst	for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
78917680Spst	     tp = tp->nxt)
79017680Spst		if (tp->addr == dnaddr)
79117680Spst			return (tp->name);
79217680Spst
79317680Spst	tp->addr = dnaddr;
79417680Spst	tp->nxt = newhnamemem();
79517680Spst	if (nflag)
79617680Spst		tp->name = dnnum_string(dnaddr);
79717680Spst	else
79817680Spst		tp->name = dnname_string(dnaddr);
79917680Spst
80017680Spst	return(tp->name);
80117680Spst}
80217680Spst
80317680Spst/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
80417680Spststruct hnamemem *
80526183Sfennernewhnamemem(void)
80617680Spst{
80717680Spst	register struct hnamemem *p;
80817680Spst	static struct hnamemem *ptr = NULL;
80917680Spst	static u_int num = 0;
81017680Spst
81117680Spst	if (num  <= 0) {
81217680Spst		num = 64;
81317680Spst		ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
81417680Spst		if (ptr == NULL)
81517680Spst			error("newhnamemem: calloc");
81617680Spst	}
81717680Spst	--num;
81817680Spst	p = ptr++;
81917680Spst	return (p);
82017680Spst}
82156896Sfenner
82256896Sfenner#ifdef INET6
82356896Sfenner/* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */
82456896Sfennerstruct h6namemem *
82556896Sfennernewh6namemem(void)
82656896Sfenner{
82756896Sfenner	register struct h6namemem *p;
82856896Sfenner	static struct h6namemem *ptr = NULL;
82956896Sfenner	static u_int num = 0;
83056896Sfenner
83156896Sfenner	if (num  <= 0) {
83256896Sfenner		num = 64;
83356896Sfenner		ptr = (struct h6namemem *)calloc(num, sizeof (*ptr));
83456896Sfenner		if (ptr == NULL)
83556896Sfenner			error("newh6namemem: calloc");
83656896Sfenner	}
83756896Sfenner	--num;
83856896Sfenner	p = ptr++;
83956896Sfenner	return (p);
84056896Sfenner}
84156896Sfenner#endif /* INET6 */
842