Update Free Software Foundation address.
[metze/wireshark/wip.git] / asn1 / pres / packet-pres-template.c
index ebed644121e641af2a2f9afcb479b2da999c17bb..b2be9b12f467859f1ab2a4a9c06f83494b1d769d 100644 (file)
@@ -1,6 +1,6 @@
 /* packet-pres.c
  * Routine to dissect ISO 8823 OSI Presentation Protocol packets
- * Based on the dissector by 
+ * Based on the dissector by
  * Yuriy Sidelnikov <YSidelnikov@hotmail.com>
  *
  * $Id$
@@ -21,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifdef HAVE_CONFIG_H
 
 #include <glib.h>
 #include <epan/packet.h>
+#include <epan/prefs.h>
 #include <epan/conversation.h>
 #include <epan/emem.h>
+#include <epan/expert.h>
+#include <epan/uat.h>
 
-#include <stdio.h>
 #include <string.h>
 
 #include <epan/asn1.h>
 #define PSNAME "PRES"
 #define PFNAME "pres"
 
+#define CLPNAME  "ISO 9576-1 OSI Connectionless Presentation Protocol"
+#define CLPSNAME "CLPRES"
+#define CLPFNAME "clpres"
+
 /* Initialize the protocol and registered fields */
-int proto_pres = -1;
+static int proto_pres = -1;
+
+/* Initialize the connectionles protocol */
+static int proto_clpres = -1;
+
+
 /*   type of session envelop */
 static struct SESSION_DATA_STRUCTURE* session = NULL;
 
@@ -68,6 +79,14 @@ typedef struct _pres_ctx_oid_t {
 } pres_ctx_oid_t;
 static GHashTable *pres_ctx_oid_table = NULL;
 
+typedef struct _pres_user_t {
+   guint ctx_id;
+   char *oid;
+} pres_user_t;
+
+static pres_user_t *pres_users;
+static guint num_pres_users;
+
 static int hf_pres_CP_type = -1;
 static int hf_pres_CPA_PPDU = -1;
 static int hf_pres_Abort_type = -1;
@@ -81,6 +100,8 @@ static gint ett_pres           = -1;
 
 #include "packet-pres-ett.c"
 
+UAT_DEC_CB_DEF(pres_users, ctx_id, pres_user_t)
+UAT_CSTRING_CB_DEF(pres_users, oid, pres_user_t)
 
 static guint
 pres_ctx_oid_hash(gconstpointer k)
@@ -123,7 +144,7 @@ register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, const char *oid)
        pco=se_alloc(sizeof(pres_ctx_oid_t));
        pco->ctx_id=idx;
        pco->oid=se_strdup(oid);
-       conversation=find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, 
+       conversation=find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
                        pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
        if (conversation) {
                pco->index = conversation->index;
@@ -139,6 +160,7 @@ register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, const char *oid)
        }
        g_hash_table_insert(pres_ctx_oid_table, pco, pco);
 }
