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