Redo the block options APIs.
authorGuy Harris <guy@alum.mit.edu>
Thu, 14 Jul 2016 23:01:57 +0000 (16:01 -0700)
committerGuy Harris <guy@alum.mit.edu>
Thu, 14 Jul 2016 23:02:39 +0000 (23:02 +0000)
A block can have zero or more instances of a given option.  We
distinguish between "one instance only" options, where a block can have
zero or one instance, and "multiple instances allowed" options, where a
block can have zero or more instances.

For "one instance only" options:

"add" routines add an instance if there isn't one already
and fail if there is;

"set" routines add an instance if there isn't one already
and change the value of the existing instance if there is one;

"set nth" routines fail;

"get" routines return the value of the instance if there is one
and fail if there isn't;

"get nth" routines fail.

For "multiple instances allowed" options:

"add" routines add an instance;

"set" routines fail;

"set nth" routines set the value of the nth instance if there is
one and fail otherwise;

"get" routines fail;

"get nth" routines get the value if the nth instance if there is
one and fail otherwise.

Rename "optionblock" to just "block"; it describes the contents of a
block, including both mandatory items and options.

Add some support for NRB options, including IPv4 and IPv6 option types.

Change-Id: Iad184f668626c3d1498b2ed00c7f1672e4abf52e
Reviewed-on: https://code.wireshark.org/review/16444
Reviewed-by: Guy Harris <guy@alum.mit.edu>
24 files changed:
capinfos.c
cfile.c
editcap.c
epan/wslua/wslua.h
epan/wslua/wslua_capture_info.c
file.c
reordercap.c
summary.c
tshark.c
ui/gtk/file_import_dlg.c
ui/gtk/summary_dlg.c
ui/qt/capture_file_properties_dialog.cpp
ui/qt/resolved_addresses_dialog.cpp
ui/tap_export_pdu.c
wiretap/erf.c
wiretap/file_access.c
wiretap/lanalyzer.c
wiretap/merge.c
wiretap/nettrace_3gpp_32_423.c
wiretap/pcapng.c
wiretap/wtap.c
wiretap/wtap.h
wiretap/wtap_opttypes.c
wiretap/wtap_opttypes.h

index de38662c8b2c93a4d068701fb324301b801ed620..f4ea0bb63ac01b01a70ab45989ad815de08fa12e 100644 (file)
@@ -194,7 +194,7 @@ typedef struct _capture_info {
   int            file_encap;
   int            file_tsprec;
   gint64         filesize;
-  wtap_optionblock_t shb;
+  wtap_block_t   shb;
   guint64        packet_bytes;
   gboolean       times_known;
   nstime_t       start_time;
@@ -712,24 +712,22 @@ print_stats(const gchar *filename, capture_info *cf_info)
 
   if (cf_info->shb != NULL) {
     if (cap_comment) {
-      GArray *opts;
       unsigned int i;
+      char *str;
 
-      wtap_optionblock_get_string_options(cf_info->shb, OPT_COMMENT, &opts);
-      for (i = 0; i < opts->len; i++) {
-        show_option_string("Capture comment:     ", g_array_index(opts, char *, i));
+      for (i = 0; wtap_block_get_nth_string_option_value(cf_info->shb, OPT_COMMENT, i, &str) == WTAP_OPTTYPE_SUCCESS; i++) {
+        show_option_string("Capture comment:     ", str);
       }
-      g_array_free(opts, TRUE);
     }
     if (cap_file_more_info) {
       char *str;
 
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_HARDWARE, &str);
-      show_option_string("Capture hardware:    ", str);
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_OS, &str);
-      show_option_string("Capture oper-sys:    ", str);
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_USERAPPL, &str);
-      show_option_string("Capture application: ", str);
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS)
+        show_option_string("Capture hardware:    ", str);
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS)
+        show_option_string("Capture oper-sys:    ", str);
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS)
+        show_option_string("Capture application: ", str);
     }
 
     if (cap_file_idb && cf_info->num_interfaces != 0) {
@@ -991,13 +989,10 @@ print_stats_table(const gchar *filename, capture_info *cf_info)
      * of options
      */
     if (cap_comment) {
-      GArray *opts;
       unsigned int i;
+      char *opt_comment;
 
-      wtap_optionblock_get_string_options(cf_info->shb, OPT_COMMENT, &opts);
-      for (i = 0; i < opts->len; i++) {
-        const char *opt_comment = g_array_index(opts, char *, i);
-
+      for (i = 0; wtap_block_get_nth_string_option_value(cf_info->shb, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) {
         if (opt_comment != NULL) {
           putsep();
           putquote();
@@ -1005,28 +1000,27 @@ print_stats_table(const gchar *filename, capture_info *cf_info)
           putquote();
         }
       }
-      g_array_free(opts, TRUE);
     }
 
     if (cap_file_more_info) {
       char *str;
 
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_HARDWARE, &str);
-      if (str != NULL) {
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS &&
+          str != NULL) {
         putsep();
         putquote();
         printf("%s", str);
         putquote();
       }
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_OS, &str);
-      if (str != NULL) {
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS &&
+          str != NULL) {
         putsep();
         putquote();
         printf("%s", str);
         putquote();
       }
-      wtap_optionblock_get_option_string(cf_info->shb, OPT_SHB_USERAPPL, &str);
-      if (str != NULL) {
+      if (wtap_block_get_string_option_value(cf_info->shb, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS &&
+          str != NULL) {
         putsep();
         putquote();
         printf("%s", str);
@@ -1213,7 +1207,7 @@ process_cap_file(wtap *wth, const char *filename)
   cf_info.idb_info_strings = g_array_sized_new(FALSE, FALSE, sizeof(gchar*), cf_info.num_interfaces);
   cf_info.num_interfaces = idb_info->interface_data->len;
   for (i = 0; i < cf_info.num_interfaces; i++) {
-    const wtap_optionblock_t if_descr = g_array_index(idb_info->interface_data, wtap_optionblock_t, i);
+    const wtap_block_t if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i);
     gchar *s = wtap_get_debug_if_descr(if_descr, 21, "\n");
     g_array_append_val(cf_info.idb_info_strings, s);
   }
diff --git a/cfile.c b/cfile.c
index e2dafe569cd4fc09f6865d0b06005ef1f0821b05..382995e696ccee40380ded5daa31358674a97a23 100644 (file)
--- a/cfile.c
+++ b/cfile.c
@@ -35,22 +35,22 @@ cap_file_get_interface_name(void *data, guint32 interface_id)
 {
   capture_file *cf = (capture_file *) data;
   wtapng_iface_descriptions_t *idb_info;
-  wtap_optionblock_t wtapng_if_descr = NULL;
+  wtap_block_t wtapng_if_descr = NULL;
   char* interface_name;
 
   idb_info = wtap_file_get_idb_info(cf->wth);
 
   if (interface_id < idb_info->interface_data->len)
-    wtapng_if_descr = g_array_index(idb_info->interface_data, wtap_optionblock_t, interface_id);
+    wtapng_if_descr = g_array_index(idb_info->interface_data, wtap_block_t, interface_id);
 
   g_free(idb_info);
 
   if (wtapng_if_descr) {
-    wtap_optionblock_get_option_string(wtapng_if_descr, OPT_IDB_NAME, &interface_name);
-    if (interface_name)
+    if (wtap_block_get_string_option_value(wtapng_if_descr, OPT_IDB_NAME, &interface_name) == WTAP_OPTTYPE_SUCCESS &&
+        interface_name)
       return interface_name;
-    wtap_optionblock_get_option_string(wtapng_if_descr, OPT_IDB_DESCR, &interface_name);
-    if (interface_name)
+    if (wtap_block_get_string_option_value(wtapng_if_descr, OPT_IDB_DESCR, &interface_name) == WTAP_OPTTYPE_SUCCESS &&
+        interface_name)
       return interface_name;
   }
   return "unknown";
index 4ece4ef944269380477dd1abb5d997e0cd58cd55..5a106a630a3f903693445d999caba7e462bc0581 100644 (file)
--- a/editcap.c
+++ b/editcap.c
@@ -1378,9 +1378,9 @@ main(int argc, char *argv[])
                 g_assert(filename);
 
                 /* If we don't have an application name add Editcap */
-                wtap_optionblock_get_option_string(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, &shb_user_appl);
-                if (shb_user_appl == NULL) {
-                    wtap_optionblock_set_option_string_format(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, "Editcap " VERSION);
+                if (wtap_block_get_string_option_value(g_array_index(shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, &shb_user_appl) != WTAP_OPTTYPE_SUCCESS ||
+                    shb_user_appl == NULL) {
+                    wtap_block_add_string_option_format(g_array_index(shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, "Editcap " VERSION);
                 }
 
                 pdh = editcap_dump_open(filename,
@@ -1842,9 +1842,9 @@ main(int argc, char *argv[])
                     wtap_strerror(write_err));
             goto error_on_exit;
         }
-        wtap_optionblock_array_free(shb_hdrs);
+        wtap_block_array_free(shb_hdrs);
         shb_hdrs = NULL;
-        wtap_optionblock_array_free(nrb_hdrs);
+        wtap_block_array_free(nrb_hdrs);
         nrb_hdrs = NULL;
         g_free(filename);
 
@@ -1868,8 +1868,8 @@ main(int argc, char *argv[])
     return 0;
 
 error_on_exit:
-    wtap_optionblock_array_free(shb_hdrs);
-    wtap_optionblock_array_free(nrb_hdrs);
+    wtap_block_array_free(shb_hdrs);
+    wtap_block_array_free(nrb_hdrs);
     g_free(idb_inf);
     exit(2);
 }
index 32f5bcb2ec1f475432a87e6741145935c52da692..333c1796871c171385b76d1a6ba58112f1fb7880 100644 (file)
@@ -557,8 +557,23 @@ extern int wslua_set__index(lua_State *L);
     WSLUA_ATTRIBUTE_GET(C,name, { \
         char* str;  \
         if ((obj->member) && (obj->member->len > 0)) { \
-            wtap_optionblock_get_option_string(g_array_index(obj->member, wtap_optionblock_t, 0), option, &str); \
-            lua_pushstring(L,str); /* this pushes nil if obj->member is null */ \
+            if (wtap_block_get_string_option_value(g_array_index(obj->member, wtap_block_t, 0), option, &str) == WTAP_OPTTYPE_SUCCESS) { \
+                lua_pushstring(L,str); /* this pushes nil if obj->member is null */ \
+            } \
+        } \
+    })
+
+/*
+ * XXX - we need to support Lua programs getting instances of a "multiple
+ * allowed" option other than the first option.
+ */
+#define WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_NTH_STRING_GETTER(C,name,member,option) \
+    WSLUA_ATTRIBUTE_GET(C,name, { \
+        char* str;  \
+        if ((obj->member) && (obj->member->len > 0)) { \
+            if (wtap_block_get_nth_string_option_value(g_array_index(obj->member, wtap_block_t, 0), option, 0, &str) == WTAP_OPTTYPE_SUCCESS) { \
+                lua_pushstring(L,str); /* this pushes nil if obj->member is null */ \
+            } \
         } \
     })
 
@@ -620,7 +635,25 @@ extern int wslua_set__index(lua_State *L);
             return luaL_error(L, "%s's attribute `%s' must be a string or nil", #C , #field ); \
         } \
         if ((obj->member) && (obj->member->len > 0)) { \
-            wtap_optionblock_set_option_string(g_array_index(obj->member, wtap_optionblock_t, 0), option, s, strlen(s)); \
+            wtap_block_set_string_option_value(g_array_index(obj->member, wtap_block_t, 0), option, s, strlen(s)); \
+        } \
+        g_free(s); \
+        return 0; \
+    } \
+    /* silly little trick so we can add a semicolon after this macro */ \
+    typedef void __dummy##C##_set_##field
+
+#define WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_NTH_STRING_SETTER(C,field,member,option) \
+    static int C##_set_##field (lua_State* L) { \
+        C obj = check##C (L,1); \
+        gchar* s = NULL; \
+        if (lua_isstring(L,-1) || lua_isnil(L,-1)) { \
+            s = g_strdup(lua_tostring(L,-1)); \
+        } else { \
+            return luaL_error(L, "%s's attribute `%s' must be a string or nil", #C , #field ); \
+        } \
+        if ((obj->member) && (obj->member->len > 0)) { \
+            wtap_block_set_nth_string_option_value(g_array_index(obj->member, wtap_block_t, 0), option, 0, s, strlen(s)); \
         } \
         g_free(s); \
         return 0; \
index e0293dad0b95e9e94258638df4628ebc45e78740..433604770ef10818b9b0e51ceb1a64bf6050b296 100644 (file)
@@ -119,8 +119,8 @@ WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(CaptureInfo,snapshot_length,wth->snapshot_le
 
 /* WSLUA_ATTRIBUTE CaptureInfo_comment RW A string comment for the whole capture file,
     or nil if there is no `comment`. */
-WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_STRING_GETTER(CaptureInfo,comment,wth->shb_hdrs,OPT_COMMENT);
-WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_STRING_SETTER(CaptureInfo,comment,wth->shb_hdrs,OPT_COMMENT);
+WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_NTH_STRING_GETTER(CaptureInfo,comment,wth->shb_hdrs,OPT_COMMENT);
+WSLUA_ATTRIBUTE_NAMED_OPT_BLOCK_NTH_STRING_SETTER(CaptureInfo,comment,wth->shb_hdrs,OPT_COMMENT);
 
 /* WSLUA_ATTRIBUTE CaptureInfo_hardware RW A string containing the description of
     the hardware used to create the capture, or nil if there is no `hardware` string. */
diff --git a/file.c b/file.c
index ba84efbd13e124598a759019f014f25c033abf79..db3a4be8de5ebd6573b6f4484f34898e7b7129ba 100644 (file)
--- a/file.c
+++ b/file.c
@@ -3839,28 +3839,47 @@ cf_unignore_frame(capture_file *cf, frame_data *frame)
 const gchar *
 cf_read_shb_comment(capture_file *cf)
 {
-  /* Get info from SHB */
-  return wtap_file_get_shb_comment(cf->wth);
+  wtap_block_t shb_inf;
+  char *shb_comment;
+
+  /* Get the SHB. */
+  /* XXX - support multiple SHBs */
+  shb_inf = wtap_file_get_shb(cf->wth);
+
+  /* Get the first comment from the SHB. */
+  /* XXX - support multiple comments */
+  if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
+    return NULL;
+  return shb_comment;
 }
 
 void
 cf_update_capture_comment(capture_file *cf, gchar *comment)
 {
-  const gchar *shb_comment;
-
-  /* Get info from SHB */
-  shb_comment = wtap_file_get_shb_comment(cf->wth);
-
-  /* See if the comment has changed or not */
-  if (shb_comment) {
-    if (strcmp(shb_comment, comment) == 0) {
-      g_free(comment);
-      return;
+  wtap_block_t shb_inf;
+  gchar *shb_comment;
+
+  /* Get the SHB. */
+  /* XXX - support multiple SHBs */
+  shb_inf = wtap_file_get_shb(cf->wth);
+
+  /* Get the first comment from the SHB. */
+  /* XXX - support multiple comments */
+  if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
+    /* There's no comment - add one. */
+    wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
+  } else {
+    /* See if the comment has changed or not */
+    if (shb_comment) {
+      if (strcmp(shb_comment, comment) == 0) {
+        g_free(comment);
+        return;
+      }
     }
-  }
 
-  /* The comment has changed, let's update it */
-  wtap_write_shb_comment(cf->wth, comment);
+    /* The comment has changed, let's update it */
+    wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
+  }
   /* Mark the file as having unsaved changes */
   cf->unsaved_changes = TRUE;
 }
index ae1e013320b5ed8958852d25225c98b15bcfdf17..206a4888c83063524c422609410f5532f9a16719 100644 (file)
@@ -308,8 +308,8 @@ main(int argc, char *argv[])
     if (pdh == NULL) {
         fprintf(stderr, "reordercap: Failed to open output file: (%s) - error %s\n",
                 outfile, wtap_strerror(err));
-        wtap_optionblock_array_free(shb_hdrs);
-        wtap_optionblock_array_free(nrb_hdrs);
+        wtap_block_array_free(shb_hdrs);
+        wtap_block_array_free(nrb_hdrs);
         exit(1);
     }
 
@@ -382,12 +382,12 @@ main(int argc, char *argv[])
     if (!wtap_dump_close(pdh, &err)) {
         fprintf(stderr, "reordercap: Error closing %s: %s\n", outfile,
                 wtap_strerror(err));
-        wtap_optionblock_array_free(shb_hdrs);
-        wtap_optionblock_array_free(nrb_hdrs);
+        wtap_block_array_free(shb_hdrs);
+        wtap_block_array_free(nrb_hdrs);
         exit(1);
     }
-    wtap_optionblock_array_free(shb_hdrs);
-    wtap_optionblock_array_free(nrb_hdrs);
+    wtap_block_array_free(shb_hdrs);
+    wtap_block_array_free(nrb_hdrs);
 
     /* Finally, close infile */
     wtap_fdclose(wth);
index 77cd3886a5eb7be34f6782a064fcf0860c1d4f18..a0f7965f48f6f92f3cfcbe4cdb98687c178d7146 100644 (file)
--- a/summary.c
+++ b/summary.c
@@ -110,9 +110,9 @@ summary_fill_in(capture_file *cf, summary_tally *st)
   iface_options iface;
   guint i;
   wtapng_iface_descriptions_t* idb_info;
-  wtap_optionblock_t wtapng_if_descr;
+  wtap_block_t wtapng_if_descr;
   wtapng_if_descr_mandatory_t *wtapng_if_descr_mand;
-  wtap_optionblock_t if_stats;
+  wtap_block_t if_stats;
   guint64 isb_ifdrop;
   char* if_string;
   wtapng_if_descr_filter_t* if_filter;
@@ -163,14 +163,23 @@ summary_fill_in(capture_file *cf, summary_tally *st)
   st->ifaces  = g_array_new(FALSE, FALSE, sizeof(iface_options));
   idb_info = wtap_file_get_idb_info(cf->wth);
   for (i = 0; i < idb_info->interface_data->len; i++) {
-    wtapng_if_descr = g_array_index(idb_info->interface_data, wtap_optionblock_t, i);
-    wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wtapng_if_descr);
-    wtap_optionblock_get_option_custom(wtapng_if_descr, OPT_IDB_FILTER, (void**)&if_filter);
-    iface.cfilter = g_strdup(if_filter->if_filter_str);
-    wtap_optionblock_get_option_string(wtapng_if_descr, OPT_IDB_NAME, &if_string);
-    iface.name = g_strdup(if_string);
-    wtap_optionblock_get_option_string(wtapng_if_descr, OPT_IDB_DESCR, &if_string);
-    iface.descr = g_strdup(if_string);
+    wtapng_if_descr = g_array_index(idb_info->interface_data, wtap_block_t, i);
+    wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wtapng_if_descr);
+    if (wtap_block_get_custom_option_value(wtapng_if_descr, OPT_IDB_FILTER, (void**)&if_filter) == WTAP_OPTTYPE_SUCCESS) {
+      iface.cfilter = g_strdup(if_filter->if_filter_str);
+    } else {
+      iface.cfilter = NULL;
+    }
+    if (wtap_block_get_string_option_value(wtapng_if_descr, OPT_IDB_NAME, &if_string) == WTAP_OPTTYPE_SUCCESS) {
+      iface.name = g_strdup(if_string);
+    } else {
+      iface.name = NULL;
+    }
+    if (wtap_block_get_string_option_value(wtapng_if_descr, OPT_IDB_DESCR, &if_string) == WTAP_OPTTYPE_SUCCESS) {
+      iface.descr = g_strdup(if_string);
+    } else {
+      iface.descr = NULL;
+    }
     iface.drops_known = FALSE;
     iface.drops = 0;
     iface.snap = wtapng_if_descr_mand->snap_len;
@@ -179,14 +188,16 @@ summary_fill_in(capture_file *cf, summary_tally *st)
     iface.isb_comment = NULL;
     if(wtapng_if_descr_mand->num_stat_entries == 1){
       /* dumpcap only writes one ISB, only handle that for now */
-      if_stats = g_array_index(wtapng_if_descr_mand->interface_statistics, wtap_optionblock_t, 0);
-      wtap_optionblock_get_option_uint64(if_stats, OPT_ISB_IFDROP, &isb_ifdrop);
-      if (isb_ifdrop != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) {
+      if_stats = g_array_index(wtapng_if_descr_mand->interface_statistics, wtap_block_t, 0);
+      if (wtap_block_get_uint64_option_value(if_stats, OPT_ISB_IFDROP, &isb_ifdrop) == WTAP_OPTTYPE_SUCCESS) {
         iface.drops_known = TRUE;
         iface.drops = isb_ifdrop;
       }
       /* XXX: this doesn't get used, and might need to be g_strdup'ed when it does */
-      wtap_optionblock_get_option_string(if_stats, OPT_COMMENT, &iface.isb_comment);
+      /* XXX - support multiple comments */
+      if (wtap_block_get_nth_string_option_value(if_stats, OPT_COMMENT, 0, &iface.isb_comment) != WTAP_OPTTYPE_SUCCESS) {
+        iface.isb_comment = NULL;
+      }
     }
     g_array_append_val(st->ifaces, iface);
   }
index 58f1765028204df88f549ccc15c21ff6cfe45e92..8fac691195623d20f2fa0dd6abc08bc8dcf45874 100644 (file)
--- a/tshark.c
+++ b/tshark.c
@@ -2877,10 +2877,10 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
     nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
 
     /* If we don't have an application name add Tshark */
-    wtap_optionblock_get_option_string(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, &shb_user_appl);
-    if (shb_user_appl == NULL) {
-        /* this is free'd by wtap_optionblock_free() later */
-        wtap_optionblock_set_option_string_format(g_array_index(shb_hdrs, wtap_optionblock_t, 0), OPT_SHB_USERAPPL, "TShark (Wireshark) %s", get_ws_vcs_version_info());
+    if (wtap_block_get_string_option_value(g_array_index(shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, &shb_user_appl) != WTAP_OPTTYPE_SUCCESS ||
+        shb_user_appl == NULL) {
+        /* this is free'd by wtap_block_free() later */
+        wtap_block_add_string_option_format(g_array_index(shb_hdrs, wtap_block_t, 0), OPT_SHB_USERAPPL, "TShark (Wireshark) %s", get_ws_vcs_version_info());
     }
 
     if (linktype != WTAP_ENCAP_PER_PACKET &&
@@ -3121,8 +3121,8 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
                 break;
               }
               wtap_dump_close(pdh, &err);
-              wtap_optionblock_array_free(shb_hdrs);
-              wtap_optionblock_array_free(nrb_hdrs);
+              wtap_block_array_free(shb_hdrs);
+              wtap_block_array_free(nrb_hdrs);
               exit(2);
             }
           }
@@ -3236,8 +3236,8 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type,
               break;
             }
             wtap_dump_close(pdh, &err);
-            wtap_optionblock_array_free(shb_hdrs);
-            wtap_optionblock_array_free(nrb_hdrs);
+            wtap_block_array_free(shb_hdrs);
+            wtap_block_array_free(nrb_hdrs);
             exit(2);
           }
         }
@@ -3353,8 +3353,8 @@ out:
   cf->wth = NULL;
 
   g_free(save_file_string);
-  wtap_optionblock_array_free(shb_hdrs);
-  wtap_optionblock_array_free(nrb_hdrs);
+  wtap_block_array_free(shb_hdrs);
+  wtap_block_array_free(nrb_hdrs);
 
   return err;
 }
index 338c312ad47d20af9b93923a970443852255707e..dc6a97a4f52419d8e418a5b557386bec802ed474 100644 (file)
@@ -458,10 +458,10 @@ file_import_open(text_import_info_t *info)
     int   err;
 
     /* pcapng defs */
-    wtap_optionblock_t           shb_hdr;
-    GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+    wtap_block_t                 shb_hdr;
+    GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
     wtapng_iface_descriptions_t *idb_inf;
-    wtap_optionblock_t           int_data;
+    wtap_block_t                 int_data;
     wtapng_if_descr_mandatory_t *int_data_mand;
     GString                     *os_info_str;
     gsize                        opt_len;
@@ -470,35 +470,35 @@ file_import_open(text_import_info_t *info)
     os_info_str = g_string_new("");
     get_os_version_info(os_info_str);
 
-    shb_hdr = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
+    shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
 
     /* options */
-    wtap_optionblock_set_option_string_format(shb_hdr, OPT_COMMENT, "File created by File->Import of file %s", info->import_text_filename);
+    wtap_block_add_string_option_format(shb_hdr, OPT_COMMENT, "File created by File->Import of file %s", info->import_text_filename);
 
     /*
      * UTF-8 string containing the name of the operating system used to create
      * this section.
      */
     opt_len = os_info_str->len;
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
+    wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
     /*
      * UTF-8 string containing the name of the application used to create
      * this section.
      */
-    wtap_optionblock_set_option_string_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
+    wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
 
     /* Create fake IDB info */
     idb_inf = g_new(wtapng_iface_descriptions_t,1);
-    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
     /* create the fake interface data */
-    int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+    int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
     int_data_mand->wtap_encap            = info->encapsulation;
     int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
     int_data_mand->link_type             = wtap_wtap_encap_to_pcap_encap(info->encapsulation);
     int_data_mand->snap_len              = WTAP_MAX_PACKET_SIZE;
-    wtap_optionblock_set_option_string(int_data, OPT_IDB_NAME, "Fake IF File->Import", strlen("Fake IF File->Import"));
+    wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF File->Import", strlen("Fake IF File->Import"));
 
     g_array_append_val(idb_inf->interface_data, int_data);
     g_array_append_val(shb_hdrs, shb_hdr);
@@ -557,7 +557,7 @@ end:
     g_free(info->date_timestamp_format);
     g_free(info);
     g_free(capfile_name);
-    wtap_optionblock_array_free(shb_hdrs);
+    wtap_block_array_free(shb_hdrs);
     wtap_free_idb_info(idb_inf);
     window_destroy(file_import_dlg_w);
 }
index 8bb85774ab1483ce2da4e3a29d0f9c45294e812e..78f596c49eec7701da4dc921e6cf8aa1242bde96 100644 (file)
@@ -188,9 +188,8 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_)
 
   unsigned int  elapsed_time;
   iface_options iface;
-  wtap_optionblock_t shb_inf;
+  wtap_block_t  shb_inf;
   unsigned int  i;
