2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
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
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.
21 * Internet, ethernet, port, and protocol string to address
22 * and address to string conversion routines
27 static const char rcsid[] =
28 "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.64 1999/11/21 09:36:44 fenner Exp $ (LBL)";
35 #include <sys/types.h>
36 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <net/ethernet.h>
49 #include <netinet6/ip6.h>
52 #include <arpa/inet.h>
57 #include <pcap-namedb.h>
70 #include "interface.h"
71 #include "addrtoname.h"
74 #include "setsignal.h"
77 static RETSIGTYPE nohostname(int);
80 * hash tables for whatever-to-name translations
83 #define HASHNAMESIZE 4096
91 struct hnamemem hnametable[HASHNAMESIZE];
92 struct hnamemem tporttable[HASHNAMESIZE];
93 struct hnamemem uporttable[HASHNAMESIZE];
94 struct hnamemem eprototable[HASHNAMESIZE];
95 struct hnamemem dnaddrtable[HASHNAMESIZE];
96 struct hnamemem llcsaptable[HASHNAMESIZE];
100 struct in6_addr addr;
102 struct h6namemem *nxt;
105 struct h6namemem h6nametable[HASHNAMESIZE];
113 u_char *e_nsap; /* used only for nsaptable[] */
114 struct enamemem *e_nxt;
117 struct enamemem enametable[HASHNAMESIZE];
118 struct enamemem nsaptable[HASHNAMESIZE];
124 struct protoidmem *p_nxt;
127 struct protoidmem protoidtable[HASHNAMESIZE];
130 * A faster replacement for inet_ntoa().
133 intoa(u_int32_t addr)
138 static char buf[sizeof(".xxx.xxx.xxx.xxx")];
141 cp = &buf[sizeof buf];
147 *--cp = byte % 10 + '0';
150 *--cp = byte % 10 + '0';
162 static u_int32_t f_netmask;
163 static u_int32_t f_localnet;
164 static u_int32_t netmask;
167 * "getname" is written in this atrocious way to make sure we don't
168 * wait forever while trying to get hostnames from yp.
175 nohostname(int signo)
177 longjmp(getname_env, 1);
181 * Return a name for the IP address pointed to by ap. This address
182 * is assumed to be in network byte order.
185 getname(const u_char *ap)
187 register struct hostent *hp;
189 static struct hnamemem *p; /* static for longjmp() */
192 addr = *(const u_int32_t *)ap;
194 memcpy(&addr, ap, sizeof(addr));
196 p = &hnametable[addr & (HASHNAMESIZE-1)];
197 for (; p->nxt; p = p->nxt) {
202 p->nxt = newhnamemem();
205 * Only print names when:
206 * (1) -n was not given.
207 * (2) Address is foreign and -f was given. (If -f was not
208 * give, f_netmask and f_local are 0 and the test
210 * (3) -a was given or the host portion is not all ones
211 * nor all zeros (i.e. not a network or broadcast address)
214 (addr & f_netmask) == f_localnet &&
216 !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) {
217 if (!setjmp(getname_env)) {
218 (void)setsignal(SIGALRM, nohostname);
220 hp = gethostbyaddr((char *)&addr, 4, AF_INET);
225 p->name = savestr(hp->h_name);
227 /* Remove domain qualifications */
228 dotp = strchr(p->name, '.');
236 p->name = savestr(intoa(addr));
242 * Return a name for the IP6 address pointed to by ap. This address
243 * is assumed to be in network byte order.
246 getname6(const u_char *ap)
248 register struct hostent *hp;
249 struct in6_addr addr;
250 static struct h6namemem *p; /* static for longjmp() */
252 char ntop_buf[INET6_ADDRSTRLEN];
254 memcpy(&addr, ap, sizeof(addr));
255 p = &h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)];
256 for (; p->nxt; p = p->nxt) {
257 if (memcmp(&p->addr, &addr, sizeof(addr)) == 0)
261 p->nxt = newh6namemem();
264 * Only print names when:
265 * (1) -n was not given.
266 * (2) Address is foreign and -f was given. (If -f was not
267 * give, f_netmask and f_local are 0 and the test
269 * (3) -a was given or the host portion is not all ones
270 * nor all zeros (i.e. not a network or broadcast address)
275 (addr & f_netmask) == f_localnet &&
277 !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))
280 if (!setjmp(getname_env)) {
281 (void)setsignal(SIGALRM, nohostname);
283 hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);
288 p->name = savestr(hp->h_name);
290 /* Remove domain qualifications */
291 dotp = strchr(p->name, '.');
299 cp = (char *)inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf));
300 p->name = savestr(cp);
305 static char hex[] = "0123456789abcdef";
308 /* Find the hash node that corresponds the ether address 'ep' */
310 static inline struct enamemem *
311 lookup_emem(const u_char *ep)
313 register u_int i, j, k;
316 k = (ep[0] << 8) | ep[1];
317 j = (ep[2] << 8) | ep[3];
318 i = (ep[4] << 8) | ep[5];
320 tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
322 if (tp->e_addr0 == i &&
331 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
332 if (tp->e_nxt == NULL)
333 error("lookup_emem: calloc");
338 /* Find the hash node that corresponds the NSAP 'nsap' */
340 static inline struct enamemem *
341 lookup_nsap(register const u_char *nsap)
343 register u_int i, j, k;
346 const u_char *ensap = nsap + nlen - 6;
349 k = (ensap[0] << 8) | ensap[1];
350 j = (ensap[2] << 8) | ensap[3];
351 i = (ensap[4] << 8) | ensap[5];
356 tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
358 if (tp->e_addr0 == i &&
361 tp->e_nsap[0] == nlen &&
362 memcmp((char *)&(nsap[1]),
363 (char *)&(tp->e_nsap[1]), nlen) == 0)
370 tp->e_nsap = (u_char *)malloc(nlen + 1);
371 if (tp->e_nsap == NULL)
372 error("lookup_nsap: malloc");
373 memcpy((char *)tp->e_nsap, (char *)nsap, nlen + 1);
374 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
375 if (tp->e_nxt == NULL)
376 error("lookup_nsap: calloc");
381 /* Find the hash node that corresponds the protoid 'pi'. */
383 static inline struct protoidmem *
384 lookup_protoid(const u_char *pi)
387 struct protoidmem *tp;
389 /* 5 octets won't be aligned */
390 i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
391 j = (pi[3] << 8) + pi[4];
392 /* XXX should be endian-insensitive, but do big-endian testing XXX */
394 tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
396 if (tp->p_oui == i && tp->p_proto == j)
402 tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
403 if (tp->p_nxt == NULL)
404 error("lookup_protoid: calloc");
410 etheraddr_string(register const u_char *ep)
414 register struct enamemem *tp;
415 char buf[sizeof("00:00:00:00:00:00")];
417 tp = lookup_emem(ep);
420 #ifdef HAVE_ETHER_NTOHOST
423 if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
424 tp->e_name = savestr(buf);
430 if ((j = *ep >> 4) != 0)
432 *cp++ = hex[*ep++ & 0xf];
433 for (i = 5; (int)--i >= 0;) {
435 if ((j = *ep >> 4) != 0)
437 *cp++ = hex[*ep++ & 0xf];
440 tp->e_name = savestr(buf);
445 etherproto_string(u_short port)
448 register struct hnamemem *tp;
449 register u_int32_t i = port;
450 char buf[sizeof("0000")];
452 for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
457 tp->nxt = newhnamemem();
461 *cp++ = hex[port >> 12 & 0xf];
462 *cp++ = hex[port >> 8 & 0xf];
463 *cp++ = hex[port >> 4 & 0xf];
464 *cp++ = hex[port & 0xf];
466 tp->name = savestr(buf);
471 protoid_string(register const u_char *pi)
475 register struct protoidmem *tp;
476 char buf[sizeof("00:00:00:00:00")];
478 tp = lookup_protoid(pi);
483 if ((j = *pi >> 4) != 0)
485 *cp++ = hex[*pi++ & 0xf];
486 for (i = 4; (int)--i >= 0;) {
488 if ((j = *pi >> 4) != 0)
490 *cp++ = hex[*pi++ & 0xf];
493 tp->p_name = savestr(buf);
498 llcsap_string(u_char sap)
501 register struct hnamemem *tp;
502 register u_int32_t i = sap;
503 char buf[sizeof("sap 00")];
505 for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
510 tp->nxt = newhnamemem();
513 (void)strcpy(cp, "sap ");
515 *cp++ = hex[sap >> 4 & 0xf];
516 *cp++ = hex[sap & 0xf];
518 tp->name = savestr(buf);
523 isonsap_string(const u_char *nsap)
525 register u_int i, nlen = nsap[0];
527 register struct enamemem *tp;
529 tp = lookup_nsap(nsap);
533 tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1));
535 error("isonsap_string: malloc");
538 for (i = 0; i < nlen; i++) {
539 *cp++ = hex[*nsap >> 4];
540 *cp++ = hex[*nsap++ & 0xf];
541 if (((i & 1) == 0) && (i + 1 < nlen))
549 tcpport_string(u_short port)
551 register struct hnamemem *tp;
552 register u_int32_t i = port;
553 char buf[sizeof("00000")];
555 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
560 tp->nxt = newhnamemem();
562 (void)sprintf(buf, "%u", i);
563 tp->name = savestr(buf);
568 udpport_string(register u_short port)
570 register struct hnamemem *tp;
571 register u_int32_t i = port;
572 char buf[sizeof("00000")];
574 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
579 tp->nxt = newhnamemem();
581 (void)sprintf(buf, "%u", i);
582 tp->name = savestr(buf);
590 register struct hnamemem *table;
592 char buf[sizeof("0000000000")];
594 while ((sv = getservent()) != NULL) {
595 int port = ntohs(sv->s_port);
596 i = port & (HASHNAMESIZE-1);
597 if (strcmp(sv->s_proto, "tcp") == 0)
598 table = &tporttable[i];
599 else if (strcmp(sv->s_proto, "udp") == 0)
600 table = &uporttable[i];
607 (void)sprintf(buf, "%d", port);
608 table->name = savestr(buf);
610 table->name = savestr(sv->s_name);
612 table->nxt = newhnamemem();
617 /*XXX from libbpfc.a */
618 extern struct eproto {
624 init_eprotoarray(void)
627 register struct hnamemem *table;
629 for (i = 0; eproto_db[i].s; i++) {
630 int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
631 table = &eprototable[j];
634 table->name = eproto_db[i].s;
635 table->addr = ntohs(eproto_db[i].p);
636 table->nxt = newhnamemem();
641 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
645 init_protoidarray(void)
648 register struct protoidmem *tp;
654 for (i = 0; eproto_db[i].s; i++) {
655 u_short etype = htons(eproto_db[i].p);
657 memcpy((char *)&protoid[3], (char *)&etype, 2);
658 tp = lookup_protoid(protoid);
659 tp->p_name = savestr(eproto_db[i].s);
663 static struct etherlist {
667 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
668 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
672 * Initialize the ethers hash table. We take two different approaches
673 * depending on whether or not the system provides the ethers name
674 * service. If it does, we just wire in a few names at startup,
675 * and etheraddr_string() fills in the table on demand. If it doesn't,
676 * then we suck in the entire /etc/ethers file at startup. The idea
677 * is that parsing the local file will be fast, but spinning through
678 * all the ethers entries via NIS & next_etherent might be very slow.
680 * XXX pcap_next_etherent doesn't belong in the pcap interface, but
681 * since the pcap module already does name-to-address translation,
682 * it's already does most of the work for the ethernet address-to-name
683 * translation, so we just pcap_next_etherent as a convenience.
686 init_etherarray(void)
688 register struct etherlist *el;
689 register struct enamemem *tp;
690 #ifdef HAVE_ETHER_NTOHOST
693 register struct pcap_etherent *ep;
696 /* Suck in entire ethers file */
697 fp = fopen(PCAP_ETHERS_FILE, "r");
699 while ((ep = pcap_next_etherent(fp)) != NULL) {
700 tp = lookup_emem(ep->addr);
701 tp->e_name = savestr(ep->name);
707 /* Hardwire some ethernet names */
708 for (el = etherlist; el->name != NULL; ++el) {
709 tp = lookup_emem(el->addr);
710 /* Don't override existing name */
711 if (tp->e_name != NULL)
714 #ifdef HAVE_ETHER_NTOHOST
715 /* Use yp/nis version of name if available */
716 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
717 tp->e_name = savestr(name);
721 tp->e_name = el->name;
725 static struct tok llcsap_db[] = {
726 { LLCSAP_NULL, "null" },
727 { LLCSAP_8021B_I, "802.1b-gsap" },
728 { LLCSAP_8021B_G, "802.1b-isap" },
729 { LLCSAP_IP, "ip-sap" },
730 { LLCSAP_PROWAYNM, "proway-nm" },
731 { LLCSAP_8021D, "802.1d" },
732 { LLCSAP_RS511, "eia-rs511" },
733 { LLCSAP_ISO8208, "x.25/llc2" },
734 { LLCSAP_PROWAY, "proway" },
735 { LLCSAP_ISONS, "iso-clns" },
736 { LLCSAP_GLOBAL, "global" },
741 init_llcsaparray(void)
744 register struct hnamemem *table;
746 for (i = 0; llcsap_db[i].s != NULL; i++) {
747 table = &llcsaptable[llcsap_db[i].v];
750 table->name = llcsap_db[i].s;
751 table->addr = llcsap_db[i].v;
752 table->nxt = newhnamemem();
757 * Initialize the address to name translation machinery. We map all
758 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
759 * to prevent blocking on the nameserver). localnet is the IP address
760 * of the local network. mask is its subnet mask.
763 init_addrtoname(u_int32_t localnet, u_int32_t mask)
767 f_localnet = localnet;
772 * Simplest way to suppress names.
784 dnaddr_string(u_short dnaddr)
786 register struct hnamemem *tp;
788 for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
790 if (tp->addr == dnaddr)
794 tp->nxt = newhnamemem();
796 tp->name = dnnum_string(dnaddr);
798 tp->name = dnname_string(dnaddr);
803 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
807 register struct hnamemem *p;
808 static struct hnamemem *ptr = NULL;
809 static u_int num = 0;
813 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
815 error("newhnamemem: calloc");
823 /* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */
827 register struct h6namemem *p;
828 static struct h6namemem *ptr = NULL;
829 static u_int num = 0;
833 ptr = (struct h6namemem *)calloc(num, sizeof (*ptr));
835 error("newh6namemem: calloc");