Ethereal-dev: [Ethereal-dev] patch to allow for field definitions after initialization

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Matthijs Melchior <mmelchior@xxxxxxxxx>
Date: Sat, 23 Aug 2003 23:47:33 +0200
Here is a patch to enable dissectors to register fields from
preferences dialogues, after initialization of the main ethereal
system. Of course, fields defined in this way will not end up in
the manual pages....

I have rearranged 'proto_init()' somewhat, and moved the code to
build the field name tree to 'proto_register_field_init()'.

Having done this, it brought to light some serious mis behavior
of the gtk2 code to construct the field name list in routine
'dfilter_expr_dlg_new()'.  To solve the problem, I have created
an new iterator to enumerate the fields for a particular protocol.
Using this, the code in 'dfilter_expr_dlg_new()' has become much
nicer!
It now shows the same protocol name as with gtk1, the short_name.



While testing the above [and looking for "asn" in the output of -G],
I found the following:

P       Packet Encoding Rules (ASN.1 X.691)     per

This is a serious typo, the P in PER does not refer to a packet,
it refers to the small number of bits: packed

Patch to correct it is attached.


Thanks for applying the patches.

--
Regards,
----------------------------------------------------------------  -o)
Matthijs Melchior                                       Maarssen  /\\
mmelchior@xxxxxxxxx          +31 346 570616          Netherlands _\_v
---------------------------------------------------------------- ----

diff -u ./epan/proto.c-ORG ./epan/proto.c
--- ./epan/proto.c-ORG	2003-07-10 03:20:13.000000000 +0200
+++ ./epan/proto.c	2003-08-23 21:03:00.000000000 +0200
@@ -124,7 +124,7 @@
 static int g_strcmp(gconstpointer a, gconstpointer b);
 
 /* special-case header field used within proto.c */
-int hf_text_only = 1;
+int hf_text_only = -1;
 
 /* Structure for information about a protocol */
 typedef struct {
@@ -138,6 +138,8 @@
 	gboolean can_disable;	/* TRUE if protocol can be disabled */
 } protocol_t;
 
+static protocol_t *find_protocol_by_id(int proto_id);
+
 /* List of all protocols */
 static GList *protocols;
 
@@ -185,27 +187,13 @@
 	   void (register_all_protocols)(void),
 	   void (register_all_protocol_handoffs)(void))
 {
-	int			id, num_symbols;
-	char			*abbrev;
-	header_field_info	*hfinfo, *same_name_hfinfo, *same_name_next_hfinfo;
 	static hf_register_info hf[] = {
 		{ &hf_text_only,
 		{ "",	"", FT_NONE, BASE_NONE, NULL, 0x0,
 			NULL, HFILL }},
 	};
 
-	if (gmc_hfinfo)
-		g_mem_chunk_destroy(gmc_hfinfo);
-	if (gmc_field_info)
-		g_mem_chunk_destroy(gmc_field_info);
-	if (gmc_proto_node)
-		g_mem_chunk_destroy(gmc_proto_node);
-	if (gmc_item_labels)
-		g_mem_chunk_destroy(gmc_item_labels);
-	if (gpa_hfinfo)
-		g_ptr_array_free(gpa_hfinfo, TRUE);
-	if (tree_is_expanded != NULL)
-		g_free(tree_is_expanded);
+	proto_cleanup();
 
 	gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
 		sizeof(header_field_info),
@@ -228,10 +216,16 @@
 		G_ALLOC_AND_FREE);
 
 	gpa_hfinfo = g_ptr_array_new();
+	gpa_name_tree = g_tree_new(g_strcmp);
 
 	/* Initialize the ftype subsystem */
 	ftypes_initialize();
 