+
 char *
 find_oid_by_pres_ctx_id(packet_info *pinfo _U_, guint32 idx)
 {
@@ -146,7 +168,7 @@ find_oid_by_pres_ctx_id(packet_info *pinfo _U_, guint32 idx)
        conversation_t *conversation;
 
        pco.ctx_id=idx;
-       conversation=find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, 
+       conversation=find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
                        pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
        if (conversation) {
                pco.index = conversation->index;
@@ -161,6 +183,47 @@ find_oid_by_pres_ctx_id(packet_info *pinfo _U_, guint32 idx)
        return NULL;
 }
 
+static void *
+pres_copy_cb(void *dest, const void *orig, size_t len _U_)
+{
+       pres_user_t *u = dest;
+       const pres_user_t *o = orig;
+
+       u->ctx_id = o->ctx_id;
+       u->oid = g_strdup(o->oid);
+
+       return dest;
+}
+
+static void
+pres_free_cb(void *r)
+{
+       pres_user_t *u = r;
+
+       g_free(u->oid);
+}
+
+static gboolean
+pres_try_users_table(guint32 ctx_id, tvbuff_t *tvb, int offset, packet_info *pinfo)
+{
+       tvbuff_t *next_tvb;
+       guint i;
+
+       for (i = 0; i < num_pres_users; i++) {
+               pres_user_t *u = &(pres_users[i]);
+
+               if (u->ctx_id == ctx_id) {
+                       /* Register oid so other dissectors can find this connection */
+                       register_ctx_id_and_oid(pinfo, u->ctx_id, u->oid);
+                       next_tvb = tvb_new_subset_remaining(tvb, offset);
+                       call_ber_oid_callback(u->oid, next_tvb, offset, pinfo, global_tree);
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
 
 #include "packet-pres-fn.c"
 
@@ -171,18 +234,17 @@ find_oid_by_pres_ctx_id(packet_info *pinfo _U_, guint32 idx)
 static int
 dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
-  proto_item *ti;
-  proto_tree *pres_tree = NULL;
-  guint s_type;
-  asn1_ctx_t asn1_ctx;
-  asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
+       proto_item *ti;
+       proto_tree *pres_tree = NULL;
+       asn1_ctx_t asn1_ctx;
+       asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
 
-  /* do we have spdu type from the session dissector?  */
+       /* do we have spdu type from the session dissector?  */
        if( !pinfo->private_data ){
                if(tree){
                        proto_tree_add_text(tree, tvb, offset, -1,
                                "Internal error:can't get spdu type from session dissector.");
-                       return  FALSE;
+                       return 0;
                }
        }else{
                session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
@@ -190,21 +252,17 @@ dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
                        if(tree){
                                proto_tree_add_text(tree, tvb, offset, -1,
                                        "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
-                               return  FALSE;
+                               return 0;
                        }
                }
        }
-/* get type of tag      */
-       s_type = tvb_get_guint8(tvb, offset);
-               /*  set up type of Ppdu */
-       if (check_col(pinfo->cinfo, COL_INFO))
-                                       col_add_str(pinfo->cinfo, COL_INFO,
-                                               val_to_str(session->spdu_type, ses_vals, "Unknown Ppdu type (0x%02x)"));
-  if (tree){
-         ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1,
-                   FALSE);
-         pres_tree = proto_item_add_subtree(ti, ett_pres);
-  }
+       /*  set up type of PPDU */
+       col_add_str(pinfo->cinfo, COL_INFO,
+                   val_to_str(session->spdu_type, ses_vals, "Unknown PPDU type (0x%02x)"));
+       if (tree){
+               ti = proto_tree_add_item(tree, proto_pres, tvb, offset, -1, ENC_NA);
+               pres_tree = proto_item_add_subtree(ti, ett_pres);
+       }
 
        switch(session->spdu_type){
                case SES_CONNECTION_REQUEST:
@@ -240,44 +298,66 @@ dissect_ppdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
        return offset;
 }
 
-void
+static void
 dissect_pres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
 {
        int offset = 0, old_offset;
-/* first, try to check length   */
-/* do we have at least 4 bytes  */
+
+       session = ((struct SESSION_DATA_STRUCTURE*)(pinfo->private_data));
+
+       /* first, try to check length   */
+       /* do we have at least 4 bytes  */
        if (!tvb_bytes_exist(tvb, 0, 4)){
-               session = ((struct SESSION_DATA_STRUCTURE*)(pinfo->private_data));
                if (session && session->spdu_type != SES_MAJOR_SYNC_POINT) {
-                       proto_tree_add_text(parent_tree, tvb, offset, 
+                       proto_tree_add_text(parent_tree, tvb, offset,
                                            tvb_reported_length_remaining(tvb,offset),"User data");
                        return;  /* no, it isn't a presentation PDU */
                }
        }
 
-       /*  we can't make any additional checking here   */
-       /*  postpone it before dissector will have more information */
-
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_clear(pinfo->cinfo, COL_INFO);
        /* save pointers for calling the acse dissector  */
        global_tree = parent_tree;
        global_pinfo = pinfo;
 
+       /* if the session unit-data packet then we process it */
+       /* as a connectionless presentation protocol unit data */
+       if(session && session->spdu_type == CLSES_UNIT_DATA)
+       {
+               proto_tree * clpres_tree = NULL;
+               proto_item *ti;
+
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "CL-PRES");
+               col_clear(pinfo->cinfo, COL_INFO);
+
+               if (parent_tree)
+               {
+                       ti = proto_tree_add_item(parent_tree, proto_clpres, tvb, offset, -1, ENC_NA);
+                       clpres_tree = proto_item_add_subtree(ti, ett_pres);
+               }
+
+               /* dissect the packet */
+               dissect_UD_type_PDU(tvb, pinfo, clpres_tree);
+               return;
+       }
+
+       /*  we can't make any additional checking here   */
+       /*  postpone it before dissector will have more information */
+
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "PRES");
+       col_clear(pinfo->cinfo, COL_INFO);
+
        if (session && session->spdu_type == SES_MAJOR_SYNC_POINT) {
                /* This is a reassembly initiated in packet-ses */
                char *oid = find_oid_by_pres_ctx_id (pinfo, session->pres_ctx_id);
                if (oid) {
                        call_ber_oid_callback (oid, tvb, offset, pinfo, parent_tree);
                } else {
-                       proto_tree_add_text(parent_tree, tvb, offset, 
+                       proto_tree_add_text(parent_tree, tvb, offset,
                                            tvb_reported_length_remaining(tvb,offset),"User data");
                }
                return;
          }
-            
+
        while (tvb_reported_length_remaining(tvb, offset) > 0){
                old_offset = offset;
                offset = dissect_ppdu(tvb, offset, pinfo, parent_tree);
@@ -297,23 +377,23 @@ void proto_register_pres(void) {
     { &hf_pres_CP_type,
       { "CP-type", "pres.cptype",
         FT_NONE, BASE_NONE, NULL, 0,
-        "", HFILL }},
+        NULL, HFILL }},
     { &hf_pres_CPA_PPDU,
       { "CPA-PPDU", "pres.cpapdu",
         FT_NONE, BASE_NONE, NULL, 0,
-        "", HFILL }},
+        NULL, HFILL }},
     { &hf_pres_Abort_type,
       { "Abort type", "pres.aborttype",
         FT_UINT32, BASE_DEC, VALS(pres_Abort_type_vals), 0,
-        "", HFILL }},
+        NULL, HFILL }},
     { &hf_pres_CPR_PPDU,
       { "CPR-PPDU", "pres.cprtype",
         FT_UINT32, BASE_DEC, VALS(pres_CPR_PPDU_vals), 0,
-        "", HFILL }},
+        NULL, HFILL }},
     { &hf_pres_Typed_data_type,
       { "Typed data type", "pres.Typed_data_type",
         FT_UINT32, BASE_DEC, VALS(pres_Typed_data_type_vals), 0,
-        "", HFILL }},
+        NULL, HFILL }},
 
 
 #include "packet-pres-hfarr.c"
