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