Ethereal-dev: Re: [ethereal-dev] plugins support

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

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Mon, 15 Nov 1999 02:17:54 -0800
> Dynamically allocating ETT_xxx values would not only be good for
> plugins, it'd be good for compiled-in dissectors - it'd obviate the need
> to add ETT_xxx values to "packet.h" if you add a new protocol with
> subtrees, or add a new subtree to an existing protocol.

Well, I now have some code that does that.

I added a "proto_register_subtree_array()" routine, which takes as
arguments a pointer to an array of "gint *"s, and a count of elements in
that array, and stores in each of the "gint"s pointed to by the elements
of that array a unique positive integer, which is an index into the
now-dynamic "tree_is_expanded" array.

A protocol would declare a number of static "gint" "ett_XXX" variables
(and initialize them to -1, so as to catch ett_XXX values not
registered), and, in its register routine, would declare an array of
"gint *"s that point to its "ett_XXX" variables, and call
"proto_register_subtree_array()" on that array.

It'd use the "ett_XXX" variables, rather than the "ETT_xxx" enum values;
the enum in question no longer exists.

We could, perhaps, register the protocol's "ett_XXX" variable in the
call that registers the protocol itself, and *if* a subtree is under a
protocol tree entry added with a call other than
"proto_tree_add_text()", we could perhaps register its "ett_XXX" value
when we register the field.  However, not all protocol tree entries with
subtrees have fields associated with them.

Here's a context diff of the non-dissector changes, and of
"packet-arp.c" (this changes every dissector that uses ETT_ values,
which means it changes every dissector, so I'm just sending one, as an
example):

Index: proto.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/proto.c,v
retrieving revision 1.48
diff -c -r1.48 proto.c
*** proto.c	1999/11/15 06:32:14	1.48
--- proto.c	1999/11/15 10:12:06
***************
*** 121,126 ****
--- 121,134 ----
  /* List which stores protocols and fields that have been registered */
  GPtrArray *gpa_hfinfo = NULL;
  
+ /* Points to the first element of an array of Booleans, indexed by
+    a subtree item type; that array element is TRUE if subtrees of
+    an item of that type are to be expanded. */
+ gboolean	*tree_is_expanded;
+ 
+ /* Number of elements in that array. */
+ int		num_tree_types;
+ 
  /* Is the parsing being done for a visible proto_tree or an invisible one?
   * By setting this correctly, the proto_tree creation is sped up by not
   * having to call vsnprintf and copy strings around.
***************
*** 145,150 ****
--- 153,160 ----
  		g_mem_chunk_destroy(gmc_item_labels);
  	if (gpa_hfinfo)
  		g_ptr_array_free(gpa_hfinfo, FALSE);
+ 	if (tree_is_expanded != NULL)
+ 		g_free(tree_is_expanded);
  
  	gmc_hfinfo = g_mem_chunk_new("gmc_hfinfo",
  		sizeof(struct header_field_info), 50 * sizeof(struct 
***************
*** 157,162 ****
--- 167,178 ----
  		G_ALLOC_AND_FREE);
  	gpa_hfinfo = g_ptr_array_new();
  
+ 	/* Allocate "tree_is_expanded", with one element for ETT_NONE,
+ 	   and initialize that element to FALSE. */
+ 	tree_is_expanded = g_malloc(sizeof (gint));
+ 	tree_is_expanded[0] = FALSE;
+ 	num_tree_types = 1;
+ 
  	/* Have each dissector register its protocols and fields. */
  	register_all_protocols();
  
***************
*** 164,169 ****
--- 180,190 ----
  		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));
