Ethereal-dev: Re: [ethereal-dev] TCP/UDP protcol dissector lookups
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: Sat, 18 Mar 2000 01:29:26 -0800
> I suspect that if we replaced "find_proto_id()" with a routine that > takes a field name as an argument, looks it up in the *complete* list of > hfinfo structures (not just in the list of protocols) and returns either > NULL (if not found) or "hfinfo->sub_dissectors" for that field (if > found), that'd let us handle that case. > > Presumably, TCP and UDP would register their hash table with "tcp.port" > and "udp.port", respectively, rather than with both "tcp.srcport" and > "tcp.dstport", and with both "udp.srcport" and "udp.dstport", > respectively. I've attached a patch - which is a patch to the current code in the CVS tree (i.e., if you applied my previous patch, un-apply it, or remove the changed files and check them out from CVS again). Currently, "register_dissector_table()" takes a field ID; perhaps it should take a field name instead.
Index: packet-udp.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet-udp.c,v
retrieving revision 1.52
diff -c -r1.52 packet-udp.c
*** packet-udp.c 2000/03/12 04:47:50 1.52
--- packet-udp.c 2000/03/18 09:25:23
***************
*** 129,232 ****
#define UDP_PORT_DHIS1 58800
#define UDP_PORT_DHIS2 58801
! struct hash_struct {
! guint16 proto;
! void (*dissect)(const u_char *, int, frame_data *, proto_tree *);
! struct hash_struct *next;
! };
!
! static struct hash_struct *hash_table[256];
!
! /*
! * These routines are for UDP, will be generalized soon: RJS
! *
! * XXX - note that they should probably check the IP address as well as
! * the port number, so that we don't mistakenly identify packets as, say,
! * TFTP, merely because they have a source or destination port number
! * equal to the port being used by a TFTP daemon on some machine other
! * than the one they're going to or from.
! */
!
! struct hash_struct *udp_find_hash_ent(guint16 proto) {
- int idx = proto % 256;
- struct hash_struct *hash_ent = hash_table[idx];
-
- while (hash_ent != NULL) {
-
- if (hash_ent -> proto == proto)
- return hash_ent;
-
- hash_ent = hash_ent -> next;
-
- }
-
- return NULL;
-
- }
-
- void udp_hash_add(guint16 proto,
- void (*dissect)(const u_char *, int, frame_data *, proto_tree *)) {
-
- int idx = proto % 256; /* Simply take the remainder, hope for no collisions */
- struct hash_struct *hash_ent = (struct hash_struct *)malloc(sizeof(struct hash_struct));
- struct hash_struct *hash_ent2;
-
- hash_ent -> proto = proto;
- hash_ent -> dissect = dissect;
- hash_ent -> next = NULL;
-
- if (hash_ent == NULL) {
-
- fprintf(stderr, "Could not allocate space for hash structure in dissect_udp\n");
- exit(1);
- }
-
- if (hash_table[idx]) { /* Something, add on end */
-
- hash_ent2 = hash_table[idx];
-
- while (hash_ent2 -> next != NULL)
- hash_ent2 = hash_ent2 -> next;
-
- hash_ent2 -> next = hash_ent; /* Bad in pathalogical cases */
-
- }
- else {
-
- hash_table[idx] = hash_ent;
-
- }
-
- }
-
void init_dissect_udp(void) {
-
- int i;
! for (i = 0; i < 256; i++) {
!
! hash_table[i] = NULL;
!
! }
/* Now add the protocols we know about */
! udp_hash_add(UDP_PORT_BOOTPS, dissect_bootp);
! udp_hash_add(UDP_PORT_TFTP, dissect_tftp);
! udp_hash_add(UDP_PORT_SAP, dissect_sap);
! udp_hash_add(UDP_PORT_HSRP, dissect_hsrp);
! udp_hash_add(UDP_PORT_PIM_RP_DISC, dissect_auto_rp);
! udp_hash_add(UDP_PORT_TACACS, dissect_tacacs);
! udp_hash_add(UDP_PORT_DHIS1, dissect_dhis);
! udp_hash_add(UDP_PORT_DHIS2, dissect_dhis);
}
void
dissect_udp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
e_udphdr uh;
guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
! struct hash_struct *dissect_routine = NULL;
proto_tree *udp_tree;
proto_item *ti;
--- 129,157 ----
#define UDP_PORT_DHIS1 58800
#define UDP_PORT_DHIS2 58801
! static dissector_table_t udp_dissector_table;
void init_dissect_udp(void) {
! udp_dissector_table = register_dissector_table(hf_udp_port);
/* Now add the protocols we know about */
! dissector_add("udp.port", UDP_PORT_BOOTPS, dissect_bootp);
! dissector_add("udp.port", UDP_PORT_TFTP, dissect_tftp);
! dissector_add("udp.port", UDP_PORT_SAP, dissect_sap);
! dissector_add("udp.port", UDP_PORT_HSRP, dissect_hsrp);
! dissector_add("udp.port", UDP_PORT_PIM_RP_DISC, dissect_auto_rp);
! dissector_add("udp.port", UDP_PORT_TACACS, dissect_tacacs);
! dissector_add("udp.port", UDP_PORT_DHIS1, dissect_dhis);
! dissector_add("udp.port", UDP_PORT_DHIS2, dissect_dhis);
}
void
dissect_udp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
e_udphdr uh;
guint16 uh_sport, uh_dport, uh_ulen, uh_sum;
! dissector_t dissect_routine;
proto_tree *udp_tree;
proto_item *ti;
***************
*** 334,340 ****
dissect_vines_frp(pd, offset, fd, tree);
} else if (PORT_IS(UDP_PORT_TFTP)) {
/* This is the first point of call, but it adds a dynamic call */
! udp_hash_add(MAX(uh_sport, uh_dport), dissect_tftp); /* Add to table */
dissect_tftp(pd, offset, fd, tree);
} else if (PORT_IS(UDP_PORT_TIME)) {
dissect_time(pd, offset, fd, tree);
--- 259,265 ----
dissect_vines_frp(pd, offset, fd, tree);
} else if (PORT_IS(UDP_PORT_TFTP)) {
/* This is the first point of call, but it adds a dynamic call */
! dissector_add("udp.port", MAX(uh_sport, uh_dport), dissect_tftp); /* Add to table */
dissect_tftp(pd, offset, fd, tree);
} else if (PORT_IS(UDP_PORT_TIME)) {
dissect_time(pd, offset, fd, tree);
***************
*** 354,374 ****
} else {
/* OK, find a routine in the table, else use the default */
! if ((dissect_routine = udp_find_hash_ent(uh_sport))) {
! struct hash_struct *dr2 = udp_find_hash_ent(uh_dport);
if (dr2 == NULL) { /* Not in the table, add */
! udp_hash_add(uh_dport, dissect_tftp);
}
! dissect_routine -> dissect(pd, offset, fd, tree);
}
! else if ((dissect_routine = udp_find_hash_ent(uh_dport))) {
! dissect_routine -> dissect(pd, offset, fd, tree);
}
else {
--- 279,299 ----
} else {
/* OK, find a routine in the table, else use the default */
! if ((dissect_routine = dissector_lookup(udp_dissector_table, uh_sport))) {
! dissector_t dr2 = dissector_lookup(udp_dissector_table, uh_dport);
if (dr2 == NULL) { /* Not in the table, add */
! dissector_add("udp.port", uh_dport, dissect_tftp);
}
! (*dissect_routine)(pd, offset, fd, tree);
}
! else if ((dissect_routine = dissector_lookup(udp_dissector_table, uh_dport))) {
! (*dissect_routine)(pd, offset, fd, tree);
}
else {
Index: packet.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.c,v
retrieving revision 1.65
diff -c -r1.65 packet.c
*** packet.c 2000/03/12 04:47:53 1.65
--- packet.c 2000/03/18 09:25:25
***************
*** 1187,1189 ****
--- 1187,1253 ----
proto_register_field_array(proto_frame, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
+
+ /*********************** code added for sub-dissector lookup *********************/
+
+ dissector_t dissector_lookup( dissector_table_t table, guint32 pattern) {
+
+ /* lookup a dissector based upon pattern. */
+
+ return g_hash_table_lookup( table, GUINT_TO_POINTER( pattern));
+ }
+
+
+ void dissector_add( char *name, guint32 pattern, dissector_t dissector) {
+
+ /* add an entry, lookup the dissector table for the specified field name, */
+ /* if a valid table found, add the subdissector */
+
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+
+ /* sanity check */
+ g_assert( sub_dissectors);
+
+ /* do the table insertion */
+ g_hash_table_insert( sub_dissectors, GUINT_TO_POINTER( pattern),
+ (gpointer)dissector);
+ }
+
+
+ void dissector_delete( char *name, guint32 pattern, dissector_t dissector) {
+
+ /* delete the entry for this dissector at this pattern */
+
+ /* NOTE: this doesn't use the dissector call variable. It is included to */
+ /* be consistant with the dissector_add and more importantly to be used */
+ /* if the technique of adding a temporary dissector is implimented. */
+ /* If temporary dissectors are deleted, then the original dissector must */
+ /* be available. */
+
+ dissector_table_t sub_dissectors = find_dissector_table( name);
+
+ /* sanity check */
+ g_assert( sub_dissectors);
+
+ /* remove the hash table entry */
+ g_hash_table_remove( sub_dissectors, GUINT_TO_POINTER( pattern));
+ }
+
+
+ dissector_table_t register_dissector_table( int id){
+
+ /* Create and register the dissector array for this field; returns */
+ /* a pointer to the dissector table. */
+
+ /* NOTE: currently use the g_direct_XXX functions so all the hashing is done */
+ /* by glib and we don't have to create hashing or comparison funtcions. */
+
+
+ header_field_info *hfinfo = find_hfinfo_record(id);
+
+ g_assert( hfinfo);
+
+ hfinfo->sub_dissectors = g_hash_table_new( g_direct_hash, g_direct_equal);
+ return hfinfo->sub_dissectors;
+ }
+
Index: packet.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/packet.h,v
retrieving revision 1.174
diff -c -r1.174 packet.h
*** packet.h 2000/03/08 06:47:51 1.174
--- packet.h 2000/03/18 09:25:26
***************
*** 205,210 ****
--- 205,228 ----
} true_false_string;
+ /* types for sub-dissector lookup */
+ typedef void (*dissector_t)(const u_char *, int, frame_data *, proto_tree *);
+
+ /* a protocol uses the function to register its sub-dissector table */
+ dissector_table_t register_dissector_table( int proto_id);
+
+ /* dissector lookup routine. called by protocol dissector to find a sub-dissector */
+ dissector_t dissector_lookup( dissector_table_t table, guint32 pattern);
+
+ /* Add a sub-dissector to a dissector table. Called by the protocol routine */
+ /* that wants to register a sub-dissector. */
+ void dissector_add( char *abbrev, guint32 pattern, dissector_t dissector);
+
+ /* Add a sub-dissector to a dissector table. Called by the protocol routine */
+ /* that wants to de-register a sub-dissector. */
+ void dissector_delete( char *abbrev, guint32 pattern, dissector_t dissector);
+
+
/* Many of the structs and definitions below and in packet-*.c files
* were taken from include files in the Linux distribution. */
***************
*** 267,274 ****
void init_dissect_rpc(void);
void init_dissect_udp(void);
-
- typedef void (*DissectFunc) (const u_char*, int, frame_data*, proto_tree*);
/*
* Routines should take four args: packet data *, offset, frame_data *,
--- 285,290 ----
Index: proto.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/proto.c,v
retrieving revision 1.56
diff -c -r1.56 proto.c
*** proto.c 2000/03/14 06:03:25 1.56
--- proto.c 2000/03/18 09:25:30
***************
*** 72,81 ****
static gboolean
proto_tree_free_node(GNode *node, gpointer data);
- static struct header_field_info*
- find_hfinfo_record(int hfindex);
-
-
static void fill_label_boolean(field_info *fi, gchar *label_str);
static void fill_label_uint(field_info *fi, gchar *label_str);
static void fill_label_enumerated_uint(field_info *fi, gchar *label_str);
--- 72,77 ----
***************
*** 250,263 ****
return FALSE; /* FALSE = do not end traversal of GNode tree */
}
! /* Finds a record in the hf_info_records array. */
! static struct header_field_info*
find_hfinfo_record(int hfindex)
{
g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
return g_ptr_array_index(gpa_hfinfo, hfindex);
}
/* Add a node with no text */
proto_item *
--- 246,274 ----
return FALSE; /* FALSE = do not end traversal of GNode tree */
}
! /* Finds a record in the hf_info_records array by id. */
! struct header_field_info*
find_hfinfo_record(int hfindex)
{
g_assert(hfindex >= 0 && hfindex < gpa_hfinfo->len);
return g_ptr_array_index(gpa_hfinfo, hfindex);
}
+ /* Finds a dissector table by field name. */
+ dissector_table_t
+ find_dissector_table(const char *name)
+ {
+ header_field_info *hfinfo;
+ int i, len;
+
+ len = gpa_hfinfo->len;
+ for (i = 0; i < len ; i++) {
+ hfinfo = find_hfinfo_record(i);
+ if (strcmp(name, hfinfo->abbrev) == 0)
+ return hfinfo->sub_dissectors;
+ }
+ return NULL;
+ }
/* Add a node with no text */
proto_item *
***************
*** 929,934 ****
--- 940,947 ----
hfinfo->bitshift = 0;
hfinfo->blurb = "";
hfinfo->parent = -1; /* this field differentiates protos and fields */
+
+ hfinfo->sub_dissectors = NULL; /* clear sub-dissector table pointer */
return proto_register_field_init(hfinfo, hfinfo->parent);
}
Index: proto.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/proto.h,v
retrieving revision 1.25
diff -c -r1.25 proto.h
*** proto.h 2000/03/14 06:03:26 1.25
--- proto.h 2000/03/18 09:25:30
***************
*** 89,94 ****
--- 89,98 ----
BASE_BIN
};
+
+ /* types for sub-dissector lookup */
+ typedef GHashTable* dissector_table_t;
+
/* information describing a header field */
typedef struct header_field_info {
char *name;
***************
*** 102,109 ****
--- 106,116 ----
int id; /* assigned by registration function, not programmer */
int parent; /* parent protocol */
int bitshift; /* bits to shift */
+ dissector_table_t sub_dissectors; /* sub-dissector table pointer */
} header_field_info;
+
+
/* Used when registering many fields at once */
typedef struct hf_register_info {
int *p_id; /* pointer to int; written to by register() function */
***************
*** 331,336 ****
--- 338,349 ----
/* Returns char* to abbrev for item # n (0-indexed) */
char* proto_registrar_get_abbrev(int n);
+
+ /* get the header field information based upon a field or protocol id */
+ struct header_field_info* find_hfinfo_record(int hfindex);
+
+ /* get the dissector table based upon a field or protocol name */
+ dissector_table_t find_dissector_table(const char *name);
/* Returns enum ftenum for item # n */
int proto_registrar_get_ftype(int n);
- References:
- RE: [ethereal-dev] TCP/UDP protcol dissector lookups
- From: Jeff Foster
- Re: [ethereal-dev] TCP/UDP protcol dissector lookups
- From: Guy Harris
- RE: [ethereal-dev] TCP/UDP protcol dissector lookups
- Prev by Date: Re: [ethereal-dev] TCP/UDP protcol dissector lookups
- Next by Date: Re: [ethereal-dev] TCP/UDP protcol dissector lookups
- Previous by thread: Re: [ethereal-dev] TCP/UDP protcol dissector lookups
- Next by thread: Re: [ethereal-dev] TCP/UDP protcol dissector lookups
- Index(es):