-  GArray       *opts;
 
   if (summary_dlg != NULL) {
     /* There's already a Summary dialog box; reactivate it. */
@@ -293,14 +292,13 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_)
     buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (comment_view));
     gtk_text_buffer_set_text (buffer, "", -1);
     if (shb_inf != NULL) {
-      wtap_optionblock_get_string_options(shb_inf, OPT_COMMENT, &opts);
-      for (i = 0; i < opts->len; i++) {
-        /* XXX - this only shows the last comment */
-        char *opt_comment = g_array_index(opts, char *, i);
+      char *opt_comment;
+
+      /* XXX - this only shows the last comment */
+      for (i = 0; wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) {
         if (opt_comment != NULL && opt_comment[0] != '\0')
           gtk_text_buffer_set_text (buffer, opt_comment, -1);
       }
-      g_array_free(opts, TRUE);
     }
     gtk_box_pack_start(GTK_BOX(comment_vbox), comment_view, TRUE, TRUE, 0);
     gtk_widget_show (comment_view);
@@ -350,21 +348,21 @@ summary_open_cb(GtkWidget *w _U_, gpointer d _U_)
   if (shb_inf != NULL) {
     char *str;
 
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_HARDWARE, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s", str);
       add_string_to_grid(grid, &row, "Capture HW:",string_buff);
     }
 
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_OS, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       /* truncate the strings to a reasonable length */
       g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s", str);
       add_string_to_grid(grid, &row, "OS:", string_buff);
     }
 
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_USERAPPL, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       /* truncate the strings to a reasonable length */
       g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s", str);
       add_string_to_grid(grid, &row, "Capture application:", string_buff);
@@ -664,8 +662,7 @@ summary_to_texbuff(GtkTextBuffer *buffer)
   summary_tally summary;
   gchar         string_buff[SUM_STR_MAX];
   gchar         tmp_buff[SUM_STR_MAX];
-  wtap_optionblock_t shb_inf;
-  GArray       *opts;
+  wtap_block_t shb_inf;
   unsigned int  i;
   unsigned int  elapsed_time;
   iface_options iface;
@@ -768,20 +765,20 @@ summary_to_texbuff(GtkTextBuffer *buffer)
   if (shb_inf != NULL) {
     char *str;
 
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_HARDWARE, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       /* truncate the string to a reasonable length */
       g_snprintf(string_buff, SUM_STR_MAX, INDENT "Capture HW: %s\n", str);
       gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
     }
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_OS, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       /* truncate the strings to a reasonable length */
       g_snprintf(string_buff, SUM_STR_MAX, INDENT "OS: %s\n", str);
       gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
     }
-    wtap_optionblock_get_option_string(shb_inf, OPT_SHB_USERAPPL, &str);
-    if (str != NULL && str[0] != '\0') {
+    if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS &&
+        str != NULL && str[0] != '\0') {
       /* truncate the string to a reasonable length */
       g_snprintf(string_buff, SUM_STR_MAX, INDENT "Capture application: %s\n", str);
       gtk_text_buffer_insert_at_cursor (buffer, string_buff, -1);
@@ -901,10 +898,10 @@ summary_to_texbuff(GtkTextBuffer *buffer)
   /* Trace file comments from SHB */
   shb_inf = wtap_file_get_shb(cfile.wth);
   if (shb_inf != NULL) {
-    wtap_optionblock_get_string_options(shb_inf, OPT_COMMENT, &opts);
-    for (i = 0; i < opts->len; i++) {
+    char *opt_comment;
+
+    for (i = 0; wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, i, &opt_comment) == WTAP_OPTTYPE_SUCCESS; i++) {
       /* XXX - separator between comments? */
-      char *opt_comment = g_array_index(opts, char *, i);
       if (opt_comment != NULL && opt_comment[0] != '\0')
         gtk_text_buffer_insert_at_cursor(buffer, opt_comment, -1);
     }
index 59c5bcf6d2aef84b349db9584aedcedb049a8e56..60ce9ddcb186fd78432d2d424a871dbbed85e915 100644 (file)
@@ -242,14 +242,15 @@ QString CaptureFilePropertiesDialog::summaryToHtml()
     out << section_tmpl_.arg(tr("Capture"));
     out << table_begin;
 
-    wtap_optionblock_t shb_inf = wtap_file_get_shb(cap_file_.capFile()->wth);
+    wtap_block_t shb_inf = wtap_file_get_shb(cap_file_.capFile()->wth);
     char *str;
 
     if (shb_inf != NULL) {
       QString capture_hardware(unknown);
-      wtap_optionblock_get_option_string(shb_inf, OPT_SHB_HARDWARE, &str);
-      if (str != NULL && str[0] != '\0') {
-          capture_hardware = str;
+      if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_HARDWARE, &str) == WTAP_OPTTYPE_SUCCESS) {
+          if (str != NULL && str[0] != '\0') {
+              capture_hardware = str;
+          }
       }
       // capture HW
       out << table_row_begin
@@ -258,9 +259,10 @@ QString CaptureFilePropertiesDialog::summaryToHtml()
           << table_row_end;
 
       QString capture_os(unknown);
-      wtap_optionblock_get_option_string(shb_inf, OPT_SHB_OS, &str);
-      if (str != NULL && str[0] != '\0') {
-          capture_os = str;
+      if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_OS, &str) == WTAP_OPTTYPE_SUCCESS) {
+          if (str != NULL && str[0] != '\0') {
+              capture_os = str;
+          }
       }
       out << table_row_begin
           << table_vheader_tmpl.arg(tr("OS"))
@@ -268,9 +270,10 @@ QString CaptureFilePropertiesDialog::summaryToHtml()
           << table_row_end;
 
       QString capture_app(unknown);
-      wtap_optionblock_get_option_string(shb_inf, OPT_SHB_USERAPPL, &str);
-      if (str != NULL && str[0] != '\0') {
-          capture_app = str;
+      if (wtap_block_get_string_option_value(shb_inf, OPT_SHB_USERAPPL, &str) == WTAP_OPTTYPE_SUCCESS) {
+          if (str != NULL && str[0] != '\0') {
+              capture_app = str;
+          }
       }
       out << table_row_begin
           << table_vheader_tmpl.arg(tr("Application"))
index 791f6d1ca7111cbb977faf0b8645b32966927478..2e8b45cd0b8207ba4bf9cf46cb88d0604023c5f5 100644 (file)
@@ -197,7 +197,22 @@ ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, CaptureFile *c
         wtap* wth = capture_file->capFile()->wth;
         if (wth) {
             // might return null
-            comment_ = wtap_get_nrb_comment(wth);
+            wtap_block_t nrb_hdr;
+
+            /*
+             * XXX - support multiple NRBs.
+             */
+            nrb_hdr = wtap_file_get_nrb(wth);
+            if (nrb_hdr != NULL) {
+                char *str;
+
+                /*
+                 * XXX - support multiple comments.
+                 */
+                if (wtap_block_get_nth_string_option_value(nrb_hdr, OPT_COMMENT, 0, &str) == WTAP_OPTTYPE_SUCCESS) {
+                    comment_ = str;
+                }
+            }
         }
     }
 
index a151e725671a1bf705b491b514fcad8233d12315..02cd3df33fffd7b66c5228ea510b62d0fa8b8af9 100644 (file)
@@ -102,10 +102,10 @@ exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, char *comment)
     int   err;
 
     /* pcapng defs */
-    wtap_optionblock_t           shb_hdr;
-    GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+    wtap_block_t                 shb_hdr;
+    GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
     wtapng_iface_descriptions_t *idb_inf;
-    wtap_optionblock_t           int_data;
+    wtap_block_t                 int_data;
     wtapng_if_descr_mandatory_t *int_data_mand;
     GString                     *os_info_str;
     gsize                        opt_len;
@@ -114,10 +114,10 @@ exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, char *comment)
     os_info_str = g_string_new("");
     get_os_version_info(os_info_str);
 
-    shb_hdr = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
+    shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
 
     /* options */
-    wtap_optionblock_set_option_string(shb_hdr, OPT_COMMENT, comment, strlen(comment));
+    wtap_block_add_string_option(shb_hdr, OPT_COMMENT, comment, strlen(comment));
     g_free(comment);
 
     /*
@@ -125,27 +125,27 @@ exp_pdu_open(exp_pdu_t *exp_pdu_tap_data, int fd, char *comment)
      * this section.
      */
     opt_len = os_info_str->len;
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
+    wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
     /*
      * UTF-8 string containing the name of the application used to create
      * this section.
      */
-    wtap_optionblock_set_option_string_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
+    wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
 
     /* Create fake IDB info */
     idb_inf = g_new(wtapng_iface_descriptions_t,1);
-    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+    idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
     /* create the fake interface data */
-    int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+    int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
     int_data_mand->wtap_encap      = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
     int_data_mand->time_units_per_second = 1000000000; /* default nanosecond resolution */
     int_data_mand->link_type       = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
     int_data_mand->snap_len        = WTAP_MAX_PACKET_SIZE;
 
-    wtap_optionblock_set_option_string(int_data, OPT_IDB_NAME, "Fake IF, PDU->Export", strlen("Fake IF, PDU->Export"));
-    wtap_optionblock_set_option_uint8(int_data, OPT_IDB_TSRESOL, 9);
+    wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF, PDU->Export", strlen("Fake IF, PDU->Export"));
+    wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 9);
 
     g_array_append_val(idb_inf->interface_data, int_data);
 
index e8208be3611cdf2d6b07964ca1a9490a08fdfb14..e694ade9b2785bcc6bb6d7f3d0384e4c180135c0 100644 (file)
@@ -946,7 +946,7 @@ int erf_dump_open(wtap_dumper *wdh, int *err)
  */
 int erf_populate_interfaces(wtap *wth)
 {
-  wtap_optionblock_t int_data;
+  wtap_block_t int_data;
   wtapng_if_descr_mandatory_t* int_data_mand;
   int i;
 
@@ -956,8 +956,8 @@ int erf_populate_interfaces(wtap *wth)
   /* Preemptively create interface entries for 4 interfaces, since this is the max number in ERF */
   for (i=0; i<4; i++) {
 
-    int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+    int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
 
     int_data_mand->wtap_encap = WTAP_ENCAP_ERF;
     /* int_data.time_units_per_second = (1LL<<32);  ERF format resolution is 2^-32, capture resolution is unknown */
@@ -969,9 +969,9 @@ int erf_populate_interfaces(wtap *wth)
     /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
     /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
     /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
-    wtap_optionblock_set_option_uint64(int_data, OPT_IDB_SPEED, 0); /* Unknown  - XXX should be left at default? */
+    /* XXX: if_speed    opt 8  Interface speed (in bits per second)*/
     /* int_data.if_tsresol = 0xa0;  ERF format resolution is 2^-32 = 0xa0, capture resolution is unknown */
-    wtap_optionblock_set_option_uint8(int_data, OPT_IDB_TSRESOL, 0x09); /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
+    wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0x09); /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
 
     /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
 
@@ -980,8 +980,8 @@ int erf_populate_interfaces(wtap *wth)
     int_data_mand->num_stat_entries = 0;
     int_data_mand->interface_statistics = NULL;
 
-    wtap_optionblock_set_option_string_format(int_data, OPT_IDB_NAME, "Port %c", 'A'+i);
-    wtap_optionblock_set_option_string_format(int_data, OPT_IDB_DESCR, "ERF Interface Id %d (Port %c)", i, 'A'+i);
+    wtap_block_add_string_option_format(int_data, OPT_IDB_NAME, "Port %c", 'A'+i);
+    wtap_block_add_string_option_format(int_data, OPT_IDB_DESCR, "ERF Interface Id %d (Port %c)", i, 'A'+i);
 
     g_array_append_val(wth->interface_data, int_data);
   }
@@ -1065,7 +1065,7 @@ static struct erf_if_mapping* erf_find_interface_mapping(erf_t *erf_priv, guint6
   return (struct erf_if_mapping*) g_hash_table_lookup(erf_priv->if_map, &if_map_lookup);
 }
 
-static void erf_set_interface_descr(wtap_optionblock_t block, guint option_id, guint64 host_id, guint8 source_id, guint8 if_num, const gchar *descr)
+static void erf_set_interface_descr(wtap_block_t block, guint option_id, guint64 host_id, guint8 source_id, guint8 if_num, const gchar *descr)
 {
   /* Source XXX,*/
   char sourceid_buf[16];
@@ -1084,9 +1084,9 @@ static void erf_set_interface_descr(wtap_optionblock_t block, guint option_id, g
   }
 
   if (descr) {
-    wtap_optionblock_set_option_string_format(block, option_id, "%s (ERF%s%s Interface %d)", descr, hostid_buf, sourceid_buf, if_num);
+    wtap_block_set_string_option_value_format(block, option_id, "%s (ERF%s%s Interface %d)", descr, hostid_buf, sourceid_buf, if_num);
   } else {
-    wtap_optionblock_set_option_string_format(block, option_id, "Port %c (ERF%s%s Interface %d)", 'A'+if_num, hostid_buf, sourceid_buf, if_num);
+    wtap_block_set_string_option_value_format(block, option_id, "Port %c (ERF%s%s Interface %d)", 'A'+if_num, hostid_buf, sourceid_buf, if_num);
   }
 }
 
@@ -1096,7 +1096,7 @@ static int erf_update_implicit_host_id(erf_t *erf_priv, wtap *wth, guint64 impli
   gpointer iter_value;
   GList* implicit_list = NULL;
   GList* item = NULL;
-  wtap_optionblock_t int_data;
+  wtap_block_t int_data;
   struct erf_if_mapping* if_map = NULL;
   int i;
 
@@ -1128,7 +1128,7 @@ static int erf_update_implicit_host_id(erf_t *erf_priv, wtap *wth, guint64 impli
       for (i = 0; i < 4; i++) {
         if (if_map->interfaces[i].if_index >= 0) {
           /* XXX: this is a pointer! */
-          int_data = g_array_index(wth->interface_data, wtap_optionblock_t, if_map->interfaces[i].if_index);
+          int_data = g_array_index(wth->interface_data, wtap_block_t, if_map->interfaces[i].if_index);
           erf_set_interface_descr(int_data, OPT_IDB_NAME, implicit_host_id, if_map->source_id, (guint8) i, if_map->interfaces[i].name);
           erf_set_interface_descr(int_data, OPT_IDB_DESCR, implicit_host_id, if_map->source_id, (guint8) i, if_map->interfaces[i].descr);
         }
@@ -1147,7 +1147,7 @@ static int erf_update_implicit_host_id(erf_t *erf_priv, wtap *wth, guint64 impli
 
 int erf_populate_interface(erf_t *erf_priv, wtap *wth, union wtap_pseudo_header *pseudo_header, guint64 host_id, guint8 source_id, guint8 if_num)
 {
-  wtap_optionblock_t int_data;
+  wtap_block_t int_data;
   wtapng_if_descr_mandatory_t* int_data_mand;
   struct erf_if_mapping* if_map = NULL;
 
@@ -1184,8 +1184,8 @@ int erf_populate_interface(erf_t *erf_priv, wtap *wth, union wtap_pseudo_header
     return if_map->interfaces[if_num].if_index;
   }
 
-  int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-  int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+  int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+  int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
 
   int_data_mand->wtap_encap = WTAP_ENCAP_ERF;
   /* int_data.time_units_per_second = (1LL<<32);  ERF format resolution is 2^-32, capture resolution is unknown */
@@ -1197,9 +1197,9 @@ int erf_populate_interface(erf_t *erf_priv, wtap *wth, union wtap_pseudo_header
   /* XXX: if_IPv6addr opt 5  Interface network address and prefix length (stored in the last byte).*/
   /* XXX: if_MACaddr  opt 6  Interface Hardware MAC address (48 bits).*/
   /* XXX: if_EUIaddr  opt 7  Interface Hardware EUI address (64 bits)*/
-  wtap_optionblock_set_option_uint64(int_data, OPT_IDB_SPEED, 0); /* Unknown  - XXX should be left at default? */
+  /* XXX: if_speed    opt 8  Interface speed (in bits per second)*/
   /* int_data.if_tsresol = 0xa0;  ERF format resolution is 2^-32 = 0xa0, capture resolution is unknown */
-  wtap_optionblock_set_option_uint8(int_data, OPT_IDB_TSRESOL, 0x09); /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
+  wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0x09); /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
   /* XXX: if_tzone      10  Time zone for GMT support (TODO: specify better). */
   /* XXX if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
   /* Interface statistics */
@@ -1247,7 +1247,7 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
 {
   struct erf_meta_tag tag = {0, 0, NULL};
 
-  wtap_optionblock_t shb_hdr;
+  wtap_block_t shb_hdr;
   char* tmp;
   gchar* app_name    = NULL;
   gchar* app_version = NULL;
@@ -1262,7 +1262,7 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
 
   /* XXX: wth->shb_hdr is already created by different layer, using directly for now. */
   /* XXX: Only one section header is supported at this time */
-  shb_hdr = g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0);
+  shb_hdr = g_array_index(wth->shb_hdrs, wtap_block_t, 0);
 
   while ((tagtotallength = erf_meta_read_tag(&tag, state->tag_ptr, state->remaining_len)) && !ERF_META_IS_SECTION(tag.type)) {
     switch (state->sectiontype) {
@@ -1274,7 +1274,7 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
 
         switch (tag.type) {
           case ERF_META_TAG_comment:
-            wtap_optionblock_set_option_string(shb_hdr, OPT_COMMENT, tag.value, tag.length);
+            wtap_block_add_string_option(shb_hdr, OPT_COMMENT, tag.value, tag.length);
             break;
         }
         /* Fall through */
@@ -1299,7 +1299,7 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
             descr = g_strndup((gchar*) tag.value, tag.length);
             break;
           case ERF_META_TAG_os:
-            wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_OS, tag.value, tag.length);
+            wtap_block_set_string_option_value(shb_hdr, OPT_SHB_OS, tag.value, tag.length);
             break;
           case ERF_META_TAG_app_name:
             g_free(app_name);
@@ -1328,7 +1328,7 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
     /* If no app_version will just use app_name */
 
     tmp = g_strjoin(" ", app_name, app_version, NULL);
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_USERAPPL, tmp, strlen(tmp));
+    wtap_block_set_string_option_value(shb_hdr, OPT_SHB_USERAPPL, tmp, strlen(tmp));
     g_free(tmp);
 
     g_free(app_name);
@@ -1357,13 +1357,13 @@ static int populate_capture_host_info(erf_t *erf_priv, wtap *wth, union wtap_pse
   /* Combine into "Description (Model; CPU)" */
   if (state->sectiontype == ERF_META_SECTION_HOST && descr) {
     if (modelcpu) {
-      wtap_optionblock_set_option_string_format(shb_hdr, OPT_SHB_HARDWARE, "%s (%s)", descr, modelcpu);
+      wtap_block_set_string_option_value_format(shb_hdr, OPT_SHB_HARDWARE, "%s (%s)", descr, modelcpu);
     } else {
-      wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_HARDWARE, descr, strlen(descr));
+      wtap_block_set_string_option_value(shb_hdr, OPT_SHB_HARDWARE, descr, strlen(descr));
       /*descr = NULL;*/
     }
   } else if (modelcpu) {
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_HARDWARE, modelcpu, strlen(modelcpu));
+    wtap_block_set_string_option_value(shb_hdr, OPT_SHB_HARDWARE, modelcpu, strlen(modelcpu));
     /*modelcpu = NULL;*/
   }
 
@@ -1428,7 +1428,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
   struct erf_meta_tag tag = {0, 0, NULL};
   guint32 tagtotallength;
   int interface_index = -1;
-  wtap_optionblock_t int_data = NULL;
+  wtap_block_t int_data = NULL;
   wtapng_if_descr_mandatory_t* int_data_mand = NULL;
   wtapng_if_descr_filter_t if_filter;
   guint32 if_num = 0;
@@ -1487,8 +1487,8 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
 
     /* Get the wiretap interface metadata */
     if (interface_index >= 0) {
-      int_data = g_array_index(wth->interface_data, wtap_optionblock_t, interface_index);
-      int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+      int_data = g_array_index(wth->interface_data, wtap_block_t, interface_index);
+      int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
     } else if (interface_index == -2) {
       /* timing/unknown port */
       return 0;
@@ -1532,7 +1532,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
         break;
       case ERF_META_TAG_if_speed:
         if (tag.length >= 8)
-          wtap_optionblock_set_option_uint64(int_data, OPT_IDB_SPEED, pntoh64(tag.value));
+          wtap_block_add_uint64_option(int_data, OPT_IDB_SPEED, pntoh64(tag.value));
         break;
       case ERF_META_TAG_if_num:
         /*
@@ -1544,7 +1544,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
         break;
       case ERF_META_TAG_fcs_len:
         if (tag.length >= 4) {
-          wtap_optionblock_set_option_uint8(int_data, OPT_IDB_FCSLEN, (guint8) pntoh32(tag.value));
+          wtap_block_add_uint8_option(int_data, OPT_IDB_FCSLEN, (guint8) pntoh32(tag.value));
           if_info->set_flags.fcs_len = 1;
         }
         break;
@@ -1556,11 +1556,11 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
         }
         break;
       case ERF_META_TAG_comment:
-        wtap_optionblock_set_option_string(int_data, OPT_COMMENT, tag.value, tag.length);
+        wtap_block_add_string_option(int_data, OPT_COMMENT, tag.value, tag.length);
         break;
       case ERF_META_TAG_filter:
         if_filter.if_filter_str = g_strndup((gchar*) tag.value, tag.length);
-        wtap_optionblock_set_option_custom(int_data, OPT_IDB_FILTER, &if_filter);
+       wtap_block_add_custom_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter);
         if_info->set_flags.filter = 1;
         break;
       default:
@@ -1584,7 +1584,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
   if (state->if_map->module_filter_str && !if_info->set_flags.filter) {
     /* Duplicate because might use with multiple interfaces */
     if_filter.if_filter_str = g_strdup(state->if_map->module_filter_str);
-    wtap_optionblock_set_option_custom(int_data, OPT_IDB_FILTER, &if_filter);
+    wtap_block_add_custom_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter);
     /*
      * Don't set flag because stream is more specific than module. Interface
      * metadata bit is set so we don't look at the filter again regardless.
@@ -1592,7 +1592,7 @@ static int populate_interface_info(erf_t *erf_priv, wtap *wth, union wtap_pseudo
   }
 
   if (state->if_map->module_fcs_len != -1 && !if_info->set_flags.fcs_len) {
-    wtap_optionblock_set_option_uint8(int_data, OPT_IDB_FCSLEN, (guint8) state->if_map->module_fcs_len);
+    wtap_block_add_uint8_option(int_data, OPT_IDB_FCSLEN, (guint8) state->if_map->module_fcs_len);
     if_info->set_flags.fcs_len = 1;
   }
 
@@ -1611,7 +1611,7 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud
   struct erf_meta_tag tag = {0, 0, NULL};
   guint32 tagtotallength;
   int interface_index = -1;
-  wtap_optionblock_t int_data = NULL;
+  wtap_block_t int_data = NULL;
   wtapng_if_descr_mandatory_t* int_data_mand = NULL;
   wtapng_if_descr_filter_t if_filter;
   guint32 if_num = 0;
@@ -1673,8 +1673,8 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud
     interface_index = if_info->if_index;
     /* Get the wiretap interface metadata */
     if (interface_index >= 0) {
-        int_data = g_array_index(wth->interface_data, wtap_optionblock_t, interface_index);
-        int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+        int_data = g_array_index(wth->interface_data, wtap_block_t, interface_index);
+        int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
     }
 
     if (!int_data) {
@@ -1689,10 +1689,25 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud
             gint8 fcs_len = (gint8) pntoh32(tag.value);
             guint8 old_fcs_len = 0;
 
-            wtap_optionblock_get_option_uint8(int_data, OPT_IDB_FCSLEN, &old_fcs_len);
-            if (fcs_len > old_fcs_len || !if_info->set_flags.fcs_len) {
-              wtap_optionblock_set_option_uint8(int_data, OPT_IDB_FCSLEN, (guint8) pntoh32(tag.value));
-              if_info->set_flags.fcs_len = 1;
+            switch (wtap_block_get_uint8_option_value(int_data, OPT_IDB_FCSLEN, &old_fcs_len)) {
+
+              case WTAP_OPTTYPE_SUCCESS:
+                /* We already have an FCS length option; update it. */
+                if (fcs_len > old_fcs_len || !if_info->set_flags.fcs_len) {
+                  wtap_block_set_uint8_option_value(int_data, OPT_IDB_FCSLEN, (guint8) pntoh32(tag.value));
+                  if_info->set_flags.fcs_len = 1;
+                }
+                break;
+
+              case WTAP_OPTTYPE_NOT_FOUND:
+                /* We don't have an FCS length option; add it. */
+                wtap_block_add_uint8_option(int_data, OPT_IDB_FCSLEN, (guint8) pntoh32(tag.value));
+                if_info->set_flags.fcs_len = 1;
+                break;
+
+              default:
+                /* "shouldn't happen" */
+                break;
             }
           }
           break;
@@ -1711,7 +1726,7 @@ static int populate_stream_info(erf_t *erf_priv _U_, wtap *wth, union wtap_pseud
           /* Override only if not set */
           if (!if_info->set_flags.filter) {
             if_filter.if_filter_str = g_strndup((gchar*) tag.value, tag.length);
-            wtap_optionblock_set_option_custom(int_data, OPT_IDB_FILTER, &if_filter);
+            wtap_block_add_custom_option(int_data, OPT_IDB_FILTER, &if_filter, sizeof if_filter);
             if_info->set_flags.filter = 1;
           }
           break;
index ff2200bd2d1bac180f0fd754b592d063fbdb1731..1466f562ff8fd4eb0454c085db8c11c594702ab9 100644 (file)
@@ -714,7 +714,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
        unsigned int    i;
        gboolean use_stdin = FALSE;
        gchar *extension;
-       wtap_optionblock_t shb;
+       wtap_block_t shb;
 
        *err = 0;
        *err_info = NULL;
@@ -834,15 +834,15 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
        wth->file_tsprec = WTAP_TSPREC_USEC;
        wth->priv = NULL;
        wth->wslua_data = NULL;
-       wth->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
-       shb = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
+       wth->shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
+       shb = wtap_block_create(WTAP_BLOCK_NG_SECTION);
        if (shb)
                g_array_append_val(wth->shb_hdrs, shb);
 
        /* Initialize the array containing a list of interfaces. pcapng_open and
         * erf_open needs this (and libpcap_open for ERF encapsulation types).
         * Always initing it here saves checking for a NULL ptr later. */
-       wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+       wth->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
        if (wth->random_fh) {
                wth->fast_seek = g_ptr_array_new();
@@ -1103,17 +1103,17 @@ success:
        if ((wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP) ||
                (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC)) {
 
-               wtap_optionblock_t descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-               wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+               wtap_block_t descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+               wtapng_if_descr_mandatory_t* descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
 
                descr_mand->wtap_encap = wth->file_encap;
                if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC) {
                        descr_mand->time_units_per_second = 1000000000; /* nanosecond resolution */
-                       wtap_optionblock_set_option_uint8(descr, OPT_IDB_TSRESOL, 9);
+                       wtap_block_add_uint8_option(descr, OPT_IDB_TSRESOL, 9);
                        descr_mand->tsprecision = WTAP_TSPREC_NSEC;
                } else {
                        descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
-                       wtap_optionblock_set_option_uint8(descr, OPT_IDB_TSRESOL, 6);
+                       /* No need to add an option, this is the default */
                        descr_mand->tsprecision = WTAP_TSPREC_USEC;
                }
                descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(wth->file_encap);
@@ -2166,7 +2166,7 @@ wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean co
                       GArray* nrb_hdrs, int *err)
 {
        wtap_dumper *wdh;
-       wtap_optionblock_t descr, file_int_data;
+       wtap_block_t descr, file_int_data;
        wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
 
        /* Check whether we can open a capture file with that file type
@@ -2188,32 +2188,29 @@ wtap_dump_init_dumper(int file_type_subtype, int encap, int snaplen, gboolean co
                guint itf_count;
 
                /* XXX: what free's this stuff? */
-               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
                for (itf_count = 0; itf_count < idb_inf->interface_data->len; itf_count++) {
-                       file_int_data = g_array_index(idb_inf->interface_data, wtap_optionblock_t, itf_count);
-                       file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(file_int_data);
-                       descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-                       wtap_optionblock_copy_options(descr, file_int_data);
+                       file_int_data = g_array_index(idb_inf->interface_data, wtap_block_t, itf_count);
+                       file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
+                       descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+                       wtap_block_copy(descr, file_int_data);
                        if ((encap != WTAP_ENCAP_PER_PACKET) && (encap != file_int_data_mand->wtap_encap)) {
-                               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+                               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
                                descr_mand->wtap_encap = encap;
                                descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
                        }
                        g_array_append_val(wdh->interface_data, descr);
                }
        } else {
-               descr = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(descr);
+               descr = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+               descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
                descr_mand->wtap_encap = encap;
                descr_mand->time_units_per_second = 1000000; /* default microsecond resolution */
                descr_mand->link_type = wtap_wtap_encap_to_pcap_encap(encap);
                descr_mand->snap_len = snaplen;
-               wtap_optionblock_set_option_string(descr, OPT_IDB_NAME, "Unknown/not available in original file format(libpcap)",
-                                                                                                               strlen("Unknown/not available in original file format(libpcap)"));
-
                descr_mand->num_stat_entries = 0;          /* Number of ISB:s */
                descr_mand->interface_statistics = NULL;
-               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+               wdh->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
                g_array_append_val(wdh->interface_data, descr);
        }
        return wdh;
index 947e3e13dfd79a33ae5be2e88c583a8f1b978ff2..6e6f3f49dc596e1e4a0086640fe6be768613946d 100644 (file)
@@ -330,7 +330,7 @@ wtap_open_return_val lanalyzer_open(wtap *wth, int *err, gchar **err_info)
                   g_free(comment);
                   return WTAP_OPEN_NOT_MINE;
             }
-            wtap_optionblock_set_option_string(g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0), OPT_COMMENT, comment, record_length);
+            wtap_block_add_string_option(g_array_index(wth->shb_hdrs, wtap_block_t, 0), OPT_COMMENT, comment, record_length);
             g_free(comment);
       }
 
index 6870e8cbeb7f06c120175b9198f02c257f26d5f6..ea3f9a6dd57b4e45591f046d6a0b0322b627ffc1 100644 (file)
@@ -365,7 +365,7 @@ create_shb_header(const merge_in_file_t *in_files, const guint in_file_count,
                   const gchar *app_name)
 {
     GArray  *shb_hdrs;
-    wtap_optionblock_t shb_hdr;
+    wtap_block_t shb_hdr;
     GString *comment_gstr;
     GString *os_info_str;
     guint i;
@@ -374,16 +374,21 @@ create_shb_header(const merge_in_file_t *in_files, const guint in_file_count,
     gsize opt_len;
 
     shb_hdrs = wtap_file_get_shb_for_new_file(in_files[0].wth);
-    shb_hdr = g_array_index(shb_hdrs, wtap_optionblock_t, 0);
+    shb_hdr = g_array_index(shb_hdrs, wtap_block_t, 0);
 
     comment_gstr = g_string_new("");
 
-    /* TODO: merge comments from all files */
-
-    wtap_optionblock_get_option_string(shb_hdr, OPT_COMMENT, &shb_comment);
-
-    /* very lame way to save comments - does not save them from the other files */
-    if (shb_comment && strlen(shb_comment) > 0) {
+    /*
+     * TODO: merge comments from all files
+     *
+     * XXX - do we want some way to record which comments, hardware/OS/app
+     * descriptions, IDBs, etc.? came from which files?
+     *
+     * XXX - fix this to handle multiple comments from a single file.
+     */
+    if (wtap_block_get_nth_string_option_value(shb_hdr, OPT_COMMENT, 0, &shb_comment) == WTAP_OPTTYPE_SUCCESS &&
+        shb_comment && strlen(shb_comment) > 0) {
+        /* very lame way to save comments - does not save them from the other files */
         g_string_append_printf(comment_gstr, "%s \n",shb_comment);
     }
 
@@ -396,27 +401,32 @@ create_shb_header(const merge_in_file_t *in_files, const guint in_file_count,
     os_info_str = g_string_new("");
     get_os_version_info(os_info_str);
 
-    shb_data = (wtapng_mandatory_section_t*)wtap_optionblock_get_mandatory_data(shb_hdr);
+    shb_data = (wtapng_mandatory_section_t*)wtap_block_get_mandatory_data(shb_hdr);
     shb_data->section_length = -1;
     /* TODO: handle comments from each file being merged */
     opt_len = comment_gstr->len;
-    wtap_optionblock_set_option_string(shb_hdr, OPT_COMMENT, g_string_free(comment_gstr, TRUE), opt_len); /* section comment */
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_HARDWARE, NULL, 0 ); /* NULL if not available, UTF-8 string containing the        */
+    wtap_block_set_nth_string_option_value(shb_hdr, OPT_COMMENT, 0, g_string_free(comment_gstr, TRUE), opt_len); /* section comment */
+    /*
+     * XXX - and how do we preserve all the OPT_SHB_HARDWARE, OPT_SHB_OS,
+     * and OPT_SHB_USERAPPL values from all the previous files?
+     */
+    wtap_block_set_string_option_value(shb_hdr, OPT_SHB_HARDWARE, NULL, 0 ); /* NULL if not available, UTF-8 string containing the        */
                                                                                       /*  description of the hardware used to create this section. */
 
     opt_len = os_info_str->len;
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len); /* UTF-8 string containing the name   */
+    wtap_block_set_string_option_value(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len); /* UTF-8 string containing the name   */
                                                                                                             /*  of the operating system used to create this section.     */
-    wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_USERAPPL, (char*)app_name, app_name ? strlen(app_name): 0 ); /* NULL if not available, UTF-8 string containing the name */
+    wtap_block_set_string_option_value(shb_hdr, OPT_SHB_USERAPPL, (char*)app_name, app_name ? strlen(app_name): 0 ); /* NULL if not available, UTF-8 string containing the name */
                                                                                       /*  of the application used to create this section.          */
 
     return shb_hdrs;
 }
 
 static gboolean
-is_duplicate_idb(const wtap_optionblock_t idb1, const wtap_optionblock_t idb2)
+is_duplicate_idb(const wtap_block_t idb1, const wtap_block_t idb2)
 {
     wtapng_if_descr_mandatory_t *idb1_mand, *idb2_mand;
+    gboolean have_idb1_value, have_idb2_value;
     guint64 idb1_if_speed, idb2_if_speed;
     guint8 idb1_if_tsresol, idb2_if_tsresol;
     guint8 idb1_if_fcslen, idb2_if_fcslen;
@@ -424,8 +434,8 @@ is_duplicate_idb(const wtap_optionblock_t idb1, const wtap_optionblock_t idb2)
          *idb1_if_description, *idb2_if_description, *idb1_if_os, *idb2_if_os;
 
     g_assert(idb1 && idb2);
-    idb1_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(idb1);
-    idb2_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(idb2);
+    idb1_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb1);
+    idb2_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb2);
 
     merge_debug("merge::is_duplicate_idb() called");
     merge_debug("idb1_mand->wtap_encap == idb2_mand->wtap_encap: %s",
@@ -439,56 +449,122 @@ is_duplicate_idb(const wtap_optionblock_t idb1, const wtap_optionblock_t idb2)
     merge_debug("idb1_mand->snap_len == idb2_mand->snap_len: %s",
                  (idb1_mand->snap_len == idb2_mand->snap_len) ? "TRUE":"FALSE");
 
-    wtap_optionblock_get_option_uint64(idb1, OPT_IDB_SPEED, &idb1_if_speed);
-    wtap_optionblock_get_option_uint64(idb2, OPT_IDB_SPEED, &idb2_if_speed);
-    merge_debug("idb1_if_speed == idb2_if_speed: %s",
-                 (idb1_if_speed == idb2_if_speed) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_uint8(idb1, OPT_IDB_TSRESOL, &idb1_if_tsresol);
-    wtap_optionblock_get_option_uint8(idb2, OPT_IDB_TSRESOL, &idb2_if_tsresol);
-    merge_debug("idb1_if_tsresol == idb2_if_tsresol: %s",
-                 (idb1_if_tsresol == idb2_if_tsresol) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_uint8(idb1, OPT_IDB_FCSLEN, &idb1_if_fcslen);
-    wtap_optionblock_get_option_uint8(idb2, OPT_IDB_FCSLEN, &idb2_if_fcslen);
-    merge_debug("idb1_if_fcslen == idb2_if_fcslen: %s",
-                 (idb1_if_fcslen == idb2_if_fcslen) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_string(idb1, OPT_COMMENT, &idb1_opt_comment);
-    wtap_optionblock_get_option_string(idb2, OPT_COMMENT, &idb2_opt_comment);
-    merge_debug("g_strcmp0(idb1_opt_comment, idb2_opt_comment) == 0: %s",
-                 (g_strcmp0(idb1_opt_comment, idb2_opt_comment) == 0) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_string(idb1, OPT_IDB_NAME, &idb1_if_name);
-    wtap_optionblock_get_option_string(idb2, OPT_IDB_NAME, &idb2_if_name);
-    merge_debug("g_strcmp0(idb1_if_name, idb2_if_name) == 0: %s",
-                 (g_strcmp0(idb1_if_name, idb2_if_name) == 0) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_string(idb1, OPT_IDB_DESCR, &idb1_if_description);
-    wtap_optionblock_get_option_string(idb2, OPT_IDB_DESCR, &idb2_if_description);
-    merge_debug("g_strcmp0(idb1_if_description, idb2_if_description) == 0: %s",
-                 (g_strcmp0(idb1_if_description, idb2_if_description) == 0) ? "TRUE":"FALSE");
-
-    wtap_optionblock_get_option_string(idb1, OPT_IDB_OS, &idb1_if_os);
-    wtap_optionblock_get_option_string(idb2, OPT_IDB_OS, &idb2_if_os);
-    merge_debug("g_strcmp0(idb1_if_os, idb2_if_os) == 0: %s",
-                 (g_strcmp0(idb1_if_os, idb2_if_os) == 0) ? "TRUE":"FALSE");
-    merge_debug("merge::is_duplicate_idb() returning");
+    if (idb1_mand->wtap_encap != idb2_mand->wtap_encap ||
+        idb1_mand->link_type != idb2_mand->link_type) {
+        /* Clearly not the same interface. */
+        merge_debug("merge::is_duplicate_idb() returning FALSE");
+        return FALSE;
+    }
+
+    if (idb1_mand->time_units_per_second != idb2_mand->time_units_per_second ||
+        idb1_mand->tsprecision != idb2_mand->tsprecision) {
+        /*
+         * Probably not the same interface, and we can't combine them
+         * in any case.
+         */
+        merge_debug("merge::is_duplicate_idb() returning FALSE");
+        return FALSE;
+    }
+
+    /* XXX: should snaplen not be compared? */
+    if (idb1_mand->snap_len == idb2_mand->snap_len) {
+        merge_debug("merge::is_duplicate_idb() returning FALSE");
+        return FALSE;
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_uint64_option_value(idb1, OPT_IDB_SPEED, &idb1_if_speed) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_uint64_option_value(idb2, OPT_IDB_SPEED, &idb2_if_speed) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("idb1_if_speed == idb2_if_speed: %s",
+                     (idb1_if_speed == idb2_if_speed) ? "TRUE":"FALSE");
+        if (idb1_if_speed != idb2_if_speed) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_uint8_option_value(idb1, OPT_IDB_TSRESOL, &idb1_if_tsresol) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_uint8_option_value(idb2, OPT_IDB_TSRESOL, &idb2_if_tsresol) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("idb1_if_tsresol == idb2_if_tsresol: %s",
+                     (idb1_if_tsresol == idb2_if_tsresol) ? "TRUE":"FALSE");
+        if (idb1_if_tsresol != idb2_if_tsresol) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_uint8_option_value(idb1, OPT_IDB_FCSLEN, &idb1_if_fcslen) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_uint8_option_value(idb2, OPT_IDB_FCSLEN, &idb2_if_fcslen) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("idb1_if_fcslen == idb2_if_fcslen: %s",
+                     (idb1_if_fcslen == idb2_if_fcslen) ? "TRUE":"FALSE");
+        if (idb1_if_fcslen == idb2_if_fcslen) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /*
+     * XXX - handle multiple comments?
+     * XXX - if the comments are different, just combine them if we
+     * decide the two interfaces are really the same?  As comments
+     * can be arbitrary strings added by people, the fact that they're
+     * different doesn't necessarily mean the interfaces are different.
+     */
+    have_idb1_value = (wtap_block_get_nth_string_option_value(idb1, OPT_COMMENT, 0, &idb1_opt_comment) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_nth_string_option_value(idb2, OPT_COMMENT, 0, &idb2_opt_comment) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("g_strcmp0(idb1_opt_comment, idb2_opt_comment) == 0: %s",
+                     (g_strcmp0(idb1_opt_comment, idb2_opt_comment) == 0) ? "TRUE":"FALSE");
+        if (g_strcmp0(idb1_opt_comment, idb2_opt_comment) != 0) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_string_option_value(idb1, OPT_IDB_NAME, &idb1_if_name) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_string_option_value(idb2, OPT_IDB_NAME, &idb2_if_name) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("g_strcmp0(idb1_if_name, idb2_if_name) == 0: %s",
+                     (g_strcmp0(idb1_if_name, idb2_if_name) == 0) ? "TRUE":"FALSE");
+        if (g_strcmp0(idb1_if_name, idb2_if_name) != 0) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_string_option_value(idb1, OPT_IDB_DESCR, &idb1_if_description) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_string_option_value(idb2, OPT_IDB_DESCR, &idb2_if_description) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("g_strcmp0(idb1_if_description, idb2_if_description) == 0: %s",
+                     (g_strcmp0(idb1_if_description, idb2_if_description) == 0) ? "TRUE":"FALSE");
+        if (g_strcmp0(idb1_if_description, idb2_if_description) != 0) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
+
+    /* XXX - what do to if we have only one value? */
+    have_idb1_value = (wtap_block_get_string_option_value(idb1, OPT_IDB_OS, &idb1_if_os) == WTAP_OPTTYPE_SUCCESS);
+    have_idb2_value = (wtap_block_get_string_option_value(idb2, OPT_IDB_OS, &idb2_if_os) == WTAP_OPTTYPE_SUCCESS);
+    if (have_idb1_value && have_idb2_value) {
+        merge_debug("g_strcmp0(idb1_if_os, idb2_if_os) == 0: %s",
+                     (g_strcmp0(idb1_if_os, idb2_if_os) == 0) ? "TRUE":"FALSE");
+        if (g_strcmp0(idb1_if_os, idb2_if_os) != 0) {
+            merge_debug("merge::is_duplicate_idb() returning FALSE");
+            return FALSE;
+        }
+    }
 
     /* does not compare filters nor interface statistics */
-    return (idb1_mand->wtap_encap == idb2_mand->wtap_encap &&
-            idb1_mand->time_units_per_second == idb2_mand->time_units_per_second &&
-            idb1_mand->tsprecision == idb2_mand->tsprecision &&
-            idb1_mand->link_type == idb2_mand->link_type &&
-            /* XXX: should snaplen not be compared? */
-            idb1_mand->snap_len == idb2_mand->snap_len &&
-            idb1_if_speed == idb2_if_speed &&
-            idb1_if_tsresol == idb2_if_tsresol &&
-            idb1_if_fcslen == idb2_if_fcslen &&
-            g_strcmp0(idb1_opt_comment, idb2_opt_comment) == 0 &&
-            g_strcmp0(idb1_if_name, idb2_if_name) == 0 &&
-            g_strcmp0(idb1_if_description, idb2_if_description) == 0 &&
-            g_strcmp0(idb1_if_os, idb2_if_os) == 0);
+    merge_debug("merge::is_duplicate_idb() returning TRUE");
+    return TRUE;
 }
 
 /*
@@ -500,7 +576,7 @@ all_idbs_are_duplicates(const merge_in_file_t *in_files, const guint in_file_cou
     wtapng_iface_descriptions_t *first_idb_list = NULL;
     wtapng_iface_descriptions_t *other_idb_list = NULL;
     guint first_idb_list_size, other_idb_list_size;
-    wtap_optionblock_t first_file_idb, other_file_idb;
+    wtap_block_t first_file_idb, other_file_idb;
     guint i, j;
 
     g_assert(in_files != NULL);
@@ -526,8 +602,8 @@ all_idbs_are_duplicates(const merge_in_file_t *in_files, const guint in_file_cou
         }
 
         for (j = 0; j < other_idb_list_size; j++) {
-            first_file_idb = g_array_index(first_idb_list->interface_data, wtap_optionblock_t, j);
-            other_file_idb = g_array_index(other_idb_list->interface_data, wtap_optionblock_t, j);
+            first_file_idb = g_array_index(first_idb_list->interface_data, wtap_block_t, j);
+            other_file_idb = g_array_index(other_idb_list->interface_data, wtap_block_t, j);
 
             if (!is_duplicate_idb(first_file_idb, other_file_idb)) {
                 merge_debug("merge::all_idbs_are_duplicates: IDBs at index %d do not match, returning FALSE", j);
@@ -556,11 +632,11 @@ all_idbs_are_duplicates(const merge_in_file_t *in_files, const guint in_file_cou
  * own (same) input file.
  */
 static gboolean
-find_duplicate_idb(const wtap_optionblock_t input_file_idb,
+find_duplicate_idb(const wtap_block_t input_file_idb,
                const wtapng_iface_descriptions_t *merged_idb_list,
                guint *found_index)
 {
-    wtap_optionblock_t merged_idb;
+    wtap_block_t merged_idb;
     guint i;
 
     g_assert(input_file_idb != NULL);
@@ -569,7 +645,7 @@ find_duplicate_idb(const wtap_optionblock_t input_file_idb,
     g_assert(found_index != NULL);
 
     for (i = 0; i < merged_idb_list->interface_data->len; i++) {
-        merged_idb = g_array_index(merged_idb_list->interface_data, wtap_optionblock_t, i);
+        merged_idb = g_array_index(merged_idb_list->interface_data, wtap_block_t, i);
 
         if (is_duplicate_idb(input_file_idb, merged_idb)) {
             *found_index = i;
@@ -583,24 +659,19 @@ find_duplicate_idb(const wtap_optionblock_t input_file_idb,
 /* adds IDB to merged file info, returns its index */
 static guint
 add_idb_to_merged_file(wtapng_iface_descriptions_t *merged_idb_list,
-                       const wtap_optionblock_t input_file_idb)
+                       const wtap_block_t input_file_idb)
 {
-    wtap_optionblock_t idb = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+    wtap_block_t idb = wtap_block_create(WTAP_BLOCK_IF_DESCR);
     wtapng_if_descr_mandatory_t* idb_mand;
-    wtapng_if_descr_filter_t if_filter;
-
 
     g_assert(merged_idb_list != NULL);
     g_assert(merged_idb_list->interface_data != NULL);
     g_assert(input_file_idb != NULL);
 
-    wtap_optionblock_copy_options(idb, input_file_idb);
-    idb_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(idb);
+    wtap_block_copy(idb, input_file_idb);
+    idb_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb);
 
     /* Don't copy filter or stat information */
-    memset(&if_filter, 0, sizeof(if_filter));
-    wtap_optionblock_set_option_custom(idb, OPT_IDB_FILTER, &if_filter);
-
     idb_mand->num_stat_entries      = 0;          /* Number of ISB:s */
     idb_mand->interface_statistics  = NULL;
 
@@ -617,13 +688,13 @@ generate_merged_idb(merge_in_file_t *in_files, const guint in_file_count, const
 {
     wtapng_iface_descriptions_t *merged_idb_list = NULL;
     wtapng_iface_descriptions_t *input_file_idb_list = NULL;
-    wtap_optionblock_t           input_file_idb;
+    wtap_block_t                 input_file_idb;
     guint                        itf_count, merged_index;
     guint                        i;
 
     /* create new IDB info */
     merged_idb_list = g_new(wtapng_iface_descriptions_t,1);
-    merged_idb_list->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+    merged_idb_list->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
     if (mode == IDB_MERGE_MODE_ALL_SAME && all_idbs_are_duplicates(in_files, in_file_count)) {
         guint num_idbs;
@@ -638,7 +709,7 @@ generate_merged_idb(merge_in_file_t *in_files, const guint in_file_count, const
         /* put them in the merged file */
         for (itf_count = 0; itf_count < num_idbs; itf_count++) {
             input_file_idb = g_array_index(input_file_idb_list->interface_data,
-                                            wtap_optionblock_t, itf_count);
+                                            wtap_block_t, itf_count);
             merged_index = add_idb_to_merged_file(merged_idb_list, input_file_idb);
             add_idb_index_map(&in_files[0], itf_count, merged_index);
         }
@@ -658,7 +729,7 @@ generate_merged_idb(merge_in_file_t *in_files, const guint in_file_count, const
 
             for (itf_count = 0; itf_count < input_file_idb_list->interface_data->len; itf_count++) {
                 input_file_idb = g_array_index(input_file_idb_list->interface_data,
-                                                wtap_optionblock_t, itf_count);
+                                                wtap_block_t, itf_count);
 
                 if (mode == IDB_MERGE_MODE_ANY_SAME &&
                     find_duplicate_idb(input_file_idb, merged_idb_list, &merged_index))
@@ -950,7 +1021,7 @@ merge_files(int out_fd, const gchar* out_filename, const int file_type,
     if (pdh == NULL) {
         merge_close_in_files(in_file_count, in_files);
         g_free(in_files);
-        wtap_optionblock_array_free(shb_hdrs);
+        wtap_block_array_free(shb_hdrs);
         wtap_free_idb_info(idb_inf);
         return MERGE_ERR_CANT_OPEN_OUTFILE;
     }
@@ -1080,7 +1151,7 @@ merge_files(int out_fd, const gchar* out_filename, const int file_type,
     }
 
     g_free(in_files);
-    wtap_optionblock_array_free(shb_hdrs);
+    wtap_block_array_free(shb_hdrs);
     wtap_free_idb_info(idb_inf);
 
     return status;
index cf4d99df75bc5c321aa7133d6bcda543f9fcc33e..6b29e30ffdb5042735d1adc1d6bb6946e58ed554 100644 (file)
@@ -709,10 +709,10 @@ create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_
        wtap_open_return_val result = WTAP_OPEN_MINE;
 
        /* pcapng defs */
-       GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
-       wtap_optionblock_t           shb_hdr;
+       GArray                      *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
+       wtap_block_t                 shb_hdr;
        wtapng_iface_descriptions_t *idb_inf = NULL;
-       wtap_optionblock_t           int_data;
+       wtap_block_t                 int_data;
        wtapng_if_descr_mandatory_t *int_data_mand;
        GString                     *os_info_str;
        gint64 file_size;
@@ -753,22 +753,22 @@ create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_
        os_info_str = g_string_new("");
        get_os_version_info(os_info_str);
 
-       shb_hdr = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
+       shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
        /* options */
-       wtap_optionblock_set_option_string(shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
+       wtap_block_add_string_option(shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
                                                                                                                        strlen("File converted to Exported PDU format during opening"));
        /*
        * UTF-8 string containing the name of the operating system used to create
        * this section.
        */
        opt_len = os_info_str->len;
-       wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
+       wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
 
        /*
        * UTF-8 string containing the name of the application used to create
        * this section.
        */
-       wtap_optionblock_set_option_string_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
+       wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
 
        /* Add header to the array */
        g_array_append_val(shb_hdrs, shb_hdr);
@@ -776,16 +776,16 @@ create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_
 
        /* Create fake IDB info */
        idb_inf = g_new(wtapng_iface_descriptions_t, 1);
-       idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+       idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
        /* create the fake interface data */
-       int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-       int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+       int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+       int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
        int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
        int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
        int_data_mand->link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
        int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE;
-       wtap_optionblock_set_option_string(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
+       wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
        int_data_mand->num_stat_entries = 0;          /* Number of ISB:s */
        int_data_mand->interface_statistics = NULL;
 
@@ -1071,7 +1071,7 @@ create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_
 end:
        g_free(wrt_err_info);
        g_free(packet_buf);
-       wtap_optionblock_array_free(shb_hdrs);
+       wtap_block_array_free(shb_hdrs);
        wtap_free_idb_info(idb_inf);
 
        return result;
@@ -1130,7 +1130,7 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
                return WTAP_OPEN_ERROR;
 
        /* Copy data from the temp file wth */
-       wtap_optionblock_copy_options(g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0), g_array_index(file_info->wth_tmp_file->shb_hdrs, wtap_optionblock_t, 0));
+       wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0), g_array_index(file_info->wth_tmp_file->shb_hdrs, wtap_block_t, 0));
 
        wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423;
        wth->file_encap = file_info->wth_tmp_file->file_encap;
index afb2d72092344a63f2329359fcd32a27b25ca3a0..a46d976197984a299f9ef166d01bfa80a7c72a7b 100644 (file)
@@ -200,8 +200,8 @@ typedef struct wtapng_simple_packet_s {
 
 /* Block data to be passed between functions during reading */
 typedef struct wtapng_block_s {
-    guint32                     type;           /* block_type as defined by pcapng */
-    wtap_optionblock_t          block;
+    guint32             type;           /* block_type as defined by pcapng */
+    wtap_block_t        block;
 
     /*
      * XXX - currently don't know how to handle these!
@@ -212,7 +212,7 @@ typedef struct wtapng_block_s {
      * in fact, they sometimes point to const values.
      */
     struct wtap_pkthdr *packet_header;
-    Buffer *frame_buffer;
+    Buffer             *frame_buffer;
 } wtapng_block_t;
 
 /* Interface data in private struct */
@@ -572,8 +572,8 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
     pn->version_major = version_major;
     pn->version_minor = version_minor;
 
-    wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
-    section_data = (wtapng_mandatory_section_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+    wblock->block = wtap_block_create(WTAP_BLOCK_NG_SECTION);
+    section_data = (wtapng_mandatory_section_t*)wtap_block_get_mandatory_data(wblock->block);
     /* 64bit section_length (currently unused) */
     if (pn->byte_swapped) {
         section_data->section_length = GUINT64_SWAP_LE_BE(shb.section_length);
@@ -614,7 +614,7 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_COMMENT):
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, option_content, oh.option_length);
+                    wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_section_header_block: opt_comment %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -624,7 +624,8 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_SHB_HARDWARE):
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_SHB_HARDWARE, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_SHB_HARDWARE, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_section_header_block: shb_hardware %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -634,7 +635,8 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_SHB_OS):
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_SHB_OS, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_SHB_OS, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_section_header_block: shb_os %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -644,7 +646,8 @@ pcapng_read_section_header_block(FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_SHB_USERAPPL):
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_SHB_USERAPPL, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_SHB_USERAPPL, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_section_header_block: shb_user_appl %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -714,8 +717,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
     }
 
     /* mandatory values */
-    wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
-    if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+    wblock->block = wtap_block_create(WTAP_BLOCK_IF_DESCR);
+    if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
     if (pn->byte_swapped) {
         if_descr_mand->link_type = GUINT16_SWAP_LE_BE(idb.linktype);
         if_descr_mand->snap_len  = GUINT32_SWAP_LE_BE(idb.snaplen);
@@ -775,7 +778,7 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_COMMENT): /* opt_comment */
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, option_content, oh.option_length);
+                    wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_if_descr_block: opt_comment %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -785,7 +788,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_IDB_NAME): /* if_name */
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_IDB_NAME, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_IDB_NAME, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_if_descr_block: if_name %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -795,7 +799,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
             case(OPT_IDB_DESCR): /* if_description */
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_IDB_DESCR, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_IDB_DESCR, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_if_descr_block: if_description %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -811,7 +816,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
                     memcpy(&tmp64, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         tmp64 = GUINT64_SWAP_LE_BE(tmp64);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_IDB_SPEED, tmp64);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_IDB_SPEED, tmp64);
                     pcapng_debug("pcapng_read_if_descr_block: if_speed %" G_GINT64_MODIFIER "u (bps)", tmp64);
                 } else {
                     pcapng_debug("pcapng_read_if_descr_block: if_speed length %u not 8 as expected", oh.option_length);
@@ -843,7 +849,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
                         pcapng_debug("pcapng_open: time conversion might be inaccurate");
                     }
                     if_descr_mand->time_units_per_second = time_units_per_second;
-                    wtap_optionblock_set_option_uint8(wblock->block, OPT_IDB_TSRESOL, if_tsresol);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint8_option(wblock->block, OPT_IDB_TSRESOL, if_tsresol);
                     if (time_units_per_second >= 1000000000)
                         tsprecision = WTAP_TSPREC_NSEC;
                     else if (time_units_per_second >= 1000000)
@@ -881,7 +888,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
                         if_filter.if_filter_bpf_bytes = (gchar *)g_malloc(oh.option_length-1);
                         memcpy(if_filter.if_filter_bpf_bytes, (char *)option_content+1, oh.option_length-1);
                     }
-                    wtap_optionblock_set_option_custom(wblock->block, OPT_IDB_FILTER, &if_filter);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_custom_option(wblock->block, OPT_IDB_FILTER, &if_filter, sizeof if_filter);
                 } else {
                     pcapng_debug("pcapng_read_if_descr_block: if_filter length %u seems strange", oh.option_length);
                 }
@@ -894,7 +902,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
                  */
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_IDB_OS, option_content, oh.option_length);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_string_option(wblock->block, OPT_IDB_OS, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_if_descr_block: if_os %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -903,7 +912,8 @@ pcapng_read_if_descr_block(wtap *wth, FILE_T fh, pcapng_block_header_t *bh,
                 break;
             case(OPT_IDB_FCSLEN): /* if_fcslen */
                 if (oh.option_length == 1) {
-                    wtap_optionblock_set_option_uint8(wblock->block, OPT_IDB_TSRESOL, option_content[0]);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint8_option(wblock->block, OPT_IDB_TSRESOL, option_content[0]);
                     pn->if_fcslen = option_content[0];
                     pcapng_debug("pcapng_read_if_descr_block: if_fcslen %u", pn->if_fcslen);
                     /* XXX - add sanity check */
@@ -1615,7 +1625,7 @@ pcapng_read_name_resolution_block(FILE_T fh, pcapng_block_header_t *bh, pcapng_t
 
     /* Ensure we have a name resolution block */
     if (wblock->block == NULL) {
-        wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_NRB);
+        wblock->block = wtap_block_create(WTAP_BLOCK_NG_NRB);
     }
 
     /*
@@ -1841,7 +1851,7 @@ read_options:
             case(OPT_COMMENT):
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, option_content, oh.option_length);
+                    wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_name_resolution_block: length %u opt_comment '%s'", oh.option_length, tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -1923,8 +1933,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
         return FALSE;
     }
 
-    wblock->block = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
-    if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+    wblock->block = wtap_block_create(WTAP_BLOCK_IF_STATS);
+    if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
     if (pn->byte_swapped) {
         if_stats_mand->interface_id = GUINT32_SWAP_LE_BE(isb.interface_id);
         if_stats_mand->ts_high      = GUINT32_SWAP_LE_BE(isb.timestamp_high);
@@ -1969,7 +1979,7 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
             case(OPT_COMMENT): /* opt_comment */
                 if (oh.option_length > 0 && oh.option_length < opt_cont_buf_len) {
                     tmp_content = g_strndup((char *)option_content, oh.option_length);
-                    wtap_optionblock_set_option_string(wblock->block, OPT_COMMENT, option_content, oh.option_length);
+                    wtap_block_add_string_option(wblock->block, OPT_COMMENT, option_content, oh.option_length);
                     pcapng_debug("pcapng_read_interface_statistics_block: opt_comment %s", tmp_content);
                     g_free(tmp_content);
                 } else {
@@ -1994,7 +2004,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     starttime = (guint64)high;
                     starttime <<= 32;
                     starttime += (guint64)low;
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_STARTTIME, starttime);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_STARTTIME, starttime);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime %" G_GINT64_MODIFIER "u", starttime);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
@@ -2018,7 +2029,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     endtime = (guint64)high;
                     endtime <<= 32;
                     endtime += (guint64)low;
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_ENDTIME, endtime);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_ENDTIME, endtime);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_endtime %" G_GINT64_MODIFIER "u", endtime);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_starttime length %u not 8 as expected", oh.option_length);
@@ -2034,7 +2046,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     memcpy(&ifrecv, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         ifrecv = GUINT64_SWAP_LE_BE(ifrecv);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_IFRECV, ifrecv);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_IFRECV, ifrecv);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_ifrecv %" G_GINT64_MODIFIER "u", ifrecv);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_ifrecv length %u not 8 as expected", oh.option_length);
@@ -2050,7 +2063,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     memcpy(&ifdrop, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         ifdrop = GUINT64_SWAP_LE_BE(ifdrop);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_IFDROP, ifdrop);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_IFDROP, ifdrop);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_ifdrop %" G_GINT64_MODIFIER "u", ifdrop);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_ifdrop length %u not 8 as expected", oh.option_length);
@@ -2066,7 +2080,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     memcpy(&filteraccept, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         filteraccept = GUINT64_SWAP_LE_BE(filteraccept);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_FILTERACCEPT, filteraccept);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_FILTERACCEPT, filteraccept);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_filteraccept %" G_GINT64_MODIFIER "u", filteraccept);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_filteraccept length %u not 8 as expected", oh.option_length);
@@ -2082,7 +2097,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     memcpy(&osdrop, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         osdrop = GUINT64_SWAP_LE_BE(osdrop);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_OSDROP, osdrop);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_OSDROP, osdrop);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_osdrop %" G_GINT64_MODIFIER "u", osdrop);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_osdrop length %u not 8 as expected", oh.option_length);
@@ -2098,7 +2114,8 @@ pcapng_read_interface_statistics_block(FILE_T fh, pcapng_block_header_t *bh, pca
                     memcpy(&usrdeliv, option_content, sizeof(guint64));
                     if (pn->byte_swapped)
                         usrdeliv = GUINT64_SWAP_LE_BE(usrdeliv);
-                    wtap_optionblock_set_option_uint64(wblock->block, OPT_ISB_USRDELIV, usrdeliv);
+                    /* Fails with multiple options; we silently ignore the failure */
+                    wtap_block_add_uint64_option(wblock->block, OPT_ISB_USRDELIV, usrdeliv);
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_usrdeliv %" G_GINT64_MODIFIER "u", usrdeliv);
                 } else {
                     pcapng_debug("pcapng_read_interface_statistics_block: isb_usrdeliv length %u not 8 as expected", oh.option_length);
@@ -2402,12 +2419,12 @@ pcapng_read_block(wtap *wth, FILE_T fh, pcapng_t *pn, wtapng_block_t *wblock, in
 static void
 pcapng_process_idb(wtap *wth, pcapng_t *pcapng, wtapng_block_t *wblock)
 {
-    wtap_optionblock_t int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
+    wtap_block_t int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
     interface_info_t iface_info;
-    wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data),
-                                *wblock_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock->block);
+    wtapng_if_descr_mandatory_t *if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data),
+                                *wblock_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wblock->block);
 