+	/* Register one special-case FT_TEXT_ONLY field for use when
+	   converting ethereal to new-style proto_tree. These fields
+	   are merely strings on the GUI tree; they are not filterable */
+	proto_register_field_array(-1, hf, array_length(hf));
+
 	/* Have each built-in dissector register its protocols, fields,
 	   dissector tables, and dissectors to be called through a
 	   handle, and do whatever one-time initialization it needs to
@@ -255,72 +249,10 @@
 	register_all_plugin_handoffs();
 #endif
 
-	/* Register one special-case FT_TEXT_ONLY field for use when
-	   converting ethereal to new-style proto_tree. These fields
-	   are merely strings on the GUI tree; they are not filterable */
-	proto_register_field_array(-1, hf, array_length(hf));
-
-	num_symbols = proto_registrar_n();
-
-	if (gpa_name_tree) {
-		/* XXX - needed? */
-		g_message("I expected gpa_name_tree to be NULL\n");
-		g_tree_destroy(gpa_name_tree);
-
-		/* Make sure the hfinfo->same_name links are broken */
-		for (id = 0; id < num_symbols; id++) {
-			hfinfo = proto_registrar_get_nth(id);
-			hfinfo->same_name_next = NULL;
-			hfinfo->same_name_prev = NULL;
-		}
-	}
-	gpa_name_tree = g_tree_new(g_strcmp);
-
-	/* Populate the abbrev/ID GTree (header-field symbol table) */
-
-	for (id = 0; id < num_symbols; id++) {
-		if (id == hf_text_only) {
-			continue;
-		}
-		abbrev = proto_registrar_get_abbrev(id);
-		hfinfo = proto_registrar_get_nth(id);
-
-		g_assert(abbrev);		/* Not Null */
-		g_assert(abbrev[0] != 0);	/* Not empty string */
-
-		/* We allow multiple hfinfo's to be registered under the same
-		 * abbreviation. This was done for X.25, as, depending
-		 * on whether it's modulo-8 or modulo-128 operation,
-		 * some bitfield fields may be in different bits of
-		 * a byte, and we want to be able to refer to that field
-		 * with one name regardless of whether the packets
-		 * are modulo-8 or modulo-128 packets. */
-		same_name_hfinfo = g_tree_lookup(gpa_name_tree, abbrev);
-		if (same_name_hfinfo) {
-			/* There's already a field with this name.
-			 * Put it after that field in the list of
-			 * fields with this name, then allow the code
-			 * after this if{} block to replace the old
-			 * hfinfo with the new hfinfo in the GTree. Thus,
-			 * we end up with a linked-list of same-named hfinfo's,
-			 * with the root of the list being the hfinfo in the GTree */
-			same_name_next_hfinfo =
-			    same_name_hfinfo->same_name_next;
-
-			hfinfo->same_name_next = same_name_next_hfinfo;
-			if (same_name_next_hfinfo)
-				same_name_next_hfinfo->same_name_prev = hfinfo;
-
-			same_name_hfinfo->same_name_next = hfinfo;
-			hfinfo->same_name_prev = same_name_hfinfo;
-		}
-		g_tree_insert(gpa_name_tree, abbrev, hfinfo);
-	}
-
 	/* We've assigned all the subtree type values; allocate the array
 	   for them, and zero it out. */
 	tree_is_expanded = g_malloc(num_tree_types*sizeof (gint *));
-	memset(tree_is_expanded, '\0', num_tree_types*sizeof (gint *));
+	memset(tree_is_expanded, 0, num_tree_types*sizeof (gint *));
 }
 
 /* String comparison func for dfilter_token GTree */
@@ -2200,6 +2132,35 @@
 	return protocol->proto_id;
 }
 
+header_field_info *
+proto_get_first_protocol_field(int proto_id, void **cookie)
+{
+	protocol_t *protocol = find_protocol_by_id(proto_id);
+	hf_register_info *ptr;
+
+	if ((protocol == NULL) || (protocol->fields == NULL))
+		return NULL;
+
+	*cookie = protocol->fields;
+	ptr = protocol->fields->data;
+	return &ptr->hfinfo;
+}
+
+header_field_info *
+proto_get_next_protocol_field(void **cookie)
+{
+	GList *list_item = *cookie;
+	hf_register_info *ptr;
+
+	list_item = g_list_next(list_item);
+	if (list_item == NULL)
+		return NULL;
+
+	*cookie = list_item;
+	ptr = list_item->data;
+	return &ptr->hfinfo;
+}
+
 /*
  * Find the protocol list entry for a protocol given its field ID.
  */
