2 * Routines for decoding Microsoft Cluster Route Control Protocol (MSRCP)
3 * Copyright 2022, Will Aftring <william.aftring@outlook.com>
5 * SPDX-License-Identifier: MIT
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
16 #include <wsutil/array.h>
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/conversation.h>
21 void proto_register_msrcp(void);
22 void proto_reg_handoff_msrcp(void);
24 static dissector_handle_t msrcp_handle
;
26 #define MSRCP_PORT 3343
27 #define MSRCP_REQUEST 0
28 #define MSRCP_RESPONSE 1
29 #define MSRCP_OFFSET_TYPE 6
30 #define MSRCP_OFFSET_SEQ 12
33 static const value_string packettypenames
[] = {
39 static const value_string headertypenames
[] = {
40 {0, "MSRCP EXTENSION NONE",},
41 {1, "MSRCP IPv4 Pair"},
42 {2, "MSRCP IPv6 Pair"},
43 {3, "MSRCP Signature"},
48 typedef struct _msrcp_conv_info_t
{
52 typedef struct _msrcp_transaction_t
{
58 } msrcp_transaction_t
;
60 static int proto_msrcp
;
61 static int hf_msrcp_id
;
62 static int hf_msrcp_type
;
63 static int hf_msrcp_vers
;
64 static int hf_msrcp_reserved
;
65 static int hf_msrcp_next_header
;
66 static int hf_msrcp_len
;
67 static int hf_msrcp_seq
;
68 static int hf_msrcp_response_in
;
69 static int hf_msrcp_response_to
;
70 static int hf_msrcp_ext_header
;
71 static int hf_msrcp_ext_next_header
;
72 static int hf_msrcp_ext_len
;
73 static int hf_msrcp_ext_res
;
76 static int ett_msrcp_nxt
;
78 static expert_field ei_msrcp_no_resp
;
80 // Handles for subparsing
81 static dissector_handle_t eth_handle
;
84 dissect_msrcp(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
103 unsigned tree_offset
= 0;
105 proto_tree
* msrcp_tree
, * nxt_tree
;
106 proto_item
* ti
, * nxt_ti
;
111 // variables for our expert analysis
112 conversation_t
* conv
= NULL
;
113 msrcp_conv_info_t
* msrcp_info
= NULL
;
114 msrcp_transaction_t
* msrcp_trans
= NULL
;
115 wmem_tree_key_t key
[3];
117 type
= tvb_get_uint8(tvb
, MSRCP_OFFSET_TYPE
);
118 seq
= tvb_get_uint32(tvb
, MSRCP_OFFSET_SEQ
, ENC_LITTLE_ENDIAN
);
120 conv
= find_or_create_conversation(pinfo
);
121 msrcp_info
= (msrcp_conv_info_t
*)conversation_get_proto_data(conv
, proto_msrcp
);
124 msrcp_info
= wmem_new(wmem_file_scope(), msrcp_conv_info_t
);
125 msrcp_info
->pdus
= wmem_tree_new(wmem_file_scope());
126 conversation_add_proto_data(conv
, proto_msrcp
, msrcp_info
);
132 key
[1].key
= &pinfo
->num
;
135 if ((type
== MSRCP_REQUEST
) || (type
== MSRCP_RESPONSE
))
137 if (!pinfo
->fd
->visited
)
139 if (type
== MSRCP_REQUEST
)
141 msrcp_trans
= wmem_new(wmem_file_scope(), msrcp_transaction_t
);
142 msrcp_trans
->req_frame
= pinfo
->num
;
143 msrcp_trans
->rep_frame
= 0;
144 msrcp_trans
->req_time
= pinfo
->abs_ts
;
145 msrcp_trans
->seq
= seq
;
146 msrcp_trans
->matched
= false;
147 wmem_tree_insert32_array(msrcp_info
->pdus
, key
, (void*)msrcp_trans
);
151 msrcp_trans
= (msrcp_transaction_t
*)wmem_tree_lookup32_array_le(msrcp_info
->pdus
, key
);
154 if (msrcp_trans
->seq
!= seq
)
158 else if (msrcp_trans
->rep_frame
== 0)
160 msrcp_trans
->rep_frame
= pinfo
->num
;
161 msrcp_trans
->matched
= true;
168 msrcp_trans
= (msrcp_transaction_t
*)wmem_tree_lookup32_array_le(msrcp_info
->pdus
, key
);
171 if (msrcp_trans
->seq
!= seq
)
175 else if ((!(type
== MSRCP_RESPONSE
)) && (msrcp_trans
->req_frame
!= pinfo
->num
))
177 msrcp_transaction_t
* retrans_msrcp
= wmem_new(pinfo
->pool
, msrcp_transaction_t
);
178 retrans_msrcp
->req_frame
= msrcp_trans
->req_frame
;
179 retrans_msrcp
->rep_frame
= 0;
180 retrans_msrcp
->req_time
= pinfo
->abs_ts
;
181 msrcp_trans
= retrans_msrcp
;
187 msrcp_trans
= wmem_new(pinfo
->pool
, msrcp_transaction_t
);
188 msrcp_trans
->req_frame
= 0;
189 msrcp_trans
->rep_frame
= 0;
190 msrcp_trans
->req_time
= pinfo
->abs_ts
;
191 msrcp_trans
->matched
= false;
196 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MSRCP");
197 col_clear(pinfo
->cinfo
, COL_INFO
);
198 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s ID %d (0x%X)",
199 val_to_str_const(type
, packettypenames
, "MSRCP"), seq
, seq
);
202 ti
= proto_tree_add_item(tree
, proto_msrcp
, tvb
, 0, -1, ENC_BIG_ENDIAN
);
203 proto_item_append_text(ti
, "Type %s",
204 val_to_str_const(type
, packettypenames
, "MSRCP"));
205 msrcp_tree
= proto_item_add_subtree(ti
, ett_msrcp
);
207 if (type
== MSRCP_REQUEST
|| type
== MSRCP_RESPONSE
)
210 proto_tree_add_item(msrcp_tree
, hf_msrcp_id
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
212 proto_tree_add_item(msrcp_tree
, hf_msrcp_vers
, tvb
, tree_offset
, 1, ENC_LITTLE_ENDIAN
);
214 proto_tree_add_item(msrcp_tree
, hf_msrcp_reserved
, tvb
, tree_offset
, 1, ENC_LITTLE_ENDIAN
);
216 proto_tree_add_item(msrcp_tree
, hf_msrcp_type
, tvb
, tree_offset
, 2, ENC_LITTLE_ENDIAN
);
218 proto_tree_add_item(msrcp_tree
, hf_msrcp_next_header
, tvb
, tree_offset
, 2, ENC_LITTLE_ENDIAN
);
220 proto_tree_add_item(msrcp_tree
, hf_msrcp_len
, tvb
, tree_offset
, 2, ENC_LITTLE_ENDIAN
);
222 it
= proto_tree_add_item(msrcp_tree
, hf_msrcp_seq
, tvb
, tree_offset
, 4, ENC_LITTLE_ENDIAN
);
225 if (msrcp_trans
->matched
)
227 if ((msrcp_trans
->req_frame
) && (type
== MSRCP_RESPONSE
))
229 it
= proto_tree_add_uint(msrcp_tree
, hf_msrcp_response_to
, tvb
, 0, 0, msrcp_trans
->req_frame
);
230 proto_item_set_generated(it
);
233 else if ((msrcp_trans
->rep_frame
) && (type
== MSRCP_REQUEST
))
235 it
= proto_tree_add_uint(msrcp_tree
, hf_msrcp_response_in
, tvb
, 0, 0, msrcp_trans
->rep_frame
);
236 proto_item_set_generated(it
);
241 expert_add_info(pinfo
, it
, &ei_msrcp_no_resp
);
242 col_prepend_fence_fstr(pinfo
->cinfo
, COL_INFO
, "[Missing MSRCP Response]");
245 nxt_ti
= proto_tree_add_item(msrcp_tree
, hf_msrcp_ext_header
, tvb
, 0, 0, ENC_ASCII
);
246 nxt_tree
= proto_item_add_subtree(nxt_ti
, ett_msrcp_nxt
);
247 proto_tree_add_item(nxt_tree
, hf_msrcp_ext_next_header
, tvb
, tree_offset
, 2, ENC_LITTLE_ENDIAN
);
249 proto_tree_add_item(nxt_tree
, hf_msrcp_ext_len
, tvb
, tree_offset
, 2, ENC_LITTLE_ENDIAN
);
251 proto_tree_add_item(nxt_tree
, hf_msrcp_ext_res
, tvb
, tree_offset
, 4, ENC_LITTLE_ENDIAN
);
256 next_tvb
= tvb_new_subset_remaining(tvb
, 0);
257 call_dissector(eth_handle
, next_tvb
, pinfo
, msrcp_tree
);
260 return tvb_captured_length(tvb
);
265 proto_register_msrcp(void)
267 expert_module_t
* expert_msrcp
;
269 static hf_register_info hf
[] = {
271 { "MSRCP ID", "msrcp.id",
272 FT_UINT32
, BASE_DEC_HEX
,
277 { "Version", "msrcp.vers",
282 { &hf_msrcp_reserved
,
283 { "Reserved", "msrcp.reserved",
289 { "MSRCP Type", "msrcp.type",
291 VALS(packettypenames
), 0x0,
294 { &hf_msrcp_next_header
,
295 { "Next Header", "msrcp.nxt_header",
297 VALS(headertypenames
), 0x0,
301 { "Total Length", "msrcp.len",
307 { "Sequence Number", "msrcp.seq",
308 FT_UINT32
, BASE_DEC_HEX
,
312 { &hf_msrcp_response_in
,
313 { "Response In", "msrcp.response_in",
314 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
315 "The response to this MSRCP request is in frame", HFILL
}
317 { &hf_msrcp_response_to
,
318 { "Request In", "msrcp.response_to",
319 FT_FRAMENUM
,BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
320 "This is a response to an MSRCP request in frame", HFILL
}
322 { &hf_msrcp_ext_header
,
323 { "Extension Header", "msrcp.ext",
328 { &hf_msrcp_ext_next_header
,
329 { "Next Header", "msrcp.ext_nxt_header",
331 VALS(headertypenames
), 0x0, NULL
, HFILL
}
334 { "Length", "msrcp.ext_len",
336 NULL
, 0x0, NULL
, HFILL
}
339 { "Reserved", "msrcp.nxt_res",
346 static int* ett
[] = {
351 static ei_register_info ei
[] = {
354 { "msrcp.no_resp", PI_SEQUENCE
, PI_WARN
,
355 "MSRCP Response not found", EXPFILL
}
359 proto_msrcp
= proto_register_protocol("MSRCP Protocol", "MSRCP", "msrcp");
361 proto_register_field_array(proto_msrcp
, hf
, array_length(hf
));
362 proto_register_subtree_array(ett
, array_length(ett
));
363 expert_msrcp
= expert_register_protocol(proto_msrcp
);
364 expert_register_field_array(expert_msrcp
, ei
, array_length(ei
));
366 msrcp_handle
= register_dissector("msrcp", dissect_msrcp
, proto_msrcp
);
370 proto_reg_handoff_msrcp(void)
372 eth_handle
= find_dissector_add_dependency("eth_withoutfcs", proto_msrcp
);
373 dissector_add_uint("udp.port", MSRCP_PORT
, msrcp_handle
);