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