Update Free Software Foundation address.
[metze/wireshark/wip.git] / asn1 / acse / packet-acse-template.c
1 /*XXX
2   There is a bug in asn2wrs 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 asn2wrs 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  * Wireshark - Network traffic analyzer
19  * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/expert.h>
45 #include <epan/oids.h>
46 #include <epan/asn1.h>
47
48 #include <string.h>
49
50 #include "packet-ber.h"
51 #include "packet-acse.h"
52 #include "packet-ses.h"
53 #include "packet-pres.h"
54 #include "packet-x509if.h"
55
56 #define PNAME  "ISO 8650-1 OSI Association Control Service"
57 #define PSNAME "ACSE"
58 #define PFNAME "acse"
59
60 #define CLPNAME  "ISO 10035-1 OSI Connectionless Association Control Service"
61 #define CLPSNAME "CLACSE"
62 #define CLPFNAME "clacse"
63
64
65 #define ACSE_APDU_OID "2.2.1.0.1"
66
67 /* Initialize the protocol and registered fields */
68 int proto_acse = -1;
69 int proto_clacse = -1;
70
71
72
73 #include "packet-acse-hf.c"
74
75 /* Initialize the subtree pointers */
76 static gint ett_acse = -1;
77 #include "packet-acse-ett.c"
78
79 static struct SESSION_DATA_STRUCTURE* session = NULL;
80
81 static const char *object_identifier_id;
82 /* indirect_reference, used to pick up the signalling so we know what
83    kind of data is transferred in SES_DATA_TRANSFER_PDUs */
84 static guint32 indir_ref=0;
85
86 static proto_tree *top_tree=NULL;
87
88 #if NOT_NEEDED
89 /* to keep track of presentation context identifiers and protocol-oids */
90 typedef struct _acse_ctx_oid_t {
91         /* XXX here we should keep track of ADDRESS/PORT as well */
92         guint32 ctx_id;
93         char *oid;
94 } acse_ctx_oid_t;
95 static GHashTable *acse_ctx_oid_table = NULL;
96
97 static guint
98 acse_ctx_oid_hash(gconstpointer k)
99 {
100         acse_ctx_oid_t *aco=(acse_ctx_oid_t *)k;
101         return aco->ctx_id;
102 }
103 /* XXX this one should be made ADDRESS/PORT aware */
104 static gint
105 acse_ctx_oid_equal(gconstpointer k1, gconstpointer k2)
106 {
107         acse_ctx_oid_t *aco1=(acse_ctx_oid_t *)k1;
108         acse_ctx_oid_t *aco2=(acse_ctx_oid_t *)k2;
109         return aco1->ctx_id==aco2->ctx_id;
110 }
111
112 static void
113 acse_init(void)
114 {
115         if( acse_ctx_oid_table ){
116                 g_hash_table_destroy(acse_ctx_oid_table);
117                 acse_ctx_oid_table = NULL;
118         }
119         acse_ctx_oid_table = g_hash_table_new(acse_ctx_oid_hash,
120                         acse_ctx_oid_equal);
121
122 }
123
124 static void
125 register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, char *oid)
126 {
127         acse_ctx_oid_t *aco, *tmpaco;
128         aco=se_alloc(sizeof(acse_ctx_oid_t));
129         aco->ctx_id=idx;
130         aco->oid=se_strdup(oid);
131
132         /* if this ctx already exists, remove the old one first */
133         tmpaco=(acse_ctx_oid_t *)g_hash_table_lookup(acse_ctx_oid_table, aco);
134         if(tmpaco){
135                 g_hash_table_remove(acse_ctx_oid_table, tmpaco);
136         }
137         g_hash_table_insert(acse_ctx_oid_table, aco, aco);
138 }
139 static char *
140 find_oid_by_ctx_id(packet_info *pinfo _U_, guint32 idx)
141 {
142         acse_ctx_oid_t aco, *tmpaco;
143         aco.ctx_id=idx;
144         tmpaco=(acse_ctx_oid_t *)g_hash_table_lookup(acse_ctx_oid_table, &aco);
145         if(tmpaco){
146                 return tmpaco->oid;
147         }
148         return NULL;
149 }
150
151 # endif /* NOT_NEEDED */
152
153 #include "packet-acse-fn.c"
154
155
156 /*
157 * Dissect ACSE PDUs inside a PPDU.
158 */
159 static void
160 dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
161 {
162         int offset = 0;
163         proto_item    *item=NULL;
164         proto_tree    *tree=NULL;
165         char *oid;
166         asn1_ctx_t asn1_ctx;
167         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
168
169
170         /* first, try to check length   */
171         /* do we have at least 2 bytes  */
172         if (!tvb_bytes_exist(tvb, 0, 2)){
173                 proto_tree_add_text(parent_tree, tvb, offset,
174                         tvb_reported_length_remaining(tvb,offset),
175                         "User data");
176                 return;  /* no, it isn't a ACSE PDU */
177         }
178         /* do we have spdu type from the session dissector?  */
179         if( !pinfo->private_data ){
180                 if(parent_tree){
181                         REPORT_DISSECTOR_BUG("Can't get SPDU type from session dissector.");
182                 }
183                 return  ;
184         } else {
185                 session  = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
186                 if(session->spdu_type == 0 ) {
187                         if(parent_tree){
188                                 REPORT_DISSECTOR_BUG(
189                                         ep_strdup_printf("Wrong spdu type %x from session dissector.",session->spdu_type));
190                                 return  ;
191                         }
192                 }
193         }
194         /* save parent_tree so subdissectors can create new top nodes */
195         top_tree=parent_tree;
196
197         /*  ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
198         /*  reject everything else                              */
199         /*  data pdu is not ACSE pdu and has to go directly to app dissector */
200         switch(session->spdu_type){
201         case SES_CONNECTION_REQUEST:            /*   AARQ   */
202         case SES_CONNECTION_ACCEPT:             /*   AARE   */
203         case SES_REFUSE:                        /*   RLRE   */
204         case SES_DISCONNECT:                    /*   RLRQ   */
205         case SES_FINISH:                        /*   RLRE   */
206         case SES_ABORT:                         /*   ABRT   */
207         case CLSES_UNIT_DATA:           /* AARQ Connetctionless session */              
208                 break;
209         case SES_DATA_TRANSFER:
210                 oid=find_oid_by_pres_ctx_id(pinfo, indir_ref);
211                 if(oid){
212                         if(strcmp(oid, ACSE_APDU_OID) == 0){
213                                 proto_tree_add_text(parent_tree, tvb, offset, -1,
214                                     "Invalid OID: %s", ACSE_APDU_OID);
215                                 THROW(ReportedBoundsError);
216                         }
217                         call_ber_oid_callback(oid, tvb, offset, pinfo, parent_tree);
218                 } else {
219                         proto_item *ti = proto_tree_add_text(parent_tree, tvb, offset, -1, "dissector is not available");
220                         expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "Dissector is not available");
221                 }
222                 top_tree = NULL;
223                 return;
224         default:
225                 top_tree = NULL;
226                 return;
227         }
228
229         if(session->spdu_type == CLSES_UNIT_DATA)
230         {
231                 /* create display subtree for the connectionless protocol */
232                 if(parent_tree)
233                 {
234                         item = proto_tree_add_item(parent_tree, proto_clacse, tvb, 0, -1, ENC_NA);
235                         tree = proto_item_add_subtree(item, ett_acse);
236                 }
237                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CL-ACSE");
238                 col_clear(pinfo->cinfo, COL_INFO);
239         }
240         else
241         {
242                 /* create display subtree for the protocol */
243                 if(parent_tree)
244                 {
245                         item = proto_tree_add_item(parent_tree, proto_acse, tvb, 0, -1, ENC_NA);
246                         tree = proto_item_add_subtree(item, ett_acse);
247                 }
248                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
249                 col_clear(pinfo->cinfo, COL_INFO);
250         }
251
252         /*  we can't make any additional checking here   */
253         /*  postpone it before dissector will have more information */
254         while (tvb_reported_length_remaining(tvb, offset) > 0){
255                 int old_offset=offset;
256                 offset = dissect_acse_ACSE_apdu(FALSE, tvb, offset, &asn1_ctx, tree, -1);
257                 if(offset == old_offset ){
258                         proto_tree_add_text(tree, tvb, offset, -1,"Malformed packet");
259                         break;
260                 }
261         }
262         
263 top_tree = NULL;
264 }
265
266 /*--- proto_register_acse ----------------------------------------------*/
267 void proto_register_acse(void) {
268
269   /* List of fields */
270   static hf_register_info hf[] = {
271 #include "packet-acse-hfarr.c"
272   };
273
274   /* List of subtrees */
275   static gint *ett[] = {
276     &ett_acse,
277 #include "packet-acse-ettarr.c"
278   };
279
280   /* Register protocol */
281   proto_acse = proto_register_protocol(PNAME, PSNAME, PFNAME);
282   register_dissector("acse", dissect_acse, proto_acse);
283
284   /* Register connectionless protocol */
285   proto_clacse = proto_register_protocol(CLPNAME, CLPSNAME, CLPFNAME);
286
287
288   /* Register fields and subtrees */
289   proto_register_field_array(proto_acse, hf, array_length(hf));
290   proto_register_subtree_array(ett, array_length(ett));
291
292 }
293
294
295 /*--- proto_reg_handoff_acse -------------------------------------------*/
296 void proto_reg_handoff_acse(void) {
297 /*#include "packet-acse-dis-tab.c"*/
298
299         oid_add_from_string("id-aCSE","2.2.3.1.1");
300         register_ber_oid_dissector(ACSE_APDU_OID, dissect_acse, proto_acse, "id-as-acse");
301
302
303 }
304