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