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