2 * Routines for X.519 Internet Directly Mapped Procotol (IDMP) packet dissection
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
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"
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 */
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 */
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 */
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 ]";
110 session
->ros_op
= op
;
111 offset
= call_ros_oid_callback(saved_protocolID
, tvb
, offset
, pinfo
, tree
, session
);
118 #include "packet-idmp-hf.c"
120 /* Initialize the subtree pointers */
122 #include "packet-idmp-ett.c"
124 #include "packet-idmp-fn.c"
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_
)
141 struct SESSION_DATA_STRUCTURE session
;
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);
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
);
190 /* This is the last segment */
191 tvb
= process_reassembled_data (tvb
, offset
, pinfo
,
192 "Reassembled IDMP", fd_head
, &idmp_frag_items
, NULL
, tree
);
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
);
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 */
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_
)
225 len
= tvb_get_ntohl(tvb
, offset
+ 2);
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
243 /*--- proto_register_idmp -------------------------------------------*/
244 void proto_register_idmp(void)
247 static hf_register_info hf
[] = {
249 { "version", "idmp.version",
250 FT_INT8
, BASE_DEC
, NULL
, 0,
251 "idmp.INTEGER", HFILL
}},
253 { "final", "idmp.final",
254 FT_BOOLEAN
, BASE_NONE
, NULL
, 0,
255 "idmp.BOOLEAN", HFILL
}},
257 { "length", "idmp.length",
258 FT_INT32
, BASE_DEC
, NULL
, 0,
259 "idmp.INTEGER", HFILL
}},
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
} },
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
[] = {
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.",
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
);