Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-msrcp.c
blob06b8bb40ace1b5a675e8e6440a363ec8fe50b7c5
1 /* packet-msrcp.c
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
14 #include "config.h"
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[] = {
34 {0, "REQUEST" },
35 {1, "RESPONSE" },
36 {0, NULL}
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"},
44 {4, "MSRCP Maximum"},
45 {0, NULL}
48 typedef struct _msrcp_conv_info_t {
49 wmem_tree_t* pdus;
50 } msrcp_conv_info_t;
52 typedef struct _msrcp_transaction_t {
53 uint32_t req_frame;
54 uint32_t rep_frame;
55 nstime_t req_time;
56 uint32_t seq;
57 bool matched;
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;
75 static int ett_msrcp;
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;
83 static int
84 dissect_msrcp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
88 Rough Packet layout:
89 Identifier: 4 bytes
90 Version: 1 byte
91 Reserved: 1 byte
92 Type: 2 bytes
93 NextHeader: 2 bytes
94 Total Length: 2 bytes
95 SeqNum: 4 bytes
96 ExtHeader: 40 bytes
97 NextHeader: 2 bytes
98 Length: 2 bytes
99 Reserved: 4 bytes
100 SrcAddr: 16 bytes
101 DstAddr: 16 bytes
103 unsigned tree_offset = 0;
105 proto_tree* msrcp_tree, * nxt_tree;
106 proto_item* ti, * nxt_ti;
107 tvbuff_t* next_tvb;
108 uint32_t seq;
109 uint16_t type;
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);
122 if (!msrcp_info)
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);
129 key[0].length = 1;
130 key[0].key = &seq;
131 key[1].length = 1;
132 key[1].key = &pinfo->num;
133 key[2].length = 0;
134 key[2].key = NULL;
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);
149 else
151 msrcp_trans = (msrcp_transaction_t*)wmem_tree_lookup32_array_le(msrcp_info->pdus, key);
152 if (msrcp_trans)
154 if (msrcp_trans->seq != seq)
156 msrcp_trans = NULL;
158 else if (msrcp_trans->rep_frame == 0)
160 msrcp_trans->rep_frame = pinfo->num;
161 msrcp_trans->matched = true;
166 else
168 msrcp_trans = (msrcp_transaction_t*)wmem_tree_lookup32_array_le(msrcp_info->pdus, key);
169 if (msrcp_trans)
171 if (msrcp_trans->seq != seq)
173 msrcp_trans = NULL;
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;
185 if (!msrcp_trans)
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)
209 proto_item* it;
210 proto_tree_add_item(msrcp_tree, hf_msrcp_id, tvb, 0, 4, ENC_BIG_ENDIAN);
211 tree_offset += 4;
212 proto_tree_add_item(msrcp_tree, hf_msrcp_vers, tvb, tree_offset, 1, ENC_LITTLE_ENDIAN);
213 tree_offset += 1;
214 proto_tree_add_item(msrcp_tree, hf_msrcp_reserved, tvb, tree_offset, 1, ENC_LITTLE_ENDIAN);
215 tree_offset += 1;
216 proto_tree_add_item(msrcp_tree, hf_msrcp_type, tvb, tree_offset, 2, ENC_LITTLE_ENDIAN);
217 tree_offset += 2;
218 proto_tree_add_item(msrcp_tree, hf_msrcp_next_header, tvb, tree_offset, 2, ENC_LITTLE_ENDIAN);
219 tree_offset += 2;
220 proto_tree_add_item(msrcp_tree, hf_msrcp_len, tvb, tree_offset, 2, ENC_LITTLE_ENDIAN);
221 tree_offset += 2;
222 it = proto_tree_add_item(msrcp_tree, hf_msrcp_seq, tvb, tree_offset, 4, ENC_LITTLE_ENDIAN);
223 tree_offset += 4;
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);
239 else
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);
248 tree_offset += 2;
249 proto_tree_add_item(nxt_tree, hf_msrcp_ext_len, tvb, tree_offset, 2, ENC_LITTLE_ENDIAN);
250 tree_offset += 2;
251 proto_tree_add_item(nxt_tree, hf_msrcp_ext_res, tvb, tree_offset, 4, ENC_LITTLE_ENDIAN);
254 else
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);
264 void
265 proto_register_msrcp(void)
267 expert_module_t* expert_msrcp;
269 static hf_register_info hf[] = {
270 { &hf_msrcp_id,
271 { "MSRCP ID", "msrcp.id",
272 FT_UINT32, BASE_DEC_HEX,
273 NULL, 0x0,
274 NULL, HFILL},
276 { &hf_msrcp_vers,
277 { "Version", "msrcp.vers",
278 FT_UINT8, BASE_DEC,
279 NULL, 0x0,
280 NULL, HFILL}
282 { &hf_msrcp_reserved,
283 { "Reserved", "msrcp.reserved",
284 FT_UINT8, BASE_DEC,
285 NULL, 0x0,
286 NULL, HFILL}
288 { &hf_msrcp_type,
289 { "MSRCP Type", "msrcp.type",
290 FT_UINT16, BASE_DEC,
291 VALS(packettypenames), 0x0,
292 NULL, HFILL}
294 { &hf_msrcp_next_header,
295 { "Next Header", "msrcp.nxt_header",
296 FT_UINT16, BASE_DEC,
297 VALS(headertypenames), 0x0,
298 NULL, HFILL}
300 { &hf_msrcp_len,
301 { "Total Length", "msrcp.len",
302 FT_UINT16, BASE_DEC,
303 NULL, 0x0,
304 NULL, HFILL}
306 { &hf_msrcp_seq,
307 { "Sequence Number", "msrcp.seq",
308 FT_UINT32, BASE_DEC_HEX,
309 NULL, 0x0,
310 NULL, HFILL}
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",
324 FT_NONE, BASE_NONE,
325 NULL, 0x0,
326 NULL, HFILL}
328 { &hf_msrcp_ext_next_header,
329 { "Next Header", "msrcp.ext_nxt_header",
330 FT_UINT16, BASE_DEC,
331 VALS(headertypenames), 0x0, NULL, HFILL}
333 { &hf_msrcp_ext_len,
334 { "Length", "msrcp.ext_len",
335 FT_UINT16, BASE_DEC,
336 NULL, 0x0, NULL, HFILL}
338 { &hf_msrcp_ext_res,
339 { "Reserved", "msrcp.nxt_res",
340 FT_UINT32, BASE_HEX,
341 NULL, 0x0,
342 NULL, HFILL}
346 static int* ett[] = {
347 &ett_msrcp,
348 &ett_msrcp_nxt
351 static ei_register_info ei[] = {
353 &ei_msrcp_no_resp,
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);
369 void
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);