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