Refactor wiretap option block types into a registration system.
authorMichael Mann <mmann78@netscape.net>
Wed, 2 Mar 2016 14:13:08 +0000 (09:13 -0500)
committerMichael Mann <mmann78@netscape.net>
Thu, 3 Mar 2016 17:02:10 +0000 (17:02 +0000)
Also required mergecap to look for plugins to initialize wiretap option blocks.

Change-Id: I4208d1028dd0f94f185393801d72025329266cb7
Reviewed-on: https://code.wireshark.org/review/14300
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
mergecap.c
wiretap/wtap_opttypes.c
wiretap/wtap_opttypes.h

index 5c27447c0cf6b1ebb30f72b03acf9abb3e261bea..cfcc1a6d73395c83a66c73ff78f47fd99775d918 100644 (file)
 #include <wsutil/clopts_common.h>
 #include <wsutil/cmdarg_err.h>
 #include <wsutil/crash_info.h>
+#include <wsutil/filesystem.h>
 #include <wsutil/file_util.h>
 #include <wsutil/strnatcmp.h>
 #include <wsutil/ws_diag_control.h>
 #include <wsutil/ws_version_info.h>
 
+#ifdef HAVE_PLUGINS
+#include <wsutil/plugins.h>
+#endif
+
+#include <wsutil/report_err.h>
+
 #include <wiretap/merge.h>
 #include <wiretap/pcap-encap.h>
 
@@ -125,6 +132,19 @@ string_elem_print(gpointer data, gpointer not_used _U_)
           ((struct string_elem *)data)->lstr);
 }
 
+#ifdef HAVE_PLUGINS
+/*
+ *  Don't report failures to load plugins because most (non-wiretap) plugins
+ *  *should* fail to load (because we're not linked against libwireshark and
+ *  dissector plugins need libwireshark).
+ */
+static void
+failure_message(const char *msg_format _U_, va_list ap _U_)
+{
+  return;
+}
+#endif
+
 static void
 list_capture_types(void) {
   int i;
@@ -279,6 +299,10 @@ main(int argc, char *argv[])
   gboolean            use_stdout         = FALSE;
   merge_progress_callback_t cb;
 
+#ifdef HAVE_PLUGINS
+  char  *init_progfile_dir_error;
+#endif
+
   cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont);
 
 #ifdef _WIN32
@@ -300,6 +324,25 @@ main(int argc, char *argv[])
        "%s",
     get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
 
+#ifdef HAVE_PLUGINS
+  if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) {
+    g_warning("captype: init_progfile_dir(): %s", init_progfile_dir_error);
+    g_free(init_progfile_dir_error);
+  } else {
+    /* Register all the plugin types we have. */
+    wtap_register_plugin_types(); /* Types known to libwiretap */
+
+    init_report_err(failure_message,NULL,NULL,NULL);
+
+    /* Scan for plugins.  This does *not* call their registration routines;
+       that's done later. */
+    scan_plugins();
+
+    /* Register all libwiretap plugin modules. */
+    register_all_wiretap_modules();
+  }
+#endif
+
   /* Process the options first */
   while ((opt = getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) {
 
index 376ac1316e6ae5200a99d779dd8c433911bb086c..e72d77d907a3726b37136a724c0d95ea4e3cbfd1 100644 (file)
 #include "wtap-int.h"
 #include "pcapng.h"
 
-struct wtap_optionblock
+typedef void (*wtap_block_create_func)(wtap_optionblock_t block);
+typedef void (*wtap_mand_free_func)(wtap_optionblock_t block);
+typedef void (*wtap_mand_copy_func)(wtap_optionblock_t dest_block, wtap_optionblock_t src_block);
+
+typedef struct wtap_opt_register
 {
     const char *name;                /**< name of block */
     const char *description;         /**< human-readable description of block */
-    wtap_optionblock_type_t type;
+    wtap_block_create_func create;
+    wtap_mand_free_func free_mand;
+    wtap_mand_copy_func copy_mand;
+} wtap_opt_register_t;
+
+struct wtap_optionblock
+{
+    wtap_opt_register_t* info;
     void* mandatory_data;
     GArray* options;
 };
 
-void wtap_opttypes_initialize(void)
+/* Keep track of wtap_opt_register_t's via their id number */
+static wtap_opt_register_t* block_list[WTAP_OPTION_BLOCK_MAX_TYPE];
+
+static void wtap_opttype_block_register(int block_type, wtap_opt_register_t *block)
 {
+    /* Check input */
+    g_assert(block_type < WTAP_OPTION_BLOCK_MAX_TYPE);
+
+    /* Don't re-register. */
+    g_assert(block_list[block_type] == NULL);
+
+    /* Sanity check */
+    g_assert(block->name);
+    g_assert(block->description);
+    g_assert(block->create);
+
+    block_list[block_type] = block;
 }
 
-static void wtap_if_descr_filter_free(void* data)
+void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block)
 {
-    wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)data;
-    g_free(filter->if_filter_str);
-    g_free(filter->if_filter_bpf_bytes);
+    return block->mandatory_data;
 }
 