@@ -325,21 +405,53 @@ void proto_register_pres(void) {
 #include "packet-pres-ettarr.c"
   };
 
+  static uat_field_t users_flds[] = {
+    UAT_FLD_DEC(pres_users,ctx_id,"Context Id","Presentation Context Identifier"),
+    UAT_FLD_CSTRING(pres_users,oid,"Syntax Name OID","Abstract Syntax Name (Object Identifier)"),
+    UAT_END_FIELDS
+  };
+
+  uat_t* users_uat = uat_new("PRES Users Context List",
+                             sizeof(pres_user_t),
+                             "pres_context_list",
+                             TRUE,
+                             (void*) &pres_users,
+                             &num_pres_users,
+                             UAT_CAT_PORTS,
+                             "ChPresContextList",
+                             pres_copy_cb,
+                             NULL,
+                             pres_free_cb,
+                             NULL,
+                             users_flds);
+
+  static module_t *pres_module;
+
   /* Register protocol */
   proto_pres = proto_register_protocol(PNAME, PSNAME, PFNAME);
   register_dissector("pres", dissect_pres, proto_pres);
+
+  /* Register connectionless protocol (just for the description) */
+  proto_clpres = proto_register_protocol(CLPNAME, CLPSNAME, CLPFNAME);
+
   /* Register fields and subtrees */
   proto_register_field_array(proto_pres, hf, array_length(hf));
   proto_register_subtree_array(ett, array_length(ett));
   register_init_routine(pres_init);
 
+  pres_module = prefs_register_protocol(proto_pres, NULL);
+
+  prefs_register_uat_preference(pres_module, "users_table", "Users Context List",
+                                "A table that enumerates user protocols to be used against"
+                                " specific presentation context identifiers",
+                                users_uat);
 }
 
 
 /*--- proto_reg_handoff_pres ---------------------------------------*/
 void proto_reg_handoff_pres(void) {
 
-/*     register_ber_oid_dissector("0.4.0.0.1.1.1.1", dissect_pres, proto_pres, 
+/*     register_ber_oid_dissector("0.4.0.0.1.1.1.1", dissect_pres, proto_pres,
          "itu-t(0) identified-organization(4) etsi(0) mobileDomain(0) gsm-Network(1) abstractSyntax(1) pres(1) version1(1)"); */
 
 }