ad51c59bd94f67e81c280b42ddbe10bef04a8119
[obnox/wireshark/wip.git] / asn1 / acse / packet-acse-template.c
1 /*XXX
2   There is a bug in asn2eth that it can not yet handle tagged assignments such
3   as EXTERNAL  ::=  [UNIVERSAL 8] IMPLICIT SEQUENCE {
4
5   This bug is workedaround by some .cnf magic but this should be cleaned up 
6   once asn2eth learns how to deal with tagged assignments
7 */
8
9 /* packet-acse.c
10  * Routines for ACSE packet dissection
11  *   Ronnie Sahlberg 2005
12  * dissect_acse() based original handwritten dissector by Sid
13  *   Yuriy Sidelnikov <YSidelnikov@hotmail.com>
14  *  
15  *
16  * $Id$
17  *
18  * Ethereal - Network traffic analyzer
19  * By Gerald Combs <gerald@ethereal.com>
20  * Copyright 1998 Gerald Combs
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public License
24  * as published by the Free Software Foundation; either version 2
25  * of the License, or (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
35  */
36
37 #ifdef HAVE_CONFIG_H
38 # include "config.h"
39 #endif
40
41 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/emem.h>
44 #include <epan/conversation.h>
45
46 #include <stdio.h>
47 #include <string.h>
48
49 #include "packet-ber.h"
50 #include "packet-acse.h"
51 #include "packet-ses.h"
52 #include "packet-x509if.h"
53
54 #define PNAME  "ACSE"
55 #define PSNAME "ACSE"
56 #define PFNAME "acse"
57
58 /* Initialize the protocol and registered fields */
59 int proto_acse = -1;
60 #include "packet-acse-hf.c"
61
62 /* Initialize the subtree pointers */
63 static gint ett_acse = -1;
64 #include "packet-acse-ett.c"
65
66 static struct SESSION_DATA_STRUCTURE* session = NULL;
67
68 static char object_identifier_id[MAX_OID_STR_LEN];
69 /* indirect_reference, used to pick up the signalling so we know what
70    kind of data is transferred in SES_DATA_TRANSFER_PDUs */
71 static guint32 indir_ref=0;
72
73 static proto_tree *top_tree=NULL;
74
75 /* to keep track of presentation context identifiers and protocol-oids */
76 typedef struct _acse_ctx_oid_t {
77         /* XXX here we should keep track of ADDRESS/PORT as well */
78         guint32 ctx_id;
79         char *oid;
80 } acse_ctx_oid_t;
81 static GHashTable *acse_ctx_oid_table = NULL;
82
83 static guint
84 acse_ctx_oid_hash(gconstpointer k)
85 {
86         acse_ctx_oid_t *aco=(acse_ctx_oid_t *)k;
87         return aco->ctx_id;
88 }
89 /* XXX this one should be made ADDRESS/PORT aware */
90 static gint
91 acse_ctx_oid_equal(gconstpointer k1, gconstpointer k2)
92 {
93         acse_ctx_oid_t *aco1=(acse_ctx_oid_t *)k1;
94         acse_ctx_oid_t *aco2=(acse_ctx_oid_t *)k2;
95         return aco1->ctx_id==aco2->ctx_id;
96 }
97
98 static void
99 acse_init(void)
100 {
101         if( acse_ctx_oid_table ){
102                 g_hash_table_destroy(acse_ctx_oid_table);
103                 acse_ctx_oid_table = NULL;
104         }
105         acse_ctx_oid_table = g_hash_table_new(acse_ctx_oid_hash,
106                         acse_ctx_oid_equal);
107
108 }
109
110 static void
111 register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, char *oid)
112 {
113         acse_ctx_oid_t *aco, *tmpaco;
114         aco=se_alloc(sizeof(acse_ctx_oid_t));
115         aco->ctx_id=idx;
116         aco->oid=se_strdup(oid);
117
118         /* if this ctx already exists, remove the old one first */
119         tmpaco=(acse_ctx_oid_t *)g_hash_table_lookup(acse_ctx_oid_table, aco);
120         if(tmpaco){
121                 g_hash_table_remove(acse_ctx_oid_table, tmpaco);
122         }
123         g_hash_table_insert(acse_ctx_oid_table, aco, aco);
124 }
125 static char *
126 find_oid_by_ctx_id(packet_info *pinfo _U_, guint32 idx)
127 {
128         acse_ctx_oid_t aco, *tmpaco;
129         aco.ctx_id=idx;
130         tmpaco=(acse_ctx_oid_t *)g_hash_table_lookup(acse_ctx_oid_table, &aco);
131         if(tmpaco){
132                 return tmpaco->oid;
133         }
134         return NULL;
135 }
136
137
138 #include "packet-acse-fn.c"
139
140
141 /*
142 * Dissect ACSE PDUs inside a PPDU.
143 */
144 static void
145 dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
146 {
147         int offset = 0;
148         proto_item    *item=NULL;
149         proto_tree    *tree=NULL;
150         char *oid;
151
152         /* save parent_tree so subdissectors can create new top nodes */
153         top_tree=parent_tree;
154
155         /* first, try to check length   */
156         /* do we have at least 2 bytes  */
157         if (!tvb_bytes_exist(tvb, 0, 2)){
158                 proto_tree_add_text(parent_tree, tvb, offset, 
159                         tvb_reported_length_remaining(tvb,offset),
160                         "User data");
161                 return;  /* no, it isn't a ACSE PDU */
162         }
163         /* do we have spdu type from the session dissector?  */
164         if( !pinfo->private_data ){
165                 if(parent_tree){
166                         proto_tree_add_text(parent_tree, tvb, offset, -1,
167                                 "Internal error:can't get spdu type from session dissector.");
168                 } 
169                 return  ;
170         } else {
171                 session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
172                 if(session->spdu_type == 0 ) {
173                         if(parent_tree){
174                                 proto_tree_add_text(parent_tree, tvb, offset, -1,
175                                         "Internal error:wrong spdu type %x from session dissector.",session->spdu_type);
176                                 return  ;
177                         }
178                 }
179         }
180         /*  ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
181         /*  reject everything else                              */
182         /*  data pdu is not ACSE pdu and has to go directly to app dissector */
183         switch(session->spdu_type){
184         case SES_CONNECTION_REQUEST:            /*   AARQ   */
185         case SES_CONNECTION_ACCEPT:                     /*   AARE   */
186         case SES_REFUSE:                                        /*   RLRE   */
187         case SES_DISCONNECT:                            /*   RLRQ   */
188         case SES_FINISH:                                        /*   RLRE   */
189         case SES_ABORT:                                         /*   ABRT   */
190                 break;
191         case SES_DATA_TRANSFER:
192                 oid=find_oid_by_ctx_id(pinfo, indir_ref);
193                 if(oid){
194                         call_ber_oid_callback(oid, tvb, offset, pinfo, parent_tree);
195                 } else {
196                         proto_tree_add_text(parent_tree, tvb, offset, -1,
197                             "dissector is not available");
198                 }
199                 return;
200         default:
201                 return;
202         }
203
204         /* create display subtree for the protocol */
205         if(parent_tree){
206                 item = proto_tree_add_item(parent_tree, proto_acse, tvb, 0, -1, FALSE);
207                 tree = proto_item_add_subtree(item, ett_acse);
208         }
209         if (check_col(pinfo->cinfo, COL_PROTOCOL))
210                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
211         if (check_col(pinfo->cinfo, COL_INFO))
212                 col_clear(pinfo->cinfo, COL_INFO);
213
214
215         /*  we can't make any additional checking here   */
216         /*  postpone it before dissector will have more information */
217         while (tvb_reported_length_remaining(tvb, offset) > 0){
218                 offset = dissect_acse_ACSE_apdu(FALSE, tvb, offset, pinfo, tree, -1);
219                 if(offset == FALSE ){
220                         proto_tree_add_text(tree, tvb, offset, -1,"Internal error");
221                         offset = tvb_length(tvb);
222                         break;
223                 }
224         }
225
226         switch(session->spdu_type){
227         case SES_CONNECTION_REQUEST:            /*   AARQ   */
228         case SES_CONNECTION_ACCEPT:                     /*   AARE   */
229                 /* these two functions are used to set up the association
230                    between a presentation identifier (indir_ref) and
231                    a protocol identified by a oid.
232                    it is ugly to handle it with global variables but
233                    better than nothing.
234                 */
235                 register_ctx_id_and_oid(pinfo, indir_ref, object_identifier_id);
236                 break;
237         }
238 }
239
240 /*--- proto_register_acse ----------------------------------------------*/
241 void proto_register_acse(void) {
242
243   /* List of fields */
244   static hf_register_info hf[] = {
245 #include "packet-acse-hfarr.c"
246   };
247
248   /* List of subtrees */
249   static gint *ett[] = {
250     &ett_acse,
251 #include "packet-acse-ettarr.c"
252   };
253
254   /* Register protocol */
255   proto_acse = proto_register_protocol(PNAME, PSNAME, PFNAME);
256   register_dissector("acse", dissect_acse, proto_acse);
257
258   /* Register fields and subtrees */
259   proto_register_field_array(proto_acse, hf, array_length(hf));
260   proto_register_subtree_array(ett, array_length(ett));
261
262   register_init_routine(acse_init);
263 }
264
265
266 /*--- proto_reg_handoff_acse -------------------------------------------*/
267 void proto_reg_handoff_acse(void) {
268 /*#include "packet-acse-dis-tab.c"*/
269         register_ber_oid_dissector("2.2.3.1.1", dissect_acse, proto_acse, "acse");
270         register_ber_oid_dissector("2.2.1.0.1", dissect_acse, proto_acse, "acse-as-id");
271 }
272