+ 
+ 	/* 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 *));
  }
  
  void
***************
*** 413,418 ****
--- 434,440 ----
  proto_tree*
  proto_item_add_subtree(proto_item *pi,  gint idx) {
  	field_info *fi = (field_info*) (((GNode*)pi)->data);
+ 	g_assert(idx >= 0 && idx < num_tree_types);
  	fi->tree_type = idx;
  	return (proto_tree*) pi;
  }
***************
*** 478,483 ****
--- 500,530 ----
  	g_ptr_array_add(gpa_hfinfo, hfinfo);
  	hfinfo->id = gpa_hfinfo->len - 1;
  	return hfinfo->id;
+ }
+ 
+ void
+ proto_register_subtree_array(gint **indices, int num_indices)
+ {
+ 	int	i;
+ 	gint	**ptr = indices;
+ 
+ 	/*
+ 	 * Add "num_indices" elements to "tree_is_expanded".
+ 	 */
+ 	tree_is_expanded = g_realloc(tree_is_expanded,
+ 	    (num_tree_types + num_indices)*sizeof (gint));
+ 
+ 	/*
+ 	 * Assign "num_indices" subtree numbers starting at "num_tree_types",
+ 	 * returning the indices through the pointers in the array whose
+ 	 * first element is pointed to by "indices", set to FALSE the
+ 	 * elements to which those subtree numbers refer, and update
+ 	 * "num_tree_types" appropriately.
+ 	 */
+ 	for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
+ 		tree_is_expanded[num_tree_types] = FALSE;
+ 		**ptr = num_tree_types;
+ 	}
  }
  
  void
Index: proto.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/proto.h,v
retrieving revision 1.19
diff -c -r1.19 proto.h
*** proto.h	1999/11/15 06:32:15	1.19
--- proto.h	1999/11/15 10:12:06
***************
*** 173,178 ****
--- 173,181 ----
  void
  proto_register_field_array(int parent, hf_register_info *hf, int num_records);
  
+ void
+ proto_register_subtree_array(gint **indices, int num_indices);
+ 
  proto_item *
  proto_tree_add_item(proto_tree *tree, int hfindex, gint start,
  	gint length, ...);
***************
*** 237,241 ****
--- 240,255 ----
   * having to call vsnprintf and copy strings around.
   */
  extern gboolean proto_tree_is_visible;
+ 
+ /* Points to the first element of an array of Booleans, indexed by
+    a subtree item type; that array element is TRUE if subtrees of
+    an item of that type are to be expanded.
+ 
+    ETT_NONE is reserved for unregistered subtree types. */
+ #define	ETT_NONE	0
+ extern gboolean	     *tree_is_expanded;
+ 
+ /* Number of elements in that array. */
+ extern int           num_tree_types;
  
  #endif /* proto.h */
Index: packet.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.c,v
retrieving revision 1.53
diff -c -r1.53 packet.c
*** packet.c	1999/11/11 05:36:05	1.53
--- packet.c	1999/11/15 10:12:08
***************
*** 67,80 ****
  
  extern capture_file  cf;
  
! gboolean	tree_is_expanded[NUM_TREE_TYPES];
  
! int proto_frame = -1;
! int hf_frame_arrival_time = -1;
! int hf_frame_time_delta = -1;
! int hf_frame_number = -1;
! int hf_frame_packet_len = -1;
! int hf_frame_capture_len = -1;
  
  gchar *
  ether_to_str(const guint8 *ad) {
--- 67,80 ----
  
  extern capture_file  cf;
  
! static int proto_frame = -1;
! static int hf_frame_arrival_time = -1;
! static int hf_frame_time_delta = -1;
! static int hf_frame_number = -1;
! static int hf_frame_packet_len = -1;
! static int hf_frame_capture_len = -1;
  
! static gint ett_frame = -1;
  
  gchar *
  ether_to_str(const guint8 *ad) {
***************
*** 735,741 ****
  	  ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
  	    NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
  
! 	  fh_tree = proto_item_add_subtree(ti, ETT_FRAME);
  
  	  tv.tv_sec = fd->abs_secs;
  	  tv.tv_usec = fd->abs_usecs;
--- 735,741 ----
  	  ti = proto_tree_add_item_format(tree, proto_frame, 0, fd->cap_len,
  	    NULL, "Frame (%d on wire, %d captured)", fd->pkt_len, fd->cap_len);
  
! 	  fh_tree = proto_item_add_subtree(ti, ett_frame);
  
  	  tv.tv_sec = fd->abs_secs;
  	  tv.tv_usec = fd->abs_usecs;
***************
*** 834,840 ****
--- 834,844 ----
  		{ "Capture Frame Length",	"frame.cap_len", FT_UINT32, BASE_DEC, NULL, 0x0,
  			"" }},
  	};
+ 	static gint *ett[] = {
+ 		&ett_frame,
+ 	};
  
  	proto_frame = proto_register_protocol("Frame", "frame");
  	proto_register_field_array(proto_frame, hf, array_length(hf));
+ 	proto_register_subtree_array(ett, array_length(ett));
  }
Index: packet.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.h,v
retrieving revision 1.140
diff -c -r1.140 packet.h
*** packet.h	1999/11/14 20:44:52	1.140
--- packet.h	1999/11/15 10:12:09
***************
*** 206,478 ****
    int dport;
  } tcp_extra_data;
  
- /* Tree types.  Each dissect_* routine should have one for each
-    add_subtree() call. */
- 
- enum {
- 	ETT_NONE,
- 	ETT_FRAME,
- 	ETT_IEEE8023,
- 	ETT_ETHER2,
- 	ETT_LLC,
- 	ETT_TOKEN_RING,
- 	ETT_TOKEN_RING_AC,
- 	ETT_TOKEN_RING_FC,
- 	ETT_TR_IERR_CNT,
- 	ETT_TR_NERR_CNT,
- 	ETT_TR_MAC,
- 	ETT_PPP,
- 	ETT_ARP,
- 	ETT_BPDU,
- 	ETT_FDDI,
- 	ETT_NULL,
- 	ETT_IP,
- 	ETT_IP_OPTIONS,
- 	ETT_IP_OPTION_SEC,
- 	ETT_IP_OPTION_ROUTE,
- 	ETT_IP_OPTION_TIMESTAMP,
- 	ETT_IP_TOS,
- 	ETT_IP_OFF,
- 	ETT_UDP,
- 	ETT_TCP,
- 	ETT_TCP_OPTIONS,
- 	ETT_TCP_OPTION_SACK,
- 	ETT_TCP_FLAGS,
- 	ETT_ICMP,
- 	ETT_IGMP,
- 	ETT_IPX,
- 	ETT_SPX,
- 	ETT_NCP,
- 	ETT_NCP_REQUEST_FIELDS,
- 	ETT_NCP_REPLY_FIELDS,
- 	ETT_DNS,
- 	ETT_DNS_FLAGS,
- 	ETT_DNS_QRY,
- 	ETT_DNS_QD,
- 	ETT_DNS_ANS,
- 	ETT_DNS_RR,
- 	ETT_EIGRP,
- 	ETT_ICQ,
- 	ETT_ICQ_DECODE,
- 	ETT_ICQ_HEADER,
- 	ETT_ICQ_BODY,
- 	ETT_ICQ_BODY_PARTS,
- 	ETT_ISAKMP,
- 	ETT_ISAKMP_FLAGS,
- 	ETT_ISAKMP_PAYLOAD,
- 	ETT_RIP,
- 	ETT_RIP_VEC,
- 	ETT_RIPNG,
- 	ETT_RIPNG_ADDR,
- 	ETT_PIM,
- 	ETT_OSPF,
- 	ETT_OSPF_HDR,
- 	ETT_OSPF_HELLO,
- 	ETT_OSPF_DESC,
- 	ETT_OSPF_LSR,
- 	ETT_OSPF_LSA_UPD,
- 	ETT_OSPF_LSA,
- 	ETT_LPD,
- 	ETT_RAW,
- 	ETT_CLIP,
- 	ETT_BOOTP,
- 	ETT_BOOTP_OPTION,
- 	ETT_BOOTPARAMS,
- 	ETT_IPv6,
- 	ETT_BGP,
- 	ETT_BGP_OPEN,
- 	ETT_BGP_UPDATE,
- 	ETT_BGP_NOTIFICATION,
- 	ETT_BGP_ATTRS,
- 	ETT_BGP_ATTR,
- 	ETT_BGP_ATTR_FLAGS,
- 	ETT_BGP_UNFEAS,
- 	ETT_BGP_NLRI,
- 	ETT_BGP_MP_REACH_NLRI,
- 	ETT_BGP_MP_UNREACH_NLRI,
- 	ETT_CLNP,
- 	ETT_COTP,
- 	ETT_VINES_FRP,
- 	ETT_VINES,
- 	ETT_VINES_ARP,
- 	ETT_VINES_ICP,
- 	ETT_VINES_IPC,
- 	ETT_VINES_RTP,
- 	ETT_VINES_SPP,
- 	ETT_VLAN,
- 	ETT_IPXRIP,
- 	ETT_IPXSAP,
- 	ETT_IPXSAP_SERVER,
- 	ETT_NBNS,
- 	ETT_NBNS_FLAGS,
- 	ETT_NBNS_NB_FLAGS,
- 	ETT_NBNS_NAME_FLAGS,
- 	ETT_NBNS_QRY,
- 	ETT_NBNS_QD,
- 	ETT_NETB,
- 	ETT_NETB_FLAGS,
- 	ETT_NETB_STATUS,
- 	ETT_NETB_NAME,
- 	ETT_NBNS_ANS,
- 	ETT_NBNS_RR,
- 	ETT_NBIPX,
- 	ETT_NBIPX_NAME_TYPE_FLAGS,
- 	ETT_AARP,
- 	ETT_GIOP,
- 	ETT_NBDGM,
- 	ETT_CDP,
- 	ETT_CDP_TLV,
- 	ETT_HTTP,
- 	ETT_TFTP,
-  	ETT_AH,
-  	ETT_ESP,
-  	ETT_IPCOMP,
-  	ETT_ICMPv6,
-  	ETT_ICMPv6OPT,
-  	ETT_ICMPv6FLAG,
- 	ETT_POP,
- 	ETT_IMAP,
- 	ETT_MAPI,
- 	ETT_FTP,
- 	ETT_TELNET,
- 	ETT_TELNET_SUBOPT,
- 	ETT_NNTP,
- 	ETT_NTP,
- 	ETT_NTP_FLAGS,
- 	ETT_SNMP,
- 	ETT_NBSS,
- 	ETT_NBSS_FLAGS,
- 	ETT_RX,
- 	ETT_RX_FLAGS,
- 	ETT_AFS,
- 	ETT_AFS_OP,
- 	ETT_AFS_FID,
- 	ETT_AFS_ACL,
- 	ETT_AFS_CALLBACK,
- 	ETT_AFS_UBIKVER,
- 	ETT_SMB,
- 	ETT_SMB_FLAGS,
- 	ETT_SMB_FLAGS2,
- 	ETT_SMB_DIALECTS,
- 	ETT_SMB_MODE,
- 	ETT_SMB_CAPABILITIES,
- 	ETT_SMB_RAWMODE,
- 	ETT_SMB_AFLAGS,
- 	ETT_SMB_DESIREDACCESS,
- 	ETT_SMB_SEARCH,
- 	ETT_SMB_FILE,
- 	ETT_SMB_OPENFUNCTION,
- 	ETT_SMB_FILEATTRIBUTES,
- 	ETT_SMB_FILETYPE,
- 	ETT_SMB_ACTION,
- 	ETT_SMB_WRITEMODE,
- 	ETT_SMB_LOCK_TYPE,
- 	ETT_BROWSE,
- 	ETT_BROWSE_FLAGS,
- 	ETT_PPTP,
- 	ETT_GRE,
- 	ETT_GRE_FLAGS,
- 	ETT_ICP,
- 	ETT_ICP_PAYLOAD,
-  	ETT_PPPOED,
-  	ETT_PPPOED_TAGS,
-  	ETT_PPPOES,
-  	ETT_LCP,
-  	ETT_LCP_OPTIONS,
-  	ETT_LCP_MRU_OPT,
-  	ETT_LCP_ASYNC_MAP_OPT,
-  	ETT_LCP_AUTHPROT_OPT,
-  	ETT_LCP_QUALPROT_OPT,
-  	ETT_LCP_MAGICNUM_OPT,
-  	ETT_LCP_FCS_ALTERNATIVES_OPT,
-  	ETT_LCP_NUMBERED_MODE_OPT,
-  	ETT_LCP_CALLBACK_OPT,
-  	ETT_LCP_MULTILINK_EP_DISC_OPT,
-  	ETT_LCP_INTERNATIONALIZATION_OPT,
-  	ETT_IPCP,
-  	ETT_IPCP_OPTIONS,
-  	ETT_IPCP_IPADDRS_OPT,
-  	ETT_IPCP_COMPRESSPROT_OPT,
-         ETT_RSVP,
-         ETT_RSVP_UNKNOWN_CLASS,
-         ETT_RSVP_HDR,
-         ETT_RSVP_SESSION,
-         ETT_RSVP_SGROUP,
-         ETT_RSVP_HOP,
-         ETT_RSVP_INTEGRITY,
-         ETT_RSVP_TIME_VALUES,
-         ETT_RSVP_ERROR,
-         ETT_RSVP_SCOPE,
-         ETT_RSVP_STYLE,
-         ETT_RSVP_FLOWSPEC,
-         ETT_RSVP_FILTER_SPEC,
-         ETT_RSVP_SENDER_TEMPLATE,
-         ETT_RSVP_SENDER_TSPEC,
-         ETT_RSVP_ADSPEC,
-         ETT_RSVP_POLICY,
-         ETT_RSVP_CONFIRM,
-         ETT_RSVP_ADSPEC_SUBTREE1,
-         ETT_RSVP_ADSPEC_SUBTREE2,
-         ETT_RSVP_ADSPEC_SUBTREE3,
- 	ETT_RTSP,
- 	ETT_SDP,
- 	ETT_RADIUS,
- 	ETT_RADIUS_AVP,
- 	ETT_LAPB,
- 	ETT_LAPD,
- 	ETT_LAPD_ADDRESS,
- 	ETT_X25,
- 	ETT_XDLC_CONTROL,
- 	ETT_Q931,
- 	ETT_Q931_IE,
- 	ETT_ATM,
- 	ETT_ATM_LANE,
- 	ETT_ATM_LANE_LC_FLAGS,
- 	ETT_ATM_LANE_LC_LAN_DEST,
- 	ETT_ATM_LANE_LC_LAN_DEST_RD,
- 	ETT_MP,
- 	ETT_MP_FLAGS,
- 	ETT_IPP,
- 	ETT_IPP_AS,
- 	ETT_IPP_ATTR,
- 	ETT_SNA,
- 	ETT_SNA_TH,
- 	ETT_SNA_TH_FID,
- 	ETT_SNA_RH,
- 	ETT_SNA_RH_0,
- 	ETT_SNA_RH_1,
- 	ETT_SNA_RH_2,
- 	ETT_SNA_RU,
- 	ETT_YHOO,
- 	ETT_RPC,
- 	ETT_RPC_STRING,
- 	ETT_RPC_CRED,
- 	ETT_RPC_VERF,
- 	ETT_RPC_GIDS,
- 	ETT_MOUNT,
- 	ETT_NFS,
- 	ETT_NFS_FHANDLE,
- 	ETT_NFS_TIMEVAL,
- 	ETT_NFS_MODE,
- 	ETT_NFS_FATTR,
- 	ETT_NFS_MODE3,
- 	ETT_NFS_SPECDATA3,
- 	ETT_NFS_FH3,
- 	ETT_NFS_NFSTIME3,
- 	ETT_NFS_FATTR3,
- 	ETT_NLM,
- 	ETT_PORTMAP,
- 	ETT_STAT,
- 	ETT_YPBIND,
- 	ETT_YPSERV,
- 	ETT_YPXFR,
- 	ETT_DDP,
- 	NUM_TREE_TYPES	/* last item number plus one */
- };
- 
- /* TRUE if subtrees of an item of the specified type are to be expanded. */
- extern gboolean	     tree_is_expanded[NUM_TREE_TYPES];
- 
  /* Utility routines used by packet*.c */
  gchar*     ether_to_str(const guint8 *);
  gchar*     ip_to_str(const guint8 *);
