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.
40 #include <epan/packet.h>
41 #include <epan/exceptions.h>
42 #include <epan/wmem/wmem.h>
43 #include <epan/expert.h>
44 #include <epan/oids.h>
45 #include <epan/asn1.h>
49 #include "packet-ber.h"
50 #include "packet-acse.h"
51 #include "packet-ses.h"
52 #include "packet-pres.h"
53 #include "packet-x509if.h"
55 #define PNAME "ISO 8650-1 OSI Association Control Service"
59 #define CLPNAME "ISO 10035-1 OSI Connectionless Association Control Service"
60 #define CLPSNAME "CLACSE"
61 #define CLPFNAME "clacse"
64 #define ACSE_APDU_OID "2.2.1.0.1"
66 /* Initialize the protocol and registered fields */
68 int proto_clacse
= -1;
72 #include "packet-acse-hf.c"
74 /* Initialize the subtree pointers */
75 static gint ett_acse
= -1;
76 #include "packet-acse-ett.c"
78 static expert_field ei_acse_dissector_not_available
= EI_INIT
;
80 static const char *object_identifier_id
;
81 /* indirect_reference, used to pick up the signalling so we know what
82 kind of data is transferred in SES_DATA_TRANSFER_PDUs */
83 static guint32 indir_ref
=0;
85 static proto_tree
*top_tree
=NULL
;
88 /* to keep track of presentation context identifiers and protocol-oids */
89 typedef struct _acse_ctx_oid_t
{
90 /* XXX here we should keep track of ADDRESS/PORT as well */
94 static GHashTable
*acse_ctx_oid_table
= NULL
;
97 acse_ctx_oid_hash(gconstpointer k
)
99 acse_ctx_oid_t
*aco
=(acse_ctx_oid_t
*)k
;
102 /* XXX this one should be made ADDRESS/PORT aware */
104 acse_ctx_oid_equal(gconstpointer k1
, gconstpointer k2
)
106 acse_ctx_oid_t
*aco1
=(acse_ctx_oid_t
*)k1
;
107 acse_ctx_oid_t
*aco2
=(acse_ctx_oid_t
*)k2
;
108 return aco1
->ctx_id
==aco2
->ctx_id
;
114 if( acse_ctx_oid_table
){
115 g_hash_table_destroy(acse_ctx_oid_table
);
116 acse_ctx_oid_table
= NULL
;
118 acse_ctx_oid_table
= g_hash_table_new(acse_ctx_oid_hash
,
124 register_ctx_id_and_oid(packet_info
*pinfo _U_
, guint32 idx
, char *oid
)
126 acse_ctx_oid_t
*aco
, *tmpaco
;
127 aco
=wmem_new(wmem_file_scope(), acse_ctx_oid_t
);
129 aco
->oid
=wmem_strdup(wmem_file_scope(), oid
);
131 /* if this ctx already exists, remove the old one first */
132 tmpaco
=(acse_ctx_oid_t
*)g_hash_table_lookup(acse_ctx_oid_table
, aco
);
134 g_hash_table_remove(acse_ctx_oid_table
, tmpaco
);
136 g_hash_table_insert(acse_ctx_oid_table
, aco
, aco
);
139 find_oid_by_ctx_id(packet_info
*pinfo _U_
, guint32 idx
)
141 acse_ctx_oid_t aco
, *tmpaco
;
143 tmpaco
=(acse_ctx_oid_t
*)g_hash_table_lookup(acse_ctx_oid_table
, &aco
);
150 # endif /* NOT_NEEDED */
152 #include "packet-acse-fn.c"
156 * Dissect ACSE PDUs inside a PPDU.
159 dissect_acse(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void* data
)
165 struct SESSION_DATA_STRUCTURE
* session
;
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 0; /* no, it isn't a ACSE PDU */
178 /* do we have spdu type from the session dissector? */
181 REPORT_DISSECTOR_BUG("Can't get SPDU type from session dissector.");
186 session
= ( (struct SESSION_DATA_STRUCTURE
*)data
);
187 if(session
->spdu_type
== 0 ) {
189 REPORT_DISSECTOR_BUG(
190 wmem_strdup_printf(wmem_packet_scope(), "Wrong spdu type %x from session dissector.",session
->spdu_type
));
195 asn1_ctx
.private_data
= session
;
196 /* save parent_tree so subdissectors can create new top nodes */
197 top_tree
=parent_tree
;
199 /* ACSE has only AARQ,AARE,RLRQ,RLRE,ABRT type of pdu */
200 /* reject everything else */
201 /* data pdu is not ACSE pdu and has to go directly to app dissector */
202 switch(session
->spdu_type
){
203 case SES_CONNECTION_REQUEST
: /* AARQ */
204 case SES_CONNECTION_ACCEPT
: /* AARE */
205 case SES_REFUSE
: /* RLRE */
206 case SES_DISCONNECT
: /* RLRQ */
207 case SES_FINISH
: /* RLRE */
208 case SES_ABORT
: /* ABRT */
209 case CLSES_UNIT_DATA
: /* AARQ Connetctionless session */
211 case SES_DATA_TRANSFER
:
212 oid
=find_oid_by_pres_ctx_id(pinfo
, indir_ref
);
214 if(strcmp(oid
, ACSE_APDU_OID
) == 0){
215 proto_tree_add_text(parent_tree
, tvb
, offset
, -1,
216 "Invalid OID: %s", ACSE_APDU_OID
);
217 THROW(ReportedBoundsError
);
219 call_ber_oid_callback(oid
, tvb
, offset
, pinfo
, parent_tree
, NULL
);
221 proto_tree_add_expert(parent_tree
, pinfo
, &ei_acse_dissector_not_available
,
231 if(session
->spdu_type
== CLSES_UNIT_DATA
)
233 /* 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 */
243 item
= proto_tree_add_item(parent_tree
, proto_acse
, tvb
, 0, -1, ENC_NA
);
244 tree
= proto_item_add_subtree(item
, ett_acse
);
246 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ACSE");
247 col_clear(pinfo
->cinfo
, COL_INFO
);
250 /* we can't make any additional checking here */
251 /* postpone it before dissector will have more information */
252 while (tvb_reported_length_remaining(tvb
, offset
) > 0){
253 int old_offset
=offset
;
254 offset
= dissect_acse_ACSE_apdu(FALSE
, tvb
, offset
, &asn1_ctx
, tree
, -1);
255 if(offset
== old_offset
){
256 proto_tree_add_text(tree
, tvb
, offset
, -1,"Malformed packet");
262 return tvb_length(tvb
);
265 /*--- proto_register_acse ----------------------------------------------*/
266 void proto_register_acse(void) {
269 static hf_register_info hf
[] = {
270 #include "packet-acse-hfarr.c"
273 /* List of subtrees */
274 static gint
*ett
[] = {
276 #include "packet-acse-ettarr.c"
279 static ei_register_info ei
[] = {
280 { &ei_acse_dissector_not_available
, { "acse.dissector_not_available", PI_UNDECODED
, PI_WARN
, "Dissector is not available", EXPFILL
}},
283 expert_module_t
* expert_acse
;
285 /* Register protocol */
286 proto_acse
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
287 new_register_dissector("acse", dissect_acse
, proto_acse
);
289 /* Register connectionless protocol */
290 proto_clacse
= proto_register_protocol(CLPNAME
, CLPSNAME
, CLPFNAME
);
293 /* Register fields and subtrees */
294 proto_register_field_array(proto_acse
, hf
, array_length(hf
));
295 proto_register_subtree_array(ett
, array_length(ett
));
296 expert_acse
= expert_register_protocol(proto_acse
);
297 expert_register_field_array(expert_acse
, ei
, array_length(ei
));
301 /*--- proto_reg_handoff_acse -------------------------------------------*/
302 void proto_reg_handoff_acse(void) {
303 /*#include "packet-acse-dis-tab.c"*/
304 dissector_handle_t acse_handle
= find_dissector("acse");
306 oid_add_from_string("id-aCSE","2.2.3.1.1");
307 register_ber_oid_dissector_handle(ACSE_APDU_OID
, acse_handle
, proto_acse
, "id-as-acse");