#define AAL_HEADER_CHARS 12
/* TODO:
+ - support for FP over AAL0
+ - support for IuR interface FP
- support for x.25?
*/
typedef struct
{
gchar *before_time;
- gchar *after_time;
+ gchar *after_time; /* If NULL assume " l " */
} line_prefix_info_t;
/*******************************************************************/
Records (file offset -> pre-data-prefix-string)
N.B. This is only needed for dumping
*/
- GHashTable *line_header_prefixes_table;
+ GHashTable *packet_prefix_table;
} dct2000_file_externals_t;
/* This global table maps wtap -> file_external structs */
/************************************************************/
/* Functions called from wiretap */
static gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info,
- long *data_offset);
-static gboolean catapult_dct2000_seek_read(wtap *wth, long seek_off,
+ 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);
/************************************************************/
/* Private helper functions */
-static gboolean read_new_line(FILE_T fh, long *offset, gint *length);
+static gboolean read_new_line(FILE_T fh, gint64 *offset, gint *length);
static gboolean parse_line(gint line_length, gint *seconds, gint *useconds,
long *before_time_offset, long *after_time_offset,
long *data_offset,
static void set_pseudo_header_info(wtap *wth,
int pkt_encap,
- long file_offset,
+ gint64 file_offset,
union wtap_pseudo_header *pseudo_header,
packet_direction_t direction);
static void set_aal_info(union wtap_pseudo_header *pseudo_header,
static void set_ppp_info(union wtap_pseudo_header *pseudo_header,
packet_direction_t direction);
+static gint wth_equal(gconstpointer v, gconstpointer v2);
+static guint wth_hash_func(gconstpointer v);
+static gint packet_offset_equal(gconstpointer v, gconstpointer v2);
+static guint packet_offset_hash_func(gconstpointer v);
-static gint prefix_equal(gconstpointer v, gconstpointer v2);
-static guint prefix_hash_func(gconstpointer v);
static gboolean get_file_time_stamp(time_t *secs, guint32 *usecs);
static gboolean free_line_prefix_info(gpointer key, gpointer value, gpointer user_data);
/********************************************/
int catapult_dct2000_open(wtap *wth, int *err, gchar **err_info _U_)
{
- long offset = 0;
+ gint64 offset = 0;
time_t timestamp;
guint32 usecs;
- gint firstline_length;
+ gint firstline_length = 0;
dct2000_file_externals_t *file_externals;
/* Clear errno before reading from the file */
errno = 0;
- /*********************************************************************/
- /* Need entry in file_externals table */
-
- /* Create file externals table if it doesn't yet exist */
- if (file_externals_table == NULL)
- {
- file_externals_table = g_hash_table_new(prefix_hash_func, prefix_equal);
- }
-
-
/********************************************************************/
/* First line needs to contain at least as many characters as magic */
}
+ /*********************************************************************/
+ /* Need entry in file_externals table */
+
+ /* Create file externals table if it doesn't yet exist */
+ if (file_externals_table == NULL)
+ {
+ file_externals_table = g_hash_table_new(wth_hash_func, wth_equal);
+ }
+
/* Allocate a new file_externals structure */
file_externals = g_malloc(sizeof(dct2000_file_externals_t));
memset((void*)file_externals, '\0', sizeof(dct2000_file_externals_t));
wth->tsprecision = WTAP_FILE_TSPREC_USEC;
- /**********************************************/
- /* Initialise line_header_prefixes_table */
- file_externals->line_header_prefixes_table =
- g_hash_table_new(prefix_hash_func, prefix_equal);
+ /***************************************************************/
+ /* Initialise packet_prefix_table (index is offset into file) */
+ file_externals->packet_prefix_table =
+ g_hash_table_new(packet_offset_hash_func, packet_offset_equal);
/* Add file_externals for this wtap into the global table */
g_hash_table_insert(file_externals_table,
/* - return TRUE and details if found */
/**************************************************/
gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info _U_,
- long *data_offset)
+ gint64 *data_offset)
{
- long offset = wth->data_offset;
+ gint64 offset = wth->data_offset;
long dollar_offset, before_time_offset, after_time_offset;
packet_direction_t direction;
int encap;
while (1)
{
int line_length, seconds, useconds, data_chars;
- long this_offset = offset;
+ gint64 this_offset = offset;
/* Are looking for first packet after 2nd line */
if (wth->data_offset == 0)
break;
}
- /* Try to parse the line as a message */
+ /* Try to parse the line as a frame record */
if (parse_line(line_length, &seconds, &useconds,
&before_time_offset, &after_time_offset,
&dollar_offset,
int stub_offset = 0;
line_prefix_info_t *line_prefix_info;
char timestamp_string[32];
+ gint64 *pkey = NULL;
+
sprintf(timestamp_string, "%d.%04d", seconds, useconds/100);
/* All packets go to Catapult DCT2000 stub dissector */
/* Store the packet prefix in the hash table */
line_prefix_info = g_malloc(sizeof(line_prefix_info_t));
+ /* Create and use buffer for contents before time */
line_prefix_info->before_time = g_malloc(before_time_offset+1);
strncpy(line_prefix_info->before_time, linebuff, before_time_offset);
line_prefix_info->before_time[before_time_offset] = '\0';
- line_prefix_info->after_time = g_malloc(dollar_offset - after_time_offset);
- strncpy(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';
+ /* Create and use buffer for contents before time.
+ Do this only if it doesn't correspond to " l ", which is by far the most
+ common case. */
+ if (((size_t)(dollar_offset - after_time_offset -1) == strlen(" l ")) &&
+ (strncmp(linebuff+after_time_offset, " l ", strlen(" l ")) == 0))
+ {
+ line_prefix_info->after_time = NULL;
+ }
+ else
+ {
+ line_prefix_info->after_time = g_malloc(dollar_offset - after_time_offset);
+ strncpy(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 */
- g_hash_table_insert(file_externals->line_header_prefixes_table,
- (void*)this_offset, line_prefix_info);
-
+ pkey = 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,
/* Read & seek function. */
/**************************************************/
static gboolean
-catapult_dct2000_seek_read(wtap *wth, long seek_off,
+catapult_dct2000_seek_read(wtap *wth, gint64 seek_off,
union wtap_pseudo_header *pseudo_header, guchar *pd,
int length, int *err, gchar **err_info)
{
- long offset = wth->data_offset;
+ gint64 offset = wth->data_offset;
long dollar_offset, before_time_offset, after_time_offset;
packet_direction_t direction;
int encap;
/* If get here, must have failed */
*err = errno;
*err_info = g_strdup_printf("catapult dct2000: seek_read failed to read/parse "
- "line at position %ld", seek_off);
+ "line at position %" G_GINT64_MODIFIER "d",
+ seek_off);
return FALSE;
}
}
/* Free up its line prefix values */
- g_hash_table_foreach_remove(file_externals->line_header_prefixes_table,
+ g_hash_table_foreach_remove(file_externals->packet_prefix_table,
free_line_prefix_info, NULL);
/* Free up its line prefix table */
- g_hash_table_destroy(file_externals->line_header_prefixes_table);
+ g_hash_table_destroy(file_externals->packet_prefix_table);
/* And remove the externals entry from the global table */
g_hash_table_remove(file_externals_table, (void*)wth);
/* Write out this packet's prefix, including calculated timestamp */
/* Look up line data prefix using stored offset */
- prefix = (line_prefix_info_t*)g_hash_table_lookup(file_externals->line_header_prefixes_table,
- (void*)pseudo_header->dct2000.seek_off);
+ prefix = (line_prefix_info_t*)g_hash_table_lookup(file_externals->packet_prefix_table,
+ (const void*)&(pseudo_header->dct2000.seek_off));
/* Write out text before timestamp */
fwrite(prefix->before_time, 1, strlen(prefix->before_time), wdh->fh);
fwrite(time_string, 1, strlen(time_string), wdh->fh);
/* Write out text between timestamp and start of hex data */
- fwrite(prefix->after_time, 1, strlen(prefix->after_time), wdh->fh);
+ if (prefix->after_time == NULL)
+ {
+ fwrite(" l ", 1, strlen(" l "), wdh->fh);
+ }
+ else
+ {
+ fwrite(prefix->after_time, 1, strlen(prefix->after_time), wdh->fh);
+ }
/****************************************************************/
/* - 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, long *offset, gint *length)
+gboolean read_new_line(FILE_T fh, gint64 *offset, gint *length)
{
char *result;
int seconds_chars;
char subsecond_decimals_buff[MAX_SUBSECOND_DECIMALS+1];
int subsecond_decimals_chars;
+ int skip_first_byte = FALSE;
gboolean atm_header_present = FALSE;
/* Read context name until find '.' */
for (n=0; linebuff[n] != '.' && (n < MAX_CONTEXT_NAME) && (n+1 < line_length); n++)
{
- if (!isalnum(linebuff[n]) && (linebuff[n] != '_'))
+ if (!isalnum((int)linebuff[n]) && (linebuff[n] != '_'))
{
return FALSE;
}
(linebuff[n] != '/') && (port_digits <= MAX_PORT_DIGITS) && (n+1 < line_length);
n++, port_digits++)
{
- if (!isdigit(linebuff[n]))
+ if (!isdigit((int)linebuff[n]))
{
return FALSE;
}
(linebuff[n] != '/') && (protocol_chars < MAX_PROTOCOL_NAME) && (n < line_length);
n++, protocol_chars++)
{
- if (!isalnum(linebuff[n]) && linebuff[n] != '_')
+ if (!isalnum((int)linebuff[n]) && linebuff[n] != '_')
{
return FALSE;
}
/* Following the / is the variant number. No digits indicate 1 */
for (variant_digits = 0;
- (isdigit(linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
+ (isdigit((int)linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
n++, variant_digits++)
{
- if (!isdigit(linebuff[n]))
+ if (!isdigit((int)linebuff[n]))
{
return FALSE;
}
n++;
for (outhdr_chars = 0;
- (isdigit(linebuff[n]) || linebuff[n] == ',') &&
+ (isdigit((int)linebuff[n]) || linebuff[n] == ',') &&
(outhdr_chars <= MAX_OUTHDR_NAME) && (n+1 < line_length);
n++, outhdr_chars++)
{
- if (!isdigit(linebuff[n]) && (linebuff[n] != ','))
+ if (!isdigit((int)linebuff[n]) && (linebuff[n] != ','))
{
return FALSE;
}
/******************************************************************/
/* Now check whether we know how to use a packet of this protocol */
- if ((strcmp(protocol_name, "ip") == 0) || (strcmp(protocol_name, "sctp") == 0))
+ if ((strcmp(protocol_name, "ip") == 0) ||
+ (strcmp(protocol_name, "sctp") == 0) ||
+ (strcmp(protocol_name, "gre") == 0) ||
+ (strcmp(protocol_name, "mipv6") == 0))
{
*encap = WTAP_ENCAP_RAW_IP;
}
atm_header_present = TRUE;
}
}
+ else if (strcmp(protocol_name, "fpiur_r5") == 0)
+ {
+ /* FP (IuR) over AAL2 */
+ *encap = WTAP_ENCAP_ATM_PDUS_UNTRUNCATED;
+ atm_header_present = TRUE;
+ }
+
else
if (strcmp(protocol_name, "ppp") == 0)
else
if (strcmp(protocol_name, "isdn_l3") == 0)
{
- /* Despite the name, this does seem to correspond to L2... */
+ /* TODO: find out what this byte means... */
+ skip_first_byte = TRUE;
+ *encap = WTAP_ENCAP_ISDN;
+ }
+ else
+ if (strcmp(protocol_name, "isdn_l2") == 0)
+ {
*encap = WTAP_ENCAP_ISDN;
}
else
*encap = DCT2000_ENCAP_MTP2;
}
else
+ if ((strcmp(protocol_name, "nbap") == 0) ||
+ (strcmp(protocol_name, "nbap_r4") == 0) ||
+ (strncmp(protocol_name, "nbap_sscfuni", strlen("nbap_sscfuni")) == 0))
+ {
+ /* The entire message in these cases is nbap, so use an encap value. */
+ *encap = DCT2000_ENCAP_NBAP;
+ }
+ else
{
- /* Not a supported board port protocol/encap, but can show as raw data anyway */
+ /* Not a supported board port protocol/encap, but can show as raw data or
+ in some cases find protocol embedded inside primitive */
*encap = DCT2000_ENCAP_UNHANDLED;
}
/* Read consecutive hex chars into atm header buffer */
for (;
- (isalnum(linebuff[n]) &&
+ (isalnum((int)linebuff[n]) &&
(n < line_length) &&
(header_chars_seen < AAL_HEADER_CHARS));
n++, header_chars_seen++)
aal_header_chars[header_chars_seen] = linebuff[n];
}
+ /* Sometimes see strange encoding of cid in last (non-digit) character */
+ if (header_chars_seen == (AAL_HEADER_CHARS-1))
+ {
+ aal_header_chars[AAL_HEADER_CHARS-1] = linebuff[n];
+ header_chars_seen++;
+ }
+
if (header_chars_seen != AAL_HEADER_CHARS || n >= line_length)
{
return FALSE;
/* Find and read the timestamp */
/* Now scan to the next digit, which should be the start of the timestamp */
- for (; !isdigit(linebuff[n]) && (n < line_length); n++);
+ for (; !isdigit((int)linebuff[n]) && (n < line_length); n++);
if (n >= line_length)
{
return FALSE;
(n < line_length);
n++, seconds_chars++)
{
- if (!isdigit(linebuff[n]))
+ if (!isdigit((int)linebuff[n]))
{
/* Found a non-digit before decimal point. Fail */
return FALSE;
/* Didn't fit in buffer. Fail rather than use truncated */
return FALSE;
}
-
+
/* Convert found value into number */
seconds_buff[seconds_chars] = '\0';
*seconds = atoi(seconds_buff);
(n < line_length);
n++, subsecond_decimals_chars++)
{
- if (!isdigit(linebuff[n]))
+ if (!isdigit((int)linebuff[n]))
{
return FALSE;
}
/* Set number of chars that comprise the hex string protocol data */
*data_chars = line_length - n;
- /* Need to skip first byte (2 hex string chars) from ISDN messages.
- TODO: find out what this byte means...
- */
- if (*encap == WTAP_ENCAP_ISDN)
+ /* May need to skip first byte (2 hex string chars) */
+ if (skip_first_byte)
{
*data_offset += 2;
*data_chars -= 2;
}
+
return TRUE;
}
/**************************************************************/
void set_pseudo_header_info(wtap *wth,
int pkt_encap,
- long file_offset,
+ gint64 file_offset,
union wtap_pseudo_header *pseudo_header,
packet_direction_t direction)
{
/* 0 means we don't know how many cells the frame comprises. */
pseudo_header->dct2000.inner_pseudo_header.atm.cells = 0;
+
+ /* 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((int)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]));
+ }
+ else
+ {
+ pseudo_header->dct2000.inner_pseudo_header.atm.aal2_cid =
+ (int)aal_header_chars[11] - 48;
+ }
+
}
return hex_lookup[hex];
}
-
-/********************************************/
-/* Equality test for line-prefix hash table */
-/********************************************/
-gint prefix_equal(gconstpointer v, gconstpointer v2)
+/***************************************************/
+/* Equality function for file_externals hash table */
+/***************************************************/
+gint wth_equal(gconstpointer v, gconstpointer v2)
{
return (v == v2);
}
+/***********************************************/
+/* Hash function for file_externals hash table */
+/***********************************************/
+guint wth_hash_func(gconstpointer v)
+{
+ return (guint)(unsigned long)v;
+}
+
+
+/***********************************************/
+/* Equality test for packet prefix hash tables */
+/***********************************************/
+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 line-prefix hash table */
+/* Hash function for packet-prefix hash table */
/********************************************/
-guint prefix_hash_func(gconstpointer v)
+guint packet_offset_hash_func(gconstpointer v)
{
- /* Just use pointer itself (is actually byte offset of line in file) */
- return (guint)v;
+ /* Use low-order bits of git64 offset value */
+ return (guint)(*(const gint64*)v);
}
}
/* Free the data allocated inside a line_prefix_info_t */
-gboolean free_line_prefix_info(gpointer key _U_, gpointer value,
+gboolean free_line_prefix_info(gpointer key, gpointer value,
gpointer user_data _U_)
{
line_prefix_info_t *info = (line_prefix_info_t*)value;
+ /* Free the 64-bit key value */
+ g_free(key);
+
/* Free the strings inside */
g_free(info->before_time);
- g_free(info->after_time);
+ if (info->after_time)
+ {
+ g_free(info->after_time);
+ }
/* And the structure itself */
g_free(info);