DLT_NULL, from "libpcap", means different things on different platforms

and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:

	1) PPP-over-HDLC (some version of ISDN4BSD?);

	2) big-endian AF_ value (BSD on big-endian platforms);

	3) little-endian AF_ value (BSD on little-endian platforms);

	4) two octets of 0 followed by an Ethernet type (Linux, at least
	   on little-endian platforms, as mutated by "libpcap").

Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.

Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.

Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.

Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.

Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces.  Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).

Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.

svn path=/trunk/; revision=540
This commit is contained in:
Guy Harris 1999-08-22 00:47:56 +00:00
parent 5c57f09423
commit ee39938f67
11 changed files with 446 additions and 177 deletions

139
capture.c
View File

@ -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 (! (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 (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 (!(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;
}

View File

@ -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;

View File

@ -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) \

View File

@ -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

11
file.c
View File

@ -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.";

10
file.h
View File

@ -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 */

View File

@ -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.

View File

@ -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;
capture_null( const u_char *pd, guint32 cap_len, packet_counts *ld )
{
guint32 null_header;
memcpy((char *)&nh.null_family, (char *)&pd[2], sizeof(nh.null_family));
/*
* 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));
/*
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;
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));
/*
* 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));
/* 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" );
if ((null_header & 0xFFFF0000) != 0) {
/* Byte-swap it. */
null_header = BSWAP32(null_header);
}
/* 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);
}
/* 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" );
/*
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;
/*
* 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" );
static hf_register_info hf[] = {
hf_null_next = proto_register_field (
/* name */ "Next",
/* abbrev */ "null.next",
/* ftype */ FT_UINT8,
/* parent */ proto_null,
/* vals[] */ NULL );
/* registered here but handled in ethertype.c */
{ &hf_null_etype,
{ "Type", "null.type", FT_VALS_UINT16, VALS(etype_vals) }},
hf_null_len = proto_register_field (
/* name */ "Length",
/* abbrev */ "null.len",
/* ftype */ FT_UINT8,
/* parent */ proto_null,
/* vals[] */ NULL );
{ &hf_null_family,
{ "Family", "null.family", FT_VALS_UINT32, VALS(family_vals) }}
};
hf_null_family = proto_register_field (
/* name */ "Family",
/* abbrev */ "null.family",
/* ftype */ FT_UINT16,
/* parent */ proto_null,
/* vals[] */ NULL );
proto_null = proto_register_protocol ("Null/Loopback", "null" );
proto_register_field_array(proto_null, hf, array_length(hf));
}

View File

@ -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 :

View File

@ -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;

View File

@ -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 *);