--- 206,211 ----
Index: packet-arp.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-arp.c,v
retrieving revision 1.21
diff -c -r1.21 packet-arp.c
*** packet-arp.c	1999/11/04 08:15:38	1.21
--- packet-arp.c	1999/11/15 10:12:10
***************
*** 46,51 ****
--- 46,53 ----
  static int hf_arp_dst_ether = -1;
  static int hf_arp_dst_proto = -1;
  
+ static gint ett_arp = -1;
+ 
  /* Definitions taken from Linux "linux/if_arp.h" header file, and from
  
  	http://www.isi.edu/in-notes/iana/assignments/arp-parameters
***************
*** 254,260 ****
  				      MIN_ARP_HEADER_SIZE + 2*ar_hln + 
  				      2*ar_pln, NULL,
  				      "Unknown ARP (opcode 0x%04x)", ar_op);
!     arp_tree = proto_item_add_subtree(ti, ETT_ARP);
      proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + AR_HRD, 2,
  			       ar_hrd);
      proto_tree_add_item(arp_tree, hf_arp_proto_type, offset + AR_PRO, 2,
--- 256,262 ----
  				      MIN_ARP_HEADER_SIZE + 2*ar_hln + 
  				      2*ar_pln, NULL,
  				      "Unknown ARP (opcode 0x%04x)", ar_op);
!     arp_tree = proto_item_add_subtree(ti, ett_arp);
      proto_tree_add_item(arp_tree, hf_arp_hard_type, offset + AR_HRD, 2,
  			       ar_hrd);
      proto_tree_add_item(arp_tree, hf_arp_proto_type, offset + AR_PRO, 2,
***************
*** 329,335 ****
--- 331,341 ----
  	FT_BYTES,	BASE_NONE,	NULL,	0x0,
        "" }}
    };
+   static gint *ett[] = {
+     &ett_arp,
+   };
  
    proto_arp = proto_register_protocol("Address Resolution Protocol", "arp");
    proto_register_field_array(proto_arp, hf, array_length(hf));
+   proto_register_subtree_array(ett, array_length(ett));
  }
Index: gtk/proto_draw.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/proto_draw.c,v
retrieving revision 1.3
diff -c -r1.3 proto_draw.c
*** proto_draw.c	1999/09/12 20:23:43	1.3
--- proto_draw.c	1999/11/15 10:14:46
***************
*** 121,127 ****
  
  void expand_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
    int i;
!   for(i=0; i < NUM_TREE_TYPES; i++) {
      tree_is_expanded[i] = TRUE;
    }
    gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
--- 121,127 ----
  
  void expand_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
    int i;
!   for(i=0; i < num_tree_types; i++) {
      tree_is_expanded[i] = TRUE;
    }
    gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
***************
*** 130,136 ****
  
  void collapse_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
    int i;
!   for(i=0; i < NUM_TREE_TYPES; i++) {
      tree_is_expanded[i] = FALSE;
    }
    gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
--- 130,136 ----
  
  void collapse_all_tree(proto_tree *protocol_tree, GtkWidget *tree_view) {
    int i;
!   for(i=0; i < num_tree_types; i++) {
      tree_is_expanded[i] = FALSE;
    }
    gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);