diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common index 7db8846269..f1fe817d3a 100644 --- a/wiretap/Makefile.common +++ b/wiretap/Makefile.common @@ -36,6 +36,7 @@ NONGENERATED_C_FILES = \ ber.c \ buffer.c \ catapult_dct2000.c \ + commview.c \ cosine.c \ csids.c \ dbs-etherwatch.c \ @@ -77,6 +78,7 @@ NONGENERATED_HEADER_FILES = \ ber.h \ buffer.h \ catapult_dct2000.h \ + commview.h \ cosine.h \ csids.h \ dbs-etherwatch.h \ diff --git a/wiretap/commview.c b/wiretap/commview.c new file mode 100644 index 0000000000..62e734651f --- /dev/null +++ b/wiretap/commview.c @@ -0,0 +1,267 @@ +/* commview.c + * Routines for opening CommView file format packet captures + * Copyright 2007, Stephen Fisher + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Based on csids.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +/* A brief description of this file format is available at: + * http://www.tamos.com/htmlhelp/commview/logformat.htm + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "wtap.h" +#include "wtap-int.h" +#include "buffer.h" +#include "file_wrappers.h" +#include "commview.h" + +typedef struct commview_header { + guint16 data_len; + guint16 source_data_len; + guint8 version; + guint16 year; + guint8 month; + guint8 day; + guint8 hours; + guint8 minutes; + guint8 seconds; + guint32 usecs; + guint8 flags; /* Bit-field positions defined below */ + guint8 signal_level; + guint8 rate; + guint8 band; + guint8 channel; + guint8 direction; /* Not applicable to WiFi packets */ + guint16 reserved; /* Unused bytes */ +} commview_header_t; + +#define COMMVIEW_HEADER_SIZE 24 + +/* Bit-field positions for various fields in the flags variable of the header */ +#define FLAGS_MEDIUM 0x0F +#define FLAGS_DECRYPTED 0x10 +#define FLAGS_BROKEN 0x20 +#define FLAGS_COMPRESSED 0x40 +#define FLAGS_RESERVED 0x80 + +/* Capture mediums as defined by the commview file format */ +#define MEDIUM_ETHERNET 0 +#define MEDIUM_WIFI 1 +#define MEDIUM_TOKEN_RING 2 + +int commview_open(wtap *wth, int *err, gchar **err_info _U_); +static gboolean commview_read(wtap *wth, int *err, gchar **err_info _U_, + gint64 *data_offset); +static gboolean commview_seek_read(wtap *wth, gint64 seek_off, + union wtap_pseudo_header *pseudo_header, + guchar *pd, int length, int *err, + gchar **err_info _U_); +static gboolean commview_read_header(commview_header_t *cv_hdr, FILE_T fh, + int *err); + + +int commview_open(wtap *wth, int *err, gchar **err_info _U_) +{ + commview_header_t cv_hdr; + + if(!commview_read_header(&cv_hdr, wth->fh, err)) + return -1; + + /* If any of these fields do not match what we expect, bail out. */ + if(cv_hdr.version != 0 || + cv_hdr.year < 1970 || cv_hdr.year >= 2038 || + cv_hdr.month < 1 || cv_hdr.month > 12 || + cv_hdr.day < 1 || cv_hdr.day > 31 || + cv_hdr.hours > 23 || + cv_hdr.minutes > 59 || + cv_hdr.seconds > 60 || + cv_hdr.signal_level > 100 || + (cv_hdr.direction != 0x00 && cv_hdr.direction != 0x01 && + cv_hdr.direction != 0x02) || + (cv_hdr.flags & FLAGS_RESERVED) != 0 || + ((cv_hdr.flags & FLAGS_MEDIUM) != MEDIUM_ETHERNET && + (cv_hdr.flags & FLAGS_MEDIUM) != MEDIUM_WIFI && + (cv_hdr.flags & FLAGS_MEDIUM) != MEDIUM_TOKEN_RING) || + cv_hdr.reserved != 0) + return 0; /* Not our kind of file */ + + /* No file header. Reset the fh to 0 so we can read the first packet */ + if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) + return -1; + + /* Set up the pointers to the handlers for this file type */ + wth->data_offset = 0; + wth->subtype_read = commview_read; + wth->subtype_seek_read = commview_seek_read; + wth->file_type = WTAP_FILE_COMMVIEW; + wth->file_encap = WTAP_ENCAP_PER_PACKET; + wth->tsprecision = WTAP_FILE_TSPREC_USEC; + + return 1; /* Our kind of file */ +} + +static gboolean +commview_read(wtap *wth, int *err, gchar **err_info _U_, gint64 *data_offset) +{ + commview_header_t cv_hdr; + struct tm tm; + int bytes_read; + + *data_offset = wth->data_offset; + + if(!commview_read_header(&cv_hdr, wth->fh, err)) + return FALSE; + + wth->data_offset += COMMVIEW_HEADER_SIZE; + + switch(cv_hdr.flags & FLAGS_MEDIUM) { + + case MEDIUM_ETHERNET : + wth->phdr.pkt_encap = WTAP_ENCAP_ETHERNET; + break; + + case MEDIUM_WIFI : + wth->phdr.pkt_encap = WTAP_ENCAP_IEEE_802_11; + break; + + case MEDIUM_TOKEN_RING : + wth->phdr.pkt_encap = WTAP_ENCAP_TOKEN_RING; + break; + } + + buffer_assure_space(wth->frame_buffer, cv_hdr.data_len); + bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1, + cv_hdr.data_len, wth->fh); + if(bytes_read != cv_hdr.data_len) { + *err = file_error(wth->fh); + if(*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + + tm.tm_year = cv_hdr.year - 1900; + tm.tm_mon = cv_hdr.month - 1; + tm.tm_mday = cv_hdr.day; + tm.tm_hour = cv_hdr.hours; + tm.tm_min = cv_hdr.minutes; + tm.tm_sec = cv_hdr.seconds; + tm.tm_isdst = -1; + + wth->data_offset += cv_hdr.data_len; + + wth->phdr.len = cv_hdr.data_len; + wth->phdr.caplen = cv_hdr.data_len; + + wth->phdr.ts.secs = mktime(&tm); + wth->phdr.ts.nsecs = cv_hdr.usecs * 1000; + + return TRUE; +} + +static gboolean +commview_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header + *pseudo_header _U_, guchar *pd, int length, int *err, + gchar **err_info _U_) +{ + commview_header_t cv_hdr; + int bytes_read; + + if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; + + if(!commview_read_header(&cv_hdr, wth->random_fh, err)) { + if(*err == 0) + *err = WTAP_ERR_SHORT_READ; + + return FALSE; + } + + if(length != cv_hdr.data_len) { + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("commview: record length %u doesn't match requested length %d", cv_hdr.data_len, length); + return FALSE; + } + + bytes_read = file_read(pd, 1, cv_hdr.data_len, wth->random_fh); + if(bytes_read != cv_hdr.data_len) { + *err = file_error(wth->random_fh); + if(*err == 0) + *err = WTAP_ERR_SHORT_READ; + + return FALSE; + } + + return TRUE; +} + +static gboolean +commview_read_header(commview_header_t *cv_hdr, FILE_T fh, int *err) +{ + int bytes_read = 0; + + bytes_read += file_read(&cv_hdr->data_len, 2, 1, fh); + bytes_read += file_read(&cv_hdr->source_data_len, 2, 1, fh); + bytes_read += file_read(&cv_hdr->version, 1, 1, fh); + bytes_read += file_read(&cv_hdr->year, 2, 1, fh); + bytes_read += file_read(&cv_hdr->month, 1, 1, fh); + bytes_read += file_read(&cv_hdr->day, 1, 1, fh); + bytes_read += file_read(&cv_hdr->hours, 1, 1, fh); + bytes_read += file_read(&cv_hdr->minutes, 1, 1, fh); + bytes_read += file_read(&cv_hdr->seconds, 1, 1, fh); + bytes_read += file_read(&cv_hdr->usecs, 4, 1, fh); + bytes_read += file_read(&cv_hdr->flags, 1, 1, fh); + bytes_read += file_read(&cv_hdr->signal_level, 1, 1, fh); + bytes_read += file_read(&cv_hdr->rate, 1, 1, fh); + bytes_read += file_read(&cv_hdr->band, 1, 1, fh); + bytes_read += file_read(&cv_hdr->channel, 1, 1, fh); + bytes_read += file_read(&cv_hdr->direction, 1, 1, fh); + bytes_read += file_read(&cv_hdr->reserved, 2, 1, fh); + + /* Convert multi-byte values from little endian to host endian format */ + cv_hdr->data_len = GUINT16_FROM_LE(cv_hdr->data_len); + cv_hdr->source_data_len = GUINT16_FROM_LE(cv_hdr->source_data_len); + cv_hdr->year = GUINT16_FROM_LE(cv_hdr->year); + cv_hdr->usecs = GUINT32_FROM_LE(cv_hdr->usecs); + + if(bytes_read < COMMVIEW_HEADER_SIZE) { + *err = file_error(fh); + if(*err == 0 && bytes_read > 0) + *err = WTAP_ERR_SHORT_READ; + + return FALSE; + } + + return TRUE; +} + diff --git a/wiretap/commview.h b/wiretap/commview.h new file mode 100644 index 0000000000..b3dfc978c7 --- /dev/null +++ b/wiretap/commview.h @@ -0,0 +1,31 @@ +/* commview.h + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef __COMMVIEW_H__ +#define __COMMVIEW_H__ + +int commview_open(wtap *wth, int *err, gchar **err_info _U_); + +#endif /* __COMMVIEW_H__ */ + diff --git a/wiretap/file_access.c b/wiretap/file_access.c index 08ca94b442..c15bbc3875 100644 --- a/wiretap/file_access.c +++ b/wiretap/file_access.c @@ -74,6 +74,7 @@ #include "catapult_dct2000.h" #include "mpeg.h" #include "netscreen.h" +#include "commview.h" @@ -141,6 +142,7 @@ static wtap_open_routine_t open_routines_base[] = { vms_open, cosine_open, hcidump_open, + commview_open }; #define N_FILE_TYPES (sizeof open_routines_base / sizeof open_routines_base[0]) @@ -567,6 +569,10 @@ static const struct file_type_info dump_open_table_base[] = { /* WTAP_FILE_NETSCREEN */ { "NetScreen snoop text file", "netscreen", "*.*", NULL, FALSE, NULL, NULL }, + + /* WTAP_FILE_COMMVIEW */ + { "TamoSoft CommView", "commview", "*.ncf", ".ncf", TRUE, + NULL, NULL } }; gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 79ad5a4166..030aa08456 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -250,6 +250,7 @@ extern "C" { #define WTAP_FILE_MPEG 46 #define WTAP_FILE_K12TEXT 47 #define WTAP_FILE_NETSCREEN 48 +#define WTAP_FILE_COMMVIEW 49 #define WTAP_NUM_FILE_TYPES wtap_get_num_file_types()