xref: /freebsd/contrib/tcpdump/addrtoname.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
1 /*
2  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  *  Internet, ethernet, port, and protocol string to address
22  *  and address to string conversion routines
23  *
24  * $FreeBSD$
25  */
26 #ifndef lint
27 static const char rcsid[] =
28     "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.83.4.1 2002/06/02 00:08:07 guy Exp $ (LBL)";
29 #endif
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/time.h>
38 
39 #include <netinet/in.h>
40 
41 #ifdef USE_ETHER_NTOHOST
42 #ifdef HAVE_NETINET_IF_ETHER_H
43 struct mbuf;		/* Squelch compiler warnings on some platforms for */
44 struct rtentry;		/* declarations in <net/if.h> */
45 #include <net/if.h>	/* for "struct ifnet" in "struct arpcom" on Solaris */
46 #include <netinet/if_ether.h>
47 #endif /* HAVE_NETINET_IF_ETHER_H */
48 #endif /* USE_ETHER_NTOHOST */
49 
50 #include <arpa/inet.h>
51 
52 #include <ctype.h>
53 #include <netdb.h>
54 #include <pcap.h>
55 #include <pcap-namedb.h>
56 #include <signal.h>
57 #include <stdio.h>
58 #include <string.h>
59 #include <stdlib.h>
60 #include <unistd.h>
61 
62 #include "interface.h"
63 #include "addrtoname.h"
64 #include "llc.h"
65 #include "setsignal.h"
66 
67 /* Forwards */
68 static RETSIGTYPE nohostname(int);
69 
70 /*
71  * hash tables for whatever-to-name translations
72  */
73 
74 #define HASHNAMESIZE 4096
75 
76 struct hnamemem {
77 	u_int32_t addr;
78 	const char *name;
79 	struct hnamemem *nxt;
80 };
81 
82 struct hnamemem hnametable[HASHNAMESIZE];
83 struct hnamemem tporttable[HASHNAMESIZE];
84 struct hnamemem uporttable[HASHNAMESIZE];
85 struct hnamemem eprototable[HASHNAMESIZE];
86 struct hnamemem dnaddrtable[HASHNAMESIZE];
87 struct hnamemem llcsaptable[HASHNAMESIZE];
88 
89 #ifdef INET6
90 struct h6namemem {
91 	struct in6_addr addr;
92 	char *name;
93 	struct h6namemem *nxt;
94 };
95 
96 struct h6namemem h6nametable[HASHNAMESIZE];
97 #endif /* INET6 */
98 
99 struct enamemem {
100 	u_short e_addr0;
101 	u_short e_addr1;
102 	u_short e_addr2;
103 	const char *e_name;
104 	u_char *e_nsap;			/* used only for nsaptable[] */
105 #define e_bs e_nsap			/* for bytestringtable */
106 	struct enamemem *e_nxt;
107 };
108 
109 struct enamemem enametable[HASHNAMESIZE];
110 struct enamemem nsaptable[HASHNAMESIZE];
111 struct enamemem bytestringtable[HASHNAMESIZE];
112 
113 struct protoidmem {
114 	u_int32_t p_oui;
115 	u_short p_proto;
116 	const char *p_name;
117 	struct protoidmem *p_nxt;
118 };
119 
120 struct protoidmem protoidtable[HASHNAMESIZE];
121 
122 /*
123  * A faster replacement for inet_ntoa().
124  */
125 const char *
126 intoa(u_int32_t addr)
127 {
128 	register char *cp;
129 	register u_int byte;
130 	register int n;
131 	static char buf[sizeof(".xxx.xxx.xxx.xxx")];
132 
133 	NTOHL(addr);
134 	cp = &buf[sizeof buf];
135 	*--cp = '\0';
136 
137 	n = 4;
138 	do {
139 		byte = addr & 0xff;
140 		*--cp = byte % 10 + '0';
141 		byte /= 10;
142 		if (byte > 0) {
143 			*--cp = byte % 10 + '0';
144 			byte /= 10;
145 			if (byte > 0)
146 				*--cp = byte + '0';
147 		}
148 		*--cp = '.';
149 		addr >>= 8;
150 	} while (--n > 0);
151 
152 	return cp + 1;
153 }
154 
155 static u_int32_t f_netmask;
156 static u_int32_t f_localnet;
157 static u_int32_t netmask;
158 
159 /*
160  * "getname" is written in this atrocious way to make sure we don't
161  * wait forever while trying to get hostnames from yp.
162  */
163 #include <setjmp.h>
164 
165 jmp_buf getname_env;
166 
167 static RETSIGTYPE
168 nohostname(int signo)
169 {
170 	longjmp(getname_env, 1);
171 }
172 
173 /*
174  * Return a name for the IP address pointed to by ap.  This address
175  * is assumed to be in network byte order.
176  */
177 const char *
178 getname(const u_char *ap)
179 {
180 	register struct hostent *hp;
181 	u_int32_t addr;
182 	static struct hnamemem *p;		/* static for longjmp() */
183 
184 	memcpy(&addr, ap, sizeof(addr));
185 	p = &hnametable[addr & (HASHNAMESIZE-1)];
186 	for (; p->nxt; p = p->nxt) {
187 		if (p->addr == addr)
188 			return (p->name);
189 	}
190 	p->addr = addr;
191 	p->nxt = newhnamemem();
192 
193 	/*
194 	 * Only print names when:
195 	 *	(1) -n was not given.
196 	 *      (2) Address is foreign and -f was given. (If -f was not
197 	 *	    give, f_netmask and f_local are 0 and the test
198 	 *	    evaluates to true)
199 	 *      (3) -a was given or the host portion is not all ones
200 	 *          nor all zeros (i.e. not a network or broadcast address)
201 	 */
202 	if (!nflag &&
203 	    (addr & f_netmask) == f_localnet &&
204 	    (aflag ||
205 	    !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) {
206 		if (!setjmp(getname_env)) {
207 			(void)setsignal(SIGALRM, nohostname);
208 			(void)alarm(20);
209 			hp = gethostbyaddr((char *)&addr, 4, AF_INET);
210 			(void)alarm(0);
211 			if (hp) {
212 				char *dotp;
213 
214 				p->name = strdup(hp->h_name);
215 				if (Nflag) {
216 					/* Remove domain qualifications */
217 					dotp = strchr(p->name, '.');
218 					if (dotp)
219 						*dotp = '\0';
220 				}
221 				return (p->name);
222 			}
223 		}
224 	}
225 	p->name = strdup(intoa(addr));
226 	return (p->name);
227 }
228 
229 #ifdef INET6
230 /*
231  * Return a name for the IP6 address pointed to by ap.  This address
232  * is assumed to be in network byte order.
233  */
234 const char *
235 getname6(const u_char *ap)
236 {
237 	register struct hostent *hp;
238 	struct in6_addr addr;
239 	static struct h6namemem *p;		/* static for longjmp() */
240 	register const char *cp;
241 	char ntop_buf[INET6_ADDRSTRLEN];
242 
243 	memcpy(&addr, ap, sizeof(addr));
244 	p = &h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)];
245 	for (; p->nxt; p = p->nxt) {
246 		if (memcmp(&p->addr, &addr, sizeof(addr)) == 0)
247 			return (p->name);
248 	}
249 	p->addr = addr;
250 	p->nxt = newh6namemem();
251 
252 	/*
253 	 * Only print names when:
254 	 *	(1) -n was not given.
255 	 *      (2) Address is foreign and -f was given. (If -f was not
256 	 *	    give, f_netmask and f_local are 0 and the test
257 	 *	    evaluates to true)
258 	 *      (3) -a was given or the host portion is not all ones
259 	 *          nor all zeros (i.e. not a network or broadcast address)
260 	 */
261 	if (!nflag
262 #if 0
263 	&&
264 	    (addr & f_netmask) == f_localnet &&
265 	    (aflag ||
266 	    !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))
267 #endif
268 	    ) {
269 		if (!setjmp(getname_env)) {
270 			(void)setsignal(SIGALRM, nohostname);
271 			(void)alarm(20);
272 			hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);
273 			(void)alarm(0);
274 			if (hp) {
275 				char *dotp;
276 
277 				p->name = strdup(hp->h_name);
278 				if (Nflag) {
279 					/* Remove domain qualifications */
280 					dotp = strchr(p->name, '.');
281 					if (dotp)
282 						*dotp = '\0';
283 				}
284 				return (p->name);
285 			}
286 		}
287 	}
288 	cp = inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf));
289 	p->name = strdup(cp);
290 	return (p->name);
291 }
292 #endif /* INET6 */
293 
294 static char hex[] = "0123456789abcdef";
295 
296 
297 /* Find the hash node that corresponds the ether address 'ep' */
298 
299 static inline struct enamemem *
300 lookup_emem(const u_char *ep)
301 {
302 	register u_int i, j, k;
303 	struct enamemem *tp;
304 
305 	k = (ep[0] << 8) | ep[1];
306 	j = (ep[2] << 8) | ep[3];
307 	i = (ep[4] << 8) | ep[5];
308 
309 	tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
310 	while (tp->e_nxt)
311 		if (tp->e_addr0 == i &&
312 		    tp->e_addr1 == j &&
313 		    tp->e_addr2 == k)
314 			return tp;
315 		else
316 			tp = tp->e_nxt;
317 	tp->e_addr0 = i;
318 	tp->e_addr1 = j;
319 	tp->e_addr2 = k;
320 	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
321 	if (tp->e_nxt == NULL)
322 		error("lookup_emem: calloc");
323 
324 	return tp;
325 }
326 
327 /*
328  * Find the hash node that corresponds to the bytestring 'bs'
329  * with length 'nlen'
330  */
331 
332 static inline struct enamemem *
333 lookup_bytestring(register const u_char *bs, const unsigned int nlen)
334 {
335 	struct enamemem *tp;
336 	register u_int i, j, k;
337 
338 	if (nlen >= 6) {
339 		k = (bs[0] << 8) | bs[1];
340 		j = (bs[2] << 8) | bs[3];
341 		i = (bs[4] << 8) | bs[5];
342 	} else if (nlen >= 4) {
343 		k = (bs[0] << 8) | bs[1];
344 		j = (bs[2] << 8) | bs[3];
345 		i = 0;
346 	} else
347 		i = j = k = 0;
348 
349 	tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)];
350 	while (tp->e_nxt)
351 		if (tp->e_addr0 == i &&
352 		    tp->e_addr1 == j &&
353 		    tp->e_addr2 == k &&
354 		    memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0)
355 			return tp;
356 		else
357 			tp = tp->e_nxt;
358 
359 	tp->e_addr0 = i;
360 	tp->e_addr1 = j;
361 	tp->e_addr2 = k;
362 
363 	tp->e_bs = (u_char *) calloc(1, nlen + 1);
364 	memcpy(tp->e_bs, bs, nlen);
365 	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
366 	if (tp->e_nxt == NULL)
367 		error("lookup_bytestring: calloc");
368 
369 	return tp;
370 }
371 
372 /* Find the hash node that corresponds the NSAP 'nsap' */
373 
374 static inline struct enamemem *
375 lookup_nsap(register const u_char *nsap)
376 {
377 	register u_int i, j, k;
378 	unsigned int nlen = *nsap;
379 	struct enamemem *tp;
380 	const u_char *ensap = nsap + nlen - 6;
381 
382 	if (nlen > 6) {
383 		k = (ensap[0] << 8) | ensap[1];
384 		j = (ensap[2] << 8) | ensap[3];
385 		i = (ensap[4] << 8) | ensap[5];
386 	}
387 	else
388 		i = j = k = 0;
389 
390 	tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
391 	while (tp->e_nxt)
392 		if (tp->e_addr0 == i &&
393 		    tp->e_addr1 == j &&
394 		    tp->e_addr2 == k &&
395 		    tp->e_nsap[0] == nlen &&
396 		    memcmp((const char *)&(nsap[1]),
397 			(char *)&(tp->e_nsap[1]), nlen) == 0)
398 			return tp;
399 		else
400 			tp = tp->e_nxt;
401 	tp->e_addr0 = i;
402 	tp->e_addr1 = j;
403 	tp->e_addr2 = k;
404 	tp->e_nsap = (u_char *)malloc(nlen + 1);
405 	if (tp->e_nsap == NULL)
406 		error("lookup_nsap: malloc");
407 	memcpy((char *)tp->e_nsap, (const char *)nsap, nlen + 1);
408 	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
409 	if (tp->e_nxt == NULL)
410 		error("lookup_nsap: calloc");
411 
412 	return tp;
413 }
414 
415 /* Find the hash node that corresponds the protoid 'pi'. */
416 
417 static inline struct protoidmem *
418 lookup_protoid(const u_char *pi)
419 {
420 	register u_int i, j;
421 	struct protoidmem *tp;
422 
423 	/* 5 octets won't be aligned */
424 	i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
425 	j =   (pi[3] << 8) + pi[4];
426 	/* XXX should be endian-insensitive, but do big-endian testing  XXX */
427 
428 	tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
429 	while (tp->p_nxt)
430 		if (tp->p_oui == i && tp->p_proto == j)
431 			return tp;
432 		else
433 			tp = tp->p_nxt;
434 	tp->p_oui = i;
435 	tp->p_proto = j;
436 	tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
437 	if (tp->p_nxt == NULL)
438 		error("lookup_protoid: calloc");
439 
440 	return tp;
441 }
442 
443 const char *
444 etheraddr_string(register const u_char *ep)
445 {
446 	register u_int i, j;
447 	register char *cp;
448 	register struct enamemem *tp;
449 	char buf[sizeof("00:00:00:00:00:00")];
450 
451 	tp = lookup_emem(ep);
452 	if (tp->e_name)
453 		return (tp->e_name);
454 #ifdef USE_ETHER_NTOHOST
455 	if (!nflag) {
456 		char buf[128];
457 		if (ether_ntohost(buf, (const struct ether_addr *)ep) == 0) {
458 			tp->e_name = strdup(buf);
459 			return (tp->e_name);
460 		}
461 	}
462 #endif
463 	cp = buf;
464 	if ((j = *ep >> 4) != 0)
465 		*cp++ = hex[j];
466 	*cp++ = hex[*ep++ & 0xf];
467 	for (i = 5; (int)--i >= 0;) {
468 		*cp++ = ':';
469 		if ((j = *ep >> 4) != 0)
470 			*cp++ = hex[j];
471 		*cp++ = hex[*ep++ & 0xf];
472 	}
473 	*cp = '\0';
474 	tp->e_name = strdup(buf);
475 	return (tp->e_name);
476 }
477 
478 const char *
479 linkaddr_string(const u_char *ep, const unsigned int len)
480 {
481 	register u_int i, j;
482 	register char *cp;
483 	register struct enamemem *tp;
484 
485 	if (len == 6)	/* XXX not totally correct... */
486 		return etheraddr_string(ep);
487 
488 	tp = lookup_bytestring(ep, len);
489 	if (tp->e_name)
490 		return (tp->e_name);
491 
492 	tp->e_name = cp = (char *)malloc(len*3);
493 	if (tp->e_name == NULL)
494 		error("linkaddr_string: malloc");
495 	if ((j = *ep >> 4) != 0)
496 		*cp++ = hex[j];
497 	*cp++ = hex[*ep++ & 0xf];
498 	for (i = len-1; i > 0 ; --i) {
499 		*cp++ = ':';
500 		if ((j = *ep >> 4) != 0)
501 			*cp++ = hex[j];
502 		*cp++ = hex[*ep++ & 0xf];
503 	}
504 	*cp = '\0';
505 	return (tp->e_name);
506 }
507 
508 const char *
509 etherproto_string(u_short port)
510 {
511 	register char *cp;
512 	register struct hnamemem *tp;
513 	register u_int32_t i = port;
514 	char buf[sizeof("0000")];
515 
516 	for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
517 		if (tp->addr == i)
518 			return (tp->name);
519 
520 	tp->addr = i;
521 	tp->nxt = newhnamemem();
522 
523 	cp = buf;
524 	NTOHS(port);
525 	*cp++ = hex[port >> 12 & 0xf];
526 	*cp++ = hex[port >> 8 & 0xf];
527 	*cp++ = hex[port >> 4 & 0xf];
528 	*cp++ = hex[port & 0xf];
529 	*cp++ = '\0';
530 	tp->name = strdup(buf);
531 	return (tp->name);
532 }
533 
534 const char *
535 protoid_string(register const u_char *pi)
536 {
537 	register u_int i, j;
538 	register char *cp;
539 	register struct protoidmem *tp;
540 	char buf[sizeof("00:00:00:00:00")];
541 
542 	tp = lookup_protoid(pi);
543 	if (tp->p_name)
544 		return tp->p_name;
545 
546 	cp = buf;
547 	if ((j = *pi >> 4) != 0)
548 		*cp++ = hex[j];
549 	*cp++ = hex[*pi++ & 0xf];
550 	for (i = 4; (int)--i >= 0;) {
551 		*cp++ = ':';
552 		if ((j = *pi >> 4) != 0)
553 			*cp++ = hex[j];
554 		*cp++ = hex[*pi++ & 0xf];
555 	}
556 	*cp = '\0';
557 	tp->p_name = strdup(buf);
558 	return (tp->p_name);
559 }
560 
561 const char *
562 llcsap_string(u_char sap)
563 {
564 	register struct hnamemem *tp;
565 	register u_int32_t i = sap;
566 	char buf[sizeof("sap 00")];
567 
568 	for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
569 		if (tp->addr == i)
570 			return (tp->name);
571 
572 	tp->addr = i;
573 	tp->nxt = newhnamemem();
574 
575 	snprintf(buf, sizeof(buf), "sap %02x", sap & 0xff);
576 	tp->name = strdup(buf);
577 	return (tp->name);
578 }
579 
580 const char *
581 isonsap_string(const u_char *nsap)
582 {
583 	register u_int i, nlen = nsap[0];
584 	register char *cp;
585 	register struct enamemem *tp;
586 
587 	tp = lookup_nsap(nsap);
588 	if (tp->e_name)
589 		return tp->e_name;
590 
591 	tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1));
592 	if (cp == NULL)
593 		error("isonsap_string: malloc");
594 
595 	nsap++;
596 	for (i = 0; i < nlen; i++) {
597 		*cp++ = hex[*nsap >> 4];
598 		*cp++ = hex[*nsap++ & 0xf];
599 		if (((i & 1) == 0) && (i + 1 < nlen))
600 			*cp++ = '.';
601 	}
602 	*cp = '\0';
603 	return (tp->e_name);
604 }
605 
606 const char *
607 tcpport_string(u_short port)
608 {
609 	register struct hnamemem *tp;
610 	register u_int32_t i = port;
611 	char buf[sizeof("00000")];
612 
613 	for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
614 		if (tp->addr == i)
615 			return (tp->name);
616 
617 	tp->addr = i;
618 	tp->nxt = newhnamemem();
619 
620 	(void)snprintf(buf, sizeof(buf), "%u", i);
621 	tp->name = strdup(buf);
622 	return (tp->name);
623 }
624 
625 const char *
626 udpport_string(register u_short port)
627 {
628 	register struct hnamemem *tp;
629 	register u_int32_t i = port;
630 	char buf[sizeof("00000")];
631 
632 	for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
633 		if (tp->addr == i)
634 			return (tp->name);
635 
636 	tp->addr = i;
637 	tp->nxt = newhnamemem();
638 
639 	(void)snprintf(buf, sizeof(buf), "%u", i);
640 	tp->name = strdup(buf);
641 	return (tp->name);
642 }
643 
644 static void
645 init_servarray(void)
646 {
647 	struct servent *sv;
648 	register struct hnamemem *table;
649 	register int i;
650 	char buf[sizeof("0000000000")];
651 
652 	while ((sv = getservent()) != NULL) {
653 		int port = ntohs(sv->s_port);
654 		i = port & (HASHNAMESIZE-1);
655 		if (strcmp(sv->s_proto, "tcp") == 0)
656 			table = &tporttable[i];
657 		else if (strcmp(sv->s_proto, "udp") == 0)
658 			table = &uporttable[i];
659 		else
660 			continue;
661 
662 		while (table->name)
663 			table = table->nxt;
664 		if (nflag) {
665 			(void)snprintf(buf, sizeof(buf), "%d", port);
666 			table->name = strdup(buf);
667 		} else
668 			table->name = strdup(sv->s_name);
669 		table->addr = port;
670 		table->nxt = newhnamemem();
671 	}
672 	endservent();
673 }
674 
675 /*XXX from libbpfc.a */
676 extern struct eproto {
677 	char *s;
678 	u_short p;
679 } eproto_db[];
680 
681 static void
682 init_eprotoarray(void)
683 {
684 	register int i;
685 	register struct hnamemem *table;
686 
687 	for (i = 0; eproto_db[i].s; i++) {
688 		int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
689 		table = &eprototable[j];
690 		while (table->name)
691 			table = table->nxt;
692 		table->name = eproto_db[i].s;
693 		table->addr = ntohs(eproto_db[i].p);
694 		table->nxt = newhnamemem();
695 	}
696 }
697 
698 static struct protoidlist {
699 	const u_char protoid[5];
700 	const char *name;
701 } protoidlist[] = {
702 	{{ 0x00, 0x00, 0x0c, 0x01, 0x07 }, "CiscoMLS" },
703 	{{ 0x00, 0x00, 0x0c, 0x20, 0x00 }, "CiscoCDP" },
704 	{{ 0x00, 0x00, 0x0c, 0x20, 0x01 }, "CiscoCGMP" },
705 	{{ 0x00, 0x00, 0x0c, 0x20, 0x03 }, "CiscoVTP" },
706 	{{ 0x00, 0xe0, 0x2b, 0x00, 0xbb }, "ExtremeEDP" },
707 	{{ 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
708 };
709 
710 /*
711  * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
712  * types.
713  */
714 static void
715 init_protoidarray(void)
716 {
717 	register int i;
718 	register struct protoidmem *tp;
719 	struct protoidlist *pl;
720 	u_char protoid[5];
721 
722 	protoid[0] = 0;
723 	protoid[1] = 0;
724 	protoid[2] = 0;
725 	for (i = 0; eproto_db[i].s; i++) {
726 		u_short etype = htons(eproto_db[i].p);
727 
728 		memcpy((char *)&protoid[3], (char *)&etype, 2);
729 		tp = lookup_protoid(protoid);
730 		tp->p_name = strdup(eproto_db[i].s);
731 	}
732 	/* Hardwire some SNAP proto ID names */
733 	for (pl = protoidlist; pl->name != NULL; ++pl) {
734 		tp = lookup_protoid(pl->protoid);
735 		/* Don't override existing name */
736 		if (tp->p_name != NULL)
737 			continue;
738 
739 		tp->p_name = pl->name;
740 	}
741 }
742 
743 static struct etherlist {
744 	const u_char addr[6];
745 	const char *name;
746 } etherlist[] = {
747 	{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
748 	{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
749 };
750 
751 /*
752  * Initialize the ethers hash table.  We take two different approaches
753  * depending on whether or not the system provides the ethers name
754  * service.  If it does, we just wire in a few names at startup,
755  * and etheraddr_string() fills in the table on demand.  If it doesn't,
756  * then we suck in the entire /etc/ethers file at startup.  The idea
757  * is that parsing the local file will be fast, but spinning through
758  * all the ethers entries via NIS & next_etherent might be very slow.
759  *
760  * XXX pcap_next_etherent doesn't belong in the pcap interface, but
761  * since the pcap module already does name-to-address translation,
762  * it's already does most of the work for the ethernet address-to-name
763  * translation, so we just pcap_next_etherent as a convenience.
764  */
765 static void
766 init_etherarray(void)
767 {
768 	register struct etherlist *el;
769 	register struct enamemem *tp;
770 #ifdef USE_ETHER_NTOHOST
771 	char name[256];
772 #else
773 	register struct pcap_etherent *ep;
774 	register FILE *fp;
775 
776 	/* Suck in entire ethers file */
777 	fp = fopen(PCAP_ETHERS_FILE, "r");
778 	if (fp != NULL) {
779 		while ((ep = pcap_next_etherent(fp)) != NULL) {
780 			tp = lookup_emem(ep->addr);
781 			tp->e_name = strdup(ep->name);
782 		}
783 		(void)fclose(fp);
784 	}
785 #endif
786 
787 	/* Hardwire some ethernet names */
788 	for (el = etherlist; el->name != NULL; ++el) {
789 		tp = lookup_emem(el->addr);
790 		/* Don't override existing name */
791 		if (tp->e_name != NULL)
792 			continue;
793 
794 #ifdef USE_ETHER_NTOHOST
795                 /* Use yp/nis version of name if available */
796                 if (ether_ntohost(name, (const struct ether_addr *)el->addr) == 0) {
797                         tp->e_name = strdup(name);
798 			continue;
799 		}
800 #endif
801 		tp->e_name = el->name;
802 	}
803 }
804 
805 static struct tok llcsap_db[] = {
806 	{ LLCSAP_NULL,		"null" },
807 	{ LLCSAP_8021B_I,	"802.1b-gsap" },
808 	{ LLCSAP_8021B_G,	"802.1b-isap" },
809 	{ LLCSAP_IP,		"ip-sap" },
810 	{ LLCSAP_PROWAYNM,	"proway-nm" },
811 	{ LLCSAP_8021D,		"802.1d" },
812 	{ LLCSAP_RS511,		"eia-rs511" },
813 	{ LLCSAP_ISO8208,	"x.25/llc2" },
814 	{ LLCSAP_PROWAY,	"proway" },
815 	{ LLCSAP_SNAP,		"snap" },
816 	{ LLCSAP_IPX,		"IPX" },
817 	{ LLCSAP_NETBEUI,	"netbeui" },
818 	{ LLCSAP_ISONS,		"iso-clns" },
819 	{ LLCSAP_GLOBAL,	"global" },
820 	{ 0,			NULL }
821 };
822 
823 static void
824 init_llcsaparray(void)
825 {
826 	register int i;
827 	register struct hnamemem *table;
828 
829 	for (i = 0; llcsap_db[i].s != NULL; i++) {
830 		table = &llcsaptable[llcsap_db[i].v];
831 		while (table->name)
832 			table = table->nxt;
833 		table->name = llcsap_db[i].s;
834 		table->addr = llcsap_db[i].v;
835 		table->nxt = newhnamemem();
836 	}
837 }
838 
839 /*
840  * Initialize the address to name translation machinery.  We map all
841  * non-local IP addresses to numeric addresses if fflag is true (i.e.,
842  * to prevent blocking on the nameserver).  localnet is the IP address
843  * of the local network.  mask is its subnet mask.
844  */
845 void
846 init_addrtoname(u_int32_t localnet, u_int32_t mask)
847 {
848 	netmask = mask;
849 	if (fflag) {
850 		f_localnet = localnet;
851 		f_netmask = mask;
852 	}
853 	if (nflag)
854 		/*
855 		 * Simplest way to suppress names.
856 		 */
857 		return;
858 
859 	init_etherarray();
860 	init_servarray();
861 	init_eprotoarray();
862 	init_llcsaparray();
863 	init_protoidarray();
864 }
865 
866 const char *
867 dnaddr_string(u_short dnaddr)
868 {
869 	register struct hnamemem *tp;
870 
871 	for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
872 	     tp = tp->nxt)
873 		if (tp->addr == dnaddr)
874 			return (tp->name);
875 
876 	tp->addr = dnaddr;
877 	tp->nxt = newhnamemem();
878 	if (nflag)
879 		tp->name = dnnum_string(dnaddr);
880 	else
881 		tp->name = dnname_string(dnaddr);
882 
883 	return(tp->name);
884 }
885 
886 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
887 struct hnamemem *
888 newhnamemem(void)
889 {
890 	register struct hnamemem *p;
891 	static struct hnamemem *ptr = NULL;
892 	static u_int num = 0;
893 
894 	if (num  <= 0) {
895 		num = 64;
896 		ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
897 		if (ptr == NULL)
898 			error("newhnamemem: calloc");
899 	}
900 	--num;
901 	p = ptr++;
902 	return (p);
903 }
904 
905 #ifdef INET6
906 /* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */
907 struct h6namemem *
908 newh6namemem(void)
909 {
910 	register struct h6namemem *p;
911 	static struct h6namemem *ptr = NULL;
912 	static u_int num = 0;
913 
914 	if (num  <= 0) {
915 		num = 64;
916 		ptr = (struct h6namemem *)calloc(num, sizeof (*ptr));
917 		if (ptr == NULL)
918 			error("newh6namemem: calloc");
919 	}
920 	--num;
921 	p = ptr++;
922 	return (p);
923 }
924 #endif /* INET6 */
925