-    wtap_optionblock_copy_options(int_data, wblock->block);
+    wtap_block_copy(int_data, wblock->block);
 
     /* XXX if_tsoffset; opt 14  A 64 bits integer value that specifies an offset (in seconds)...*/
     /* Interface statistics */
@@ -2456,7 +2473,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
 
     case PCAPNG_BLOCK_NOT_SHB:
         /* An error indicating that this isn't a pcap-ng file. */
-        wtap_optionblock_free(wblock.block);
+        wtap_block_free(wblock.block);
         wblock.block = NULL;
         *err = 0;
         *err_info = NULL;
@@ -2464,7 +2481,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
 
     case PCAPNG_BLOCK_ERROR:
         /* An I/O error, or this probably *is* a pcap-ng file but not a valid one. */
-        wtap_optionblock_free(wblock.block);
+        wtap_block_free(wblock.block);
         wblock.block = NULL;
         return WTAP_OPEN_ERROR;
     }
@@ -2477,7 +2494,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
          * binary data?
          */
         pcapng_debug("pcapng_open: first block type %u not SHB", wblock.type);
-        wtap_optionblock_free(wblock.block);
+        wtap_block_free(wblock.block);
         wblock.block = NULL;
         return WTAP_OPEN_NOT_MINE;
     }
@@ -2488,7 +2505,7 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
      * some other type of file, so we can't return WTAP_OPEN_NOT_MINE
      * past this point.
      */
-    wtap_optionblock_copy_options(g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0), wblock.block);
+    wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0), wblock.block);
 
     wth->file_encap = WTAP_ENCAP_UNKNOWN;
     wth->snapshot_length = 0;
@@ -2533,12 +2550,12 @@ pcapng_open(wtap *wth, int *err, gchar **err_info)
         if (pcapng_read_block(wth, wth->fh, &pn, &wblock, err, err_info) != PCAPNG_BLOCK_OK) {
             if (*err == 0) {
                 pcapng_debug("No more IDBs available...");
-                wtap_optionblock_free(wblock.block);
+                wtap_block_free(wblock.block);
                 wblock.block = NULL;
                 break;
             } else {
                 pcapng_debug("pcapng_open: couldn't read IDB");
-                wtap_optionblock_free(wblock.block);
+                wtap_block_free(wblock.block);
                 wblock.block = NULL;
                 return WTAP_OPEN_ERROR;
             }
@@ -2557,8 +2574,8 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
 {
     pcapng_t *pcapng = (pcapng_t *)wth->priv;
     wtapng_block_t wblock;
-    wtap_optionblock_t wtapng_if_descr;
-    wtap_optionblock_t if_stats;
+    wtap_block_t wtapng_if_descr;
+    wtap_block_t if_stats;
     wtapng_if_stats_mandatory_t *if_stats_mand_block, *if_stats_mand;
     wtapng_if_descr_mandatory_t *wtapng_if_descr_mand;
 
@@ -2603,7 +2620,7 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
                 /* More name resolution entries */
                 pcapng_debug("pcapng_read: block type BLOCK_TYPE_NRB");
                 if (wth->nrb_hdrs == NULL) {
-                    wth->nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+                    wth->nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
                 }
                 g_array_append_val(wth->nrb_hdrs, wblock.block);
                 break;
@@ -2611,26 +2628,26 @@ pcapng_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
             case(BLOCK_TYPE_ISB):
                 /* Another interface statistics report */
                 pcapng_debug("pcapng_read: block type BLOCK_TYPE_ISB");
-                if_stats_mand_block = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(wblock.block);
+                if_stats_mand_block = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(wblock.block);
                 if (wth->interface_data->len <= if_stats_mand_block->interface_id) {
                     pcapng_debug("pcapng_read: BLOCK_TYPE_ISB wblock.if_stats.interface_id %u >= number_of_interfaces", if_stats_mand_block->interface_id);
                 } else {
                     /* Get the interface description */
-                    wtapng_if_descr = g_array_index(wth->interface_data, wtap_optionblock_t, if_stats_mand_block->interface_id);
-                    wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(wtapng_if_descr);
+                    wtapng_if_descr = g_array_index(wth->interface_data, wtap_block_t, if_stats_mand_block->interface_id);
+                    wtapng_if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(wtapng_if_descr);
                     if (wtapng_if_descr_mand->num_stat_entries == 0) {
                         /* First ISB found, no previous entry */
                         pcapng_debug("pcapng_read: block type BLOCK_TYPE_ISB. First ISB found, no previous entry");
-                        wtapng_if_descr_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+                        wtapng_if_descr_mand->interface_statistics = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
                     }
 
-                    if_stats = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_STATS);
-                    if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats);
+                    if_stats = wtap_block_create(WTAP_BLOCK_IF_STATS);
+                    if_stats_mand = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
                     if_stats_mand->interface_id  = if_stats_mand_block->interface_id;
                     if_stats_mand->ts_high       = if_stats_mand_block->ts_high;
                     if_stats_mand->ts_low        = if_stats_mand_block->ts_low;
 
-                    wtap_optionblock_copy_options(if_stats, wblock.block);
+                    wtap_block_copy(if_stats, wblock.block);
                     g_array_append_val(wtapng_if_descr_mand->interface_statistics, if_stats);
                     wtapng_if_descr_mand->num_stat_entries++;
                 }
@@ -2674,7 +2691,7 @@ pcapng_seek_read(wtap *wth, gint64 seek_off,
 
     /* read the block */
     ret = pcapng_read_block(wth, wth->random_fh, pcapng, &wblock, err, err_info);
-    wtap_optionblock_free(wblock.block);
+    wtap_block_free(wblock.block);
     if (ret != PCAPNG_BLOCK_OK) {
         pcapng_debug("pcapng_seek_read: couldn't read packet block (err=%d).",
                       *err);
@@ -2704,10 +2721,10 @@ pcapng_close(wtap *wth)
     g_array_free(pcapng->interfaces, TRUE);
 }
 
-typedef struct pcapng_optionblock_size_t
+typedef struct pcapng_block_size_t
 {
     guint32 size;
-} pcapng_optionblock_size_t;
+} pcapng_block_size_t;
 
 static guint32 pcapng_compute_option_string_size(char *str)
 {
@@ -2728,9 +2745,9 @@ static guint32 pcapng_compute_option_string_size(char *str)
     return size;
 }
 
