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