@@ -2339,6 +2300,10 @@
 static int
 proto_register_field_init(header_field_info *hfinfo, int parent)
 {
+	/* The field must have names */
+	g_assert(hfinfo->name);
+	g_assert(hfinfo->abbrev);
+
 	/* These types of fields are allowed to have value_strings or true_false_strings */
 	g_assert((hfinfo->strings == NULL) || (
 			(hfinfo->type == FT_UINT8) ||
@@ -2389,6 +2354,41 @@
 	/* if we always add and never delete, then id == len - 1 is correct */
 	g_ptr_array_add(gpa_hfinfo, hfinfo);
 	hfinfo->id = gpa_hfinfo->len - 1;
+
+	/* if we have real names, enter this field in the name tree */
+	if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
+
+		header_field_info *same_name_hfinfo, *same_name_next_hfinfo;
+
+		/* We allow multiple hfinfo's to be registered under the same
+		 * abbreviation. This was done for X.25, as, depending
+		 * on whether it's modulo-8 or modulo-128 operation,
+		 * some bitfield fields may be in different bits of
+		 * a byte, and we want to be able to refer to that field
+		 * with one name regardless of whether the packets
+		 * are modulo-8 or modulo-128 packets. */
+		same_name_hfinfo = g_tree_lookup(gpa_name_tree, hfinfo->abbrev);
+		if (same_name_hfinfo) {
+			/* There's already a field with this name.
+			 * Put it after that field in the list of
+			 * fields with this name, then allow the code
+			 * after this if{} block to replace the old
+			 * hfinfo with the new hfinfo in the GTree. Thus,
+			 * we end up with a linked-list of same-named hfinfo's,
+			 * with the root of the list being the hfinfo in the GTree */
+			same_name_next_hfinfo =
+			    same_name_hfinfo->same_name_next;
+
+			hfinfo->same_name_next = same_name_next_hfinfo;
+			if (same_name_next_hfinfo)
+				same_name_next_hfinfo->same_name_prev = hfinfo;
+
+			same_name_hfinfo->same_name_next = hfinfo;
+			hfinfo->same_name_prev = same_name_hfinfo;
+		}
+		g_tree_insert(gpa_name_tree, hfinfo->abbrev, hfinfo);
+	}
+
 	return hfinfo->id;
 }
 
@@ -3289,7 +3289,7 @@
 		 * with no pseudo-field being used, but that might also
 		 * require special checks for -1 to be added.
 		 */
-		if (strlen(hfinfo->name) == 0 || strlen(hfinfo->abbrev) == 0)
+		if (hfinfo->name[0] == 0 || hfinfo->abbrev[0] == 0)
 			continue;
 
 		/* format for protocols */
diff -u ./epan/proto.h-ORG ./epan/proto.h
--- ./epan/proto.h-ORG	2003-05-04 04:24:55.000000000 +0200
+++ ./epan/proto.h	2003-08-23 18:06:48.000000000 +0200
@@ -541,10 +541,13 @@
 /* Can item #n decoding be disabled? */
 extern gboolean proto_can_disable_protocol(int proto_id);
 
-/* Routines to use to iterate over the protocols; they return the item
- * number of the protocol in question, and keep state in "*cookie". */
+/* Routines to use to iterate over the protocols and their fields;
+ * they return the item number of the protocol in question or the
+ * appropriate hfinfo pointer, and keep state in "*cookie". */
 extern int proto_get_first_protocol(void **cookie);
 extern int proto_get_next_protocol(void **cookie);
+extern header_field_info *proto_get_first_protocol_field(int proto_id, void **cookle);
+extern header_field_info *proto_get_next_protocol_field(void **cookle);
 
 /* Given a protocol's filter_name, return it's proto_id */
 extern int proto_get_id_by_filter_name(gchar* filter_name);
diff -u ./gtk/dfilter_expr_dlg.c-ORG ./gtk/dfilter_expr_dlg.c
--- ./gtk/dfilter_expr_dlg.c-ORG	2003-03-11 00:58:20.000000000 +0100
+++ ./gtk/dfilter_expr_dlg.c	2003-08-23 23:39:47.000000000 +0200
@@ -1287,33 +1287,18 @@
                                     hfinfo);
         g_hash_table_insert(proto_array, (gpointer)i, protocol_node);
     }
