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