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