-wtap_optionblock_t wtap_optionblock_create(wtap_optionblock_type_t block_type)
+static wtap_opttype_t* wtap_optionblock_get_option(wtap_optionblock_t block, guint option_id)
 {
-    wtap_optionblock_t block = NULL;
+    guint i;
+    wtap_opttype_t* opttype = NULL;
 
-    switch(block_type)
+    for (i = 0; i < block->options->len; i++)
     {
-    case WTAP_OPTION_BLOCK_NG_SECTION:
-        {
-        wtapng_mandatory_section_t* section_mand;
-
-        block = g_new(struct wtap_optionblock, 1);
-        block->name = "SHB";
-        block->description = "Section Header block";
-        block->type = WTAP_OPTION_BLOCK_NG_SECTION;
-        block->mandatory_data = g_new(wtapng_mandatory_section_t, 1);
-        section_mand = (wtapng_mandatory_section_t*)block->mandatory_data;
-        section_mand->section_length = -1;
-        block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
-
-        wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
-        wtap_optionblock_add_option_string(block, OPT_SHB_HARDWARE, "hardware", "SBH Hardware", NULL, NULL);
-        wtap_optionblock_add_option_string(block, OPT_SHB_OS, "os", "SBH Operating System", NULL, NULL);
-        wtap_optionblock_add_option_string(block, OPT_SHB_USERAPPL, "user_appl", "SBH User Application", NULL, NULL);
-        }
-        break;
-    case WTAP_OPTION_BLOCK_NG_NRB:
-        block = g_new(struct wtap_optionblock, 1);
-        block->name = "NRB";
-        block->description = "Name Resolution Block";
-        block->type = WTAP_OPTION_BLOCK_NG_NRB;
-        block->mandatory_data = NULL;
-        block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
-
-        wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
-        break;
-
-    case WTAP_OPTION_BLOCK_IF_STATS:
-        block = g_new(struct wtap_optionblock, 1);
-        block->name = "ISB";
-        block->description = "Interface Statistics Block";
-        block->type = WTAP_OPTION_BLOCK_IF_STATS;
-        block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
-        block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
-
-        wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_STARTTIME, "start_time", "Start Time", 0, 0);
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_ENDTIME, "end_time", "End Time", 0, 0);
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_IFRECV, "recv", "Receive Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_IFDROP, "drop", "Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_FILTERACCEPT, "filter_accept", "Filter Accept", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_OSDROP, "os_drop", "OS Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        wtap_optionblock_add_option_uint64(block, OPT_ISB_USRDELIV, "user_deliv", "User Delivery", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        break;
-    case WTAP_OPTION_BLOCK_IF_DESCR:
-        {
-        wtapng_if_descr_filter_t default_filter;
-        memset(&default_filter, 0, sizeof(default_filter));
-
-        block = g_new(struct wtap_optionblock, 1);
-        block->name = "IDB";
-        block->description = "Interface Description Block";
-        block->type = WTAP_OPTION_BLOCK_IF_DESCR;
-        block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
-        block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
-
-        wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
-        wtap_optionblock_add_option_string(block, OPT_IDB_NAME, "name", "Device name", NULL, NULL);
-        wtap_optionblock_add_option_string(block, OPT_IDB_DESCR, "description", "Device description", NULL, NULL);
-        wtap_optionblock_add_option_uint64(block, OPT_IDB_SPEED, "speed", "Interface speed (in bps)", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
-        wtap_optionblock_add_option_uint8(block, OPT_IDB_TSRESOL, "ts_resolution", "Resolution of timestamps", 6, 6);
-        wtap_optionblock_add_option_custom(block, OPT_IDB_FILTER, "filter", "Filter string", &default_filter, &default_filter, sizeof(wtapng_if_descr_filter_t), wtap_if_descr_filter_free);
-        wtap_optionblock_add_option_string(block, OPT_IDB_OS, "os", "Operating System", NULL, NULL);
-        wtap_optionblock_add_option_uint8(block, OPT_IDB_FCSLEN, "fcslen", "FCS Length", -1, -1);
-        }
-        break;
+        opttype = g_array_index(block->options, wtap_opttype_t*, i);
+        if (opttype->number == option_id)
+            return opttype;
     }
 
