aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--capture.c139
-rw-r--r--ethereal.c6
-rw-r--r--ethereal.h3
-rw-r--r--etypes.h4
-rw-r--r--file.c11
-rw-r--r--file.h10
-rw-r--r--packet-eth.c4
-rw-r--r--packet-null.c367
-rw-r--r--packet.c4
-rw-r--r--wiretap/libpcap.c63
-rw-r--r--wiretap/wtap.h26
11 files changed, 453 insertions, 184 deletions
diff --git a/capture.c b/capture.c
index 92293844b2..93d1946f8b 100644
--- a/capture.c
+++ b/capture.c
@@ -1,7 +1,7 @@
/* capture.c
* Routines for packet capture windows
*
- * $Id: capture.c,v 1.57 1999/08/19 05:42:22 guy Exp $
+ * $Id: capture.c,v 1.58 1999/08/22 00:47:45 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -109,6 +109,8 @@ extern int quit_after_cap;
/* Capture filter key */
#define E_CAP_FILT_TE_KEY "cap_filt_te"
+static void search_for_if_cb(gpointer data, gpointer user_data);
+static void free_if_cb(gpointer data, gpointer user_data);
static void capture_prep_ok_cb(GtkWidget *, gpointer);
static void capture_prep_close_cb(GtkWidget *, gpointer);
static float pct(gint, gint);
@@ -116,12 +118,20 @@ static void capture_stop_cb(GtkWidget *, gpointer);
static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
const u_char *);
+struct search_user_data {
+ char *name;
+ int found;
+};
+
static GList *
get_interface_list() {
GList *il = NULL;
+ gint nonloopback_pos = 0;
struct ifreq *ifr, *last;
struct ifconf ifc;
+ struct ifreq ifrflags;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ struct search_user_data user_data;
if (sock < 0)
{
@@ -139,7 +149,7 @@ get_interface_list() {
ifc.ifc_len < sizeof(struct ifreq))
{
simple_dialog(ESD_TYPE_WARN, NULL,
- "Can't list interfaces: ioctl error.");
+ "Can't list interfaces: SIOCGIFCONF error: %s", strerror(errno));
return NULL;
}
@@ -148,19 +158,62 @@ get_interface_list() {
while (ifr < last)
{
/*
- * What we want:
- * - Interfaces that are up, and not loopback
- * - IP interfaces (do we really need this?)
- * - Anything that doesn't begin with "lo" (loopback again) or "dummy"
- * - Anything that doesn't include a ":" (Solaris virtuals)
+ * Skip addresses that begin with "dummy", or that include a ":"
+ * (the latter are Solaris virtuals).
+ */
+ if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||
+ strchr(ifr->ifr_name, ':') != NULL)
+ goto next;
+
+ /*
+ * If we already have this interface name on the list, don't add
+ * it (SIOCGIFCONF returns, at least on BSD-flavored systems, one
+ * entry per interface *address*; if an interface has multiple
+ * addresses, we get multiple entries for it).
+ */
+ user_data.name = ifr->ifr_name;
+ user_data.found = FALSE;
+ g_list_foreach(il, search_for_if_cb, &user_data);
+ if (user_data.found)
+ goto next;
+
+ /*
+ * Get the interface flags.
+ */
+ memset(&ifrflags, 0, sizeof ifrflags);
+ strncpy(ifrflags.ifr_name, ifr->ifr_name, sizeof ifrflags.ifr_name);
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+ if (errno == ENXIO)
+ goto next;
+ simple_dialog(ESD_TYPE_WARN, NULL,
+ "Can't list interfaces: SIOCGIFFLAGS error on %s: %s",
+ ifr->ifr_name, strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * Skip interfaces that aren't up.
*/
- if (! (ifr->ifr_flags & (IFF_UP | IFF_LOOPBACK)) &&
- (ifr->ifr_addr.sa_family == AF_INET) &&
- strncmp(ifr->ifr_name, "lo", 2) &&
- strncmp(ifr->ifr_name, "dummy", 5) &&
- ! strchr(ifr->ifr_name, ':')) {
- il = g_list_append(il, g_strdup(ifr->ifr_name));
+ if (!(ifrflags.ifr_flags & IFF_UP))
+ goto next;
+
+ /*
+ * If it's a loopback interface, add it at the end of the list,
+ * otherwise add it after the last non-loopback interface,
+ * so all loopback interfaces go at the end - we don't want a
+ * loopback interface to be the default capture device unless there
+ * are no non-loopback devices.
+ */
+ if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||
+ strncmp(ifr->ifr_name, "lo", 2) == 0)
+ il = g_list_insert(il, g_strdup(ifr->ifr_name), -1);
+ else {
+ il = g_list_insert(il, g_strdup(ifr->ifr_name), nonloopback_pos);
+ /* Insert the next non-loopback interface after this one. */
+ nonloopback_pos++;
}
+
+next:
#ifdef HAVE_SA_LEN
ifr = (struct ifreq *) ((char *) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
#else
@@ -170,6 +223,26 @@ get_interface_list() {
free(ifc.ifc_buf);
return il;
+
+fail:
+ g_list_foreach(il, free_if_cb, NULL);
+ g_list_free(il);
+ return NULL;
+}
+
+static void
+search_for_if_cb(gpointer data, gpointer user_data)
+{
+ struct search_user_data *search_user_data = user_data;
+
+ if (strcmp((char *)data, search_user_data->name) == 0)
+ search_user_data->found = TRUE;
+}
+
+static void
+free_if_cb(gpointer data, gpointer user_data)
+{
+ g_free(data);
}
void
@@ -268,7 +341,7 @@ capture_prep_cb(GtkWidget *w, gpointer d) {
gtk_widget_show(snap_lb);
adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap,
- MIN_PACKET_SIZE, MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
+ MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
snap_sb = gtk_spin_button_new (adj, 0, 0);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
gtk_widget_set_usize (snap_sb, 80, 0);
@@ -330,7 +403,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
cf.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
if (cf.snap < 1)
- cf.snap = MAX_PACKET_SIZE;
+ cf.snap = WTAP_MAX_PACKET_SIZE;
else if (cf.snap < MIN_PACKET_SIZE)
cf.snap = MIN_PACKET_SIZE;
@@ -427,7 +500,6 @@ typedef struct _loop_data {
gint go;
gint max;
gint linktype;
- gint wtap_linktype;
gint sync_packets;
packet_counts counts;
wtap_dumper *pdh;
@@ -449,7 +521,7 @@ capture(void) {
ld.go = TRUE;
ld.counts.total = 0;
ld.max = cf.count;
- ld.linktype = DLT_NULL;
+ ld.linktype = WTAP_ENCAP_UNKNOWN;
ld.sync_packets = 0;
ld.counts.tcp = 0;
ld.counts.udp = 0;
@@ -465,15 +537,14 @@ capture(void) {
pch = pcap_open_live(cf.iface, cf.snap, 1, 250, err_str);
if (pch) {
- ld.linktype = pcap_datalink(pch);
- ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
- if (ld.wtap_linktype == WTAP_ENCAP_UNKNOWN) {
+ ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(pch));
+ if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
errmsg = "The network you're capturing from is of a type"
" that Ethereal doesn't support.";
goto fail;
}
ld.pdh = wtap_dump_fdopen(cf.save_file_fd, WTAP_FILE_PCAP,
- ld.wtap_linktype, pcap_snapshot(pch), &err);
+ ld.linktype, pcap_snapshot(pch), &err);
if (ld.pdh == NULL) { /* We have an error */
switch (err) {
@@ -740,29 +811,41 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
whdr.ts = phdr->ts;
whdr.caplen = phdr->caplen;
whdr.len = phdr->len;
- whdr.pkt_encap = ld->wtap_linktype;
+ whdr.pkt_encap = ld->linktype;
/* XXX - do something if this fails */
wtap_dump(ld->pdh, &whdr, pd, &err);
}
switch (ld->linktype) {
- case DLT_EN10MB :
+ case WTAP_ENCAP_ETHERNET:
capture_eth(pd, phdr->caplen, &ld->counts);
break;
- case DLT_FDDI :
+ case WTAP_ENCAP_FDDI:
capture_fddi(pd, phdr->caplen, &ld->counts);
break;
- case DLT_IEEE802 :
+ case WTAP_ENCAP_TR:
capture_tr(pd, phdr->caplen, &ld->counts);
break;
- case DLT_NULL :
+ case WTAP_ENCAP_NULL:
capture_null(pd, phdr->caplen, &ld->counts);
break;
- case DLT_PPP :
+ case WTAP_ENCAP_PPP:
capture_ppp(pd, phdr->caplen, &ld->counts);
break;
- case DLT_RAW :
+#if 0
+#ifdef DLT_ENC
+ case DLT_ENC : /* XXX - OpenBSD "IPSEC enc type (af header, spi,
+ flags)" */
+#endif
+#ifdef DLT_LOOP
+ case DLT_LOOP : /* XXX - prepended 4-byte AF_xxxx value in OpenBSD,
+ network byte order */
+#endif
+#endif
+ /* XXX - FreeBSD may append 4-byte ATM pseudo-header
+ to DLT_ATM_RFC1483, with LLC header following */
+ case WTAP_ENCAP_RAW_IP:
capture_raw(pd, phdr->caplen, &ld->counts);
break;
}
diff --git a/ethereal.c b/ethereal.c
index 0959b7a907..ce790f7909 100644
--- a/ethereal.c
+++ b/ethereal.c
@@ -1,6 +1,6 @@
/* ethereal.c
*
- * $Id: ethereal.c,v 1.101 1999/08/20 21:57:29 guy Exp $
+ * $Id: ethereal.c,v 1.102 1999/08/22 00:47:44 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -1101,7 +1101,7 @@ main(int argc, char *argv[])
cf.save_file = NULL;
cf.save_file_fd = -1;
cf.user_saved = 0;
- cf.snap = MAX_PACKET_SIZE;
+ cf.snap = WTAP_MAX_PACKET_SIZE;
cf.count = 0;
cf.cinfo.num_cols = prefs->num_cols;
cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
@@ -1258,7 +1258,7 @@ main(int argc, char *argv[])
}
if (cf.snap < 1)
- cf.snap = MAX_PACKET_SIZE;
+ cf.snap = WTAP_MAX_PACKET_SIZE;
else if (cf.snap < MIN_PACKET_SIZE)
cf.snap = MIN_PACKET_SIZE;
diff --git a/ethereal.h b/ethereal.h
index c031792374..c51b57dfc2 100644
--- a/ethereal.h
+++ b/ethereal.h
@@ -1,7 +1,7 @@
/* ethereal.h
* Global defines, etc.
*
- * $Id: ethereal.h,v 1.21 1999/08/12 07:36:40 guy Exp $
+ * $Id: ethereal.h,v 1.22 1999/08/22 00:47:44 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -41,7 +41,6 @@
#endif
#define MIN_PACKET_SIZE 68 /* minimum amount of packet data we can read */
-#define MAX_PACKET_SIZE 65535 /* maximum amount of packet data we can read */
/* Byte swapping routines */
#define SWAP16(x) \
diff --git a/etypes.h b/etypes.h
index 3f50d600da..9422c9a5a4 100644
--- a/etypes.h
+++ b/etypes.h
@@ -1,7 +1,7 @@
/* etypes.h
* Defines ethernet packet types, similar to tcpdump's ethertype.h
*
- * $Id: etypes.h,v 1.6 1999/06/22 22:02:11 gram Exp $
+ * $Id: etypes.h,v 1.7 1999/08/22 00:47:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -26,6 +26,8 @@
#ifndef __ETYPES_H__
#define __ETYPES_H__
+#define IEEE_802_3_MAX_LEN 1500
+
#ifndef ETHERTYPE_UNK
#define ETHERTYP_UNK 0x0000
#endif
diff --git a/file.c b/file.c
index 1e2f53e328..5145e6914a 100644
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.77 1999/08/20 20:37:47 gram Exp $
+ * $Id: file.c,v 1.78 1999/08/22 00:47:43 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -257,6 +257,10 @@ read_cap_file(capture_file *cf) {
" in the middle of a packet.";
break;
+ case WTAP_ERR_BAD_RECORD:
+ errmsg = "The capture file appears to be damaged or corrupt.";
+ break;
+
default:
if (err < 0) {
sprintf(errmsg_errno, "An error occurred while reading the"
@@ -1018,10 +1022,13 @@ file_open_error_message(int err, int for_writing)
case WTAP_ERR_FILE_UNKNOWN_FORMAT:
case WTAP_ERR_UNSUPPORTED:
- case WTAP_ERR_BAD_RECORD:
errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
break;
+ case WTAP_ERR_BAD_RECORD:
+ errmsg = "The file \"%s\" appears to be damaged or corrupt.";
+ break;
+
case WTAP_ERR_CANT_OPEN:
if (for_writing)
errmsg = "The file \"%s\" could not be created for some unknown reason.";
diff --git a/file.h b/file.h
index b87ce3fd8d..c83f7fbe68 100644
--- a/file.h
+++ b/file.h
@@ -1,7 +1,7 @@
/* file.h
* Definitions for file structures and routines
*
- * $Id: file.h,v 1.38 1999/08/18 16:28:22 gram Exp $
+ * $Id: file.h,v 1.39 1999/08/22 00:47:43 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -76,13 +76,7 @@ typedef struct _capture_file {
gchar *cfilter; /* Capture filter string */
bpf_prog fcode; /* Compiled capture filter program */
#endif
- /* XXX - I'm cheating for now. I'll hardcode 65536 here until I re-arrange
- * more header files so that ethereal.h is split up into two files, a
- * generic header and a gtk+-specific header (or the gtk+ definitions are
- * moved to different header files) --gilbert
- */
- /*guint8 pd[MAX_PACKET_SIZE];*/ /* Packet data */
- guint8 pd[65536]; /* Packet data */
+ guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */
frame_data *plist; /* Packet list */
frame_data *plist_end; /* Last packet in list */
column_info cinfo; /* Column formatting information */
diff --git a/packet-eth.c b/packet-eth.c
index af8928ee31..ab53dc70b3 100644
--- a/packet-eth.c
+++ b/packet-eth.c
@@ -1,7 +1,7 @@
/* packet-eth.c
* Routines for ethernet packet disassembly
*
- * $Id: packet-eth.c,v 1.16 1999/08/20 06:55:06 guy Exp $
+ * $Id: packet-eth.c,v 1.17 1999/08/22 00:47:43 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -45,8 +45,6 @@ static int hf_eth_src = -1;
static int hf_eth_len = -1;
static int hf_eth_type = -1;
-#define IEEE_802_3_MAX_LEN 1500
-
#define ETH_HEADER_SIZE 14
/* These are the Netware-ish names for the different Ethernet frame types.
diff --git a/packet-null.c b/packet-null.c
index 4c55508117..59ccafe634 100644
--- a/packet-null.c
+++ b/packet-null.c
@@ -1,7 +1,7 @@
/* packet-null.c
* Routines for null packet disassembly
*
- * $Id: packet-null.c,v 1.11 1999/08/21 17:56:06 guy Exp $
+ * $Id: packet-null.c,v 1.12 1999/08/22 00:47:42 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -39,142 +39,275 @@
#endif
#include "packet.h"
+#include "etypes.h"
+extern const value_string etype_vals[];
+
+/* protocols and header fields */
static int proto_null = -1;
-static int hf_null_next = -1;
-static int hf_null_len = -1;
+static int hf_null_etype = -1;
static int hf_null_family = -1;
/* Null/loopback structs and definitions */
-typedef struct _e_nullhdr {
- guint8 null_next;
- guint8 null_len;
- guint16 null_family;
-} e_nullhdr;
+/* Macro to byte-swap 32-bit quantities. */
+#define BSWAP32(x) \
+ ((((x)&0xFF000000)>>24) | \
+ (((x)&0x00FF0000)>>8) | \
+ (((x)&0x0000FF00)<<8) | \
+ (((x)&0x000000FF)<<24))
+
+/* BSD AF_ values. */
+#define BSD_AF_INET 2
+#define BSD_AF_APPLETALK 16
+#define BSD_AF_IPX 23 /* at least on FreeBSD */
+#define BSD_AF_INET6 28 /* at least on FreeBSD */
+
+/* Family values. */
+static const value_string family_vals[] = {
+ {BSD_AF_INET, "IP" },
+ {BSD_AF_APPLETALK, "Appletalk" },
+ {BSD_AF_IPX, "Netware IPX/SPX"},
+ {BSD_AF_INET6, "IPv6" },
+ {0, NULL }
+};
void
-capture_null( const u_char *pd, guint32 cap_len, packet_counts *ld ) {
- e_nullhdr nh;
-
- memcpy((char *)&nh.null_family, (char *)&pd[2], sizeof(nh.null_family));
-
- /*
- From what I've read in various sources, this is supposed to be an
- address family, e.g. AF_INET. However, a FreeBSD ISDN PPP dump that
- Andreas Klemm sent to ethereal-dev has a packet type of DLT_NULL, and
- the family bits look like PPP's protocol field. A dump of the loopback
- interface on my Linux box also has a link type of DLT_NULL (as it should
- be), but the family bits look like ethernet's protocol type. To
- further confuse matters, nobody seems to be paying attention to byte
- order.
- - gcc
- */
-
- switch (nh.null_family) {
- case 0x0008:
- case 0x0800:
- case 0x0021:
- case 0x2100:
- case 0x0057:
- case 0x5700:
- case 0x86DD:
- case 0xDD86:
- capture_ip(pd, 4, cap_len, ld);
- break;
- default:
- ld->other++;
- break;
+capture_null( const u_char *pd, guint32 cap_len, packet_counts *ld )
+{
+ guint32 null_header;
+
+ /*
+ * BSD drivers that use DLT_NULL - including the FreeBSD 3.2 ISDN-for-BSD
+ * drivers, as well as the 4.4-Lite and FreeBSD loopback drivers -
+ * appear to stuff the AF_ value for the protocol, in *host* byte
+ * order, in the first four bytes.
+ *
+ * However, according to Gerald Combs, a FreeBSD ISDN PPP dump that
+ * Andreas Klemm sent to ethereal-dev has a packet type of DLT_NULL,
+ * and the family bits look like PPP's protocol field. (Was this an
+ * older, or different, ISDN driver?) Looking at what appears to be
+ * that capture file, it appears that it's using PPP in HDLC framing,
+ * RFC 1549, wherein the first two octets of the frame are 0xFF
+ * (address) and 0x03 (control), so the header bytes are, in order:
+ *
+ * 0xFF
+ * 0x03
+ * high-order byte of a PPP protocol field
+ * low-order byte of a PPP protocol field
+ *
+ * when reading it on a little-endian machine; that means it's
+ * PPPP03FF, where PPPP is a byte-swapped PPP protocol field.
+ *
+ * "libpcap" for Linux uses DLT_NULL only for the loopback device.
+ * The loopback driver in Linux 2.0.36, at least, puts an *Ethernet*
+ * header at the beginning of loopback packets; however, "libpcap"
+ * for Linux compensates for this by skipping the source and
+ * destination MAC addresses, replacing them with 2 bytes of 0.
+ * This means that if we're reading the capture on a little-endian
+ * machine, the header, treated as a 32-bit integer, looks like
+ *
+ * EEEEEEEEEEEEEEEE0000000000000000
+ *
+ * where "EEEEEEEEEEEEEEEE" is the Ethernet type, and if we're reading
+ * it on a big-endian machine, it looks like
+ *
+ * 0000000000000000EEEEEEEEEEEEEEEE
+ *
+ * The Ethernet type might or might not be byte-swapped; I haven't
+ * bothered thinking about that yet.
+ *
+ * AF_ values are (relatively) small integers, and shouldn't have their
+ * upper 16 bits zero; Ethernet types have to fit in 16 bits and
+ * thus must have their upper 16 bits zero. Therefore, if the upper
+ * 16 bits of the field aren't zero, it's in the wrong byte order.
+ *
+ * Ethernet types are bigger than 1536, and AF_ values are smaller
+ * than 1536, so we needn't worry about one being mistaken for
+ * the other. (There may be a problem if the 16-bit Ethernet
+ * type is byte-swapped as a 16-bit quantity, but if when treated
+ * as a 32-bit quantity its upper 16 bits are zero, but I'll think
+ * about that one later.)
+ *
+ * As for the PPP protocol field values:
+ *
+ * 0x0000 does not appear to be a valid PPP protocol field value,
+ * so the upper 16 bits will be non-zero, and we'll byte swap it.
+ * It'll then be
+ *
+ * 0xFF03PPPP
+ *
+ * where PPPP is a non-byte-swapped PPP protocol field; we'll
+ * check for the upper 16 bits of the byte-swapped field being
+ * non-zero and, if so, assume the lower 16 bits are a PPP
+ * protocol field (AF_ and Ethernet protocol fields should leave
+ * the upper 16 bits zero - unless somebody stuff something else
+ * there; see below).
+ *
+ * So, to compensate for this mess, we:
+ *
+ * check if the first two octets are 0xFF and 0x03 and, if so,
+ * treat it as a PPP frame;
+ *
+ * otherwise, byte-swap the value if its upper 16 bits aren't zero,
+ * and compare the lower 16 bits of the value against Ethernet
+ * and AF_ types.
+ *
+ * If, as implied by an earlier version of the "e_nullhdr" structure,
+ * the family is only 16 bits, and there are "next" and "len" fields
+ * before it, that all goes completely to hell. (Note that, for
+ * the BSD header, we could byte-swap it if the capture was written
+ * on a machine with the opposite byte-order to ours - the "libpcap"
+ * header lets us determine that - but it's more of a mess for Linux,
+ * given that the effect of inserting the two 0 bytes depends only
+ * on the byte order of the machine reading the file.)
+ */
+ if (pd[0] == 0xFF && pd[1] == 0x03) {
+ /*
+ * Hand it to PPP.
+ */
+ capture_ppp(pd, cap_len, ld);
+ } else {
+ /*
+ * Treat it as a normal DLT_NULL header.
+ */
+ memcpy((char *)&null_header, (char *)&pd[0], sizeof(null_header));
+
+ if ((null_header & 0xFFFF0000) != 0) {
+ /* Byte-swap it. */
+ null_header = BSWAP32(null_header);
+ }
+
+ /*
+ * The null header value must be greater than the IEEE 802.3 maximum
+ * frame length to be a valid Ethernet type; if it is, hand it
+ * to "ethertype()", otherwise treat it as a BSD AF_type (we wire
+ * in the values of the BSD AF_ types, because the values
+ * in the file will be BSD values, and the OS on which
+ * we're building this might not have the same values or
+ * might not have them defined at all; XXX - what if different
+ * BSD derivatives have different values?).
+ */
+ if (null_header > IEEE_802_3_MAX_LEN)
+ capture_ethertype(null_header, 4, pd, cap_len, ld);
+ else {
+ switch (null_header) {
+
+ case BSD_AF_INET:
+ capture_ip(pd, 4, cap_len, ld);
+ break;
+
+ default:
+ ld->other++;
+ break;
+ }
+ }
}
}
void
-dissect_null( const u_char *pd, frame_data *fd, proto_tree *tree ) {
- e_nullhdr nh;
+dissect_null( const u_char *pd, frame_data *fd, proto_tree *tree )
+{
+ guint32 null_header;
proto_tree *fh_tree;
proto_item *ti;
- nh.null_next = pd[0];
- nh.null_len = pd[1];
- memcpy((char *)&nh.null_family, (char *)&pd[2], sizeof(nh.null_family));
-
- /* load the top pane info. This should be overwritten by
- the next protocol in the stack */
- if(check_col(fd, COL_RES_DL_SRC))
- col_add_str(fd, COL_RES_DL_SRC, "N/A" );
- if(check_col(fd, COL_RES_DL_DST))
- col_add_str(fd, COL_RES_DL_DST, "N/A" );
- if(check_col(fd, COL_PROTOCOL))
- col_add_str(fd, COL_PROTOCOL, "N/A" );
- if(check_col(fd, COL_INFO))
- col_add_str(fd, COL_INFO, "Null/Loopback" );
-
- /* populate a tree in the second pane with the status of the link
- layer (ie none) */
- if(tree) {
- ti = proto_tree_add_item(tree, proto_null, 0, 4, NULL);
- fh_tree = proto_item_add_subtree(ti, ETT_NULL);
- proto_tree_add_item(fh_tree, hf_null_next, 0, 1, nh.null_next);
- proto_tree_add_item(fh_tree, hf_null_len, 1, 1, nh.null_len);
- proto_tree_add_item(fh_tree, hf_null_family, 2, 2, nh.null_family);
- }
+ /*
+ * See comment in "capture_null()" for an explanation of what we're
+ * doing.
+ */
+ if (pd[0] == 0xFF && pd[1] == 0x03) {
+ /*
+ * Hand it to PPP.
+ */
+ dissect_ppp(pd, fd, tree);
+ } else {
+ /*
+ * Treat it as a normal DLT_NULL header.
+ */
+ memcpy((char *)&null_header, (char *)&pd[0], sizeof(null_header));
- /*
- From what I've read in various sources, this is supposed to be an
- address family, e.g. AF_INET. However, a FreeBSD ISDN PPP dump that
- Andreas Klemm sent to ethereal-dev has a packet type of DLT_NULL, and
- the family bits look like PPP's protocol field. A dump of the loopback
- interface on my Linux box also has a link type of DLT_NULL (as it should
- be), but the family bits look like ethernet's protocol type. To
- further confuse matters, nobody seems to be paying attention to byte
- order.
- - gcc
- */
-
- switch (nh.null_family) {
- case 0x0008:
- case 0x0800:
- case 0x0021:
- case 0x2100:
- dissect_ip(pd, 4, fd, tree);
- break;
- case 0x86DD:
- case 0xDD86:
- case 0x0057:
- case 0x5700:
- dissect_ipv6(pd, 4, fd, tree);
- break;
- default:
- dissect_data(pd, 4, fd, tree);
- break;
+ if ((null_header & 0xFFFF0000) != 0) {
+ /* Byte-swap it. */
+ null_header = BSWAP32(null_header);
+ }
+
+ /* load the top pane info. This should be overwritten by
+ the next protocol in the stack */
+ if(check_col(fd, COL_RES_DL_SRC))
+ col_add_str(fd, COL_RES_DL_SRC, "N/A" );
+ if(check_col(fd, COL_RES_DL_DST))
+ col_add_str(fd, COL_RES_DL_DST, "N/A" );
+ if(check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "N/A" );
+ if(check_col(fd, COL_INFO))
+ col_add_str(fd, COL_INFO, "Null/Loopback" );
+
+ /*
+ * The null header value must be greater than the IEEE 802.3 maximum
+ * frame length to be a valid Ethernet type; if it is, hand it
+ * to "ethertype()", otherwise treat it as a BSD AF_type (we wire
+ * in the values of the BSD AF_ types, because the values
+ * in the file will be BSD values, and the OS on which
+ * we're building this might not have the same values or
+ * might not have them defined at all; XXX - what if different
+ * BSD derivatives have different values?).
+ */
+ if (null_header > IEEE_802_3_MAX_LEN) {
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_null, 0, 4, NULL);
+ fh_tree = proto_item_add_subtree(ti, ETT_NULL);
+ } else
+ fh_tree = NULL;
+ ethertype(null_header, 4, pd, fd, tree, fh_tree, hf_null_etype);
+ } else {
+ /* populate a tree in the second pane with the status of the link
+ layer (ie none) */
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_null, 0, 4, NULL);
+ fh_tree = proto_item_add_subtree(ti, ETT_NULL);
+ proto_tree_add_item(fh_tree, hf_null_family, 0, 4, null_header);
+ }
+
+ switch (null_header) {
+
+ case BSD_AF_INET:
+ dissect_ip(pd, 4, fd, tree);
+ break;
+
+ case BSD_AF_APPLETALK:
+ dissect_ddp(pd, 4, fd, tree);
+ break;
+
+ case BSD_AF_IPX:
+ dissect_ipx(pd, 4, fd, tree);
+ break;
+
+ case BSD_AF_INET6:
+ dissect_ipv6(pd, 4, fd, tree);
+ break;
+
+ default:
+ dissect_data(pd, 4, fd, tree);
+ break;
+ }
+ }
}
}
void
proto_register_null(void)
{
- proto_null = proto_register_protocol (
- /* name */ "Null/Loopback",
- /* abbrev */ "null" );
-
- hf_null_next = proto_register_field (
- /* name */ "Next",
- /* abbrev */ "null.next",
- /* ftype */ FT_UINT8,
- /* parent */ proto_null,
- /* vals[] */ NULL );
-
- hf_null_len = proto_register_field (
- /* name */ "Length",
- /* abbrev */ "null.len",
- /* ftype */ FT_UINT8,
- /* parent */ proto_null,
- /* vals[] */ NULL );
-
- hf_null_family = proto_register_field (
- /* name */ "Family",
- /* abbrev */ "null.family",
- /* ftype */ FT_UINT16,
- /* parent */ proto_null,
- /* vals[] */ NULL );
+ static hf_register_info hf[] = {
+
+ /* registered here but handled in ethertype.c */
+ { &hf_null_etype,
+ { "Type", "null.type", FT_VALS_UINT16, VALS(etype_vals) }},
+
+ { &hf_null_family,
+ { "Family", "null.family", FT_VALS_UINT32, VALS(family_vals) }}
+ };
+
+ proto_null = proto_register_protocol ("Null/Loopback", "null" );
+ proto_register_field_array(proto_null, hf, array_length(hf));
}
diff --git a/packet.c b/packet.c
index de5d9a81d1..0fbb99714d 100644
--- a/packet.c
+++ b/packet.c
@@ -1,7 +1,7 @@
/* packet.c
* Routines for packet disassembly
*
- * $Id: packet.c,v 1.38 1999/08/20 06:55:05 guy Exp $
+ * $Id: packet.c,v 1.39 1999/08/22 00:47:45 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -663,7 +663,7 @@ dissect_packet(const u_char *pd, frame_data *fd, proto_tree *tree)
case WTAP_ENCAP_TR :
dissect_tr(pd, 0, fd, tree);
break;
- case WTAP_ENCAP_NONE :
+ case WTAP_ENCAP_NULL :
dissect_null(pd, fd, tree);
break;
case WTAP_ENCAP_PPP :
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c
index d2445db79e..73e0f1acb7 100644
--- a/wiretap/libpcap.c
+++ b/wiretap/libpcap.c
@@ -1,6 +1,6 @@
/* libpcap.c
*
- * $Id: libpcap.c,v 1.10 1999/08/19 05:31:37 guy Exp $
+ * $Id: libpcap.c,v 1.11 1999/08/22 00:47:56 guy Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -75,26 +75,45 @@ static int libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
const u_char *pd, int *err);
static int libpcap_dump_close(wtap_dumper *wdh, int *err);
+/*
+ * XXX - this is a bit of a mess. OpenBSD, and perhaps NetBSD, have
+ * different DLT_ codes from FreeBSD (and from the LBL BPF code).
+ * For now, we simply treat all except DLT_RAW as "unknown"; this
+ * means you won't be able to capture from a network using those
+ * types in Ethereal (and that capturing from the loopback interface
+ * won't necessarily work right on OpenBSD, either).
+ *
+ * Does anybody know what BSD/OS uses as DLT_ types for SLIP and
+ * PPP? The LBL code, and the OpenBSD code, appear to disagree....
+ *
+ * Nothing in FreeBSD appears to use DLT_RAW, so it's not clear what
+ * link-layer header or fake header appears. If it's completely
+ * unused, or if it behaves the same way OpenBSD DLT_LOOP behaves,
+ * i.e. it puts an address family in *network* byte order (as opposed
+ * to the *host* byte order that DLT_NULL uses on FreeBSD), then
+ * we should just make it WTAP_ENCAP_LOOP and process that as an
+ * OpenBSD DLT_LOOP.
+ */
static const int pcap_encap[] = {
- WTAP_ENCAP_NONE, /* no encapsulation */
+ WTAP_ENCAP_NULL, /* null encapsulation */
WTAP_ENCAP_ETHERNET,
- WTAP_ENCAP_NONE, /* 3Mb experimental Ethernet */
- WTAP_ENCAP_NONE, /* Amateur Radio AX.25 */
- WTAP_ENCAP_NONE, /* Proteon ProNET Token Ring */
- WTAP_ENCAP_NONE, /* Chaos */
+ WTAP_ENCAP_UNKNOWN, /* 3Mb experimental Ethernet */
+ WTAP_ENCAP_UNKNOWN, /* Amateur Radio AX.25 */
+ WTAP_ENCAP_UNKNOWN, /* Proteon ProNET Token Ring */
+ WTAP_ENCAP_UNKNOWN, /* Chaos */
WTAP_ENCAP_TR, /* IEEE 802 Networks - assume token ring */
WTAP_ENCAP_ARCNET,
WTAP_ENCAP_SLIP,
WTAP_ENCAP_PPP,
WTAP_ENCAP_FDDI,
WTAP_ENCAP_ATM_RFC1483,
- WTAP_ENCAP_RAW_IP,
- WTAP_ENCAP_NONE,
- WTAP_ENCAP_NONE,
- WTAP_ENCAP_NONE,
- WTAP_ENCAP_NONE,
- WTAP_ENCAP_NONE,
- WTAP_ENCAP_NONE,
+ WTAP_ENCAP_RAW_IP, /* or, on OpenBSD, DLT_LOOP */
+ WTAP_ENCAP_UNKNOWN, /* BSD/OS SLIP *and* OpenBSD DLT_ENC */
+ WTAP_ENCAP_UNKNOWN, /* BSD/OS PPP *and* OpenBSD DLT_RAW */
+ WTAP_ENCAP_UNKNOWN, /* OpenBSD BSD/OS SLIP */
+ WTAP_ENCAP_UNKNOWN, /* OpenBSD BSD/OS PPP */
+ WTAP_ENCAP_UNKNOWN,
+ WTAP_ENCAP_UNKNOWN,
WTAP_ENCAP_LINUX_ATM_CLIP
};
#define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0])
@@ -152,8 +171,9 @@ int libpcap_open(wtap *wth, int *err)
*err = WTAP_ERR_UNSUPPORTED;
return -1;
}
- if (hdr.network >= NUM_PCAP_ENCAPS) {
- g_message("pcap: network type %d unknown", hdr.network);
+ if (hdr.network >= NUM_PCAP_ENCAPS
+ || pcap_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
+ g_message("pcap: network type %d unknown or unsupported", hdr.network);
*err = WTAP_ERR_UNSUPPORTED;
return -1;
}
@@ -173,7 +193,7 @@ int libpcap_open(wtap *wth, int *err)
/* Read the next packet */
static int libpcap_read(wtap *wth, int *err)
{
- int packet_size;
+ guint packet_size;
int bytes_read;
struct pcaprec_hdr hdr;
int data_offset;
@@ -221,6 +241,17 @@ static int libpcap_read(wtap *wth, int *err)
}
packet_size = hdr.incl_len;
+ if (packet_size > WTAP_MAX_PACKET_SIZE) {
+ /*
+ * Probably a corrupt capture file; don't blow up trying
+ * to allocate space for an immensely-large packet.
+ */
+ g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
+ packet_size, WTAP_MAX_PACKET_SIZE);
+ *err = WTAP_ERR_BAD_RECORD;
+ return -1;
+ }
+
buffer_assure_space(wth->frame_buffer, packet_size);
data_offset = ftell(wth->fh);
errno = WTAP_ERR_CANT_READ;
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index c7bcf5c10c..78ee772f39 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1,6 +1,6 @@
/* wtap.h
*
- * $Id: wtap.h,v 1.29 1999/08/20 06:55:19 guy Exp $
+ * $Id: wtap.h,v 1.30 1999/08/22 00:47:55 guy Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
@@ -39,6 +39,12 @@
* type for all packets in the file; this may cause those routines to
* fail if the capture file format being written can't support that.
*
+ * WTAP_ENCAP_NULL is the DLT_NULL some BSD systems use; at least with
+ * many drivers on FreeBSD (and the loopback driver in 4.4-Lite, so
+ * hopefully most BSD drivers, at least, model their DLT_NULL after it),
+ * it puts a 4-byte field containing the AF_ address family value,
+ * in *host* byte order, at the beginning of the packet.
+ *
* WTAP_ENCAP_UNKNOWN is returned by "wtap_pcap_encap_to_wtap_encap()"
* if it's handed an unknown encapsulation. */
#define WTAP_ENCAP_UNKNOWN -2
@@ -55,9 +61,10 @@
#define WTAP_ENCAP_LINUX_ATM_CLIP 9
#define WTAP_ENCAP_LAPB 10
#define WTAP_ENCAP_ATM_SNIFFER 11
+#define WTAP_ENCAP_NULL 12
/* last WTAP_ENCAP_ value + 1 */
-#define WTAP_NUM_ENCAP_TYPES 11
+#define WTAP_NUM_ENCAP_TYPES 12
/* File types that can be read by wiretap.
We may eventually support writing some or all of these file types,
@@ -76,6 +83,11 @@
#define WTAP_FILE_NETXRAY_2_001 12
#define WTAP_FILE_RADCOM 13
+/*
+ * Maximum packet size we'll support.
+ */
+#define WTAP_MAX_PACKET_SIZE 65535
+
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
@@ -208,6 +220,16 @@ struct wtap_pkthdr {
union pseudo_header pseudo_header;
};
+/*
+ * Header that OpenBSD (and possibly other BSDs) DLT_ENC prepends to
+ * a packet.
+ */
+struct dlt_enc_hdr {
+ guint32 af;
+ guint32 spi;
+ guint32 flags;
+};
+
typedef void (*wtap_handler)(u_char*, const struct wtap_pkthdr*,
int, const u_char *);