]> The Tcpdump Group git mirrors - tcpdump/blob - addrtoname.c
add AES and SHA2-*
[tcpdump] / addrtoname.c
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: /tcpdump/master/tcpdump/addrtoname.c,v 1.68 2000-07-01 03:38:59 assar Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/time.h>
36
37 struct mbuf;
38 struct rtentry;
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 #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);
518 if (cp == NULL)
519 error("isonsap_string: malloc");
520
521 nsap++;
522 *cp++ = '/';
523 for (i = nlen; (int)--i >= 0;) {
524 *cp++ = hex[*nsap >> 4];
525 *cp++ = hex[*nsap++ & 0xf];
526 }
527 *cp = '\0';
528 return (tp->e_name);
529 }
530
531 char *
532 tcpport_string(u_short port)
533 {
534 register struct hnamemem *tp;
535 register u_int32_t i = port;
536 char buf[sizeof("00000")];
537
538 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
539 if (tp->addr == i)
540 return (tp->name);
541
542 tp->addr = i;
543 tp->nxt = newhnamemem();
544
545 (void)snprintf(buf, sizeof(buf), "%u", i);
546 tp->name = savestr(buf);
547 return (tp->name);
548 }
549
550 char *
551 udpport_string(register u_short port)
552 {
553 register struct hnamemem *tp;
554 register u_int32_t i = port;
555 char buf[sizeof("00000")];
556
557 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
558 if (tp->addr == i)
559 return (tp->name);
560
561 tp->addr = i;
562 tp->nxt = newhnamemem();
563
564 (void)snprintf(buf, sizeof(buf), "%u", i);
565 tp->name = savestr(buf);
566 return (tp->name);
567 }
568
569 static void
570 init_servarray(void)
571 {
572 struct servent *sv;
573 register struct hnamemem *table;
574 register int i;
575 char buf[sizeof("0000000000")];
576
577 while ((sv = getservent()) != NULL) {
578 int port = ntohs(sv->s_port);
579 i = port & (HASHNAMESIZE-1);
580 if (strcmp(sv->s_proto, "tcp") == 0)
581 table = &tporttable[i];
582 else if (strcmp(sv->s_proto, "udp") == 0)
583 table = &uporttable[i];
584 else
585 continue;
586
587 while (table->name)
588 table = table->nxt;
589 if (nflag) {
590 (void)snprintf(buf, sizeof(buf), "%d", port);
591 table->name = savestr(buf);
592 } else
593 table->name = savestr(sv->s_name);
594 table->addr = port;
595 table->nxt = newhnamemem();
596 }
597 endservent();
598 }
599
600 /*XXX from libbpfc.a */
601 extern struct eproto {
602 char *s;
603 u_short p;
604 } eproto_db[];
605
606 static void
607 init_eprotoarray(void)
608 {
609 register int i;
610 register struct hnamemem *table;
611
612 for (i = 0; eproto_db[i].s; i++) {
613 int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
614 table = &eprototable[j];
615 while (table->name)
616 table = table->nxt;
617 table->name = eproto_db[i].s;
618 table->addr = ntohs(eproto_db[i].p);
619 table->nxt = newhnamemem();
620 }
621 }
622
623 /*
624 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
625 * types.
626 */
627 static void
628 init_protoidarray(void)
629 {
630 register int i;
631 register struct protoidmem *tp;
632 u_char protoid[5];
633
634 protoid[0] = 0;
635 protoid[1] = 0;
636 protoid[2] = 0;
637 for (i = 0; eproto_db[i].s; i++) {
638 u_short etype = htons(eproto_db[i].p);
639
640 memcpy((char *)&protoid[3], (char *)&etype, 2);
641 tp = lookup_protoid(protoid);
642 tp->p_name = savestr(eproto_db[i].s);
643 }
644 }
645
646 static struct etherlist {
647 u_char addr[6];
648 char *name;
649 } etherlist[] = {
650 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
651 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
652 };
653
654 /*
655 * Initialize the ethers hash table. We take two different approaches
656 * depending on whether or not the system provides the ethers name
657 * service. If it does, we just wire in a few names at startup,
658 * and etheraddr_string() fills in the table on demand. If it doesn't,
659 * then we suck in the entire /etc/ethers file at startup. The idea
660 * is that parsing the local file will be fast, but spinning through
661 * all the ethers entries via NIS & next_etherent might be very slow.
662 *
663 * XXX pcap_next_etherent doesn't belong in the pcap interface, but
664 * since the pcap module already does name-to-address translation,
665 * it's already does most of the work for the ethernet address-to-name
666 * translation, so we just pcap_next_etherent as a convenience.
667 */
668 static void
669 init_etherarray(void)
670 {
671 register struct etherlist *el;
672 register struct enamemem *tp;
673 #ifdef HAVE_ETHER_NTOHOST
674 char name[256];
675 #else
676 register struct pcap_etherent *ep;
677 register FILE *fp;
678
679 /* Suck in entire ethers file */
680 fp = fopen(PCAP_ETHERS_FILE, "r");
681 if (fp != NULL) {
682 while ((ep = pcap_next_etherent(fp)) != NULL) {
683 tp = lookup_emem(ep->addr);
684 tp->e_name = savestr(ep->name);
685 }
686 (void)fclose(fp);
687 }
688 #endif
689
690 /* Hardwire some ethernet names */
691 for (el = etherlist; el->name != NULL; ++el) {
692 tp = lookup_emem(el->addr);
693 /* Don't override existing name */
694 if (tp->e_name != NULL)
695 continue;
696
697 #ifdef HAVE_ETHER_NTOHOST
698 /* Use yp/nis version of name if available */
699 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
700 tp->e_name = savestr(name);
701 continue;
702 }
703 #endif
704 tp->e_name = el->name;
705 }
706 }
707
708 static struct tok llcsap_db[] = {
709 { LLCSAP_NULL, "null" },
710 { LLCSAP_8021B_I, "802.1b-gsap" },
711 { LLCSAP_8021B_G, "802.1b-isap" },
712 { LLCSAP_IP, "ip-sap" },
713 { LLCSAP_PROWAYNM, "proway-nm" },
714 { LLCSAP_8021D, "802.1d" },
715 { LLCSAP_RS511, "eia-rs511" },
716 { LLCSAP_ISO8208, "x.25/llc2" },
717 { LLCSAP_PROWAY, "proway" },
718 { LLCSAP_ISONS, "iso-clns" },
719 { LLCSAP_GLOBAL, "global" },
720 { 0, NULL }
721 };
722
723 static void
724 init_llcsaparray(void)
725 {
726 register int i;
727 register struct hnamemem *table;
728
729 for (i = 0; llcsap_db[i].s != NULL; i++) {
730 table = &llcsaptable[llcsap_db[i].v];
731 while (table->name)
732 table = table->nxt;
733 table->name = llcsap_db[i].s;
734 table->addr = llcsap_db[i].v;
735 table->nxt = newhnamemem();
736 }
737 }
738
739 /*
740 * Initialize the address to name translation machinery. We map all
741 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
742 * to prevent blocking on the nameserver). localnet is the IP address
743 * of the local network. mask is its subnet mask.
744 */
745 void
746 init_addrtoname(u_int32_t localnet, u_int32_t mask)
747 {
748 netmask = mask;
749 if (fflag) {
750 f_localnet = localnet;
751 f_netmask = mask;
752 }
753 if (nflag)
754 /*
755 * Simplest way to suppress names.
756 */
757 return;
758
759 init_etherarray();
760 init_servarray();
761 init_eprotoarray();
762 init_llcsaparray();
763 init_protoidarray();
764 }
765
766 char *
767 dnaddr_string(u_short dnaddr)
768 {
769 register struct hnamemem *tp;
770
771 for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
772 tp = tp->nxt)
773 if (tp->addr == dnaddr)
774 return (tp->name);
775
776 tp->addr = dnaddr;
777 tp->nxt = newhnamemem();
778 if (nflag)
779 tp->name = dnnum_string(dnaddr);
780 else
781 tp->name = dnname_string(dnaddr);
782
783 return(tp->name);
784 }
785
786 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
787 struct hnamemem *
788 newhnamemem(void)
789 {
790 register struct hnamemem *p;
791 static struct hnamemem *ptr = NULL;
792 static u_int num = 0;
793
794 if (num <= 0) {
795 num = 64;
796 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
797 if (ptr == NULL)
798 error("newhnamemem: calloc");
799 }
800 --num;
801 p = ptr++;
802 return (p);
803 }
804
805 #ifdef INET6
806 /* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */
807 struct h6namemem *
808 newh6namemem(void)
809 {
810 register struct h6namemem *p;
811 static struct h6namemem *ptr = NULL;
812 static u_int num = 0;
813
814 if (num <= 0) {
815 num = 64;
816 ptr = (struct h6namemem *)calloc(num, sizeof (*ptr));
817 if (ptr == NULL)
818 error("newh6namemem: calloc");
819 }
820 --num;
821 p = ptr++;
822 return (p);
823 }
824 #endif /* INET6 */