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