* and address to string conversion routines
*/
#ifndef lint
-static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.88 2002-06-02 00:07:36 guy Exp $ (LBL)";
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.108.2.8 2006-02-27 07:27:16 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <netinet/in.h>
+#include <tcpdump-stdinc.h>
#ifdef USE_ETHER_NTOHOST
#ifdef HAVE_NETINET_IF_ETHER_H
#include <net/if.h> /* for "struct ifnet" in "struct arpcom" on Solaris */
#include <netinet/if_ether.h>
#endif /* HAVE_NETINET_IF_ETHER_H */
-#endif /* USE_ETHER_NTOHOST */
+#ifdef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST
+#include <netinet/ether.h>
+#endif /* NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */
+
+#if !defined(HAVE_DECL_ETHER_NTOHOST) || !HAVE_DECL_ETHER_NTOHOST
+#ifndef HAVE_STRUCT_ETHER_ADDR
+struct ether_addr {
+ unsigned char ether_addr_octet[6];
+};
+#endif
+extern int ether_ntohost(char *, const struct ether_addr *);
+#endif
-#include <arpa/inet.h>
+#endif /* USE_ETHER_NTOHOST */
-#include <ctype.h>
-#include <netdb.h>
#include <pcap.h>
#include <pcap-namedb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <unistd.h>
#include "interface.h"
#include "addrtoname.h"
#include "llc.h"
#include "setsignal.h"
+#include "extract.h"
+#include "oui.h"
+
+#ifndef ETHER_ADDR_LEN
+#include "ether.h"
+#endif
/*
* hash tables for whatever-to-name translations
*/
#define HASHNAMESIZE 4096
+#define BUFSIZE 128
struct hnamemem {
u_int32_t addr;
struct hnamemem uporttable[HASHNAMESIZE];
struct hnamemem eprototable[HASHNAMESIZE];
struct hnamemem dnaddrtable[HASHNAMESIZE];
-struct hnamemem llcsaptable[HASHNAMESIZE];
struct hnamemem ipxsaptable[HASHNAMESIZE];
+#if defined(INET6) && defined(WIN32)
+/*
+ * fake gethostbyaddr for Win2k/XP
+ * gethostbyaddr() returns incorrect value when AF_INET6 is passed
+ * to 3rd argument.
+ *
+ * h_name in struct hostent is only valid.
+ */
+static struct hostent *
+win32_gethostbyaddr(const char *addr, int len, int type)
+{
+ static struct hostent host;
+ static char hostbuf[NI_MAXHOST];
+ char hname[NI_MAXHOST];
+ struct sockaddr_in6 addr6;
+
+ host.h_name = hostbuf;
+ switch (type) {
+ case AF_INET:
+ return gethostbyaddr(addr, len, type);
+ break;
+ case AF_INET6:
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ memcpy(&addr6.sin6_addr, addr, len);
+ if (getnameinfo((struct sockaddr *)&addr6, sizeof(addr6),
+ hname, sizeof(hname), NULL, 0, 0)) {
+ return NULL;
+ } else {
+ strcpy(host.h_name, hname);
+ return &host;
+ }
+ break;
+ default:
+ return NULL;
+ }
+}
+#define gethostbyaddr win32_gethostbyaddr
+#endif /* INET6 & WIN32 */
+
#ifdef INET6
struct h6namemem {
struct in6_addr addr;
static char buf[sizeof(".xxx.xxx.xxx.xxx")];
NTOHL(addr);
- cp = &buf[sizeof buf];
+ cp = buf + sizeof(buf);
*--cp = '\0';
n = 4;
static u_int32_t f_netmask;
static u_int32_t f_localnet;
-static u_int32_t netmask;
/*
* Return a name for the IP address pointed to by ap. This address
* is assumed to be in network byte order.
+ *
+ * NOTE: ap is *NOT* necessarily part of the packet data (not even if
+ * this is being called with the "ipaddr_string()" macro), so you
+ * *CANNOT* use the TCHECK{2}/TTEST{2} macros on it. Furthermore,
+ * even in cases where it *is* part of the packet data, the caller
+ * would still have to check for a null return value, even if it's
+ * just printing the return value with "%s" - not all versions of
+ * printf print "(null)" with "%s" and a null pointer, some of them
+ * don't check for a null pointer and crash in that case.
+ *
+ * The callers of this routine should, before handing this routine
+ * a pointer to packet data, be sure that the data is present in
+ * the packet buffer. They should probably do those checks anyway,
+ * as other data at that layer might not be IP addresses, and it
+ * also needs to check whether they're present in the packet buffer.
*/
const char *
getname(const u_char *ap)
p->nxt = newhnamemem();
/*
- * Only print names when:
- * (1) -n was not given.
+ * Print names unless:
+ * (1) -n was given.
* (2) Address is foreign and -f was given. (If -f was not
- * give, f_netmask and f_local are 0 and the test
+ * given, f_netmask and f_localnet are 0 and the test
* evaluates to true)
- * (3) -a was given or the host portion is not all ones
- * nor all zeros (i.e. not a network or broadcast address)
*/
if (!nflag &&
- (addr & f_netmask) == f_localnet &&
- (aflag ||
- !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))) {
+ (addr & f_netmask) == f_localnet) {
hp = gethostbyaddr((char *)&addr, 4, AF_INET);
if (hp) {
char *dotp;
p->nxt = newh6namemem();
/*
- * Only print names when:
- * (1) -n was not given.
- * (2) Address is foreign and -f was given. (If -f was not
- * give, f_netmask and f_local are 0 and the test
- * evaluates to true)
- * (3) -a was given or the host portion is not all ones
- * nor all zeros (i.e. not a network or broadcast address)
+ * Do not print names if -n was given.
*/
- if (!nflag
-#if 0
- &&
- (addr & f_netmask) == f_localnet &&
- (aflag ||
- !((addr & ~netmask) == 0 || (addr | netmask) == 0xffffffff))
-#endif
- ) {
+ if (!nflag) {
hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);
if (hp) {
char *dotp;
}
/*
- * Find the hash node that corresponds to the bytestring 'bs'
+ * Find the hash node that corresponds to the bytestring 'bs'
* with length 'nlen'
*/
const char *
etheraddr_string(register const u_char *ep)
{
- register u_int i, j;
+ register int i;
register char *cp;
register struct enamemem *tp;
- char buf[sizeof("00:00:00:00:00:00")];
+ int oui;
+ char buf[BUFSIZE];
tp = lookup_emem(ep);
if (tp->e_name)
return (tp->e_name);
#ifdef USE_ETHER_NTOHOST
if (!nflag) {
- char buf2[128];
- if (ether_ntohost(buf2, (const struct ether_addr *)ep) == 0) {
+ char buf2[BUFSIZE];
+
+ /*
+ * We don't cast it to "const struct ether_addr *"
+ * because some systems fail to declare the second
+ * argument as a "const" pointer, even though they
+ * don't modify what it points to.
+ */
+ if (ether_ntohost(buf2, (struct ether_addr *)ep) == 0) {
tp->e_name = strdup(buf2);
return (tp->e_name);
}
}
#endif
cp = buf;
- if ((j = *ep >> 4) != 0)
- *cp++ = hex[j];
+ oui = EXTRACT_24BITS(ep);
+ *cp++ = hex[*ep >> 4 ];
*cp++ = hex[*ep++ & 0xf];
- for (i = 5; (int)--i >= 0;) {
+ for (i = 5; --i >= 0;) {
*cp++ = ':';
- if ((j = *ep >> 4) != 0)
- *cp++ = hex[j];
+ *cp++ = hex[*ep >> 4 ];
*cp++ = hex[*ep++ & 0xf];
}
- *cp = '\0';
+
+ if (!nflag) {
+ snprintf(cp, BUFSIZE - (2 + 5*3), " (oui %s)",
+ tok2str(oui_values, "Unknown", oui));
+ } else
+ *cp = '\0';
tp->e_name = strdup(buf);
return (tp->e_name);
}
const char *
linkaddr_string(const u_char *ep, const unsigned int len)
{
- register u_int i, j;
+ register u_int i;
register char *cp;
register struct enamemem *tp;
if (len == 6) /* XXX not totally correct... */
return etheraddr_string(ep);
-
+
tp = lookup_bytestring(ep, len);
if (tp->e_name)
return (tp->e_name);
tp->e_name = cp = (char *)malloc(len*3);
if (tp->e_name == NULL)
error("linkaddr_string: malloc");
- if ((j = *ep >> 4) != 0)
- *cp++ = hex[j];
+ *cp++ = hex[*ep >> 4];
*cp++ = hex[*ep++ & 0xf];
for (i = len-1; i > 0 ; --i) {
*cp++ = ':';
- if ((j = *ep >> 4) != 0)
- *cp++ = hex[j];
+ *cp++ = hex[*ep >> 4];
*cp++ = hex[*ep++ & 0xf];
}
*cp = '\0';
return (tp->p_name);
}
+#define ISONSAP_MAX_LENGTH 20
const char *
-llcsap_string(u_char sap)
-{
- register struct hnamemem *tp;
- register u_int32_t i = sap;
- char buf[sizeof("sap 00")];
-
- for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
- if (tp->addr == i)
- return (tp->name);
-
- tp->addr = i;
- tp->nxt = newhnamemem();
-
- snprintf(buf, sizeof(buf), "sap %02x", sap & 0xff);
- tp->name = strdup(buf);
- return (tp->name);
-}
-
-const char *
-isonsap_string(const u_char *nsap)
+isonsap_string(const u_char *nsap, register u_int nsap_length)
{
- register u_int i, nlen = nsap[0];
+ register u_int nsap_idx;
register char *cp;
register struct enamemem *tp;
+ if (nsap_length < 1 || nsap_length > ISONSAP_MAX_LENGTH)
+ return ("isonsap_string: illegal length");
+
tp = lookup_nsap(nsap);
if (tp->e_name)
return tp->e_name;
- tp->e_name = cp = (char *)malloc(nlen * 2 + 2);
+ tp->e_name = cp = (char *)malloc(sizeof("xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx"));
if (cp == NULL)
error("isonsap_string: malloc");
- nsap++;
- *cp++ = '/';
- for (i = nlen; (int)--i >= 0;) {
+ for (nsap_idx = 0; nsap_idx < nsap_length; nsap_idx++) {
*cp++ = hex[*nsap >> 4];
*cp++ = hex[*nsap++ & 0xf];
+ if (((nsap_idx & 1) == 0) &&
+ (nsap_idx + 1 < nsap_length)) {
+ *cp++ = '.';
+ }
}
*cp = '\0';
return (tp->e_name);
endservent();
}
-/*XXX from libbpfc.a */
-extern struct eproto {
- char *s;
+/* in libpcap.a (nametoaddr.c) */
+#if defined(WIN32) && !defined(USE_STATIC_LIBPCAP)
+__declspec(dllimport)
+#else
+extern
+#endif
+const struct eproto {
+ const char *s;
u_short p;
} eproto_db[];
continue;
#ifdef USE_ETHER_NTOHOST
- /* Use yp/nis version of name if available */
- if (ether_ntohost(name, (const struct ether_addr *)el->addr) == 0) {
- tp->e_name = strdup(name);
+ /*
+ * Use YP/NIS version of name if available.
+ *
+ * We don't cast it to "const struct ether_addr *"
+ * because some systems don't modify the Ethernet
+ * address but fail to declare the second argument
+ * as a "const" pointer.
+ */
+ if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
+ tp->e_name = strdup(name);
continue;
}
#endif
}
}
-static struct tok llcsap_db[] = {
- { LLCSAP_NULL, "null" },
- { LLCSAP_8021B_I, "802.1b-gsap" },
- { LLCSAP_8021B_G, "802.1b-isap" },
- { LLCSAP_IP, "ip-sap" },
- { LLCSAP_PROWAYNM, "proway-nm" },
- { LLCSAP_8021D, "802.1d" },
- { LLCSAP_RS511, "eia-rs511" },
- { LLCSAP_ISO8208, "x.25/llc2" },
- { LLCSAP_PROWAY, "proway" },
- { LLCSAP_SNAP, "snap" },
- { LLCSAP_IPX, "IPX" },
- { LLCSAP_NETBEUI, "netbeui" },
- { LLCSAP_ISONS, "iso-clns" },
- { LLCSAP_GLOBAL, "global" },
- { 0, NULL }
-};
-
-static void
-init_llcsaparray(void)
-{
- register int i;
- register struct hnamemem *table;
-
- for (i = 0; llcsap_db[i].s != NULL; i++) {
- table = &llcsaptable[llcsap_db[i].v];
- while (table->name)
- table = table->nxt;
- table->name = llcsap_db[i].s;
- table->addr = llcsap_db[i].v;
- table->nxt = newhnamemem();
- }
-}
-
static struct tok ipxsap_db[] = {
{ 0x0000, "Unknown" },
{ 0x0001, "User" },
void
init_addrtoname(u_int32_t localnet, u_int32_t mask)
{
- netmask = mask;
if (fflag) {
f_localnet = localnet;
f_netmask = mask;
init_etherarray();
init_servarray();
init_eprotoarray();
- init_llcsaparray();
init_protoidarray();
init_ipxsaparray();
}