Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-sndcp-xid.c
blob16d115934ce457bd4fdfe83fe8867daa8ceb4ed3
1 /* packet-sndcp-xid.c
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
13 #include "config.h"
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
26 #define ALGO_V42BIS 0
27 #define ALGO_V44 1
28 #define ALGO_RFC1144 0
29 #define ALGO_RFC2507 1
30 #define ALGO_ROHC 2
32 void proto_register_sndcp_xid(void);
34 static const value_string sndcp_xid_dcomp_algo_str[] = {
35 {0x0, "V.42 bis"},
36 {0x1, "V.44"},
37 {0, NULL}
40 static const value_string sndcp_xid_pcomp_algo_str[] = {
41 {0x0, "RFC 1144"},
42 {0x1, "RFC 2507"},
43 {0x2, "ROHC (RFC 3095)"},
44 {0, NULL}
47 typedef struct
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);
51 } algo_parameters_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];
65 /* L3 XID parsing */
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);
156 return 2U;
159 static uint16_t parse_rfc1144_s0(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
161 uint8_t s0;
162 s0 = tvb_get_uint8(tvb, offset);
164 proto_tree_add_uint(tree, hf_sndcp_xid_rfc1144_s0, tvb, offset, 1, s0);
166 return 1U;
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);
178 return 2U;
181 static uint16_t parse_rfc2507_f_max_time(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
183 uint8_t f_max_time;
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);
188 return 1U;
191 static uint16_t parse_rfc2507_max_header(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
193 uint8_t max_header;
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);
198 return 1U;
201 static uint16_t parse_rfc2507_tcp_space(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
203 uint8_t tcp_space;
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);
208 return 1U;
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);
220 return 2U;
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);
233 return 2U;
235 static uint16_t parse_rohc_max_header(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
237 uint8_t max_header;
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);
243 return 2U;
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);
255 return 2U;
258 static uint16_t parse_V42bis_p0(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
260 uint8_t p0;
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);
267 return 1U;
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);
280 return 2U;
283 static uint16_t parse_V42bis_p2(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
285 uint8_t p2;
287 p2 = tvb_get_uint8(tvb, offset);
289 proto_tree_add_uint(tree, hf_sndcp_xid_V42bis_p2, tvb, offset, 1, p2);
291 return 1U;
294 static uint16_t parse_V44_c0(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
296 uint8_t c0;
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);
302 return 1U;
305 static uint16_t parse_V44_p0(tvbuff_t *tvb, proto_tree *tree, uint16_t offset)
307 uint8_t p0;
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);
314 return 1U;
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);
328 return 2U;
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);
341 return 2U;
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);
354 return 2U;
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);
367 return 2U;
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,
376 parse_rfc1144_s0,
377 NULL
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,
388 NULL
391 static uint16_t (*rohc_elem_fcn[])(tvbuff_t *, proto_tree *, uint16_t) = {
392 parse_applicable_nsapi,
393 parse_rohc_max_cid,
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 */
411 NULL
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},
418 {2, rohc_elem_fcn}
421 /* Data compression algorithms */
423 static uint16_t (*v42bis_elem_fcn[])(tvbuff_t *, proto_tree *, uint16_t) = {
424 parse_applicable_nsapi,
425 parse_V42bis_p0,
426 parse_V42bis_p1,
427 parse_V42bis_p2,
428 NULL
431 static uint16_t (*v44_elem_fcn[])(tvbuff_t *, proto_tree *, uint16_t) = {
432 parse_applicable_nsapi,
433 parse_V44_c0,
434 parse_V44_p0,
435 parse_V44_p1t,
436 parse_V44_p1r,
437 parse_V44_p3t,
438 parse_V44_p3r,
439 NULL
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},
445 {2, v44_elem_fcn},
449 /* Code to actually dissect the packets
451 static int
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,
479 1, parameter_type);
480 proto_tree_add_uint(version_tree, hf_sndcp_xid_len, tvb, offset+1,
481 1, parameter_len);
482 proto_tree_add_uint(version_tree, hf_sndcp_xid_value, tvb, offset+2,
483 1, value);
484 offset += 3;
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,
494 1, parameter_type);
495 proto_tree_add_uint(dcomp_tree, hf_sndcp_xid_len, tvb, offset+1,
496 1, parameter_len);
497 offset += 2;
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,
512 1, parameter_type);
513 proto_tree_add_uint(pcomp_tree, hf_sndcp_xid_len, tvb, offset+1,
514 1, parameter_len);
515 offset += 2;
517 pcomp_tvb = tvb_new_subset_length(tvb, offset, parameter_len);
518 parse_compression_parameters(pcomp_tvb, pcomp_tree, false);
519 offset += parameter_len;
522 else
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;
535 bool p_bit_set;
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 */
554 if (p_bit_set)
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 */
560 if (dcomp)
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;
568 else return;
570 else
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;
578 else return;
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++)
602 uint8_t byte;
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 */
613 else
615 proto_tree_add_uint(comp_entity_tree, hf_sndcp_xid_comp_spare, tvb, offset+i, 1, byte);
619 entity_offset = i;
620 function_index = 0;
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);
627 function_index++;
629 offset += entity_offset;
632 else /* P bit not set */
634 len = tvb_get_uint8(tvb, offset+1);
636 if (dcomp)
638 algo_pars = dcomp_algo_pars;
639 algo_id = dcomp_entity_algo_id[entity];
640 comp_algo_str = sndcp_xid_dcomp_algo_str;
642 else
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);
657 offset += 2;
658 entity_offset = 0;
659 function_index = 0;
661 if (dcomp)
663 if (algo_id > ALGO_V44) return;
665 else
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);
675 function_index++;
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.
689 void
690 proto_register_sndcp_xid(void)
692 /* Setup list of header fields
694 static hf_register_info hf[] = {
695 /* L3 XID Parameter Parsing Info */
696 {&hf_sndcp_xid_type,
697 { "Parameter type","llcgprs.l3xidpartype", FT_UINT8, BASE_DEC, NULL, 0x0, "Data", HFILL}},
698 {&hf_sndcp_xid_len,
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[] = {
836 &ett_sndcp_xid,
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
854 * Local variables:
855 * c-basic-offset: 4
856 * tab-width: 8
857 * indent-tabs-mode: nil
858 * End:
860 * vi: set shiftwidth=4 tabstop=8 expandtab:
861 * :indentSize=4:tabSize=8:noTabs=true: