aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cfile.c23
-rw-r--r--cfile.h2
-rw-r--r--epan/epan-int.h2
-rw-r--r--epan/epan.c9
-rw-r--r--epan/epan.h5
-rw-r--r--file.c1
-rw-r--r--wiretap/pcapng.c106
-rw-r--r--wiretap/wtap.c3
-rw-r--r--wiretap/wtap.h1
9 files changed, 148 insertions, 4 deletions
diff --git a/cfile.c b/cfile.c
index a689b2e11c..830e871593 100644
--- a/cfile.c
+++ b/cfile.c
@@ -29,8 +29,8 @@
#include "cfile.h"
-const char *
-cap_file_get_interface_name(void *data, guint32 interface_id)
+static const wtapng_if_descr_t *
+cap_file_get_interface_desc(void *data, guint32 interface_id)
{
capture_file *cf = (capture_file *) data;
wtapng_iface_descriptions_t *idb_info;
@@ -42,6 +42,13 @@ cap_file_get_interface_name(void *data, guint32 interface_id)
wtapng_if_descr = &g_array_index(idb_info->interface_data, wtapng_if_descr_t, interface_id);
g_free(idb_info);
+ return wtapng_if_descr;
+}
+
+const char *
+cap_file_get_interface_name(void *data, guint32 interface_id)
+{
+ const wtapng_if_descr_t *wtapng_if_descr = cap_file_get_interface_desc(data, interface_id);
if (wtapng_if_descr) {
if (wtapng_if_descr->if_name)
@@ -52,6 +59,18 @@ cap_file_get_interface_name(void *data, guint32 interface_id)
return "unknown";
}
+const GArray *
+cap_file_get_interface_option(void *data, guint32 interface_id, guint16 option_code)
+{
+ const wtapng_if_descr_t *wtapng_if_descr = cap_file_get_interface_desc(data, interface_id);
+
+ if (wtapng_if_descr && wtapng_if_descr->if_options) {
+ gint code = (gint) option_code;
+ return (const GArray *) g_hash_table_lookup(wtapng_if_descr->if_options, &code);
+ }
+ return NULL;
+}
+
void
cap_file_init(capture_file *cf)
{
diff --git a/cfile.h b/cfile.h
index f34c34ee14..f164303f18 100644
--- a/cfile.h
+++ b/cfile.h
@@ -133,6 +133,8 @@ extern void cap_file_init(capture_file *cf);
extern const char *cap_file_get_interface_name(void *data, guint32 interface_id);
+extern const GArray *cap_file_get_interface_option(void *data, guint32 interface_id, guint16 option_code);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/epan/epan-int.h b/epan/epan-int.h
index 35e91975be..5089025c30 100644
--- a/epan/epan-int.h
+++ b/epan/epan-int.h
@@ -31,6 +31,8 @@ struct epan_session {
const nstime_t *(*get_frame_ts)(void *data, guint32 frame_num);
const char *(*get_interface_name)(void *data, guint32 interface_id);
const char *(*get_user_comment)(void *data, const frame_data *fd);
+ const GArray *(*get_interface_option)(void *data, guint32 interface_id,
+ guint16 option_code);
};
#endif
diff --git a/epan/epan.c b/epan/epan.c
index e83864121d..4426981b2f 100644
--- a/epan/epan.c
+++ b/epan/epan.c
@@ -178,6 +178,15 @@ epan_get_interface_name(const epan_t *session, guint32 interface_id)
return NULL;
}
+const GArray *
+epan_get_interface_option(const epan_t *session, guint32 interface_id, guint16 option_code)
+{
+ if (session->get_interface_option)
+ return session->get_interface_option(session->data, interface_id, option_code);
+
+ return NULL;
+}
+
const nstime_t *
epan_get_frame_ts(const epan_t *session, guint32 frame_num)
{
diff --git a/epan/epan.h b/epan/epan.h
index faf8e3a448..da00026bb7 100644
--- a/epan/epan.h
+++ b/epan/epan.h
@@ -18,7 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#ifndef __EPAN_H__
#define __EPAN_H__
@@ -124,7 +123,7 @@ void epan_circuit_cleanup(void);
/** A client will create one epan_t for an entire dissection session.
* A single epan_t will be used to analyze the entire sequence of packets,
* sequentially, in a single session. A session corresponds to a single
- * packet trace file. The reaons epan_t exists is that some packets in
+ * packet trace file. The reason epan_t exists is that some packets in
* some protocols cannot be decoded without knowledge of previous packets.
* This inter-packet "state" is stored in the epan_t.
*/
@@ -136,6 +135,8 @@ const char *epan_get_user_comment(const epan_t *session, const frame_data *fd);
const char *epan_get_interface_name(const epan_t *session, guint32 interface_id);
+const GArray *epan_get_interface_option(const epan_t *session, guint32 interface_id, guint16 option_code);
+
const nstime_t *epan_get_frame_ts(const epan_t *session, guint32 frame_num);
WS_DLL_PUBLIC void epan_free(epan_t *session);
diff --git a/file.c b/file.c
index d57e0a9b8b..2eaecf5cc0 100644
--- a/file.c
+++ b/file.c
@@ -329,6 +329,7 @@ ws_epan_new(capture_file *cf)
epan->get_frame_ts = ws_get_frame_ts;
epan->get_interface_name = cap_file_get_interface_name;
epan->get_user_comment = ws_get_user_comment;
+ epan->get_interface_option = cap_file_get_interface_option;
return epan;
}
diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c
index c350532b3f..875571866d 100644
--- a/wiretap/pcapng.c
+++ b/wiretap/pcapng.c
@@ -344,6 +344,9 @@ typedef struct wtapng_block_s {
wtapng_if_stats_t if_stats;
} data;
+ /* keys are (pointers to) gint, vals are (pointers to) arrays of GByteArray */
+ GHashTable * pcapng_options;
+
/*
* XXX - currently don't know how to handle these!
*
@@ -357,6 +360,69 @@ typedef struct wtapng_block_s {
int *file_encap;
} wtapng_block_t;
+static void
+pcapng_destroy_option_key(gpointer data)
+{
+ g_free(data);
+}
+
+static void
+pcapng_destroy_option_value(gpointer data)
+{
+ GArray * pval = (GArray *) data;
+ if (pval) {
+ guint i;
+ for(i=0; i<pval->len; i++) {
+ GByteArray * element = g_array_index(pval, GByteArray *, i);
+ g_byte_array_unref(element);
+ }
+ g_array_unref(pval);
+ }
+}
+
+static void
+pcapng_init_block_options(wtapng_block_t *wblock)
+{
+ wblock->pcapng_options = g_hash_table_new_full(g_int_hash,
+ g_int_equal,
+ pcapng_destroy_option_key,
+ pcapng_destroy_option_value);
+}
+
+static void
+pcapng_unref_block_options(wtapng_block_t *wblock)
+{
+ if (wblock->pcapng_options) {
+ g_hash_table_destroy(wblock->pcapng_options);
+ wblock->pcapng_options = NULL;
+ }
+}
+
+static void
+pcapng_collect_block_option(wtapng_block_t *wblock, guint16 code,
+ const guint8 *data, gsize len)
+{
+ if (wblock->pcapng_options) {
+ gint tempkey = (gint) code;
+ GArray * pval = (GArray *) g_hash_table_lookup(wblock->pcapng_options, &tempkey);
+ if(!pval) {
+ /* this key does not yet exist, so create a
+ new key and new array for its first value,
+ and insert it into the hash table */
+ gpointer pkey = g_try_malloc(sizeof(gint));
+ if (pkey) {
+ pval = g_array_new(FALSE, TRUE, sizeof(GByteArray *));
+ g_hash_table_insert(wblock->pcapng_options, pkey, pval);
+ }
+ }
+ if (pval) {
+ GByteArray * optionbuf = g_byte_array_new_take(g_strndup(data, len), len);
+ g_array_append_val(pval, optionbuf);
+ }
+ }
+}
+
+
/* Interface data in private struct */
typedef struct interface_data_s {
int wtap_encap;
@@ -607,6 +673,11 @@ pcapng_read_section_header_block(FILE_T fh, gboolean first_block,
block_read += bytes_read;
to_read -= bytes_read;
+ if (oh.option_code) {
+ /* collect the raw option information */
+ pcapng_collect_block_option(wblock, oh.option_code, option_content, oh.option_length);
+ }
+
/* handle option content */
switch (oh.option_code) {
case(OPT_EOFOPT):
@@ -779,6 +850,11 @@ pcapng_read_if_descr_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn,
block_read += bytes_read;
to_read -= bytes_read;
+ if (oh.option_code) {
+ /* collect the raw option information */
+ pcapng_collect_block_option(wblock, oh.option_code, option_content, oh.option_length);
+ }
+
/* handle option content */
switch (oh.option_code) {
case(0): /* opt_endofopt */
@@ -1206,6 +1282,11 @@ pcapng_read_packet_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t *pn, wta
block_read += bytes_read;
to_read -= bytes_read;
+ if (oh.option_code) {
+ /* collect the raw option information */
+ pcapng_collect_block_option(wblock, oh.option_code, option_content, oh.option_length);
+ }
+
/* handle option content */
switch (oh.option_code) {
case(OPT_EOFOPT):
@@ -1827,6 +1908,11 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
block_read += bytes_read;
to_read -= bytes_read;
+ if (oh.option_code) {
+ /* collect the raw option information */
+ pcapng_collect_block_option(wblock, oh.option_code, option_content, oh.option_length);
+ }
+
/* handle option content */
switch (oh.option_code) {
case(0): /* opt_endofopt */
@@ -2131,6 +2217,9 @@ pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
/* Interface statistics */
int_data.num_stat_entries = 0;
int_data.interface_statistics = NULL;
+ /* move the options over */
+ int_data.if_options = wblock->pcapng_options;
+ wblock->pcapng_options = NULL;
g_array_append_val(wth->interface_data, int_data);
wth->number_of_interfaces++;
@@ -2154,6 +2243,8 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
pcapng_block_header_t bh;
gint64 saved_offset;
+ pcapng_init_block_options(&wblock);
+
pn.shb_read = FALSE;
/* we don't know the byte swapping of the file yet */
pn.byte_swapped = FALSE;
@@ -2174,6 +2265,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
bytes_read = pcapng_read_block(wth->fh, TRUE, &pn, &wblock, err, err_info);
if (bytes_read <= 0) {
pcapng_debug0("pcapng_open: couldn't read first SHB");
+ pcapng_unref_block_options(&wblock);
*err = file_error(wth->fh, err_info);
if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
return -1;
@@ -2188,6 +2280,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
* binary data?
*/
pcapng_debug1("pcapng_open: first block type %u not SHB", wblock.type);
+ pcapng_unref_block_options(&wblock);
return 0;
}
pn.shb_read = TRUE;
@@ -2233,6 +2326,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
if (bytes_read != sizeof bh) {
*err = file_error(wth->fh, err_info);
pcapng_debug3("pcapng_open: Check for more IDB:s, file_read() returned %d instead of %u, err = %d.", bytes_read, (unsigned int)sizeof bh, *err);
+ pcapng_unref_block_options(&wblock);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
@@ -2258,6 +2352,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
if (bytes_read <= 0) {
pcapng_debug0("pcapng_open: couldn't read IDB");
*err = file_error(wth->fh, err_info);
+ pcapng_unref_block_options(&wblock);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
@@ -2265,6 +2360,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
pcapng_process_idb(wth, pcapng, &wblock);
pcapng_debug2("pcapng_open: Read IDB number_of_interfaces %u, wtap_encap %i", wth->number_of_interfaces, *wblock.file_encap);
}
+ pcapng_unref_block_options(&wblock);
return 1;
}
@@ -2279,6 +2375,8 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
wtapng_if_descr_t *wtapng_if_descr;
wtapng_if_stats_t if_stats;
+ pcapng_init_block_options(&wblock);
+
*data_offset = file_tell(wth->fh);
pcapng_debug1("pcapng_read: data_offset is initially %" G_GINT64_MODIFIER "d", *data_offset);
@@ -2295,6 +2393,7 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
if (bytes_read <= 0) {
pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset);
pcapng_debug0("pcapng_read: couldn't read packet block");
+ pcapng_unref_block_options(&wblock);
return FALSE;
}
@@ -2305,6 +2404,7 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
wth->phdr.pkt_encap = WTAP_ENCAP_UNKNOWN;
*err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup_printf("pcapng: multi-section files not currently supported");
+ pcapng_unref_block_options(&wblock);
return FALSE;
case(BLOCK_TYPE_PB):
@@ -2373,6 +2473,7 @@ got_packet:
/*pcapng_debug2("Read length: %u Packet length: %u", bytes_read, wth->phdr.caplen);*/
pcapng_debug1("pcapng_read: data_offset is finally %" G_GINT64_MODIFIER "d", *data_offset + bytes_read);
+ pcapng_unref_block_options(&wblock);
return TRUE;
}
@@ -2389,10 +2490,12 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
int bytes_read;
wtapng_block_t wblock;
+ pcapng_init_block_options(&wblock);
/* seek to the right file position */
bytes_read64 = file_seek(wth->random_fh, seek_off, SEEK_SET, err);
if (bytes_read64 <= 0) {
+ pcapng_unref_block_options(&wblock);
return FALSE; /* Seek error */
}
pcapng_debug1("pcapng_seek_read: reading at offset %" G_GINT64_MODIFIER "u", seek_off);
@@ -2406,6 +2509,7 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
if (bytes_read <= 0) {
pcapng_debug3("pcapng_seek_read: couldn't read packet block (err=%d, errno=%d, bytes_read=%d).",
*err, errno, bytes_read);
+ pcapng_unref_block_options(&wblock);
return FALSE;
}
@@ -2414,9 +2518,11 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
if (wblock.type != BLOCK_TYPE_PB && wblock.type != BLOCK_TYPE_EPB &&
wblock.type != BLOCK_TYPE_SPB) {
pcapng_debug1("pcapng_seek_read: block type %u not PB/EPB/SPB", wblock.type);
+ pcapng_unref_block_options(&wblock);
return FALSE;
}
+ pcapng_unref_block_options(&wblock);
return TRUE;
}
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index 8774f35e1f..d8bbdbb65f 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -925,6 +925,9 @@ wtap_close(wtap *wth)
if(wtapng_if_descr->num_stat_entries != 0){
g_array_free(wtapng_if_descr->interface_statistics, TRUE);
}
+ if(wtapng_if_descr->if_options){
+ g_hash_table_destroy(wtapng_if_descr->if_options);
+ }
}
if(wth->number_of_interfaces != 0){
g_array_free(wth->interface_data, TRUE);
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index db18a2f3af..bd6e6e8b42 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1118,6 +1118,7 @@ typedef struct wtapng_if_descr_s {
guint8 num_stat_entries;
GArray *interface_statistics; /**< An array holding the interface statistics from
* pcapng ISB:s or equivalent(?)*/
+ GHashTable *if_options;
} wtapng_if_descr_t;