aboutsummaryrefslogtreecommitdiffstats
path: root/asn1/ros
diff options
context:
space:
mode:
authorGraeme Lunt <graeme.lunt@smhs.co.uk>2007-12-03 19:29:24 +0000
committerGraeme Lunt <graeme.lunt@smhs.co.uk>2007-12-03 19:29:24 +0000
commit5d8693069d80e1c3d45c2b9484b39878d3df2d61 (patch)
treec889eb889809d345e9a9cdd2014b1c1b382e917e /asn1/ros
parentaabf0f25d1ef33c78c12bda7b24821c604094c9f (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
Diffstat (limited to 'asn1/ros')
-rw-r--r--asn1/ros/Remote-Operations-Information-Objects.asn4
-rw-r--r--asn1/ros/packet-ros-template.c115
-rw-r--r--asn1/ros/packet-ros-template.h27
-rw-r--r--asn1/ros/ros.cnf2
4 files changed, 145 insertions, 3 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);
}