2019-06-27 18:20:02 +00:00
|
|
|
/* busmaster.c
|
|
|
|
*
|
|
|
|
* Wiretap Library
|
|
|
|
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
|
|
|
|
*
|
|
|
|
* Support for Busmaster log file format
|
|
|
|
* Copyright (c) 2019 by Maksim Salau <maksim.salau@gmail.com>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <wtap-int.h>
|
|
|
|
#include <file_wrappers.h>
|
|
|
|
#include <epan/dissectors/packet-socketcan.h>
|
2021-08-20 09:17:14 +00:00
|
|
|
#include <wsutil/exported_pdu_tlvs.h>
|
2019-06-27 18:20:02 +00:00
|
|
|
#include "busmaster.h"
|
|
|
|
#include "busmaster_priv.h"
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
static void
|
|
|
|
busmaster_close(wtap *wth);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
busmaster_read(wtap *wth, wtap_rec *rec, Buffer *buf,
|
|
|
|
int *err, gchar **err_info,
|
|
|
|
gint64 *data_offset);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
busmaster_seek_read(wtap *wth, gint64 seek_off,
|
|
|
|
wtap_rec *rec, Buffer *buf,
|
|
|
|
int *err, gchar **err_info);
|
|
|
|
|
2021-02-18 06:26:02 +00:00
|
|
|
static int busmaster_file_type_subtype = -1;
|
|
|
|
|
|
|
|
void register_busmaster(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See
|
|
|
|
*
|
|
|
|
* http://rbei-etas.github.io/busmaster/
|
|
|
|
*
|
|
|
|
* for the BUSMASTER software.
|
|
|
|
*/
|
|
|
|
|
2019-06-27 18:20:02 +00:00
|
|
|
static gboolean
|
|
|
|
busmaster_gen_packet(wtap_rec *rec, Buffer *buf,
|
|
|
|
const busmaster_priv_t *priv_entry, const msg_t *msg,
|
|
|
|
int *err, gchar **err_info)
|
|
|
|
{
|
|
|
|
time_t secs = 0;
|
|
|
|
guint32 nsecs = 0;
|
|
|
|
gboolean has_ts = FALSE;
|
|
|
|
gboolean is_fd = (msg->type == MSG_TYPE_STD_FD)
|
|
|
|
|| (msg->type == MSG_TYPE_EXT_FD);
|
|
|
|
gboolean is_eff = (msg->type == MSG_TYPE_EXT)
|
|
|
|
|| (msg->type == MSG_TYPE_EXT_RTR)
|
|
|
|
|| (msg->type == MSG_TYPE_EXT_FD);
|
|
|
|
gboolean is_rtr = (msg->type == MSG_TYPE_STD_RTR)
|
|
|
|
|| (msg->type == MSG_TYPE_EXT_RTR);
|
|
|
|
gboolean is_err = (msg->type == MSG_TYPE_ERR);
|
|
|
|
|
|
|
|
static const char *const can_proto_name = "can-hostendian";
|
|
|
|
static const char *const canfd_proto_name = "canfd";
|
|
|
|
|
|
|
|
const char *proto_name = is_fd ? canfd_proto_name : can_proto_name;
|
|
|
|
guint proto_name_length = (guint)strlen(proto_name) + 1;
|
|
|
|
guint header_length;
|
|
|
|
guint packet_length;
|
|
|
|
guint frame_length;
|
|
|
|
guint8 *buf_data;
|
|
|
|
|
|
|
|
/* Adjust proto name length to be aligned on 4 byte boundary */
|
|
|
|
proto_name_length += (proto_name_length % 4) ? (4 - (proto_name_length % 4)) : 0;
|
|
|
|
|
|
|
|
header_length = 4 + proto_name_length + 4;
|
|
|
|
frame_length = is_fd ? sizeof(canfd_frame_t) : sizeof(can_frame_t);
|
|
|
|
packet_length = header_length + frame_length;
|
|
|
|
|
|
|
|
ws_buffer_clean(buf);
|
|
|
|
ws_buffer_assure_space(buf, packet_length);
|
|
|
|
buf_data = ws_buffer_start_ptr(buf);
|
|
|
|
|
|
|
|
memset(buf_data, 0, packet_length);
|
|
|
|
|
2021-08-20 07:35:33 +00:00
|
|
|
phton16(buf_data + 0, EXP_PDU_TAG_PROTO_NAME);
|
|
|
|
phton16(buf_data + 2, proto_name_length);
|
2019-06-27 18:20:02 +00:00
|
|
|
memcpy(buf_data + 4, proto_name, strlen(proto_name));
|
|
|
|
|
|
|
|
if (!priv_entry)
|
|
|
|
{
|
|
|
|
*err = WTAP_ERR_BAD_FILE;
|
|
|
|
*err_info = g_strdup("Header is missing");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_fd)
|
|
|
|
{
|
2020-04-13 21:39:32 +00:00
|
|
|
canfd_frame_t canfd_frame = {0};
|
2019-06-27 18:20:02 +00:00
|
|
|
|
|
|
|
canfd_frame.can_id = (msg->id & (is_eff ? CAN_EFF_MASK : CAN_SFF_MASK)) |
|
|
|
|
(is_eff ? CAN_EFF_FLAG : 0) |
|
|
|
|
(is_err ? CAN_ERR_FLAG : 0);
|
|
|
|
canfd_frame.flags = 0;
|
|
|
|
canfd_frame.len = msg->data.length;
|
|
|
|
|
|
|
|
memcpy(canfd_frame.data,
|
|
|
|
msg->data.data,
|
|
|
|
MIN(msg->data.length, sizeof(canfd_frame.data)));
|
|
|
|
|
|
|
|
memcpy(buf_data + header_length,
|
|
|
|
(guint8 *)&canfd_frame,
|
|
|
|
sizeof(canfd_frame));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-13 21:39:32 +00:00
|
|
|
can_frame_t can_frame = {0};
|
2019-06-27 18:20:02 +00:00
|
|
|
|
|
|
|
can_frame.can_id = (msg->id & (is_eff ? CAN_EFF_MASK : CAN_SFF_MASK)) |
|
|
|
|
(is_rtr ? CAN_RTR_FLAG : 0) |
|
|
|
|
(is_eff ? CAN_EFF_FLAG : 0) |
|
|
|
|
(is_err ? CAN_ERR_FLAG : 0);
|
|
|
|
can_frame.can_dlc = msg->data.length;
|
|
|
|
|
|
|
|
memcpy(can_frame.data,
|
|
|
|
msg->data.data,
|
|
|
|
MIN(msg->data.length, sizeof(can_frame.data)));
|
|
|
|
|
|
|
|
memcpy(buf_data + header_length,
|
|
|
|
(guint8 *)&can_frame,
|
|
|
|
sizeof(can_frame));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv_entry->time_mode == TIME_MODE_SYSTEM)
|
|
|
|
{
|
|
|
|
struct tm tm;
|
|
|
|
|
2019-08-04 01:37:29 +00:00
|
|
|
tm.tm_year = priv_entry->start_date.year - 1900;
|
|
|
|
tm.tm_mon = priv_entry->start_date.month - 1;
|
|
|
|
tm.tm_mday = priv_entry->start_date.day;
|
|
|
|
tm.tm_hour = msg->timestamp.hours;
|
|
|
|
tm.tm_min = msg->timestamp.minutes;
|
|
|
|
tm.tm_sec = msg->timestamp.seconds;
|
|
|
|
tm.tm_isdst = -1;
|
2019-06-27 18:20:02 +00:00
|
|
|
|
|
|
|
secs = mktime(&tm);
|
|
|
|
nsecs = msg->timestamp.micros * 1000u;
|
|
|
|
has_ts = TRUE;
|
|
|
|
}
|
|
|
|
else if (priv_entry->time_mode == TIME_MODE_ABSOLUTE)
|
|
|
|
{
|
|
|
|
struct tm tm;
|
|
|
|
guint32 micros;
|
|
|
|
|
2019-08-04 01:37:29 +00:00
|
|
|
tm.tm_year = priv_entry->start_date.year - 1900;
|
|
|
|
tm.tm_mon = priv_entry->start_date.month - 1;
|
|
|
|
tm.tm_mday = priv_entry->start_date.day;
|
|
|
|
tm.tm_hour = priv_entry->start_time.hours;
|
|
|
|
tm.tm_min = priv_entry->start_time.minutes;
|
|
|
|
tm.tm_sec = priv_entry->start_time.seconds;
|
|
|
|
tm.tm_isdst = -1;
|
2019-06-27 18:20:02 +00:00
|
|
|
|
|
|
|
secs = mktime(&tm);
|
|
|
|
|
|
|
|
secs += msg->timestamp.hours * 3600;
|
|
|
|
secs += msg->timestamp.minutes * 60;
|
|
|
|
secs += msg->timestamp.seconds;
|
|
|
|
|
|
|
|
micros = priv_entry->start_time.micros + msg->timestamp.micros;
|
|
|
|
if (micros >= 1000000u)
|
|
|
|
{
|
|
|
|
micros -= 1000000u;
|
|
|
|
secs += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsecs = micros * 1000u;
|
|
|
|
has_ts = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rec->rec_type = REC_TYPE_PACKET;
|
2021-08-30 02:12:13 +00:00
|
|
|
rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
|
2019-06-27 18:20:02 +00:00
|
|
|
rec->presence_flags = has_ts ? WTAP_HAS_TS : 0;
|
|
|
|
rec->ts.secs = secs;
|
|
|
|
rec->ts.nsecs = nsecs;
|
|
|
|
|
|
|
|
rec->rec_header.packet_header.caplen = packet_length;
|
|
|
|
rec->rec_header.packet_header.len = packet_length;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static log_entry_type_t
|
|
|
|
busmaster_parse(FILE_T fh, busmaster_state_t *state, int *err, char **err_info)
|
|
|
|
{
|
|
|
|
gboolean ok;
|
|
|
|
gint64 seek_off;
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: Running busmaster file decoder\n", G_STRFUNC);
|
|
|
|
|
|
|
|
state->fh = fh;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (file_eof(fh))
|
|
|
|
return LOG_ENTRY_EOF;
|
|
|
|
|
|
|
|
seek_off = file_tell(fh);
|
|
|
|
busmaster_debug_printf("%s: Starting parser at offset %" PRIi64 "\n",
|
|
|
|
G_STRFUNC, seek_off);
|
|
|
|
state->file_bytes_read = 0;
|
|
|
|
ok = run_busmaster_parser(state, err, err_info);
|
|
|
|
|
|
|
|
/* Rewind the file to the offset we have finished parsing */
|
|
|
|
busmaster_debug_printf("%s: Rewinding to offset %" PRIi64 "\n",
|
|
|
|
G_STRFUNC, seek_off + state->file_bytes_read);
|
|
|
|
if (file_seek(fh, seek_off + state->file_bytes_read, SEEK_SET, err) == -1)
|
|
|
|
{
|
|
|
|
g_free(*err_info);
|
|
|
|
*err = errno;
|
|
|
|
*err_info = g_strdup(g_strerror(errno));
|
|
|
|
return LOG_ENTRY_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (ok && state->entry_type == LOG_ENTRY_NONE);
|
|
|
|
|
|
|
|
if (!ok)
|
|
|
|
return LOG_ENTRY_ERROR;
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: Success\n", G_STRFUNC);
|
|
|
|
|
|
|
|
return state->entry_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
wtap_open_return_val
|
|
|
|
busmaster_open(wtap *wth, int *err, char **err_info)
|
|
|
|
{
|
2020-04-13 21:39:32 +00:00
|
|
|
busmaster_state_t state = {0};
|
2019-06-27 18:20:02 +00:00
|
|
|
log_entry_type_t entry;
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: Trying to open with busmaster log reader\n",
|
|
|
|
G_STRFUNC);
|
|
|
|
|
|
|
|
/* Rewind to the beginning */
|
|
|
|
if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
|
|
|
|
return WTAP_OPEN_ERROR;
|
|
|
|
|
|
|
|
entry = busmaster_parse(wth->fh, &state, err, err_info);
|
|
|
|
|
|
|
|
g_free(*err_info);
|
|
|
|
*err_info = NULL;
|
|
|
|
*err = 0;
|
|
|
|
|
|
|
|
if (entry != LOG_ENTRY_HEADER)
|
|
|
|
return WTAP_OPEN_NOT_MINE;
|
|
|
|
|
|
|
|
/* Rewind to the beginning, so busmaster_read may read from the very beginning */
|
|
|
|
if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
|
|
|
|
return WTAP_OPEN_ERROR;
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: That's a busmaster log\n", G_STRFUNC);
|
|
|
|
|
|
|
|
wth->priv = NULL;
|
|
|
|
wth->subtype_close = busmaster_close;
|
|
|
|
wth->subtype_read = busmaster_read;
|
|
|
|
wth->subtype_seek_read = busmaster_seek_read;
|
2021-02-18 06:26:02 +00:00
|
|
|
wth->file_type_subtype = busmaster_file_type_subtype;
|
2019-06-27 18:20:02 +00:00
|
|
|
wth->file_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
|
|
|
|
wth->file_tsprec = WTAP_TSPREC_USEC;
|
|
|
|
|
|
|
|
return WTAP_OPEN_MINE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
busmaster_close(wtap *wth)
|
|
|
|
{
|
|
|
|
busmaster_debug_printf("%s\n", G_STRFUNC);
|
|
|
|
|
|
|
|
g_slist_free_full((GSList *)wth->priv, g_free);
|
|
|
|
wth->priv = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static busmaster_priv_t *
|
|
|
|
busmaster_find_priv_entry(void *priv, gint64 offset)
|
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
for (list = (GSList *)priv; list; list = g_slist_next(list))
|
|
|
|
{
|
|
|
|
busmaster_priv_t *entry = (busmaster_priv_t *)list->data;
|
|
|
|
|
|
|
|
if (((entry->file_end_offset == -1)
|
|
|
|
&& (g_slist_next(list) == NULL))
|
|
|
|
|| ((offset >= entry->file_start_offset)
|
|
|
|
&& (offset <= entry->file_end_offset)))
|
|
|
|
{
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
busmaster_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info,
|
|
|
|
gint64 *data_offset)
|
|
|
|
{
|
|
|
|
log_entry_type_t entry;
|
|
|
|
busmaster_state_t state;
|
|
|
|
busmaster_priv_t *priv_entry;
|
|
|
|
gboolean is_msg = FALSE;
|
|
|
|
gboolean is_ok = TRUE;
|
|
|
|
|
|
|
|
while (!is_msg && is_ok)
|
|
|
|
{
|
|
|
|
busmaster_debug_printf("%s: offset = %" PRIi64 "\n",
|
|
|
|
G_STRFUNC, file_tell(wth->fh));
|
|
|
|
|
|
|
|
if (file_eof(wth->fh))
|
|
|
|
{
|
|
|
|
busmaster_debug_printf("%s: End of file detected, nothing to do here\n",
|
|
|
|
G_STRFUNC);
|
|
|
|
*err = 0;
|
|
|
|
*err_info = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*data_offset = file_tell(wth->fh);
|
|
|
|
priv_entry = busmaster_find_priv_entry(wth->priv, *data_offset);
|
|
|
|
|
|
|
|
memset(&state, 0, sizeof(state));
|
|
|
|
if (priv_entry)
|
|
|
|
state.header = *priv_entry;
|
|
|
|
entry = busmaster_parse(wth->fh, &state, err, err_info);
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: analyzing output\n", G_STRFUNC);
|
|
|
|
switch (entry)
|
|
|
|
{
|
|
|
|
case LOG_ENTRY_EMPTY:
|
|
|
|
break;
|
|
|
|
case LOG_ENTRY_FOOTER_AND_HEADER:
|
|
|
|
case LOG_ENTRY_FOOTER:
|
|
|
|
priv_entry = (busmaster_priv_t *)g_slist_last((GSList *)wth->priv)->data;
|
|
|
|
if (!priv_entry)
|
|
|
|
{
|
|
|
|
*err = WTAP_ERR_BAD_FILE;
|
|
|
|
*err_info = g_strdup("Header is missing");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
priv_entry->file_end_offset = *data_offset;
|
|
|
|
if (entry == LOG_ENTRY_FOOTER)
|
|
|
|
break;
|
|
|
|
/* fall-through */
|
|
|
|
case LOG_ENTRY_HEADER:
|
|
|
|
if (state.header.protocol != PROTOCOL_CAN &&
|
|
|
|
state.header.protocol != PROTOCOL_J1939)
|
|
|
|
{
|
|
|
|
*err = WTAP_ERR_UNSUPPORTED;
|
|
|
|
*err_info = g_strdup("Unsupported protocol type");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wth->priv)
|
|
|
|
{
|
|
|
|
/* Check that the previous section has a footer */
|
|
|
|
priv_entry = (busmaster_priv_t *)g_slist_last((GSList *)wth->priv)->data;
|
|
|
|
|
|
|
|
if (priv_entry && priv_entry->file_end_offset == -1)
|
|
|
|
{
|
|
|
|
*err = WTAP_ERR_BAD_FILE;
|
|
|
|
*err_info = g_strdup("Footer is missing");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start a new section */
|
|
|
|
priv_entry = g_new(busmaster_priv_t, 1);
|
|
|
|
|
|
|
|
priv_entry[0] = state.header;
|
|
|
|
priv_entry->file_start_offset = file_tell(wth->fh);
|
|
|
|
priv_entry->file_end_offset = -1;
|
|
|
|
|
|
|
|
wth->priv = g_slist_append((GSList *)wth->priv, priv_entry);
|
|
|
|
break;
|
|
|
|
case LOG_ENTRY_MSG:
|
|
|
|
is_msg = TRUE;
|
|
|
|
priv_entry = busmaster_find_priv_entry(wth->priv, *data_offset);
|
|
|
|
is_ok = busmaster_gen_packet(rec, buf, priv_entry, &state.msg, err, err_info);
|
|
|
|
break;
|
|
|
|
case LOG_ENTRY_EOF:
|
|
|
|
case LOG_ENTRY_ERROR:
|
|
|
|
case LOG_ENTRY_NONE:
|
|
|
|
default:
|
|
|
|
is_ok = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: stopped at offset %" PRIi64 " with entry %d\n",
|
|
|
|
G_STRFUNC, file_tell(wth->fh), entry);
|
|
|
|
|
|
|
|
return is_ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
busmaster_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
|
|
|
|
Buffer *buf, int *err, gchar **err_info)
|
|
|
|
{
|
|
|
|
busmaster_priv_t *priv_entry;
|
2020-04-13 21:39:32 +00:00
|
|
|
busmaster_state_t state = {0};
|
2019-06-27 18:20:02 +00:00
|
|
|
log_entry_type_t entry;
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: offset = %" PRIi64 "\n", G_STRFUNC, seek_off);
|
|
|
|
|
|
|
|
priv_entry = busmaster_find_priv_entry(wth->priv, seek_off);
|
|
|
|
if (!priv_entry)
|
|
|
|
{
|
|
|
|
busmaster_debug_printf("%s: analyzing output\n", G_STRFUNC);
|
|
|
|
*err = WTAP_ERR_BAD_FILE;
|
|
|
|
*err_info = g_strdup("Malformed header");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
state.header = *priv_entry;
|
|
|
|
entry = busmaster_parse(wth->random_fh, &state, err, err_info);
|
|
|
|
|
|
|
|
busmaster_debug_printf("%s: analyzing output\n", G_STRFUNC);
|
|
|
|
|
|
|
|
if (entry == LOG_ENTRY_ERROR || entry == LOG_ENTRY_NONE)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (entry != LOG_ENTRY_MSG)
|
|
|
|
{
|
|
|
|
*err = WTAP_ERR_BAD_FILE;
|
|
|
|
*err_info = g_strdup("Failed to read a frame");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return busmaster_gen_packet(rec, buf, priv_entry, &state.msg, err, err_info);
|
|
|
|
}
|
|
|
|
|
wiretap: have file handlers advertise blocks and options supported.
Instead of a "supports name resolution" Boolean and bitflags for types of
comments supported, provide a list of block types that the file
type/subtype supports, with each block type having a list of options
supported. Indicate whether "supported" means "one instance" or
"multiple instances".
"Supports" doesn't just mean "can be written", it also means "could be
read".
Rename WTAP_BLOCK_IF_DESCRIPTION to WTAP_BLOCK_IF_ID_AND_INFO, to
indicate that it provides, in addition to information about the
interface, an ID (implicitly, in pcapng files, by its ordinal number)
that is associated with every packet in the file. Emphasize that in
comments - just because your capture file format can list the interfaces
on which a capture was done, that doesn't mean it supports this; it
doesn't do so if the file doesn't indicate, for every packet, on which
of those interfaces it was captured (I'm looking at *you*, Microsoft
Network Monitor...).
Use APIs to query that information to do what the "does this file
type/subtype support name resolution information", "does this file
type/subtype support all of these comment types", and "does this file
type/subtype support - and require - interface IDs" APIs did.
Provide backwards compatibility for Lua.
This allows us to eliminate the WTAP_FILE_TYPE_SUBTYPE_ values for IBM's
iptrace; do so.
2021-02-21 22:18:04 +00:00
|
|
|
static const struct supported_block_type busmaster_blocks_supported[] = {
|
|
|
|
/*
|
|
|
|
* We support packet blocks, with no comments or other options.
|
|
|
|
*/
|
|
|
|
{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
|
|
|
|
};
|
|
|
|
|
2021-02-18 06:26:02 +00:00
|
|
|
static const struct file_type_subtype_info busmaster_info = {
|
|
|
|
"BUSMASTER log file", "busmaster", "log", NULL,
|
wiretap: have file handlers advertise blocks and options supported.
Instead of a "supports name resolution" Boolean and bitflags for types of
comments supported, provide a list of block types that the file
type/subtype supports, with each block type having a list of options
supported. Indicate whether "supported" means "one instance" or
"multiple instances".
"Supports" doesn't just mean "can be written", it also means "could be
read".
Rename WTAP_BLOCK_IF_DESCRIPTION to WTAP_BLOCK_IF_ID_AND_INFO, to
indicate that it provides, in addition to information about the
interface, an ID (implicitly, in pcapng files, by its ordinal number)
that is associated with every packet in the file. Emphasize that in
comments - just because your capture file format can list the interfaces
on which a capture was done, that doesn't mean it supports this; it
doesn't do so if the file doesn't indicate, for every packet, on which
of those interfaces it was captured (I'm looking at *you*, Microsoft
Network Monitor...).
Use APIs to query that information to do what the "does this file
type/subtype support name resolution information", "does this file
type/subtype support all of these comment types", and "does this file
type/subtype support - and require - interface IDs" APIs did.
Provide backwards compatibility for Lua.
This allows us to eliminate the WTAP_FILE_TYPE_SUBTYPE_ values for IBM's
iptrace; do so.
2021-02-21 22:18:04 +00:00
|
|
|
FALSE, BLOCKS_SUPPORTED(busmaster_blocks_supported),
|
2021-02-18 06:26:02 +00:00
|
|
|
NULL, NULL, NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
void register_busmaster(void)
|
|
|
|
{
|
2021-02-24 03:10:35 +00:00
|
|
|
busmaster_file_type_subtype = wtap_register_file_type_subtype(&busmaster_info);
|
2021-02-18 06:26:02 +00:00
|
|
|
}
|
|
|
|
|
2019-06-27 18:20:02 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
|
|
*/
|