Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / asn1 / rtse / packet-rtse-template.c
blob33414731ecc9fb1f96235957f8338eaca6b4e8da
1 /* packet-rtse-template.c
2 * Routines for RTSE packet dissection
3 * Graeme Lunt 2005
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/conversation.h>
16 #include <epan/prefs.h>
17 #include <epan/reassemble.h>
18 #include <epan/asn1.h>
19 #include <epan/expert.h>
21 #include <wsutil/array.h>
22 #include <wsutil/str_util.h>
24 #include "packet-ber.h"
25 #include "packet-pres.h"
26 #include "packet-acse.h"
27 #include "packet-ros.h"
28 #include "packet-rtse.h"
30 #define PNAME "X.228 OSI Reliable Transfer Service"
31 #define PSNAME "RTSE"
32 #define PFNAME "rtse"
34 void proto_register_rtse(void);
35 void proto_reg_handoff_rtse(void);
37 /* Initialize the protocol and registered fields */
38 static int proto_rtse;
40 static bool open_request=false;
41 static uint32_t app_proto=0;
43 static proto_tree *top_tree;
45 /* Preferences */
46 static bool rtse_reassemble = true;
48 #include "packet-rtse-hf.c"
50 /* Initialize the subtree pointers */
51 static int ett_rtse;
52 #include "packet-rtse-ett.c"
54 static expert_field ei_rtse_dissector_oid_not_implemented;
55 static expert_field ei_rtse_unknown_rtse_pdu;
56 static expert_field ei_rtse_abstract_syntax;
58 static dissector_table_t rtse_oid_dissector_table;
59 static dissector_handle_t rtse_handle;
60 static int ett_rtse_unknown;
62 static reassembly_table rtse_reassembly_table;
64 static int hf_rtse_segment_data;
65 static int hf_rtse_fragments;
66 static int hf_rtse_fragment;
67 static int hf_rtse_fragment_overlap;
68 static int hf_rtse_fragment_overlap_conflicts;
69 static int hf_rtse_fragment_multiple_tails;
70 static int hf_rtse_fragment_too_long_fragment;
71 static int hf_rtse_fragment_error;
72 static int hf_rtse_fragment_count;
73 static int hf_rtse_reassembled_in;
74 static int hf_rtse_reassembled_length;
76 static int ett_rtse_fragment;
77 static int ett_rtse_fragments;
79 static const fragment_items rtse_frag_items = {
80 /* Fragment subtrees */
81 &ett_rtse_fragment,
82 &ett_rtse_fragments,
83 /* Fragment fields */
84 &hf_rtse_fragments,
85 &hf_rtse_fragment,
86 &hf_rtse_fragment_overlap,
87 &hf_rtse_fragment_overlap_conflicts,
88 &hf_rtse_fragment_multiple_tails,
89 &hf_rtse_fragment_too_long_fragment,
90 &hf_rtse_fragment_error,
91 &hf_rtse_fragment_count,
92 /* Reassembled in field */
93 &hf_rtse_reassembled_in,
94 /* Reassembled length field */
95 &hf_rtse_reassembled_length,
96 /* Reassembled data field */
97 NULL,
98 /* Tag */
99 "RTSE fragments"
102 void
103 register_rtse_oid_dissector_handle(const char *oid, dissector_handle_t dissector, int proto, const char *name, bool uses_ros)
105 /* XXX: Note that this fcn is called from proto_reg_handoff in *other* dissectors ... */
107 static dissector_handle_t ros_handle = NULL;
109 if (ros_handle == NULL)
110 ros_handle = find_dissector("ros");
112 /* register RTSE with the BER (ACSE) */
113 register_ber_oid_dissector_handle(oid, rtse_handle, proto, name);
115 if (uses_ros) {
116 /* make sure we call ROS ... */
117 dissector_add_string("rtse.oid", oid, ros_handle);
119 /* and then tell ROS how to dissect the AS*/
120 if (dissector != NULL)
121 register_ros_oid_dissector_handle(oid, dissector, proto, name, true);
123 } else {
124 /* otherwise we just remember how to dissect the AS */
125 dissector_add_string("rtse.oid", oid, dissector);
129 static int
130 call_rtse_oid_callback(const char *oid, tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, void* data)
132 tvbuff_t *next_tvb;
133 int len;
135 next_tvb = tvb_new_subset_remaining(tvb, offset);
137 if ((len = dissector_try_string_with_data(rtse_oid_dissector_table, oid, next_tvb, pinfo, tree, true, data)) == 0) {
138 proto_item *item;
139 proto_tree *next_tree;
141 next_tree = proto_tree_add_subtree_format(tree, next_tvb, 0, -1, ett_rtse_unknown, &item,
142 "RTSE: Dissector for OID:%s not implemented. Contact Wireshark developers if you want this supported", oid);
144 expert_add_info_format(pinfo, item, &ei_rtse_dissector_oid_not_implemented,
145 "RTSE: Dissector for OID %s not implemented", oid);
146 len = dissect_unknown_ber(pinfo, next_tvb, offset, next_tree);
149 offset += len;
151 return offset;
154 static int
155 call_rtse_external_type_callback(bool implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
157 const char *oid = NULL;
159 if (actx->external.indirect_ref_present) {
161 oid = (const char *)find_oid_by_pres_ctx_id(actx->pinfo, actx->external.indirect_reference);
163 if (!oid)
164 proto_tree_add_expert_format(tree, actx->pinfo, &ei_rtse_abstract_syntax, tvb, offset, tvb_captured_length_remaining(tvb, offset),
165 "Unable to determine abstract syntax for indirect reference: %d.", actx->external.indirect_reference);
166 } else if (actx->external.direct_ref_present) {
167 oid = actx->external.direct_reference;
170 if (oid)
171 offset = call_rtse_oid_callback(oid, tvb, offset, actx->pinfo, top_tree ? top_tree : tree, actx->private_data);
173 return offset;
176 #include "packet-rtse-fn.c"
179 * Dissect RTSE PDUs inside a PPDU.
181 static int
182 dissect_rtse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
184 int offset = 0;
185 int old_offset;
186 proto_item *item;
187 proto_tree *tree;
188 proto_tree *next_tree=NULL;
189 tvbuff_t *next_tvb = NULL;
190 tvbuff_t *data_tvb = NULL;
191 fragment_head *frag_msg = NULL;
192 uint32_t fragment_length;
193 uint32_t rtse_id = 0;
194 bool data_handled = false;
195 struct SESSION_DATA_STRUCTURE* session;
196 conversation_t *conversation = NULL;
197 asn1_ctx_t asn1_ctx;
198 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
200 /* do we have application context from the acse dissector? */
201 if (data == NULL)
202 return 0;
203 session = (struct SESSION_DATA_STRUCTURE*)data;
205 /* save parent_tree so subdissectors can create new top nodes */
206 top_tree=parent_tree;
208 asn1_ctx.private_data = session;
210 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSE");
211 col_clear(pinfo->cinfo, COL_INFO);
213 if (rtse_reassemble &&
214 ((session->spdu_type == SES_DATA_TRANSFER) ||
215 (session->spdu_type == SES_MAJOR_SYNC_POINT)))
217 /* Use conversation index as fragment id */
218 conversation = find_conversation_pinfo(pinfo, 0);
219 if (conversation != NULL) {
220 rtse_id = conversation->conv_index;
222 session->rtse_reassemble = true;
224 if (rtse_reassemble && session->spdu_type == SES_MAJOR_SYNC_POINT) {
225 frag_msg = fragment_end_seq_next (&rtse_reassembly_table,
226 pinfo, rtse_id, NULL);
227 next_tvb = process_reassembled_data (tvb, offset, pinfo, "Reassembled RTSE",
228 frag_msg, &rtse_frag_items, NULL, parent_tree);
231 item = proto_tree_add_item(parent_tree, proto_rtse, next_tvb ? next_tvb : tvb, 0, -1, ENC_NA);
232 tree = proto_item_add_subtree(item, ett_rtse);
234 if (rtse_reassemble && session->spdu_type == SES_DATA_TRANSFER) {
235 /* strip off the OCTET STRING encoding - including any CONSTRUCTED OCTET STRING */
236 dissect_ber_octet_string(false, &asn1_ctx, tree, tvb, offset, hf_rtse_segment_data, &data_tvb);
238 if (data_tvb) {
239 fragment_length = tvb_captured_length_remaining (data_tvb, 0);
240 proto_item_append_text(asn1_ctx.created_item, " (%u byte%s)", fragment_length,
241 plurality(fragment_length, "", "s"));
242 frag_msg = fragment_add_seq_next (&rtse_reassembly_table,
243 data_tvb, 0, pinfo,
244 rtse_id, NULL,
245 fragment_length, true);
246 if (frag_msg && pinfo->num != frag_msg->reassembled_in) {
247 /* Add a "Reassembled in" link if not reassembled in this frame */
248 proto_tree_add_uint (tree, *(rtse_frag_items.hf_reassembled_in),
249 data_tvb, 0, 0, frag_msg->reassembled_in);
251 pinfo->fragmented = true;
252 data_handled = true;
253 } else {
254 fragment_length = tvb_captured_length_remaining (tvb, offset);
257 col_append_fstr(pinfo->cinfo, COL_INFO, "[RTSE fragment, %u byte%s]",
258 fragment_length, plurality(fragment_length, "", "s"));
259 } else if (rtse_reassemble && session->spdu_type == SES_MAJOR_SYNC_POINT) {
260 if (next_tvb) {
261 /* ROS won't do this for us */
262 session->ros_op = (ROS_OP_INVOKE | ROS_OP_ARGUMENT);
263 /*offset=*/dissect_ber_external_type(false, tree, next_tvb, 0, &asn1_ctx, -1, call_rtse_external_type_callback);
264 top_tree = NULL;
265 /* Return other than 0 to indicate that we handled this packet */
266 return 1;
267 } else {
268 offset = tvb_captured_length (tvb);
270 pinfo->fragmented = false;
271 data_handled = true;
274 if (!data_handled) {
275 while (tvb_reported_length_remaining(tvb, offset) > 0) {
276 old_offset=offset;
277 offset=dissect_rtse_RTSE_apdus(true, tvb, offset, &asn1_ctx, tree, -1);
278 if (offset == old_offset) {
279 next_tree = proto_tree_add_subtree(tree, tvb, offset, -1,
280 ett_rtse_unknown, &item, "Unknown RTSE PDU");
281 expert_add_info (pinfo, item, &ei_rtse_unknown_rtse_pdu);
282 dissect_unknown_ber(pinfo, tvb, offset, next_tree);
283 break;
288 top_tree = NULL;
289 return tvb_captured_length(tvb);
292 /*--- proto_register_rtse -------------------------------------------*/
293 void proto_register_rtse(void) {
295 /* List of fields */
296 static hf_register_info hf[] =
298 /* Fragment entries */
299 { &hf_rtse_segment_data,
300 { "RTSE segment data", "rtse.segment", FT_NONE, BASE_NONE,
301 NULL, 0x00, NULL, HFILL } },
302 { &hf_rtse_fragments,
303 { "RTSE fragments", "rtse.fragments", FT_NONE, BASE_NONE,
304 NULL, 0x00, NULL, HFILL } },
305 { &hf_rtse_fragment,
306 { "RTSE fragment", "rtse.fragment", FT_FRAMENUM, BASE_NONE,
307 NULL, 0x00, NULL, HFILL } },
308 { &hf_rtse_fragment_overlap,
309 { "RTSE fragment overlap", "rtse.fragment.overlap", FT_BOOLEAN,
310 BASE_NONE, NULL, 0x0, NULL, HFILL } },
311 { &hf_rtse_fragment_overlap_conflicts,
312 { "RTSE fragment overlapping with conflicting data",
313 "rtse.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE,
314 NULL, 0x0, NULL, HFILL } },
315 { &hf_rtse_fragment_multiple_tails,
316 { "RTSE has multiple tail fragments",
317 "rtse.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE,
318 NULL, 0x0, NULL, HFILL } },
319 { &hf_rtse_fragment_too_long_fragment,
320 { "RTSE fragment too long", "rtse.fragment.too_long_fragment",
321 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
322 { &hf_rtse_fragment_error,
323 { "RTSE defragmentation error", "rtse.fragment.error", FT_FRAMENUM,
324 BASE_NONE, NULL, 0x00, NULL, HFILL } },
325 { &hf_rtse_fragment_count,
326 { "RTSE fragment count", "rtse.fragment.count", FT_UINT32, BASE_DEC,
327 NULL, 0x00, NULL, HFILL } },
328 { &hf_rtse_reassembled_in,
329 { "Reassembled RTSE in frame", "rtse.reassembled.in", FT_FRAMENUM, BASE_NONE,
330 NULL, 0x00, "This RTSE packet is reassembled in this frame", HFILL } },
331 { &hf_rtse_reassembled_length,
332 { "Reassembled RTSE length", "rtse.reassembled.length", FT_UINT32, BASE_DEC,
333 NULL, 0x00, "The total length of the reassembled payload", HFILL } },
335 #include "packet-rtse-hfarr.c"
338 /* List of subtrees */
339 static int *ett[] = {
340 &ett_rtse,
341 &ett_rtse_unknown,
342 &ett_rtse_fragment,
343 &ett_rtse_fragments,
344 #include "packet-rtse-ettarr.c"
347 static ei_register_info ei[] = {
348 { &ei_rtse_dissector_oid_not_implemented, { "rtse.dissector_oid_not_implemented", PI_UNDECODED, PI_WARN, "RTSE: Dissector for OID not implemented", EXPFILL }},
349 { &ei_rtse_unknown_rtse_pdu, { "rtse.unknown_rtse_pdu", PI_UNDECODED, PI_WARN, "Unknown RTSE PDU", EXPFILL }},
350 { &ei_rtse_abstract_syntax, { "rtse.bad_abstract_syntax", PI_PROTOCOL, PI_WARN, "Unable to determine abstract syntax for indirect reference", EXPFILL }},
353 expert_module_t* expert_rtse;
354 module_t *rtse_module;
356 /* Register protocol */
357 proto_rtse = proto_register_protocol(PNAME, PSNAME, PFNAME);
358 rtse_handle = register_dissector("rtse", dissect_rtse, proto_rtse);
359 /* Register fields and subtrees */
360 proto_register_field_array(proto_rtse, hf, array_length(hf));
361 proto_register_subtree_array(ett, array_length(ett));
362 expert_rtse = expert_register_protocol(proto_rtse);
363 expert_register_field_array(expert_rtse, ei, array_length(ei));
365 reassembly_table_register (&rtse_reassembly_table,
366 &addresses_reassembly_table_functions);
368 rtse_module = prefs_register_protocol_subtree("OSI", proto_rtse, NULL);
370 prefs_register_bool_preference(rtse_module, "reassemble",
371 "Reassemble segmented RTSE datagrams",
372 "Whether segmented RTSE datagrams should be reassembled."
373 " To use this option, you must also enable"
374 " \"Allow subdissectors to reassemble TCP streams\""
375 " in the TCP protocol settings.", &rtse_reassemble);
377 rtse_oid_dissector_table = register_dissector_table("rtse.oid", "RTSE OID Dissectors", proto_rtse, FT_STRING, STRING_CASE_SENSITIVE);
381 /*--- proto_reg_handoff_rtse --- */
382 void proto_reg_handoff_rtse(void) {
388 * Editor modelines - https://www.wireshark.org/tools/modelines.html
390 * Local variables:
391 * c-basic-offset: 4
392 * tab-width: 8
393 * indent-tabs-mode: nil
394 * End:
396 * vi: set shiftwidth=4 tabstop=8 expandtab:
397 * :indentSize=4:tabSize=8:noTabs=true: