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