TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / epan / dissectors / asn1 / idmp / packet-idmp-template.c
blobf78784d5b81ce79217baea30069b4ea22de9d10d
1 /* packet-idmp.c
2 * Routines for X.519 Internet Directly Mapped Procotol (IDMP) packet dissection
3 * Graeme Lunt 2010
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/prefs.h>
16 #include <epan/reassemble.h>
17 #include <epan/conversation.h>
18 #include <epan/oids.h>
19 #include <epan/asn1.h>
20 #include <epan/ipproto.h>
21 #include <epan/strutil.h>
23 #include <wsutil/str_util.h>
24 #include <wsutil/array.h>
26 #include "packet-tcp.h"
28 #include "packet-ber.h"
29 #include "packet-ros.h"
30 #include "packet-x509ce.h"
33 #define PNAME "X.519 Internet Directly Mapped Protocol"
34 #define PSNAME "IDMP"
35 #define PFNAME "idmp"
37 void proto_register_idmp(void);
38 void proto_reg_handoff_idm(void);
39 void register_idmp_protocol_info(const char *oid, const ros_info_t *rinfo, int proto _U_, const char *name);
41 static bool idmp_desegment = true;
42 #define IDMP_TCP_PORT 1102 /* made up for now - not IANA registered */
43 static bool idmp_reassemble = true;
44 static dissector_handle_t idmp_handle;
46 static proto_tree *top_tree;
47 static const char *protocolID;
48 static const char *saved_protocolID;
49 static uint32_t opcode = -1;
51 /* Initialize the protocol and registered fields */
52 int proto_idmp;
54 static int hf_idmp_version;
55 static int hf_idmp_final;
56 static int hf_idmp_length;
57 static int hf_idmp_PDU;
59 static reassembly_table idmp_reassembly_table;
61 static int hf_idmp_fragments;
62 static int hf_idmp_fragment;
63 static int hf_idmp_fragment_overlap;
64 static int hf_idmp_fragment_overlap_conflicts;
65 static int hf_idmp_fragment_multiple_tails;
66 static int hf_idmp_fragment_too_long_fragment;
67 static int hf_idmp_fragment_error;
68 static int hf_idmp_fragment_count;
69 static int hf_idmp_reassembled_in;
70 static int hf_idmp_reassembled_length;
71 static int hf_idmp_segment_data;
73 static int ett_idmp_fragment;
74 static int ett_idmp_fragments;
76 static const fragment_items idmp_frag_items = {
77 /* Fragment subtrees */
78 &ett_idmp_fragment,
79 &ett_idmp_fragments,
80 /* Fragment fields */
81 &hf_idmp_fragments,
82 &hf_idmp_fragment,
83 &hf_idmp_fragment_overlap,
84 &hf_idmp_fragment_overlap_conflicts,
85 &hf_idmp_fragment_multiple_tails,
86 &hf_idmp_fragment_too_long_fragment,
87 &hf_idmp_fragment_error,
88 &hf_idmp_fragment_count,
89 /* Reassembled in field */
90 &hf_idmp_reassembled_in,
91 /* Reassembled length field */
92 &hf_idmp_reassembled_length,
93 /* Reassembled data field */
94 NULL,
95 /* Tag */
96 "IDMP fragments"
100 static int call_idmp_oid_callback(tvbuff_t *tvb, int offset, packet_info *pinfo, int op, proto_tree *tree, struct SESSION_DATA_STRUCTURE *session)
102 if(session != NULL) {
104 /* XXX saved_protocolID should be part of session data */
105 if (!saved_protocolID) {
106 saved_protocolID = "[ unknown ]";
109 /* mimic ROS! */
110 session->ros_op = op;
111 offset = call_ros_oid_callback(saved_protocolID, tvb, offset, pinfo, tree, session);
114 return offset;
118 #include "packet-idmp-hf.c"
120 /* Initialize the subtree pointers */
121 static int ett_idmp;
122 #include "packet-idmp-ett.c"
124 #include "packet-idmp-fn.c"
126 void
127 register_idmp_protocol_info(const char *oid, const ros_info_t *rinfo, int proto _U_, const char *name)
129 /* just register with ROS for now */
130 register_ros_protocol_info(oid, rinfo, proto, name, false);
134 static int dissect_idmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
136 int offset = 0;
138 proto_item *item;
139 proto_tree *tree;
140 asn1_ctx_t asn1_ctx;
141 struct SESSION_DATA_STRUCTURE session;
142 bool idmp_final;
143 uint32_t idmp_length;
144 fragment_head *fd_head;
145 conversation_t *conv;
146 uint32_t dst_ref = 0;
148 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
150 conv = find_conversation_pinfo(pinfo, 0);
151 if (conv) {
152 /* Found a conversation, also use index for the generated dst_ref */
153 dst_ref = conv->conv_index;
156 /* save parent_tree so subdissectors can create new top nodes */
157 top_tree=parent_tree;
159 item = proto_tree_add_item(parent_tree, proto_idmp, tvb, 0, -1, ENC_NA);
160 tree = proto_item_add_subtree(item, ett_idmp);
162 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IDMP");
164 /* now check the segment fields */
166 proto_tree_add_item(tree, hf_idmp_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
167 proto_tree_add_item(tree, hf_idmp_final, tvb, offset, 1, ENC_BIG_ENDIAN);
168 idmp_final = tvb_get_uint8(tvb, offset); offset++;
169 proto_tree_add_item(tree, hf_idmp_length, tvb, offset, 4, ENC_BIG_ENDIAN);
170 idmp_length = tvb_get_ntohl(tvb, offset); offset += 4;
172 asn1_ctx.private_data = &session;
174 if(idmp_reassemble) {
176 pinfo->fragmented = !idmp_final;
178 col_append_fstr(pinfo->cinfo, COL_INFO, " [%sIDMP fragment, %u byte%s]",
179 idmp_final ? "Final " : "" ,
180 idmp_length, plurality(idmp_length, "", "s"));
182 fd_head = fragment_add_seq_next(&idmp_reassembly_table, tvb, offset,
183 pinfo, dst_ref, NULL,
184 idmp_length, !idmp_final);
186 if(fd_head && fd_head->next) {
187 proto_tree_add_item(tree, hf_idmp_segment_data, tvb, offset, (idmp_length) ? -1 : 0, ENC_NA);
189 if (idmp_final) {
190 /* This is the last segment */
191 tvb = process_reassembled_data (tvb, offset, pinfo,
192 "Reassembled IDMP", fd_head, &idmp_frag_items, NULL, tree);
193 offset = 0;
194 } else if (pinfo->num != fd_head->reassembled_in) {
195 /* Add a "Reassembled in" link if not reassembled in this frame */
196 proto_tree_add_uint (tree, hf_idmp_reassembled_in,
197 tvb, 0, 0, fd_head->reassembled_in);
201 } else {
202 if(!idmp_final) {
204 col_append_fstr(pinfo->cinfo, COL_INFO, " [IDMP fragment, %u byte%s, IDMP reassembly not enabled]",
205 idmp_length, plurality(idmp_length, "", "s"));
207 proto_tree_add_bytes_format_value(tree, hf_idmp_segment_data, tvb, offset, (idmp_length) ? -1 : 0,
208 NULL, "(IDMP reassembly not enabled)");
211 /* not reassembling - just dissect */
212 if(idmp_final) {
213 asn1_ctx.private_data = &session;
214 dissect_idmp_IDM_PDU(false, tvb, offset, &asn1_ctx, tree, hf_idmp_PDU);
217 return tvb_captured_length(tvb);
220 static unsigned get_idmp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
221 int offset, void *data _U_)
223 uint32_t len;
225 len = tvb_get_ntohl(tvb, offset + 2);
227 return len + 6;
230 static int dissect_idmp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
232 tcp_dissect_pdus(tvb, pinfo, parent_tree, idmp_desegment, 0, get_idmp_pdu_len, dissect_idmp, data);
233 return tvb_captured_length(tvb);
236 static void idmp_reassemble_cleanup(void)
238 protocolID = NULL; // packet scoped
239 saved_protocolID = NULL; // epan scoped copy of protocolID
240 opcode = -1;
243 /*--- proto_register_idmp -------------------------------------------*/
244 void proto_register_idmp(void)
246 /* List of fields */
247 static hf_register_info hf[] = {
248 { &hf_idmp_version,
249 { "version", "idmp.version",
250 FT_INT8, BASE_DEC, NULL, 0,
251 "idmp.INTEGER", HFILL }},
252 { &hf_idmp_final,
253 { "final", "idmp.final",
254 FT_BOOLEAN, BASE_NONE, NULL, 0,
255 "idmp.BOOLEAN", HFILL }},
256 { &hf_idmp_length,
257 { "length", "idmp.length",
258 FT_INT32, BASE_DEC, NULL, 0,
259 "idmp.INTEGER", HFILL }},
260 { &hf_idmp_PDU,
261 { "IDM-PDU", "idmp.pdu",
262 FT_UINT32, BASE_DEC, VALS(idmp_IDM_PDU_vals), 0,
263 "idmp.PDU", HFILL }},
264 /* Fragment entries */
265 { &hf_idmp_fragments,
266 { "IDMP fragments", "idmp.fragments", FT_NONE, BASE_NONE,
267 NULL, 0x00, NULL, HFILL } },
268 { &hf_idmp_fragment,
269 { "IDMP fragment", "idmp.fragment", FT_FRAMENUM, BASE_NONE,
270 NULL, 0x00, NULL, HFILL } },
271 { &hf_idmp_fragment_overlap,
272 { "IDMP fragment overlap", "idmp.fragment.overlap", FT_BOOLEAN,
273 BASE_NONE, NULL, 0x00, NULL, HFILL } },
274 { &hf_idmp_fragment_overlap_conflicts,
275 { "IDMP fragment overlapping with conflicting data",
276 "idmp.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE,
277 NULL, 0x00, NULL, HFILL } },
278 { &hf_idmp_fragment_multiple_tails,
279 { "IDMP has multiple tail fragments",
280 "idmp.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE,
281 NULL, 0x00, NULL, HFILL } },
282 { &hf_idmp_fragment_too_long_fragment,
283 { "IDMP fragment too long", "idmp.fragment.too_long_fragment",
284 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
285 { &hf_idmp_fragment_error,
286 { "IDMP defragmentation error", "idmp.fragment.error", FT_FRAMENUM,
287 BASE_NONE, NULL, 0x00, NULL, HFILL } },
288 { &hf_idmp_fragment_count,
289 { "IDMP fragment count", "idmp.fragment.count", FT_UINT32, BASE_DEC,
290 NULL, 0x00, NULL, HFILL } },
291 { &hf_idmp_reassembled_in,
292 { "Reassembled IDMP in frame", "idmp.reassembled.in", FT_FRAMENUM, BASE_NONE,
293 NULL, 0x00, "This IDMP packet is reassembled in this frame", HFILL } },
294 { &hf_idmp_reassembled_length,
295 { "Reassembled IDMP length", "idmp.reassembled.length", FT_UINT32, BASE_DEC,
296 NULL, 0x00, "The total length of the reassembled payload", HFILL } },
297 { &hf_idmp_segment_data,
298 { "IDMP segment data", "idmp.segment_data", FT_BYTES, BASE_NONE,
299 NULL, 0x00, NULL, HFILL } },
301 #include "packet-idmp-hfarr.c"
304 /* List of subtrees */
305 static int *ett[] = {
306 &ett_idmp,
307 &ett_idmp_fragment,
308 &ett_idmp_fragments,
309 #include "packet-idmp-ettarr.c"
311 module_t *idmp_module;
313 /* Register protocol */
314 proto_idmp = proto_register_protocol(PNAME, PSNAME, PFNAME);
316 /* Register fields and subtrees */
317 proto_register_field_array(proto_idmp, hf, array_length(hf));
318 proto_register_subtree_array(ett, array_length(ett));
320 idmp_handle = register_dissector("idmp", dissect_idmp_tcp, proto_idmp);
322 register_cleanup_routine (&idmp_reassemble_cleanup);
323 reassembly_table_register (&idmp_reassembly_table,
324 &addresses_reassembly_table_functions);
327 /* Register our configuration options for IDMP, particularly our port */
329 idmp_module = prefs_register_protocol_subtree("OSI/X.500", proto_idmp, NULL);
331 prefs_register_bool_preference(idmp_module, "desegment_idmp_messages",
332 "Reassemble IDMP messages spanning multiple TCP segments",
333 "Whether the IDMP dissector should reassemble messages spanning multiple TCP segments."
334 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
335 &idmp_desegment);
337 prefs_register_bool_preference(idmp_module, "reassemble",
338 "Reassemble segmented IDMP datagrams",
339 "Whether segmented IDMP datagrams should be reassembled."
340 " To use this option, you must also enable"
341 " \"Allow subdissectors to reassemble TCP streams\""
342 " in the TCP protocol settings.", &idmp_reassemble);
346 /*--- proto_reg_handoff_idm --- */
347 void proto_reg_handoff_idm(void) {
348 dissector_add_uint_with_preference("tcp.port", IDMP_TCP_PORT, idmp_handle);