forked from osmocom/wireshark
From Fred Fierling (bug 3486):
Added support for Daintree's Sensor Network Analyzer capture files. svn path=/trunk/; revision=28463
This commit is contained in:
parent
905b8d0b2d
commit
5fa6b90f6b
4
AUTHORS
4
AUTHORS
|
@ -2855,6 +2855,10 @@ Benjamin Tse <benjamin_tse@agilent.com> {
|
|||
Overlapped pipe I/O for dumpcap under Windows
|
||||
}
|
||||
|
||||
Fred Fierling <fff [AT] exegin.com> {
|
||||
Daintree's Sensor Network Analyzer file support
|
||||
}
|
||||
|
||||
and by:
|
||||
|
||||
Pavel Roskin <proski [AT] gnu.org>
|
||||
|
|
|
@ -40,6 +40,7 @@ NONGENERATED_C_FILES = \
|
|||
commview.c \
|
||||
cosine.c \
|
||||
csids.c \
|
||||
daintree-sna.c \
|
||||
dbs-etherwatch.c \
|
||||
dct3trace.c \
|
||||
erf.c \
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
/* daintree_sna.c
|
||||
* Routines for opening .dcf capture files created by Daintree's
|
||||
* Sensor Network Analyzer for 802.15.4 radios
|
||||
* Copyright 2009, Exegin Technologies Limited <fff@exegin.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* Started with packetlogger.c as a template, but little packetlogger code
|
||||
* remains. Borrowed many snippets from dbs-etherwatch.c, the
|
||||
* daintree_sna_hex_char function having the largest chunk.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This module reads capture files saved by Daintree's Sensor Network Analyzer.
|
||||
* Daintree captures are plain text files with a two line header,
|
||||
* followed by packet records, one per line, with whitespace separated fields
|
||||
* consisting of: packet number, time, bytes of capture data, capture data,
|
||||
* unknown, unknown, signal strength?, unknown, etc, and terminated with CRLF.
|
||||
*/
|
||||
|
||||
/* Example capture file:
|
||||
|
||||
#Format=4
|
||||
# SNA v2.2.0.4 SUS:20090709 ACT:819705
|
||||
1 1233783799.326400 10 030809ffffffff07ffff 42 1 -69 25 2 0 1 32767
|
||||
2 1233783799.477440 5 02000bffff 110 1 -44 25 6 0 1 32767
|
||||
3 1233783799.809920 5 020013ffff 107 1 -45 25 43 0 1 3276
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "wtap.h"
|
||||
#include "wtap-int.h"
|
||||
#include "buffer.h"
|
||||
#include "file_wrappers.h"
|
||||
#include "daintree-sna.h"
|
||||
|
||||
typedef struct daintree_sna_header {
|
||||
guint32 len;
|
||||
guint64 ts;
|
||||
} daintree_sna_header_t;
|
||||
|
||||
#define DAINTREE_SNA_HEADER_SIZE 2
|
||||
#define FCS_LENGTH 2
|
||||
|
||||
static const char daintree_magic_text[] =
|
||||
{ '#', 'F', 'o', 'r', 'm', 'a', 't', '=' };
|
||||
|
||||
#define DAINTREE_MAGIC_TEXT_SIZE (sizeof daintree_magic_text)
|
||||
#define DAINTREE_MAX_LINE_SIZE 512
|
||||
#define COMMENT_LINE daintree_magic_text[0]
|
||||
|
||||
static char readLine[DAINTREE_MAX_LINE_SIZE];
|
||||
static char seekLine[DAINTREE_MAX_LINE_SIZE];
|
||||
static char readData[DAINTREE_MAX_LINE_SIZE/2];
|
||||
static char seekData[DAINTREE_MAX_LINE_SIZE/2];
|
||||
|
||||
static gboolean daintree_sna_read(wtap *wth, int *err, gchar **err_info _U_,
|
||||
gint64 *data_offset);
|
||||
|
||||
static gboolean daintree_sna_seek_read(wtap *wth, gint64 seek_off,
|
||||
union wtap_pseudo_header *pseudo_header _U_,
|
||||
guchar *pd, int len, int *err,
|
||||
gchar **err_info _U_);
|
||||
|
||||
static guint daintree_sna_hex_char(guchar *str, int *err);
|
||||
|
||||
/* Open a file and determine if it's a Daintree file */
|
||||
int daintree_sna_open(wtap *wth, int *err _U_, gchar **err_info _U_)
|
||||
{
|
||||
guint i;
|
||||
|
||||
/* get first line of file header */
|
||||
if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) return 0;
|
||||
wth->data_offset += strlen(readLine);
|
||||
|
||||
/* check magic text */
|
||||
i = 0;
|
||||
while (i < DAINTREE_MAGIC_TEXT_SIZE) {
|
||||
if (readLine[i] != daintree_magic_text[i]) return 0; /* not daintree format */
|
||||
i++;
|
||||
}
|
||||
|
||||
/* read second header line */
|
||||
if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) return 0;
|
||||
wth->data_offset += strlen(readLine);
|
||||
if (readLine[0] != COMMENT_LINE) return 0; /* daintree files have a two line header */
|
||||
|
||||
/* set up the pointers to the handlers for this file type */
|
||||
wth->subtype_read = daintree_sna_read;
|
||||
wth->subtype_seek_read = daintree_sna_seek_read;
|
||||
|
||||
/* set up for file type */
|
||||
wth->file_type = WTAP_FILE_DAINTREE_SNA;
|
||||
wth->file_encap = WTAP_ENCAP_IEEE802_15_4;
|
||||
wth->tsprecision = WTAP_FILE_TSPREC_USEC;
|
||||
|
||||
return 1; /* it's a Daintree file */
|
||||
}
|
||||
|
||||
/* Read the capture file sequentially
|
||||
* Wireshark scans the file with sequential reads during preview and initial display. */
|
||||
static gboolean
|
||||
daintree_sna_read(wtap *wth, int *err, gchar **err_info _U_, gint64 *data_offset)
|
||||
{
|
||||
guint64 seconds;
|
||||
|
||||
*data_offset = wth->data_offset;
|
||||
|
||||
/* we've only seen file header lines starting with '#', but
|
||||
* if others appear in the file, they are tossed */
|
||||
do {
|
||||
if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh) == NULL) {
|
||||
*err = file_error(wth->fh);
|
||||
return FALSE; /* all done */
|
||||
}
|
||||
wth->data_offset += strlen(readLine);
|
||||
} while (readLine[0] == COMMENT_LINE);
|
||||
|
||||
/* parse one line of capture data */
|
||||
if (sscanf(readLine, "%*s %" G_GINT64_MODIFIER "u.%u %u %s",
|
||||
&seconds, &wth->phdr.ts.nsecs,
|
||||
&wth->phdr.len, readData) != 4) {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup("daintree_sna: invalid read record");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wth->phdr.ts.secs = (time_t) seconds;
|
||||
wth->phdr.ts.nsecs *= 1000; /* convert mS to nS */
|
||||
|
||||
/* convert packet data from ASCII string to hex, sanity-check its length against what we assume is the
|
||||
* packet length field, write data to frame buffer */
|
||||
if ((wth->phdr.caplen = daintree_sna_hex_char(readData, err)) > FCS_LENGTH) {
|
||||
if (wth->phdr.caplen <= wth->phdr.len) {
|
||||
/* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
|
||||
wth->phdr.caplen -= FCS_LENGTH;
|
||||
buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
|
||||
memcpy(buffer_start_ptr(wth->frame_buffer), readData, wth->phdr.caplen);
|
||||
} else {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup_printf("daintree_sna: capture length (%d) > packet length (%d)",
|
||||
wth->phdr.caplen, wth->phdr.len);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup("daintree_sna: invalid packet data");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read the capture file randomly
|
||||
* Wireshark opens the capture file for random access when displaying user-selected packets */
|
||||
static gboolean
|
||||
daintree_sna_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header
|
||||
*pseudo_header _U_, guchar *pd, int len, int *err,
|
||||
gchar **err_info _U_)
|
||||
{
|
||||
guint pkt_len;
|
||||
|
||||
if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
|
||||
return FALSE;
|
||||
|
||||
/* It appears only file header lines start with '#', but
|
||||
* if we find any others, we toss them */
|
||||
do {
|
||||
if (file_gets(seekLine, DAINTREE_MAX_LINE_SIZE, wth->random_fh) == NULL) {
|
||||
*err = file_error(wth->random_fh);
|
||||
return FALSE; /* all done */
|
||||
}
|
||||
} while (seekLine[0] == COMMENT_LINE);
|
||||
|
||||
/* ignore all but packet data, since the sequential read pass stored everything else */
|
||||
if (sscanf(seekLine, "%*s %*u.%*u %*u %s", seekData) != 1) {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup("daintree_sna: corrupted seek record");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* convert packet data from ASCII hex string to guchar */
|
||||
if ((pkt_len = daintree_sna_hex_char(seekData, err)) <= FCS_LENGTH) {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup("daintree_sna: corrupted packet data");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pkt_len -= FCS_LENGTH; /* remove padded bytes that Daintree stores instead of FCS */
|
||||
|
||||
if (pkt_len == (guint) len) {
|
||||
/* move to frame buffer for dissection */
|
||||
memcpy(pd, seekData, pkt_len);
|
||||
} else {
|
||||
*err = WTAP_ERR_BAD_RECORD;
|
||||
*err_info = g_strdup("daintree-sna: corrupted frame");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Convert an ASCII hex string to guchar */
|
||||
static guint
|
||||
daintree_sna_hex_char(guchar *str, int *err _U_) {
|
||||
guint bytes;
|
||||
guchar *p;
|
||||
|
||||
p = str; /* overlay source buffer */
|
||||
bytes = 0;
|
||||
/* convert hex string to guchar */
|
||||
while(*str) {
|
||||
if (!isxdigit((guchar)*str)) return 0;
|
||||
/* most significant nibble */
|
||||
if(isdigit((guchar)*str)) {
|
||||
*p = (*str - '0') << 4;
|
||||
} else {
|
||||
*p = ((tolower(*str) - 'a') + 10) << 4;
|
||||
}
|
||||
str++;
|
||||
|
||||
if (!isxdigit((guchar)*str)) return 0;
|
||||
/* least significant nibble */
|
||||
if(isdigit((guchar)*str)) {
|
||||
*p += *str - '0';
|
||||
} else {
|
||||
*p += (tolower(*str) - 'a') + 10;
|
||||
}
|
||||
str++;
|
||||
|
||||
/* next byte in buffer */
|
||||
p++;
|
||||
bytes++;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* daintree-sna.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* 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 __DAINTREE_SNA_H__
|
||||
#define __DAINTREE_SNA_H__
|
||||
|
||||
int daintree_sna_open(wtap *wth, int *err, gchar **err_info _U_);
|
||||
|
||||
#endif /* __DAINTREE_SNA_H__ */
|
||||
|
|
@ -80,6 +80,7 @@
|
|||
#include "tnef.h"
|
||||
#include "dct3trace.h"
|
||||
#include "packetlogger.h"
|
||||
#include "daintree-sna.h"
|
||||
|
||||
|
||||
/* The open_file_* routines should return:
|
||||
|
@ -128,6 +129,7 @@ static wtap_open_routine_t open_routines_base[] = {
|
|||
mpeg_open,
|
||||
tnef_open,
|
||||
dct3trace_open,
|
||||
daintree_sna_open,
|
||||
/* Files that don't have magic bytes at a fixed location,
|
||||
* but that instead require a heuristic of some sort to
|
||||
* identify them. This includes the ASCII trace files that
|
||||
|
@ -602,7 +604,10 @@ static const struct file_type_info dump_open_table_base[] = {
|
|||
{ "Gammu DCT3 trace", "dct3trace", "*.xml", NULL, FALSE, NULL, NULL },
|
||||
|
||||
/* WTAP_FILE_PACKETLOGGER */
|
||||
{ "PacketLogger", "pklg", "*.pklg", NULL, FALSE, NULL, NULL }
|
||||
{ "PacketLogger", "pklg", "*.pklg", NULL, FALSE, NULL, NULL },
|
||||
|
||||
/* WTAP_FILE_DAINTREE_SNA */
|
||||
{ "Daintree SNA", "dsna", "*.dcf", NULL, FALSE, NULL, NULL }
|
||||
};
|
||||
|
||||
gint wtap_num_file_types = sizeof(dump_open_table_base) / sizeof(struct file_type_info);
|
||||
|
|
|
@ -271,6 +271,7 @@ extern "C" {
|
|||
#define WTAP_FILE_TNEF 53
|
||||
#define WTAP_FILE_DCT3TRACE 54
|
||||
#define WTAP_FILE_PACKETLOGGER 55
|
||||
#define WTAP_FILE_DAINTREE_SNA 56
|
||||
|
||||
#define WTAP_NUM_FILE_TYPES wtap_get_num_file_types()
|
||||
|
||||
|
|
Loading…
Reference in New Issue