X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=wiretap%2Flanalyzer.c;h=50ce3339e083ddd791a25d1a7a2d87ebd4071936;hb=ffa9e938e24779470c664ea8eca1e452ce025f97;hp=5fbf8714c2177d76b3d24b8472327b07c2508af9;hpb=d94bd07f99438278cb11f24b00571ab2907b6bdb;p=metze%2Fwireshark%2Fwip.git diff --git a/wiretap/lanalyzer.c b/wiretap/lanalyzer.c index 5fbf8714c2..50ce3339e0 100644 --- a/wiretap/lanalyzer.c +++ b/wiretap/lanalyzer.c @@ -1,6 +1,4 @@ /* lanalyzer.c - * - * $Id$ * * Wiretap Library * Copyright (c) 1998 by Gilbert Ramirez @@ -17,30 +15,27 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include #include #include "wtap-int.h" #include "file_wrappers.h" -#include "buffer.h" #include "lanalyzer.h" /* The LANalyzer format is documented (at least in part) in Novell document TID022037, which can be found at, among other places: - http://www.windowsecurity.com/whitepapers/Description_of_the_LANalysers_output_file.html + http://www.windowsecurity.com/whitepapers/Description_of_the_LANalysers_output_file.html */ /* Record header format */ typedef struct { - guint8 record_type[2]; - guint8 record_length[2]; + guint8 record_type[2]; + guint8 record_length[2]; } LA_RecordHeader; #define LA_RecordHeaderSize 4 @@ -126,8 +121,8 @@ typedef guint16 TimeStamp[3]; /* 0.5 microseconds since start of trace */ /* LANalyzer board types (which indicate the type of network on which the capture was done). */ -#define BOARD_325 226 /* LANalyzer 325 (Ethernet) */ -#define BOARD_325TR 227 /* LANalyzer 325TR (Token-ring) */ +#define BOARD_325 226 /* LANalyzer 325 (Ethernet) */ +#define BOARD_325TR 227 /* LANalyzer 325TR (Token-ring) */ /* @@ -182,7 +177,7 @@ typedef guint16 TimeStamp[3]; /* 0.5 microseconds since start of trace */ typedef struct { gboolean init; - struct timeval start; + nstime_t start; guint32 pkts; int encap; int lastlen; @@ -263,327 +258,305 @@ static const guint8 LA_CyclicInformationFake[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +static const guint8 z64[64] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + typedef struct { - time_t start; + time_t start; } lanalyzer_t; static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset); static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off, - union wtap_pseudo_header *pseudo_header, guint8 *pd, int length, - int *err, gchar **err_info); -static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err); + struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info); +static gboolean lanalyzer_dump_finish(wtap_dumper *wdh, int *err); -int lanalyzer_open(wtap *wth, int *err, gchar **err_info) +wtap_open_return_val lanalyzer_open(wtap *wth, int *err, gchar **err_info) { - int bytes_read; - LA_RecordHeader rec_header; - char summary[210]; - guint16 board_type, mxslc; - guint16 record_type, record_length; - guint8 cr_day, cr_month; - guint16 cr_year; - struct tm tm; - lanalyzer_t *lanalyzer; - - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(&rec_header, LA_RecordHeaderSize, wth->fh); - if (bytes_read != LA_RecordHeaderSize) { - *err = file_error(wth->fh, err_info); - if (*err != 0) - return -1; - return 0; - } - wth->data_offset += LA_RecordHeaderSize; - record_type = pletohs(rec_header.record_type); - record_length = pletohs(rec_header.record_length); /* make sure to do this for while() loop */ - - if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) { - return 0; - } - - /* If we made it this far, then the file is a LANAlyzer file. - * Let's get some info from it. Note that we get wth->snapshot_length - * from a record later in the file. */ - wth->file_type = WTAP_FILE_LANALYZER; - lanalyzer = (lanalyzer_t *)g_malloc(sizeof(lanalyzer_t));; - wth->priv = (void *)lanalyzer; - wth->subtype_read = lanalyzer_read; - wth->subtype_seek_read = lanalyzer_seek_read; - wth->snapshot_length = 0; - wth->tsprecision = WTAP_FILE_TSPREC_NSEC; - - /* Read records until we find the start of packets */ - while (1) { - if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) { - g_free(wth->priv); - return -1; - } - wth->data_offset += record_length; - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(&rec_header, LA_RecordHeaderSize, wth->fh); - if (bytes_read != LA_RecordHeaderSize) { - *err = file_error(wth->fh, err_info); - if (*err != 0) { - g_free(wth->priv); - return -1; - } - g_free(wth->priv); - return 0; - } - wth->data_offset += LA_RecordHeaderSize; - - record_type = pletohs(rec_header.record_type); - record_length = pletohs(rec_header.record_length); - - /*g_message("Record 0x%04X Length %d", record_type, record_length);*/ - switch (record_type) { - /* Trace Summary Record */ - case RT_Summary: - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(summary, sizeof summary, - wth->fh); - if (bytes_read != sizeof summary) { - *err = file_error(wth->fh, err_info); - if (*err != 0) { - g_free(wth->priv); - return -1; - } - g_free(wth->priv); - return 0; - } - wth->data_offset += sizeof summary; - - /* Assume that the date of the creation of the trace file - * is the same date of the trace. Lanalyzer doesn't - * store the creation date/time of the trace, but only of - * the file. Unless you traced at 11:55 PM and saved at 00:05 - * AM, the assumption that trace.date == file.date is true. - */ - cr_day = summary[0]; - cr_month = summary[1]; - cr_year = pletohs(&summary[2]); - /*g_message("Day %d Month %d Year %d (%04X)", cr_day, cr_month, - cr_year, cr_year);*/ - - /* Get capture start time. I learned how to do - * this from Guy's code in ngsniffer.c - */ - tm.tm_year = cr_year - 1900; - tm.tm_mon = cr_month - 1; - tm.tm_mday = cr_day; - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - tm.tm_isdst = -1; - lanalyzer->start = mktime(&tm); - /*g_message("Day %d Month %d Year %d", tm.tm_mday, - tm.tm_mon, tm.tm_year);*/ - mxslc = pletohs(&summary[30]); - wth->snapshot_length = mxslc; - - record_length = 0; /* to fake the next iteration of while() */ - board_type = pletohs(&summary[188]); - switch (board_type) { - case BOARD_325: - wth->file_encap = WTAP_ENCAP_ETHERNET; - break; - case BOARD_325TR: - wth->file_encap = WTAP_ENCAP_TOKEN_RING; - break; - default: - g_free(wth->priv); - *err = WTAP_ERR_UNSUPPORTED_ENCAP; - *err_info = g_strdup_printf("lanalyzer: board type %u unknown", - board_type); - return -1; - } - break; - - /* Trace Packet Data Record */ - case RT_PacketData: - /* Go back header number of bytes so that lanalyzer_read - * can read this header */ - if (file_seek(wth->fh, -LA_RecordHeaderSize, SEEK_CUR, err) == -1) { - g_free(wth->priv); - return -1; - } - wth->data_offset -= LA_RecordHeaderSize; - return 1; - - default: - ; /* no action */ - } - } + LA_RecordHeader rec_header; + char header_fixed[2]; + char *comment; + char summary[210]; + guint16 board_type, mxslc; + guint16 record_type, record_length; + guint8 cr_day, cr_month; + guint16 cr_year; + struct tm tm; + lanalyzer_t *lanalyzer; + + if (!wtap_read_bytes(wth->fh, &rec_header, LA_RecordHeaderSize, + err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + record_type = pletoh16(rec_header.record_type); + record_length = pletoh16(rec_header.record_length); /* make sure to do this for while() loop */ + + if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) { + return WTAP_OPEN_NOT_MINE; + } + + /* Read the major and minor version numbers */ + if (record_length < 2) { + /* + * Not enough room for the major and minor version numbers. + * Just treat that as a "not a LANalyzer file" indication. + */ + return WTAP_OPEN_NOT_MINE; + } + if (!wtap_read_bytes(wth->fh, &header_fixed, sizeof header_fixed, + err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + record_length -= sizeof header_fixed; + + if (record_length != 0) { + /* Read the rest of the record as a comment. */ + comment = (char *)g_malloc(record_length + 1); + if (!wtap_read_bytes(wth->fh, comment, record_length, + err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + comment[record_length] = '\0'; + wth->shb_hdr.opt_comment = comment; + } + + /* If we made it this far, then the file is a LANAlyzer file. + * Let's get some info from it. Note that we get wth->snapshot_length + * from a record later in the file. */ + wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LANALYZER; + lanalyzer = (lanalyzer_t *)g_malloc(sizeof(lanalyzer_t)); + wth->priv = (void *)lanalyzer; + wth->subtype_read = lanalyzer_read; + wth->subtype_seek_read = lanalyzer_seek_read; + wth->snapshot_length = 0; + wth->file_tsprec = WTAP_TSPREC_NSEC; + + /* Read records until we find the start of packets */ + while (1) { + if (!wtap_read_bytes_or_eof(wth->fh, &rec_header, + LA_RecordHeaderSize, err, err_info)) { + if (*err == 0) { + /* + * End of file and no packets; + * accept this file. + */ + return WTAP_OPEN_MINE; + } + return WTAP_OPEN_ERROR; + } + + record_type = pletoh16(rec_header.record_type); + record_length = pletoh16(rec_header.record_length); + + /*g_message("Record 0x%04X Length %d", record_type, record_length);*/ + switch (record_type) { + /* Trace Summary Record */ + case RT_Summary: + if (!wtap_read_bytes(wth->fh, summary, + sizeof summary, err, err_info)) + return WTAP_OPEN_ERROR; + + /* Assume that the date of the creation of the trace file + * is the same date of the trace. Lanalyzer doesn't + * store the creation date/time of the trace, but only of + * the file. Unless you traced at 11:55 PM and saved at 00:05 + * AM, the assumption that trace.date == file.date is true. + */ + cr_day = summary[0]; + cr_month = summary[1]; + cr_year = pletoh16(&summary[2]); + /*g_message("Day %d Month %d Year %d (%04X)", cr_day, cr_month, + cr_year, cr_year);*/ + + /* Get capture start time. I learned how to do + * this from Guy's code in ngsniffer.c + */ + tm.tm_year = cr_year - 1900; + tm.tm_mon = cr_month - 1; + tm.tm_mday = cr_day; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + lanalyzer->start = mktime(&tm); + /*g_message("Day %d Month %d Year %d", tm.tm_mday, + tm.tm_mon, tm.tm_year);*/ + mxslc = pletoh16(&summary[30]); + wth->snapshot_length = mxslc; + + board_type = pletoh16(&summary[188]); + switch (board_type) { + case BOARD_325: + wth->file_encap = WTAP_ENCAP_ETHERNET; + break; + case BOARD_325TR: + wth->file_encap = WTAP_ENCAP_TOKEN_RING; + break; + default: + *err = WTAP_ERR_UNSUPPORTED; + *err_info = g_strdup_printf("lanalyzer: board type %u unknown", + board_type); + return WTAP_OPEN_ERROR; + } + break; + + /* Trace Packet Data Record */ + case RT_PacketData: + /* Go back header number of bytes so that lanalyzer_read + * can read this header */ + if (file_seek(wth->fh, -LA_RecordHeaderSize, SEEK_CUR, err) == -1) { + return WTAP_OPEN_ERROR; + } + return WTAP_OPEN_MINE; + + default: + if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) { + return WTAP_OPEN_ERROR; + } + break; + } + } } -#define DESCRIPTOR_LEN 32 +#define DESCRIPTOR_LEN 32 + +static gboolean lanalyzer_read_trace_record(wtap *wth, FILE_T fh, + struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) +{ + char LE_record_type[2]; + char LE_record_length[2]; + guint16 record_type, record_length; + int record_data_size; + int packet_size; + gchar descriptor[DESCRIPTOR_LEN]; + lanalyzer_t *lanalyzer; + guint16 time_low, time_med, time_high, true_size; + guint64 t; + time_t tsecs; + + /* read the record type and length. */ + if (!wtap_read_bytes_or_eof(fh, LE_record_type, 2, err, err_info)) + return FALSE; + if (!wtap_read_bytes(fh, LE_record_length, 2, err, err_info)) + return FALSE; + + record_type = pletoh16(LE_record_type); + record_length = pletoh16(LE_record_length); + + /* Only Trace Packet Data Records should occur now that we're in + * the middle of reading packets. If any other record type exists + * after a Trace Packet Data Record, mark it as an error. */ + if (record_type != RT_PacketData) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record", + record_type); + return FALSE; + } + + if (record_length < DESCRIPTOR_LEN) { + /* + * Uh-oh, the record isn't big enough to even have a + * descriptor. + */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("lanalyzer: file has a %u-byte record, too small to have even a packet descriptor", + record_length); + return FALSE; + } + record_data_size = record_length - DESCRIPTOR_LEN; + + /* Read the descriptor data */ + if (!wtap_read_bytes(fh, descriptor, DESCRIPTOR_LEN, err, err_info)) + return FALSE; + + true_size = pletoh16(&descriptor[4]); + packet_size = pletoh16(&descriptor[6]); + + /* + * OK, is the frame data size greater than than what's left of the + * record? + */ + if (packet_size > record_data_size) { + /* + * Yes - treat this as an error. + */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("lanalyzer: Record length is less than packet size"); + return FALSE; + } + + phdr->rec_type = REC_TYPE_PACKET; + phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; + + time_low = pletoh16(&descriptor[8]); + time_med = pletoh16(&descriptor[10]); + time_high = pletoh16(&descriptor[12]); + t = (((guint64)time_low) << 0) + (((guint64)time_med) << 16) + + (((guint64)time_high) << 32); + tsecs = (time_t) (t/2000000); + lanalyzer = (lanalyzer_t *)wth->priv; + phdr->ts.secs = tsecs + lanalyzer->start; + phdr->ts.nsecs = ((guint32) (t - tsecs*2000000)) * 500; + + if (true_size - 4 >= packet_size) { + /* + * It appears that the "true size" includes the FCS; + * make it reflect the non-FCS size (the "packet size" + * appears never to include the FCS, even if no slicing + * is done). + */ + true_size -= 4; + } + phdr->len = true_size; + phdr->caplen = packet_size; + + switch (wth->file_encap) { + + case WTAP_ENCAP_ETHERNET: + /* We assume there's no FCS in this frame. */ + phdr->pseudo_header.eth.fcs_len = 0; + break; + } + + /* Read the packet data */ + return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info); +} /* Read the next packet */ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info, - gint64 *data_offset) + gint64 *data_offset) { - int packet_size = 0; - int bytes_read; - char LE_record_type[2]; - char LE_record_length[2]; - guint16 record_type, record_length; - gchar descriptor[DESCRIPTOR_LEN]; - guint16 time_low, time_med, time_high, true_size; - guint64 t; - time_t tsecs; - lanalyzer_t *lanalyzer; - - /* read the record type and length. */ - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(LE_record_type, 2, wth->fh); - if (bytes_read != 2) { - *err = file_error(wth->fh, err_info); - if (*err == 0 && bytes_read != 0) { - *err = WTAP_ERR_SHORT_READ; - } - return FALSE; - } - wth->data_offset += 2; - bytes_read = file_read(LE_record_length, 2, wth->fh); - if (bytes_read != 2) { - *err = file_error(wth->fh, err_info); - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - wth->data_offset += 2; - - record_type = pletohs(LE_record_type); - record_length = pletohs(LE_record_length); - - /* Only Trace Packet Data Records should occur now that we're in - * the middle of reading packets. If any other record type exists - * after a Trace Packet Data Record, mark it as an error. */ - if (record_type != RT_PacketData) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record", - record_type); - return FALSE; - } - else { - if (record_length < DESCRIPTOR_LEN) { - /* - * Uh-oh, the record isn't big enough to even have a - * descriptor. - */ - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("lanalyzer: file has a %u-byte record, too small to have even a packet descriptor", - record_length); - return FALSE; - } - packet_size = record_length - DESCRIPTOR_LEN; - } - - /* Read the descriptor data */ - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(descriptor, DESCRIPTOR_LEN, wth->fh); - if (bytes_read != DESCRIPTOR_LEN) { - *err = file_error(wth->fh, err_info); - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - wth->data_offset += DESCRIPTOR_LEN; - - /* Read the packet data */ - buffer_assure_space(wth->frame_buffer, packet_size); - *data_offset = wth->data_offset; - errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), - packet_size, wth->fh); - - if (bytes_read != packet_size) { - *err = file_error(wth->fh, err_info); - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - wth->data_offset += packet_size; - - true_size = pletohs(&descriptor[4]); - packet_size = pletohs(&descriptor[6]); - - /* - * OK, is the frame data size greater than than what's left of the - * record? - */ - if (packet_size > record_length - DESCRIPTOR_LEN) { - /* - * Yes - treat this as an error. - */ - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("lanalyzer: Record length is less than packet size"); - return FALSE; - } - - time_low = pletohs(&descriptor[8]); - time_med = pletohs(&descriptor[10]); - time_high = pletohs(&descriptor[12]); - t = (((guint64)time_low) << 0) + (((guint64)time_med) << 16) + - (((guint64)time_high) << 32); - tsecs = (time_t) (t/2000000); - lanalyzer = (lanalyzer_t *)wth->priv; - wth->phdr.ts.secs = tsecs + lanalyzer->start; - wth->phdr.ts.nsecs = ((guint32) (t - tsecs*2000000)) * 500; - - if (true_size - 4 >= packet_size) { - /* - * It appears that the "true size" includes the FCS; - * make it reflect the non-FCS size (the "packet size" - * appears never to include the FCS, even if no slicing - * is done). - */ - true_size -= 4; - } - wth->phdr.len = true_size; - wth->phdr.caplen = packet_size; - - switch (wth->file_encap) { - - case WTAP_ENCAP_ETHERNET: - /* We assume there's no FCS in this frame. */ - wth->pseudo_header.eth.fcs_len = 0; - break; - } - - return TRUE; + *data_offset = file_tell(wth->fh); + + /* Read the record */ + return lanalyzer_read_trace_record(wth, wth->fh, &wth->phdr, + wth->frame_buffer, err, err_info); } static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off, - union wtap_pseudo_header *pseudo_header, guint8 *pd, int length, - int *err, gchar **err_info) + struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { - int bytes_read; - - if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) - return FALSE; - - /* - * Read the packet data. - */ - bytes_read = file_read(pd, length, wth->random_fh); - if (bytes_read != length) { - *err = file_error(wth->random_fh, err_info); - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - - switch (wth->file_encap) { - - case WTAP_ENCAP_ETHERNET: - /* We assume there's no FCS in this frame. */ - pseudo_header->eth.fcs_len = 0; - break; - } - - return TRUE; + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; + + /* Read the record */ + if (!lanalyzer_read_trace_record(wth, wth->random_fh, phdr, buf, + err, err_info)) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + return TRUE; } /*--------------------------------------------------- @@ -592,78 +565,81 @@ static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off, *---------------------------------------------------*/ static gboolean s0write(wtap_dumper *wdh, size_t cnt, int *err) { - static const guint8 z64[64]; - size_t snack; + size_t snack; - while (cnt) { - snack = cnt > 64 ? 64 : cnt; + while (cnt) { + snack = cnt > 64 ? 64 : cnt; - if (!wtap_dump_file_write(wdh, z64, snack, err)) - return FALSE; - cnt -= snack; - } - return TRUE; /* ok */ + if (!wtap_dump_file_write(wdh, z64, snack, err)) + return FALSE; + cnt -= snack; + } + return TRUE; /* ok */ } /*--------------------------------------------------- * Returns TRUE on success, FALSE on error - * Write an 8-bit value with error control + * Write an 8-bit value *---------------------------------------------------*/ static gboolean s8write(wtap_dumper *wdh, const guint8 s8, int *err) { - return wtap_dump_file_write(wdh, &s8, 1, err); + return wtap_dump_file_write(wdh, &s8, 1, err); } /*--------------------------------------------------- * Returns TRUE on success, FALSE on error - * Write a 16-bit value with error control + * Write a 16-bit value as little-endian *---------------------------------------------------*/ static gboolean s16write(wtap_dumper *wdh, const guint16 s16, int *err) { - return wtap_dump_file_write(wdh, &s16, 2, err); + guint16 s16_le = GUINT16_TO_LE(s16); + return wtap_dump_file_write(wdh, &s16_le, 2, err); } /*--------------------------------------------------- * Returns TRUE on success, FALSE on error - * Write a 32-bit value with error control + * Write a 32-bit value as little-endian *---------------------------------------------------*/ static gboolean s32write(wtap_dumper *wdh, const guint32 s32, int *err) { - return wtap_dump_file_write(wdh, &s32, 4, err); + guint32 s32_le = GUINT32_TO_LE(s32); + return wtap_dump_file_write(wdh, &s32_le, 4, err); } /*--------------------------------------------------- - * - * calculates C.c = A.a - B.b + * Returns TRUE on success, FALSE on error + * Write a 48-bit value as little-endian *---------------------------------------------------*/ -static void my_timersub(const struct timeval *a, - const struct timeval *b, - struct timeval *c) +static gboolean s48write(wtap_dumper *wdh, const guint64 s48, int *err) { - gint32 usec = a->tv_usec; - - c->tv_sec = a->tv_sec - b->tv_sec; - if (b->tv_usec > usec) { - c->tv_sec--; - usec += 1000000; - } - c->tv_usec = usec - b->tv_usec; +#ifdef WORDS_BIGENDIAN + guint16 s48_upper_le = GUINT16_SWAP_LE_BE((guint16) (s48 >> 32)); + guint32 s48_lower_le = GUINT32_SWAP_LE_BE((guint32) (s48 & 0xFFFFFFFF)); +#else + guint16 s48_upper_le = (guint16) (s48 >> 32); + guint32 s48_lower_le = (guint32) (s48 & 0xFFFFFFFF); +#endif + return wtap_dump_file_write(wdh, &s48_lower_le, 4, err) && + wtap_dump_file_write(wdh, &s48_upper_le, 2, err); } /*--------------------------------------------------- * Write a record for a packet to a dump file. * Returns TRUE on success, FALSE on failure. *---------------------------------------------------*/ static gboolean lanalyzer_dump(wtap_dumper *wdh, - const struct wtap_pkthdr *phdr, - const union wtap_pseudo_header *pseudo_header _U_, - const guint8 *pd, int *err) + const struct wtap_pkthdr *phdr, + const guint8 *pd, int *err, gchar **err_info _U_) { - double x; - int i; + guint64 x; int len; - struct timeval tv; LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->priv); - struct timeval td; + nstime_t td; int thisSize = phdr->caplen + LA_PacketRecordSize + LA_RecordHeaderSize; + /* We can only write packet records. */ + if (phdr->rec_type != REC_TYPE_PACKET) { + *err = WTAP_ERR_UNWRITABLE_REC_TYPE; + return FALSE; + } + if (wdh->bytes_dumped + thisSize > LA_ProFileLimit) { /* printf(" LA_ProFileLimit reached\n"); */ *err = EFBIG; @@ -672,50 +648,49 @@ static gboolean lanalyzer_dump(wtap_dumper *wdh, len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0); - if (!s16write(wdh, htoles(0x1005), err)) - return FALSE; - if (!s16write(wdh, htoles(len), err)) + /* len goes into a 16-bit field, so there's a hard limit of 65535. */ + if (len > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; return FALSE; + } - tv.tv_sec = (long int) phdr->ts.secs; - tv.tv_usec = phdr->ts.nsecs / 1000; + if (!s16write(wdh, 0x1005, err)) + return FALSE; + if (!s16write(wdh, (guint16)len, err)) + return FALSE; if (!itmp->init) { /* collect some information for the * finally written header */ - /* XXX - this conversion could probably improved, if the start uses ns */ - itmp->start = tv; + itmp->start = phdr->ts; itmp->pkts = 0; itmp->init = TRUE; itmp->encap = wdh->encap; itmp->lastlen = 0; } - my_timersub(&(tv),&(itmp->start),&td); - - x = (double) td.tv_usec; - x += (double) td.tv_sec * 1000000; - x *= 2; - - if (!s16write(wdh, htoles(0x0001), err)) /* pr.rx_channels */ + if (!s16write(wdh, 0x0001, err)) /* pr.rx_channels */ return FALSE; - if (!s16write(wdh, htoles(0x0008), err)) /* pr.rx_errors */ + if (!s16write(wdh, 0x0008, err)) /* pr.rx_errors */ return FALSE; - if (!s16write(wdh, htoles(phdr->len + 4), err)) /* pr.rx_frm_len */ + if (!s16write(wdh, (guint16) (phdr->len + 4), err)) /* pr.rx_frm_len */ return FALSE; - if (!s16write(wdh, htoles(phdr->caplen), err)) /* pr.rx_frm_sln */ + if (!s16write(wdh, (guint16) phdr->caplen, err)) /* pr.rx_frm_sln */ return FALSE; - for (i = 0; i < 3; i++) { - if (!s16write(wdh, htoles((guint16) x), err)) /* pr.rx_time[i] */ - return FALSE; - x /= 0xffff; - } + nstime_delta(&td, &phdr->ts, &itmp->start); + + /* Convert to half-microseconds, rounded up. */ + x = (td.nsecs + 250) / 500; /* nanoseconds -> half-microseconds, rounded */ + x += td.secs * 2000000; /* seconds -> half-microseconds */ + + if (!s48write(wdh, x, err)) /* pr.rx_time[i] */ + return FALSE; - if (!s32write(wdh, htolel(++itmp->pkts), err)) /* pr.pktno */ + if (!s32write(wdh, ++itmp->pkts, err)) /* pr.pktno */ return FALSE; - if (!s16write(wdh, htoles(itmp->lastlen), err)) /* pr.prlen */ + if (!s16write(wdh, (guint16)itmp->lastlen, err)) /* pr.prlen */ return FALSE; itmp->lastlen = len; @@ -742,7 +717,7 @@ int lanalyzer_dump_can_write_encap(int encap) if ( encap != WTAP_ENCAP_ETHERNET && encap != WTAP_ENCAP_TOKEN_RING ) - return WTAP_ERR_UNSUPPORTED_ENCAP; + return WTAP_ERR_UNWRITABLE_ENCAP; /* * printf("lanalyzer_dump_can_write_encap(%d)\n",encap); */ @@ -760,14 +735,14 @@ gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err) tmp = g_malloc(sizeof(LA_TmpInfo)); if (!tmp) { - *err = errno; - return FALSE; + *err = errno; + return FALSE; } ((LA_TmpInfo*)tmp)->init = FALSE; - wdh->priv = tmp; - wdh->subtype_write = lanalyzer_dump; - wdh->subtype_close = lanalyzer_dump_close; + wdh->priv = tmp; + wdh->subtype_write = lanalyzer_dump; + wdh->subtype_finish = lanalyzer_dump_finish; /* Some of the fields in the file header aren't known yet so just skip over it for now. It will be created after all @@ -784,10 +759,9 @@ gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err) + sizeof (LA_CyclicInformationFake) + LA_IndexRecordSize; - if (fseek(wdh->fh, jump, SEEK_SET) == -1) { - *err = errno; - return FALSE; - } + if (wtap_dump_file_seek(wdh, jump, SEEK_SET, err) == -1) + return FALSE; + wdh->bytes_dumped = jump; return TRUE; } @@ -801,56 +775,49 @@ static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err) guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING ? BOARD_325TR /* LANalyzer Board Type */ : BOARD_325; /* LANalyzer Board Type */ - time_t secs; struct tm *fT; - /* The secs variable is needed to work around 32/64-bit time_t issues. - itmp->start is a timeval struct, which declares its tv_sec field - (itmp->start.tv_sec) as a long (typically 32 bits). time_t can be 32 - or 64 bits, depending on the platform. Invoking as follows could - pass a pointer to a 32-bit long where a pointer to a 64-bit time_t - is expected: localtime((time_t*) &(itmp->start.tv_sec)) */ - secs = itmp->start.tv_sec; - fT = localtime(&secs); + fT = localtime(&itmp->start.secs); if (fT == NULL) return FALSE; - fseek(wdh->fh, 0, SEEK_SET); + if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1) + return FALSE; if (!wtap_dump_file_write(wdh, &LA_HeaderRegularFake, sizeof LA_HeaderRegularFake, err)) - return FALSE; + return FALSE; if (!wtap_dump_file_write(wdh, &LA_RxChannelNameFake, sizeof LA_RxChannelNameFake, err)) - return FALSE; + return FALSE; if (!wtap_dump_file_write(wdh, &LA_TxChannelNameFake, sizeof LA_TxChannelNameFake, err)) - return FALSE; + return FALSE; if (!wtap_dump_file_write(wdh, &LA_RxTemplateNameFake, sizeof LA_RxTemplateNameFake, err)) - return FALSE; + return FALSE; if (!wtap_dump_file_write(wdh, &LA_TxTemplateNameFake, sizeof LA_TxTemplateNameFake, err)) - return FALSE; + return FALSE; if (!wtap_dump_file_write(wdh, &LA_DisplayOptionsFake, sizeof LA_DisplayOptionsFake, err)) - return FALSE; + return FALSE; /*-----------------------------------------------------------------*/ - if (!s16write(wdh, htoles(RT_Summary), err)) /* rid */ + if (!s16write(wdh, RT_Summary, err)) /* rid */ return FALSE; - if (!s16write(wdh, htoles(SummarySize), err)) /* rlen */ + if (!s16write(wdh, SummarySize, err)) /* rlen */ return FALSE; if (!s8write(wdh, (guint8) fT->tm_mday, err)) /* s.datcre.day */ return FALSE; if (!s8write(wdh, (guint8) (fT->tm_mon+1), err)) /* s.datcre.mon */ return FALSE; - if (!s16write(wdh, htoles(fT->tm_year + 1900), err)) /* s.datcre.year */ + if (!s16write(wdh, (guint16) (fT->tm_year + 1900), err)) /* s.datcre.year */ return FALSE; if (!s8write(wdh, (guint8) fT->tm_mday, err)) /* s.datclo.day */ return FALSE; if (!s8write(wdh, (guint8) (fT->tm_mon+1), err)) /* s.datclo.mon */ return FALSE; - if (!s16write(wdh, htoles(fT->tm_year + 1900), err)) /* s.datclo.year */ + if (!s16write(wdh, (guint16) (fT->tm_year + 1900), err)) /* s.datclo.year */ return FALSE; if (!s8write(wdh, (guint8) fT->tm_sec, err)) /* s.timeopn.second */ return FALSE; @@ -874,13 +841,13 @@ static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err) return FALSE; if (!s0write(wdh, 6, err)) /* EAddr == 0 */ return FALSE; - if (!s16write(wdh, htoles(1), err)) /* s.mxseqno */ + if (!s16write(wdh, 1, err)) /* s.mxseqno */ return FALSE; - if (!s16write(wdh, htoles(0), err)) /* s.slcoffo */ + if (!s16write(wdh, 0, err)) /* s.slcoffo */ return FALSE; - if (!s16write(wdh, htoles(1514), err)) /* s.mxslc */ + if (!s16write(wdh, 1514, err)) /* s.mxslc */ return FALSE; - if (!s32write(wdh, htolel(itmp->pkts), err)) /* s.totpktt */ + if (!s32write(wdh, itmp->pkts, err)) /* s.totpktt */ return FALSE; /* * statrg == 0; ? -1 @@ -889,33 +856,33 @@ static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err) */ if (!s0write(wdh, 12, err)) return FALSE; - if (!s32write(wdh, htolel(itmp->pkts), err)) /* sr.s.mxpkta[1] */ + if (!s32write(wdh, itmp->pkts, err)) /* sr.s.mxpkta[1] */ return FALSE; - if (!s0write(wdh, 34*4, err)) /* s.mxpkta[2-33]=0 */ + if (!s0write(wdh, 34*4, err)) /* s.mxpkta[2-33]=0 */ return FALSE; - if (!s16write(wdh, htoles(board_type), err)) + if (!s16write(wdh, board_type, err)) return FALSE; - if (!s0write(wdh, 20, err)) /* board_version == 0 */ + if (!s0write(wdh, 20, err)) /* board_version == 0 */ return FALSE; /*-----------------------------------------------------------------*/ - if (!s16write(wdh, htoles(RT_SubfileSummary), err)) /* ssr.rid */ + if (!s16write(wdh, RT_SubfileSummary, err)) /* ssr.rid */ return FALSE; - if (!s16write(wdh, htoles(LA_SubfileSummaryRecordSize-4), err)) /* ssr.rlen */ + if (!s16write(wdh, LA_SubfileSummaryRecordSize-4, err)) /* ssr.rlen */ return FALSE; - if (!s16write(wdh, htoles(1), err)) /* ssr.seqno */ + if (!s16write(wdh, 1, err)) /* ssr.seqno */ return FALSE; - if (!s32write(wdh, htolel(itmp->pkts), err)) /* ssr.totpkts */ + if (!s32write(wdh, itmp->pkts, err)) /* ssr.totpkts */ return FALSE; /*-----------------------------------------------------------------*/ if (!wtap_dump_file_write(wdh, &LA_CyclicInformationFake, sizeof LA_CyclicInformationFake, err)) return FALSE; /*-----------------------------------------------------------------*/ - if (!s16write(wdh, htoles(RT_Index), err)) /* rid */ + if (!s16write(wdh, RT_Index, err)) /* rid */ return FALSE; - if (!s16write(wdh, htoles(LA_IndexRecordSize -4), err)) /* rlen */ + if (!s16write(wdh, LA_IndexRecordSize -4, err)) /* rlen */ return FALSE; - if (!s16write(wdh, htoles(LA_IndexSize), err)) /* idxsp */ + if (!s16write(wdh, LA_IndexSize, err)) /* idxsp */ return FALSE; if (!s0write(wdh, LA_IndexRecordSize - 6, err)) return FALSE; @@ -927,8 +894,21 @@ static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err) * Finish writing to a dump file. * Returns TRUE on success, FALSE on failure. *---------------------------------------------------*/ -static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err) +static gboolean lanalyzer_dump_finish(wtap_dumper *wdh, int *err) { lanalyzer_dump_header(wdh,err); return *err ? FALSE : TRUE; } + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 6 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=6 tabstop=8 expandtab: + * :indentSize=6:tabSize=8:noTabs=true: + */