2 * Routines for Subnetwork Dependent Convergence Protocol (SNDCP) XID dissection
3 * Used to dissect XID compression parameters negotiated in GSM (TS44.065)
4 * Copyright 2008, Vincent Helfre <vincent.helfre [AT] ericsson.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
18 /* Parameter types: TS 44.065 8
20 #define SNDCP_VERSION_PAR_TYPE 0
21 #define DATA_COMPRESSION_PAR_TYPE 1
22 #define PROTOCOL_COMPRESSION_PAR_TYPE 2
24 /* Algorithm identifiers: TS 44.065 6.6.1.1.4 and 6.5.1.1.4
28 #define ALGO_RFC1144 0
29 #define ALGO_RFC2507 1
32 void proto_register_sndcp_xid(void);
34 static const value_string sndcp_xid_dcomp_algo_str
[] = {
40 static const value_string sndcp_xid_pcomp_algo_str
[] = {
43 {0x2, "ROHC (RFC 3095)"},
49 uint8_t nb_of_dcomp_pcomp
; /* note that a DCOMP or a PCOMP is 4 bit wide */
50 uint16_t (**func_array_ptr
) (tvbuff_t
*, proto_tree
*, uint16_t);
53 /* Initialize the protocol and registered fields
55 static int proto_sndcp_xid
;
57 /* These fields are used to store the algorithm ID
58 * When the P bit is not set, try to decode the algo based on what whas stored.
59 * Entity ranges from 0 to 31 (6.5.1.1.3)
61 static uint8_t dcomp_entity_algo_id
[32];
62 static uint8_t pcomp_entity_algo_id
[32];
66 static int hf_sndcp_xid_type
;
67 static int hf_sndcp_xid_len
;
68 static int hf_sndcp_xid_value
;
69 static int hf_sndcp_xid_comp_pbit
;
70 static int hf_sndcp_xid_comp_spare_byte1
;
71 static int hf_sndcp_xid_comp_entity
;
72 static int hf_sndcp_xid_comp_spare_byte2
;
73 static int hf_sndcp_xid_comp_algo_id
;
74 static int hf_sndcp_xid_comp_len
;
75 /* There is currently a maximum of 15 DCOMP/PCOMP: 6.5.1.1.5 */
76 static int hf_sndcp_xid_comp
[15];
77 static int hf_sndcp_xid_comp_spare
;
79 static int hf_element_applicable_nsapi_15
;
80 static int hf_element_applicable_nsapi_14
;
81 static int hf_element_applicable_nsapi_13
;
82 static int hf_element_applicable_nsapi_12
;
83 static int hf_element_applicable_nsapi_11
;
84 static int hf_element_applicable_nsapi_10
;
85 static int hf_element_applicable_nsapi_9
;
86 static int hf_element_applicable_nsapi_8
;
87 static int hf_element_applicable_nsapi_7
;
88 static int hf_element_applicable_nsapi_6
;
89 static int hf_element_applicable_nsapi_5
;
90 static int hf_element_applicable_nsapi_spare
;
92 static int hf_sndcp_xid_rfc1144_s0
;
93 static int hf_sndcp_xid_rfc2507_f_max_period_msb
;
94 static int hf_sndcp_xid_rfc2507_f_max_period_lsb
;
95 static int hf_sndcp_xid_rfc2507_f_max_time
;
96 static int hf_sndcp_xid_rfc2507_max_header
;
97 static int hf_sndcp_xid_rfc2507_tcp_space
;
98 static int hf_sndcp_xid_rfc2507_non_tcp_space_msb
;
99 static int hf_sndcp_xid_rfc2507_non_tcp_space_lsb
;
100 static int hf_sndcp_xid_rohc_max_cid_spare
;
101 static int hf_sndcp_xid_rohc_max_cid_msb
;
102 static int hf_sndcp_xid_rohc_max_cid_lsb
;
103 static int hf_sndcp_xid_rohc_max_header
;
104 static int hf_sndcp_xid_rohc_profile_msb
;
105 static int hf_sndcp_xid_rohc_profile_lsb
;
107 static int hf_sndcp_xid_V42bis_p0_spare
;
108 static int hf_sndcp_xid_V42bis_p0
;
109 static int hf_sndcp_xid_V42bis_p1_msb
;
110 static int hf_sndcp_xid_V42bis_p1_lsb
;
111 static int hf_sndcp_xid_V42bis_p2
;
112 static int hf_sndcp_xid_V44_c0
;
113 static int hf_sndcp_xid_V44_c0_spare
;
114 static int hf_sndcp_xid_V44_p0_spare
;
115 static int hf_sndcp_xid_V44_p0
;
116 static int hf_sndcp_xid_V44_p1t_msb
;
117 static int hf_sndcp_xid_V44_p1t_lsb
;
118 static int hf_sndcp_xid_V44_p1r_msb
;
119 static int hf_sndcp_xid_V44_p1r_lsb
;
120 static int hf_sndcp_xid_V44_p3t_msb
;
121 static int hf_sndcp_xid_V44_p3t_lsb
;
122 static int hf_sndcp_xid_V44_p3r_msb
;
123 static int hf_sndcp_xid_V44_p3r_lsb
;
126 /* Initialize the subtree pointers
128 static int ett_sndcp_xid
;
129 static int ett_sndcp_xid_version_field
;
130 static int ett_sndcp_comp_field
;
132 static void parse_compression_parameters(tvbuff_t
*tvb
, proto_tree
*tree
, bool dcomp
);
133 /******************************************************/
134 /* Compression algorithms element dissector functions */
135 /******************************************************/
136 static uint16_t parse_applicable_nsapi(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
138 uint8_t nsapi_byte1
, nsapi_byte2
;
139 nsapi_byte1
= tvb_get_uint8(tvb
, offset
);
140 nsapi_byte2
= tvb_get_uint8(tvb
, offset
+1);
142 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_15
, tvb
, offset
, 1, nsapi_byte1
);
143 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_14
, tvb
, offset
, 1, nsapi_byte1
);
144 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_13
, tvb
, offset
, 1, nsapi_byte1
);
145 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_12
, tvb
, offset
, 1, nsapi_byte1
);
146 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_11
, tvb
, offset
, 1, nsapi_byte1
);
147 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_10
, tvb
, offset
, 1, nsapi_byte1
);
148 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_9
, tvb
, offset
, 1, nsapi_byte1
);
149 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_8
, tvb
, offset
, 1, nsapi_byte1
);
151 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_7
, tvb
, offset
+1, 1, nsapi_byte2
);
152 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_6
, tvb
, offset
+1, 1, nsapi_byte2
);
153 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_5
, tvb
, offset
+1, 1, nsapi_byte2
);
154 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_spare
, tvb
, offset
+1, 1, nsapi_byte2
);
159 static uint16_t parse_rfc1144_s0(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
162 s0
= tvb_get_uint8(tvb
, offset
);
164 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc1144_s0
, tvb
, offset
, 1, s0
);
169 static uint16_t parse_rfc2507_f_max_period(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
171 uint8_t f_max_period_byte1
, f_max_period_byte2
;
172 f_max_period_byte1
= tvb_get_uint8(tvb
, offset
);
173 f_max_period_byte2
= tvb_get_uint8(tvb
, offset
+1);
175 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_period_msb
, tvb
, offset
, 1, f_max_period_byte1
);
176 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_period_lsb
, tvb
, offset
, 1, f_max_period_byte2
);
181 static uint16_t parse_rfc2507_f_max_time(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
184 f_max_time
= tvb_get_uint8(tvb
, offset
);
186 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_time
, tvb
, offset
, 1, f_max_time
);
191 static uint16_t parse_rfc2507_max_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
194 max_header
= tvb_get_uint8(tvb
, offset
);
196 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_max_header
, tvb
, offset
, 1, max_header
);
201 static uint16_t parse_rfc2507_tcp_space(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
204 tcp_space
= tvb_get_uint8(tvb
, offset
);
206 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_tcp_space
, tvb
, offset
, 1, tcp_space
);
211 static uint16_t parse_rfc2507_non_tcp_space(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
213 uint8_t tcp_space_msb
, tcp_space_lsb
;
214 tcp_space_msb
= tvb_get_uint8(tvb
, offset
);
215 tcp_space_lsb
= tvb_get_uint8(tvb
, offset
+1);
217 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_non_tcp_space_msb
, tvb
, offset
, 1, tcp_space_msb
);
218 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_non_tcp_space_lsb
, tvb
, offset
, 1, tcp_space_lsb
);
223 static uint16_t parse_rohc_max_cid(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
225 uint8_t max_cid_msb
, max_cid_lsb
;
226 max_cid_msb
= tvb_get_uint8(tvb
, offset
);
227 max_cid_lsb
= tvb_get_uint8(tvb
, offset
+1);
229 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_spare
, tvb
, offset
, 1, max_cid_msb
);
230 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_msb
, tvb
, offset
, 1, max_cid_msb
);
231 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_lsb
, tvb
, offset
+1, 1, max_cid_lsb
);
235 static uint16_t parse_rohc_max_header(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
239 max_header
= tvb_get_uint8(tvb
, offset
+1);
241 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_header
, tvb
, offset
+1, 1, max_header
);
246 static uint16_t parse_rohc_profile(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
248 uint8_t profile_msb
, profile_lsb
;
249 profile_msb
= tvb_get_uint8(tvb
, offset
);
250 profile_lsb
= tvb_get_uint8(tvb
, offset
+1);
252 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_profile_msb
, tvb
, offset
, 1, profile_msb
);
253 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_profile_lsb
, tvb
, offset
+1, 1, profile_lsb
);
258 static uint16_t parse_V42bis_p0(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
262 p0
= tvb_get_uint8(tvb
, offset
);
264 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p0_spare
, tvb
, offset
, 1, p0
);
265 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p0
, tvb
, offset
, 1, p0
);
270 static uint16_t parse_V42bis_p1(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
272 uint8_t p1_msb
, p1_lsb
;
274 p1_msb
= tvb_get_uint8(tvb
, offset
);
275 p1_lsb
= tvb_get_uint8(tvb
, offset
+1);
277 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p1_msb
, tvb
, offset
, 1, p1_msb
);
278 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p1_lsb
, tvb
, offset
+1, 1, p1_lsb
);
283 static uint16_t parse_V42bis_p2(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
287 p2
= tvb_get_uint8(tvb
, offset
);
289 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p2
, tvb
, offset
, 1, p2
);
294 static uint16_t parse_V44_c0(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
298 c0
= tvb_get_uint8(tvb
, offset
);
299 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_c0_spare
, tvb
, offset
, 1, c0
);
300 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_c0
, tvb
, offset
, 1, c0
);
305 static uint16_t parse_V44_p0(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
309 p0
= tvb_get_uint8(tvb
, offset
);
311 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p0_spare
, tvb
, offset
, 1, p0
);
312 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p0
, tvb
, offset
, 1, p0
);
318 static uint16_t parse_V44_p1t(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
320 uint8_t p1t_msb
, p1t_lsb
;
322 p1t_msb
= tvb_get_uint8(tvb
, offset
);
323 p1t_lsb
= tvb_get_uint8(tvb
, offset
+1);
325 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1t_msb
, tvb
, offset
, 1, p1t_msb
);
326 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1t_lsb
, tvb
, offset
+1, 1, p1t_lsb
);
331 static uint16_t parse_V44_p1r(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
333 uint8_t p1r_msb
, p1r_lsb
;
335 p1r_msb
= tvb_get_uint8(tvb
, offset
);
336 p1r_lsb
= tvb_get_uint8(tvb
, offset
+1);
338 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1r_msb
, tvb
, offset
, 1, p1r_msb
);
339 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1r_lsb
, tvb
, offset
+1, 1, p1r_lsb
);
344 static uint16_t parse_V44_p3t(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
346 uint8_t p3t_msb
, p3t_lsb
;
348 p3t_msb
= tvb_get_uint8(tvb
, offset
);
349 p3t_lsb
= tvb_get_uint8(tvb
, offset
+1);
351 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3t_msb
, tvb
, offset
, 1, p3t_msb
);
352 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3t_lsb
, tvb
, offset
+1, 1, p3t_lsb
);
357 static uint16_t parse_V44_p3r(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t offset
)
359 uint8_t p3r_msb
, p3r_lsb
;
361 p3r_msb
= tvb_get_uint8(tvb
, offset
);
362 p3r_lsb
= tvb_get_uint8(tvb
, offset
+1);
364 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3r_msb
, tvb
, offset
, 1, p3r_msb
);
365 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3r_lsb
, tvb
, offset
+1, 1, p3r_lsb
);
371 /***************************************************/
372 /* Compression algorithms element dissector arrays */
373 /***************************************************/
374 static uint16_t (*rfc1144_elem_fcn
[])(tvbuff_t
*, proto_tree
*, uint16_t) = {
375 parse_applicable_nsapi
,
381 static uint16_t (*rfc2507_elem_fcn
[])(tvbuff_t
*, proto_tree
*, uint16_t) = {
382 parse_applicable_nsapi
,
383 parse_rfc2507_f_max_period
,
384 parse_rfc2507_f_max_time
,
385 parse_rfc2507_max_header
,
386 parse_rfc2507_tcp_space
,
387 parse_rfc2507_non_tcp_space
,
391 static uint16_t (*rohc_elem_fcn
[])(tvbuff_t
*, proto_tree
*, uint16_t) = {
392 parse_applicable_nsapi
,
394 parse_rohc_max_header
,
395 parse_rohc_profile
, /* Profile 1 */
396 parse_rohc_profile
, /* Profile 2 */
397 parse_rohc_profile
, /* Profile 3 */
398 parse_rohc_profile
, /* Profile 4 */
399 parse_rohc_profile
, /* Profile 5 */
400 parse_rohc_profile
, /* Profile 6 */
401 parse_rohc_profile
, /* Profile 7 */
402 parse_rohc_profile
, /* Profile 8 */
403 parse_rohc_profile
, /* Profile 9 */
404 parse_rohc_profile
, /* Profile 10 */
405 parse_rohc_profile
, /* Profile 11 */
406 parse_rohc_profile
, /* Profile 12 */
407 parse_rohc_profile
, /* Profile 13 */
408 parse_rohc_profile
, /* Profile 14 */
409 parse_rohc_profile
, /* Profile 15 */
410 parse_rohc_profile
, /* Profile 16 */
414 /* Array containing the number of pcomp and the function array pointer */
415 static algo_parameters_t pcomp_algo_pars
[] = {
416 {2, rfc1144_elem_fcn
},
417 {5, rfc2507_elem_fcn
},
421 /* Data compression algorithms */
423 static uint16_t (*v42bis_elem_fcn
[])(tvbuff_t
*, proto_tree
*, uint16_t) = {
424 parse_applicable_nsapi
,
431 static uint16_t (*v44_elem_fcn
[])(tvbuff_t
*, proto_tree
*, uint16_t) = {
432 parse_applicable_nsapi
,
442 /* Array containing the number of dcomp and the function array pointer */
443 static algo_parameters_t dcomp_algo_pars
[] = {
444 {1, v42bis_elem_fcn
},
449 /* Code to actually dissect the packets
452 dissect_sndcp_xid(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
454 /* Set up structures needed to add the protocol subtree and manage it
456 proto_item
*ti
, *dcomp_item
;
457 proto_tree
*sndcp_tree
, *version_tree
, *dcomp_tree
, *pcomp_tree
;
458 uint16_t offset
= 0, l3_param_len
;
459 uint8_t parameter_type
, parameter_len
;
461 /* create display subtree for the protocol
463 ti
= proto_tree_add_item(tree
, proto_sndcp_xid
, tvb
, 0, -1, ENC_NA
);
464 sndcp_tree
= proto_item_add_subtree(ti
, ett_sndcp_xid
);
465 l3_param_len
= tvb_reported_length(tvb
);
467 while (offset
< l3_param_len
-1)
469 parameter_type
= tvb_get_uint8(tvb
, offset
);
470 parameter_len
= tvb_get_uint8(tvb
, offset
+1);
472 if (parameter_type
== SNDCP_VERSION_PAR_TYPE
)
474 uint8_t value
= tvb_get_uint8(tvb
, offset
+2);
475 version_tree
= proto_tree_add_subtree_format(sndcp_tree
, tvb
, offset
, parameter_len
+2,
476 ett_sndcp_xid_version_field
, NULL
, "Version (SNDCP version number) - Value %d", value
);
478 proto_tree_add_uint(version_tree
, hf_sndcp_xid_type
, tvb
, offset
,
480 proto_tree_add_uint(version_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
482 proto_tree_add_uint(version_tree
, hf_sndcp_xid_value
, tvb
, offset
+2,
487 else if (parameter_type
== DATA_COMPRESSION_PAR_TYPE
)
489 tvbuff_t
* dcomp_tvb
;
491 dcomp_tree
= proto_tree_add_subtree(sndcp_tree
, tvb
, offset
, parameter_len
+2,
492 ett_sndcp_comp_field
, &dcomp_item
, "Data Compression");
493 proto_tree_add_uint(dcomp_tree
, hf_sndcp_xid_type
, tvb
, offset
,
495 proto_tree_add_uint(dcomp_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
499 dcomp_tvb
= tvb_new_subset_length(tvb
, offset
, parameter_len
);
500 parse_compression_parameters(dcomp_tvb
, dcomp_tree
, true);
501 offset
+= parameter_len
;
505 else if (parameter_type
== PROTOCOL_COMPRESSION_PAR_TYPE
)
507 tvbuff_t
* pcomp_tvb
;
509 pcomp_tree
= proto_tree_add_subtree(sndcp_tree
, tvb
, offset
, parameter_len
+2,
510 ett_sndcp_comp_field
, NULL
, "Protocol Control Information Compression");
511 proto_tree_add_uint(pcomp_tree
, hf_sndcp_xid_type
, tvb
, offset
,
513 proto_tree_add_uint(pcomp_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
517 pcomp_tvb
= tvb_new_subset_length(tvb
, offset
, parameter_len
);
518 parse_compression_parameters(pcomp_tvb
, pcomp_tree
, false);
519 offset
+= parameter_len
;
524 break; /* error: exit */
527 return tvb_captured_length(tvb
);
531 static void parse_compression_parameters(tvbuff_t
*tvb
, proto_tree
*tree
, bool dcomp
)
533 uint8_t entity
, len
, algo_id
;
534 uint8_t number_of_comp
, i
;
536 algo_parameters_t
* algo_pars
;
537 uint8_t function_index
;
538 proto_tree
*comp_entity_tree
= NULL
;
539 uint16_t tvb_len
, offset
=0 , new_offset
, entity_offset
;
540 value_string
const * comp_algo_str
;
542 tvb_len
= tvb_reported_length(tvb
);
543 if (tvb_len
< 3) return; /* entity, algo and length bytes should always be present 6.5.1.1 and 6.6.1.1 */
545 /* Loop to decode each entity (cf Figure 10) */
546 while (offset
< tvb_len
)
548 /* Read the entity byte */
549 entity
= tvb_get_uint8(tvb
, offset
);
550 p_bit_set
= ((entity
& 0x80) == 0x80) ? 1 : 0;
551 entity
= entity
& 0x1F;
553 /* P bit is set: means that algo identifier and dcomp are present */
556 /* Read the algorithm id. TODO: store the algo in a different variable for each different entity */
557 algo_id
= tvb_get_uint8(tvb
, offset
+1) & 0x1F;
559 /* sanity check: check that the algo id that will be used inside the array has a valid range */
562 if(algo_id
<= ALGO_V44
)
564 algo_pars
= dcomp_algo_pars
;
565 dcomp_entity_algo_id
[entity
] = algo_id
;
566 comp_algo_str
= sndcp_xid_dcomp_algo_str
;
572 if (algo_id
<= ALGO_ROHC
)
574 algo_pars
= pcomp_algo_pars
;
575 pcomp_entity_algo_id
[entity
] = algo_id
;
576 comp_algo_str
= sndcp_xid_pcomp_algo_str
;
581 /* Read the length */
582 len
= tvb_get_uint8(tvb
, offset
+2);
584 comp_entity_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, len
+ 3,
585 ett_sndcp_comp_field
, NULL
, "Entity %d, Algorithm %s",
586 entity
& 0x1F, val_to_str(algo_id
& 0x1F, comp_algo_str
,"Undefined Algorithm Identifier:%X"));
588 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_pbit
, tvb
, offset
, 1, p_bit_set
<< 7);
589 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte1
, tvb
, offset
, 1, entity
);
590 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_entity
, tvb
, offset
, 1, entity
);
592 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte2
, tvb
, offset
+1, 1, algo_id
);
593 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_algo_id
, tvb
, offset
+1, 1, algo_id
);
594 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_len
, tvb
, offset
+2, 1, len
);
596 /* Read the dcomp/pcomp field */
597 offset
+= 3; /* entity_offset will be used as the offset from length byte */
598 number_of_comp
= algo_pars
[algo_id
].nb_of_dcomp_pcomp
;
600 for (i
=0; i
< (number_of_comp
+1) / 2; i
++)
604 byte
= tvb_get_uint8(tvb
, offset
+i
);
605 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp
[2*i
], tvb
, offset
+i
, 1, byte
);
607 /* if there is an even number of dcomp/pcomp */
608 if (2*i
+1 < number_of_comp
)
610 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp
[2*i
+1], tvb
, offset
+i
, 1, byte
);
612 /* else there is padding in the end */
615 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare
, tvb
, offset
+i
, 1, byte
);
622 /* Process the elements byte per byte */
623 while ((entity_offset
< len
) && (algo_pars
[algo_id
].func_array_ptr
[function_index
] != NULL
))
625 new_offset
= offset
+entity_offset
;
626 entity_offset
+= algo_pars
[algo_id
].func_array_ptr
[function_index
](tvb
, comp_entity_tree
, new_offset
);
629 offset
+= entity_offset
;
632 else /* P bit not set */
634 len
= tvb_get_uint8(tvb
, offset
+1);
638 algo_pars
= dcomp_algo_pars
;
639 algo_id
= dcomp_entity_algo_id
[entity
];
640 comp_algo_str
= sndcp_xid_dcomp_algo_str
;
644 algo_pars
= pcomp_algo_pars
;
645 algo_id
= pcomp_entity_algo_id
[entity
];
646 comp_algo_str
= sndcp_xid_pcomp_algo_str
;
648 comp_entity_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, len
+ 2,
649 ett_sndcp_comp_field
, NULL
, "Entity %d decoded as Algorithm %s",
650 entity
& 0x1F, val_to_str(algo_id
& 0x1F, comp_algo_str
,"Undefined Algorithm Identifier:%X"));
652 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_pbit
, tvb
, offset
, 1, p_bit_set
<< 7);
653 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte1
, tvb
, offset
, 1, entity
);
654 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_entity
, tvb
, offset
, 1, entity
);
655 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_len
, tvb
, offset
+2, 1, len
);
663 if (algo_id
> ALGO_V44
) return;
667 if (algo_id
> ALGO_ROHC
) return;
670 /* Process the elements byte per byte */
671 while ((entity_offset
< len
) && (algo_pars
[algo_id
].func_array_ptr
[function_index
] != NULL
))
673 new_offset
= offset
+entity_offset
;
674 entity_offset
+= algo_pars
[algo_id
].func_array_ptr
[function_index
](tvb
, comp_entity_tree
, new_offset
);
677 offset
+= entity_offset
;
681 /* Else if length is lower than 3, the packet is not correctly formatted */
684 /* Register the protocol with Wireshark
685 this format is required because a script is used to build the C function
686 that calls all the protocol registration.
690 proto_register_sndcp_xid(void)
692 /* Setup list of header fields
694 static hf_register_info hf
[] = {
695 /* L3 XID Parameter Parsing Info */
697 { "Parameter type","llcgprs.l3xidpartype", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
699 { "Length","llcgprs.l3xidparlen", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
700 {&hf_sndcp_xid_value
,
701 { "Value","llcgprs.l3xidparvalue", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
702 {&hf_sndcp_xid_comp_pbit
,
703 { "P bit","llcgprs.l3xiddcomppbit", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
704 {&hf_sndcp_xid_comp_spare_byte1
,
705 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0x60, "Ignore", HFILL
}},
706 {&hf_sndcp_xid_comp_entity
,
707 { "Entity","llcgprs.l3xidentity", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Data", HFILL
}},
708 {&hf_sndcp_xid_comp_spare_byte2
,
709 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0xE0, "Ignore", HFILL
}},
710 {&hf_sndcp_xid_comp_algo_id
,
711 { "Algorithm identifier","llcgprs.l3xidalgoid", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Data", HFILL
}},
712 {&hf_sndcp_xid_comp_len
,
713 { "Length","llcgprs.l3xidcomplen", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
714 {&hf_sndcp_xid_comp
[0],
715 { "DCOMP1","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
716 {&hf_sndcp_xid_comp
[1],
717 { "DCOMP2","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
718 {&hf_sndcp_xid_comp
[2],
719 { "DCOMP3","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
720 {&hf_sndcp_xid_comp
[3],
721 { "DCOMP4","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
722 {&hf_sndcp_xid_comp
[4],
723 { "DCOMP5","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
724 {&hf_sndcp_xid_comp
[5],
725 { "DCOMP6","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
726 {&hf_sndcp_xid_comp
[6],
727 { "DCOMP7","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
728 {&hf_sndcp_xid_comp
[7],
729 { "DCOMP8","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
730 {&hf_sndcp_xid_comp
[8],
731 { "DCOMP9","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
732 {&hf_sndcp_xid_comp
[9],
733 { "DCOMP10","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
734 {&hf_sndcp_xid_comp
[10],
735 { "DCOMP11","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
736 {&hf_sndcp_xid_comp
[11],
737 { "DCOMP12","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
738 {&hf_sndcp_xid_comp
[12],
739 { "DCOMP13","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
740 {&hf_sndcp_xid_comp
[13],
741 { "DCOMP14","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
742 {&hf_sndcp_xid_comp
[14],
743 { "DCOMP15","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
744 {&hf_sndcp_xid_comp_spare
,
745 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0x0F, "Ignore", HFILL
}},
746 {&hf_element_applicable_nsapi_15
,
747 { "NSAPI 15","sndcpxid.nsapi15", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
748 {&hf_element_applicable_nsapi_14
,
749 { "NSAPI 14","sndcpxid.nsapi14", FT_UINT8
, BASE_DEC
, NULL
, 0x40, "Data", HFILL
}},
750 {&hf_element_applicable_nsapi_13
,
751 { "NSAPI 13","sndcpxid.nsapi13", FT_UINT8
, BASE_DEC
, NULL
, 0x20, "Data", HFILL
}},
752 {&hf_element_applicable_nsapi_12
,
753 { "NSAPI 12","sndcpxid.nsapi12", FT_UINT8
, BASE_DEC
, NULL
, 0x10, "Data", HFILL
}},
754 {&hf_element_applicable_nsapi_11
,
755 { "NSAPI 11","sndcpxid.nsapi11", FT_UINT8
, BASE_DEC
, NULL
, 0x08, "Data", HFILL
}},
756 {&hf_element_applicable_nsapi_10
,
757 { "NSAPI 10","sndcpxid.nsapi10", FT_UINT8
, BASE_DEC
, NULL
, 0x04, "Data", HFILL
}},
758 {&hf_element_applicable_nsapi_9
,
759 { "NSAPI 9","sndcpxid.nsapi9", FT_UINT8
, BASE_DEC
, NULL
, 0x02, "Data", HFILL
}},
760 {&hf_element_applicable_nsapi_8
,
761 { "NSAPI 8","sndcpxid.nsapi8", FT_UINT8
, BASE_DEC
, NULL
, 0x01, "Data", HFILL
}},
762 {&hf_element_applicable_nsapi_7
,
763 { "NSAPI 7","sndcpxid.nsapi7", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
764 {&hf_element_applicable_nsapi_6
,
765 { "NSAPI 6","sndcpxid.nsapi6", FT_UINT8
, BASE_DEC
, NULL
, 0x40, "Data", HFILL
}},
766 {&hf_element_applicable_nsapi_5
,
767 { "NSAPI 5","sndcpxid.nsapi5", FT_UINT8
, BASE_DEC
, NULL
, 0x20, "Data", HFILL
}},
768 {&hf_element_applicable_nsapi_spare
,
769 { "Spare","sndcpxid.spare", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Ignore", HFILL
}},
770 {&hf_sndcp_xid_rfc1144_s0
,
771 { "S0 - 1","sndcpxid.rfc1144_s0", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
772 {&hf_sndcp_xid_rfc2507_f_max_period_msb
,
773 { "F Max Period MSB","sndcpxid.rfc2507_f_max_period_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
774 {&hf_sndcp_xid_rfc2507_f_max_period_lsb
,
775 { "F Max Period LSB","sndcpxid.rfc2507_f_max_period_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
776 {&hf_sndcp_xid_rfc2507_f_max_time
,
777 { "F Max Time","sndcpxid.rfc2507_f_max_time", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
778 {&hf_sndcp_xid_rfc2507_max_header
,
779 { "Max Header","sndcpxid.rfc2507_max_header", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
780 {&hf_sndcp_xid_rfc2507_tcp_space
,
781 { "TCP Space","sndcpxid.rfc2507_max_tcp_space", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
782 {&hf_sndcp_xid_rfc2507_non_tcp_space_msb
,
783 { "TCP non space MSB","sndcpxid.rfc2507_max_non_tcp_space_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
784 {&hf_sndcp_xid_rfc2507_non_tcp_space_lsb
,
785 { "TCP non space LSB","sndcpxid.rfc2507_max_non_tcp_space_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
786 {&hf_sndcp_xid_rohc_max_cid_spare
,
787 { "Spare","sndcpxid.rohc_max_cid_spare", FT_UINT8
, BASE_DEC
, NULL
, 0xC0, "Ignore", HFILL
}},
788 {&hf_sndcp_xid_rohc_max_cid_msb
,
789 { "Max CID MSB","sndcpxid.rohc_max_cid_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x3F, "Data", HFILL
}},
790 {&hf_sndcp_xid_rohc_max_cid_lsb
,
791 { "Max CID LSB","sndcpxid.rohc_max_cid_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
792 {&hf_sndcp_xid_rohc_max_header
,
793 { "Max header","sndcpxid.rohc_max_header", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "Data", HFILL
}},
794 {&hf_sndcp_xid_rohc_profile_msb
,
795 { "Profile MSB","sndcpxid.rohc_profile_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
796 {&hf_sndcp_xid_rohc_profile_lsb
,
797 { "Profile LSB","sndcpxid.rohc_profile_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
798 {&hf_sndcp_xid_V42bis_p0_spare
,
799 { "Spare","sndcpxid.V42bis_p0spare", FT_UINT8
, BASE_DEC
, NULL
, 0xFC, "Ignore", HFILL
}},
800 {&hf_sndcp_xid_V42bis_p0
,
801 { "P0","sndcpxid.V42bis_p0", FT_UINT8
, BASE_HEX
, NULL
, 0x03, "Data", HFILL
}},
802 {&hf_sndcp_xid_V42bis_p1_msb
,
803 { "P1 MSB","sndcpxid.V42bis_p1_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
804 {&hf_sndcp_xid_V42bis_p1_lsb
,
805 { "P1 LSB","sndcpxid.V42bis_p1_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
806 {&hf_sndcp_xid_V42bis_p2
,
807 { "P2","sndcpxid.V42bis_p2", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
808 {&hf_sndcp_xid_V44_c0_spare
,
809 { "P2","sndcpxid.V44_c0_spare", FT_UINT8
, BASE_HEX
, NULL
, 0x3F, "Ignore", HFILL
}},
810 {&hf_sndcp_xid_V44_c0
,
811 { "P2","sndcpxid.V44_c0", FT_UINT8
, BASE_HEX
, NULL
, 0xC0, "Data", HFILL
}},
812 {&hf_sndcp_xid_V44_p0_spare
,
813 { "Spare","sndcpxid.V44_p0spare", FT_UINT8
, BASE_DEC
, NULL
, 0xFC, "Ignore", HFILL
}},
814 {&hf_sndcp_xid_V44_p0
,
815 { "P0","sndcpxid.V44_p0", FT_UINT8
, BASE_HEX
, NULL
, 0x03, "Data", HFILL
}},
816 {&hf_sndcp_xid_V44_p1t_msb
,
817 { "P1t MSB","sndcpxid.V44_p1t_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
818 {&hf_sndcp_xid_V44_p1t_lsb
,
819 { "P1t LSB","sndcpxid.V44_p1t_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
820 {&hf_sndcp_xid_V44_p1r_msb
,
821 { "P1r MSB","sndcpxid.V44_p1r_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
822 {&hf_sndcp_xid_V44_p1r_lsb
,
823 { "P1r LSB","sndcpxid.V44_p1r_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
824 {&hf_sndcp_xid_V44_p3t_msb
,
825 { "P3t MSB","sndcpxid.V44_p3t_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
826 {&hf_sndcp_xid_V44_p3t_lsb
,
827 { "P3t LSB","sndcpxid.V44_p3t_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
828 {&hf_sndcp_xid_V44_p3r_msb
,
829 { "P3r MSB","sndcpxid.V44_p3r_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
830 {&hf_sndcp_xid_V44_p3r_lsb
,
831 { "P3r LSB","sndcpxid.V44_p3r_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "Data", HFILL
}},
834 /* Setup protocol subtree array */
835 static int *ett
[] = {
837 &ett_sndcp_xid_version_field
,
838 &ett_sndcp_comp_field
841 /* Register the protocol name and description */
842 proto_sndcp_xid
= proto_register_protocol("Subnetwork Dependent Convergence Protocol XID",
843 "SNDCP XID", "sndcpxid");
845 /* Required function calls to register the header fields and subtrees used */
846 proto_register_field_array(proto_sndcp_xid
, hf
, array_length(hf
));
847 proto_register_subtree_array(ett
, array_length(ett
));
848 register_dissector("sndcpxid", dissect_sndcp_xid
, proto_sndcp_xid
);
852 * Editor modelines - https://www.wireshark.org/tools/modelines.html
857 * indent-tabs-mode: nil
860 * vi: set shiftwidth=4 tabstop=8 expandtab:
861 * :indentSize=4:tabSize=8:noTabs=true: