Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-pdc.c
blob422bc4c3f13021729590d7cd7edee717fae41e24
1 /* packet-pdc.c
2 * Routines for PDC dissection
3 * Copyright 2014, Antony Bridle <antony.bridle@nats.co.uk>
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 "packet-tcp.h"
17 void proto_register_pdc(void);
18 void proto_reg_handoff_pdc(void);
20 /*PDC Protocol*/
21 #define PDC_PROCOTOL "PDC"
23 /* PDC version */
24 #define PDC_VERSION 2
26 #define SIMPDU 1
27 #define RSMPDU 2
28 #define DRMPDU 3
29 #define DTMPDU 4
30 #define ADMPDU 5
31 #define EDMPDU 6
32 #define AKMPDU 8
34 /*Variable length Parameter Codes*/
35 #define PARAM_CODE_VERSION 2
36 #define PARAM_CODE_REFERENCES 3
37 #define PARAM_CODE_TRANSPORT 4
39 /* required for the TCP split packet combining */
40 #define PDC_MSG_SIZE_FIELD_LENGTH 2 /* minimum amount of data to find out how big the split packet should be when recombined */
41 #define FRAME_HEADER_LEN 8
43 /* global handle for our dissector */
44 static dissector_handle_t pdc_tcp_handle;
46 /* global handle for calling asterix decoder if required */
47 static dissector_handle_t asterix_handle;
49 static int proto_pdc;
51 /*HF Declarations*/
52 static int hf_pdc_len;
53 static int hf_pdc_mpdu_code;
54 static int hf_pdc_credit;
55 static int hf_pdc_simpdu_state;
56 static int hf_pdc_yr_admu_nr;
57 static int hf_pdc_akmpdu_mns;
58 static int hf_pdc_akmpdu_cdt;
59 static int hf_pdc_simpdu_var;
60 static int hf_pdc_simpdu_var_len;
61 static int hf_pdc_simpdu_param;
62 static int hf_pdc_simpdu_var_version;
63 static int hf_pdc_simpdu_var_REFSRC;
64 static int hf_pdc_simpdu_var_REFDEST;
65 static int hf_pdc_simpdu_var_TSEL;
66 static int hf_pdc_drmpdu_abort;
67 static int hf_pdc_drmpdu_reason;
68 static int hf_pdc_drmpdu_mode;
69 static int hf_pdc_drmpdu_init;
70 static int hf_pdc_dtmpdu_user_size;
71 static int hf_pdc_admpdu_admpdunr;
72 static int hf_pdc_admpdu_size;
74 /*Tree Declarations*/
75 static int ett_pdc;
76 static int ett_pdc_simpdu_var;
79 /*Value String Declarations*/
80 static const value_string valstr_simpdu_state[] = {
81 { 1, "Operational" },
82 { 2, "Standby" },
83 { 3, "Master" },
84 { 4, "Slave" },
85 { 5, "Single" },
86 { 0, NULL }
89 static const value_string valstr_simpdu_param[] = {
90 { 2, "Version Number" },
91 { 3, "References" },
92 { 4, "Transport Selector" },
93 { 0, NULL }
96 static const value_string valstr_mpdus[] = {
97 { 1, "State Information" },
98 { 2, "Request State" },
99 { 3, "Disconnect Request" },
100 { 4, "Data" },
101 { 5, "Acknowledged Data" },
102 { 6, "Expedited Data" },
103 { 8, "Data Acknowledgement" },
104 { 0, NULL }
107 static const value_string valstr_drmpdu_abort[] = {
108 { 0, "Orderly Release" },
109 { 1, "Abortive Release" },
110 { 0, NULL }
113 static const value_string valstr_drmpdu_mode[] = {
114 { 0, "Node Shutdown" },
115 { 7, "PDC Release"},
116 { 0, NULL }
119 static const value_string valstr_drmpdu_initatior[] = {
120 { 0, "Server" },
121 { 15, "Client"},
122 { 0, NULL }
125 static const value_string valstr_drmpdu_reason[] = {
126 { 0, "Reason Not Specified" },
127 { 1, "Normal Disconnect Initiated by the MS-User" },
128 { 2, "Protocol Error" },
129 { 3, "Connection Request Refused" },
130 { 4, "The Remote Operational MS Entity Does Not Respond" },
131 { 5, "The Protocol Version Is Not Supported" },
132 { 6, "Mismatched References" },
133 { 0, NULL }
136 /* start of functions here */
137 static int dissect_simpdu(tvbuff_t *tvb, proto_tree *tree, uint16_t offset, uint8_t lenIndicator)
139 int bytesProcessed;
140 uint8_t paramCode;
141 proto_item *simpduItem;
142 proto_tree *simpduVarTree;
143 proto_tree *simpduVarTree1;
145 bytesProcessed = 0;
147 /*Add the Credit allocation*/
148 proto_tree_add_item(tree, hf_pdc_credit, tvb, offset, 1, ENC_BIG_ENDIAN);
149 bytesProcessed += 1;
151 /*Add the State*/
152 proto_tree_add_item(tree, hf_pdc_simpdu_state, tvb, offset + bytesProcessed , 1, ENC_BIG_ENDIAN);
153 bytesProcessed += 1;
155 /*Add the YR-ADMU-NR*/
156 proto_tree_add_item(tree, hf_pdc_yr_admu_nr, tvb, offset + bytesProcessed , 4, ENC_BIG_ENDIAN);
157 bytesProcessed += 4;
159 /*Determine what's in the variable part*/
160 if (lenIndicator > 7)
162 /*Add the Variable Length Tree*/
163 simpduItem = proto_tree_add_item (tree, hf_pdc_simpdu_var, tvb, offset + bytesProcessed, lenIndicator - 7, ENC_NA);
164 simpduVarTree = proto_item_add_subtree (simpduItem, ett_pdc_simpdu_var);
166 while ((offset + bytesProcessed) < ( lenIndicator + 1 ))
168 /*Get the parameter code*/
169 paramCode = tvb_get_uint8(tvb, offset + bytesProcessed);
170 simpduItem = proto_tree_add_item (simpduVarTree, hf_pdc_simpdu_param, tvb, offset + bytesProcessed, 1, ENC_BIG_ENDIAN);
171 simpduVarTree1 = proto_item_add_subtree (simpduItem, ett_pdc_simpdu_var);
172 bytesProcessed += 1;
173 switch (paramCode)
175 case PARAM_CODE_VERSION:
176 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len, tvb, offset + bytesProcessed, 1, ENC_BIG_ENDIAN);
177 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_version, tvb, offset + bytesProcessed + 1, 1, ENC_BIG_ENDIAN);
178 bytesProcessed += 2;
179 break;
180 case PARAM_CODE_REFERENCES:
181 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len, tvb, offset + bytesProcessed, 1, ENC_BIG_ENDIAN);
182 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_REFSRC, tvb, offset + bytesProcessed + 1, 2, ENC_BIG_ENDIAN);
183 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_REFDEST, tvb, offset + bytesProcessed + 3, 2, ENC_BIG_ENDIAN);
184 bytesProcessed += 5;
185 break;
186 case PARAM_CODE_TRANSPORT:
187 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_len, tvb, offset + bytesProcessed, 1, ENC_BIG_ENDIAN);
188 proto_tree_add_item(simpduVarTree1, hf_pdc_simpdu_var_TSEL, tvb, offset + bytesProcessed + 1, 2, ENC_BIG_ENDIAN);
189 bytesProcessed += 3;
190 break;
192 } /* end of whileloop */
194 return (bytesProcessed);
197 static int dissect_rsmpdu(void)
199 return 0;
202 static int dissect_drmpdu(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
204 /*DR-MPDU*/
205 proto_tree_add_item(tree, hf_pdc_drmpdu_abort, tvb, offset, 1, ENC_BIG_ENDIAN);
206 proto_tree_add_item(tree, hf_pdc_drmpdu_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
207 proto_tree_add_item(tree, hf_pdc_drmpdu_init, tvb, offset, 1, ENC_BIG_ENDIAN);
208 proto_tree_add_item(tree, hf_pdc_drmpdu_reason, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
210 return 2;
213 #if (PDC_VERSION == 2)
214 static int dissect_admpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, uint16_t offset, packet_info *pinfo)
216 uint16_t userDataLen;
217 uint16_t returnLen;
218 tvbuff_t *asterixTVB;
220 /*Add the ad*/
221 proto_tree_add_item(tree, hf_pdc_admpdu_admpdunr, tvb, offset, 4, ENC_BIG_ENDIAN);
222 offset += 4;
224 proto_tree_add_item(tree, hf_pdc_admpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN);
225 /* length of user data field */
226 userDataLen = tvb_get_ntohs(tvb, offset);
227 offset += 2;
229 returnLen = userDataLen + 6;
230 asterixTVB = tvb_new_subset_length(tvb, offset, userDataLen);
232 if (asterix_handle != NULL)
233 call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
235 return (returnLen);
237 #else
238 static int dissect_admpdu(tvbuff_t *tvb, proto_tree *parent_tree _U_, proto_tree *tree, uint16_t offset, packet_info *pinfo _U_)
240 /*Add the ad*/
241 proto_tree_add_item(tree, hf_pdc_admpdu_admpdunr, tvb, offset, 4, ENC_BIG_ENDIAN);
243 return 2;
245 #endif
247 #if (PDC_VERSION == 2)
248 static int dissect_dtmpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, uint16_t offset, packet_info *pinfo)
250 uint16_t userDataLen;
251 uint16_t returnLen;
252 tvbuff_t *asterixTVB;
254 proto_tree_add_item(tree, hf_pdc_dtmpdu_user_size, tvb, offset, 2, ENC_BIG_ENDIAN);
255 /* length of user data field */
256 userDataLen = tvb_get_ntohs(tvb, 2);
257 returnLen = userDataLen + 2;
258 asterixTVB = tvb_new_subset_length(tvb, offset + 2, userDataLen);
260 if (asterix_handle != NULL)
261 call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
263 return (returnLen);
265 #else
266 static int dissect_dtmpdu(tvbuff_t *tvb _U_, proto_tree *parent_tree _U_, proto_tree *tree _U_, uint16_t offset _U_, packet_info *pinfo _U_)
268 return 2;
270 #endif
273 #if (PDC_VERSION == 2)
274 static int dissect_edmpdu(tvbuff_t *tvb, proto_tree *parent_tree, proto_tree *tree, uint16_t offset, packet_info *pinfo)
276 uint16_t userDataLen;
277 uint16_t returnLen;
278 tvbuff_t *asterixTVB;
280 proto_tree_add_item(tree, hf_pdc_dtmpdu_user_size, tvb, offset, 2, ENC_BIG_ENDIAN);
281 /* length of user data field */
282 userDataLen = tvb_get_ntohs(tvb, 2);
283 returnLen = userDataLen + 2;
284 asterixTVB = tvb_new_subset_length(tvb, offset + 2, userDataLen);
286 if (asterix_handle != NULL)
287 call_dissector(asterix_handle, asterixTVB, pinfo, parent_tree);
289 return (returnLen);
291 #else
292 static int dissect_edmpdu(tvbuff_t *tvb _U_, proto_tree *parent_tree _U_, proto_tree *tree _U_, uint16_t offset _U_, packet_info *pinfo _U_)
294 return 2;
296 #endif
298 static int dissect_akmpdu(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
300 proto_tree_add_item(tree, hf_pdc_akmpdu_mns, tvb, offset, 2, ENC_BIG_ENDIAN);
301 proto_tree_add_item(tree, hf_pdc_akmpdu_cdt, tvb, offset, 2, ENC_BIG_ENDIAN);
302 proto_tree_add_item(tree, hf_pdc_yr_admu_nr, tvb, offset + 2, 4, ENC_BIG_ENDIAN);
303 return (6);
306 static int dissect_pdc_packet(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
308 unsigned i = 0;
309 uint8_t len_indicator;
310 uint8_t mpduCode;
311 uint16_t length;
312 proto_item *pdcPacketItem;
313 proto_tree *pdcPacketTree;
315 length = 0;
317 /*Get the length indictor and the MPDU Code*/
318 len_indicator = tvb_get_uint8 (tvb, i);
319 mpduCode = tvb_get_uint8 (tvb, i + 1);
320 length += 2;
322 /*Add the PDC Tree*/
323 pdcPacketItem = proto_tree_add_item (tree, proto_pdc, tvb, i, len_indicator + 1, ENC_NA);
324 pdcPacketTree = proto_item_add_subtree (pdcPacketItem, ett_pdc);
326 /*Add the Length and packet type*/
327 proto_tree_add_item(pdcPacketTree, hf_pdc_len, tvb, i, 1, ENC_BIG_ENDIAN);
328 proto_tree_add_item(pdcPacketTree, hf_pdc_mpdu_code, tvb, i + 1, 1, ENC_BIG_ENDIAN);
330 /*Call the correct dissecting function*/
331 switch (mpduCode)
333 case SIMPDU:
334 length += dissect_simpdu(tvb, pdcPacketTree, length, len_indicator);
335 col_set_str(pinfo->cinfo, COL_INFO, "SIMPDU");
336 break;
337 case RSMPDU:
338 length += dissect_rsmpdu();
339 col_set_str(pinfo->cinfo, COL_INFO, "RSMPDU");
340 break;
341 case DRMPDU:
342 length += dissect_drmpdu(tvb, pdcPacketTree, length);
343 col_set_str(pinfo->cinfo, COL_INFO, "DRMPDU");
344 break;
345 case DTMPDU:
346 length += dissect_dtmpdu(tvb, tree, pdcPacketTree, length, pinfo);
347 col_set_str(pinfo->cinfo, COL_INFO, "DTMPDU");
348 break;
349 case ADMPDU:
350 length += dissect_admpdu(tvb, tree, pdcPacketTree, length, pinfo);
351 col_set_str(pinfo->cinfo, COL_INFO, "ADMPDU");
352 break;
353 case EDMPDU:
354 length += dissect_edmpdu(tvb, tree, pdcPacketTree, length, pinfo);
355 col_set_str(pinfo->cinfo, COL_INFO, "EDMPDU");
356 break;
357 case AKMPDU:
358 length += dissect_akmpdu(tvb, pdcPacketTree, length);
359 col_set_str(pinfo->cinfo, COL_INFO, "AKMPDU");
360 break;
361 default:
362 break;
364 return (length); /* XXX: returned length ignored by caller: Remove keeping track of data processed ? */
365 /* col_set_str() could then be done separately with 'if (tree)' around the dissection */
368 /* Actual dissector bits and bytes done here */
369 static int dissect_pdc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
371 /*Set the Column*/
372 col_set_str(pinfo->cinfo, COL_PROTOCOL, PDC_PROCOTOL );
373 col_clear(pinfo->cinfo, COL_INFO);
375 dissect_pdc_packet(tvb, tree, pinfo);
377 return tvb_reported_length(tvb);
380 /* function to provide TCP split packet combiner with size of packet */
381 static unsigned get_pdc_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
382 int offset, void *data _U_)
384 unsigned size;
385 unsigned extra;
386 uint8_t mpdu_type;
388 mpdu_type = tvb_get_uint8(tvb, offset+1);
389 switch (mpdu_type)
391 case SIMPDU:
392 size = tvb_get_uint8(tvb, offset);
393 extra = 1;
394 break;
395 case RSMPDU:
396 size = tvb_get_uint8(tvb, offset);
397 extra = 1;
398 break;
399 case DRMPDU:
400 size = tvb_get_uint8(tvb, offset);
401 extra = 1;
402 break;
403 case DTMPDU:
404 size = tvb_get_ntohs(tvb, offset+2);
405 extra = 4;
406 break;
407 case ADMPDU:
408 size = tvb_get_ntohs(tvb, offset+6);
409 extra = 8;
410 break;
411 case EDMPDU:
412 size = tvb_get_uint8(tvb, offset);
413 extra = 1;
414 break;
415 case AKMPDU:
416 size = tvb_get_uint8(tvb, offset)+1;
417 extra = 0;
418 break;
419 default:
420 size = 0;
421 extra = 0;
423 return size + extra;
426 /* top level call to recombine split tcp packets */
428 static int tcp_dissect_pdc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
430 uint8_t mpdu_type;
431 uint8_t minimum_bytes;
433 mpdu_type = tvb_get_uint8(tvb,1);
434 switch (mpdu_type)
436 case SIMPDU:
437 minimum_bytes = 2;
438 break;
439 case RSMPDU:
440 minimum_bytes = 2;
441 break;
442 case DRMPDU:
443 minimum_bytes = 2;
444 break;
445 case DTMPDU:
446 minimum_bytes = 4;
447 break;
448 case ADMPDU:
449 minimum_bytes = 8;
450 break;
451 case EDMPDU:
452 minimum_bytes = 2;
453 break;
454 case AKMPDU:
455 minimum_bytes = 2;
456 break;
457 default:
458 minimum_bytes = 2;
459 break;
461 tcp_dissect_pdus(tvb, pinfo, tree, true, minimum_bytes, get_pdc_message_len, dissect_pdc, NULL);
462 return tvb_captured_length(tvb);
465 void proto_register_pdc(void)
467 static hf_register_info hf[] =
469 { &hf_pdc_len,
470 { "Length Indicator", "pdc.li",
471 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
473 { &hf_pdc_mpdu_code,
474 { "MPDU code", "pdc.mpducode",
475 FT_UINT8, BASE_DEC, VALS(valstr_mpdus), 0x0, NULL, HFILL }},
477 { &hf_pdc_credit,
478 { "Credit", "pdc.cdt",
479 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
481 { &hf_pdc_yr_admu_nr,
482 { "YR-ADMU-NR", "pdc.yradmunr",
483 FT_UINT32, BASE_DEC, NULL, 0x0, NULL , HFILL }},
485 { &hf_pdc_simpdu_state,
486 { "State", "pdc.state",
487 FT_UINT8, BASE_DEC, VALS(valstr_simpdu_state), 0x0, NULL, HFILL }},
489 { &hf_pdc_akmpdu_mns,
490 { "MNS", "pdc.akmpdu.mns",
491 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL }},
493 { &hf_pdc_akmpdu_cdt,
494 { "CDT", "pdc.akmpdu.cdt",
495 FT_UINT16, BASE_DEC, NULL, 0x07FF, NULL, HFILL }},
497 { &hf_pdc_simpdu_var,
498 { "Variable Part", "pdc.simpdu.variable",
499 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
501 { &hf_pdc_simpdu_param,
502 { "Parameter", "pdc.simpdu.param",
503 FT_UINT8, BASE_DEC, VALS(valstr_simpdu_param), 0x0, NULL, HFILL }},
505 { &hf_pdc_simpdu_var_len,
506 { "Length", "pdc.simpdu.variable.length",
507 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
509 { &hf_pdc_simpdu_var_version,
510 { "PDC Version Number", "pdc.simpdu.variable.version",
511 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
513 { &hf_pdc_simpdu_var_REFSRC,
514 { "Reference Source", "pdc.simpdu.variable.refsrc",
515 FT_UINT32, BASE_DEC, NULL, 0x0,NULL, HFILL }},
517 { &hf_pdc_simpdu_var_REFDEST,
518 { "Reference Destination", "pdc.simpdu.variable.refdst",
519 FT_UINT32, BASE_DEC, NULL, 0x0,NULL, HFILL }},
521 { &hf_pdc_simpdu_var_TSEL,
522 { "Transport Selector", "pdc.simpdu.tsel",
523 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
525 { &hf_pdc_drmpdu_abort,
526 { "Abort", "pdc.drmpdu.abort",
527 FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_abort), 0x80, NULL, HFILL }},
529 { &hf_pdc_drmpdu_reason,
530 { "Reason", "pdc.drmpdu.reason",
531 FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_reason), 0x0, NULL, HFILL }},
533 { &hf_pdc_drmpdu_mode,
534 { "Mode", "pdc.drmpdu.mode",
535 FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_mode), 0x70, NULL, HFILL }},
537 { &hf_pdc_drmpdu_init,
538 { "Reason", "pdc.drmpdu.init",
539 FT_UINT8, BASE_DEC, VALS(valstr_drmpdu_initatior), 0x0F, NULL, HFILL }},
541 { &hf_pdc_dtmpdu_user_size,
542 { "User Data Length", "pdc.dtmpdu.usersize",
543 FT_UINT16, BASE_DEC, NULL, 0x0, NULL , HFILL }},
545 { &hf_pdc_admpdu_admpdunr,
546 { "AD-MPDU-NR", "pdc.admpdu.admpdunr",
547 FT_UINT32, BASE_DEC, NULL, 0x0, NULL , HFILL }},
549 { &hf_pdc_admpdu_size,
550 { "User Data Size", "pdc.admpdu.usersize",
551 FT_UINT16, BASE_DEC, NULL, 0x0, NULL , HFILL }},
554 /* Setup protocol subtree array */
555 static int *ett[] = {
556 &ett_pdc,
557 &ett_pdc_simpdu_var
560 proto_pdc = proto_register_protocol (
561 "PDC Protocol", /* name */
562 "PDC", /* short name */
563 "pdc" /* abbrev */
566 /*Required Function Calls to register the header fields and subtrees used*/
567 proto_register_field_array(proto_pdc, hf, array_length(hf));
568 proto_register_subtree_array(ett, array_length(ett));
570 /* Register our dissector handle */
571 pdc_tcp_handle = register_dissector("pdc", tcp_dissect_pdc, proto_pdc);
574 /* Function to add pdc dissector to tcp.port dissector table and to get handle for asterix dissector */
575 void proto_reg_handoff_pdc(void)
577 asterix_handle = find_dissector_add_dependency("asterix", proto_pdc);
578 dissector_add_for_decode_as_with_preference("tcp.port", pdc_tcp_handle);
582 * Editor modelines - https://www.wireshark.org/tools/modelines.html
584 * Local variables:
585 * c-basic-offset: 8
586 * tab-width: 8
587 * indent-tabs-mode: t
588 * End:
590 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
591 * :indentSize=8:tabSize=8:noTabs=false: