diff options
author | Graeme Lunt <graeme.lunt@smhs.co.uk> | 2007-12-03 19:29:24 +0000 |
---|---|---|
committer | Graeme Lunt <graeme.lunt@smhs.co.uk> | 2007-12-03 19:29:24 +0000 |
commit | 5d8693069d80e1c3d45c2b9484b39878d3df2d61 (patch) | |
tree | c889eb889809d345e9a9cdd2014b1c1b382e917e | |
parent | aabf0f25d1ef33c78c12bda7b24821c604094c9f (diff) |
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
-rw-r--r-- | asn1/ros/Remote-Operations-Information-Objects.asn | 4 | ||||
-rw-r--r-- | asn1/ros/packet-ros-template.c | 115 | ||||
-rw-r--r-- | asn1/ros/packet-ros-template.h | 27 | ||||
-rw-r--r-- | asn1/ros/ros.cnf | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-ros.c | 153 | ||||
-rw-r--r-- | epan/dissectors/packet-ros.h | 27 |
6 files changed, 305 insertions, 23 deletions
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); } diff --git a/epan/dissectors/packet-ros.c b/epan/dissectors/packet-ros.c index 20518b6e27..36dccff4ae 100644 --- a/epan/dissectors/packet-ros.c +++ b/epan/dissectors/packet-ros.c @@ -137,7 +137,9 @@ static gint ett_ros_Code = -1; #line 84 "packet-ros-template.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 @@ -151,13 +153,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; @@ -405,7 +517,7 @@ dissect_ros_T_argument(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset static const ber_sequence_t Invoke_sequence[] = { { &hf_ros_invokeId , BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_ros_InvokeId }, - { &hf_ros_linkedId , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL, dissect_ros_INTEGER }, + { &hf_ros_linkedId , BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_ros_INTEGER }, { &hf_ros_opcode , BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_NOOWNTAG, dissect_ros_OperationCode }, { &hf_ros_argument , BER_CLASS_ANY, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_ros_T_argument }, { NULL, 0, 0, 0, NULL } @@ -497,7 +609,7 @@ dissect_ros_T_parameter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset 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); } @@ -609,10 +721,10 @@ static const value_string ros_T_problem_vals[] = { }; static const ber_choice_t T_problem_choice[] = { - { 0, &hf_ros_general , BER_CLASS_CON, 0, 0, dissect_ros_GeneralProblem }, - { 1, &hf_ros_invokeProblem , BER_CLASS_CON, 1, 0, dissect_ros_InvokeProblem }, - { 2, &hf_ros_rejectResult , BER_CLASS_CON, 2, 0, dissect_ros_ReturnResultProblem }, - { 3, &hf_ros_rejectError , BER_CLASS_CON, 3, 0, dissect_ros_ReturnErrorProblem }, + { 0, &hf_ros_general , BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_ros_GeneralProblem }, + { 1, &hf_ros_invokeProblem , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ros_InvokeProblem }, + { 2, &hf_ros_rejectResult , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ros_ReturnResultProblem }, + { 3, &hf_ros_rejectError , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_ros_ReturnErrorProblem }, { 0, NULL, 0, 0, 0, NULL } }; @@ -777,16 +889,16 @@ static const value_string ros_ROS_vals[] = { }; static const ber_choice_t ROS_choice[] = { - { 1, &hf_ros_invoke , BER_CLASS_CON, 1, 0, dissect_ros_Invoke }, - { 2, &hf_ros_returnResult , BER_CLASS_CON, 2, 0, dissect_ros_ReturnResult }, - { 3, &hf_ros_returnError , BER_CLASS_CON, 3, 0, dissect_ros_ReturnError }, - { 4, &hf_ros_reject , BER_CLASS_CON, 4, 0, dissect_ros_Reject }, - { 16, &hf_ros_bind_invoke , BER_CLASS_CON, 16, 0, dissect_ros_T_bind_invoke }, - { 17, &hf_ros_bind_result , BER_CLASS_CON, 17, 0, dissect_ros_T_bind_result }, - { 18, &hf_ros_bind_error , BER_CLASS_CON, 18, 0, dissect_ros_T_bind_error }, - { 19, &hf_ros_unbind_invoke , BER_CLASS_CON, 19, 0, dissect_ros_T_unbind_invoke }, - { 20, &hf_ros_unbind_result , BER_CLASS_CON, 20, 0, dissect_ros_T_unbind_result }, - { 21, &hf_ros_unbind_error , BER_CLASS_CON, 21, 0, dissect_ros_T_unbind_error }, + { 1, &hf_ros_invoke , BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_ros_Invoke }, + { 2, &hf_ros_returnResult , BER_CLASS_CON, 2, BER_FLAGS_IMPLTAG, dissect_ros_ReturnResult }, + { 3, &hf_ros_returnError , BER_CLASS_CON, 3, BER_FLAGS_IMPLTAG, dissect_ros_ReturnError }, + { 4, &hf_ros_reject , BER_CLASS_CON, 4, BER_FLAGS_IMPLTAG, dissect_ros_Reject }, + { 16, &hf_ros_bind_invoke , BER_CLASS_CON, 16, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_invoke }, + { 17, &hf_ros_bind_result , BER_CLASS_CON, 17, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_result }, + { 18, &hf_ros_bind_error , BER_CLASS_CON, 18, BER_FLAGS_IMPLTAG, dissect_ros_T_bind_error }, + { 19, &hf_ros_unbind_invoke , BER_CLASS_CON, 19, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_invoke }, + { 20, &hf_ros_unbind_result , BER_CLASS_CON, 20, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_result }, + { 21, &hf_ros_unbind_error , BER_CLASS_CON, 21, BER_FLAGS_IMPLTAG, dissect_ros_T_unbind_error }, { 0, NULL, 0, 0, 0, NULL } }; @@ -842,7 +954,7 @@ dissect_ros_Priority(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U /*--- End of included file: packet-ros-fn.c ---*/ -#line 264 "packet-ros-template.c" +#line 376 "packet-ros-template.c" /* * Dissect ROS PDUs inside a PPDU. @@ -1077,7 +1189,7 @@ void proto_register_ros(void) { "ros.OBJECT_IDENTIFIER", HFILL }}, /*--- End of included file: packet-ros-hfarr.c ---*/ -#line 386 "packet-ros-template.c" +#line 498 "packet-ros-template.c" }; /* List of subtrees */ @@ -1098,7 +1210,7 @@ void proto_register_ros(void) { &ett_ros_Code, /*--- End of included file: packet-ros-ettarr.c ---*/ -#line 393 "packet-ros-template.c" +#line 505 "packet-ros-template.c" }; /* Register protocol */ @@ -1110,6 +1222,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/epan/dissectors/packet-ros.h b/epan/dissectors/packet-ros.h index 5abc0aba35..4fc50b600f 100644 --- a/epan/dissectors/packet-ros.h +++ b/epan/dissectors/packet-ros.h @@ -53,17 +53,44 @@ int dissect_ros_Code(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U # 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 */ |