addrtoname.c revision 39300
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
2317680Spst */
2417680Spst#ifndef lint
2526183Sfennerstatic const char rcsid[] =
2639300Sfenner    "@(#) $Header: addrtoname.c,v 1.61 97/06/15 13:20:18 leres Exp $ (LBL)";
2717680Spst#endif
2817680Spst
2917680Spst#include <sys/types.h>
3017680Spst#include <sys/socket.h>
3117680Spst#include <sys/time.h>
3217680Spst
3317680Spst#if __STDC__
3417680Spststruct mbuf;
3517680Spststruct rtentry;
3617680Spst#endif
3717680Spst#include <net/if.h>
3817680Spst
3917680Spst#include <netinet/in.h>
4021262Swollman#include <net/ethernet.h>
4117680Spst
4217680Spst#include <arpa/inet.h>
4317680Spst
4417680Spst#include <ctype.h>
4517680Spst#include <netdb.h>
4617680Spst#include <pcap.h>
4717680Spst#include <pcap-namedb.h>
4839300Sfenner#ifdef HAVE_MALLOC_H
4939300Sfenner#include <malloc.h>
5039300Sfenner#endif
5139300Sfenner#ifdef HAVE_MEMORY_H
5239300Sfenner#include <memory.h>
5339300Sfenner#endif
5417680Spst#include <signal.h>
5517680Spst#include <stdio.h>
5617680Spst#include <string.h>
5717680Spst#include <stdlib.h>
5817680Spst#include <unistd.h>
5917680Spst
6017680Spst#include "interface.h"
6117680Spst#include "addrtoname.h"
6217680Spst#include "llc.h"
6339300Sfenner#include "savestr.h"
6439300Sfenner#include "setsignal.h"
6517680Spst
6617680Spst/* Forwards */
6717680Spststatic RETSIGTYPE nohostname(int);
6817680Spst
6917680Spst/*
7017680Spst * hash tables for whatever-to-name translations
7117680Spst */
7217680Spst
7317680Spst#define HASHNAMESIZE 4096
7417680Spst
7517680Spststruct hnamemem {
7617680Spst	u_int32_t addr;
7717680Spst	char *name;
7817680Spst	struct hnamemem *nxt;
7917680Spst};
8017680Spst
8117680Spststruct hnamemem hnametable[HASHNAMESIZE];
8217680Spststruct hnamemem tporttable[HASHNAMESIZE];
8317680Spststruct hnamemem uporttable[HASHNAMESIZE];
8417680Spststruct hnamemem eprototable[HASHNAMESIZE];
8517680Spststruct hnamemem dnaddrtable[HASHNAMESIZE];
8617680Spststruct hnamemem llcsaptable[HASHNAMESIZE];
8717680Spst
8817680Spststruct enamemem {
8917680Spst	u_short e_addr0;
9017680Spst	u_short e_addr1;
9117680Spst	u_short e_addr2;
9217680Spst	char *e_name;
9317680Spst	u_char *e_nsap;			/* used only for nsaptable[] */
9417680Spst	struct enamemem *e_nxt;
9517680Spst};
9617680Spst
9717680Spststruct enamemem enametable[HASHNAMESIZE];
9817680Spststruct enamemem nsaptable[HASHNAMESIZE];
9917680Spst
10017680Spststruct protoidmem {
10117680Spst	u_int32_t p_oui;
10217680Spst	u_short p_proto;
10317680Spst	char *p_name;
10417680Spst	struct protoidmem *p_nxt;
10517680Spst};
10617680Spst
10717680Spststruct protoidmem protoidtable[HASHNAMESIZE];
10817680Spst
10917680Spst/*
11017680Spst * A faster replacement for inet_ntoa().
11117680Spst */
11217680Spstchar *
11317680Spstintoa(u_int32_t addr)
11417680Spst{
11517680Spst	register char *cp;
11617680Spst	register u_int byte;
11717680Spst	register int n;
11817680Spst	static char buf[sizeof(".xxx.xxx.xxx.xxx")];
11917680Spst
12017680Spst	NTOHL(addr);
12117680Spst	cp = &buf[sizeof buf];
12217680Spst	*--cp = '\0';
12317680Spst
12417680Spst	n = 4;
12517680Spst	do {
12617680Spst		byte = addr & 0xff;
12717680Spst		*--cp = byte % 10 + '0';
12817680Spst		byte /= 10;
12917680Spst		if (byte > 0) {
13017680Spst			*--cp = byte % 10 + '0';
13117680Spst			byte /= 10;
13217680Spst			if (byte > 0)
13317680Spst				*--cp = byte + '0';
13417680Spst		}
13517680Spst		*--cp = '.';
13617680Spst		addr >>= 8;
13717680Spst	} while (--n > 0);
13817680Spst
13917680Spst	return cp + 1;
14017680Spst}
14117680Spst
14217680Spststatic u_int32_t f_netmask;
14317680Spststatic u_int32_t f_localnet;
14417680Spststatic u_int32_t netmask;
14517680Spst
14617680Spst/*
14717680Spst * "getname" is written in this atrocious way to make sure we don't
14817680Spst * wait forever while trying to get hostnames from yp.
14917680Spst */
15017680Spst#include <setjmp.h>
15117680Spst
15217680Spstjmp_buf getname_env;
15317680Spst
15417680Spststatic RETSIGTYPE
15517680Spstnohostname(int signo)
15617680Spst{
15717680Spst	longjmp(getname_env, 1);
15817680Spst}
15917680Spst
16017680Spst/*
16117680Spst * Return a name for the IP address pointed to by ap.  This address
16217680Spst * is assumed to be in network byte order.
16317680Spst */
16417680Spstchar *
16517680Spstgetname(const u_char *ap)
16617680Spst{
16717680Spst	register struct hostent *hp;
16817680Spst	u_int32_t addr;
16917680Spst	static struct hnamemem *p;		/* static for longjmp() */
17017680Spst
17117680Spst#ifndef LBL_ALIGN
17217680Spst	addr = *(const u_int32_t *)ap;
17317680Spst#else
17417680Spst	/*
17526183Sfenner	 * Extract 32 bits in network order, dealing with alignment.
17617680Spst	 */
17717680Spst	switch ((long)ap & 3) {
17817680Spst
17917680Spst	case 0:
18017680Spst		addr = *(u_int32_t *)ap;
18117680Spst		break;
18217680Spst
18317680Spst	case 2:
18426183Sfenner#ifdef WORDS_BIGENDIAN
18526183Sfenner		addr = ((u_int32_t)*(u_short *)ap << 16) |
18626183Sfenner			(u_int32_t)*(u_short *)(ap + 2);
18726183Sfenner#else
18817680Spst		addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
18917680Spst			(u_int32_t)*(u_short *)ap;
19017680Spst#endif
19117680Spst		break;
19217680Spst
19317680Spst	default:
19426183Sfenner#ifdef WORDS_BIGENDIAN
19526183Sfenner		addr = ((u_int32_t)ap[0] << 24) |
19626183Sfenner			((u_int32_t)ap[1] << 16) |
19726183Sfenner			((u_int32_t)ap[2] << 8) |
19826183Sfenner			(u_int32_t)ap[3];
19926183Sfenner#else
20017680Spst		addr = ((u_int32_t)ap[3] << 24) |
20117680Spst			((u_int32_t)ap[2] << 16) |
20217680Spst			((u_int32_t)ap[1] << 8) |
20317680Spst			(u_int32_t)ap[0];
20417680Spst#endif
20517680Spst		break;
20617680Spst	}
20717680Spst#endif
20817680Spst	p = &hnametable[addr & (HASHNAMESIZE-1)];
20917680Spst	for (; p->nxt; p = p->nxt) {
21017680Spst		if (p->addr == addr)
21117680Spst			return (p->name);
21217680Spst	}
21317680Spst	p->addr = addr;
21417680Spst	p->nxt = newhnamemem();
21517680Spst
21617680Spst	/*
21717680Spst	 * Only print names when:
21817680Spst	 *	(1) -n was not given.
21939300Sfenner	 *      (2) Address is foreign and -f was given. (If -f was not
22039300Sfenner	 *	    give, f_netmask and f_local are 0 and the test
22139300Sfenner	 *	    evaluates to true)
22239300Sfenner	 *      (3) -a was given or the host portion is not all ones
22339300Sfenner	 *          nor all zeros (i.e. not a network or broadcast address)
22417680Spst	 */
22539300Sfenner	if (!nflag &&
22639300Sfenner	    (addr & f_netmask) == f_localnet &&
22739300Sfenner	    (aflag ||
22839300Sfenner	    !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) {
22917680Spst		if (!setjmp(getname_env)) {
23039300Sfenner			(void)setsignal(SIGALRM, nohostname);
23117680Spst			(void)alarm(20);
23217680Spst			hp = gethostbyaddr((char *)&addr, 4, AF_INET);
23317680Spst			(void)alarm(0);
23417680Spst			if (hp) {
23517680Spst				char *dotp;
23617680Spst
23717680Spst				p->name = savestr(hp->h_name);
23817680Spst				if (Nflag) {
23917680Spst					/* Remove domain qualifications */
24017680Spst					dotp = strchr(p->name, '.');
24117680Spst					if (dotp)
24217680Spst						*dotp = '\0';
24317680Spst				}
24417680Spst				return (p->name);
24517680Spst			}
24617680Spst		}
24717680Spst	}
24817680Spst	p->name = savestr(intoa(addr));
24917680Spst	return (p->name);
25017680Spst}
25117680Spst
25217680Spststatic char hex[] = "0123456789abcdef";
25317680Spst
25417680Spst
25517680Spst/* Find the hash node that corresponds the ether address 'ep' */
25617680Spst
25717680Spststatic inline struct enamemem *
25817680Spstlookup_emem(const u_char *ep)
25917680Spst{
26017680Spst	register u_int i, j, k;
26117680Spst	struct enamemem *tp;
26217680Spst
26317680Spst	k = (ep[0] << 8) | ep[1];
26417680Spst	j = (ep[2] << 8) | ep[3];
26517680Spst	i = (ep[4] << 8) | ep[5];
26617680Spst
26717680Spst	tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
26817680Spst	while (tp->e_nxt)
26917680Spst		if (tp->e_addr0 == i &&
27017680Spst		    tp->e_addr1 == j &&
27117680Spst		    tp->e_addr2 == k)
27217680Spst			return tp;
27317680Spst		else
27417680Spst			tp = tp->e_nxt;
27517680Spst	tp->e_addr0 = i;
27617680Spst	tp->e_addr1 = j;
27717680Spst	tp->e_addr2 = k;
27817680Spst	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
27917680Spst	if (tp->e_nxt == NULL)
28017680Spst		error("lookup_emem: calloc");
28117680Spst
28217680Spst	return tp;
28317680Spst}
28417680Spst
28517680Spst/* Find the hash node that corresponds the NSAP 'nsap' */
28617680Spst
28717680Spststatic inline struct enamemem *
28817680Spstlookup_nsap(register const u_char *nsap)
28917680Spst{
29017680Spst	register u_int i, j, k;
29117680Spst	int nlen = *nsap;
29217680Spst	struct enamemem *tp;
29317680Spst	const u_char *ensap = nsap + nlen - 6;
29417680Spst
29517680Spst	if (nlen > 6) {
29617680Spst		k = (ensap[0] << 8) | ensap[1];
29717680Spst		j = (ensap[2] << 8) | ensap[3];
29817680Spst		i = (ensap[4] << 8) | ensap[5];
29917680Spst	}
30017680Spst	else
30117680Spst		i = j = k = 0;
30217680Spst
30317680Spst	tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
30417680Spst	while (tp->e_nxt)
30517680Spst		if (tp->e_addr0 == i &&
30617680Spst		    tp->e_addr1 == j &&
30717680Spst		    tp->e_addr2 == k &&
30817680Spst		    tp->e_nsap[0] == nlen &&
30917680Spst		    memcmp((char *)&(nsap[1]),
31017680Spst			(char *)&(tp->e_nsap[1]), nlen) == 0)
31117680Spst			return tp;
31217680Spst		else
31317680Spst			tp = tp->e_nxt;
31417680Spst	tp->e_addr0 = i;
31517680Spst	tp->e_addr1 = j;
31617680Spst	tp->e_addr2 = k;
31717680Spst	tp->e_nsap = (u_char *)malloc(nlen + 1);
31817680Spst	if (tp->e_nsap == NULL)
31917680Spst		error("lookup_nsap: malloc");
32039300Sfenner	memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1);
32117680Spst	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
32217680Spst	if (tp->e_nxt == NULL)
32317680Spst		error("lookup_nsap: calloc");
32417680Spst
32517680Spst	return tp;
32617680Spst}
32717680Spst
32817680Spst/* Find the hash node that corresponds the protoid 'pi'. */
32917680Spst
33017680Spststatic inline struct protoidmem *
33117680Spstlookup_protoid(const u_char *pi)
33217680Spst{
33317680Spst	register u_int i, j;
33417680Spst	struct protoidmem *tp;
33517680Spst
33617680Spst	/* 5 octets won't be aligned */
33717680Spst	i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
33817680Spst	j =   (pi[3] << 8) + pi[4];
33917680Spst	/* XXX should be endian-insensitive, but do big-endian testing  XXX */
34017680Spst
34117680Spst	tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
34217680Spst	while (tp->p_nxt)
34317680Spst		if (tp->p_oui == i && tp->p_proto == j)
34417680Spst			return tp;
34517680Spst		else
34617680Spst			tp = tp->p_nxt;
34717680Spst	tp->p_oui = i;
34817680Spst	tp->p_proto = j;
34917680Spst	tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
35017680Spst	if (tp->p_nxt == NULL)
35117680Spst		error("lookup_protoid: calloc");
35217680Spst
35317680Spst	return tp;
35417680Spst}
35517680Spst
35617680Spstchar *
35717680Spstetheraddr_string(register const u_char *ep)
35817680Spst{
35917680Spst	register u_int i, j;
36017680Spst	register char *cp;
36117680Spst	register struct enamemem *tp;
36217680Spst	char buf[sizeof("00:00:00:00:00:00")];
36317680Spst
36417680Spst	tp = lookup_emem(ep);
36517680Spst	if (tp->e_name)
36617680Spst		return (tp->e_name);
36717680Spst#ifdef HAVE_ETHER_NTOHOST
36817680Spst	if (!nflag) {
36917680Spst		char buf[128];
37017680Spst		if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
37117680Spst			tp->e_name = savestr(buf);
37217680Spst			return (tp->e_name);
37317680Spst		}
37417680Spst	}
37517680Spst#endif
37617680Spst	cp = buf;
37717680Spst	if ((j = *ep >> 4) != 0)
37817680Spst		*cp++ = hex[j];
37917680Spst	*cp++ = hex[*ep++ & 0xf];
38017680Spst	for (i = 5; (int)--i >= 0;) {
38117680Spst		*cp++ = ':';
38217680Spst		if ((j = *ep >> 4) != 0)
38317680Spst			*cp++ = hex[j];
38417680Spst		*cp++ = hex[*ep++ & 0xf];
38517680Spst	}
38617680Spst	*cp = '\0';
38717680Spst	tp->e_name = savestr(buf);
38817680Spst	return (tp->e_name);
38917680Spst}
39017680Spst
39117680Spstchar *
39217680Spstetherproto_string(u_short port)
39317680Spst{
39417680Spst	register char *cp;
39517680Spst	register struct hnamemem *tp;
39617680Spst	register u_int32_t i = port;
39717680Spst	char buf[sizeof("0000")];
39817680Spst
39917680Spst	for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
40017680Spst		if (tp->addr == i)
40117680Spst			return (tp->name);
40217680Spst
40317680Spst	tp->addr = i;
40417680Spst	tp->nxt = newhnamemem();
40517680Spst
40617680Spst	cp = buf;
40717680Spst	NTOHS(port);
40817680Spst	*cp++ = hex[port >> 12 & 0xf];
40917680Spst	*cp++ = hex[port >> 8 & 0xf];
41017680Spst	*cp++ = hex[port >> 4 & 0xf];
41117680Spst	*cp++ = hex[port & 0xf];
41217680Spst	*cp++ = '\0';
41317680Spst	tp->name = savestr(buf);
41417680Spst	return (tp->name);
41517680Spst}
41617680Spst
41717680Spstchar *
41817680Spstprotoid_string(register const u_char *pi)
41917680Spst{
42017680Spst	register u_int i, j;
42117680Spst	register char *cp;
42217680Spst	register struct protoidmem *tp;
42317680Spst	char buf[sizeof("00:00:00:00:00")];
42417680Spst
42517680Spst	tp = lookup_protoid(pi);
42617680Spst	if (tp->p_name)
42717680Spst		return tp->p_name;
42817680Spst
42917680Spst	cp = buf;
43017680Spst	if ((j = *pi >> 4) != 0)
43117680Spst		*cp++ = hex[j];
43217680Spst	*cp++ = hex[*pi++ & 0xf];
43317680Spst	for (i = 4; (int)--i >= 0;) {
43417680Spst		*cp++ = ':';
43517680Spst		if ((j = *pi >> 4) != 0)
43617680Spst			*cp++ = hex[j];
43717680Spst		*cp++ = hex[*pi++ & 0xf];
43817680Spst	}
43917680Spst	*cp = '\0';
44017680Spst	tp->p_name = savestr(buf);
44117680Spst	return (tp->p_name);
44217680Spst}
44317680Spst
44417680Spstchar *
44517680Spstllcsap_string(u_char sap)
44617680Spst{
44717680Spst	register char *cp;
44817680Spst	register struct hnamemem *tp;
44917680Spst	register u_int32_t i = sap;
45017680Spst	char buf[sizeof("sap 00")];
45117680Spst
45217680Spst	for (tp = &llcsaptable[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	(void)strcpy(cp, "sap ");
46117680Spst	cp += strlen(cp);
46217680Spst	*cp++ = hex[sap >> 4 & 0xf];
46317680Spst	*cp++ = hex[sap & 0xf];
46417680Spst	*cp++ = '\0';
46517680Spst	tp->name = savestr(buf);
46617680Spst	return (tp->name);
46717680Spst}
46817680Spst
46917680Spstchar *
47017680Spstisonsap_string(const u_char *nsap)
47117680Spst{
47217680Spst	register u_int i, nlen = nsap[0];
47317680Spst	register char *cp;
47417680Spst	register struct enamemem *tp;
47517680Spst
47617680Spst	tp = lookup_nsap(nsap);
47717680Spst	if (tp->e_name)
47817680Spst		return tp->e_name;
47917680Spst
48017688Spst	tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1));
48117680Spst	if (cp == NULL)
48217680Spst		error("isonsap_string: malloc");
48317680Spst
48417680Spst	nsap++;
48517688Spst	for (i = 0; i < nlen; i++) {
48617680Spst		*cp++ = hex[*nsap >> 4];
48717680Spst		*cp++ = hex[*nsap++ & 0xf];
48817688Spst		if (((i & 1) == 0) && (i + 1 < nlen))
48917688Spst			*cp++ = '.';
49017680Spst	}
49117680Spst	*cp = '\0';
49217680Spst	return (tp->e_name);
49317680Spst}
49417680Spst
49517680Spstchar *
49617680Spsttcpport_string(u_short port)
49717680Spst{
49817680Spst	register struct hnamemem *tp;
49917680Spst	register u_int32_t i = port;
50017680Spst	char buf[sizeof("00000")];
50117680Spst
50217680Spst	for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
50317680Spst		if (tp->addr == i)
50417680Spst			return (tp->name);
50517680Spst
50617680Spst	tp->addr = i;
50717680Spst	tp->nxt = newhnamemem();
50817680Spst
50917680Spst	(void)sprintf(buf, "%u", i);
51017680Spst	tp->name = savestr(buf);
51117680Spst	return (tp->name);
51217680Spst}
51317680Spst
51417680Spstchar *
51517680Spstudpport_string(register u_short port)
51617680Spst{
51717680Spst	register struct hnamemem *tp;
51817680Spst	register u_int32_t i = port;
51917680Spst	char buf[sizeof("00000")];
52017680Spst
52117680Spst	for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
52217680Spst		if (tp->addr == i)
52317680Spst			return (tp->name);
52417680Spst
52517680Spst	tp->addr = i;
52617680Spst	tp->nxt = newhnamemem();
52717680Spst
52817680Spst	(void)sprintf(buf, "%u", i);
52917680Spst	tp->name = savestr(buf);
53017680Spst	return (tp->name);
53117680Spst}
53217680Spst
53317680Spststatic void
53417680Spstinit_servarray(void)
53517680Spst{
53617680Spst	struct servent *sv;
53717680Spst	register struct hnamemem *table;
53817680Spst	register int i;
53917680Spst	char buf[sizeof("0000000000")];
54017680Spst
54117680Spst	while ((sv = getservent()) != NULL) {
54217680Spst		int port = ntohs(sv->s_port);
54317680Spst		i = port & (HASHNAMESIZE-1);
54417680Spst		if (strcmp(sv->s_proto, "tcp") == 0)
54517680Spst			table = &tporttable[i];
54617680Spst		else if (strcmp(sv->s_proto, "udp") == 0)
54717680Spst			table = &uporttable[i];
54817680Spst		else
54917680Spst			continue;
55017680Spst
55117680Spst		while (table->name)
55217680Spst			table = table->nxt;
55317680Spst		if (nflag) {
55417680Spst			(void)sprintf(buf, "%d", port);
55517680Spst			table->name = savestr(buf);
55617680Spst		} else
55717680Spst			table->name = savestr(sv->s_name);
55817680Spst		table->addr = port;
55917680Spst		table->nxt = newhnamemem();
56017680Spst	}
56117680Spst	endservent();
56217680Spst}
56317680Spst
56417680Spst/*XXX from libbpfc.a */
56517680Spstextern struct eproto {
56617680Spst	char *s;
56717680Spst	u_short p;
56817680Spst} eproto_db[];
56917680Spst
57017680Spststatic void
57117680Spstinit_eprotoarray(void)
57217680Spst{
57317680Spst	register int i;
57417680Spst	register struct hnamemem *table;
57517680Spst
57617680Spst	for (i = 0; eproto_db[i].s; i++) {
57717680Spst		int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
57817680Spst		table = &eprototable[j];
57917680Spst		while (table->name)
58017680Spst			table = table->nxt;
58117680Spst		table->name = eproto_db[i].s;
58217680Spst		table->addr = ntohs(eproto_db[i].p);
58317680Spst		table->nxt = newhnamemem();
58417680Spst	}
58517680Spst}
58617680Spst
58717680Spst/*
58817680Spst * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
58917680Spst * types.
59017680Spst */
59117680Spststatic void
59217680Spstinit_protoidarray(void)
59317680Spst{
59417680Spst	register int i;
59517680Spst	register struct protoidmem *tp;
59617680Spst	u_char protoid[5];
59717680Spst
59817680Spst	protoid[0] = 0;
59917680Spst	protoid[1] = 0;
60017680Spst	protoid[2] = 0;
60117680Spst	for (i = 0; eproto_db[i].s; i++) {
60217680Spst		u_short etype = htons(eproto_db[i].p);
60317680Spst
60417680Spst		memcpy((char *)&protoid[3], (char *)&etype, 2);
60517680Spst		tp = lookup_protoid(protoid);
60617680Spst		tp->p_name = savestr(eproto_db[i].s);
60717680Spst	}
60817680Spst}
60917680Spst
61017680Spststatic struct etherlist {
61117680Spst	u_char addr[6];
61217680Spst	char *name;
61317680Spst} etherlist[] = {
61417680Spst	{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
61517680Spst	{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
61617680Spst};
61717680Spst
61817680Spst/*
61917680Spst * Initialize the ethers hash table.  We take two different approaches
62017680Spst * depending on whether or not the system provides the ethers name
62117680Spst * service.  If it does, we just wire in a few names at startup,
62217680Spst * and etheraddr_string() fills in the table on demand.  If it doesn't,
62317680Spst * then we suck in the entire /etc/ethers file at startup.  The idea
62417680Spst * is that parsing the local file will be fast, but spinning through
62517680Spst * all the ethers entries via NIS & next_etherent might be very slow.
62617680Spst *
62717680Spst * XXX pcap_next_etherent doesn't belong in the pcap interface, but
62817680Spst * since the pcap module already does name-to-address translation,
62917680Spst * it's already does most of the work for the ethernet address-to-name
63017680Spst * translation, so we just pcap_next_etherent as a convenience.
63117680Spst */
63217680Spststatic void
63317680Spstinit_etherarray(void)
63417680Spst{
63517680Spst	register struct etherlist *el;
63617680Spst	register struct enamemem *tp;
63717680Spst#ifdef HAVE_ETHER_NTOHOST
63817680Spst	char name[256];
63917680Spst#else
64017680Spst	register struct pcap_etherent *ep;
64117680Spst	register FILE *fp;
64217680Spst
64317680Spst	/* Suck in entire ethers file */
64417680Spst	fp = fopen(PCAP_ETHERS_FILE, "r");
64517680Spst	if (fp != NULL) {
64617680Spst		while ((ep = pcap_next_etherent(fp)) != NULL) {
64717680Spst			tp = lookup_emem(ep->addr);
64817680Spst			tp->e_name = savestr(ep->name);
64917680Spst		}
65017680Spst		(void)fclose(fp);
65117680Spst	}
65217680Spst#endif
65317680Spst
65417680Spst	/* Hardwire some ethernet names */
65517680Spst	for (el = etherlist; el->name != NULL; ++el) {
65617680Spst		tp = lookup_emem(el->addr);
65717680Spst		/* Don't override existing name */
65817680Spst		if (tp->e_name != NULL)
65917680Spst			continue;
66017680Spst
66117680Spst#ifdef HAVE_ETHER_NTOHOST
66217680Spst                /* Use yp/nis version of name if available */
66317680Spst                if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
66417680Spst                        tp->e_name = savestr(name);
66517680Spst			continue;
66617680Spst		}
66717680Spst#endif
66817680Spst		tp->e_name = el->name;
66917680Spst	}
67017680Spst}
67117680Spst
67217680Spststatic struct tok llcsap_db[] = {
67317680Spst	{ LLCSAP_NULL,		"null" },
67417680Spst	{ LLCSAP_8021B_I,	"802.1b-gsap" },
67517680Spst	{ LLCSAP_8021B_G,	"802.1b-isap" },
67617680Spst	{ LLCSAP_IP,		"ip-sap" },
67717680Spst	{ LLCSAP_PROWAYNM,	"proway-nm" },
67817680Spst	{ LLCSAP_8021D,		"802.1d" },
67917680Spst	{ LLCSAP_RS511,		"eia-rs511" },
68017680Spst	{ LLCSAP_ISO8208,	"x.25/llc2" },
68117680Spst	{ LLCSAP_PROWAY,	"proway" },
68217680Spst	{ LLCSAP_ISONS,		"iso-clns" },
68317680Spst	{ LLCSAP_GLOBAL,	"global" },
68417680Spst	{ 0,			NULL }
68517680Spst};
68617680Spst
68717680Spststatic void
68817680Spstinit_llcsaparray(void)
68917680Spst{
69017680Spst	register int i;
69117680Spst	register struct hnamemem *table;
69217680Spst
69317680Spst	for (i = 0; llcsap_db[i].s != NULL; i++) {
69417680Spst		table = &llcsaptable[llcsap_db[i].v];
69517680Spst		while (table->name)
69617680Spst			table = table->nxt;
69717680Spst		table->name = llcsap_db[i].s;
69817680Spst		table->addr = llcsap_db[i].v;
69917680Spst		table->nxt = newhnamemem();
70017680Spst	}
70117680Spst}
70217680Spst
70317680Spst/*
70417680Spst * Initialize the address to name translation machinery.  We map all
70517680Spst * non-local IP addresses to numeric addresses if fflag is true (i.e.,
70617680Spst * to prevent blocking on the nameserver).  localnet is the IP address
70717680Spst * of the local network.  mask is its subnet mask.
70817680Spst */
70917680Spstvoid
71039300Sfennerinit_addrtoname(u_int32_t localnet, u_int32_t mask)
71117680Spst{
71217680Spst	netmask = mask;
71317680Spst	if (fflag) {
71417680Spst		f_localnet = localnet;
71517680Spst		f_netmask = mask;
71617680Spst	}
71717680Spst	if (nflag)
71817680Spst		/*
71917680Spst		 * Simplest way to suppress names.
72017680Spst		 */
72117680Spst		return;
72217680Spst
72317680Spst	init_etherarray();
72417680Spst	init_servarray();
72517680Spst	init_eprotoarray();
72617680Spst	init_llcsaparray();
72717680Spst	init_protoidarray();
72817680Spst}
72917680Spst
73017680Spstchar *
73117680Spstdnaddr_string(u_short dnaddr)
73217680Spst{
73317680Spst	register struct hnamemem *tp;
73417680Spst
73517680Spst	for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
73617680Spst	     tp = tp->nxt)
73717680Spst		if (tp->addr == dnaddr)
73817680Spst			return (tp->name);
73917680Spst
74017680Spst	tp->addr = dnaddr;
74117680Spst	tp->nxt = newhnamemem();
74217680Spst	if (nflag)
74317680Spst		tp->name = dnnum_string(dnaddr);
74417680Spst	else
74517680Spst		tp->name = dnname_string(dnaddr);
74617680Spst
74717680Spst	return(tp->name);
74817680Spst}
74917680Spst
75017680Spst/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
75117680Spststruct hnamemem *
75226183Sfennernewhnamemem(void)
75317680Spst{
75417680Spst	register struct hnamemem *p;
75517680Spst	static struct hnamemem *ptr = NULL;
75617680Spst	static u_int num = 0;
75717680Spst
75817680Spst	if (num  <= 0) {
75917680Spst		num = 64;
76017680Spst		ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
76117680Spst		if (ptr == NULL)
76217680Spst			error("newhnamemem: calloc");
76317680Spst	}
76417680Spst	--num;
76517680Spst	p = ptr++;
76617680Spst	return (p);
76717680Spst}
768