From 5d8693069d80e1c3d45c2b9484b39878d3df2d61 Mon Sep 17 00:00:00 2001 From: Graeme Lunt Date: Mon, 3 Dec 2007 19:29:24 +0000 Subject: Support table-based dissection of ROS operations. This simplifies the generation of dissectors for ROS-based protocols using the asn2wrs #.TABLE directive. See the P7 dissector for an example. svn path=/trunk/; revision=23706 --- asn1/ros/Remote-Operations-Information-Objects.asn | 4 +- asn1/ros/packet-ros-template.c | 115 ++++++++++++++++++++- asn1/ros/packet-ros-template.h | 27 +++++ asn1/ros/ros.cnf | 2 +- 4 files changed, 145 insertions(+), 3 deletions(-) (limited to 'asn1/ros') diff --git a/asn1/ros/Remote-Operations-Information-Objects.asn b/asn1/ros/Remote-Operations-Information-Objects.asn index 8eeafd110b..40ae404177 100644 --- a/asn1/ros/Remote-Operations-Information-Objects.asn +++ b/asn1/ros/Remote-Operations-Information-Objects.asn @@ -1,7 +1,9 @@ -- Generated by Asnp, the pretty-printer of France Telecom R&D (http://asn1.elibel.tm.fr/asnp/) -- Module Remote-Operations-Information-Objects (Rec. X.880:07/1994) Remote-Operations-Information-Objects {joint-iso-itu-t remote-operations(4) - informationObjects(5) version1(0)} DEFINITIONS ::= + informationObjects(5) version1(0)} DEFINITIONS +IMPLICIT TAGS -- WS: Don't know why I need to add this - but if it isn't, the ROS operationCode is not successfully decoded - even though it doesn't have any tags! An asn2wrs issue? +::= BEGIN -- exports everything diff --git a/asn1/ros/packet-ros-template.c b/asn1/ros/packet-ros-template.c index c4c2351934..bf7abe37fc 100644 --- a/asn1/ros/packet-ros-template.c +++ b/asn1/ros/packet-ros-template.c @@ -83,7 +83,9 @@ static gint ett_ros = -1; #include "packet-ros-ett.c" static dissector_table_t ros_oid_dissector_table=NULL; + static GHashTable *oid_table=NULL; +static GHashTable *protocol_table=NULL; static gint ett_ros_unknown = -1; void @@ -97,13 +99,123 @@ register_ros_oid_dissector_handle(const char *oid, dissector_handle_t dissector, register_ber_oid_dissector_handle(oid, ros_handle, proto, name); } +void +register_ros_protocol_info(const char *oid, const ros_info_t *rinfo, int proto _U_, const char *name, gboolean uses_rtse) +{ + g_hash_table_insert(protocol_table, (gpointer)oid, (gpointer)rinfo); + g_hash_table_insert(oid_table, (gpointer)oid, (gpointer)name); + + if(!uses_rtse) + /* if we are not using RTSE, then we must register ROS with BER (ACSE) */ + register_ber_oid_dissector_handle(oid, ros_handle, proto, name); +} + +static new_dissector_t ros_lookup_opr_dissector(gint32 opcode, const ros_opr_t *operations, gboolean argument) +{ + /* we don't know what order asn2wrs/module definition is, so ... */ + if(operations) { + for(;operations->arg_pdu != (new_dissector_t)(-1); operations++) + if(operations->opcode == opcode) + return argument ? operations->arg_pdu : operations->res_pdu; + + } + return NULL; +} + +static new_dissector_t ros_lookup_err_dissector(gint32 errcode, const ros_err_t *errors) +{ + /* we don't know what order asn2wrs/module definition is, so ... */ + if(errors) { + for(;errors->err_pdu != (new_dissector_t) (-1); errors++) { + if(errors->errcode == errcode) + return errors->err_pdu; + } + } + return NULL; +} + + +static gboolean ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + ros_info_t *rinfo; + gint32 opcode = 0; + const gchar *opname = NULL; + const gchar *suffix = NULL; + int offset = 0; + new_dissector_t opdissector = NULL; + const value_string *lookup; + proto_item *item=NULL; + proto_tree *ros_tree=NULL; + + if((rinfo = (ros_info_t*)g_hash_table_lookup(protocol_table, oid)) != NULL) { + + if(tree){ + item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, FALSE); + ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto)); + } + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name); + + /* if this is a bind operation */ + if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) { + /* use the in-built operation codes */ + if((session->ros_op & ROS_OP_PDU_MASK) == ROS_OP_ERROR) + opcode = err_ros_bind; + else + opcode = op_ros_bind; + } else + /* otherwise just take the opcode */ + opcode = session->ros_op & ROS_OP_OPCODE_MASK; + + /* default lookup in the operations */ + lookup = rinfo->opr_code_strings; + + switch(session->ros_op & ROS_OP_PDU_MASK) { + case ROS_OP_ARGUMENT: + opdissector = ros_lookup_opr_dissector(opcode, rinfo->opr_code_dissectors, TRUE); + suffix = "_argument"; + break; + case ROS_OP_RESULT: + opdissector = ros_lookup_opr_dissector(opcode, rinfo->opr_code_dissectors, FALSE); + suffix = "_result"; + break; + case ROS_OP_ERROR: + opdissector = ros_lookup_err_dissector(opcode, rinfo->err_code_dissectors); + lookup = rinfo->err_code_strings; + break; + default: + break; + } + + if(opdissector) { + + opname = val_to_str(opcode, lookup, "Unknown opcode (%d)"); + + if (check_col(pinfo->cinfo, COL_INFO)) { + col_set_str(pinfo->cinfo, COL_INFO, opname); + if(suffix) + col_append_fstr(pinfo->cinfo, COL_INFO, suffix); + } + + offset = (*opdissector)(tvb, pinfo, ros_tree); + + return TRUE; + } + } + + return FALSE; +} + static int call_ros_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) { tvbuff_t *next_tvb; next_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), tvb_reported_length_remaining(tvb, offset)); - if(!dissector_try_string(ros_oid_dissector_table, oid, next_tvb, pinfo, tree)){ + + if(!ros_try_string(oid, next_tvb, pinfo, tree) && + !dissector_try_string(ros_oid_dissector_table, oid, next_tvb, pinfo, tree)){ proto_item *item=NULL; proto_tree *next_tree=NULL; @@ -401,6 +513,7 @@ void proto_register_ros(void) { ros_oid_dissector_table = register_dissector_table("ros.oid", "ROS OID Dissectors", FT_STRING, BASE_NONE); oid_table=g_hash_table_new(g_str_hash, g_str_equal); + protocol_table=g_hash_table_new(g_str_hash, g_str_equal); ros_handle = find_dissector("ros"); diff --git a/asn1/ros/packet-ros-template.h b/asn1/ros/packet-ros-template.h index 11c7c6d702..08209cb9f6 100644 --- a/asn1/ros/packet-ros-template.h +++ b/asn1/ros/packet-ros-template.h @@ -36,17 +36,44 @@ # define ROS_OP_MASK 0xff000000 +# define ROS_OP_PDU_MASK 0xf0000000 # define ROS_OP_ARGUMENT 0x10000000 # define ROS_OP_RESULT 0x20000000 # define ROS_OP_ERROR 0x30000000 # define ROS_OP_REJECT 0x40000000 +# define ROS_OP_TYPE_MASK 0x0f000000 # define ROS_OP_BIND 0x01000000 # define ROS_OP_UNBIND 0x02000000 # define ROS_OP_INVOKE 0x03000000 # define ROS_OP_OPCODE_MASK (~ROS_OP_MASK) +# define op_ros_bind (-1) /* pseudo operation code for asn2wrs generated binds */ +# define err_ros_bind (-1) /* pseudo eror code for asn2wrs generated binds */ + +typedef struct _ros_opr_t { + gint32 opcode; + new_dissector_t arg_pdu; + new_dissector_t res_pdu; +} ros_opr_t; + +typedef struct _ros_err_t { + gint32 errcode; + new_dissector_t err_pdu; +} ros_err_t; + +typedef struct _ros_info_t { + const gchar *name; + int *proto; + gint *ett_proto; + const value_string *opr_code_strings; + const ros_opr_t *opr_code_dissectors; + const value_string *err_code_strings; + const ros_err_t *err_code_dissectors; +} ros_info_t; + void register_ros_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto _U_, const char *name, gboolean uses_rtse); +void register_ros_protocol_info(const char *oid, const ros_info_t *rinfo, int proto _U_, const char *name, gboolean uses_rtse); #endif /* PACKET_ROS_H */ diff --git a/asn1/ros/ros.cnf b/asn1/ros/ros.cnf index 6ab6c0e50f..813f79da23 100644 --- a/asn1/ros/ros.cnf +++ b/asn1/ros/ros.cnf @@ -61,7 +61,7 @@ Reject/problem/returnResult rejectResult if(session && session->pres_ctx_id && (oid = find_oid_by_pres_ctx_id(actx->pinfo, session->pres_ctx_id))) { /* this should be ROS! */ session->ros_op = (ROS_OP_INVOKE | ROS_OP_ERROR); - /* now add the opcode (really the errode) */ + /* now add the opcode (really the error code) */ session->ros_op |= opcode; offset = call_ros_oid_callback(oid, tvb, offset, actx->pinfo, top_tree); } -- cgit v1.2.3