Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gcsna.c
blobbd23809cd6380355a4c5bb2b2891883e17ed25a6
1 /*
2 * packet-gcsna.c
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
10 * Ref GCSNA: 3GPP2 C.S0097 v2.0
13 # include "config.h"
15 #include <epan/packet.h>
16 #include <epan/expert.h>
18 void proto_reg_handoff_gcsna(void);
19 void proto_register_gcsna(void);
21 /* gcsna Handle for the dissection */
22 static dissector_handle_t gcsna_handle;
23 static dissector_handle_t cdma2k_handle;
25 /* Function handlers for each message/information fields */
26 static void gcsna_message_decode(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset, proto_tree *mainTree, uint16_t *noerror, packet_info *pinfo);
27 static void gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, unsigned *offset);
28 static void gcsna_message_GCSNAL2Ack(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
29 static void gcsna_message_GCSNAServiceReject(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset);
31 /*Initialize all the header parameters that are to be displayed*/
32 static int proto_gcsna;
33 static int hf_gcsna_msghdr;
34 static int hf_gcsna_msgid;
35 static int hf_gcsna_rejSequence;
36 static int hf_gcsna_cause;
37 static int hf_gcsna_ackSequence;
38 static int hf_gcsna_recordType;
39 static int hf_gcsna_1xProtocolRevision;
40 static int hf_gcsna_invalidMessageId;
41 static int hf_gcsna_l2ack;
42 static int hf_gcsna_servicereject;
43 static int hf_gcsna_gcsna_option;
44 static int hf_gcsna_gcsnaClass;
45 static int hf_gcsna_gcsnaClassRev;
46 static int hf_gcsna_altGCSNAOption;
47 static int hf_gcsna_altGCSNAOptionIncluded;
48 static int hf_gcsna_NumaltGCSNAOption;
49 static int hf_gcsna_ackRequired;
50 static int hf_gcsna_stopDupDetect;
51 static int hf_gcsna_msgSequence;
52 static int hf_gcsna_tlacEncapsulated;
53 static int hf_gcsna_NumTLACEncapsulated1xL3PDU;
54 static int hf_gcsna_tlacReserved;
55 static int hf_gcsna_iwsidIncluded;
56 static int hf_gcsna_iwsidValue;
57 static int hf_gcsna_unsupported_reject_seq;
59 /* Toggle sub-tree items */
60 static int ett_gcsna_msghdr;
61 static int ett_gcsna_subtree;
62 static int ett_gcsna_option;
64 static expert_field ei_gcsna_error;
66 #define GCSNA1XCIRCUITSERVICE 0x01
67 #define GCSNAL2ACK 0x02
68 #define GCSNASERVICEREJECT 0x03
70 /* Msg Types */
71 static const value_string gcsna_message_types[] = {
72 { 0x01, "GCSNA 1X Circuitservice" },
73 { 0x02, "GCSNA L2 Ack"},
74 { 0x03, "GCSNA Servicereject"},
75 { 0, NULL },
78 /* Cause Types */
79 static const value_string gcsna_cause_types[] = {
80 { 0, "Invalid GCSNAOption" },
81 { 1, "Invalid 1xProtocolRevision" },
82 { 2, "Invalid GCSNAOption and 1xProtocolRevision"},
83 { 3, "Invalid Message Id"},
84 { 4, "GCSNA 1xParameters provisioning is not supported" },
85 { 5, "Unsupported RecordType in GCSNA 1xParameters message"},
86 { 0, NULL },
90 GCSNA Class GCSNA ClassRevision 1x Service
91 +----------+-------------------+--------------------------------+
92 | | 0 | Release 8 1xCSFB from E-UTRAN |
93 | +-------------------+--------------------------------+
94 | 0 | 1 | Release 9 e1xCSFB from E-UTRAN |
95 | +-------------------+--------------------------------+
96 | | 2 | C.S0097-A supported eCSFB |
97 +----------+-------------------+--------------------------------+
98 | 1 | 0 | SRVCC from E-UTRAN |
99 +----------+-------------------+--------------------------------+
102 static const value_string gcsna_option_values[] = {
103 { 0, "Release 8 1xCSFB from E-UTRAN" },
104 { 1, "Release 9 e1xCSFB from E-UTRAN" },
105 { 2, "C.S0097-A supported eCSFB"},
106 { 8, "SRVCC from E-UTRAN"},
107 { 0, NULL },
110 static const value_string gcsna_tru_false_values[] = {
111 { 0, "False" },
112 { 1, "True" },
113 { 0, NULL },
116 /* Decoder for all the information elements of A21 Message Type */
117 static void
118 gcsna_message_decode(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset, proto_tree *mainTree, uint16_t *noerror, packet_info *pinfo)
120 uint16_t msgId = -1;
121 msgId = tvb_get_uint8(tvb, *offset);
122 *offset += 1;
124 switch (msgId)
126 case GCSNA1XCIRCUITSERVICE:
128 gcsna_message_GCSNA1xCircuitService(item, tvb, pinfo, mainTree, tree, offset);
129 break;
132 case GCSNAL2ACK:
134 gcsna_message_GCSNAL2Ack(item, tvb, tree, offset);
135 break;
138 case GCSNASERVICEREJECT:
140 gcsna_message_GCSNAServiceReject(item, tvb, tree, offset);
141 break;
144 default:
146 *noerror = 0;
147 break;
152 static void
153 gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, unsigned *offset)
155 uint16_t alt_gcsna_incl = 0, num_alt_gcsna_opt = -1, iws_incl = 0;
156 uint8_t num_res;
157 unsigned bit_offset = *offset * 8;
158 proto_tree *subtree = NULL;
159 tvbuff_t *new_tvb;
161 /* GCSNAOption 8 bits */
162 item = proto_tree_add_item(tree, hf_gcsna_gcsna_option, tvb, *offset, 1, ENC_BIG_ENDIAN);
163 subtree = proto_item_add_subtree(item, ett_gcsna_option);
164 proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
165 bit_offset += 5;
166 proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
167 bit_offset += 3;
169 alt_gcsna_incl = tvb_get_bits8(tvb, bit_offset, 1);
170 proto_tree_add_bits_item(tree, hf_gcsna_altGCSNAOptionIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
171 bit_offset += 1;
172 if (alt_gcsna_incl)
174 num_alt_gcsna_opt = tvb_get_bits8(tvb, bit_offset, 8);
175 proto_tree_add_bits_item(tree, hf_gcsna_NumaltGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
176 bit_offset += 8;
178 while (num_alt_gcsna_opt != 0)
180 proto_tree_add_bits_item(tree, hf_gcsna_altGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
181 bit_offset += 8;
182 num_alt_gcsna_opt--;
186 iws_incl = tvb_get_bits8(tvb, bit_offset, 1);
187 proto_tree_add_bits_item(tree, hf_gcsna_iwsidIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
188 bit_offset++;
190 if (iws_incl)
192 proto_tree_add_bits_item(tree, hf_gcsna_iwsidValue, tvb, bit_offset, 16, ENC_BIG_ENDIAN);
193 bit_offset += 16;
196 proto_tree_add_bits_item(tree, hf_gcsna_ackRequired, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
197 bit_offset++;
198 proto_tree_add_bits_item(tree, hf_gcsna_stopDupDetect, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
199 bit_offset++;
200 proto_tree_add_bits_item(tree, hf_gcsna_msgSequence, tvb, bit_offset, 6, ENC_BIG_ENDIAN);
201 bit_offset += 6;
203 proto_tree_add_bits_item(tree, hf_gcsna_NumTLACEncapsulated1xL3PDU, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
204 bit_offset += 2;
206 /* The sender shall include reserved bits to make this message integral number of octets up to TLACEncapsulated1xL3PDU field.
207 * The sender shall set all bits in this field to '0'. The receiver shall ignore this field.
210 /* calculate number of reserved bits */
211 num_res = 8 - (bit_offset & 0x3);
212 proto_tree_add_bits_item(tree, hf_gcsna_tlacReserved, tvb, bit_offset, num_res, ENC_BIG_ENDIAN);
213 bit_offset = bit_offset + num_res;
214 *offset = bit_offset >> 3;
216 proto_tree_add_item(tree, hf_gcsna_tlacEncapsulated, tvb, *offset, -1, ENC_NA);
218 if (cdma2k_handle) {
219 new_tvb = tvb_new_subset_length(tvb, *offset, -1);
220 call_dissector(cdma2k_handle, new_tvb, pinfo, mainTree);
222 /* set the offset to the end of the message */
223 *offset += tvb_reported_length_remaining(tvb, *offset);
227 static void gcsna_message_GCSNAL2Ack(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
229 proto_tree *subtree = NULL;
231 item = proto_tree_add_item(tree, hf_gcsna_l2ack, tvb, *offset, 1, ENC_NA);
232 subtree = proto_item_add_subtree(item, ett_gcsna_subtree);
234 proto_tree_add_bits_item(subtree, hf_gcsna_ackSequence, tvb, *offset * 8, 6, ENC_BIG_ENDIAN);
235 *offset += 1;
238 static void gcsna_message_GCSNAServiceReject(proto_item *item, tvbuff_t *tvb, proto_tree *tree, unsigned *offset)
240 uint16_t cause_val = -1, num_fields = -1, l_offset = -1;
241 proto_tree *subtree = NULL;
243 item = proto_tree_add_item(tree, hf_gcsna_servicereject, tvb, *offset, 1, ENC_NA);
244 subtree = proto_item_add_subtree(item, ett_gcsna_subtree);
246 l_offset = *offset * 8;
247 proto_tree_add_bits_item(subtree, hf_gcsna_rejSequence, tvb, l_offset, 6, ENC_BIG_ENDIAN);
248 l_offset += 6;
249 proto_tree_add_bits_item(subtree, hf_gcsna_cause, tvb, l_offset, 8, ENC_BIG_ENDIAN);
250 cause_val = tvb_get_bits8(tvb, *offset * 8 + 6, 8);
251 l_offset += 8;
253 switch (cause_val)
255 case 0:
256 case 2:
258 num_fields = tvb_get_bits8(tvb, l_offset, 8);
259 l_offset += 8;
261 while (num_fields > 0)
263 proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, l_offset, 5, ENC_BIG_ENDIAN);
264 l_offset += 5;
265 proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, l_offset, 3, ENC_BIG_ENDIAN);
266 l_offset += 3;
267 num_fields--;
270 if (cause_val == 2)
272 proto_tree_add_bits_item(subtree, hf_gcsna_1xProtocolRevision, tvb, l_offset, 8, ENC_BIG_ENDIAN);
273 l_offset += 8;
276 break;
279 case 1:
281 proto_tree_add_bits_item(subtree, hf_gcsna_1xProtocolRevision, tvb, l_offset, 8, ENC_BIG_ENDIAN);
282 l_offset += 8;
283 break;
286 case 3:
288 proto_tree_add_bits_item(subtree, hf_gcsna_invalidMessageId, tvb, l_offset, 8, ENC_BIG_ENDIAN);
289 l_offset += 8;
290 break;
293 /*This Cause Value is not supported in IWS Stack*/
294 case 5:
296 num_fields = tvb_get_bits8(tvb, l_offset, 8);
297 l_offset += 8;
299 while (num_fields > 0)
301 proto_tree_add_bits_item(subtree, hf_gcsna_recordType, tvb, l_offset, 8, ENC_BIG_ENDIAN);
302 l_offset += 8;
303 num_fields--;
305 break;
308 default:
310 proto_tree_add_item(subtree, hf_gcsna_unsupported_reject_seq, tvb, l_offset, -1, ENC_NA);
311 break;
315 if (l_offset % 8 == 0)
317 *offset = (l_offset / 8);
318 } else
320 *offset = (l_offset / 8) + 1;
325 /*Method called when the dissection starts.....Starting point*/
326 static int
327 dissect_gcsna(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
330 /* Initialization*/
331 proto_tree *gcsna_msghdr_tree_start = NULL;
333 proto_item *item = NULL;
335 uint32_t offset = 0;
336 uint16_t noerror = 1;
339 /*Add the protocol name to display*/
340 col_set_str(pinfo->cinfo, COL_PROTOCOL, "gcsna");
341 col_set_str(pinfo->cinfo, COL_INFO, "[gcsna]");
343 item = proto_tree_add_item(tree, hf_gcsna_msghdr, tvb, 0, -1, ENC_NA);
344 gcsna_msghdr_tree_start = proto_item_add_subtree(item, ett_gcsna_msghdr);
346 if (tree)
348 proto_tree_add_item(gcsna_msghdr_tree_start, hf_gcsna_msgid, tvb, offset, 1, ENC_BIG_ENDIAN);
350 while (tvb_captured_length_remaining(tvb, offset) != 0 && noerror == 1)
351 gcsna_message_decode(item, tvb, gcsna_msghdr_tree_start, &offset, tree, &noerror, pinfo);
353 if (noerror == 0)
355 expert_add_info(pinfo, item, &ei_gcsna_error);
358 return tvb_reported_length(tvb);
361 /*Register gcsna to be accessed by other dissectors/plugins*/
362 void
363 proto_register_gcsna(void)
365 static hf_register_info hf[] = {
366 { &hf_gcsna_servicereject,
367 { "GCSNA SERVICEREJECT", "gcsna.servicereject", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } },
368 /*{ & hf_gcsna_msgid,
369 { "GCSNA Message Type", "gcsna.MsgType", FT_UINT8, BASE_HEX_DEC, VALS(A21_Message_Types), 0x0, NULL, HFILL } },*/
370 { &hf_gcsna_l2ack,
371 { "L2ACK", "gcsna.l2ack", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } },
372 { &hf_gcsna_msghdr,
373 { "General Circuit Services Notification Application Protocol", "gcsna.msghdr", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } },
374 { &hf_gcsna_NumTLACEncapsulated1xL3PDU,
375 { "NumTLACEncapsulated1xL3PDU", "gcsna.NumTLACEncapsulated1xL3PDU", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
376 { &hf_gcsna_tlacReserved,
377 { "Reserved", "gcsna.tlacReserved", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
378 { &hf_gcsna_tlacEncapsulated,
379 { "TLAC Encapsulated", "gcsna.tlacEncapsulated", FT_BYTES, BASE_NONE,NULL, 0x0, NULL, HFILL } },
380 { &hf_gcsna_msgSequence,
381 { "Msg Sequence", "gcsna.msgSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
382 { &hf_gcsna_stopDupDetect,
383 { "Stop Dup Detect", "gcsna.stopDupDetect", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
384 { &hf_gcsna_ackRequired,
385 { "Ack Required", "gcsna.ackRequired", FT_UINT8, BASE_DEC,VALS(gcsna_tru_false_values), 0x0, NULL, HFILL } },
386 { &hf_gcsna_altGCSNAOptionIncluded,
387 { "AlternativeGCSNAOption_INCL", "gcsna.altGCSNAOptionIncluded", FT_UINT8, BASE_DEC,VALS(gcsna_tru_false_values), 0x0, NULL, HFILL } },
388 { &hf_gcsna_altGCSNAOption,
389 { "Alternate GCSNA Option", "gcsna.altGCSNAOption", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
390 { &hf_gcsna_gcsna_option,
391 { "GCSNA Option", "gcsna.Option", FT_UINT8, BASE_HEX, VALS(gcsna_option_values), 0x0, NULL, HFILL } },
392 { &hf_gcsna_NumaltGCSNAOption,
393 { "NumAlternativeGCSNAOptions", "gcsna.NumaltGCSNAOption", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
394 { &hf_gcsna_iwsidValue,
395 { "IWS_ID", "gcsna.iwsidValue", FT_UINT16, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
396 { &hf_gcsna_iwsidIncluded,
397 { "IWSIDIncl", "gcsna.iwsidIncluded", FT_UINT8, BASE_DEC,VALS(gcsna_tru_false_values), 0x0, NULL, HFILL } },
398 { &hf_gcsna_gcsnaClassRev,
399 { "GCSNA Class revision", "gcsna.ClassRev", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
400 { &hf_gcsna_gcsnaClass,
401 { "GCSNA Class", "gcsna.Class", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
402 { &hf_gcsna_invalidMessageId,
403 { "InvalidMessageId", "gcsna.invalidMessageId", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
404 { &hf_gcsna_1xProtocolRevision,
405 { "1xProtocolRevision", "gcsna.1xProtocolRevision", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
406 { &hf_gcsna_recordType,
407 { "Record Type", "gcsna.recordType", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
408 { &hf_gcsna_ackSequence,
409 { "Ack Sequence", "gcsna.ackSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
410 { &hf_gcsna_cause,
411 { "Cause", "gcsna.cause", FT_UINT8, BASE_HEX_DEC,VALS(gcsna_cause_types), 0x0, NULL, HFILL } },
412 { &hf_gcsna_rejSequence,
413 { "Reject Sequence", "gcsna.rejSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } },
414 { &hf_gcsna_msgid,
415 { "GCSNA Message Type", "gcsna.msgId", FT_UINT8, BASE_HEX_DEC,VALS(gcsna_message_types), 0x0, NULL, HFILL } },
416 { &hf_gcsna_unsupported_reject_seq,
417 { "Invalid / Unsupported GCSNA Message Reject Sequence", "gcsna.unsupportedrejectseq", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } }
421 static int *ett[] = {
422 &ett_gcsna_msghdr,
423 &ett_gcsna_subtree,
424 &ett_gcsna_option
428 static ei_register_info ei[] = {
429 { &ei_gcsna_error, { "gcsna.error", PI_PROTOCOL, PI_ERROR, "Violation of protocol specs (e.g. invalid information element)", EXPFILL }},
432 expert_module_t* expert_gcsna;
434 proto_gcsna = proto_register_protocol("GCSNA", "GCSNA", "gcsna");
436 gcsna_handle = register_dissector("gcsna", dissect_gcsna, proto_gcsna);
438 proto_register_field_array(proto_gcsna, hf, array_length(hf));
439 proto_register_subtree_array(ett, array_length(ett));
441 expert_gcsna = expert_register_protocol(proto_gcsna);
442 expert_register_field_array(expert_gcsna, ei, array_length(ei));
446 void
447 proto_reg_handoff_gcsna(void)
449 cdma2k_handle = find_dissector("cdma2k");