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