-static void compute_shb_option_size(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void compute_shb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
 {
-    pcapng_optionblock_size_t* block_size = (pcapng_optionblock_size_t*)user_data;
+    pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
     guint32 size = 0;
 
     switch(option_id)
@@ -2739,8 +2756,7 @@ static void compute_shb_option_size(wtap_optionblock_t block _U_, guint option_i
     case OPT_SHB_HARDWARE:
     case OPT_SHB_OS:
     case OPT_SHB_USERAPPL:
-        if (option != NULL)
-            size = pcapng_compute_option_string_size(option->stringval);
+        size = pcapng_compute_option_string_size(optval->stringval);
         break;
     default:
         /* Unknown options - size by datatype? */
@@ -2805,7 +2821,7 @@ static gboolean pcapng_write_option_string(wtap_dumper *wdh, guint option_id, ch
     return TRUE;
 }
 
-static void write_wtap_shb_block(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void write_wtap_shb_block(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
 {
     pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
 
@@ -2819,8 +2835,8 @@ static void write_wtap_shb_block(wtap_optionblock_t block _U_, guint option_id,
     case OPT_SHB_HARDWARE:
     case OPT_SHB_OS:
     case OPT_SHB_USERAPPL:
-        if ((option != NULL) && (option->stringval != NULL)) {
-            if (!pcapng_write_option_string(write_block->wdh, option_id, option->stringval, write_block->err)) {
+        if (optval->stringval != NULL) {
+            if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
                 write_block->success = FALSE;
                 return;
             }
@@ -2841,12 +2857,12 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
 {
     pcapng_block_header_t bh;
     pcapng_section_header_block_t shb;
-    pcapng_optionblock_size_t block_size;
+    pcapng_block_size_t block_size;
     struct pcapng_option_header option_hdr;
-    wtap_optionblock_t wdh_shb = NULL;
+    wtap_block_t wdh_shb = NULL;
 
     if (wdh->shb_hdrs && (wdh->shb_hdrs->len > 0)) {
-        wdh_shb = g_array_index(wdh->shb_hdrs, wtap_optionblock_t, 0);
+        wdh_shb = g_array_index(wdh->shb_hdrs, wtap_block_t, 0);
     }
 
     block_size.size = 0;
@@ -2855,7 +2871,7 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
         pcapng_debug("pcapng_write_section_header_block: Have shb_hdr");
 
         /* Compute block size */
-        wtap_optionblock_foreach_option(wdh_shb, compute_shb_option_size, &block_size);
+        wtap_block_foreach_option(wdh_shb, compute_shb_option_size, &block_size);
 
         if (block_size.size > 0) {
             /* End-of-options tag */
@@ -2879,7 +2895,7 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
     shb.version_major = 1;
     shb.version_minor = 0;
     if (wdh_shb) {
-        wtapng_mandatory_section_t* section_data = (wtapng_mandatory_section_t*)wtap_optionblock_get_mandatory_data(wdh_shb);
+        wtapng_mandatory_section_t* section_data = (wtapng_mandatory_section_t*)wtap_block_get_mandatory_data(wdh_shb);
         shb.section_length = section_data->section_length;
     } else {
         shb.section_length = -1;
@@ -2897,7 +2913,7 @@ pcapng_write_section_header_block(wtap_dumper *wdh, int *err)
             block_data.wdh = wdh;
             block_data.err = err;
             block_data.success = TRUE;
-            wtap_optionblock_foreach_option(wdh_shb, write_wtap_shb_block, &block_data);
+            wtap_block_foreach_option(wdh_shb, write_wtap_shb_block, &block_data);
 
             if (!block_data.success)
                 return FALSE;
@@ -2935,7 +2951,7 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
     guint32 options_total_length = 0;
     struct option option_hdr;
     guint32 comment_len = 0, comment_pad_len = 0;
-    wtap_optionblock_t int_data;
+    wtap_block_t int_data;
     wtapng_if_descr_mandatory_t *int_data_mand;
 
     /* Don't write anything we're not willing to read. */
@@ -3001,9 +3017,9 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh,
         *err = WTAP_ERR_INTERNAL;
         return FALSE;
     }
-    int_data = g_array_index(wdh->interface_data, wtap_optionblock_t,
+    int_data = g_array_index(wdh->interface_data, wtap_block_t,
                              epb.interface_id);
-    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+    int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
     ts = ((guint64)phdr->ts.secs) * int_data_mand->time_units_per_second +
         (((guint64)phdr->ts.nsecs) * int_data_mand->time_units_per_second) / 1000000000;
     epb.timestamp_high      = (guint32)(ts >> 32);
@@ -3217,15 +3233,145 @@ pcapng_write_sysdig_event_block(wtap_dumper *wdh,
 
 }
 
-/* Arbitrary. */
-#define NRES_REC_MAX_SIZE ((WTAP_MAX_PACKET_SIZE * 4) + 16)
+/*
+ * libpcap's maximum pcapng block size is currently 16MB.
+ *
+ * The maximum pcapng block size in OS X's private pcapng reading code
+ * is 1MB.  (Yes, this means that a program using the standard pcap
+ * code to read pcapng files can handle bigger blocks than can programs
+ * using the private code, such as Apple's tcpdump, can handle.)
+ *
+ * The pcapng reading code here can handle NRBs of arbitrary size (less
+ * than 4GB, obviously), as they read each NRB record independently,
+ * rather than reading the entire block into memory.
+ *
+ * So, for now, we set the maximum NRB block size we write as 1 MB.
+ *
+ * (Yes, for the benefit of the fussy, "MB" is really "MiB".)
+ */
+
+#define NRES_BLOCK_MAX_SIZE (1024*1024)
+
+static void
+compute_nrb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
+{
+    pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
+    guint32 size = 0;
+
+    switch(option_id)
+    {
+    case OPT_COMMENT:
+    case OPT_NS_DNSNAME:
+        size = pcapng_compute_option_string_size(optval->stringval);
+        break;
+    case OPT_NS_DNSIP4ADDR:
+        size = 4;
+        break;
+    case OPT_NS_DNSIP6ADDR:
+        size = 16;
+        break;
+    default:
+        /* Unknown options - size by datatype? */
+        break;
+    }
+
+    block_size->size += size;
+    /* Add bytes for option header if option should be written */
+    if (size > 0) {
+        /* Add optional padding to 32 bits */
+        if ((block_size->size & 0x03) != 0)
+        {
+            block_size->size += 4 - (block_size->size & 0x03);
+        }
+        block_size->size += 4;
+    }
+}
+
+static void
+put_nrb_option(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t* optval, void* user_data)
+{
+    guint8 **opt_ptrp = (guint8 **)user_data;
+    guint32 size = 0;
+    struct pcapng_option_header option_hdr;
+    guint32 pad;
+
+    switch(option_id)
+    {
+    case OPT_COMMENT:
+    case OPT_NS_DNSNAME:
+        if (optval->stringval != NULL) {
+            /* String options don't consider pad bytes part of the length */
+            size = (guint32)strlen(optval->stringval) & 0xffff;
+            option_hdr.type         = (guint16)option_id;
+            option_hdr.value_length = (guint16)size;
+            memcpy(*opt_ptrp, &option_hdr, 4);
+            *opt_ptrp += 4;
+
+            memcpy(*opt_ptrp, optval->stringval, size);
+            *opt_ptrp += size;
+
+            if ((size % 4)) {
+                pad = 4 - (size % 4);
+            } else {
+                pad = 0;
+            }
+
+            /* put padding (if any) */
+            if (pad != 0) {
+                memset(*opt_ptrp, 0, pad);
+                *opt_ptrp += pad;
+            }
+        }
+        break;
+    case OPT_NS_DNSIP4ADDR:
+        option_hdr.type         = (guint16)option_id;
+        option_hdr.value_length = 4;
+        memcpy(*opt_ptrp, &option_hdr, 4);
+        *opt_ptrp += 4;
+
+        memcpy(*opt_ptrp, &optval->ipv4val, 4);
+        *opt_ptrp += 4;
+        break;
+    case OPT_NS_DNSIP6ADDR:
+        option_hdr.type         = (guint16)option_id;
+        option_hdr.value_length = 16;
+        memcpy(*opt_ptrp, &option_hdr, 4);
+        *opt_ptrp += 4;
+
+        memcpy(*opt_ptrp, &optval->ipv6val, 16);
+        *opt_ptrp += 16;
+        break;
+    default:
+        /* Unknown options - size by datatype? */
+        break;
+    }
+}
+
+static void
+put_nrb_options(wtap_dumper *wdh, guint8 *opt_ptr)
+{
+    if (wdh->nrb_hdrs && wdh->nrb_hdrs->len > 0) {
+        wtap_block_t nrb_hdr = g_array_index(wdh->nrb_hdrs, wtap_block_t, 0);
+        struct option option_hdr;
+
+        wtap_block_foreach_option(nrb_hdr, put_nrb_option, &opt_ptr);
+
+        /* Put end of options */
+        option_hdr.type = OPT_EOFOPT;
+        option_hdr.value_length = 0;
+        memcpy(opt_ptr, &option_hdr, 4);
+    }
+}
+
 static gboolean
 pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
 {
     pcapng_block_header_t bh;
     pcapng_name_resolution_block_t nrb;
-    guint8 *rec_data;
-    guint32 rec_off;
+    pcapng_block_size_t opts_size;
+    size_t max_rec_data_size;
+    guint8 *block_data;
+    guint32 block_off;
     size_t hostnamelen;
     guint16 namelen;
     guint32 tot_rec_len;
@@ -3234,14 +3380,66 @@ pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
     int i;
 
     if ((!wdh->addrinfo_lists) || ((!wdh->addrinfo_lists->ipv4_addr_list)&&(!wdh->addrinfo_lists->ipv6_addr_list))) {
+        /*
+         * No name/address pairs to write.
+         * XXX - what if we have options?
+         */
+        return TRUE;
+    }
+
+    /* Calculate the space needed for options. */
+    opts_size.size = 0;
+    if (wdh->nrb_hdrs && wdh->nrb_hdrs->len > 0) {
+        wtap_block_t nrb_hdr = g_array_index(wdh->nrb_hdrs, wtap_block_t, 0);
+
+        wtap_block_foreach_option(nrb_hdr, compute_nrb_option_size, &opts_size);
+        if (opts_size.size > 0) {
+            /* End-of options tag */
+            opts_size.size += 4;
+        }
+    }
+
+    /*
+     * Make sure we can fit at least one maximum-sized record, plus
+     * an end-of-records record, plus the options, into a maximum-sized
+     * block.
+     *
+     * That requires that there be enough space for the block header
+     * (8 bytes), a maximum-sized record (2 bytes of record type, 2
+     * bytes of record value length, 65535 bytes of record value,
+     * and 1 byte of padding), an end-of-records record (4 bytes),
+     * the options (opts_size.size bytes), and the block trailer (4
+     * bytes).
+     */
+    if (8 + 2 + 2 + 65535 + 1 + 4 + opts_size.size + 4 > NRES_BLOCK_MAX_SIZE) {
+        /*
+         * XXX - we can't even fit the options in the largest NRB size
+         * we're willing to write and still have room enough for a
+         * maximum-sized record.  Just discard the information for now.
+         */
         return TRUE;
     }
 
-    rec_off = 8; /* block type + block total length */
+    /*
+     * Allocate a buffer for the largest block we'll write.
+     */
+    block_data = (guint8 *)g_malloc(NRES_BLOCK_MAX_SIZE);
+
+    /*
+     * Calculate the maximum amount of record data we'll be able to
+     * fit into such a block, after taking into account the block header
+     * (8 bytes), the end-of-records record (4 bytes), the options
+     * (opts_size.size bytes), and the block trailer (4 bytes).
+     */
+    max_rec_data_size = NRES_BLOCK_MAX_SIZE - (8 + 4 + opts_size.size + 4);
+
+    block_off = 8; /* block type + block total length */
     bh.block_type = BLOCK_TYPE_NRB;
-    bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-    rec_data = (guint8 *)g_malloc(NRES_REC_MAX_SIZE);
+    bh.block_total_length = 12; /* block header + block trailer */
 
+    /*
+     * Write out the IPv4 resolved addresses, if any.
+     */
     if (wdh->addrinfo_lists->ipv4_addr_list){
         i = 0;
         ipv4_hash_list_entry = (hashipv4_t *)g_list_nth_data(wdh->addrinfo_lists->ipv4_addr_list, i);
@@ -3259,50 +3457,60 @@ pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
                 continue;
             }
             namelen = (guint16)(hostnamelen + 1);
-            nrb.record_len = 4 + namelen;
+            nrb.record_len = 4 + namelen;  /* 4 bytes IPv4 address length */
             /* 2 bytes record type, 2 bytes length field */
             tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
 
-            if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
+            if (block_off + tot_rec_len > max_rec_data_size) {
                 /*
                  * This record would overflow our maximum size for Name
                  * Resolution Blocks; write out all the records we created
                  * before it, and start a new NRB.
                  */
 
-                /* First, copy the block header. */
-                memcpy(rec_data, &bh, sizeof(bh));
+                /* Append the end-of-records record */
+                memset(block_data + block_off, 0, 4);
+                block_off += 4;
+                bh.block_total_length += 4;
+
+                /*
+                 * Put the options into the block.
+                 *
+                 * XXX - this puts the same options in all NRBs.
+                 */
+                put_nrb_options(wdh, block_data + block_off);
+                block_off += opts_size.size;
+                bh.block_total_length += opts_size.size;
 
-                /* End of record */
-                memset(rec_data + rec_off, 0, 4);
-                rec_off += 4;
+                /* Copy the block header. */
+                memcpy(block_data, &bh, sizeof(bh));
 
-                memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+                /* Copy the block trailer. */
+                memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
 
-                pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+                pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
 
-                if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
-                    g_free(rec_data);
+                if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+                    g_free(block_data);
                     return FALSE;
                 }
                 wdh->bytes_dumped += bh.block_total_length;
 
                 /*Start a new NRB */
-                rec_off = 8; /* block type + block total length */
+                block_off = 8; /* block type + block total length */
                 bh.block_type = BLOCK_TYPE_NRB;
-                bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-
+                bh.block_total_length = 12; /* block header + block trailer */
             }
 
             bh.block_total_length += tot_rec_len;
-            memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
-            rec_off += 4;
-            memcpy(rec_data + rec_off, &(ipv4_hash_list_entry->addr), 4);
-            rec_off += 4;
-            memcpy(rec_data + rec_off, ipv4_hash_list_entry->name, namelen);
-            rec_off += namelen;
-            memset(rec_data + rec_off, 0, PADDING4(namelen));
-            rec_off += PADDING4(namelen);
+            memcpy(block_data + block_off, &nrb, sizeof(nrb));
+            block_off += 4;
+            memcpy(block_data + block_off, &(ipv4_hash_list_entry->addr), 4);
+            block_off += 4;
+            memcpy(block_data + block_off, ipv4_hash_list_entry->name, namelen);
+            block_off += namelen;
+            memset(block_data + block_off, 0, PADDING4(namelen));
+            block_off += PADDING4(namelen);
             pcapng_debug("NRB: added IPv4 record for %s", ipv4_hash_list_entry->name);
 
             i++;
@@ -3333,46 +3541,56 @@ pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
             /* 2 bytes record type, 2 bytes length field */
             tot_rec_len = 4 + nrb.record_len + PADDING4(nrb.record_len);
 
-            if (rec_off + tot_rec_len > NRES_REC_MAX_SIZE){
+            if (block_off + tot_rec_len > max_rec_data_size) {
                 /*
                  * This record would overflow our maximum size for Name
                  * Resolution Blocks; write out all the records we created
                  * before it, and start a new NRB.
                  */
 
-                /* First, copy the block header. */
-                memcpy(rec_data, &bh, sizeof(bh));
+                /* Append the end-of-records record */
+                memset(block_data + block_off, 0, 4);
+                block_off += 4;
+                bh.block_total_length += 4;
 
-                /* End of record */
-                memset(rec_data + rec_off, 0, 4);
-                rec_off += 4;
+                /*
+                 * Put the options into the block.
+                 *
+                 * XXX - this puts the same options in all NRBs.
+                 */
+                put_nrb_options(wdh, block_data + block_off);
+                block_off += opts_size.size;
+                bh.block_total_length += opts_size.size;
+
+                /* Copy the block header. */
+                memcpy(block_data, &bh, sizeof(bh));
 
-                memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+                /* Copy the block trailer. */
+                memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
 
-                pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+                pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
 
-                if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
-                    g_free(rec_data);
+                if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+                    g_free(block_data);
                     return FALSE;
                 }
                 wdh->bytes_dumped += bh.block_total_length;
 
                 /*Start a new NRB */
-                rec_off = 8; /* block type + block total length */
+                block_off = 8; /* block type + block total length */
                 bh.block_type = BLOCK_TYPE_NRB;
-                bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-
+                bh.block_total_length = 12; /* block header + block trailer */
             }
 
             bh.block_total_length += tot_rec_len;
-            memcpy(rec_data + rec_off, &nrb, sizeof(nrb));
-            rec_off += 4;
-            memcpy(rec_data + rec_off, &(ipv6_hash_list_entry->addr), 16);
-            rec_off += 16;
-            memcpy(rec_data + rec_off, ipv6_hash_list_entry->name, namelen);
-            rec_off += namelen;
-            memset(rec_data + rec_off, 0, PADDING4(namelen));
-            rec_off += PADDING4(namelen);
+            memcpy(block_data + block_off, &nrb, sizeof(nrb));
+            block_off += 4;
+            memcpy(block_data + block_off, &(ipv6_hash_list_entry->addr), 16);
+            block_off += 16;
+            memcpy(block_data + block_off, ipv6_hash_list_entry->name, namelen);
+            block_off += namelen;
+            memset(block_data + block_off, 0, PADDING4(namelen));
+            block_off += PADDING4(namelen);
             pcapng_debug("NRB: added IPv6 record for %s", ipv6_hash_list_entry->name);
 
             i++;
@@ -3382,139 +3600,59 @@ pcapng_write_name_resolution_block(wtap_dumper *wdh, int *err)
         wdh->addrinfo_lists->ipv6_addr_list = NULL;
     }
 
-    /* add options, if any */
-    if (wdh->nrb_hdrs && wdh->nrb_hdrs->len > 0) {
-        gboolean have_options = FALSE;
-        guint32 options_total_length = 0;
-        struct option option_hdr;
-        guint32 comment_len = 0, comment_pad_len = 0;
-        wtap_optionblock_t nrb_hdr = g_array_index(wdh->nrb_hdrs, wtap_optionblock_t, 0);
-        guint32 prev_rec_off = rec_off;
-        char* opt_comment;
-
-        /* get lengths first to make sure we can fit this into the block */
-        wtap_optionblock_get_option_string(nrb_hdr, OPT_COMMENT, &opt_comment);
-        if (opt_comment) {
-            have_options = TRUE;
-            comment_len = (guint32)strlen(opt_comment) & 0xffff;
-            if ((comment_len % 4)) {
-                comment_pad_len = 4 - (comment_len % 4);
-            } else {
-                comment_pad_len = 0;
-            }
-            options_total_length = options_total_length + comment_len + comment_pad_len + 4 /* comment options tag */ ;
-        }
-
-        if (have_options) {
-            /* End-of options tag */
-            options_total_length += 4;
-
-            if (rec_off + options_total_length > NRES_REC_MAX_SIZE) {
-                /*
-                 * This record would overflow our maximum size for Name
-                 * Resolution Blocks; write out all the records we created
-                 * before it, and start a new NRB.
-                 */
-
-                /* First, copy the block header. */
-                memcpy(rec_data, &bh, sizeof(bh));
-
-                /* End of record */
-                memset(rec_data + rec_off, 0, 4);
-                rec_off += 4;
-
-                memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
-
-                pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
-
-                if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
-                    g_free(rec_data);
-                    return FALSE;
-                }
-                wdh->bytes_dumped += bh.block_total_length;
-
-                /*Start a new NRB */
-                prev_rec_off = rec_off = 8; /* block type + block total length */
-                bh.block_type = BLOCK_TYPE_NRB;
-                bh.block_total_length = rec_off + 8; /* end-of-record + block total length */
-            }
-
-            bh.block_total_length += options_total_length;
-
-            if (comment_len > 0) {
-                option_hdr.type         = OPT_COMMENT;
-                option_hdr.value_length = comment_len;
-
-                memcpy(rec_data + rec_off, &option_hdr, sizeof(option_hdr));
-                rec_off += (guint32)sizeof(option_hdr);
-
-                /* Write the comments string */
-                memcpy(rec_data + rec_off, opt_comment, comment_len);
-                rec_off += comment_len;
-                memset(rec_data + rec_off, 0, comment_pad_len);
-                rec_off += comment_pad_len;
-
-                pcapng_debug("pcapng_write_name_resolution_block: Wrote Options comments: comment_len %u, comment_pad_len %u",
-                              comment_len,
-                              comment_pad_len);
-            }
-
-            /* Write end of options */
-            memset(rec_data + rec_off, 0, 4);
-            rec_off += 4;
-
-            /* sanity check */
-            g_assert(options_total_length == rec_off - prev_rec_off);
-        }
-    }
+    /* Append the end-of-records record */
+    memset(block_data + block_off, 0, 4);
+    block_off += 4;
+    bh.block_total_length += 4;
 
-    /* We know the total length now; copy the block header. */
-    memcpy(rec_data, &bh, sizeof(bh));
+    /*
+     * Put the options into the block.
+     */
+    put_nrb_options(wdh, block_data + block_off);
+    block_off += opts_size.size;
+    bh.block_total_length += opts_size.size;
 
-    /* End of record */
-    memset(rec_data + rec_off, 0, 4);
-    rec_off += 4;
+    /* Copy the block header. */
+    memcpy(block_data, &bh, sizeof(bh));
 
-    memcpy(rec_data + rec_off, &bh.block_total_length, sizeof(bh.block_total_length));
+    /* Copy the block trailer. */
+    memcpy(block_data + block_off, &bh.block_total_length, sizeof(bh.block_total_length));
 
-    pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, rec_off %u", bh.block_total_length, rec_off);
+    pcapng_debug("pcapng_write_name_resolution_block: Write bh.block_total_length bytes %d, block_off %u", bh.block_total_length, block_off);
 
-    if (!wtap_dump_file_write(wdh, rec_data, bh.block_total_length, err)) {
-        g_free(rec_data);
+    if (!wtap_dump_file_write(wdh, block_data, bh.block_total_length, err)) {
+        g_free(block_data);
         return FALSE;
     }
-
-    g_free(rec_data);
     wdh->bytes_dumped += bh.block_total_length;
+
+    g_free(block_data);
+
     return TRUE;
 }
 
-static void compute_isb_option_size(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void compute_isb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
 {
-    pcapng_optionblock_size_t* block_size = (pcapng_optionblock_size_t*)user_data;
+    pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
     guint32 size = 0;
 
     switch(option_id)
     {
     case OPT_COMMENT:
-        if (option != NULL) {
-            size = pcapng_compute_option_string_size(option->stringval);
+        if (optval->stringval != NULL) {
+            size = pcapng_compute_option_string_size(optval->stringval);
         }
         break;
     case OPT_ISB_STARTTIME:
     case OPT_ISB_ENDTIME:
-        if ((option != NULL) && (option->uint64val != 0)) {
-            size = 8;
-        }
+        size = 8;
         break;
     case OPT_ISB_IFRECV:
     case OPT_ISB_IFDROP:
     case OPT_ISB_FILTERACCEPT:
     case OPT_ISB_OSDROP:
     case OPT_ISB_USRDELIV:
-        if ((option != NULL) && (option->uint64val != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF))) {
-            size = 8;
-        }
+        size = 8;
         break;
     default:
         /* Unknown options - size by datatype? */
@@ -3533,7 +3671,7 @@ static void compute_isb_option_size(wtap_optionblock_t block _U_, guint option_i
     }
 }
 
-static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void write_wtap_isb_block(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
 {
     pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
     struct pcapng_option_header option_hdr;
@@ -3545,8 +3683,8 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
     switch(option_id)
     {
     case OPT_COMMENT:
-        if ((option != NULL) && (option->stringval != NULL)) {
-            if (!pcapng_write_option_string(write_block->wdh, option_id, option->stringval, write_block->err)) {
+        if (optval->stringval != NULL) {
+            if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
                 write_block->success = FALSE;
                 return;
             }
@@ -3554,7 +3692,7 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
         break;
     case OPT_ISB_STARTTIME:
     case OPT_ISB_ENDTIME:
-        if ((option != NULL) && (option->uint64val != 0)) {
+        {
             guint32 high, low;
 
             option_hdr.type         = option_id;
@@ -3565,8 +3703,8 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
             }
             write_block->wdh->bytes_dumped += 4;
 
-            high = (guint32)(option->uint64val >> 32);
-            low = (guint32)(option->uint64val >> 0);
+            high = (guint32)(optval->uint64val >> 32);
+            low = (guint32)(optval->uint64val >> 0);
             if (!wtap_dump_file_write(write_block->wdh, &high, sizeof(guint32), write_block->err)) {
                 write_block->success = FALSE;
                 return;
@@ -3584,7 +3722,7 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
     case OPT_ISB_FILTERACCEPT:
     case OPT_ISB_OSDROP:
     case OPT_ISB_USRDELIV:
-        if ((option != NULL) && (option->uint64val != G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF))) {
+        {
             option_hdr.type         = option_id;
             option_hdr.value_length = 8;
             if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
@@ -3593,7 +3731,7 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
             }
             write_block->wdh->bytes_dumped += 4;
 
-            if (!wtap_dump_file_write(write_block->wdh, &option->uint64val, sizeof(guint64), write_block->err)) {
+            if (!wtap_dump_file_write(write_block->wdh, &optval->uint64val, sizeof(guint64), write_block->err)) {
                 write_block->success = FALSE;
                 return;
             }
@@ -3607,20 +3745,20 @@ static void write_wtap_isb_block(wtap_optionblock_t block _U_, guint option_id,
 }
 
 static gboolean
-pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_optionblock_t if_stats, int *err)
+pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_block_t if_stats, int *err)
 {
     pcapng_block_header_t bh;
     pcapng_interface_statistics_block_t isb;
-    pcapng_optionblock_size_t block_size;
+    pcapng_block_size_t block_size;
     pcapng_write_block_t block_data;
     struct pcapng_option_header option_hdr;
-    wtapng_if_stats_mandatory_t* mand_data = (wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats);
+    wtapng_if_stats_mandatory_t* mand_data = (wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats);
 
     pcapng_debug("pcapng_write_interface_statistics_block");
 
     /* Compute block size */
     block_size.size = 0;
-    wtap_optionblock_foreach_option(if_stats, compute_isb_option_size, &block_size);
+    wtap_block_foreach_option(if_stats, compute_isb_option_size, &block_size);
 
     if (block_size.size > 0) {
         /* End-of-options tag */
@@ -3650,7 +3788,7 @@ pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_optionblock_t if_
         block_data.wdh = wdh;
         block_data.err = err;
         block_data.success = TRUE;
-        wtap_optionblock_foreach_option(if_stats, write_wtap_isb_block, &block_data);
+        wtap_block_foreach_option(if_stats, write_wtap_isb_block, &block_data);
 
         if (!block_data.success)
             return FALSE;
@@ -3671,9 +3809,9 @@ pcapng_write_interface_statistics_block(wtap_dumper *wdh, wtap_optionblock_t if_
     return TRUE;
 }
 
-static void compute_idb_option_size(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void compute_idb_option_size(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
 {
-    pcapng_optionblock_size_t* block_size = (pcapng_optionblock_size_t*)user_data;
+    pcapng_block_size_t* block_size = (pcapng_block_size_t*)user_data;
     guint32 size = 0;
 
     switch(option_id)
@@ -3682,23 +3820,19 @@ static void compute_idb_option_size(wtap_optionblock_t block _U_, guint option_i
     case OPT_IDB_NAME:
     case OPT_IDB_DESCR:
     case OPT_IDB_OS:
-        if (option != NULL) {
-            size = pcapng_compute_option_string_size(option->stringval);
+        if (optval != NULL) {
+            size = pcapng_compute_option_string_size(optval->stringval);
         }
         break;
     case OPT_IDB_SPEED:
-        if ((option != NULL) && (option->uint64val != 0)) {
-            size = 8;
-        }
+        size = 8;
         break;
     case OPT_IDB_TSRESOL:
-        if ((option != NULL) && (option->uint8val != 0)) {
-            size = 1;
-        }
+        size = 1;
         break;
     case OPT_IDB_FILTER:
-        if (option != NULL) {
-            wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)option->customval.data;
+        {
+            wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->customval.data;
             guint32 pad;
             if ((filter != NULL) && (filter->if_filter_str != NULL)) {
                 size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff;
@@ -3732,7 +3866,7 @@ static void compute_idb_option_size(wtap_optionblock_t block _U_, guint option_i
     }
 }
 
-static void write_wtap_idb_block(wtap_optionblock_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_option_type* option, void* user_data)
+static void write_wtap_idb_block(wtap_block_t block _U_, guint option_id, wtap_opttype_e option_type _U_, wtap_optval_t *optval, void* user_data)
 {
     pcapng_write_block_t* write_block = (pcapng_write_block_t*)user_data;
     struct pcapng_option_header option_hdr;
@@ -3744,56 +3878,52 @@ static void write_wtap_idb_block(wtap_optionblock_t block _U_, guint option_id,
     case OPT_IDB_NAME:
     case OPT_IDB_DESCR:
     case OPT_IDB_OS:
-        if ((option != NULL) && (option->stringval != NULL)) {
-            if (!pcapng_write_option_string(write_block->wdh, option_id, option->stringval, write_block->err)) {
+        if (optval->stringval != NULL) {
+            if (!pcapng_write_option_string(write_block->wdh, option_id, optval->stringval, write_block->err)) {
                 write_block->success = FALSE;
                 return;
             }
         }
         break;
     case OPT_IDB_SPEED:
-        if ((option != NULL) && (option->uint64val != 0)) {
-            option_hdr.type         = option_id;
-            option_hdr.value_length = 8;
-            if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
-                write_block->success = FALSE;
-                return;
-            }
-            write_block->wdh->bytes_dumped += 4;
+        option_hdr.type         = option_id;
+        option_hdr.value_length = 8;
+        if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+            write_block->success = FALSE;
+            return;
+        }
+        write_block->wdh->bytes_dumped += 4;
 
-            if (!wtap_dump_file_write(write_block->wdh, &option->uint64val, sizeof(guint64), write_block->err)) {
-                write_block->success = FALSE;
-                return;
-            }
-            write_block->wdh->bytes_dumped += 8;
+        if (!wtap_dump_file_write(write_block->wdh, &optval->uint64val, sizeof(guint64), write_block->err)) {
+            write_block->success = FALSE;
+            return;
         }
+        write_block->wdh->bytes_dumped += 8;
         break;
     case OPT_IDB_TSRESOL:
-        if ((option != NULL) && (option->uint8val != 0)) {
-            option_hdr.type         = option_id;
-            option_hdr.value_length = 1;
-            if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
-                write_block->success = FALSE;
-                return;
-            }
-            write_block->wdh->bytes_dumped += 4;
+        option_hdr.type         = option_id;
+        option_hdr.value_length = 1;
+        if (!wtap_dump_file_write(write_block->wdh, &option_hdr, 4, write_block->err)) {
+            write_block->success = FALSE;
+            return;
+        }
+        write_block->wdh->bytes_dumped += 4;
 
-            if (!wtap_dump_file_write(write_block->wdh, &option->uint8val, 1, write_block->err)) {
-                write_block->success = FALSE;
-                return;
-            }
-            write_block->wdh->bytes_dumped += 1;
+        if (!wtap_dump_file_write(write_block->wdh, &optval->uint8val, 1, write_block->err)) {
+            write_block->success = FALSE;
+            return;
+        }
+        write_block->wdh->bytes_dumped += 1;
 
-            if (!wtap_dump_file_write(write_block->wdh, &zero_pad, 3, write_block->err)) {
-                write_block->success = FALSE;
-                return;
-            }
-            write_block->wdh->bytes_dumped += 3;
+        if (!wtap_dump_file_write(write_block->wdh, &zero_pad, 3, write_block->err)) {
+            write_block->success = FALSE;
+            return;
         }
+        write_block->wdh->bytes_dumped += 3;
         break;
     case OPT_IDB_FILTER:
-        if (option != NULL) {
-            wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)option->customval.data;
+        {
+            wtapng_if_descr_filter_t* filter = (wtapng_if_descr_filter_t*)optval->customval.data;
             guint32 size, pad;
             if ((filter != NULL) && (filter->if_filter_str != NULL)) {
                 size = (guint32)(strlen(filter->if_filter_str) + 1) & 0xffff;
@@ -3847,14 +3977,14 @@ static void write_wtap_idb_block(wtap_optionblock_t block _U_, guint option_id,
 }
 
 static gboolean
-pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_optionblock_t int_data, int *err)
+pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_block_t int_data, int *err)
 {
     pcapng_block_header_t bh;
     pcapng_interface_description_block_t idb;
-    pcapng_optionblock_size_t block_size;
+    pcapng_block_size_t block_size;
     pcapng_write_block_t block_data;
     struct pcapng_option_header option_hdr;
-    wtapng_if_descr_mandatory_t* mand_data = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+    wtapng_if_descr_mandatory_t* mand_data = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
 
     pcapng_debug("pcapng_write_if_descr_block: encap = %d (%s), snaplen = %d",
                   mand_data->link_type,
@@ -3868,7 +3998,7 @@ pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_optionblock_t int_data, int *
 
     /* Compute block size */
     block_size.size = 0;
-    wtap_optionblock_foreach_option(int_data, compute_idb_option_size, &block_size);
+    wtap_block_foreach_option(int_data, compute_idb_option_size, &block_size);
 
     if (block_size.size > 0) {
         /* End-of-options tag */
@@ -3898,7 +4028,7 @@ pcapng_write_if_descr_block(wtap_dumper *wdh, wtap_optionblock_t int_data, int *
         block_data.wdh = wdh;
         block_data.err = err;
         block_data.success = TRUE;
-        wtap_optionblock_foreach_option(int_data, write_wtap_idb_block, &block_data);
+        wtap_block_foreach_option(int_data, write_wtap_idb_block, &block_data);
 
         if (!block_data.success)
             return FALSE;
@@ -3990,17 +4120,17 @@ static gboolean pcapng_dump_finish(wtap_dumper *wdh, int *err)
     for (i = 0; i < wdh->interface_data->len; i++) {
 
         /* Get the interface description */
-        wtap_optionblock_t int_data;
+        wtap_block_t int_data;
         wtapng_if_descr_mandatory_t *int_data_mand;
 
-        int_data = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
-        int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
+        int_data = g_array_index(wdh->interface_data, wtap_block_t, i);
+        int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
 
         for (j = 0; j < int_data_mand->num_stat_entries; j++) {
-            wtap_optionblock_t if_stats;
+            wtap_block_t if_stats;
 
-            if_stats = g_array_index(int_data_mand->interface_statistics, wtap_optionblock_t, j);
-            pcapng_debug("pcapng_dump_finish: write ISB for interface %u", ((wtapng_if_stats_mandatory_t*)wtap_optionblock_get_mandatory_data(if_stats))->interface_id);
+            if_stats = g_array_index(int_data_mand->interface_statistics, wtap_block_t, j);
+            pcapng_debug("pcapng_dump_finish: write ISB for interface %u", ((wtapng_if_stats_mandatory_t*)wtap_block_get_mandatory_data(if_stats))->interface_id);
             if (!pcapng_write_interface_statistics_block(wdh, if_stats, err)) {
                 return FALSE;
             }
@@ -4043,9 +4173,9 @@ pcapng_dump_open(wtap_dumper *wdh, int *err)
     for (i = 0; i < wdh->interface_data->len; i++) {
 
         /* Get the interface description */
-        wtap_optionblock_t idb;
+        wtap_block_t idb;
 
-        idb = g_array_index(wdh->interface_data, wtap_optionblock_t, i);
+        idb = g_array_index(wdh->interface_data, wtap_block_t, i);
 
         if (!pcapng_write_if_descr_block(wdh, idb, err)) {
             return FALSE;
index 0d1acc3657ea117926979fec374b8f96e224337a..01dfee42d3bd8190884fac7b111a30b5bb47bf3c 100644 (file)
@@ -161,84 +161,45 @@ wtap_file_tsprec(wtap *wth)
        return wth->file_tsprec;
 }
 
-const gchar *
-wtap_file_get_shb_comment(wtap *wth)
-{
-       char* opt_comment;
-       if ((wth == NULL) || (wth->shb_hdrs == NULL) || (wth->shb_hdrs->len == 0))
-               return NULL;
-
-       wtap_optionblock_get_option_string(g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0), OPT_COMMENT, &opt_comment);
-       return opt_comment;
-}
-
-wtap_optionblock_t
+wtap_block_t
 wtap_file_get_shb(wtap *wth)
 {
        if ((wth == NULL) || (wth->shb_hdrs == NULL) || (wth->shb_hdrs->len == 0))
                return NULL;
 
-       return g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0);
+       return g_array_index(wth->shb_hdrs, wtap_block_t, 0);
 }
 
 GArray*
 wtap_file_get_shb_for_new_file(wtap *wth)
 {
        guint shb_count;
-       wtap_optionblock_t shb_hdr_src, shb_hdr_dest;
+       wtap_block_t shb_hdr_src, shb_hdr_dest;
        GArray* shb_hdrs;
 
        if ((wth == NULL) || (wth->shb_hdrs == NULL) || (wth->shb_hdrs->len == 0))
                return NULL;
 
-       shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+       shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
        for (shb_count = 0; shb_count < wth->shb_hdrs->len; shb_count++) {
-               shb_hdr_src = g_array_index(wth->shb_hdrs, wtap_optionblock_t, shb_count);
-               shb_hdr_dest = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
-               wtap_optionblock_copy_options(shb_hdr_dest, shb_hdr_src);
+               shb_hdr_src = g_array_index(wth->shb_hdrs, wtap_block_t, shb_count);
+               shb_hdr_dest = wtap_block_create(WTAP_BLOCK_NG_SECTION);
+               wtap_block_copy(shb_hdr_dest, shb_hdr_src);
                g_array_append_val(shb_hdrs, shb_hdr_dest);
        }
 
        return shb_hdrs;
 }
 
-const gchar*
-wtap_get_nrb_comment(wtap *wth)
-{
-       char* opt_comment;
-       g_assert(wth);
-
-       if ((wth == NULL) || (wth->nrb_hdrs == NULL) || (wth->nrb_hdrs->len == 0))
-               return NULL;
-
-       wtap_optionblock_get_option_string(g_array_index(wth->nrb_hdrs, wtap_optionblock_t, 0), OPT_COMMENT, &opt_comment);
-       return opt_comment;
-}
-
-void
-wtap_write_nrb_comment(wtap *wth, gchar *comment)
-{
-       wtap_optionblock_t nrb;
-       g_assert(wth);
-
-       if (wth == NULL)
-               return;
-
-       if (wth->nrb_hdrs == NULL) {
-               wth->nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
-               nrb = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_NRB);
-               g_array_append_val(wth->nrb_hdrs, nrb);
-       }
-
-       wtap_optionblock_set_option_string(g_array_index(wth->nrb_hdrs, wtap_optionblock_t, 0), OPT_COMMENT, comment, (gsize)(comment ? strlen(comment) : 0));
-}
-
+/*
+ * XXX - replace with APIs that let us handle multiple comments.
+ */
 void
 wtap_write_shb_comment(wtap *wth, gchar *comment)
 {
        if ((wth != NULL) && (wth->shb_hdrs != NULL) && (wth->shb_hdrs->len > 0)) {
-               wtap_optionblock_set_option_string(g_array_index(wth->shb_hdrs, wtap_optionblock_t, 0), OPT_COMMENT, comment, (gsize)(comment ? strlen(comment) : 0));
+               wtap_block_set_nth_string_option_value(g_array_index(wth->shb_hdrs, wtap_block_t, 0), OPT_COMMENT, 0, comment, (gsize)(comment ? strlen(comment) : 0));
        }
 }
 
@@ -261,12 +222,12 @@ wtap_free_idb_info(wtapng_iface_descriptions_t *idb_info)
        if (idb_info == NULL)
                return;
 
-       wtap_optionblock_array_free(idb_info->interface_data);
+       wtap_block_array_free(idb_info->interface_data);
        g_free(idb_info);
 }
 
 gchar *
-wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
+wtap_get_debug_if_descr(const wtap_block_t if_descr,
                         const int indent,
                         const char* line_end)
 {
@@ -280,18 +241,20 @@ wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
 
        g_assert(if_descr);
 
-       if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(if_descr);
-       wtap_optionblock_get_option_string(if_descr, OPT_IDB_NAME, &tmp_content);
-       g_string_printf(info,
-                       "%*cName = %s%s", indent, ' ',
-                       tmp_content ? tmp_content : "UNKNOWN",
-                       line_end);
+       if_descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(if_descr);
+       if (wtap_block_get_string_option_value(if_descr, OPT_IDB_NAME, &tmp_content) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_printf(info,
+                               "%*cName = %s%s", indent, ' ',
+                               tmp_content ? tmp_content : "UNKNOWN",
+                               line_end);
+       }
 
-       wtap_optionblock_get_option_string(if_descr, OPT_IDB_DESCR, &tmp_content);
-       g_string_append_printf(info,
-                       "%*cDescription = %s%s", indent, ' ',
-                       tmp_content ? tmp_content : "NONE",
-                       line_end);
+       if (wtap_block_get_string_option_value(if_descr, OPT_IDB_DESCR, &tmp_content) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cDescription = %s%s", indent, ' ',
+                               tmp_content ? tmp_content : "NONE",
+                               line_end);
+       }
 
        g_string_append_printf(info,
                        "%*cEncapsulation = %s (%d/%u - %s)%s", indent, ' ',
@@ -301,22 +264,24 @@ wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
                        wtap_encap_short_string(if_descr_mand->wtap_encap),
                        line_end);
 
-       wtap_optionblock_get_option_uint64(if_descr, OPT_IDB_SPEED, &tmp64);
-       g_string_append_printf(info,
-                       "%*cSpeed = %" G_GINT64_MODIFIER "u%s", indent, ' ',
-                       tmp64,
-                       line_end);
+       if (wtap_block_get_uint64_option_value(if_descr, OPT_IDB_SPEED, &tmp64) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cSpeed = %" G_GINT64_MODIFIER "u%s", indent, ' ',
+                               tmp64,
+                               line_end);
+       }
 
        g_string_append_printf(info,
                        "%*cCapture length = %u%s", indent, ' ',
                        if_descr_mand->snap_len,
                        line_end);
 
-       wtap_optionblock_get_option_uint8(if_descr, OPT_IDB_FCSLEN, &itmp8);
-       g_string_append_printf(info,
-                       "%*cFCS length = %d%s", indent, ' ',
-                       itmp8,
-                       line_end);
+       if (wtap_block_get_uint8_option_value(if_descr, OPT_IDB_FCSLEN, &itmp8) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cFCS length = %d%s", indent, ' ',
+                               itmp8,
+                               line_end);
+       }
 
        g_string_append_printf(info,
                        "%*cTime precision = %s (%d)%s", indent, ' ',
@@ -329,34 +294,41 @@ wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
                        if_descr_mand->time_units_per_second,
                        line_end);
 
-       wtap_optionblock_get_option_uint8(if_descr, OPT_IDB_TSRESOL, &tmp8);
-       g_string_append_printf(info,
-                       "%*cTime resolution = 0x%.2x%s", indent, ' ',
-                       tmp8,
-                       line_end);
+       if (wtap_block_get_uint8_option_value(if_descr, OPT_IDB_TSRESOL, &tmp8) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cTime resolution = 0x%.2x%s", indent, ' ',
+                               tmp8,
+                               line_end);
+       }
 
-       wtap_optionblock_get_option_custom(if_descr, OPT_IDB_FILTER, (void**)&if_filter);
-       g_string_append_printf(info,
-                       "%*cFilter string = %s%s", indent, ' ',
-                       if_filter->if_filter_str ? if_filter->if_filter_str : "NONE",
-                       line_end);
+       if (wtap_block_get_custom_option_value(if_descr, OPT_IDB_FILTER, (void**)&if_filter) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cFilter string = %s%s", indent, ' ',
+                               if_filter->if_filter_str ? if_filter->if_filter_str : "NONE",
+                               line_end);
 
-       wtap_optionblock_get_option_string(if_descr, OPT_IDB_OS, &tmp_content);
-       g_string_append_printf(info,
-                       "%*cOperating system = %s%s", indent, ' ',
-                       tmp_content ? tmp_content : "UNKNOWN",
-                       line_end);
+               g_string_append_printf(info,
+                               "%*cBPF filter length = %u%s", indent, ' ',
+                               if_filter->bpf_filter_len,
+                               line_end);
+       }
 
-       wtap_optionblock_get_option_string(if_descr, OPT_COMMENT, &tmp_content);
-       g_string_append_printf(info,
-                       "%*cComment = %s%s", indent, ' ',
-                       tmp_content ? tmp_content : "NONE",
-                       line_end);
+       if (wtap_block_get_string_option_value(if_descr, OPT_IDB_OS, &tmp_content) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cOperating system = %s%s", indent, ' ',
+                               tmp_content ? tmp_content : "UNKNOWN",
+                               line_end);
+       }
 
-       g_string_append_printf(info,
-                       "%*cBPF filter length = %u%s", indent, ' ',
-                       if_filter->bpf_filter_len,
-                       line_end);
+       /*
+        * XXX - support multiple comments.
+        */
+       if (wtap_block_get_nth_string_option_value(if_descr, OPT_COMMENT, 0, &tmp_content) == WTAP_OPTTYPE_SUCCESS) {
+               g_string_append_printf(info,
+                               "%*cComment = %s%s", indent, ' ',
+                               tmp_content ? tmp_content : "NONE",
+                               line_end);
+       }
 
        g_string_append_printf(info,
                        "%*cNumber of stat entries = %u%s", indent, ' ',
@@ -366,22 +338,31 @@ wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
        return g_string_free(info, FALSE);
 }
 
+wtap_block_t
+wtap_file_get_nrb(wtap *wth)
+{
+       if ((wth == NULL) || (wth->nrb_hdrs == NULL) || (wth->nrb_hdrs->len == 0))
+               return NULL;
+
+       return g_array_index(wth->nrb_hdrs, wtap_block_t, 0);
+}
+
 GArray*
 wtap_file_get_nrb_for_new_file(wtap *wth)
 {
        guint nrb_count;
-       wtap_optionblock_t nrb_hdr_src, nrb_hdr_dest;
+       wtap_block_t nrb_hdr_src, nrb_hdr_dest;
        GArray* nrb_hdrs;
 
        if ((wth == NULL || wth->nrb_hdrs == NULL) || (wth->nrb_hdrs->len == 0))
                return NULL;
 
-       nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
+       nrb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
 
        for (nrb_count = 0; nrb_count < wth->nrb_hdrs->len; nrb_count++) {
-               nrb_hdr_src = g_array_index(wth->nrb_hdrs, wtap_optionblock_t, nrb_count);
-               nrb_hdr_dest = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_NRB);
-               wtap_optionblock_copy_options(nrb_hdr_dest, nrb_hdr_src);
+               nrb_hdr_src = g_array_index(wth->nrb_hdrs, wtap_block_t, nrb_count);
+               nrb_hdr_dest = wtap_block_create(WTAP_BLOCK_NG_NRB);
+               wtap_block_copy(nrb_hdr_dest, nrb_hdr_src);
                g_array_append_val(nrb_hdrs, nrb_hdr_dest);
        }
 
@@ -1212,9 +1193,9 @@ wtap_close(wtap *wth)
                g_ptr_array_free(wth->fast_seek, TRUE);
        }
 
-       wtap_optionblock_array_free(wth->shb_hdrs);
-       wtap_optionblock_array_free(wth->nrb_hdrs);
-       wtap_optionblock_array_free(wth->interface_data);
+       wtap_block_array_free(wth->shb_hdrs);
+       wtap_block_array_free(wth->nrb_hdrs);
+       wtap_block_array_free(wth->interface_data);
 
        g_free(wth);
 }
index b89701f24cb21b9150050556f21bbd9b1b272500..566ec50a752367dc3ea8512ba8d5a9cb26011639 100644 (file)
@@ -1268,7 +1268,7 @@ typedef struct wtapng_section_mandatory_s {
 } wtapng_mandatory_section_t;
 
 /** struct holding the information to build IDB:s
- *  the interface_data array holds an array of wtap_optionblock_t
+ *  the interface_data array holds an array of wtap_block_t
  *  represending IDB of one per interface.
  */
 typedef struct wtapng_iface_descriptions_s {
@@ -1592,13 +1592,15 @@ int wtap_file_tsprec(wtap *wth);
  *
  * @param wth The wiretap session.
  * @return The existing section header, which must NOT be g_free'd.
+ *
+ * XXX - need to be updated to handle multiple SHBs.
  */
 WS_DLL_PUBLIC
-wtap_optionblock_t wtap_file_get_shb(wtap *wth);
+wtap_block_t wtap_file_get_shb(wtap *wth);
 
 /**
  * @brief Gets new section header block for new file, based on existing info.
- * @details Creates a new wtap_optionblock_t section header block and only
+ * @details Creates a new wtap_block_t section header block and only
  *          copies appropriate members of the SHB for a new file. In
  *          particular, the comment string is copied, and any custom options
  *          which should be copied are copied. The os, hardware, and
@@ -1612,16 +1614,6 @@ wtap_optionblock_t wtap_file_get_shb(wtap *wth);
 WS_DLL_PUBLIC
 GArray* wtap_file_get_shb_for_new_file(wtap *wth);
 
-/**
- * @brief Gets the section header comment string.
- * @details This gets the pointer, without duplicating the string.
- *
- * @param wth The wtap session.
- * @return The comment string.
- */
-WS_DLL_PUBLIC
-const gchar* wtap_file_get_shb_comment(wtap *wth);
-
 /**
  * @brief Sets or replaces the section header comment.
  * @details The passed-in comment string is set to be the comment
@@ -1675,46 +1667,37 @@ void wtap_free_idb_info(wtapng_iface_descriptions_t *idb_info);
  * @return A newly allocated gcahr array string, which must be g_free'd.
  */
 WS_DLL_PUBLIC
-gchar *wtap_get_debug_if_descr(const wtap_optionblock_t if_descr,
+gchar *wtap_get_debug_if_descr(const wtap_block_t if_descr,
                                const int indent,
                                const char* line_end);
 
 /**
- * @brief Gets new name resolution info for new file, based on existing info.
- * @details Creates a new wtap_optionblock_t of name resolution info and only
- *          copies appropriate members for a new file.
- *
- * @note Use wtap_free_nrb() to free the returned pointer.
+ * @brief Gets existing name resolution block, not for new file.
+ * @details Returns the pointer to the existing NRB, without creating a
+ *          new one. This should only be used for accessing info, not
+ *          for creating a new file based on existing NRB info. Use
+ *          wtap_file_get_nrb_for_new_file() for that.
  *
  * @param wth The wiretap session.
- * @return The new name resolution info, which must be freed.
- */
-WS_DLL_PUBLIC
-GArray* wtap_file_get_nrb_for_new_file(wtap *wth);
-
-/**
- * @brief Gets the name resolution comment, if any.
- * @details This retrieves the name resolution comment string pointer,
- *          possibly NULL.
+ * @return The existing section header, which must NOT be g_free'd.
  *
- * @param wth The wiretap session.
- * @return The comment string.
+ * XXX - need to be updated to handle multiple NRBs.
  */
 WS_DLL_PUBLIC
-const gchar* wtap_get_nrb_comment(wtap *wth);
+wtap_block_t wtap_file_get_nrb(wtap *wth);
 
 /**
- * @brief Sets or replaces the name resolution comment.
- * @details The passed-in comment string is set to be the comment
- *          for the name resolution block. The passed-in string's
- *          ownership will be owned by the block, so it should be
- *          duplicated before passing into this function.
+ * @brief Gets new name resolution info for new file, based on existing info.
+ * @details Creates a new wtap_block_t of name resolution info and only
+ *          copies appropriate members for a new file.
+ *
+ * @note Use wtap_free_nrb() to free the returned pointer.
  *
  * @param wth The wiretap session.
- * @param comment The comment string.
+ * @return The new name resolution info, which must be freed.
  */
 WS_DLL_PUBLIC
-void wtap_write_nrb_comment(wtap *wth, gchar *comment);
+GArray* wtap_file_get_nrb_for_new_file(wtap *wth);
 
 /*** close the file descriptors for the current file ***/
 WS_DLL_PUBLIC
index f42aa262504a8c454cdde2bc5e41acb6d919e8b7..445621e274f5ea66c3b10376ecd2d0ccf7ea0029 100644 (file)
 #define wtap_debug(...)
 #endif
 
-typedef struct wtap_opt_register
-{
+/*
+ * Structure describing a type of block.
+ */
+typedef struct {
+    wtap_block_type_t block_type;    /**< internal type code for block */
     const char *name;                /**< name of block */
     const char *description;         /**< human-readable description of block */
     wtap_block_create_func create;
     wtap_mand_free_func free_mand;
     wtap_mand_copy_func copy_mand;
-} wtap_opt_register_t;
+    GArray *options;                 /**< array of known options */
+} wtap_blocktype_t;
 
-typedef struct wtap_optblock_internal {
-    const char *name;                /**< name of option */
-    const char *description;         /**< human-readable description of option */
-    guint number;                    /**< Option index */
-    wtap_opttype_e type;             /**< type of that option */
-} wtap_optblock_internal_t;
+typedef void (*wtap_opttype_free_custom_func)(void* data);
 
-typedef struct wtap_optblock_value {
-    wtap_optblock_internal_t* info;
-    wtap_option_type option;         /**< pointer to variable storing the value */
-    wtap_option_type default_val;    /**< the default value of the option */
-} wtap_optblock_value_t;
-
-struct wtap_optionblock
+/*
+ * Structure describing a type of option.
+ */
+typedef struct {
+    const char *name;                        /**< name of option */
+    const char *description;                 /**< human-readable description of option */
+    wtap_opttype_e data_type;                /**< data type of that option */
+    guint flags;                             /**< flags for the option */
+    wtap_opttype_free_custom_func free_func; /**< function to free custom option data */
+} wtap_opttype_t;
+
+/* Flags */
+#define WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED 0x00000001 /* multiple instances allowed */
+
+struct wtap_block
 {
-    wtap_opt_register_t* info;
+    wtap_blocktype_t* info;
     void* mandatory_data;
-    GArray* option_infos; /* Only want to keep 1 copy of "static" option information */
-    GArray* option_values;
+    GArray* options;
 };
 
-#define MAX_WTAP_OPTION_BLOCK_CUSTOM    10
-#define MAX_WTAP_OPTION_BLOCK_TYPE_VALUE (WTAP_OPTION_BLOCK_END_OF_LIST+MAX_WTAP_OPTION_BLOCK_CUSTOM)
+#define MAX_WTAP_BLOCK_CUSTOM    10
+#define MAX_WTAP_BLOCK_TYPE_VALUE (WTAP_BLOCK_END_OF_LIST+MAX_WTAP_BLOCK_CUSTOM)
 
-/* Keep track of wtap_opt_register_t's via their id number */
-static wtap_opt_register_t* block_list[MAX_WTAP_OPTION_BLOCK_TYPE_VALUE];
+/* Keep track of wtap_blocktype_t's via their id number */
+static wtap_blocktype_t* blocktype_list[MAX_WTAP_BLOCK_TYPE_VALUE];
 static guint num_custom_blocks;
-static wtap_opt_register_t custom_block_list[MAX_WTAP_OPTION_BLOCK_CUSTOM];
+static wtap_blocktype_t custom_blocktype_list[MAX_WTAP_BLOCK_CUSTOM];
 
-static void wtap_opttype_block_register(int block_type, wtap_opt_register_t *block)
+static void wtap_opttype_block_register(int block_type, wtap_blocktype_t *blocktype)
 {
+    static const wtap_opttype_t opt_comment = {
+        "opt_comment",
+        "Comment",
+        WTAP_OPTTYPE_STRING, 
+        WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED,
+        NULL
+    };
+
     /* Check input */
-    g_assert(block_type < WTAP_OPTION_BLOCK_END_OF_LIST);
+    g_assert(block_type < WTAP_BLOCK_END_OF_LIST);
 
     /* Don't re-register. */
-    g_assert(block_list[block_type] == NULL);
+    g_assert(blocktype_list[block_type] == NULL);
 
     /* Sanity check */
-    g_assert(block->name);
-    g_assert(block->description);
-    g_assert(block->create);
+    g_assert(blocktype->name);
+    g_assert(blocktype->description);
+    g_assert(blocktype->create);
+
+    blocktype->block_type = block_type;
 
-    block_list[block_type] = block;
+    /*
+     * Initialize the set of supported options.
+     * All blocks that support options at all support OPT_COMMENT.
+     */
+    blocktype->options = g_array_sized_new(FALSE, TRUE, sizeof (wtap_opttype_t), OPT_COMMENT + 1);
+    if (OPT_COMMENT + 1 > blocktype->options->len)
+        g_array_set_size(blocktype->options, OPT_COMMENT + 1);
+    g_array_insert_val(blocktype->options, OPT_COMMENT, opt_comment);
+
+    blocktype_list[block_type] = blocktype;
 }
 
 int wtap_opttype_register_custom_block_type(const char* name, const char* description, wtap_block_create_func create,
-                                                wtap_mand_free_func free_mand, wtap_mand_copy_func copy_mand)
+                                            wtap_mand_free_func free_mand, wtap_mand_copy_func copy_mand)
 {
     int block_type;
 
@@ -100,494 +125,738 @@ int wtap_opttype_register_custom_block_type(const char* name, const char* descri
     g_assert(create);
 
     /* This shouldn't happen, so flag it for fixing */
-    g_assert(num_custom_blocks < MAX_WTAP_OPTION_BLOCK_CUSTOM);
+    g_assert(num_custom_blocks < MAX_WTAP_BLOCK_CUSTOM);
 
-    block_type = WTAP_OPTION_BLOCK_END_OF_LIST+num_custom_blocks;
+    block_type = WTAP_BLOCK_END_OF_LIST+num_custom_blocks;
 
-    custom_block_list[num_custom_blocks].name = name;
-    custom_block_list[num_custom_blocks].description = description;
-    custom_block_list[num_custom_blocks].create = create;
-    custom_block_list[num_custom_blocks].free_mand = free_mand;
-    custom_block_list[num_custom_blocks].copy_mand = copy_mand;
-    block_list[block_type] = &custom_block_list[num_custom_blocks];
+    custom_blocktype_list[num_custom_blocks].name = name;
+    custom_blocktype_list[num_custom_blocks].description = description;
+    custom_blocktype_list[num_custom_blocks].create = create;
+    custom_blocktype_list[num_custom_blocks].free_mand = free_mand;
+    custom_blocktype_list[num_custom_blocks].copy_mand = copy_mand;
+    blocktype_list[block_type] = &custom_blocktype_list[num_custom_blocks];
 
     num_custom_blocks++;
     return block_type;
 }
 
-void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block)
+static void wtap_opttype_option_register(wtap_blocktype_t *blocktype, int opttype, wtap_opttype_t *option)
+{
+    if ((guint)opttype + 1 > blocktype->options->len)
+        g_array_set_size(blocktype->options, opttype + 1);
+    g_array_insert_val(blocktype->options, opttype, *option);
+}
+
+void* wtap_block_get_mandatory_data(wtap_block_t block)
 {
     return block->mandatory_data;
 }
 
-static wtap_optblock_value_t* wtap_optionblock_get_option(wtap_optionblock_t block, guint option_id)
+static wtap_optval_t *
+wtap_block_get_option(wtap_block_t block, guint option_id)
 {
     guint i;
-    wtap_optblock_value_t* opttype = NULL;
+    wtap_option_t *opt;
 
-    for (i = 0; i < block->option_values->len; i++)
-    {
-        opttype = g_array_index(block->option_values, wtap_optblock_value_t*, i);
-        if (opttype->info->number == option_id)
-            return opttype;
+    for (i = 0; i < block->options->len; i++) {
+        opt = &g_array_index(block->options, wtap_option_t, i);
+        if (opt->option_id == option_id)
+            return &opt->value;
+    }
+
+    return NULL;
+}
+
+static wtap_optval_t *
+wtap_block_get_nth_option(wtap_block_t block, guint option_id, guint idx)
+{
+    guint i;
+    wtap_option_t *opt;
+    guint opt_idx;
+
+    opt_idx = 0;
+    for (i = 0; i < block->options->len; i++) {
+        opt = &g_array_index(block->options, wtap_option_t, i);
+        if (opt->option_id == option_id) {
+            if (opt_idx == idx)
+                return &opt->value;
+            opt_idx++;
+        }
     }
 
     return NULL;
 }
 
-wtap_optionblock_t wtap_optionblock_create(int block_type)
+wtap_block_t wtap_block_create(wtap_block_type_t block_type)
 {
-    wtap_optionblock_t block;
+    wtap_block_t block;
 
-    if (block_type >= (int)(WTAP_OPTION_BLOCK_END_OF_LIST+num_custom_blocks))
+    if (block_type >= (WTAP_BLOCK_END_OF_LIST+num_custom_blocks))
         return NULL;
 
-    block = g_new(struct wtap_optionblock, 1);
-    block->info = block_list[block_type];
-    block->option_infos = g_array_new(FALSE, FALSE, sizeof(wtap_optblock_internal_t*));
-    block->option_values = g_array_new(FALSE, FALSE, sizeof(wtap_optblock_value_t*));
+    block = g_new(struct wtap_block, 1);
+    block->info = blocktype_list[block_type];
+    block->options = g_array_new(FALSE, FALSE, sizeof(wtap_option_t));
     block->info->create(block);
 
     return block;
 }
 
-static void wtap_optionblock_free_options(wtap_optionblock_t block)
+static void wtap_block_free_options(wtap_block_t block)
 {
     guint i;
-    wtap_optblock_value_t* opttype = NULL;
+    wtap_option_t *opt;
+    wtap_opttype_t *opttype;
+
+    for (i = 0; i < block->options->len; i++) {
+        opt = &g_array_index(block->options, wtap_option_t, i);
+        opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id);
+        switch (opttype->data_type) {
 
-    for (i = 0; i < block->option_values->len; i++) {
-        opttype = g_array_index(block->option_values, wtap_optblock_value_t*, i);
-        switch(opttype->info->type)
-        {
         case WTAP_OPTTYPE_STRING:
-            g_free(opttype->option.stringval);
+            g_free(opt->value.stringval);
             break;
+
         case WTAP_OPTTYPE_CUSTOM:
-            opttype->option.customval.free_func(opttype->option.customval.data);
-            g_free(opttype->option.customval.data);
-            opttype->default_val.customval.free_func(opttype->default_val.customval.data);
-            g_free(opttype->default_val.customval.data);
+            opttype->free_func(opt->value.customval.data);
+            g_free(opt->value.customval.data);
             break;
+
         default:
             break;
         }
-        g_free(opttype);
     }
 }
 
-void wtap_optionblock_free(wtap_optionblock_t block)
+void wtap_block_free(wtap_block_t block)
 {
-    unsigned i;
     if (block != NULL)
     {
         if (block->info->free_mand != NULL)
             block->info->free_mand(block);
 
         g_free(block->mandatory_data);
-        wtap_optionblock_free_options(block);
-        for (i = 0; i < block->option_infos->len; i++)
-            g_free(g_array_index(block->option_infos, wtap_optblock_internal_t*, i));
-        if (block->option_infos != NULL)
-            g_array_free(block->option_infos, TRUE);
-        if (block->option_values != NULL)
-            g_array_free(block->option_values, TRUE);
+        wtap_block_free_options(block);
+        if (block->options != NULL)
+            g_array_free(block->options, TRUE);
         g_free(block);
     }
 }
 
-void wtap_optionblock_array_free(GArray* block_array)
+void wtap_block_array_free(GArray* block_array)
 {
     guint block;
+
     if (block_array == NULL)
         return;
 
     for (block = 0; block < block_array->len; block++) {
-        wtap_optionblock_free(g_array_index(block_array, wtap_optionblock_t, block));
+        wtap_block_free(g_array_index(block_array, wtap_block_t, block));
     }
     g_array_free(block_array, TRUE);
 }
 
-void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+/*
+ * Make a copy of a block.
+ */
+void
+wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block)
 {
     guint i;
-    wtap_optblock_internal_t *src_internal;
-    wtap_optblock_value_t *dest_value, *src_value;
+    wtap_option_t *src_opt;
+    wtap_opttype_t *opttype;
 
+    /*
+     * Copy the mandatory data.
+     */
     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->option_values->len; i++)
+    for (i = 0; i < src_block->options->len; i++)
     {
-        src_internal = g_array_index(src_block->option_infos, wtap_optblock_internal_t*, i);
-        src_value = g_array_index(src_block->option_values, wtap_optblock_value_t*, i);
-        dest_value = wtap_optionblock_get_option(dest_block, src_internal->number);
-        if (dest_value == NULL)
-        {
-            wtap_optblock_reg_t reg_optblock;
+        src_opt = &g_array_index(src_block->options, wtap_option_t, i);
+        opttype = &g_array_index(src_block->info->options, wtap_opttype_t, src_opt->option_id);
 
-            reg_optblock.name = src_internal->name;
-            reg_optblock.description = src_internal->description;
-            reg_optblock.type = src_internal->type;
-            reg_optblock.option = src_value->option;
-            reg_optblock.default_val = src_value->default_val;
+        switch(opttype->data_type) {
 
-            wtap_optionblock_add_option(dest_block, src_internal->number, &reg_optblock);
-        }
-        else
-        {
-            /* Option exists, replace it */
-            switch(src_internal->type)
-            {
-            case WTAP_OPTTYPE_UINT8:
-                dest_value->option.uint8val = src_value->option.uint8val;
-                break;
-            case WTAP_OPTTYPE_UINT64:
-                dest_value->option.uint64val = src_value->option.uint64val;
-                break;
-            case WTAP_OPTTYPE_STRING:
-                g_free(dest_value->option.stringval);
-                dest_value->option.stringval = g_strdup(src_value->option.stringval);
-                break;
-            case WTAP_OPTTYPE_CUSTOM:
-                dest_value->option.customval.free_func(dest_value->option.customval.data);
-                g_free(dest_value->option.customval.data);
-                dest_value->option.customval.data = g_memdup(src_value->option.customval.data, src_value->option.customval.size);
-                break;
-            }
+        case WTAP_OPTTYPE_UINT8:
+            wtap_block_add_uint8_option(dest_block, src_opt->option_id, src_opt->value.uint8val);
+            break;
+
+        case WTAP_OPTTYPE_UINT64:
+            wtap_block_add_uint64_option(dest_block, src_opt->option_id, src_opt->value.uint64val);
+            break;
+
+        case WTAP_OPTTYPE_IPv4:
+            wtap_block_add_ipv4_option(dest_block, src_opt->option_id, src_opt->value.ipv4val);
+            break;
+
+        case WTAP_OPTTYPE_IPv6:
+            wtap_block_add_ipv6_option(dest_block, src_opt->option_id, &src_opt->value.ipv6val);
+            break;
+
+        case WTAP_OPTTYPE_STRING:
+            wtap_block_add_string_option(dest_block, src_opt->option_id, src_opt->value.stringval, strlen(src_opt->value.stringval));
+            break;
+
+        case WTAP_OPTTYPE_CUSTOM:
+            wtap_block_add_custom_option(dest_block, src_opt->option_id, src_opt->value.customval.data, src_opt->value.customval.size);
+            break;
         }
     }
 }
 
-void wtap_optionblock_foreach_option(wtap_optionblock_t block, wtap_optionblock_foreach_func func, void* user_data)
+void wtap_block_foreach_option(wtap_block_t block, wtap_block_foreach_func func, void* user_data)
 {
     guint i;
-    wtap_optblock_internal_t *internal_data;
-    wtap_optblock_value_t *value;
+    wtap_option_t *opt;
+    wtap_opttype_t *opttype;
 
-    for (i = 0; i < block->option_values->len; i++)
-    {
-        internal_data = g_array_index(block->option_infos, wtap_optblock_internal_t*, i);
-        value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
-        func(block, internal_data->number, value->info->type, &value->option, user_data);
+    for (i = 0; i < block->options->len; i++) {
+        opt = &g_array_index(block->options, wtap_option_t, i);
+        opttype = &g_array_index(block->info->options, wtap_opttype_t, opt->option_id);
+        func(block, opt->option_id, opttype->data_type, &opt->value, user_data);
     }
 }
 
-wtap_opttype_return_val wtap_optionblock_add_option(wtap_optionblock_t block, guint option_id, wtap_optblock_reg_t* option)
+wtap_opttype_return_val
+wtap_block_num_options_of_type(wtap_block_t block, guint option_id, guint *countp)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
-    wtap_optblock_internal_t *opt_internal;
+    guint n_options;
+    guint i;
+    wtap_option_t *opt;
+    wtap_opttype_t *opttype;
+
+    if (option_id >= block->info->options->len) {
+        /* There's no option for this block with that option ID */
+        return WTAP_OPTTYPE_NO_SUCH_OPTION;
+    }
 
-    /* Option already exists */
-    if (opt_value != NULL)
-        return WTAP_OPTTYPE_ALREADY_EXISTS;
+    opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
+
+    /*
+     * Can there be more than one instance of this option?
+     */
+    if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
+        /*
+         * No; this is only for use with options with multiple
+         * instances.
+         */
+        return WTAP_OPTTYPE_NUMBER_MISMATCH;
+    }
+
+    n_options = 0;
+    for (i = 0; i < block->options->len; i++) {
+        opt = g_array_index(block->options, wtap_option_t*, i);
+        if (opt->option_id == option_id)
+            n_options++;
+    }
+    *countp = n_options;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    opt_value = g_new0(wtap_optblock_value_t, 1);
-    opt_internal = g_new(wtap_optblock_internal_t, 1);
+static wtap_opttype_return_val
+wtap_block_add_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_option_t **optp)
+{
+    wtap_option_t *opt;
+    wtap_opttype_t *opttype;
+    guint i;
 
-    opt_internal->name = option->name;
-    opt_internal->description = option->description;
-    opt_internal->number = option_id;
-    opt_internal->type = option->type;
+    if (option_id >= block->info->options->len) {
+        /* There's no option for this block with that option ID */
+        return WTAP_OPTTYPE_NO_SUCH_OPTION;
+    }
+    opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
 
-    opt_value->info = opt_internal;
+    /*
+     * Is this an option of the specified data type?
+     */
+    if (opttype->data_type != type) {
+        /*
+         * No.
+         */
+        return WTAP_OPTTYPE_TYPE_MISMATCH;
+    }
 
-    switch(option->type)
-    {
-    case WTAP_OPTTYPE_UINT8:
-        opt_value->option.uint8val = option->option.uint8val;
-        opt_value->default_val.uint8val = option->default_val.uint8val;
-        break;
-    case WTAP_OPTTYPE_UINT64:
-        opt_value->option.uint64val = option->option.uint64val;
-        opt_value->default_val.uint64val = option->default_val.uint64val;
-        break;
-    case WTAP_OPTTYPE_STRING:
-        opt_value->option.stringval = g_strdup(option->option.stringval);
-        opt_value->default_val.stringval = option->default_val.stringval;
-        break;
-    case WTAP_OPTTYPE_CUSTOM:
-        opt_value->option.customval.size = option->option.customval.size;
-        opt_value->option.customval.data = g_memdup(option->option.customval.data, option->option.customval.size);
-        opt_value->option.customval.free_func = option->option.customval.free_func;
-        opt_value->default_val.customval.size = option->default_val.customval.size;
-        opt_value->default_val.customval.data = g_memdup(option->default_val.customval.data, option->default_val.customval.size);
-        opt_value->default_val.customval.free_func = option->default_val.customval.free_func;
-        break;
+    /*
+     * Can there be more than one instance of this option?
+     */
+    if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
+        /*
+         * No. Is there already an instance of this option?
+         */
+        if (wtap_block_get_option(block, option_id) != NULL) {
+            /*
+             * Yes. Fail.
+             */
+            return WTAP_OPTTYPE_ALREADY_EXISTS;
+        }
     }
 
-    g_array_append_val(block->option_infos, opt_internal);
-    g_array_append_val(block->option_values, opt_value);
+    /*
+     * Add an instance.
+     */
+    i = block->options->len;
+    g_array_set_size(block->options, i + 1);
+    opt = &g_array_index(block->options, wtap_option_t, i);
+    opt->option_id = option_id;
+    *optp = opt;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* value, gsize value_length)
+static wtap_opttype_return_val
+wtap_block_get_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, wtap_optval_t **optvalp)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_t *opttype;
+    wtap_optval_t *optval;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    if (option_id >= block->info->options->len) {
+        /* There's no option for this block with that option ID */
+        return WTAP_OPTTYPE_NO_SUCH_OPTION;
+    }
+
+    opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
 
-    if (opt_value->info->type != WTAP_OPTTYPE_STRING)
+    /*
+     * Is this an option of the specified data type?
+     */
+    if (opttype->data_type != type) {
+        /*
+         * No.
+         */
         return WTAP_OPTTYPE_TYPE_MISMATCH;
+    }
+
+    /*
+     * Can there be more than one instance of this option?
+     */
+    if (opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED) {
+        /*
+         * Yes.  You can't ask for "the" value.
+         */
+        return WTAP_OPTTYPE_NUMBER_MISMATCH;
+    }
 
-    g_free(opt_value->option.stringval);
-    opt_value->option.stringval = g_strndup(value, value_length);
+    optval = wtap_block_get_option(block, option_id);
+    if (optval == NULL) {
+        /* Didn't find the option */
+        return WTAP_OPTTYPE_NOT_FOUND;
+    }
+
+    *optvalp = optval;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_set_option_string_format(wtap_optionblock_t block, guint option_id, const char *format, ...)
+static wtap_opttype_return_val
+wtap_block_get_nth_option_common(wtap_block_t block, guint option_id, wtap_opttype_e type, guint idx, wtap_optval_t **optvalp)
 {
-    va_list va;
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_t *opttype;
+    wtap_optval_t *optval;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    if (option_id >= block->info->options->len) {
+        /* There's no option for this block with that option ID */
+        return WTAP_OPTTYPE_NO_SUCH_OPTION;
+    }
+
+    opttype = &g_array_index(block->info->options, wtap_opttype_t, option_id);
 
-    if (opt_value->info->type != WTAP_OPTTYPE_STRING)
+    /*
+     * Is this an option of the specified data type?
+     */
+    if (opttype->data_type != type) {
+        /*
+         * No.
+         */
         return WTAP_OPTTYPE_TYPE_MISMATCH;
+    }
 
-    g_free(opt_value->option.stringval);
-    va_start(va, format);
-    opt_value->option.stringval = g_strdup_vprintf(format, va);
-    va_end(va);
+    /*
+     * Can there be more than one instance of this option?
+     */
+    if (!(opttype->flags & WTAP_OPTTYPE_FLAG_MULTIPLE_ALLOWED)) {
+        /*
+         * No.
+         */
+        return WTAP_OPTTYPE_NUMBER_MISMATCH;
+    }
+
+    optval = wtap_block_get_nth_option(block, option_id, idx);
+    if (optval == NULL) {
+        /* Didn't find the option */
+        return WTAP_OPTTYPE_NOT_FOUND;
+    }
+
+    *optvalp = optval;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** value)
+wtap_opttype_return_val
+wtap_block_add_uint8_option(wtap_block_t block, guint option_id, guint8 value)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.uint8val = value;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_STRING)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_set_uint8_option_value(wtap_block_t block, guint option_id, guint8 value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    *value = opt_value->option.stringval;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    optval->uint8val = value;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_get_string_options(wtap_optionblock_t block, guint option_id, GArray **value)
+wtap_opttype_return_val
+wtap_block_get_uint8_option_value(wtap_block_t block, guint option_id, guint8* value)
 {
-    guint n_options;
-    guint i;
-    wtap_optblock_value_t* opt_value;
-    GArray *opt_values;
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    n_options = 0;
-    for (i = 0; i < block->option_values->len; i++)
-    {
-        opt_value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
-        if (opt_value->info->number == option_id) {
-            if (opt_value->info->type != WTAP_OPTTYPE_STRING)
-                return WTAP_OPTTYPE_TYPE_MISMATCH;
-            n_options++;
-        }
-    }
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT8, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->uint8val;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    opt_values = g_array_sized_new(FALSE, FALSE, sizeof (char *), n_options);
-    for (i = 0; i < block->option_values->len; i++)
-    {
-        opt_value = g_array_index(block->option_values, wtap_optblock_value_t*, i);
-        if (opt_value->info->number == option_id)
-            g_array_append_val(opt_values, opt_value->option.stringval);
-    }
+wtap_opttype_return_val
+wtap_block_add_uint64_option(wtap_block_t block, guint option_id, guint64 value)
+{
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    *value = opt_values;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.uint64val = value;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 value)
+wtap_opttype_return_val
+wtap_block_set_uint64_option_value(wtap_block_t block, guint option_id, guint64 value)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    optval->uint64val = value;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_UINT64)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_get_uint64_option_value(wtap_block_t block, guint option_id, guint64 *value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    opt_value->option.uint64val = value;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_UINT64, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->uint64val;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* value)
+wtap_opttype_return_val
+wtap_block_add_ipv4_option(wtap_block_t block, guint option_id, guint32 value)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.ipv4val = value;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_UINT64)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_set_ipv4_option_value(wtap_block_t block, guint option_id, guint32 value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    *value = opt_value->option.uint64val;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    optval->ipv4val = value;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
+wtap_opttype_return_val
+wtap_block_get_ipv4_option_value(wtap_block_t block, guint option_id, guint32* value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
+
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->ipv4val;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-wtap_opttype_return_val wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 value)
+wtap_opttype_return_val
+wtap_block_add_ipv6_option(wtap_block_t block, guint option_id, struct e_in6_addr *value)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.ipv6val = *value;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_UINT8)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_set_ipv6_option_value(wtap_block_t block, guint option_id, struct e_in6_addr *value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    opt_value->option.uint8val = value;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv6, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    optval->ipv6val = *value;
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* value)
+wtap_opttype_return_val
+wtap_block_get_ipv6_option_value(wtap_block_t block, guint option_id, struct e_in6_addr* value)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_IPv4, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->ipv6val;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_UINT8)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_add_string_option(wtap_block_t block, guint option_id, const char *value, gsize value_length)
+{
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    *value = opt_value->option.uint8val;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.stringval = g_strndup(value, value_length);
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* value)
+static wtap_opttype_return_val
+wtap_block_add_string_option_vformat(wtap_block_t block, guint option_id, const char *format, va_list va)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
-    void* prev_value;
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.stringval = g_strdup_vprintf(format, va);
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_CUSTOM)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_add_string_option_format(wtap_block_t block, guint option_id, const char *format, ...)
+{
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
+    va_list va;
 
-    prev_value = opt_value->option.customval.data;
-    opt_value->option.customval.data = g_memdup(value, opt_value->option.customval.size);
-    /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
-    g_free(prev_value);
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_STRING, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    va_start(va, format);
+    opt->value.stringval = g_strdup_vprintf(format, va);
+    va_end(va);
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-wtap_opttype_return_val wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** value)
+wtap_opttype_return_val
+wtap_block_set_string_option_value(wtap_block_t block, guint option_id, const char *value, size_t value_length)
 {
-    wtap_optblock_value_t* opt_value = wtap_optionblock_get_option(block, option_id);
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
+
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS) {
+        if (ret == WTAP_OPTTYPE_NOT_FOUND) {
+            /*
+             * There's no instance to set, so just try to create a new one
+             * with the value.
+             */
+            return wtap_block_add_string_option(block, option_id, value, value_length);
+        }
+        /* Otherwise fail. */
+        return ret;
+    }
+    g_free(optval->stringval);
+    optval->stringval = g_strndup(value, value_length);
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    /* Didn't find the option */
-    if (opt_value == NULL)
-        return WTAP_OPTTYPE_NOT_FOUND;
+wtap_opttype_return_val
+wtap_block_set_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, const char *value, size_t value_length)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
+
+    ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    g_free(optval->stringval);
+    optval->stringval = g_strndup(value, value_length);
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    if (opt_value->info->type != WTAP_OPTTYPE_CUSTOM)
-        return WTAP_OPTTYPE_TYPE_MISMATCH;
+wtap_opttype_return_val
+wtap_block_set_string_option_value_format(wtap_block_t block, guint option_id, const char *format, ...)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
+    va_list va;
 
-    *value = opt_value->option.customval.data;
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS) {
+        if (ret == WTAP_OPTTYPE_NOT_FOUND) {
+            /*
+             * There's no instance to set, so just try to create a new one
+             * with the formatted string.
+             */
+            va_start(va, format);
+            ret = wtap_block_add_string_option_vformat(block, option_id, format, va);
+            va_end(va);
+            return ret;
+        }
+        /* Otherwise fail. */
+        return ret;
+    }
+    g_free(optval->stringval);
+    va_start(va, format);
+    optval->stringval = g_strdup_vprintf(format, va);
+    va_end(va);
     return WTAP_OPTTYPE_SUCCESS;
 }
 
-static void shb_create(wtap_optionblock_t block)
+wtap_opttype_return_val
+wtap_block_get_string_option_value(wtap_block_t block, guint option_id, char** value)
 {
-    static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t hardware_option = {"hardware", "SBH Hardware", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t os_option = {"os", "SBH Operating System", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t user_appl_option = {"user_appl", "SBH User Application", WTAP_OPTTYPE_STRING, {0}, {0}};
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1);
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_STRING, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->stringval;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    /* Set proper values for the union */
-    comment_option.option.stringval = NULL;
-    comment_option.default_val.stringval = NULL;
-    hardware_option.option.stringval = NULL;
-    hardware_option.default_val.stringval = NULL;
-    os_option.option.stringval = NULL;
-    os_option.default_val.stringval = NULL;
-    user_appl_option.option.stringval = NULL;
-    user_appl_option.default_val.stringval = NULL;
+wtap_opttype_return_val
+wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, char** value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    section_mand->section_length = -1;
+    ret = wtap_block_get_nth_option_common(block, option_id, WTAP_OPTTYPE_STRING, idx, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->stringval;
+    return WTAP_OPTTYPE_SUCCESS;
+}
 
-    block->mandatory_data = section_mand;
+wtap_opttype_return_val
+wtap_block_add_custom_option(wtap_block_t block, guint option_id, void *value, size_t value_size)
+{
+    wtap_opttype_return_val ret;
+    wtap_option_t *opt;
+
+    ret = wtap_block_add_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &opt);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    opt->value.customval.size = (guint)value_size;
+    opt->value.customval.data = g_memdup(value, (guint)value_size);
+    return WTAP_OPTTYPE_SUCCESS;
+}
+
+wtap_opttype_return_val
+wtap_block_get_custom_option_value(wtap_block_t block, guint option_id, void** value)
+{
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
 
-    wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
-    wtap_optionblock_add_option(block, OPT_SHB_HARDWARE, &hardware_option);
-    wtap_optionblock_add_option(block, OPT_SHB_OS, &os_option);
-    wtap_optionblock_add_option(block, OPT_SHB_USERAPPL, &user_appl_option);
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    *value = optval->customval.data;
+    return WTAP_OPTTYPE_SUCCESS;
 }
 
-static void shb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+wtap_opttype_return_val
+wtap_block_set_custom_option_value(wtap_block_t block, guint option_id, void *value)
 {
-    memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
+    wtap_opttype_return_val ret;
+    wtap_optval_t *optval;
+    void *prev_value;
+
+    ret = wtap_block_get_option_common(block, option_id, WTAP_OPTTYPE_CUSTOM, &optval);
+    if (ret != WTAP_OPTTYPE_SUCCESS)
+        return ret;
+    prev_value = optval->customval.data;
+    /*
+     * XXX - a custom value can be a structure that points to other data,
+     * but we're doing a shallow copy here.
+     */
+    optval->customval.data = g_memdup(value, optval->customval.size);
+    /* Free after memory is duplicated in case structure was manipulated with a "get then set" */
+    g_free(prev_value);
+
+    return WTAP_OPTTYPE_SUCCESS;
 }
 
-static void nrb_create(wtap_optionblock_t block)
+static void shb_create(wtap_block_t block)
 {
-    static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
+    wtapng_mandatory_section_t* section_mand = g_new(wtapng_mandatory_section_t, 1);
 
-    /* Set proper values for the union */
-    comment_option.option.stringval = NULL;
-    comment_option.default_val.stringval = NULL;
+    section_mand->section_length = -1;
 
-    block->mandatory_data = NULL;
+    block->mandatory_data = section_mand;
+}
 
-    wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
+static void shb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
+{
+    memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_mandatory_section_t));
 }
 
-static void isb_create(wtap_optionblock_t block)
+static void nrb_create(wtap_block_t block)
 {
-    static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t starttime_option = {"start_time", "Start Time", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t endtime_option = {"end_time", "End Time", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t rcv_pkt_option = {"recv", "Receive Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t drop_pkt_option = {"drop", "Dropped Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t filteraccept_option = {"filter_accept", "Filter Accept", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t os_drop_option = {"os_drop", "OS Dropped Packets", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t user_deliv_option = {"user_deliv", "User Delivery", WTAP_OPTTYPE_UINT64, {0}, {0}};
+    block->mandatory_data = NULL;
+}
 
+static void isb_create(wtap_block_t block)
+{
     block->mandatory_data = g_new0(wtapng_if_stats_mandatory_t, 1);
+}
 
-    /* Set proper values for the union */
-    comment_option.option.stringval = NULL;
-    comment_option.default_val.stringval = NULL;
-    starttime_option.option.uint64val = 0;
-    starttime_option.default_val.uint64val = 0;
-    endtime_option.option.uint64val = 0;
-    endtime_option.default_val.uint64val = 0;
-    rcv_pkt_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    rcv_pkt_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    drop_pkt_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    drop_pkt_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    filteraccept_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    filteraccept_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    os_drop_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    os_drop_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    user_deliv_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    user_deliv_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-
-    wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
-    wtap_optionblock_add_option(block, OPT_ISB_STARTTIME, &starttime_option);
-    wtap_optionblock_add_option(block, OPT_ISB_ENDTIME, &endtime_option);
-    wtap_optionblock_add_option(block, OPT_ISB_IFRECV, &rcv_pkt_option);
-    wtap_optionblock_add_option(block, OPT_ISB_IFDROP, &drop_pkt_option);
-    wtap_optionblock_add_option(block, OPT_ISB_FILTERACCEPT, &filteraccept_option);
-    wtap_optionblock_add_option(block, OPT_ISB_OSDROP, &os_drop_option);
-    wtap_optionblock_add_option(block, OPT_ISB_USRDELIV, &user_deliv_option);
-}
-
-static void isb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_block)
+static void isb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
 {
     memcpy(dest_block->mandatory_data, src_block->mandatory_data, sizeof(wtapng_if_stats_mandatory_t));
 }
@@ -599,72 +868,30 @@ static void idb_filter_free(void* data)
     g_free(filter->if_filter_bpf_bytes);
 }
 
-static void idb_create(wtap_optionblock_t block)
+static void idb_create(wtap_block_t block)
 {
-    static wtap_optblock_reg_t comment_option = {"opt_comment", "Optional comment", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t name_option = {"name", "Device name", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t description_option = {"description", "Device description", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t speed_option = {"speed", "Interface speed (in bps)", WTAP_OPTTYPE_UINT64, {0}, {0}};
-    static wtap_optblock_reg_t tsresol_option = {"ts_resolution", "Resolution of timestamps", WTAP_OPTTYPE_UINT8, {0}, {0}};
-    static wtap_optblock_reg_t filter_option = {"filter", "Filter string", WTAP_OPTTYPE_CUSTOM, {0}, {0}};
-    static wtap_optblock_reg_t os_option = {"os", "Operating System", WTAP_OPTTYPE_STRING, {0}, {0}};
-    static wtap_optblock_reg_t fcslen_option = {"fcslen", "FCS Length", WTAP_OPTTYPE_UINT8, {0}, {0}};
-
-    static wtapng_if_descr_filter_t default_filter;
-
     block->mandatory_data = g_new0(wtapng_if_descr_mandatory_t, 1);
+}
 
-    /* Set proper values for the union */
-    comment_option.option.stringval = NULL;
-    comment_option.default_val.stringval = NULL;
-    name_option.option.stringval = NULL;
-    name_option.default_val.stringval = NULL;
-    description_option.option.stringval = NULL;
-    description_option.default_val.stringval = NULL;
-    speed_option.option.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    speed_option.default_val.uint64val = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
-    tsresol_option.option.uint8val = 6;
-    tsresol_option.default_val.uint8val = 6;
-    filter_option.option.customval.size = sizeof(wtapng_if_descr_filter_t);
-    filter_option.option.customval.data = &default_filter;
-    filter_option.option.customval.free_func = idb_filter_free;
-    filter_option.default_val.customval.size = sizeof(wtapng_if_descr_filter_t);
-    filter_option.default_val.customval.data = &default_filter;
-    filter_option.default_val.customval.free_func = idb_filter_free;
-    os_option.option.stringval = NULL;
-    os_option.default_val.stringval = NULL;
-    fcslen_option.option.uint8val = -1;
-    fcslen_option.default_val.uint8val = -1;
-
-    wtap_optionblock_add_option(block, OPT_COMMENT, &comment_option);
-    wtap_optionblock_add_option(block, OPT_IDB_NAME, &name_option);
-    wtap_optionblock_add_option(block, OPT_IDB_DESCR, &description_option);
-    wtap_optionblock_add_option(block, OPT_IDB_SPEED, &speed_option);
-    wtap_optionblock_add_option(block, OPT_IDB_TSRESOL, &tsresol_option);
-    wtap_optionblock_add_option(block, OPT_IDB_FILTER, &filter_option);
-    wtap_optionblock_add_option(block, OPT_IDB_OS, &os_option);
-    wtap_optionblock_add_option(block, OPT_IDB_FCSLEN, &fcslen_option);
-}
-
-static void idb_free_mand(wtap_optionblock_t block)
+static void idb_free_mand(wtap_block_t block)
 {
     guint j;
-    wtap_optionblock_t if_stats;
+    wtap_block_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);
+        if_stats = g_array_index(mand->interface_statistics, wtap_block_t, j);
+        wtap_block_free(if_stats);
     }
 
     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)
+static void idb_copy_mand(wtap_block_t dest_block, wtap_block_t src_block)
 {
     guint j;
-    wtap_optionblock_t src_if_stats, dest_if_stats;
+    wtap_block_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;
 
@@ -675,12 +902,12 @@ static void idb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_
     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_new(FALSE, FALSE, sizeof(wtap_block_t));
         for (j = 0; j < src_mand->num_stat_entries; j++)
         {
-            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);
+            src_if_stats = g_array_index(src_mand->interface_statistics, wtap_block_t, j);
+            dest_if_stats = wtap_block_create(WTAP_BLOCK_IF_STATS);
+            wtap_block_copy(dest_if_stats, src_if_stats);
             dest_mand->interface_statistics = g_array_append_val(dest_mand->interface_statistics, dest_if_stats);
         }
     }
@@ -688,45 +915,228 @@ static void idb_copy_mand(wtap_optionblock_t dest_block, wtap_optionblock_t src_
 
 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_blocktype_t shb_block = {
+        WTAP_BLOCK_NG_SECTION,  /* block_type */
+        "SHB",                  /* name */
+        "Section Header Block", /* description */
+        shb_create,             /* create */
+        NULL,                   /* free_mand */
+        shb_copy_mand,          /* copy_mand */
+        NULL                    /* options */
+    };
+    static wtap_opttype_t shb_hardware = {
+        "hardware",
+        "SHB Hardware",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t shb_os = {
+        "os",
+        "SHB Operating System",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t shb_userappl = {
+        "user_appl",
+        "SHB User Application",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
     };
 
-    static wtap_opt_register_t nrb_block = {
-        "NRB",              /* name */
-        "Name Resolution Block",  /* description */
-        nrb_create,         /* create */
-        NULL,               /* free_mand */
-        NULL,               /* copy_mand */
+    static wtap_blocktype_t idb_block = {
+        WTAP_BLOCK_IF_DESCR,           /* block_type */
+        "IDB",                         /* name */
+        "Interface Description Block", /* description */
+        idb_create,                    /* create */
+        idb_free_mand,                 /* free_mand */
+        idb_copy_mand,                 /* copy_mand */
+        NULL                           /* options */
+    };
+    static wtap_opttype_t if_name = {
+        "name",
+        "IDB Name",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t if_description = {
+        "description",
+        "IDB Description",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t if_speed = {
+        "speed",
+        "IDB Speed",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t if_tsresol = {
+        "tsresol",
+        "IDB Time Stamp Resolution",
+        WTAP_OPTTYPE_UINT8, /* XXX - signed? */
+        0,
+        NULL
+    };
+    static wtap_opttype_t if_filter = {
+        "filter",
+        "IDB Filter",
+        WTAP_OPTTYPE_CUSTOM,
+        0,
+        idb_filter_free
+    };
+    static wtap_opttype_t if_os = {
+        "os",
+        "IDB Operating System",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t if_fcslen = {
+        "fcslen",
+        "IDB FCS Length",
+        WTAP_OPTTYPE_UINT8,
+        0,
+        NULL
     };
 
-    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_blocktype_t nrb_block = {
+        WTAP_BLOCK_NG_NRB,       /* block_type */
+        "NRB",                   /* name */
+        "Name Resolution Block", /* description */
+        nrb_create,              /* create */
+        NULL,                    /* free_mand */
+        NULL,                    /* copy_mand */
+        NULL                     /* options */
+    };
+    static wtap_opttype_t ns_dnsname = {
+        "dnsname",
+        "NRB DNS server name",
+        WTAP_OPTTYPE_STRING,
+        0,
+        NULL
+    };
+    static wtap_opttype_t ns_dnsIP4addr = {
+        "dnsIP4addr",
+        "NRB DNS server IPv4 address",
+        WTAP_OPTTYPE_IPv4,
+        0,
+        NULL
+    };
+    static wtap_opttype_t ns_dnsIP6addr = {
+        "dnsIP6addr",
+        "NRB DNS server IPv6 address",
+        WTAP_OPTTYPE_IPv6,
+        0,
+        NULL
     };
 
-    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 */
+    static wtap_blocktype_t isb_block = {
+        WTAP_BLOCK_IF_STATS,          /* block_type */
+        "ISB",                        /* name */
+        "Interface Statistics Block", /* description */
+        isb_create,                   /* create */
+        NULL,                         /* free_mand */
+        isb_copy_mand,                /* copy_mand */
+        NULL                          /* options */
+    };
+    static wtap_opttype_t isb_starttime = {
+        "starttime",
+        "ISB Start Time",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_endtime = {
+        "endtime",
+        "ISB End Time",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_ifrecv = {
+        "ifrecv",
+        "ISB Received Packets",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_ifdrop = {
+        "ifdrop",
+        "ISB Dropped Packets",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_filteraccept = {
+        "filteraccept",
+        "ISB Packets Accepted By Filter",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_osdrop = {
+        "osdrop",
+        "ISB Packets Dropped By The OS",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
+    };
+    static wtap_opttype_t isb_usrdeliv = {
+        "usrdeliv",
+        "ISB Packets Delivered To The User",
+        WTAP_OPTTYPE_UINT64,
+        0,
+        NULL
     };
 
     /* Initialize the custom block array.  This is for future proofing
        "outside registered" block types (for NULL checking) */
-    memset(block_list, 0, MAX_WTAP_OPTION_BLOCK_TYPE_VALUE*sizeof(wtap_opt_register_t*));
+    memset(blocktype_list, 0, MAX_WTAP_BLOCK_TYPE_VALUE*sizeof(wtap_blocktype_t*));
     num_custom_blocks = 0;
 
-    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 );
+    /*
+     * Registser the SHB and the options that can appear in it.
+     */
+    wtap_opttype_block_register(WTAP_BLOCK_NG_SECTION, &shb_block);
+    wtap_opttype_option_register(&shb_block, OPT_SHB_HARDWARE, &shb_hardware);
+    wtap_opttype_option_register(&shb_block, OPT_SHB_OS, &shb_os);
+    wtap_opttype_option_register(&shb_block, OPT_SHB_USERAPPL, &shb_userappl);
+
+    /*
+     * Register the IDB and the options that can appear in it.
+     */
+    wtap_opttype_block_register(WTAP_BLOCK_IF_DESCR, &idb_block);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_NAME, &if_name);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_DESCR, &if_description);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_SPEED, &if_speed);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_TSRESOL, &if_tsresol);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_FILTER, &if_filter);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_OS, &if_os);
+    wtap_opttype_option_register(&idb_block, OPT_IDB_FCSLEN, &if_fcslen);
+
+    /*
+     * Register the NRB and the options that can appear in it.
+     */
+    wtap_opttype_block_register(WTAP_BLOCK_NG_NRB, &nrb_block);
+    wtap_opttype_option_register(&nrb_block, OPT_NS_DNSNAME, &ns_dnsname);
+    wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP4ADDR, &ns_dnsIP4addr);
+    wtap_opttype_option_register(&nrb_block, OPT_NS_DNSIP6ADDR, &ns_dnsIP6addr);
+
+    /*
+     * Register the ISB and the options that can appear in it.
+     */
+    wtap_opttype_block_register(WTAP_BLOCK_IF_STATS, &isb_block);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_STARTTIME, &isb_starttime);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_ENDTIME, &isb_endtime);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_IFRECV, &isb_ifrecv);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_IFDROP, &isb_ifdrop);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_FILTERACCEPT, &isb_filteraccept);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_OSDROP, &isb_osdrop);
+    wtap_opttype_option_register(&isb_block, OPT_ISB_USRDELIV, &isb_usrdeliv);
 }
index 120e167c640755f362f865931a0dd8c685c6dfa3..688de52aa512e26213b5c8fe3379c1d8064bd277 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "ws_symbol_export.h"
 
+#include <wsutil/inet_ipv6.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -31,7 +33,7 @@ extern "C" {
 /*
  * We use the pcapng option codes for option type values.
  */
-#define OPT_EOFOPT           0x0000 /**< Appears in pcapng files, but not in option blocks. */
+#define OPT_EOFOPT           0x0000 /**< Appears in pcapng files, but not in blocks. */
 #define OPT_COMMENT          0x0001 /**< NULL if not available */
 
 /* Section Header block (SHB) */
@@ -109,6 +111,10 @@ extern "C" {
                                      *                     second offsets be useful for highly syncronized capture systems?
                                      */
 
+#define OPT_NS_DNSNAME       2
+#define OPT_NS_DNSIP4ADDR    3
+#define OPT_NS_DNSIP6ADDR    4
+
 #define OPT_ISB_STARTTIME    0x0002
 #define OPT_ISB_ENDTIME      0x0003
 #define OPT_ISB_IFRECV       0x0004
@@ -117,64 +123,73 @@ extern "C" {
 #define OPT_ISB_OSDROP       0x0007
 #define OPT_ISB_USRDELIV     0x0008
 
-struct wtap_optionblock;
-typedef struct wtap_optionblock *wtap_optionblock_t;
+struct wtap_block;
+typedef struct wtap_block *wtap_block_t;
 
-/* Currently supported option blocks */
+/*
+ * Currently supported blocks; these are not the pcapng block type values
+ * for them, they're identifiers used internally.
+ */
 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_END_OF_LIST
-} wtap_optionblock_type_t;
+    WTAP_BLOCK_NG_SECTION = 0,
+    WTAP_BLOCK_IF_DESCR,
+    WTAP_BLOCK_NG_NRB,
+    WTAP_BLOCK_IF_STATS,
+    WTAP_BLOCK_END_OF_LIST
+} wtap_block_type_t;
 
 /* Currently supported option types */
 typedef enum {
     WTAP_OPTTYPE_UINT8,
     WTAP_OPTTYPE_UINT64,
     WTAP_OPTTYPE_STRING,
+    WTAP_OPTTYPE_IPv4,
+    WTAP_OPTTYPE_IPv6,
     WTAP_OPTTYPE_CUSTOM
 } wtap_opttype_e;
 
 typedef enum {
     WTAP_OPTTYPE_SUCCESS = 0,
-    WTAP_OPTTYPE_NOT_FOUND = -1,
-    WTAP_OPTTYPE_TYPE_MISMATCH = -2,
-    WTAP_OPTTYPE_ALREADY_EXISTS = -3
+    WTAP_OPTTYPE_NO_SUCH_OPTION = -1,
+    WTAP_OPTTYPE_NOT_FOUND = -2,
+    WTAP_OPTTYPE_TYPE_MISMATCH = -3,
+    WTAP_OPTTYPE_NUMBER_MISMATCH = -4,
+    WTAP_OPTTYPE_ALREADY_EXISTS = -5,
 } wtap_opttype_return_val;
 
-typedef void (*wtap_opttype_free_custom_func)(void* data);
-
 struct wtap_opttype_custom
 {
     void* data;
     guint size;
-    wtap_opttype_free_custom_func free_func;
 };
 
+/*
+ * Structure describing a value of an option.
+ */
 typedef union {
     guint8 uint8val;
     guint64 uint64val;
+    guint32 ipv4val;    /* network byte order */
+    struct e_in6_addr ipv6val;
     char *stringval;
     struct wtap_opttype_custom customval;
-} wtap_option_type;
+} wtap_optval_t;
 
-struct wtap_dumper;
+/*
+ * Structure describing an option in a block.
+ */
+typedef struct {
+    guint option_id;     /**< option code for the option */
+    wtap_optval_t value; /**< value */
+} wtap_option_t;
 
-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);
+struct wtap_dumper;
 
-typedef struct wtap_optblock_reg {
-    const char *name;                /**< name of option */
-    const char *description;         /**< human-readable description of option */
-    wtap_opttype_e type;             /**< type of that option */
-    wtap_option_type option;         /**< pointer to variable storing the value */
-    wtap_option_type default_val;    /**< the default value of the option */
-} wtap_optblock_reg_t;
+typedef void (*wtap_block_create_func)(wtap_block_t block);
+typedef void (*wtap_mand_free_func)(wtap_block_t block);
+typedef void (*wtap_mand_copy_func)(wtap_block_t dest_block, wtap_block_t src_block);
 
-/** Initialize option block types.
+/** Initialize block types.
  *
  * This is currently just a placeholder as nothing needs to be
  * initialized yet.  Should handle "registration" when code is
@@ -182,76 +197,96 @@ typedef struct wtap_optblock_reg {
  */
 WS_DLL_PUBLIC void wtap_opttypes_initialize(void);
 
-/** Create an option block by type
+/** Create a block by type
  *
- * Return a newly allocated option block with default options provided
+ * Return a newly allocated block with default options provided
  *
- * @param[in] block_type Option block type to be created
- * @return Newly allocated option block
+ * @param[in] block_type Block type to be created
+ * @return Newly allocated block
  */
-WS_DLL_PUBLIC wtap_optionblock_t wtap_optionblock_create(int block_type);
+WS_DLL_PUBLIC wtap_block_t wtap_block_create(wtap_block_type_t block_type);
 
-/** Free an option block
+/** Free a block
  *
- * Needs to be called to clean up any allocated option block
+ * Needs to be called to clean up any allocated block
  *
  * @param[in] block Block to be freed
  */
-WS_DLL_PUBLIC void wtap_optionblock_free(wtap_optionblock_t block);
+WS_DLL_PUBLIC void wtap_block_free(wtap_block_t block);
 
-/** Free an array of option blocks
+/** Free an array of blocks
  *
- * Needs to be called to clean up option blocks allocated
+ * Needs to be called to clean up blocks allocated
  * through GArray (for multiple blocks of same type)
  * Includes freeing the GArray
  *
  * @param[in] block_array Array of blocks to be freed
  */
-WS_DLL_PUBLIC void wtap_optionblock_array_free(GArray* block_array);
+WS_DLL_PUBLIC void wtap_block_array_free(GArray* block_array);
 
-/** Provide mandatory data of an option block
+/** Provide mandatory data of a block
  *
  * @param[in] block Block from which to retrieve mandatory data
- * @return Option block mandatory data.  Structure varies based on option block type
+ * @return Block mandatory data.  Structure varies based on block type
  */
-WS_DLL_PUBLIC void* wtap_optionblock_get_mandatory_data(wtap_optionblock_t block);
+WS_DLL_PUBLIC void* wtap_block_get_mandatory_data(wtap_block_t block);
 
-/** Add an option to the option block
+/** Add UINT8 option value to a block
  *
- * @param[in] block Block to which to add option
+ * @param[in] block Block to which to add the option
  * @param[in] option_id Identifier value for option
- * @param[in] option structure explaining it
+ * @param[in] value Value of option
  * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_add_option(wtap_optionblock_t block, guint option_id, wtap_optblock_reg_t* option);
+wtap_block_add_uint8_option(wtap_block_t block, guint option_id, guint8 value);
 
-/** Set string option value in an option block
+/** Set UINT8 option value in a block
  *
  * @param[in] block Block in which to set the option value
  * @param[in] option_id Identifier value for option
  * @param[in] value New value of option
- * @param[in] value_length Maximum length of string to copy.
  * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_set_option_string(wtap_optionblock_t block, guint option_id, char* value, gsize value_length);
+wtap_block_set_uint8_option_value(wtap_block_t block, guint option_id, guint8 value);
+
+/** Get UINT8 option value from a block
+ *
+ * @param[in] block Block from which to get the option value
+ * @param[in] option_id Identifier value for option
+ * @param[out] value Returned value of option
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_get_uint8_option_value(wtap_block_t block, guint option_id, guint8* value) G_GNUC_WARN_UNUSED_RESULT;
+
+/** Add UINT64 option value to a block
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] option_id Identifier value for option
+ * @param[in] value Value of option
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_add_uint64_option(wtap_block_t block, guint option_id, guint64 value);
 
-/** Set string option value in an option block to a printf-formatted string
+/** Set UINT64 option value in a block
  *
  * @param[in] block Block in which to set the option value
  * @param[in] option_id Identifier value for option
- * @param[in] format printf-like format string
+ * @param[in] value New value of option
  * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_set_option_string_format(wtap_optionblock_t block, guint option_id, const char *format, ...)
-                                          G_GNUC_PRINTF(3,4);
+wtap_block_set_uint64_option_value(wtap_block_t block, guint option_id, guint64 value);
 
-/** Get string option value from an option block
+/** Get UINT64 option value from a block
  *
  * @param[in] block Block from which to get the option value
  * @param[in] option_id Identifier value for option
@@ -260,20 +295,20 @@ wtap_optionblock_set_option_string_format(wtap_optionblock_t block, guint option
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_get_option_string(wtap_optionblock_t block, guint option_id, char** value);
+wtap_block_get_uint64_option_value(wtap_block_t block, guint option_id, guint64* value) G_GNUC_WARN_UNUSED_RESULT;
 
-/** Get array of string option values from an option block
+/** Add IPv4 address option value to a block
  *
- * @param[in] block Block from which to get option values
+ * @param[in] block Block to which to add the option
  * @param[in] option_id Identifier value for option
- * @param[out] value Returned GArray of option values
+ * @param[in] value Value of option
  * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_get_string_options(wtap_optionblock_t block, guint option_id, GArray **value);
+wtap_block_add_ipv4_option(wtap_block_t block, guint option_id, guint32 value);
 
-/** Set UINT64 option value in an option block
+/** Set IPv4 option value in a block
  *
  * @param[in] block Block in which to set the option value
  * @param[in] option_id Identifier value for option
@@ -282,9 +317,9 @@ wtap_optionblock_get_string_options(wtap_optionblock_t block, guint option_id, G
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, guint64 value);
+wtap_block_set_ipv4_option_value(wtap_block_t block, guint option_id, guint32 value);
 
-/** Get UINT64 option value from an option block
+/** Get IPv4 option value from a block
  *
  * @param[in] block Block from which to get the option value
  * @param[in] option_id Identifier value for option
@@ -293,9 +328,20 @@ wtap_optionblock_set_option_uint64(wtap_optionblock_t block, guint option_id, gu
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, guint64* value);
+wtap_block_get_ipv4_option_value(wtap_block_t block, guint option_id, guint32* value) G_GNUC_WARN_UNUSED_RESULT;
+
+/** Add IPv6 address option value to a block
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] option_id Identifier value for option
+ * @param[in] value Value of option
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_add_ipv6_option(wtap_block_t block, guint option_id, struct e_in6_addr *value);
 
-/** Set UINT8 option value in an option block
+/** Set IPv6 option value in a block
  *
  * @param[in] block Block in which to set the option value
  * @param[in] option_id Identifier value for option
@@ -304,9 +350,9 @@ wtap_optionblock_get_option_uint64(wtap_optionblock_t block, guint option_id, gu
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, guint8 value);
+wtap_block_set_ipv6_option_value(wtap_block_t block, guint option_id, struct e_in6_addr *value);
 
-/** Get UINT8 option value from an option block
+/** Get IPv6 option value from a block
  *
  * @param[in] block Block from which to get the option value
  * @param[in] option_id Identifier value for option
@@ -315,9 +361,105 @@ wtap_optionblock_set_option_uint8(wtap_optionblock_t block, guint option_id, gui
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, guint8* value);
+wtap_block_get_ipv6_option_value(wtap_block_t block, guint option_id, struct e_in6_addr* value) G_GNUC_WARN_UNUSED_RESULT;
+
+/** Add a string option to a block
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] option_id Identifier value for option
+ * @param[in] value Value of option
+ * @param[in] value_length Maximum length of string to copy.
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_add_string_option(wtap_block_t block, guint option_id, const char *value, gsize value_length);
+
+/** Add a string option to a block witha printf-formatted string as its value
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] option_id Identifier value for option
+ * @param[in] format printf-like format string
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_add_string_option_format(wtap_block_t block, guint option_id, const char *format, ...)
+                                    G_GNUC_PRINTF(3,4);
+
+/** Set string option value in a block
+ *
+ * @param[in] block Block in which to set the option value
+ * @param[in] option_id Identifier value for option
+ * @param[in] value New value of option
+ * @param[in] value_length Maximum length of string to copy.
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_set_string_option_value(wtap_block_t block, guint option_id, const char* value, gsize value_length);
+
+/** Set string option value for nth instance of a particular option in a block
+ *
+ * @param[in] block Block in which to set the option value
+ * @param[in] option_id Identifier value for option
+ * @param[in] idx Instance number of option with that ID
+ * @param[in] value New value of option
+ * @param[in] value_length Maximum length of string to copy.
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_set_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, const char* value, gsize value_length);
+
+/** Set string option value in a block to a printf-formatted string
+ *
+ * @param[in] block Block in which to set the option value
+ * @param[in] option_id Identifier value for option
+ * @param[in] format printf-like format string
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_set_string_option_value_format(wtap_block_t block, guint option_id, const char *format, ...)
+                                          G_GNUC_PRINTF(3,4);
+
+/** Get string option value from a block
+ *
+ * @param[in] block Block from which to get the option value
+ * @param[in] option_id Identifier value for option
+ * @param[out] value Returned value of option
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_get_string_option_value(wtap_block_t block, guint option_id, char** value) G_GNUC_WARN_UNUSED_RESULT;
+
+/** Get string option value for nth instance of a particular option in a block
+ *
+ * @param[in] block Block from which to get the option value
+ * @param[in] option_id Identifier value for option
+ * @param[in] idx Instance number of option with that ID
+ * @param[out] value Returned value of option
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_get_nth_string_option_value(wtap_block_t block, guint option_id, guint idx, char** value) G_GNUC_WARN_UNUSED_RESULT;
+
+/** Add a "custom" option value to a block
+ *
+ * @param[in] block Block to which to add the option
+ * @param[in] option_id Identifier value for option
+ * @param[in] value Value of option
+ * @param[in] value_size Size of value
+ * @return wtap_opttype_return_val - WTAP_OPTTYPE_SUCCESS if successful,
+ * error code otherwise
+ */
+WS_DLL_PUBLIC wtap_opttype_return_val
+wtap_block_add_custom_option(wtap_block_t block, guint option_id, void* value, size_t value_size);
 
-/** Set a "custom" option value in an option block
+/** Set a "custom" option value in a block
  *
  * @param[in] block Block in which to set the option value
  * @param[in] option_id Identifier value for option
@@ -326,9 +468,9 @@ wtap_optionblock_get_option_uint8(wtap_optionblock_t block, guint option_id, gui
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, void* value);
+wtap_block_set_custom_option_value(wtap_block_t block, guint option_id, void* value);
 
-/** Get a "custom" option value from an option block
+/** Get a "custom" option value from a block
  *
  * @param[in] block Block from which to get the option value
  * @param[in] option_id Identifier value for option
@@ -337,9 +479,9 @@ wtap_optionblock_set_option_custom(wtap_optionblock_t block, guint option_id, vo
  * error code otherwise
  */
 WS_DLL_PUBLIC wtap_opttype_return_val
-wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, void** value);
+wtap_block_get_custom_option_value(wtap_block_t block, guint option_id, void** value) G_GNUC_WARN_UNUSED_RESULT;
 
-/** Copy an option block to another.
+/** Copy a block to another.
  *
  * Any options that are in the destination but not the source are not removed.
  * Options that are just in source will be added to destination
@@ -347,11 +489,11 @@ wtap_optionblock_get_option_custom(wtap_optionblock_t block, guint option_id, vo
  * @param[in] dest_block Block to be copied to
  * @param[in] src_block Block to be copied from
  */
-WS_DLL_PUBLIC void wtap_optionblock_copy_options(wtap_optionblock_t dest_block, wtap_optionblock_t src_block);
+WS_DLL_PUBLIC void wtap_block_copy(wtap_block_t dest_block, wtap_block_t src_block);
 
 
-typedef void (*wtap_optionblock_foreach_func)(wtap_optionblock_t block, guint option_id, wtap_opttype_e option_type, wtap_option_type* option, void* user_data);
-WS_DLL_PUBLIC void wtap_optionblock_foreach_option(wtap_optionblock_t block, wtap_optionblock_foreach_func func, void* user_data);
+typedef void (*wtap_block_foreach_func)(wtap_block_t block, guint option_id, wtap_opttype_e option_type, wtap_optval_t *option, void *user_data);
+WS_DLL_PUBLIC void wtap_block_foreach_option(wtap_block_t block, wtap_block_foreach_func func, void* user_data);
 
 WS_DLL_PUBLIC int wtap_opttype_register_custom_block_type(const char* name, const char* description, wtap_block_create_func create,
                                                 wtap_mand_free_func free_mand, wtap_mand_copy_func copy_mand);