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