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