-#endif
 
     len = proto_registrar_n();
     for (i = 0; i < len; i++) {
-#if GTK_MAJOR_VERSION < 2
         /*
          * If this field is a protocol, skip it - we already put
          * it in above.
          */
         if (proto_registrar_is_protocol(i))
             continue;
-#else
-        GtkTreeIter child_iter;
-#endif
 
         hfinfo = proto_registrar_get_nth(i);
 
-#if GTK_MAJOR_VERSION >= 2
-        if (hfinfo->type == FT_PROTOCOL)
-        {
-            /* Create a node for the protocol */
-            gtk_tree_store_append(store, &iter, NULL);
-            gtk_tree_store_set(store, &iter, 0, hfinfo->abbrev, 1, hfinfo, -1);
-            continue;
-        }
-#endif
-
         /*
          * If this field isn't at the head of the list of
          * fields with this name, skip this field - all
@@ -1331,7 +1316,6 @@
 
         /* Create a node for the item, and put it
            under its parent protocol. */
-#if GTK_MAJOR_VERSION < 2
         protocol_node = g_hash_table_lookup(proto_array,
                                             GINT_TO_POINTER(proto_registrar_get_parent(i)));
         item_node = gtk_ctree_insert_node(GTK_CTREE(tree),
@@ -1341,16 +1325,39 @@
                                           FALSE, FALSE);
         gtk_ctree_node_set_row_data(GTK_CTREE(tree),
                                     item_node, hfinfo);
-#else
-        gtk_tree_store_append(store, &child_iter, &iter);
-        gtk_tree_store_set(store, &child_iter, 0, hfinfo->name, 1, hfinfo, -1);
-#endif
     }
-#if GTK_MAJOR_VERSION < 2
     g_hash_table_destroy(proto_array);
-#else
+
+#else /* GTK_MAJOR_VERSION < 2 */
+{
+    /* GTK2 code using two levels iterator to enumerate all protocol fields */
+
+    GtkTreeIter iter, child_iter;
+    void *cookie, *cookie2;
+    gchar *name;
+
+    for (i = proto_get_first_protocol(&cookie); i != -1;
+         i = proto_get_next_protocol(&cookie)) {
+
+	hfinfo = proto_registrar_get_nth(i);
+	name = proto_get_protocol_short_name(i); /* name, short_name or filter name ? */
+
+	gtk_tree_store_append(store, &iter, NULL);
+	gtk_tree_store_set(store, &iter, 0, name, 1, hfinfo, -1);
+
+	for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
+	     hfinfo = proto_get_next_protocol_field(&cookie2)) {
+
+		if (hfinfo->same_name_prev != NULL) /* ignore duplicate names */
+			continue;
+
+		gtk_tree_store_append(store, &child_iter, &iter);
+		gtk_tree_store_set(store, &child_iter, 0, hfinfo->name, 1, hfinfo, -1);
+	}
+    }
     g_object_unref(G_OBJECT(store));
-#endif
+}
+#endif /* GTK_MAJOR_VERSION < 2 */
 
     gtk_widget_show_all(tree);
 
--- packet-per.c-ORG	2003-07-19 05:45:04.000000000 +0200
+++ packet-per.c	2003-08-23 23:27:10.000000000 +0200
@@ -1340,7 +1340,7 @@
 	};
 	module_t *per_module;
 
-	proto_per = proto_register_protocol("Packet Encoding Rules (ASN.1 X.691)", "PER", "per");
+	proto_per = proto_register_protocol("Packed Encoding Rules (ASN.1 X.691)", "PER", "per");
 	proto_register_field_array(proto_per, hf, array_length(hf));
 	proto_register_subtree_array(ett, array_length(ett));