diff options
author | gram <gram@f5534014-38df-0310-8fa8-9805f1628bb7> | 1998-12-17 06:39:13 +0000 |
---|---|---|
committer | gram <gram@f5534014-38df-0310-8fa8-9805f1628bb7> | 1998-12-17 06:39:13 +0000 |
commit | 1ddb4c7c35fb90dd2fe6c7381da61b58feae4318 (patch) | |
tree | 587f449e06f87b718322a12b551dc858e442f780 /wiretap | |
parent | ac9fe64a3b04ee9333446ed2de17754ae9638065 (diff) |
Added Guy Harris' patch to read Sniffer ATM trace files. Very nice.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@128 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/libpcap.c | 4 | ||||
-rw-r--r-- | wiretap/ngsniffer.c | 685 | ||||
-rw-r--r-- | wiretap/ngsniffer.h | 6 | ||||
-rw-r--r-- | wiretap/wtap.h | 12 |
4 files changed, 581 insertions, 126 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index fc901c6b19..4285319f02 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -1,6 +1,6 @@ /* libpcap.c * - * $Id: libpcap.c,v 1.1 1998/11/15 05:29:11 guy Exp $ + * $Id: libpcap.c,v 1.2 1998/12/17 06:39:10 gram Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -82,7 +82,7 @@ int libpcap_open(wtap *wth) WTAP_ENCAP_SLIP, WTAP_ENCAP_PPP, WTAP_ENCAP_FDDI, - WTAP_ENCAP_NONE, /* LLC/SNAP-encapsulated ATM (RFC 1483) */ + WTAP_ENCAP_ATM_RFC1483, WTAP_ENCAP_RAW_IP }; #define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0]) diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c index 8a84c47359..082f2fedf4 100644 --- a/wiretap/ngsniffer.c +++ b/wiretap/ngsniffer.c @@ -1,6 +1,6 @@ /* ngsniffer.c * - * $Id: ngsniffer.c,v 1.9 1998/12/15 04:11:58 guy Exp $ + * $Id: ngsniffer.c,v 1.10 1998/12/17 06:39:12 gram Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -61,10 +61,185 @@ #include "wtap.h" #include "ngsniffer.h" +/* + * Sniffer record types. + */ +#define REC_VERS 1 /* Version record (f_vers) */ +#define REC_FRAME2 4 /* Frame data (f_frame2) */ +#define REC_FRAME4 8 /* Frame data (f_frame4) */ +#define REC_EOF 3 /* End-of-file record (no data follows) */ + +/* + * Sniffer version record format. + * + * XXX - the Sniffer documentation doesn't say what the compression stuff + * means. The manual says "IMPORTANT: You must save the file uncompressed + * to use this format specification." + */ +struct vers_rec { + gint16 maj_vers; /* major version number */ + gint16 min_vers; /* minor version number */ + gint16 time; /* DOS-format time */ + gint16 date; /* DOS-format date */ + gint8 type; /* what type of records follow */ + gint8 network; /* network type */ + gint8 format; /* format version (we only support version 1!) */ + guint8 timeunit; /* timestamp units */ + gint8 cmprs_vers; /* compression version */ + gint8 cmprs_level; /* compression level */ + gint16 rsvd[2]; /* reserved */ +}; + +/* + * Sniffer type 2 data record format - followed by frame data. + */ +struct frame2_rec { + guint16 time_low; /* low part of time stamp */ + guint16 time_med; /* middle part of time stamp */ + guint16 time_high; /* high part of time stamp */ + gint16 size; /* number of bytes of data */ + guint8 fs; /* frame error status bits */ + guint8 flags; /* buffer flags */ + gint16 true_size; /* size of original frame, in bytes */ + gint16 rsvd; /* reserved */ +}; + +/* + * Sniffer type 4 data record format - followed by frame data. + * + * XXX - the manual says that the "flags" field holds "buffer flags; + * BF_xxxx", but doesn't say what the BF_xxxx flags are. + * + * XXX - the manual also says there's an 8-byte "ATMTimeStamp" driver + * time stamp at the end of "ATMSaveInfo", but, from an ATM Sniffer capture + * file I've looked at, that appears not to be the case. + */ + +/* + * Fields from the AAL5 trailer for the frame, if it's an AAL5 frame + * rather than a cell. + */ +typedef struct _ATM_AAL5Trailer { + guint16 aal5t_u2u; /* user-to-user indicator */ + guint16 aal5t_len; /* length of the packet */ + guint32 aal5t_chksum; /* checksum for AAL5 packet */ +} ATM_AAL5Trailer; + +typedef struct _ATMTimeStamp { + guint32 msw; /* most significant word */ + guint32 lsw; /* least significant word */ +} ATMTimeStamp; + +typedef struct _ATMSaveInfo { + guint32 StatusWord; /* status word from driver */ + ATM_AAL5Trailer Trailer; /* AAL5 trailer */ + guint8 AppTrafType; /* traffic type */ + guint8 AppHLType; /* protocol type */ + guint16 AppReserved; /* reserved */ + guint16 Vpi; /* virtual path identifier */ + guint16 Vci; /* virtual circuit identifier */ + guint16 channel; /* link: 0 for DCE, 1 for DTE */ + guint16 cells; /* number of cells */ + guint32 AppVal1; /* type-dependent */ + guint32 AppVal2; /* type-dependent */ +} ATMSaveInfo; + +/* + * Bits in StatusWord. + */ +#define SW_ERRMASK 0x0F /* Error mask: */ +#define SW_RX_FIFO_UNDERRUN 0x01 /* Receive FIFO underrun */ +#define SW_RX_FIFO_OVERRUN 0x02 /* Receive FIFO overrun */ +#define SW_RX_PKT_TOO_LONG 0x03 /* Received packet > max size */ +#define SW_CRC_ERROR 0x04 /* CRC error */ +#define SW_USER_ABORTED_RX 0x05 /* User aborted receive */ +#define SW_BUF_LEN_TOO_LONG 0x06 /* buffer len > max buf */ +#define SW_INTERNAL_T1_ERROR 0x07 /* Internal T1 error */ +#define SW_RX_CHANNEL_DEACTIV8 0x08 /* Rx channel deactivate */ + +#define SW_ERROR 0x80 /* Error indicator */ +#define SW_CONGESTION 0x40 /* Congestion indicator */ +#define SW_CLP 0x20 /* Cell loss priority indicator */ +#define SW_RAW_CELL 0x100 /* RAW cell indicator */ +#define SW_OAM_CELL 0x200 /* OAM cell indicator */ + +/* + * Bits in AppTrafType. + * + * For AAL types other than AAL5, the packet data is presumably for a + * single cell, not a reassembled frame, as the ATM Sniffer manual says + * it dosn't reassemble cells other than AAL5 cells. + */ +#define ATT_AALTYPE 0x0F /* AAL type: */ +#define ATT_AAL_UNKNOWN 0x00 /* Unknown AAL */ +#define ATT_AAL1 0x01 /* AAL1 */ +#define ATT_AAL3_4 0x02 /* AAL3/4 */ +#define ATT_AAL5 0x03 /* AAL5 */ +#define ATT_AAL_USER 0x04 /* User AAL */ +#define ATT_AAL_SIGNALLING 0x05 /* Signaling AAL */ +#define ATT_OAMCELL 0x06 /* OAM cell */ + +#define ATT_HLTYPE 0xF0 /* Higher-layer type: */ +#define ATT_HL_UNKNOWN 0x00 /* unknown */ +#define ATT_HL_LLCMX 0x10 /* LLC multiplexed (probably RFC 1483) */ +#define ATT_HL_VCMX 0x20 /* VC multiplexed (probably RFC 1483) */ +#define ATT_HL_LANE 0x30 /* LAN Emulation */ +#define ATT_HL_ILMI 0x40 /* ILMI */ +#define ATT_HL_FRMR 0x50 /* Frame Relay */ +#define ATT_HL_SPANS 0x60 /* FORE SPANS */ +#define ATT_HL_IPSILON 0x70 /* Ipsilon */ + +/* + * Values for AppHLType; the interpretation depends on the ATT_HLTYPE + * bits in AppTrafType. + */ +#define AHLT_UNKNOWN 0x0 +#define AHLT_VCMX_802_3_FCS 0x1 /* VCMX: 802.3 FCS */ +#define AHLT_LANE_LE_CTRL 0x1 /* LANE: LE Ctrl */ +#define AHLT_IPSILON_FT0 0x1 /* Ipsilon: Flow Type 0 */ +#define AHLT_VCMX_802_4_FCS 0x2 /* VCMX: 802.4 FCS */ +#define AHLT_LANE_802_3 0x2 /* LANE: 802.3 */ +#define AHLT_IPSILON_FT1 0x2 /* Ipsilon: Flow Type 1 */ +#define AHLT_VCMX_802_5_FCS 0x3 /* VCMX: 802.5 FCS */ +#define AHLT_LANE_802_5 0x3 /* LANE: 802.5 */ +#define AHLT_IPSILON_FT2 0x3 /* Ipsilon: Flow Type 2 */ +#define AHLT_VCMX_FDDI_FCS 0x4 /* VCMX: FDDI FCS */ +#define AHLT_LANE_802_3_MC 0x4 /* LANE: 802.3 multicast */ +#define AHLT_VCMX_802_6_FCS 0x5 /* VCMX: 802.6 FCS */ +#define AHLT_LANE_802_5_MC 0x5 /* LANE: 802.5 multicast */ +#define AHLT_VCMX_802_3 0x7 /* VCMX: 802.3 */ +#define AHLT_VCMX_802_4 0x8 /* VCMX: 802.4 */ +#define AHLT_VCMX_802_5 0x9 /* VCMX: 802.5 */ +#define AHLT_VCMX_FDDI 0xa /* VCMX: FDDI */ +#define AHLT_VCMX_802_6 0xb /* VCMX: 802.6 */ +#define AHLT_VCMX_FRAGMENTS 0xc /* VCMX: Fragments */ +#define AHLT_VCMX_BPDU 0xe /* VCMX: BPDU */ + +struct frame4_rec { + guint16 time_low; /* low part of time stamp */ + guint16 time_med; /* middle part of time stamp */ + gint8 time_high; /* high part of time stamp */ + gint8 time_day; /* time in days since start of capture */ + gint16 size; /* number of bytes of data */ + gint8 fs; /* frame error status bits */ + gint8 flags; /* buffer flags */ + gint16 true_size; /* size of original frame, in bytes */ + gint16 rsvd3; /* reserved */ + gint16 atm_pad; /* pad to 4-byte boundary */ + ATMSaveInfo atm_info; /* ATM-specific stuff */ +}; + +/* + * Size of ATM LANE header - we have to strip it off as our caller expects + * a MAC header at the beginning of the frame data. + */ +#define ATM_LANE_HEADER_LEN 2 + /* values for V.timeunit */ #define NUM_NGSNIFF_TIMEUNITS 7 static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 0.0, 0.1 }; +#define NGSNIFF_ENCAP_ATM 10 #define NUM_NGSNIFF_ENCAPS 11 static int sniffer_encap[] = { WTAP_ENCAP_TR, @@ -80,6 +255,9 @@ static int sniffer_encap[] = { WTAP_ENCAP_NONE /* ATM */ }; +static int get_atm_linktype(wtap *wth); +static int linktype_for_packet(u_int app_traf_type, u_int app_hl_type); + /* Returns WTAP_FILE_NGSNIFFER on success, WTAP_FILE_UNKNOWN on failure */ int ngsniffer_open(wtap *wth) { @@ -89,10 +267,7 @@ int ngsniffer_open(wtap *wth) char record_length[4]; /* only the first 2 bytes are length, the last 2 are "reserved" and are thrown away */ guint16 type, length = 0; - guint8 format; - guint8 network; - gchar version[18]; /* to hold the entire version record */ - guint8 timeunit; + struct vers_rec version; guint16 start_date; guint16 start_time; struct tm tm; @@ -118,99 +293,280 @@ int ngsniffer_open(wtap *wth) /*wth->frame_number = 0;*/ /*wth->file_byte_offset = 0x10b;*/ - /* Read records until we find the start of packets */ - while (1) { - fseek(wth->fh, length, SEEK_CUR); + /* + * Read the first record, which the manual says is a version + * record. + */ + bytes_read = fread(record_type, 1, 2, wth->fh); + bytes_read += fread(record_length, 1, 4, wth->fh); + if (bytes_read != 6) { + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + + type = pletohs(record_type); + length = pletohs(record_length); + + if (type != REC_VERS) { + g_message("ngsniffer: Sniffer file doesn't start with a version record"); + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + + fread(&version, 1, sizeof version, wth->fh); + + /* Make sure this is an uncompressed Sniffer file */ + if (version.format != 1) { + g_message("ngsniffer: This Sniffer file type is not supported"); + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + + /* Get data link type */ + if (version.network >= NUM_NGSNIFF_ENCAPS) { + g_message("ngsniffer: network type %d unknown", version.network); + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + else { + wth->encapsulation = sniffer_encap[version.network]; + } + + /* Get time unit */ + if (version.timeunit >= NUM_NGSNIFF_TIMEUNITS) { + g_message("ngsniffer: Unknown timeunit %d", version.timeunit); + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + else { + wth->capture.ngsniffer->timeunit = Usec[version.timeunit]; + } + + /* Get capture start time */ + start_time = pletohs(&version.time); + start_date = pletohs(&version.date); + tm.tm_year = ((start_date&0xfe00)>>9) + 1980 - 1900; + tm.tm_mon = ((start_date&0x1e0)>>5) - 1; + tm.tm_mday = (start_date&0x1f); + /* The time does not appear to act as an offset; only the date + tm.tm_hour = (start_time&0xf800)>>11; + tm.tm_min = (start_time&0x7e0)>>5; + tm.tm_sec = (start_time&0x1f)<<1;*/ + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + wth->capture.ngsniffer->start = mktime(&tm); + /* + * XXX - what if "secs" is -1? Unlikely, + * but if the capture was done in a time + * zone that switches between standard and + * summer time sometime other than when we + * do, and thus the time was one that doesn't + * exist here because a switch from standard + * to summer time zips over it, it could + * happen. + * + * On the other hand, if the capture was done + * in a different time zone, this won't work + * right anyway; unfortunately, the time zone + * isn't stored in the capture file. + */ + + /* + * Unless this is an ATM capture file, we won't have to read + * any data records to figure out the network type; zero out + * "pkt_len" to indicate that we've not read the first packet's + * header. + */ + wth->capture.ngsniffer->pkt_len = 0; + wth->capture.ngsniffer->is_atm = 0; + + if (version.network == NGSNIFF_ENCAP_ATM) { + /* + * Gak. There's no link-layer header; however, the + * frame is probably the data that AAL5 handed up, + * which contains RFC 1483 stuff or LANE stuff or SPANS + * stuff or whatever, or, if the "frame" is just an + * ATM cell, it's probably just the cell. + * + * I.e., there *is* no appropriate "link type". + * + * So what we do is scan forward, looking for the first + * LANE or RFC 1483 LLC-multiplexed frame, use that to + * determine the link type, and arrange to discard all + * frames other than those of that type. That denies + * "libpcap" applications access to anything other + * than that, but I *suspect* you don't get a mix of + * RFC 1483 LLC-multiplexed and LANE traffic, and + * the applications probably would have no idea how + * to cope with raw cells or other types of frames + * anyway; the only place you lose is with FORE + * SPANS. + */ + wth->encapsulation = get_atm_linktype(wth); + if (wth->encapsulation == -1) { + /* + * Oops, we couldn't find a link type we can + * handle. + */ + g_message("ngsniffer: no LANE or RFC 1483 LLC-multiplexed frames found"); + free(wth->capture.ngsniffer); + return WTAP_FILE_UNKNOWN; + } + wth->capture.ngsniffer->is_atm = 1; + } + return WTAP_FILE_NGSNIFFER; +} + +static int get_atm_linktype(wtap *wth) +{ + int bytes_read; + char record_type[2]; + char record_length[4]; /* only 1st 2 bytes are length */ + guint16 type, length; + struct frame4_rec frame4; + int linktype; + guint16 time_low, time_med, time_high, true_size, size; + + for (;;) { + /* + * Read the record header. + */ bytes_read = fread(record_type, 1, 2, wth->fh); bytes_read += fread(record_length, 1, 4, wth->fh); if (bytes_read != 6) { - free(wth->capture.ngsniffer); - return WTAP_FILE_UNKNOWN; + /* + * End of file or error. Probably means there *are* + * no LANE or RFC 1483 LLC-multiplexed frames, + * which means we can't handle this in + * "wiretap". Return an error. + */ + return -1; } type = pletohs(record_type); length = pletohs(record_length); + if (type == REC_EOF) { + /* + * End of file. Probably means there *are* + * no LANE or RFC 1483 LLC-multiplexed frames, + * which means we can't handle this in + * "wiretap". Return an error. + */ + return -1; + } + switch (type) { - /* Version Record */ - case REC_VERS: - fread(version, 1, 18, wth->fh); - length = 0; /* to fake the next iteration of while() */ - - /* Make sure this is an uncompressed Sniffer file */ - format = version[10]; - if (format != 1) { - g_message("ngsniffer: This Sniffer file type is not supported"); - free(wth->capture.ngsniffer); - return WTAP_FILE_UNKNOWN; - } - - /* Get data link type */ - network = version[9]; - if (network >= NUM_NGSNIFF_ENCAPS) { - g_message("ngsniffer: network type %d unknown", network); - free(wth->capture.ngsniffer); - return WTAP_FILE_UNKNOWN; - } - else { - wth->encapsulation = sniffer_encap[network]; - } - - /* Get time unit */ - timeunit = version[11]; - if (timeunit >= NUM_NGSNIFF_TIMEUNITS) { - g_message("ngsniffer: Unknown timeunit %d", timeunit); - free(wth->capture.ngsniffer); - return WTAP_FILE_UNKNOWN; - } - else { - wth->capture.ngsniffer->timeunit = Usec[timeunit]; - } - - /* Get capture start time */ - start_time = pletohs(&version[4]); - start_date = pletohs(&version[6]); - tm.tm_year = ((start_date&0xfe00)>>9) + 1980 - 1900; - tm.tm_mon = ((start_date&0x1e0)>>5) - 1; - tm.tm_mday = (start_date&0x1f); - /* The time does not appear to act as an - * offset; only the date - tm.tm_hour = (start_time&0xf800)>>11; - tm.tm_min = (start_time&0x7e0)>>5; - tm.tm_sec = (start_time&0x1f)<<1;*/ - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - tm.tm_isdst = -1; - wth->capture.ngsniffer->start = mktime(&tm); + + case REC_FRAME2: + /* + * Umm, we're not supposed to get these in an + * ATM Sniffer file; return an error. + */ + return -1; + + case REC_FRAME4: + /* Read the f_frame4_struct */ + bytes_read = fread(&frame4, 1, sizeof frame4, wth->fh); + if (bytes_read != sizeof frame4) { /* - * XXX - what if "secs" is -1? Unlikely, - * but if the capture was done in a time - * zone that switches between standard and - * summer time sometime other than when we - * do, and thus the time was one that doesn't - * exist here because a switch from standard - * to summer time zips over it, it could - * happen. - * - * On the other hand, if the capture was done - * in a different time zone, this won't work - * right anyway; unfortunately, the time zone - * isn't stored in the capture file. + * Read error or short record. Return + * an error. */ + return -1; + } + time_low = pletohs(&frame4.time_low); + time_med = pletohs(&frame4.time_med); + time_high = frame4.time_high; + size = pletohs(&frame4.size); + true_size = pletohs(&frame4.true_size); + + length -= sizeof frame4; /* we already read that much */ + + /* + * Skip it if it's not an AAL5 frame. + */ + if ((frame4.atm_info.AppTrafType & ATT_AALTYPE) + != ATT_AAL5) break; - case REC_FRAME2: - wth->capture.ngsniffer->pkt_len = length - 14; - return WTAP_FILE_NGSNIFFER; + /* + * OK, can we determine a network type from it? + */ + linktype = linktype_for_packet( + frame4.atm_info.AppTrafType, + frame4.atm_info.AppHLType); + if (linktype == -1) { + /* + * Nope - keep looking. + */ + break; + } + + /* + * XXX - use the "time_day" field? Is that for captures + * that take a *really* long time? + */ + wth->capture.ngsniffer->t = (double)time_low+(double)(time_med)*65536.0 + + (double)time_high*4294967296.0; + + wth->capture.ngsniffer->true_size = true_size; + wth->capture.ngsniffer->size = size; + goto found; - default: - /* Continue with while() loop */ + default: + break; /* unknown type, skip it */ } + + /* + * Well, we don't know what it is, or we know what + * it is but can't handle it. Skip past the data + * portion, and keep looping. + */ + fseek(wth->fh, length, SEEK_CUR); } - /* never gets here */ - return WTAP_FILE_NGSNIFFER; +found: + /* + * Note that we've already read the header, so that we don't do + * it in "ngsniffer_read()"; we've saved the stuff we need + * from the header, so we use it instead - and we save the + * length of the record, so we know how much to read. + */ + wth->capture.ngsniffer->pkt_len = length; + return (linktype); +} + +static int linktype_for_packet(u_int app_traf_type, u_int app_hl_type) +{ + switch (app_traf_type & ATT_HLTYPE) { + + case ATT_HL_LLCMX: + return (WTAP_ENCAP_ATM_RFC1483); + + case ATT_HL_LANE: + /* + * OK, is it 802.3, 802.5, or "none of the above"? + */ + switch (app_hl_type) { + + case AHLT_LANE_802_3: + case AHLT_LANE_802_3_MC: + return (WTAP_ENCAP_ETHERNET); + + case AHLT_LANE_802_5: + case AHLT_LANE_802_5_MC: + return (WTAP_ENCAP_TR); + } + } + + /* + * Keep looking until we find one of the above or run out of + * capture file. + */ + return (-1); } /* Read the next packet */ @@ -221,58 +577,161 @@ int ngsniffer_read(wtap *wth) char record_type[2]; char record_length[4]; /* only 1st 2 bytes are length */ guint16 type, length; - char frame2[14]; + struct frame2_rec frame2; + struct frame4_rec frame4; + int linktype; double t; guint16 time_low, time_med, time_high, true_size, size; int data_offset; - /* if this is the very first packet, then the fh cursor will be at the - * start of a f_frame2_struct instead of at the start of the record. - * Check for this */ - if (!packet_size) { + /* + * If we've already read the first packet's header, get the + * information we saved from it, and skip ahead and read + * the data. + */ + if (wth->capture.ngsniffer->pkt_len != 0) { + length = wth->capture.ngsniffer->pkt_len; + true_size = wth->capture.ngsniffer->true_size; + size = wth->capture.ngsniffer->size; + t = wth->capture.ngsniffer->t; + wth->capture.ngsniffer->pkt_len = 0; /* won't have read header for next packet */ + goto found; + } - /* Read record info */ + for (;;) { + /* + * Read the record header. + */ bytes_read = fread(record_type, 1, 2, wth->fh); bytes_read += fread(record_length, 1, 4, wth->fh); if (bytes_read != 6) { + /* + * End of file or error. + */ return 0; } type = pletohs(record_type); length = pletohs(record_length); - if (type != REC_FRAME2) { + switch (type) { + + case REC_FRAME2: + /* Read the f_frame2_struct */ + bytes_read = fread(&frame2, 1, sizeof frame2, wth->fh); + if (bytes_read != sizeof frame2) { + /* + * Read error or short record. Return + * an error. + */ + g_message("ngsniffer_read: not enough frame2 data (%d bytes)", + bytes_read); + return 0; + } + time_low = pletohs(&frame2.time_low); + time_med = pletohs(&frame2.time_med); + time_high = pletohs(&frame2.time_high); + size = pletohs(&frame2.size); + true_size = pletohs(&frame2.true_size); + + length -= sizeof frame2; /* we already read that much */ + + t = (double)time_low+(double)(time_med)*65536.0 + + (double)time_high*4294967296.0; + + goto found; + + case REC_FRAME4: + /* Read the f_frame4_struct */ + bytes_read = fread(&frame4, 1, sizeof frame4, wth->fh); + if (bytes_read != sizeof frame4) { + /* + * Read error or short record. Return + * an error. + */ + g_message("ngsniffer_read: not enough frame4 data (%d bytes)", + bytes_read); + return 0; + } + time_low = pletohs(&frame4.time_low); + time_med = pletohs(&frame4.time_med); + time_high = frame4.time_high; + size = pletohs(&frame4.size); + true_size = pletohs(&frame4.true_size); + + length -= sizeof frame4; /* we already read that much */ + + /* + * Skip it if it's not an AAL5 frame. + */ + if ((frame4.atm_info.AppTrafType & ATT_AALTYPE) + != ATT_AAL5) + break; + + /* + * Skip it if it's not a frame of the type we're + * handling. + */ + linktype = linktype_for_packet( + frame4.atm_info.AppTrafType, + frame4.atm_info.AppHLType); + if (wth->encapsulation != linktype) + break; + + /* + * XXX - use the "time_day" field? Is that for captures + * that take a *really* long time? + */ + t = (double)time_low+(double)(time_med)*65536.0 + + (double)time_high*4294967296.0; + + goto found; + + case REC_EOF: + /* + * End of file. Return an EOF indication. + */ return 0; + + default: + break; /* unknown type, skip it */ } - else { - packet_size = length - 14; - } - } - else { - wth->capture.ngsniffer->pkt_len = 0; - } - /* Read the f_frame2_struct */ - bytes_read = fread(frame2, 1, 14, wth->fh); - if (bytes_read != 14) { - g_message("ngsniffer_read: not enough frame2 data (%d bytes)", - bytes_read); - return 0; + /* + * Well, we don't know what it is, or we know what + * it is but can't handle it. Skip past the data + * portion, and keep looping. + */ + fseek(wth->fh, length, SEEK_CUR); } - /* Read some of the fields in frame2 */ - size = pletohs(&frame2[6]); - true_size = pletohs(&frame2[10]); - time_low = pletohs(&frame2[0]); - time_med = pletohs(&frame2[2]); - time_high = frame2[4]; +found: + wth->phdr.len = true_size ? true_size : size; + wth->phdr.caplen = size; - buffer_assure_space(&wth->frame_buffer, packet_size); + /* + * For ATM LANE, skip the 2-byte LAN Emulation header. That + * leaves an Ethernet/802.3 header for Ethernet/802.3, and + * leaves a pad byte and an 802.5 frame control byte for 802.5. + */ + if (wth->capture.ngsniffer->is_atm && wth->encapsulation != WTAP_ENCAP_ATM_RFC1483) { + if (length <= ATM_LANE_HEADER_LEN) + return -1; + fseek(wth->fh, ATM_LANE_HEADER_LEN, SEEK_CUR); + wth->phdr.caplen -= ATM_LANE_HEADER_LEN; + wth->phdr.len -= ATM_LANE_HEADER_LEN; + length -= ATM_LANE_HEADER_LEN; + } + + /* + * Read the packet data. + */ + buffer_assure_space(&wth->frame_buffer, length); data_offset = ftell(wth->fh); bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1, - packet_size, wth->fh); + length, wth->fh); - if (bytes_read != packet_size) { + if (bytes_read != length) { if (ferror(wth->fh)) { g_message("ngsniffer_read: fread for data: read error\n"); } else { @@ -282,16 +741,10 @@ int ngsniffer_read(wtap *wth) return -1; } - t = (double)time_low+(double)(time_med)*65536.0 + - (double)time_high*4294967296.0; t = t/1000000.0 * wth->capture.ngsniffer->timeunit; /* t = # of secs */ t += wth->capture.ngsniffer->start; - wth->phdr.ts.tv_sec = (long)t; wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec)) *1.0e6); - wth->phdr.len = true_size ? true_size : size; - wth->phdr.caplen = size; - return data_offset; } diff --git a/wiretap/ngsniffer.h b/wiretap/ngsniffer.h index 3fc1626392..40dd6e23f8 100644 --- a/wiretap/ngsniffer.h +++ b/wiretap/ngsniffer.h @@ -1,6 +1,6 @@ /* ngsniffer.h * - * $Id: ngsniffer.h,v 1.3 1998/11/13 05:57:39 gram Exp $ + * $Id: ngsniffer.h,v 1.4 1998/12/17 06:39:13 gram Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -21,9 +21,5 @@ * */ -#define REC_VERS 1 /* Version record (f_vers) */ -#define REC_FRAME2 4 /* Frame data (f_frame2) */ -#define REC_EOF 3 /* End-of-file record (no data follows) */ - int ngsniffer_open(wtap *wth); int ngsniffer_read(wtap *wth); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 36c20fd0bb..eab1568d99 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1,6 +1,6 @@ /* wtap.h * - * $Id: wtap.h,v 1.7 1998/12/13 05:08:05 gram Exp $ + * $Id: wtap.h,v 1.8 1998/12/17 06:39:13 gram Exp $ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu> @@ -21,7 +21,8 @@ * */ -/* Encapsulation types */ +/* Encapsulation types. Choose names that truly reflect + * what is contained in the packet trace file. */ #define WTAP_ENCAP_NONE 0 #define WTAP_ENCAP_ETHERNET 1 #define WTAP_ENCAP_TR 2 @@ -30,6 +31,7 @@ #define WTAP_ENCAP_FDDI 5 #define WTAP_ENCAP_RAW_IP 6 #define WTAP_ENCAP_ARCNET 7 +#define WTAP_ENCAP_ATM_RFC1483 8 /* File types that can be read by wiretap */ #define WTAP_FILE_UNKNOWN 0 @@ -47,9 +49,13 @@ #include <buffer.h> typedef struct { - guint16 pkt_len; double timeunit; time_t start; + guint16 pkt_len; + guint16 size; + guint16 true_size; + double t; + int is_atm; } ngsniffer_t; typedef struct { |