+    return NULL;
+}
+
+wtap_optionblock_t wtap_optionblock_create(wtap_optionblock_type_t block_type)
+{
+    wtap_optionblock_t block;
+
+    if (block_type >= WTAP_OPTION_BLOCK_MAX_TYPE)
+        return NULL;
+
+    block = g_new(struct wtap_optionblock, 1);
+    block->info = block_list[block_type];
+    block->info->create(block);
+
     return block;
 }
 
@@ -155,49 +128,81 @@ static void wtap_optionblock_free_options(wtap_optionblock_t block)
 
 void wtap_optionblock_free(wtap_optionblock_t block)
 {
-    guint j;
-    wtap_optionblock_t if_stats;
-
     if (block != NULL)
     {
-        /* Need special consideration for freeing of the interface_statistics member */
-        if (block->type == WTAP_OPTION_BLOCK_IF_DESCR)
-        {
-            wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data;
-            for(j = 0; j < mand->num_stat_entries; j++) {
-                if_stats = g_array_index(mand->interface_statistics, wtap_optionblock_t, j);
-                wtap_optionblock_free(if_stats);
-            }
-
-            if (mand->interface_statistics)
-                g_array_free(mand->interface_statistics, TRUE);
-        }
+        if (block->info->free_mand != NULL)
+            block->info->free_mand(block);
 
         g_free(block->mandatory_data);
         wtap_optionblock_free_options(block);
-        g_array_free(block->options, FALSE);
+        if (block->options != NULL)
+            g_array_free(block->options, FALSE);
         g_free(block);
     }
 }
 
