/* catapult_dct2000.c
- *
- * $Id$
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
*
* 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 <errno.h>
#include <string.h>
#include <stdlib.h>
-#include <ctype.h>
#include "wtap-int.h"
#include "file_wrappers.h"
-#include "buffer.h"
#include "catapult_dct2000.h"
static gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
static gboolean catapult_dct2000_seek_read(wtap *wth, gint64 seek_off,
- union wtap_pseudo_header *pseudo_header,
- guchar *pd, int length,
- int *err, gchar **err_info);
+ struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err,
+ gchar **err_info);
static void catapult_dct2000_close(wtap *wth);
static gboolean catapult_dct2000_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header,
- const guchar *pd, int *err);
+ const guint8 *pd, int *err, gchar **err_info);
/************************************************************/
/* Private helper functions */
static gboolean read_new_line(FILE_T fh, gint64 *offset, gint *length,
- gchar *buf, size_t bufsize);
+ gchar *buf, size_t bufsize, int *err,
+ gchar **err_info);
static gboolean parse_line(char *linebuff, gint line_length,
gint *seconds, gint *useconds,
long *before_time_offset, long *after_time_offset,
long *data_offset,
gint *data_chars,
packet_direction_t *direction,
- int *encap, int *is_comment,
+ int *encap, int *is_comment, int *is_sprint,
gchar *aal_header_chars,
gchar *context_name, guint8 *context_portp,
gchar *protocol_name, gchar *variant_name,
gchar *outhdr_name);
-static int write_stub_header(guchar *frame_buffer, char *timestamp_string,
- packet_direction_t direction, int encap,
- gchar *context_name, guint8 context_port,
- gchar *protocol_name, gchar *variant_name,
- gchar *outhdr_name);
-static guchar hex_from_char(gchar c);
-static gchar char_from_hex(guchar hex);
-
-static void set_pseudo_header_info(wtap *wth,
- int pkt_encap,
- gint64 file_offset,
- union wtap_pseudo_header *pseudo_header,
- packet_direction_t direction,
- gchar *aal_header_chars);
+static gboolean process_parsed_line(wtap *wth,
+ dct2000_file_externals_t *file_externals,
+ struct wtap_pkthdr *phdr,
+ Buffer *buf, gint64 file_offset,
+ char *linebuff, long dollar_offset,
+ int seconds, int useconds,
+ gchar *timestamp_string,
+ packet_direction_t direction, int encap,
+ gchar *context_name, guint8 context_port,
+ gchar *protocol_name, gchar *variant_name,
+ gchar *outhdr_name, gchar *aal_header_chars,
+ gboolean is_comment, int data_chars,
+ int *err, gchar **err_info);
+static guint8 hex_from_char(gchar c);
+static void prepare_hex_byte_from_chars_table(void);
+static guint8 hex_byte_from_chars(gchar *c);
+static gchar char_from_hex(guint8 hex);
+
static void set_aal_info(union wtap_pseudo_header *pseudo_header,
packet_direction_t direction,
gchar *aal_header_chars);
/********************************************/
/* Open file (for reading) */
/********************************************/
-int catapult_dct2000_open(wtap *wth, int *err, gchar **err_info _U_)
+wtap_open_return_val
+catapult_dct2000_open(wtap *wth, int *err, gchar **err_info)
{
gint64 offset = 0;
time_t timestamp;
guint32 usecs;
gint firstline_length = 0;
dct2000_file_externals_t *file_externals;
- gchar linebuff[MAX_LINE_LENGTH];
+ static gchar linebuff[MAX_LINE_LENGTH];
+ static gboolean hex_byte_table_values_set = FALSE;
/* Clear errno before reading from the file */
errno = 0;
/********************************************************************/
/* First line needs to contain at least as many characters as magic */
- read_new_line(wth->fh, &offset, &firstline_length, linebuff,
- sizeof linebuff);
+ if (!read_new_line(wth->fh, &offset, &firstline_length, linebuff,
+ sizeof linebuff, err, err_info)) {
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
if (((size_t)firstline_length < strlen(catapult_dct2000_magic)) ||
firstline_length >= MAX_FIRST_LINE_LENGTH) {
- return 0;
+ return WTAP_OPEN_NOT_MINE;
}
/* This file is not for us if it doesn't match our signature */
if (memcmp(catapult_dct2000_magic, linebuff, strlen(catapult_dct2000_magic)) != 0) {
- return 0;
+ return WTAP_OPEN_NOT_MINE;
}
+ /* Make sure table is ready for use */
+ if (!hex_byte_table_values_set) {
+ prepare_hex_byte_from_chars_table();
+ hex_byte_table_values_set = TRUE;
+ }
/*********************************************************************/
/* Need entry in file_externals table */
/* Allocate a new file_externals structure for this file */
- file_externals = g_malloc(sizeof(dct2000_file_externals_t));
+ file_externals = g_new(dct2000_file_externals_t,1);
memset((void*)file_externals, '\0', sizeof(dct2000_file_externals_t));
/* Copy this first line into buffer so could write out later */
/* Second line contains file timestamp */
/* Store this offset in in file_externals */
- read_new_line(wth->fh, &offset, &(file_externals->secondline_length),
- linebuff, sizeof linebuff);
+ if (!read_new_line(wth->fh, &offset, &(file_externals->secondline_length),
+ linebuff, sizeof linebuff, err, err_info)) {
+ g_free(file_externals);
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
+ }
if ((file_externals->secondline_length >= MAX_TIMESTAMP_LINE_LENGTH) ||
(!get_file_time_stamp(linebuff, ×tamp, &usecs))) {
/* Give up if file time line wasn't valid */
g_free(file_externals);
- return 0;
+ return WTAP_OPEN_NOT_MINE;
}
/* Fill in timestamp */
/* File is for us. Fill in details so packets can be read */
/* Set our file type */
- wth->file_type = WTAP_FILE_CATAPULT_DCT2000;
+ wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000;
/* Use our own encapsulation to send all packets to our stub dissector */
wth->file_encap = WTAP_ENCAP_CATAPULT_DCT2000;
wth->subtype_close = catapult_dct2000_close;
/* Choose microseconds (have 4 decimal places...) */
- wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+ wth->file_tsprec = WTAP_TSPREC_USEC;
/***************************************************************/
wth->priv = (void*)file_externals;
*err = errno;
- return 1;
+ return WTAP_OPEN_MINE;
}
+/* Ugly, but much faster than using g_snprintf! */
+static void write_timestamp_string(char *timestamp_string, int secs, int tenthousandths)
+{
+ int idx = 0;
+
+ /* Secs */
+ if (secs < 10) {
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else if (secs < 100) {
+ timestamp_string[idx++] = ( secs / 10) + '0';
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else if (secs < 1000) {
+ timestamp_string[idx++] = ((secs) / 100) + '0';
+ timestamp_string[idx++] = ((secs % 100)) / 10 + '0';
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else if (secs < 10000) {
+ timestamp_string[idx++] = ((secs) / 1000) + '0';
+ timestamp_string[idx++] = ((secs % 1000)) / 100 + '0';
+ timestamp_string[idx++] = ((secs % 100)) / 10 + '0';
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else if (secs < 100000) {
+ timestamp_string[idx++] = ((secs) / 10000) + '0';
+ timestamp_string[idx++] = ((secs % 10000)) / 1000 + '0';
+ timestamp_string[idx++] = ((secs % 1000)) / 100 + '0';
+ timestamp_string[idx++] = ((secs % 100)) / 10 + '0';
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else if (secs < 1000000) {
+ timestamp_string[idx++] = ((secs) / 100000) + '0';
+ timestamp_string[idx++] = ((secs % 100000)) / 10000 + '0';
+ timestamp_string[idx++] = ((secs % 10000)) / 1000 + '0';
+ timestamp_string[idx++] = ((secs % 1000)) / 100 + '0';
+ timestamp_string[idx++] = ((secs % 100)) / 10 + '0';
+ timestamp_string[idx++] = ((secs % 10)) + '0';
+ }
+ else {
+ g_snprintf(timestamp_string, MAX_TIMESTAMP_LEN, "%d.%04d", secs, tenthousandths);
+ return;
+ }
+
+ timestamp_string[idx++] = '.';
+ timestamp_string[idx++] = ( tenthousandths / 1000) + '0';
+ timestamp_string[idx++] = ((tenthousandths % 1000) / 100) + '0';
+ timestamp_string[idx++] = ((tenthousandths % 100) / 10) + '0';
+ timestamp_string[idx++] = ((tenthousandths % 10)) + '0';
+ timestamp_string[idx++] = '\0';
+}
/**************************************************/
/* Read packet function. */
/* Look for and read the next usable packet */
/* - return TRUE and details if found */
/**************************************************/
-gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info _U_,
- gint64 *data_offset)
+static gboolean
+catapult_dct2000_read(wtap *wth, int *err, gchar **err_info,
+ gint64 *data_offset)
{
- gint64 offset = wth->data_offset;
+ gint64 offset = file_tell(wth->fh);
long dollar_offset, before_time_offset, after_time_offset;
packet_direction_t direction;
int encap;
dct2000_file_externals_t *file_externals =
(dct2000_file_externals_t*)wth->priv;
- /* There *has* to be an entry for this wth */
- if (!file_externals) {
- return FALSE;
- }
-
/* Search for a line containing a usable packet */
while (1) {
int line_length, seconds, useconds, data_chars;
int is_comment = FALSE;
+ int is_sprint = FALSE;
gint64 this_offset = offset;
- gchar linebuff[MAX_LINE_LENGTH+1];
+ static gchar linebuff[MAX_LINE_LENGTH+1];
gchar aal_header_chars[AAL_HEADER_CHARS];
gchar context_name[MAX_CONTEXT_NAME];
- guint8 context_port;
+ guint8 context_port = 0;
gchar protocol_name[MAX_PROTOCOL_NAME+1];
gchar variant_name[MAX_VARIANT_DIGITS+1];
gchar outhdr_name[MAX_OUTHDR_NAME+1];
/* Are looking for first packet after 2nd line */
- if (wth->data_offset == 0) {
+ if (file_tell(wth->fh) == 0) {
this_offset += (file_externals->firstline_length+1+
file_externals->secondline_length+1);
}
- /* Clear errno before reading from the file */
- errno = 0;
-
/* Read a new line from file into linebuff */
- if (read_new_line(wth->fh, &offset, &line_length, linebuff,
- sizeof linebuff) == FALSE) {
- /* Get out if no more lines can be read */
+ if (!read_new_line(wth->fh, &offset, &line_length, linebuff,
+ sizeof linebuff, err, err_info)) {
+ if (*err != 0)
+ return FALSE; /* error */
+ /* No more lines can be read, so quit. */
break;
}
if (parse_line(linebuff, line_length, &seconds, &useconds,
&before_time_offset, &after_time_offset,
&dollar_offset,
- &data_chars, &direction, &encap, &is_comment,
+ &data_chars, &direction, &encap, &is_comment, &is_sprint,
aal_header_chars,
context_name, &context_port,
protocol_name, variant_name, outhdr_name)) {
- guchar *frame_buffer;
- int n;
- int stub_offset = 0;
line_prefix_info_t *line_prefix_info;
char timestamp_string[MAX_TIMESTAMP_LEN+1];
gint64 *pkey = NULL;
- g_snprintf(timestamp_string, MAX_TIMESTAMP_LEN, "%d.%04d", seconds, useconds/100);
-
- /* All packets go to Catapult DCT2000 stub dissector */
- wth->phdr.pkt_encap = WTAP_ENCAP_CATAPULT_DCT2000;
+ write_timestamp_string(timestamp_string, seconds, useconds/100);
/* Set data_offset to the beginning of the line we're returning.
This will be the seek_off parameter when this frame is re-read.
*/
*data_offset = this_offset;
- /* This is the position in the file where the next _read() will be called from */
- wth->data_offset = this_offset + line_length + 1;
-
- /* Fill in timestamp (capture base + packet offset) */
- wth->phdr.ts.secs = file_externals->start_secs + seconds;
- if ((file_externals->start_usecs + useconds) >= 1000000) {
- wth->phdr.ts.secs++;
- }
- wth->phdr.ts.nsecs =
- ((file_externals->start_usecs + useconds) % 1000000) *1000;
-
- /* Get buffer pointer ready */
- buffer_assure_space(wth->frame_buffer,
- strlen(context_name)+1 + /* Context name */
- 1 + /* port */
- strlen(timestamp_string)+1 + /* timestamp */
- strlen(variant_name)+1 + /* variant */
- strlen(outhdr_name)+1 + /* outhdr */
- strlen(protocol_name)+1 + /* Protocol name */
- 1 + /* direction */
- 1 + /* encap */
- is_comment ? data_chars : (data_chars/2));
- frame_buffer = buffer_start_ptr(wth->frame_buffer);
-
-
- /*********************/
- /* Write stub header */
- stub_offset = write_stub_header(frame_buffer, timestamp_string,
- direction, encap, context_name,
- context_port,
- protocol_name, variant_name,
- outhdr_name);
-
- /* Binary data length is half bytestring length + stub header */
- wth->phdr.len = stub_offset + (is_comment ? data_chars : (data_chars/2));
- wth->phdr.caplen = stub_offset + (is_comment ? data_chars : (data_chars/2));
-
-
- if (!is_comment) {
- /****************************************************/
- /* Copy data into buffer, converting from ascii hex */
- for (n=0; n <= data_chars; n+=2) {
- frame_buffer[stub_offset + n/2] =
- (hex_from_char(linebuff[dollar_offset+n]) << 4) |
- hex_from_char(linebuff[dollar_offset+n+1]);
- }
- }
- else {
- /***********************************************************/
- /* Copy packet data into buffer, just copying ascii chars */
- for (n=0; n <= data_chars; n++) {
- frame_buffer[stub_offset + n] = linebuff[dollar_offset+n];
- }
- }
+ if (!process_parsed_line(wth, file_externals,
+ &wth->phdr,
+ wth->frame_buffer, this_offset,
+ linebuff, dollar_offset,
+ seconds, useconds,
+ timestamp_string,
+ direction, encap,
+ context_name, context_port,
+ protocol_name, variant_name,
+ outhdr_name, aal_header_chars,
+ is_comment, data_chars,
+ err, err_info))
+ return FALSE;
/* Store the packet prefix in the hash table */
- line_prefix_info = g_malloc(sizeof(line_prefix_info_t));
+ line_prefix_info = g_new(line_prefix_info_t,1);
/* Create and use buffer for contents before time */
- line_prefix_info->before_time = g_malloc(before_time_offset+2);
- g_strlcpy(line_prefix_info->before_time, linebuff, before_time_offset+1);
- line_prefix_info->before_time[before_time_offset+1] = '\0';
+ line_prefix_info->before_time = (gchar *)g_malloc(before_time_offset+1);
+ memcpy(line_prefix_info->before_time, linebuff, before_time_offset);
+ line_prefix_info->before_time[before_time_offset] = '\0';
/* Create and use buffer for contents before time.
Do this only if it doesn't correspond to " l ", which is by far the most
}
else {
/* Allocate & write buffer for line between timestamp and data */
- line_prefix_info->after_time = g_malloc(dollar_offset - after_time_offset);
- g_strlcpy(line_prefix_info->after_time, linebuff+after_time_offset,
- dollar_offset - after_time_offset);
+ line_prefix_info->after_time = (gchar *)g_malloc(dollar_offset - after_time_offset);
+ memcpy(line_prefix_info->after_time, linebuff+after_time_offset, dollar_offset - after_time_offset);
line_prefix_info->after_time[dollar_offset - after_time_offset-1] = '\0';
}
/* Add packet entry into table */
- pkey = g_malloc(sizeof(*pkey));
+ pkey = (gint64 *)g_malloc(sizeof(*pkey));
*pkey = this_offset;
g_hash_table_insert(file_externals->packet_prefix_table, pkey, line_prefix_info);
- /* Set pseudo-header if necessary */
- set_pseudo_header_info(wth, encap, this_offset, &wth->pseudo_header,
- direction, aal_header_chars);
-
/* OK, we have packet details to return */
- *err = errno;
return TRUE;
}
}
/* No packet details to return... */
- *err = errno;
return FALSE;
}
/**************************************************/
static gboolean
catapult_dct2000_seek_read(wtap *wth, gint64 seek_off,
- union wtap_pseudo_header *pseudo_header, guchar *pd,
- int length, int *err, gchar **err_info)
+ struct wtap_pkthdr *phdr, Buffer *buf,
+ int *err, gchar **err_info)
{
- gint64 offset = wth->data_offset;
+ gint64 offset = 0;
+ int length;
long dollar_offset, before_time_offset, after_time_offset;
- gchar linebuff[MAX_LINE_LENGTH+1];
+ static gchar linebuff[MAX_LINE_LENGTH+1];
gchar aal_header_chars[AAL_HEADER_CHARS];
gchar context_name[MAX_CONTEXT_NAME];
- guint8 context_port;
+ guint8 context_port = 0;
gchar protocol_name[MAX_PROTOCOL_NAME+1];
gchar variant_name[MAX_VARIANT_DIGITS+1];
gchar outhdr_name[MAX_OUTHDR_NAME+1];
int is_comment = FALSE;
+ int is_sprint = FALSE;
packet_direction_t direction;
int encap;
int seconds, useconds, data_chars;
+ /* Get wtap external structure for this wtap */
+ dct2000_file_externals_t *file_externals =
+ (dct2000_file_externals_t*)wth->priv;
+
/* Reset errno */
*err = errno = 0;
}
/* Re-read whole line (this really should succeed) */
- if (read_new_line(wth->random_fh, &offset, &length, linebuff,
- sizeof linebuff) == FALSE) {
+ if (!read_new_line(wth->random_fh, &offset, &length, linebuff,
+ sizeof linebuff, err, err_info)) {
return FALSE;
}
if (parse_line(linebuff, length, &seconds, &useconds,
&before_time_offset, &after_time_offset,
&dollar_offset,
- &data_chars, &direction, &encap, &is_comment,
+ &data_chars, &direction, &encap, &is_comment, &is_sprint,
aal_header_chars,
context_name, &context_port,
protocol_name, variant_name, outhdr_name)) {
- int n;
- int stub_offset = 0;
char timestamp_string[MAX_TIMESTAMP_LEN+1];
- g_snprintf(timestamp_string, MAX_TIMESTAMP_LEN, "%d.%04d", seconds, useconds/100);
-
- /* Make sure all packets go to catapult dct2000 dissector */
- wth->phdr.pkt_encap = WTAP_ENCAP_CATAPULT_DCT2000;
-
- /*********************/
- /* Write stub header */
- stub_offset = write_stub_header(pd, timestamp_string,
- direction, encap, context_name,
- context_port,
- protocol_name, variant_name,
- outhdr_name);
-
-
- if (!is_comment) {
- /***********************************************************/
- /* Copy packet data into buffer, converting from ascii hex */
- for (n=0; n <= data_chars; n+=2) {
- pd[stub_offset + n/2] = (hex_from_char(linebuff[dollar_offset+n]) << 4) |
- hex_from_char(linebuff[dollar_offset+n+1]);
- }
- }
- else {
- /***********************************************************/
- /* Copy packet data into buffer, just copying ascii chars */
- for (n=0; n <= data_chars; n++) {
- pd[stub_offset+n] = linebuff[dollar_offset+n];
- }
- }
-
- /* Set packet pseudo-header if necessary */
- set_pseudo_header_info(wth, encap, seek_off, pseudo_header, direction,
- aal_header_chars);
+ write_timestamp_string(timestamp_string, seconds, useconds/100);
+
+ if (!process_parsed_line(wth, file_externals,
+ phdr, buf, seek_off,
+ linebuff, dollar_offset,
+ seconds, useconds,
+ timestamp_string,
+ direction, encap,
+ context_name, context_port,
+ protocol_name, variant_name,
+ outhdr_name, aal_header_chars,
+ is_comment, data_chars,
+ err, err_info))
+ return FALSE;
*err = errno = 0;
return TRUE;
/***************************************************************************/
/* Free dct2000-specific capture info from file that was open for reading */
/***************************************************************************/
-void catapult_dct2000_close(wtap *wth)
+static void
+catapult_dct2000_close(wtap *wth)
{
/* Get externals for this file */
dct2000_file_externals_t *file_externals =
(dct2000_file_externals_t*)wth->priv;
- /* The entry *has* to be found */
- if (!file_externals) {
- return;
- }
-
/* Free up its line prefix values */
g_hash_table_foreach_remove(file_externals->packet_prefix_table,
free_line_prefix_info, NULL);
/***************************/
typedef struct {
- gboolean first_packet_written;
- struct wtap_nstime start_time;
+ gboolean first_packet_written;
+ nstime_t start_time;
} dct2000_dump_t;
/*****************************************************/
/* The file that we are writing to has been opened. */
/* Set other dump callbacks. */
/*****************************************************/
-gboolean catapult_dct2000_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err _U_)
+gboolean
+catapult_dct2000_dump_open(wtap_dumper *wdh, int *err _U_)
{
/* Fill in other dump callbacks */
wdh->subtype_write = catapult_dct2000_dump;
/* Respond to queries about which encap types we support */
/* writing to. */
/*********************************************************/
-int catapult_dct2000_dump_can_write_encap(int encap)
+int
+catapult_dct2000_dump_can_write_encap(int encap)
{
switch (encap) {
case WTAP_ENCAP_CATAPULT_DCT2000:
default:
/* But don't write to any other formats... */
- return WTAP_ERR_UNSUPPORTED_ENCAP;
+ return WTAP_ERR_UNWRITABLE_ENCAP;
}
}
/* Write a single packet out to the file */
/*****************************************/
-gboolean catapult_dct2000_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header,
- const guchar *pd, int *err)
+static gboolean
+catapult_dct2000_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
+ const guint8 *pd, int *err, gchar **err_info _U_)
{
+ const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
guint32 n;
line_prefix_info_t *prefix = NULL;
gchar time_string[16];
gboolean is_comment;
+ gboolean is_sprint = FALSE;
dct2000_dump_t *dct2000;
+ int consecutive_slashes=0;
+ char *p_c;
/******************************************************/
/* Get the file_externals structure for this file */
dct2000_file_externals_t *file_externals =
(dct2000_file_externals_t*)pseudo_header->dct2000.wth->priv;
+ /* We can only write packet records. */
+ if (phdr->rec_type != REC_TYPE_PACKET) {
+ *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
+ return FALSE;
+ }
+
dct2000 = (dct2000_dump_t *)wdh->priv;
if (dct2000 == NULL) {
dct2000->start_time.nsecs =
(file_externals->start_usecs * 1000);
- /* Set flag do don't write header out again */
+ /* Set flag so don't write header out again */
dct2000->first_packet_written = TRUE;
}
}
/* Can infer from prefix if this is a comment (whose payload is displayed differently) */
- is_comment = (strstr(prefix->before_time, "/////") != NULL);
+ /* This is much faster than strstr() for "/////" */
+ p_c = prefix->before_time;
+ while (p_c && (*p_c != '/')) {
+ p_c++;
+ }
+ while (p_c && (*p_c == '/')) {
+ consecutive_slashes++;
+ p_c++;
+ }
+ is_comment = (consecutive_slashes == 5);
/* Calculate time of this packet to write, relative to start of dump */
if (phdr->ts.nsecs >= dct2000->start_time.nsecs) {
- g_snprintf(time_string, 16, "%ld.%04d",
- (long)(phdr->ts.secs - dct2000->start_time.secs),
- (phdr->ts.nsecs - dct2000->start_time.nsecs) / 100000);
+ write_timestamp_string(time_string,
+ (int)(phdr->ts.secs - dct2000->start_time.secs),
+ (phdr->ts.nsecs - dct2000->start_time.nsecs) / 100000);
}
else {
- g_snprintf(time_string, 16, "%ld.%04u",
- (long)(phdr->ts.secs - dct2000->start_time.secs-1),
- ((1000000000 + (phdr->ts.nsecs / 100000)) - (dct2000->start_time.nsecs / 100000)) % 10000);
+ write_timestamp_string(time_string,
+ (int)(phdr->ts.secs - dct2000->start_time.secs-1),
+ ((1000000000 + (phdr->ts.nsecs / 100000)) - (dct2000->start_time.nsecs / 100000)) % 10000);
}
/* Write out the calculated timestamp */
n++;
/* Protocol name */
+ if (is_comment) {
+ is_sprint = (strcmp((const char *)pd+n, "sprint") == 0);
+ }
for (; pd[n] != '\0'; n++);
n++;
/**************************************/
/* Remainder is encapsulated protocol */
- if (!wtap_dump_file_write(wdh, "$", 1, err)) {
+ if (!wtap_dump_file_write(wdh, is_sprint ? " " : "$", 1, err)) {
return FALSE;
}
if (!is_comment) {
- /* Each binary byte is written out as 2 hex string chars */
+ /* Each binary byte is written out as 2 hex string chars */
for (; n < phdr->len; n++) {
gchar c[2];
- c[0] = char_from_hex((guchar)(pd[n] >> 4));
- c[1] = char_from_hex((guchar)(pd[n] & 0x0f));
+ c[0] = char_from_hex((guint8)(pd[n] >> 4));
+ c[1] = char_from_hex((guint8)(pd[n] & 0x0f));
/* Write both hex chars of byte together */
if (!wtap_dump_file_write(wdh, c, 2, err)) {
/* - on return 'offset' will point to the next position to read from */
/* - return TRUE if this read is successful */
/**********************************************************************/
-gboolean read_new_line(FILE_T fh, gint64 *offset, gint *length,
- gchar *linebuff, size_t linebuffsize)
+static gboolean
+read_new_line(FILE_T fh, gint64 *offset, gint *length,
+ gchar *linebuff, size_t linebuffsize, int *err, gchar **err_info)
{
- char *result;
-
/* Read in a line */
- result = file_gets(linebuff, (int)linebuffsize - 1, fh);
- if (result == NULL) {
+ gint64 pos_before = file_tell(fh);
+
+ if (file_gets(linebuff, (int)linebuffsize - 1, fh) == NULL) {
/* No characters found, or error */
+ *err = file_error(fh, err_info);
return FALSE;
}
- /* Set length and offset.. */
- *length = (gint)strlen(linebuff);
+ /* Set length (avoiding strlen()) and offset.. */
+ *length = (gint)(file_tell(fh) - pos_before);
*offset = *offset + *length;
/* ...but don't want to include newline in line length */
- if (linebuff[*length-1] == '\n') {
+ if (*length > 0 && linebuff[*length-1] == '\n') {
+ linebuff[*length-1] = '\0';
+ *length = *length - 1;
+ }
+ /* Nor do we want '\r' (as will be written when log is created on windows) */
+ if (*length > 0 && linebuff[*length-1] == '\r') {
linebuff[*length-1] = '\0';
*length = *length - 1;
}
/* - data position and length */
/* Return TRUE if this packet looks valid and can be displayed */
/**********************************************************************/
-static gboolean parse_line(gchar *linebuff, gint line_length,
- gint *seconds, gint *useconds,
- long *before_time_offset, long *after_time_offset,
- long *data_offset, gint *data_chars,
- packet_direction_t *direction,
- int *encap, int *is_comment,
- gchar *aal_header_chars,
- gchar *context_name, guint8 *context_portp,
- gchar *protocol_name, gchar *variant_name,
- gchar *outhdr_name)
+static gboolean
+parse_line(gchar *linebuff, gint line_length,
+ gint *seconds, gint *useconds,
+ long *before_time_offset, long *after_time_offset,
+ long *data_offset, gint *data_chars,
+ packet_direction_t *direction,
+ int *encap, int *is_comment, int *is_sprint,
+ gchar *aal_header_chars,
+ gchar *context_name, guint8 *context_portp,
+ gchar *protocol_name, gchar *variant_name,
+ gchar *outhdr_name)
{
int n = 0;
int port_digits;
gboolean atm_header_present = FALSE;
*is_comment = FALSE;
+ *is_sprint = FALSE;
/* Read context name until find '.' */
- for (n=0; (linebuff[n] != '.') && (n < MAX_CONTEXT_NAME) && (n+1 < line_length); n++) {
+ for (n=0; (n < MAX_CONTEXT_NAME) && (n+1 < line_length) && (linebuff[n] != '.'); n++) {
if (linebuff[n] == '/') {
context_name[n] = '\0';
}
/* There is no variant, outhdr, etc. Set protocol to be a comment */
- g_snprintf(protocol_name, MAX_PROTOCOL_NAME, "comment");
+ g_strlcpy(protocol_name, "comment", MAX_PROTOCOL_NAME);
*is_comment = TRUE;
break;
}
- if (!isalnum((guchar)linebuff[n]) && (linebuff[n] != '_') && (linebuff[n] != '-')) {
+ if (!g_ascii_isalnum(linebuff[n]) && (linebuff[n] != '_') && (linebuff[n] != '-')) {
return FALSE;
}
context_name[n] = linebuff[n];
return FALSE;
}
- /* Reset strings (that won't be set be comments) */
- g_strlcpy(variant_name, "0", MAX_VARIANT_DIGITS);
- g_strlcpy(outhdr_name, "", MAX_OUTHDR_NAME);
- g_strlcpy(port_number_string, "0", MAX_PORT_DIGITS);
+ /* Reset strings (that won't be set by comments) */
+ variant_name[0] = '\0';
+ outhdr_name[0] = '\0';
+ port_number_string[0] = '\0';
if (!(*is_comment)) {
/* '.' must follow context name */
(linebuff[n] != '/') && (port_digits <= MAX_PORT_DIGITS) && (n+1 < line_length);
n++, port_digits++) {
- if (!isdigit((guchar)linebuff[n])) {
+ if (!g_ascii_isdigit(linebuff[n])) {
return FALSE;
}
port_number_string[port_digits] = linebuff[n];
return FALSE;
}
port_number_string[port_digits] = '\0';
- *context_portp = atoi(port_number_string);
+ if (port_digits == 1) {
+ *context_portp = port_number_string[0] - '0';
+ }
+ else {
+ *context_portp = atoi(port_number_string);
+ }
/* Skip it */
n++;
(linebuff[n] != '/') && (protocol_chars < MAX_PROTOCOL_NAME) && (n < line_length);
n++, protocol_chars++) {
- if (!isalnum((guchar)linebuff[n]) && linebuff[n] != '_') {
+ if (!g_ascii_isalnum(linebuff[n]) && linebuff[n] != '_') {
return FALSE;
}
protocol_name[protocol_chars] = linebuff[n];
/* Following the / is the variant number. No digits indicate 1 */
for (variant_digits = 0;
- (isdigit((guchar)linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
+ (g_ascii_isdigit(linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
n++, variant_digits++) {
- if (!isdigit((guchar)linebuff[n])) {
+ if (!g_ascii_isdigit(linebuff[n])) {
return FALSE;
}
variant_name[variant_digits] = linebuff[n];
if (variant_digits > MAX_VARIANT_DIGITS || (n+1 >= line_length)) {
return FALSE;
}
+
if (variant_digits > 0) {
variant_name[variant_digits] = '\0';
- variant = atoi(variant_name);
+ if (variant_digits == 1) {
+ variant = variant_name[0] - '0';
+ }
+ else {
+ variant = atoi(variant_name);
+ }
}
else {
- g_strlcpy(variant_name, "1", MAX_VARIANT_DIGITS+1);
+ variant_name[0] = '1';
+ variant_name[1] = '\0';
}
n++;
for (outhdr_chars = 0;
- (isdigit((guchar)linebuff[n]) || linebuff[n] == ',') &&
+ (g_ascii_isdigit(linebuff[n]) || linebuff[n] == ',') &&
(outhdr_chars <= MAX_OUTHDR_NAME) && (n+1 < line_length);
n++, outhdr_chars++) {
- if (!isdigit((guchar)linebuff[n]) && (linebuff[n] != ',')) {
+ if (!g_ascii_isdigit(linebuff[n]) && (linebuff[n] != ',')) {
return FALSE;
}
outhdr_name[outhdr_chars] = linebuff[n];
/* FP may be carried over ATM, which has separate atm header to parse */
if ((strcmp(protocol_name, "fp") == 0) ||
- (strcmp(protocol_name, "fp_r4") == 0) ||
- (strcmp(protocol_name, "fp_r5") == 0) ||
- (strcmp(protocol_name, "fp_r6") == 0) ||
- (strcmp(protocol_name, "fp_r7") == 0)) {
+ (strncmp(protocol_name, "fp_r", 4) == 0)) {
if ((variant > 256) && (variant % 256 == 3)) {
/* FP over udp is contained in IPPrim... */
atm_header_present = TRUE;
}
-
else
if (strcmp(protocol_name, "ppp") == 0) {
*encap = WTAP_ENCAP_PPP;
/* Read consecutive hex chars into atm header buffer */
for (;
- ((linebuff[n] >= '0') && (linebuff[n] <= '?') &&
- (n < line_length) &&
+ ((n < line_length) &&
+ (linebuff[n] >= '0') && (linebuff[n] <= '?') &&
(header_chars_seen < AAL_HEADER_CHARS));
n++, header_chars_seen++) {
aal_header_chars[header_chars_seen] = linebuff[n];
/* Next 6 characters after '9' are mapped to a->f */
- if (!isdigit((guchar)linebuff[n])) {
+ if (!g_ascii_isdigit(linebuff[n])) {
aal_header_chars[header_chars_seen] = 'a' + (linebuff[n] - '9') -1;
}
}
}
}
- /* Scan ahead to the next space */
- for (; (linebuff[n] != ' ') && (n+1 < line_length); n++);
- if (n+1 >= line_length) {
- return FALSE;
- }
- /* Skip it */
+ /* Skip next '/' */
n++;
+ /* If there is a number, skip all info to next '/'.
+ TODO: for IP encapsulation, should store PDCP ueid, drb in pseudo info
+ and display dct2000 dissector... */
+ if (g_ascii_isdigit(linebuff[n])) {
+ while ((n+1 < line_length) && linebuff[n] != '/') {
+ n++;
+ }
+ }
+
+ /* Skip '/' */
+ while ((n+1 < line_length) && linebuff[n] == '/') {
+ n++;
+ }
+
+ /* Skip a space that may happen here */
+ if ((n+1 < line_length) && linebuff[n] == ' ') {
+ n++;
+ }
+
/* Next character gives direction of message (must be 's' or 'r') */
if (!(*is_comment)) {
if (linebuff[n] == 's') {
return FALSE;
}
- for (; !isdigit((guchar)linebuff[n]) && (n < line_length); n++);
+ for (; (n < line_length) && !g_ascii_isdigit(linebuff[n]); n++);
if (n >= line_length) {
return FALSE;
}
(n < line_length);
n++, seconds_chars++) {
- if (!isdigit((guchar)linebuff[n])) {
+ if (!g_ascii_isdigit(linebuff[n])) {
/* Found a non-digit before decimal point. Fail */
return FALSE;
}
(n < line_length);
n++, subsecond_decimals_chars++) {
- if (!isdigit((guchar)linebuff[n])) {
+ if (!g_ascii_isdigit(linebuff[n])) {
return FALSE;
}
subsecond_decimals_buff[subsecond_decimals_chars] = linebuff[n];
return FALSE;
}
- *after_time_offset = n;
+ *after_time_offset = n++;
- /* Now skip ahead to find start of data (marked by '$') */
- /* Want to avoid matching with normal sprint command output at the moment... */
- for (; (linebuff[n] != '$') && (linebuff[n] != '\'') && (n+1 < line_length); n++);
- if ((linebuff[n] == '\'') || (n+1 >= line_length)) {
- return FALSE;
+ /* If we have a string message, it could either be a comment (with '$') or
+ a sprint line (no '$') */
+ if (*is_comment) {
+ if (strncmp(linebuff+n, "l $", 3) != 0) {
+ *is_sprint = TRUE;
+ g_strlcpy(protocol_name, "sprint", MAX_PROTOCOL_NAME);
+ }
+ }
+
+ if (!(*is_sprint)) {
+ /* Now skip ahead to find start of data (marked by '$') */
+ for (; (linebuff[n] != '$') && (linebuff[n] != '\'') && (n+1 < line_length); n++);
+ if ((linebuff[n] == '\'') || (n+1 >= line_length)) {
+ return FALSE;
+ }
+ /* Skip it */
+ n++;
}
- /* Skip it */
- n++;
/* Set offset to data start within line */
*data_offset = n;
return TRUE;
}
-/*****************************************************************/
-/* Write the stub info to the data buffer while reading a packet */
-/*****************************************************************/
-static int write_stub_header(guchar *frame_buffer, char *timestamp_string,
- packet_direction_t direction, int encap,
- gchar *context_name, guint8 context_port,
- gchar *protocol_name, gchar *variant_name,
- gchar *outhdr_name)
+/***********************************/
+/* Process results of parse_line() */
+/***********************************/
+static gboolean
+process_parsed_line(wtap *wth, dct2000_file_externals_t *file_externals,
+ struct wtap_pkthdr *phdr,
+ Buffer *buf, gint64 file_offset,
+ char *linebuff, long dollar_offset,
+ int seconds, int useconds, gchar *timestamp_string,
+ packet_direction_t direction, int encap,
+ gchar *context_name, guint8 context_port,
+ gchar *protocol_name, gchar *variant_name,
+ gchar *outhdr_name, gchar *aal_header_chars,
+ gboolean is_comment, int data_chars,
+ int *err, gchar **err_info)
{
+ int n;
int stub_offset = 0;
+ gsize length;
+ guint8 *frame_buffer;
+
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS;
+
+ /* Make sure all packets go to Catapult DCT2000 dissector */
+ phdr->pkt_encap = WTAP_ENCAP_CATAPULT_DCT2000;
+
+ /* Fill in timestamp (capture base + packet offset) */
+ phdr->ts.secs = file_externals->start_secs + seconds;
+ if ((file_externals->start_usecs + useconds) >= 1000000) {
+ phdr->ts.secs++;
+ }
+ phdr->ts.nsecs =
+ ((file_externals->start_usecs + useconds) % 1000000) *1000;
+
+ /*
+ * Calculate the length of the stub info and the packet data.
+ * The packet data length is half bytestring length.
+ */
+ phdr->caplen = (guint)strlen(context_name)+1 + /* Context name */
+ 1 + /* port */
+ (guint)strlen(timestamp_string)+1 + /* timestamp */
+ (guint)strlen(variant_name)+1 + /* variant */
+ (guint)strlen(outhdr_name)+1 + /* outhdr */
+ (guint)strlen(protocol_name)+1 + /* Protocol name */
+ 1 + /* direction */
+ 1 + /* encap */
+ (is_comment ? data_chars : (data_chars/2));
+ if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
+ /*
+ * Probably a corrupt capture file; return an error,
+ * so that our caller doesn't blow up trying to allocate
+ * space for an immensely-large packet.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("catapult dct2000: File has %u-byte packet, bigger than maximum of %u",
+ phdr->caplen, WTAP_MAX_PACKET_SIZE);
+ return FALSE;
+ }
+ phdr->len = phdr->caplen;
+
+ /*****************************/
+ /* Get the data buffer ready */
+ ws_buffer_assure_space(buf, phdr->caplen);
+ frame_buffer = ws_buffer_start_ptr(buf);
+
+ /******************************************/
+ /* Write the stub info to the data buffer */
- g_strlcpy((char*)frame_buffer, context_name, MAX_CONTEXT_NAME+1);
- stub_offset += (int)(strlen(context_name) + 1);
+ /* Context name */
+ length = g_strlcpy((char*)frame_buffer, context_name, MAX_CONTEXT_NAME+1);
+ stub_offset += (int)(length + 1);
/* Context port number */
frame_buffer[stub_offset] = context_port;
stub_offset++;
/* Timestamp within file */
- g_strlcpy((char*)&frame_buffer[stub_offset], timestamp_string, MAX_TIMESTAMP_LEN+1);
- stub_offset += (int)(strlen(timestamp_string) + 1);
+ length = g_strlcpy((char*)&frame_buffer[stub_offset], timestamp_string, MAX_TIMESTAMP_LEN+1);
+ stub_offset += (int)(length + 1);
/* Protocol name */
- g_strlcpy((char*)&frame_buffer[stub_offset], protocol_name, MAX_PROTOCOL_NAME+1);
- stub_offset += (int)(strlen(protocol_name) + 1);
+ length = g_strlcpy((char*)&frame_buffer[stub_offset], protocol_name, MAX_PROTOCOL_NAME+1);
+ stub_offset += (int)(length + 1);
/* Protocol variant number (as string) */
- g_strlcpy((void*)&frame_buffer[stub_offset], variant_name, MAX_VARIANT_DIGITS+1);
- stub_offset += (int)(strlen(variant_name) + 1);
+ length = g_strlcpy((gchar*)&frame_buffer[stub_offset], variant_name, MAX_VARIANT_DIGITS+1);
+ stub_offset += (int)(length + 1);
/* Outhdr */
- g_strlcpy((char*)&frame_buffer[stub_offset], outhdr_name, MAX_OUTHDR_NAME+1);
- stub_offset += (int)(strlen(outhdr_name) + 1);
+ length = g_strlcpy((char*)&frame_buffer[stub_offset], outhdr_name, MAX_OUTHDR_NAME+1);
+ stub_offset += (int)(length + 1);
/* Direction */
frame_buffer[stub_offset] = direction;
frame_buffer[stub_offset] = (guint8)encap;
stub_offset++;
- return stub_offset;
-}
-
+ if (!is_comment) {
+ /***********************************************************/
+ /* Copy packet data into buffer, converting from ascii hex */
+ for (n=0; n < data_chars; n+=2) {
+ frame_buffer[stub_offset + n/2] =
+ hex_byte_from_chars(linebuff+dollar_offset+n);
+ }
+ }
+ else {
+ /***********************************************************/
+ /* Copy packet data into buffer, just copying ascii chars */
+ for (n=0; n < data_chars; n++) {
+ frame_buffer[stub_offset + n] = linebuff[dollar_offset+n];
+ }
+ }
-/**************************************************************/
-/* Set pseudo-header info depending upon packet encapsulation */
-/**************************************************************/
-static void set_pseudo_header_info(wtap *wth,
- int pkt_encap,
- gint64 file_offset,
- union wtap_pseudo_header *pseudo_header,
- packet_direction_t direction,
- gchar *aal_header_chars)
-{
- pseudo_header->dct2000.seek_off = file_offset;
- pseudo_header->dct2000.wth = wth;
+ /*****************************************/
+ /* Set packet pseudo-header if necessary */
+ phdr->pseudo_header.dct2000.seek_off = file_offset;
+ phdr->pseudo_header.dct2000.wth = wth;
- switch (pkt_encap) {
+ switch (encap) {
case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
- set_aal_info(pseudo_header, direction, aal_header_chars);
+ set_aal_info(&phdr->pseudo_header, direction, aal_header_chars);
break;
case WTAP_ENCAP_ISDN:
- set_isdn_info(pseudo_header, direction);
+ set_isdn_info(&phdr->pseudo_header, direction);
break;
case WTAP_ENCAP_PPP:
- set_ppp_info(pseudo_header, direction);
+ set_ppp_info(&phdr->pseudo_header, direction);
break;
default:
/* Other supported types don't need to set anything here... */
break;
}
-}
+ return TRUE;
+}
/*********************************************/
/* Fill in atm pseudo-header with known info */
/*********************************************/
-static void set_aal_info(union wtap_pseudo_header *pseudo_header,
- packet_direction_t direction,
- gchar *aal_header_chars)
+static void
+set_aal_info(union wtap_pseudo_header *pseudo_header,
+ packet_direction_t direction,
+ gchar *aal_header_chars)
{
/* 'aal_head_chars' has this format (for AAL2 at least):
Global Flow Control (4 bits) | VPI (8 bits) | VCI (16 bits) |
/* vpi is 8 bits (2nd & 3rd nibble) */
pseudo_header->dct2000.inner_pseudo_header.atm.vpi =
- ((hex_from_char(aal_header_chars[1]) << 4) |
- hex_from_char(aal_header_chars[2]));
+ hex_byte_from_chars(aal_header_chars+1);
/* vci is next 16 bits */
pseudo_header->dct2000.inner_pseudo_header.atm.vci =
/* cid is usually last byte. Unless last char is not hex digit, in which
case cid is derived from last char in ascii */
- if (isalnum((guchar)aal_header_chars[11])) {
+ if (g_ascii_isalnum(aal_header_chars[11])) {
pseudo_header->dct2000.inner_pseudo_header.atm.aal2_cid =
- ((hex_from_char(aal_header_chars[10]) << 4) |
- hex_from_char(aal_header_chars[11]));
+ hex_byte_from_chars(aal_header_chars+10);
}
else {
pseudo_header->dct2000.inner_pseudo_header.atm.aal2_cid =
- (int)aal_header_chars[11] - 48;
+ (int)aal_header_chars[11] - '0';
}
}
/**********************************************/
/* Fill in isdn pseudo-header with known info */
/**********************************************/
-void set_isdn_info(union wtap_pseudo_header *pseudo_header,
- packet_direction_t direction)
+static void
+set_isdn_info(union wtap_pseudo_header *pseudo_header,
+ packet_direction_t direction)
{
/* This field is used to set the 'Source' and 'Destination' columns to
'User' or 'Network'. If we assume that we're simulating the network,
/*********************************************/
/* Fill in ppp pseudo-header with known info */
/*********************************************/
-static void set_ppp_info(union wtap_pseudo_header *pseudo_header,
- packet_direction_t direction)
+static void
+set_ppp_info(union wtap_pseudo_header *pseudo_header,
+ packet_direction_t direction)
{
/* Set direction. */
pseudo_header->dct2000.inner_pseudo_header.p2p.sent = (direction == sent);
/********************************************************/
/* Return hex nibble equivalent of hex string character */
/********************************************************/
-guchar hex_from_char(gchar c)
+static guint8
+hex_from_char(gchar c)
{
if ((c >= '0') && (c <= '9')) {
return c - '0';
}
+
+/* Table allowing fast lookup from a pair of ascii hex characters to a guint8 */
+static guint8 s_tableValues[256][256];
+
+/* Prepare table values so ready so don't need to check inside hex_byte_from_chars() */
+static void prepare_hex_byte_from_chars_table(void)
+{
+ guchar hex_char_array[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ gint i, j;
+ for (i=0; i < 16; i++) {
+ for (j=0; j < 16; j++) {
+ s_tableValues[hex_char_array[i]][hex_char_array[j]] = i*16 + j;
+ }
+ }
+}
+
+/* Extract and return a byte value from 2 ascii hex chars, starting from the given pointer */
+static guint8 hex_byte_from_chars(gchar *c)
+{
+ /* Return value from quick table lookup */
+ return s_tableValues[(unsigned char)c[0]][(unsigned char)c[1]];
+}
+
+
+
/********************************************************/
/* Return character corresponding to hex nibble value */
/********************************************************/
-gchar char_from_hex(guchar hex)
+static gchar
+char_from_hex(guint8 hex)
{
- static char hex_lookup[16] =
+ static const char hex_lookup[16] =
{ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
if (hex > 15) {
/***********************************************/
/* Equality test for packet prefix hash tables */
/***********************************************/
-gint packet_offset_equal(gconstpointer v, gconstpointer v2)
+static gint
+packet_offset_equal(gconstpointer v, gconstpointer v2)
{
/* Dereferenced pointers must have same gint64 offset value */
return (*(const gint64*)v == *(const gint64*)v2);
/********************************************/
/* Hash function for packet-prefix hash table */
/********************************************/
-guint packet_offset_hash_func(gconstpointer v)
+static guint
+packet_offset_hash_func(gconstpointer v)
{
- /* Use low-order bits of git64 offset value */
+ /* Use low-order bits of gint64 offset value */
return (guint)(*(const gint64*)v);
}
/* Set secs and usecs as output */
/* Return FALSE if no valid time can be read */
/************************************************************************/
-gboolean get_file_time_stamp(gchar *linebuff, time_t *secs, guint32 *usecs)
+static gboolean
+get_file_time_stamp(gchar *linebuff, time_t *secs, guint32 *usecs)
{
- int n;
struct tm tm;
#define MAX_MONTH_LETTERS 9
char month[MAX_MONTH_LETTERS+1];
return FALSE;
}
- /**************************************************************/
- /* First is month. Read until get a space following the month */
- for (n=0; (linebuff[n] != ' ') && (n < MAX_MONTH_LETTERS); n++) {
- month[n] = linebuff[n];
+ /********************************************************/
+ /* Scan for all fields */
+ scan_found = sscanf(linebuff, "%9s %2d, %4d %2d:%2d:%2d.%4u",
+ month, &day, &year, &hour, &minute, &second, usecs);
+ if (scan_found != 7) {
+ /* Give up if not all found */
+ return FALSE;
}
- month[n] = '\0';
if (strcmp(month, "January" ) == 0) tm.tm_mon = 0;
else if (strcmp(month, "February" ) == 0) tm.tm_mon = 1;
/* Give up if not found a properly-formatted date */
return FALSE;
}
- /* Skip space char */
- n++;
-
- /********************************************************/
- /* Scan for remaining numerical fields */
- scan_found = sscanf(linebuff+n, "%d, %d %d:%d:%d.%u",
- &day, &year, &hour, &minute, &second, usecs);
- if (scan_found != 6) {
- /* Give up if not all found */
- return FALSE;
- }
/******************************************************/
/* Fill in remaining fields and return it in a time_t */
}
/* Free the data allocated inside a line_prefix_info_t */
-gboolean free_line_prefix_info(gpointer key, gpointer value,
- gpointer user_data _U_)
+static gboolean
+free_line_prefix_info(gpointer key, gpointer value,
+ gpointer user_data _U_)
{
line_prefix_info_t *info = (line_prefix_info_t*)value;
return TRUE;
}
+/*
+ * Editor modelines - http://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:
+ */