2 There is a bug in asn2wrs that it can not yet handle tagged assignments such
3 as EXTERNAL ::= [UNIVERSAL 8] IMPLICIT SEQUENCE {
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
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>
18 * Wireshark - Network traffic analyzer
19 * By Gerald Combs <gerald@wireshark.org>
20 * Copyright 1998 Gerald Combs
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.
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.
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.
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>
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"
56 #define PNAME "ISO 8650-1 OSI Association Control Service"
60 #define CLPNAME "ISO 10035-1 OSI Connectionless Association Control Service"
61 #define CLPSNAME "CLACSE"
62 #define CLPFNAME "clacse"
65 #define ACSE_APDU_OID "2.2.1.0.1"
67 /* Initialize the protocol and registered fields */
69 int proto_clacse = -1;
73 #include "packet-acse-hf.c"
75 /* Initialize the subtree pointers */
76 static gint ett_acse = -1;
77 #include "packet-acse-ett.c"
79 static struct SESSION_DATA_STRUCTURE* session = NULL;
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;
86 static proto_tree *top_tree=NULL;
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 */
95 static GHashTable *acse_ctx_oid_table = NULL;
98 acse_ctx_oid_hash(gconstpointer k)
100 acse_ctx_oid_t *aco=(acse_ctx_oid_t *)k;
103 /* XXX this one should be made ADDRESS/PORT aware */
105 acse_ctx_oid_equal(gconstpointer k1, gconstpointer k2)
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;
115 if( acse_ctx_oid_table ){
116 g_hash_table_destroy(acse_ctx_oid_table);
117 acse_ctx_oid_table = NULL;
119 acse_ctx_oid_table = g_hash_table_new(acse_ctx_oid_hash,
125 register_ctx_id_and_oid(packet_info *pinfo _U_, guint32 idx, char *oid)
127 acse_ctx_oid_t *aco, *tmpaco;
128 aco=se_alloc(sizeof(acse_ctx_oid_t));
130 aco->oid=se_strdup(oid);
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);
135 g_hash_table_remove(acse_ctx_oid_table, tmpaco);
137 g_hash_table_insert(acse_ctx_oid_table, aco, aco);
140 find_oid_by_ctx_id(packet_info *pinfo _U_, guint32 idx)
142 acse_ctx_oid_t aco, *tmpaco;
144 tmpaco=(acse_ctx_oid_t *)g_hash_table_lookup(acse_ctx_oid_table, &aco);
151 # endif /* NOT_NEEDED */
153 #include "packet-acse-fn.c"
157 * Dissect ACSE PDUs inside a PPDU.
160 dissect_acse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
163 proto_item *item=NULL;
164 proto_tree *tree=NULL;
167 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
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),
176 return; /* no, it isn't a ACSE PDU */
178 /* do we have spdu type from the session dissector? */
179 if( !pinfo->private_data ){
181 REPORT_DISSECTOR_BUG("Can't get SPDU type from session dissector.");
185 session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );
186 if(session->spdu_type == 0 ) {
188 REPORT_DISSECTOR_BUG(
189 ep_strdup_printf("Wrong spdu type %x from session dissector.",session->spdu_type));
194 /* save parent_tree so subdissectors can create new top nodes */
195 top_tree=parent_tree;
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 */
209 case SES_DATA_TRANSFER:
210 oid=find_oid_by_pres_ctx_id(pinfo, indir_ref);
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);
217 call_ber_oid_callback(oid, tvb, offset, pinfo, parent_tree);
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");
229 if(session->spdu_type == CLSES_UNIT_DATA)
231 /* create display subtree for the connectionless protocol */
234 item = proto_tree_add_item(parent_tree, proto_clacse, tvb, 0, -1, ENC_NA);
235 tree = proto_item_add_subtree(item, ett_acse);
237 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CL-ACSE");
238 col_clear(pinfo->cinfo, COL_INFO);
242 /* create display subtree for the protocol */
245 item = proto_tree_add_item(parent_tree, proto_acse, tvb, 0, -1, ENC_NA);
246 tree = proto_item_add_subtree(item, ett_acse);
248 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ACSE");
249 col_clear(pinfo->cinfo, COL_INFO);
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");
266 /*--- proto_register_acse ----------------------------------------------*/
267 void proto_register_acse(void) {
270 static hf_register_info hf[] = {
271 #include "packet-acse-hfarr.c"
274 /* List of subtrees */
275 static gint *ett[] = {
277 #include "packet-acse-ettarr.c"
280 /* Register protocol */
281 proto_acse = proto_register_protocol(PNAME, PSNAME, PFNAME);
282 register_dissector("acse", dissect_acse, proto_acse);
284 /* Register connectionless protocol */
285 proto_clacse = proto_register_protocol(CLPNAME, CLPSNAME, CLPFNAME);
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));
295 /*--- proto_reg_handoff_acse -------------------------------------------*/
296 void proto_reg_handoff_acse(void) {
297 /*#include "packet-acse-dis-tab.c"*/
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");