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
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
71 static const value_string gcsna_message_types
[] = {
72 { 0x01, "GCSNA 1X Circuitservice" },
73 { 0x02, "GCSNA L2 Ack"},
74 { 0x03, "GCSNA Servicereject"},
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"},
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"},
110 static const value_string gcsna_tru_false_values
[] = {
116 /* Decoder for all the information elements of A21 Message Type */
118 gcsna_message_decode(proto_item
*item
, tvbuff_t
*tvb
, proto_tree
*tree
, unsigned *offset
, proto_tree
*mainTree
, uint16_t *noerror
, packet_info
*pinfo
)
121 msgId
= tvb_get_uint8(tvb
, *offset
);
126 case GCSNA1XCIRCUITSERVICE
:
128 gcsna_message_GCSNA1xCircuitService(item
, tvb
, pinfo
, mainTree
, tree
, offset
);
134 gcsna_message_GCSNAL2Ack(item
, tvb
, tree
, offset
);
138 case GCSNASERVICEREJECT
:
140 gcsna_message_GCSNAServiceReject(item
, tvb
, tree
, offset
);
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;
157 unsigned bit_offset
= *offset
* 8;
158 proto_tree
*subtree
= NULL
;
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
);
166 proto_tree_add_bits_item(subtree
, hf_gcsna_gcsnaClassRev
, tvb
, bit_offset
, 3, ENC_BIG_ENDIAN
);
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
);
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
);
178 while (num_alt_gcsna_opt
!= 0)
180 proto_tree_add_bits_item(tree
, hf_gcsna_altGCSNAOption
, tvb
, bit_offset
, 8, ENC_BIG_ENDIAN
);
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
);
192 proto_tree_add_bits_item(tree
, hf_gcsna_iwsidValue
, tvb
, bit_offset
, 16, ENC_BIG_ENDIAN
);
196 proto_tree_add_bits_item(tree
, hf_gcsna_ackRequired
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
198 proto_tree_add_bits_item(tree
, hf_gcsna_stopDupDetect
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
200 proto_tree_add_bits_item(tree
, hf_gcsna_msgSequence
, tvb
, bit_offset
, 6, ENC_BIG_ENDIAN
);
203 proto_tree_add_bits_item(tree
, hf_gcsna_NumTLACEncapsulated1xL3PDU
, tvb
, bit_offset
, 2, ENC_BIG_ENDIAN
);
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
);
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
);
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
);
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);
258 num_fields
= tvb_get_bits8(tvb
, 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
);
265 proto_tree_add_bits_item(subtree
, hf_gcsna_gcsnaClassRev
, tvb
, l_offset
, 3, ENC_BIG_ENDIAN
);
272 proto_tree_add_bits_item(subtree
, hf_gcsna_1xProtocolRevision
, tvb
, l_offset
, 8, ENC_BIG_ENDIAN
);
281 proto_tree_add_bits_item(subtree
, hf_gcsna_1xProtocolRevision
, tvb
, l_offset
, 8, ENC_BIG_ENDIAN
);
288 proto_tree_add_bits_item(subtree
, hf_gcsna_invalidMessageId
, tvb
, l_offset
, 8, ENC_BIG_ENDIAN
);
293 /*This Cause Value is not supported in IWS Stack*/
296 num_fields
= tvb_get_bits8(tvb
, 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
);
310 proto_tree_add_item(subtree
, hf_gcsna_unsupported_reject_seq
, tvb
, l_offset
, -1, ENC_NA
);
315 if (l_offset
% 8 == 0)
317 *offset
= (l_offset
/ 8);
320 *offset
= (l_offset
/ 8) + 1;
325 /*Method called when the dissection starts.....Starting point*/
327 dissect_gcsna(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
)
331 proto_tree
*gcsna_msghdr_tree_start
= NULL
;
333 proto_item
*item
= NULL
;
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
);
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
);
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*/
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 } },*/
371 { "L2ACK", "gcsna.l2ack", FT_NONE
, BASE_NONE
,NULL
, 0x0, NULL
, HFILL
} },
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
} },
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
} },
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
[] = {
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
));
447 proto_reg_handoff_gcsna(void)
449 cdma2k_handle
= find_dissector("cdma2k");