-void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block)
-{
-    return block->mandatory_data;
-}
-
-static wtap_opttype_t* wtap_optionblock_get_option(wtap_optionblock_t block, guint option_id)
+void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
 {
     guint i;
-    wtap_opttype_t* opttype = NULL;
+    wtap_opttype_t *dest_opttype, *src_opttype;
 
-    for (i = 0; i < block->options->len; i++)
+    if (dest_block->info->copy_mand != NULL)
+        dest_block->info->copy_mand(dest_block, src_block);
+
+    /* Copy the options.  For now, don't remove any options that are in destination
+     * but not source.
+     */
+    for (i = 0; i < src_block->options->len; i++)
     {
-        opttype = g_array_index(block->options, wtap_opttype_t*, i);
-        if (opttype->number == option_id)
-            return opttype;
+        src_opttype = g_array_index(src_block->options, wtap_opttype_t*, i);
+        dest_opttype = wtap_optionblock_get_option(dest_block, src_opttype->number);
+        if (dest_opttype == NULL)
+        {
+            /* Option doesn't exist, add it */
+            switch(src_opttype->type)
+            {
+            case WTAP_OPTTYPE_UINT8:
+                wtap_optionblock_add_option_uint8(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
+                                                  src_opttype->option.uint8val, src_opttype->default_val.uint8val);
+                break;
+            case WTAP_OPTTYPE_UINT64:
+                wtap_optionblock_add_option_uint64(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
+                                                  src_opttype->option.uint64val, src_opttype->default_val.uint64val);
+                break;
+            case WTAP_OPTTYPE_STRING:
+                wtap_optionblock_add_option_string(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
+                                                  src_opttype->option.stringval, src_opttype->default_val.stringval);
+                break;
+            case WTAP_OPTTYPE_CUSTOM:
+                wtap_optionblock_add_option_custom(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
+                                                 src_opttype->option.customval.data, src_opttype->default_val.customval.data,
+                                                 src_opttype->option.customval.size, src_opttype->option.customval.free_func);
+                break;
+            }
+        }
+        else
+        {
+            /* Option exists, replace it */
+            switch(src_opttype->type)
+            {
+            case WTAP_OPTTYPE_UINT8:
+                dest_opttype->option.uint8val = src_opttype->option.uint8val;
+                break;
+            case WTAP_OPTTYPE_UINT64:
+                dest_opttype->option.uint64val = src_opttype->option.uint64val;
+                break;
+            case WTAP_OPTTYPE_STRING:
+                g_free(dest_opttype->option.stringval);
+                dest_opttype->option.stringval = g_strdup(src_opttype->option.stringval);
+                break;
+            case WTAP_OPTTYPE_CUSTOM:
+                dest_opttype->option.customval.free_func(dest_opttype->option.customval.data);
+                g_free(dest_opttype->option.customval.data);
+                dest_opttype->option.customval.data = g_memdup(src_opttype->option.customval.data, src_opttype->option.customval.size);
+                break;
+            }
+        }
     }
-
-    return NULL;
 }
 
 int wtap_optionblock_add_option_string(wtap_optionblock_t block, guint option_id,
@@ -418,94 +423,159 @@ int wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+static void shb_create(wtap_optionblock_t block)
 {
-    guint i;
-    wtap_opttype_t *dest_opttype, *src_opttype;
+    wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1);
 
-    switch(src_block->type)
-    {
-    case WTAP_OPTION_BLOCK_NG_SECTION:
-        memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
-        break;
-    case WTAP_OPTION_BLOCK_NG_NRB:
-        /* No mandatory data */
-        break;
-    case WTAP_OPTION_BLOCK_IF_STATS:
-        memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
-        break;
-    case WTAP_OPTION_BLOCK_IF_DESCR:
-        {
-        wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data,
-                                    *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data;
-        /* Need special consideration for copying of the interface_statistics member */
-        if (dest_mand->num_stat_entries != 0)
-        {
-            g_array_free(dest_mand->interface_statistics, TRUE);
-        }
+    section_mand->section_length = -1;
 
-        memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t));
-        if (src_mand->num_stat_entries != 0)
-        {
-            dest_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
-            dest_mand->interface_statistics = g_array_append_vals(dest_mand->interface_statistics, src_mand->interface_statistics->data, src_mand->interface_statistics->len);
-        }
-        }
-        break;
+    block->mandatory_data = section_mand;
+    block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
+
+    wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
+    wtap_optionblock_add_option_string(block, OPT_SHB_HARDWARE, "hardware", "SBH Hardware", NULL, NULL);
+    wtap_optionblock_add_option_string(block, OPT_SHB_OS, "os", "SBH Operating System", NULL, NULL);
+    wtap_optionblock_add_option_string(block, OPT_SHB_USERAPPL, "user_appl", "SBH User Application", NULL, NULL);
+}
+
+static void shb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+{
+    memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
+}
+
+static void nrb_create(wtap_optionblock_t block)
+{
+    block->mandatory_data = NULL;
+    block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
+
+    wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
+}
+
+static void isb_create(wtap_optionblock_t block)
+{
+    block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
+    block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
+
+    wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_STARTTIME, "start_time", "Start Time", 0, 0);
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_ENDTIME, "end_time", "End Time", 0, 0);
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_IFRECV, "recv", "Receive Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_IFDROP, "drop", "Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_FILTERACCEPT, "filter_accept", "Filter Accept", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_OSDROP, "os_drop", "OS Dropped Packets", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+    wtap_optionblock_add_option_uint64(block, OPT_ISB_USRDELIV, "user_deliv", "User Delivery", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+}
+
+static void isb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+{
+    memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
+}
+
+static void idb_filter_free(void* data)
+{
+    wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)data;
+    g_free(filter->if_filter_str);
+    g_free(filter->if_filter_bpf_bytes);
+}
+
+static void idb_create(wtap_optionblock_t block)
+{
+    wtapng_if_descr_filter_t default_filter;
+    memset(&default_filter, 0, sizeof(default_filter));
+
+    block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
+    block->options = g_array_new(FALSE, FALSE, sizeof(wtap_opttype_t*));
+
+    wtap_optionblock_add_option_string(block, OPT_COMMENT, "opt_comment", "Optional comment", NULL, NULL);
+    wtap_optionblock_add_option_string(block, OPT_IDB_NAME, "name", "Device name", NULL, NULL);
+    wtap_optionblock_add_option_string(block, OPT_IDB_DESCR, "description", "Device description", NULL, NULL);
+    wtap_optionblock_add_option_uint64(block, OPT_IDB_SPEED, "speed", "Interface speed (in bps)", G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF), G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF));
+    wtap_optionblock_add_option_uint8(block, OPT_IDB_TSRESOL, "ts_resolution", "Resolution of timestamps", 6, 6);
+    wtap_optionblock_add_option_custom(block, OPT_IDB_FILTER, "filter", "Filter string", &default_filter, &default_filter, sizeof(wtapng_if_descr_filter_t), idb_filter_free);
+    wtap_optionblock_add_option_string(block, OPT_IDB_OS, "os", "Operating System", NULL, NULL);
+    wtap_optionblock_add_option_uint8(block, OPT_IDB_FCSLEN, "fcslen", "FCS Length", -1, -1);
+}
+
+static void idb_free_mand(wtap_optionblock_t block)
+{
+    guint j;
+    wtap_optionblock_t if_stats;
+    wtapng_if_descr_mandatory_t* mand = (wtapng_if_descr_mandatory_t*)block->mandatory_data;
+
+    for(j = 0; j < mand->num_stat_entries; j++) {
+        if_stats = g_array_index(mand->interface_statistics, wtap_optionblock_t, j);
+        wtap_optionblock_free(if_stats);
     }
 
-    /* Copy the options.  For now, don't remove any options that are in destination
-     * but not source.
-     */
-    for (i = 0; i < src_block->options->len; i++)
+    if (mand->interface_statistics)
+        g_array_free(mand->interface_statistics, TRUE);
+}
+
+static void idb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+{
+    guint j;
+    wtap_optionblock_t src_if_stats, dest_if_stats;
+    wtapng_if_descr_mandatory_t *src_mand = (wtapng_if_descr_mandatory_t*)src_block->mandatory_data,
+                                *dest_mand = (wtapng_if_descr_mandatory_t*)dest_block->mandatory_data;
+
+    /* Need special consideration for copying of the interface_statistics member */
+    if (dest_mand->num_stat_entries != 0)
+        g_array_free(dest_mand->interface_statistics, TRUE);
+
+    memcpy(dest_mand, src_mand, sizeof(wtapng_if_descr_mandatory_t));
+    if (src_mand->num_stat_entries != 0)
     {
-        src_opttype = g_array_index(src_block->options, wtap_opttype_t*, i);
-        dest_opttype = wtap_optionblock_get_option(dest_block, src_opttype->number);
-        if (dest_opttype == NULL)
-        {
-            /* Option doesn't exist, add it */
-            switch(src_opttype->type)
-            {
-            case WTAP_OPTTYPE_UINT8:
-                wtap_optionblock_add_option_uint8(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
-                                                  src_opttype->option.uint8val, src_opttype->default_val.uint8val);
-                break;
-            case WTAP_OPTTYPE_UINT64:
-                wtap_optionblock_add_option_uint64(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
-                                                  src_opttype->option.uint64val, src_opttype->default_val.uint64val);
-                break;
-            case WTAP_OPTTYPE_STRING:
-                wtap_optionblock_add_option_string(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
-                                                  src_opttype->option.stringval, src_opttype->default_val.stringval);
-                break;
-            case WTAP_OPTTYPE_CUSTOM:
-                wtap_optionblock_add_option_custom(dest_block, src_opttype->number, src_opttype->name, src_opttype->description,
-                                                 src_opttype->option.customval.data, src_opttype->default_val.customval.data,
-                                                 src_opttype->option.customval.size, src_opttype->option.customval.free_func);
-                break;
-            }
-        }
-        else
+        dest_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+        for (j = 0; j < src_mand->num_stat_entries; j++)
         {
-            /* Option exists, replace it */
-            switch(src_opttype->type)
-            {
-            case WTAP_OPTTYPE_UINT8:
-                dest_opttype->option.uint8val = src_opttype->option.uint8val;
-                break;
-            case WTAP_OPTTYPE_UINT64:
-                dest_opttype->option.uint64val = src_opttype->option.uint64val;
-                break;
-            case WTAP_OPTTYPE_STRING:
-                g_free(dest_opttype->option.stringval);
-                dest_opttype->option.stringval = g_strdup(src_opttype->option.stringval);
-                break;
-            case WTAP_OPTTYPE_CUSTOM:
-                dest_opttype->option.customval.free_func(dest_opttype->option.customval.data);
-                g_free(dest_opttype->option.customval.data);
-                dest_opttype->option.customval.data = g_memdup(src_opttype->option.customval.data, src_opttype->option.customval.size);
-                break;
-            }
+            src_if_stats = g_array_index(src_mand->interface_statistics, wtap_optionblock_t, j);
+            dest_if_stats = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
+            wtap_optionblock_copy_options(dest_if_stats, src_if_stats);
+            dest_mand->interface_statistics = g_array_append_val(dest_mand->interface_statistics, dest_if_stats);
         }
     }
 }
+
+void wtap_opttypes_initialize(void)
+{
+    static wtap_opt_register_t shb_block = {
+        "SHB",              /* name */
+        "Section Header Block",  /* description */
+        shb_create,         /* create */
+        NULL,               /* free_mand */
+        shb_copy_mand,      /* copy_mand */
+    };
+
+    static wtap_opt_register_t nrb_block = {
+        "NRB",              /* name */
+        "Name Resolution Block",  /* description */
+        nrb_create,         /* create */
+        NULL,               /* free_mand */
+        NULL,               /* copy_mand */
+    };
+
+    static wtap_opt_register_t isb_block = {
+        "ISB",              /* name */
+        "Interface Statistics Block",  /* description */
+        isb_create,         /* create */
+        NULL,               /* free_mand */
+        isb_copy_mand,      /* copy_mand */
+    };
+
+    static wtap_opt_register_t idb_block = {
+        "IDB",              /* name */
+        "Interface Description Block",  /* description */
+        idb_create,         /* create */
+        idb_free_mand,      /* free_mand */
+        idb_copy_mand,      /* copy_mand */
+    };
+
+    /* Initialize the block array.  This is mostly for future proofing
+       "outside registered" block types (for NULL checking) */
+    memset(block_list, 0, WTAP_OPTION_BLOCK_MAX_TYPE*sizeof(wtap_opt_register_t*));
+
+    wtap_opttype_block_register(WTAP_OPTION_BLOCK_NG_SECTION, &shb_block );
+    wtap_opttype_block_register(WTAP_OPTION_BLOCK_NG_NRB, &nrb_block );
+    wtap_opttype_block_register(WTAP_OPTION_BLOCK_IF_STATS, &isb_block );
+    wtap_opttype_block_register(WTAP_OPTION_BLOCK_IF_DESCR, &idb_block );
+}
index f25e07f38845bc512d1857a543d9c325a501e549..7d404f221dd83b8e17bdeaf600d5ae4a1e2e00a9 100644 (file)
@@ -29,7 +29,8 @@ typedef enum {
     WTAP_OPTION_BLOCK_IF_DESCR = 0,
     WTAP_OPTION_BLOCK_IF_STATS,
     WTAP_OPTION_BLOCK_NG_SECTION,
-    WTAP_OPTION_BLOCK_NG_NRB
+    WTAP_OPTION_BLOCK_NG_NRB,
+    WTAP_OPTION_BLOCK_MAX_TYPE
 } wtap_optionblock_type_t;
 
 /* Currently supported option types */