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>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
34 /* Parameter types: TS 44.065 8
36 #define SNDCP_VERSION_PAR_TYPE 0
37 #define DATA_COMPRESSION_PAR_TYPE 1
38 #define PROTOCOL_COMPRESSION_PAR_TYPE 2
40 /* Algorithm identifiers: TS 44.065 6.6.1.1.4 and 6.5.1.1.4
44 #define ALGO_RFC1144 0
45 #define ALGO_RFC2507 1
48 static const value_string sndcp_xid_dcomp_algo_str
[] = {
54 static const value_string sndcp_xid_pcomp_algo_str
[] = {
57 {0x2, "ROHC (RFC 3095)"},
63 guint8 nb_of_dcomp_pcomp
; /* note that a DCOMP or a PCOMP is 4 bit wide */
64 guint16 (**func_array_ptr
) (tvbuff_t
*, proto_tree
*, guint16
);
67 /* Initialize the protocol and registered fields
69 static int proto_sndcp_xid
= -1;
71 /* These fields are used to store store the algorithm ID
72 * When the P bit is not set, try to decode the algo based on what whas stored.
73 * Entity ranges from 0 to 31 (6.5.1.1.3)
75 static guint8 dcomp_entity_algo_id
[32]={-1, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, -1, -1, -1, -1, -1,
77 -1, -1, -1, -1, -1, -1, -1, -1,
78 -1, -1, -1, -1, -1, -1, -1, -1};
79 static guint8 pcomp_entity_algo_id
[32]={-1, -1, -1, -1, -1, -1, -1, -1,
80 -1, -1, -1, -1, -1, -1, -1, -1,
81 -1, -1, -1, -1, -1, -1, -1, -1,
82 -1, -1, -1, -1, -1, -1, -1, -1};
87 static int hf_sndcp_xid_type
= -1;
88 static int hf_sndcp_xid_len
= -1;
89 static int hf_sndcp_xid_value
= -1;
90 static int hf_sndcp_xid_comp_pbit
= -1;
91 static int hf_sndcp_xid_comp_spare_byte1
= -1;
92 static int hf_sndcp_xid_comp_entity
= -1;
93 static int hf_sndcp_xid_comp_spare_byte2
= -1;
94 static int hf_sndcp_xid_comp_algo_id
= -1;
95 static int hf_sndcp_xid_comp_len
= -1;
96 /* There is currently a maximum of 15 DCOMP/PCOMP: 6.5.1.1.5 */
97 static int hf_sndcp_xid_comp
[15] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
98 static int hf_sndcp_xid_comp_spare
= -1;
100 static int hf_element_applicable_nsapi_15
= -1;
101 static int hf_element_applicable_nsapi_14
= -1;
102 static int hf_element_applicable_nsapi_13
= -1;
103 static int hf_element_applicable_nsapi_12
= -1;
104 static int hf_element_applicable_nsapi_11
= -1;
105 static int hf_element_applicable_nsapi_10
= -1;
106 static int hf_element_applicable_nsapi_9
= -1;
107 static int hf_element_applicable_nsapi_8
= -1;
108 static int hf_element_applicable_nsapi_7
= -1;
109 static int hf_element_applicable_nsapi_6
= -1;
110 static int hf_element_applicable_nsapi_5
= -1;
111 static int hf_element_applicable_nsapi_spare
= -1;
113 static int hf_sndcp_xid_rfc1144_s0
= -1;
114 static int hf_sndcp_xid_rfc2507_f_max_period_msb
= -1;
115 static int hf_sndcp_xid_rfc2507_f_max_period_lsb
= -1;
116 static int hf_sndcp_xid_rfc2507_f_max_time
= -1;
117 static int hf_sndcp_xid_rfc2507_max_header
= -1;
118 static int hf_sndcp_xid_rfc2507_tcp_space
= -1;
119 static int hf_sndcp_xid_rfc2507_non_tcp_space_msb
= -1;
120 static int hf_sndcp_xid_rfc2507_non_tcp_space_lsb
= -1;
121 static int hf_sndcp_xid_rohc_max_cid_spare
= -1;
122 static int hf_sndcp_xid_rohc_max_cid_msb
= -1;
123 static int hf_sndcp_xid_rohc_max_cid_lsb
= -1;
124 static int hf_sndcp_xid_rohc_max_header
= -1;
125 static int hf_sndcp_xid_rohc_profile_msb
= -1;
126 static int hf_sndcp_xid_rohc_profile_lsb
= -1;
128 static int hf_sndcp_xid_V42bis_p0_spare
= -1;
129 static int hf_sndcp_xid_V42bis_p0
= -1;
130 static int hf_sndcp_xid_V42bis_p1_msb
= -1;
131 static int hf_sndcp_xid_V42bis_p1_lsb
= -1;
132 static int hf_sndcp_xid_V42bis_p2
= -1;
133 static int hf_sndcp_xid_V44_c0
= -1;
134 static int hf_sndcp_xid_V44_c0_spare
= -1;
135 static int hf_sndcp_xid_V44_p0_spare
= -1;
136 static int hf_sndcp_xid_V44_p0
= -1;
137 static int hf_sndcp_xid_V44_p1t_msb
= -1;
138 static int hf_sndcp_xid_V44_p1t_lsb
= -1;
139 static int hf_sndcp_xid_V44_p1r_msb
= -1;
140 static int hf_sndcp_xid_V44_p1r_lsb
= -1;
141 static int hf_sndcp_xid_V44_p3t_msb
= -1;
142 static int hf_sndcp_xid_V44_p3t_lsb
= -1;
143 static int hf_sndcp_xid_V44_p3r_msb
= -1;
144 static int hf_sndcp_xid_V44_p3r_lsb
= -1;
147 /* Initialize the subtree pointers
149 static gint ett_sndcp_xid
= -1;
150 static gint ett_sndcp_xid_version_field
= -1;
151 static gint ett_sndcp_comp_field
= -1;
153 static void parse_compression_parameters(tvbuff_t
*tvb
, proto_tree
*tree
, gboolean dcomp
);
154 /******************************************************/
155 /* Compression algorithms element dissector functions */
156 /******************************************************/
157 static guint16
parse_applicable_nsapi(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
159 guint8 nsapi_byte1
, nsapi_byte2
;
160 nsapi_byte1
= tvb_get_guint8(tvb
, offset
);
161 nsapi_byte2
= tvb_get_guint8(tvb
, offset
+1);
163 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_15
, tvb
, offset
, 1, nsapi_byte1
);
164 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_14
, tvb
, offset
, 1, nsapi_byte1
);
165 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_13
, tvb
, offset
, 1, nsapi_byte1
);
166 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_12
, tvb
, offset
, 1, nsapi_byte1
);
167 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_11
, tvb
, offset
, 1, nsapi_byte1
);
168 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_10
, tvb
, offset
, 1, nsapi_byte1
);
169 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_9
, tvb
, offset
, 1, nsapi_byte1
);
170 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_8
, tvb
, offset
, 1, nsapi_byte1
);
172 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_7
, tvb
, offset
+1, 1, nsapi_byte2
);
173 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_6
, tvb
, offset
+1, 1, nsapi_byte2
);
174 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_5
, tvb
, offset
+1, 1, nsapi_byte2
);
175 proto_tree_add_uint(tree
, hf_element_applicable_nsapi_spare
, tvb
, offset
+1, 1, nsapi_byte2
);
180 static guint16
parse_rfc1144_s0(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
183 s0
= tvb_get_guint8(tvb
, offset
);
185 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc1144_s0
, tvb
, offset
, 1, s0
);
190 static guint16
parse_rfc2507_f_max_period(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
192 guint8 f_max_period_byte1
, f_max_period_byte2
;
193 f_max_period_byte1
= tvb_get_guint8(tvb
, offset
);
194 f_max_period_byte2
= tvb_get_guint8(tvb
, offset
+1);
196 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_period_msb
, tvb
, offset
, 1, f_max_period_byte1
);
197 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_period_lsb
, tvb
, offset
, 1, f_max_period_byte2
);
202 static guint16
parse_rfc2507_f_max_time(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
205 f_max_time
= tvb_get_guint8(tvb
, offset
);
207 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_f_max_time
, tvb
, offset
, 1, f_max_time
);
212 static guint16
parse_rfc2507_max_header(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
215 max_header
= tvb_get_guint8(tvb
, offset
);
217 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_max_header
, tvb
, offset
, 1, max_header
);
222 static guint16
parse_rfc2507_tcp_space(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
225 tcp_space
= tvb_get_guint8(tvb
, offset
);
227 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_tcp_space
, tvb
, offset
, 1, tcp_space
);
232 static guint16
parse_rfc2507_non_tcp_space(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
234 guint8 tcp_space_msb
, tcp_space_lsb
;
235 tcp_space_msb
= tvb_get_guint8(tvb
, offset
);
236 tcp_space_lsb
= tvb_get_guint8(tvb
, offset
+1);
238 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_non_tcp_space_msb
, tvb
, offset
, 1, tcp_space_msb
);
239 proto_tree_add_uint(tree
, hf_sndcp_xid_rfc2507_non_tcp_space_lsb
, tvb
, offset
, 1, tcp_space_lsb
);
244 static guint16
parse_rohc_max_cid(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
246 guint8 max_cid_msb
, max_cid_lsb
;
247 max_cid_msb
= tvb_get_guint8(tvb
, offset
);
248 max_cid_lsb
= tvb_get_guint8(tvb
, offset
+1);
250 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_spare
, tvb
, offset
, 1, max_cid_msb
);
251 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_msb
, tvb
, offset
, 1, max_cid_msb
);
252 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_cid_lsb
, tvb
, offset
+1, 1, max_cid_lsb
);
256 static guint16
parse_rohc_max_header(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
260 max_header
= tvb_get_guint8(tvb
, offset
+1);
262 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_max_header
, tvb
, offset
+1, 1, max_header
);
267 static guint16
parse_rohc_profile(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
269 guint8 profile_msb
, profile_lsb
;
270 profile_msb
= tvb_get_guint8(tvb
, offset
);
271 profile_lsb
= tvb_get_guint8(tvb
, offset
+1);
273 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_profile_msb
, tvb
, offset
, 1, profile_msb
);
274 proto_tree_add_uint(tree
, hf_sndcp_xid_rohc_profile_lsb
, tvb
, offset
+1, 1, profile_lsb
);
279 static guint16
parse_V42bis_p0(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
283 p0
= tvb_get_guint8(tvb
, offset
);
285 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p0_spare
, tvb
, offset
, 1, p0
);
286 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p0
, tvb
, offset
, 1, p0
);
291 static guint16
parse_V42bis_p1(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
293 guint8 p1_msb
, p1_lsb
;
295 p1_msb
= tvb_get_guint8(tvb
, offset
);
296 p1_lsb
= tvb_get_guint8(tvb
, offset
+1);
298 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p1_msb
, tvb
, offset
, 1, p1_msb
);
299 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p1_lsb
, tvb
, offset
+1, 1, p1_lsb
);
304 static guint16
parse_V42bis_p2(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
308 p2
= tvb_get_guint8(tvb
, offset
);
310 proto_tree_add_uint(tree
, hf_sndcp_xid_V42bis_p2
, tvb
, offset
, 1, p2
);
315 static guint16
parse_V44_c0(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
319 c0
= tvb_get_guint8(tvb
, offset
);
320 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_c0_spare
, tvb
, offset
, 1, c0
);
321 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_c0
, tvb
, offset
, 1, c0
);
326 static guint16
parse_V44_p0(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
330 p0
= tvb_get_guint8(tvb
, offset
);
332 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p0_spare
, tvb
, offset
, 1, p0
);
333 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p0
, tvb
, offset
, 1, p0
);
339 static guint16
parse_V44_p1t(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
341 guint8 p1t_msb
, p1t_lsb
;
343 p1t_msb
= tvb_get_guint8(tvb
, offset
);
344 p1t_lsb
= tvb_get_guint8(tvb
, offset
+1);
346 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1t_msb
, tvb
, offset
, 1, p1t_msb
);
347 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1t_lsb
, tvb
, offset
+1, 1, p1t_lsb
);
352 static guint16
parse_V44_p1r(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
354 guint8 p1r_msb
, p1r_lsb
;
356 p1r_msb
= tvb_get_guint8(tvb
, offset
);
357 p1r_lsb
= tvb_get_guint8(tvb
, offset
+1);
359 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1r_msb
, tvb
, offset
, 1, p1r_msb
);
360 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p1r_lsb
, tvb
, offset
+1, 1, p1r_lsb
);
365 static guint16
parse_V44_p3t(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
367 guint8 p3t_msb
, p3t_lsb
;
369 p3t_msb
= tvb_get_guint8(tvb
, offset
);
370 p3t_lsb
= tvb_get_guint8(tvb
, offset
+1);
372 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3t_msb
, tvb
, offset
, 1, p3t_msb
);
373 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3t_lsb
, tvb
, offset
+1, 1, p3t_lsb
);
378 static guint16
parse_V44_p3r(tvbuff_t
*tvb
, proto_tree
*tree
, guint16 offset
)
380 guint8 p3r_msb
, p3r_lsb
;
382 p3r_msb
= tvb_get_guint8(tvb
, offset
);
383 p3r_lsb
= tvb_get_guint8(tvb
, offset
+1);
385 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3r_msb
, tvb
, offset
, 1, p3r_msb
);
386 proto_tree_add_uint(tree
, hf_sndcp_xid_V44_p3r_lsb
, tvb
, offset
+1, 1, p3r_lsb
);
392 /***************************************************/
393 /* Compression algorithms element dissector arrays */
394 /***************************************************/
395 static guint16 (*rfc1144_elem_fcn
[])(tvbuff_t
*, proto_tree
*, guint16
) = {
396 parse_applicable_nsapi
,
402 static guint16 (*rfc2507_elem_fcn
[])(tvbuff_t
*, proto_tree
*, guint16
) = {
403 parse_applicable_nsapi
,
404 parse_rfc2507_f_max_period
,
405 parse_rfc2507_f_max_time
,
406 parse_rfc2507_max_header
,
407 parse_rfc2507_tcp_space
,
408 parse_rfc2507_non_tcp_space
,
412 static guint16 (*rohc_elem_fcn
[])(tvbuff_t
*, proto_tree
*, guint16
) = {
413 parse_applicable_nsapi
,
415 parse_rohc_max_header
,
416 parse_rohc_profile
, /* Profile 1 */
417 parse_rohc_profile
, /* Profile 2 */
418 parse_rohc_profile
, /* Profile 3 */
419 parse_rohc_profile
, /* Profile 4 */
420 parse_rohc_profile
, /* Profile 5 */
421 parse_rohc_profile
, /* Profile 6 */
422 parse_rohc_profile
, /* Profile 7 */
423 parse_rohc_profile
, /* Profile 8 */
424 parse_rohc_profile
, /* Profile 9 */
425 parse_rohc_profile
, /* Profile 10 */
426 parse_rohc_profile
, /* Profile 11 */
427 parse_rohc_profile
, /* Profile 12 */
428 parse_rohc_profile
, /* Profile 13 */
429 parse_rohc_profile
, /* Profile 14 */
430 parse_rohc_profile
, /* Profile 15 */
431 parse_rohc_profile
, /* Profile 16 */
435 /* Array containing the number of pcomp and the function array pointer */
436 static algo_parameters_t pcomp_algo_pars
[] = {
437 {2, rfc1144_elem_fcn
},
438 {5, rfc2507_elem_fcn
},
442 /* Data compression algorithms */
444 static guint16 (*v42bis_elem_fcn
[])(tvbuff_t
*, proto_tree
*, guint16
) = {
445 parse_applicable_nsapi
,
452 static guint16 (*v44_elem_fcn
[])(tvbuff_t
*, proto_tree
*, guint16
) = {
453 parse_applicable_nsapi
,
463 /* Array containing the number of dcomp and the function array pointer */
464 static algo_parameters_t dcomp_algo_pars
[] = {
465 {1, v42bis_elem_fcn
},
470 /* Code to actually dissect the packets
473 dissect_sndcp_xid(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
475 /* Set up structures needed to add the protocol subtree and manage it
477 proto_item
*ti
, *version_item
, *dcomp_item
, *pcomp_item
;
478 proto_tree
*sndcp_tree
, *version_tree
, *dcomp_tree
, *pcomp_tree
;
479 guint16 offset
= 0, l3_param_len
;
480 guint8 parameter_type
, parameter_len
;
482 /* create display subtree for the protocol
484 ti
= proto_tree_add_item(tree
, proto_sndcp_xid
, tvb
, 0, -1, ENC_NA
);
485 sndcp_tree
= proto_item_add_subtree(ti
, ett_sndcp_xid
);
486 l3_param_len
= tvb_reported_length(tvb
);
488 while (offset
< l3_param_len
-1)
490 parameter_type
= tvb_get_guint8(tvb
, offset
);
491 parameter_len
= tvb_get_guint8(tvb
, offset
+1);
493 if (parameter_type
== SNDCP_VERSION_PAR_TYPE
)
495 guint8 value
= tvb_get_guint8(tvb
, offset
+2);
496 version_item
= proto_tree_add_text(sndcp_tree
, tvb
, offset
, parameter_len
+2,
497 "Version (SNDCP version number) - Value %d", value
);
499 version_tree
= proto_item_add_subtree(version_item
, ett_sndcp_xid_version_field
);
500 proto_tree_add_uint(version_tree
, hf_sndcp_xid_type
, tvb
, offset
,
502 proto_tree_add_uint(version_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
504 proto_tree_add_uint(version_tree
, hf_sndcp_xid_value
, tvb
, offset
+2,
509 else if (parameter_type
== DATA_COMPRESSION_PAR_TYPE
)
511 tvbuff_t
* dcomp_tvb
;
513 dcomp_item
= proto_tree_add_text(sndcp_tree
, tvb
, offset
, parameter_len
+2,
515 dcomp_tree
= proto_item_add_subtree(dcomp_item
, ett_sndcp_comp_field
);
516 proto_tree_add_uint(dcomp_tree
, hf_sndcp_xid_type
, tvb
, offset
,
518 proto_tree_add_uint(dcomp_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
522 dcomp_tvb
= tvb_new_subset(tvb
, offset
, parameter_len
, parameter_len
);
523 parse_compression_parameters(dcomp_tvb
, dcomp_tree
, TRUE
);
524 offset
+= parameter_len
;
528 else if (parameter_type
== PROTOCOL_COMPRESSION_PAR_TYPE
)
530 tvbuff_t
* pcomp_tvb
;
532 pcomp_item
= proto_tree_add_text(sndcp_tree
, tvb
, offset
, parameter_len
+2,
533 "Protocol Control Information Compression");
534 pcomp_tree
= proto_item_add_subtree(pcomp_item
, ett_sndcp_comp_field
);
535 proto_tree_add_uint(pcomp_tree
, hf_sndcp_xid_type
, tvb
, offset
,
537 proto_tree_add_uint(pcomp_tree
, hf_sndcp_xid_len
, tvb
, offset
+1,
541 pcomp_tvb
= tvb_new_subset(tvb
, offset
, parameter_len
, parameter_len
);
542 parse_compression_parameters(pcomp_tvb
, pcomp_tree
, FALSE
);
543 offset
+= parameter_len
;
548 break; /* error: exit */
554 static void parse_compression_parameters(tvbuff_t
*tvb
, proto_tree
*tree
, gboolean dcomp
)
556 guint8 entity
, len
, algo_id
;
557 guint8 number_of_comp
, i
;
559 algo_parameters_t
* algo_pars
;
560 guint8 function_index
;
561 proto_item
*comp_entity_field
= NULL
;
562 proto_tree
*comp_entity_tree
= NULL
;
563 guint16 tvb_len
, offset
=0 , new_offset
, entity_offset
;
564 value_string
const * comp_algo_str
;
566 tvb_len
= tvb_reported_length(tvb
);
567 if (tvb_len
< 3) return; /* entity, algo and length bytes should always be present 6.5.1.1 and 6.6.1.1 */
569 /* Loop to decode each entity (cf Figure 10) */
570 while (offset
< tvb_len
)
572 /* Read the entity byte */
573 entity
= tvb_get_guint8(tvb
, offset
);
574 p_bit_set
= ((entity
& 0x80) == 0x80) ? 1 : 0;
575 entity
= entity
& 0x1F;
577 /* P bit is set: means that algo identifier and dcomp are present */
580 /* Read the algorithm id. TODO: store the algo in a different variable for each different entity */
581 algo_id
= tvb_get_guint8(tvb
, offset
+1) & 0x1F;
583 /* sanity check: check that the algo id that will be used inside the array has a valid range */
586 if(algo_id
<= ALGO_V44
)
588 algo_pars
= dcomp_algo_pars
;
589 dcomp_entity_algo_id
[entity
] = algo_id
;
590 comp_algo_str
= sndcp_xid_dcomp_algo_str
;
596 if (algo_id
<= ALGO_ROHC
)
598 algo_pars
= pcomp_algo_pars
;
599 pcomp_entity_algo_id
[entity
] = algo_id
;
600 comp_algo_str
= sndcp_xid_pcomp_algo_str
;
605 /* Read the length */
606 len
= tvb_get_guint8(tvb
, offset
+2);
608 comp_entity_field
= proto_tree_add_text(tree
, tvb
, offset
, len
+ 3,
609 "Entity %d, Algorithm %s",
610 entity
& 0x1F, val_to_str(algo_id
& 0x1F, comp_algo_str
,"Undefined Algorithm Identifier:%X"));
611 comp_entity_tree
= proto_item_add_subtree(comp_entity_field
, ett_sndcp_comp_field
);
613 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_pbit
, tvb
, offset
, 1, p_bit_set
<< 7);
614 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte1
, tvb
, offset
, 1, entity
);
615 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_entity
, tvb
, offset
, 1, entity
);
617 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte2
, tvb
, offset
+1, 1, algo_id
);
618 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_algo_id
, tvb
, offset
+1, 1, algo_id
);
619 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_len
, tvb
, offset
+2, 1, len
);
621 /* Read the dcomp/pcomp field */
622 offset
+= 3; /* entity_offset will be used as the offset from length byte */
623 number_of_comp
= algo_pars
[algo_id
].nb_of_dcomp_pcomp
;
625 for (i
=0; i
< (number_of_comp
+1) / 2; i
++)
629 byte
= tvb_get_guint8(tvb
, offset
+i
);
630 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp
[2*i
], tvb
, offset
+i
, 1, byte
);
632 /* if there is an even number of dcomp/pcomp */
633 if (2*i
+1 < number_of_comp
)
635 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp
[2*i
+1], tvb
, offset
+i
, 1, byte
);
637 /* else there is padding in the end */
640 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare
, tvb
, offset
+i
, 1, byte
);
647 /* Process the elements byte per byte */
648 while ((entity_offset
< len
) && (algo_pars
[algo_id
].func_array_ptr
[function_index
] != NULL
))
650 new_offset
= offset
+entity_offset
;
651 entity_offset
+= algo_pars
[algo_id
].func_array_ptr
[function_index
](tvb
, comp_entity_tree
, new_offset
);
654 offset
+= entity_offset
;
657 else /* P bit not set */
659 len
= tvb_get_guint8(tvb
, offset
+1);
663 algo_pars
= dcomp_algo_pars
;
664 algo_id
= dcomp_entity_algo_id
[entity
];
665 comp_algo_str
= sndcp_xid_dcomp_algo_str
;
669 algo_pars
= pcomp_algo_pars
;
670 algo_id
= pcomp_entity_algo_id
[entity
];
671 comp_algo_str
= sndcp_xid_pcomp_algo_str
;
673 comp_entity_field
= proto_tree_add_text(tree
, tvb
, offset
, len
+ 2,
674 "Entity %d decoded as Algorithm %s",
675 entity
& 0x1F, val_to_str(algo_id
& 0x1F, comp_algo_str
,"Undefined Algorithm Identifier:%X"));
677 comp_entity_tree
= proto_item_add_subtree(comp_entity_field
, ett_sndcp_comp_field
);
679 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_pbit
, tvb
, offset
, 1, p_bit_set
<< 7);
680 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_spare_byte1
, tvb
, offset
, 1, entity
);
681 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_entity
, tvb
, offset
, 1, entity
);
682 proto_tree_add_uint(comp_entity_tree
, hf_sndcp_xid_comp_len
, tvb
, offset
+2, 1, len
);
690 if (algo_id
> ALGO_V44
) return;
694 if (algo_id
> ALGO_ROHC
) return;
697 /* Process the elements byte per byte */
698 while ((entity_offset
< len
) && (algo_pars
[algo_id
].func_array_ptr
[function_index
] != NULL
))
700 new_offset
= offset
+entity_offset
;
701 entity_offset
+= algo_pars
[algo_id
].func_array_ptr
[function_index
](tvb
, comp_entity_tree
, new_offset
);
704 offset
+= entity_offset
;
708 /* Else if length is lower than 3, the packet is not correctly formatted */
711 /* Register the protocol with Wireshark
712 this format is required because a script is used to build the C function
713 that calls all the protocol registration.
717 proto_register_sndcp_xid(void)
719 /* Setup list of header fields
721 static hf_register_info hf
[] = {
722 /* L3 XID Parameter Parsing Info */
724 { "Parameter type","llcgprs.l3xidpartype", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
726 { "Length","llcgprs.l3xidparlen", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
727 {&hf_sndcp_xid_value
,
728 { "Value","llcgprs.l3xidparvalue", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
729 {&hf_sndcp_xid_comp_pbit
,
730 { "P bit","llcgprs.l3xiddcomppbit", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
731 {&hf_sndcp_xid_comp_spare_byte1
,
732 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0x60, "Ignore", HFILL
}},
733 {&hf_sndcp_xid_comp_entity
,
734 { "Entity","llcgprs.l3xidentity", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Data", HFILL
}},
735 {&hf_sndcp_xid_comp_spare_byte2
,
736 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0xE0, "Ignore", HFILL
}},
737 {&hf_sndcp_xid_comp_algo_id
,
738 { "Algorithm identifier","llcgprs.l3xidalgoid", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Data", HFILL
}},
739 {&hf_sndcp_xid_comp_len
,
740 { "Length","llcgprs.l3xidcomplen", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
741 {&hf_sndcp_xid_comp
[0],
742 { "DCOMP1","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
743 {&hf_sndcp_xid_comp
[1],
744 { "DCOMP2","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
745 {&hf_sndcp_xid_comp
[2],
746 { "DCOMP3","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
747 {&hf_sndcp_xid_comp
[3],
748 { "DCOMP4","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
749 {&hf_sndcp_xid_comp
[4],
750 { "DCOMP5","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
751 {&hf_sndcp_xid_comp
[5],
752 { "DCOMP6","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
753 {&hf_sndcp_xid_comp
[6],
754 { "DCOMP7","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
755 {&hf_sndcp_xid_comp
[7],
756 { "DCOMP8","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
757 {&hf_sndcp_xid_comp
[8],
758 { "DCOMP9","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
759 {&hf_sndcp_xid_comp
[9],
760 { "DCOMP10","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
761 {&hf_sndcp_xid_comp
[10],
762 { "DCOMP11","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
763 {&hf_sndcp_xid_comp
[11],
764 { "DCOMP12","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
765 {&hf_sndcp_xid_comp
[12],
766 { "DCOMP13","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
767 {&hf_sndcp_xid_comp
[13],
768 { "DCOMP14","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0x0F, "Data", HFILL
}},
769 {&hf_sndcp_xid_comp
[14],
770 { "DCOMP15","llcgprs.l3xiddcomp", FT_UINT8
, BASE_DEC
, NULL
, 0xF0, "Data", HFILL
}},
771 {&hf_sndcp_xid_comp_spare
,
772 { "Spare","llcgprs.l3xidspare", FT_UINT8
, BASE_HEX
, NULL
, 0x0F, "Ignore", HFILL
}},
773 {&hf_element_applicable_nsapi_15
,
774 { "NSAPI 15","sndcpxid.nsapi15", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
775 {&hf_element_applicable_nsapi_14
,
776 { "NSAPI 14","sndcpxid.nsapi14", FT_UINT8
, BASE_DEC
, NULL
, 0x40, "Data", HFILL
}},
777 {&hf_element_applicable_nsapi_13
,
778 { "NSAPI 13","sndcpxid.nsapi13", FT_UINT8
, BASE_DEC
, NULL
, 0x20, "Data", HFILL
}},
779 {&hf_element_applicable_nsapi_12
,
780 { "NSAPI 12","sndcpxid.nsapi12", FT_UINT8
, BASE_DEC
, NULL
, 0x10, "Data", HFILL
}},
781 {&hf_element_applicable_nsapi_11
,
782 { "NSAPI 11","sndcpxid.nsapi11", FT_UINT8
, BASE_DEC
, NULL
, 0x08, "Data", HFILL
}},
783 {&hf_element_applicable_nsapi_10
,
784 { "NSAPI 10","sndcpxid.nsapi10", FT_UINT8
, BASE_DEC
, NULL
, 0x04, "Data", HFILL
}},
785 {&hf_element_applicable_nsapi_9
,
786 { "NSAPI 9","sndcpxid.nsapi9", FT_UINT8
, BASE_DEC
, NULL
, 0x02, "Data", HFILL
}},
787 {&hf_element_applicable_nsapi_8
,
788 { "NSAPI 8","sndcpxid.nsapi8", FT_UINT8
, BASE_DEC
, NULL
, 0x01, "Data", HFILL
}},
789 {&hf_element_applicable_nsapi_7
,
790 { "NSAPI 7","sndcpxid.nsapi7", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "Data", HFILL
}},
791 {&hf_element_applicable_nsapi_6
,
792 { "NSAPI 6","sndcpxid.nsapi6", FT_UINT8
, BASE_DEC
, NULL
, 0x40, "Data", HFILL
}},
793 {&hf_element_applicable_nsapi_5
,
794 { "NSAPI 5","sndcpxid.nsapi5", FT_UINT8
, BASE_DEC
, NULL
, 0x20, "Data", HFILL
}},
795 {&hf_element_applicable_nsapi_spare
,
796 { "Spare","sndcpxid.spare", FT_UINT8
, BASE_DEC
, NULL
, 0x1F, "Ignore", HFILL
}},
797 {&hf_sndcp_xid_rfc1144_s0
,
798 { "S0 - 1","sndcpxid.rfc1144_s0", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
799 {&hf_sndcp_xid_rfc2507_f_max_period_msb
,
800 { "F Max Period MSB","sndcpxid.rfc2507_f_max_period_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
801 {&hf_sndcp_xid_rfc2507_f_max_period_lsb
,
802 { "F Max Period LSB","sndcpxid.rfc2507_f_max_period_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
803 {&hf_sndcp_xid_rfc2507_f_max_time
,
804 { "F Max Time","sndcpxid.rfc2507_f_max_time", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
805 {&hf_sndcp_xid_rfc2507_max_header
,
806 { "Max Header","sndcpxid.rfc2507_max_header", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
807 {&hf_sndcp_xid_rfc2507_tcp_space
,
808 { "TCP Space","sndcpxid.rfc2507_max_tcp_space", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
809 {&hf_sndcp_xid_rfc2507_non_tcp_space_msb
,
810 { "TCP non space MSB","sndcpxid.rfc2507_max_non_tcp_space_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
811 {&hf_sndcp_xid_rfc2507_non_tcp_space_lsb
,
812 { "TCP non space LSB","sndcpxid.rfc2507_max_non_tcp_space_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
813 {&hf_sndcp_xid_rohc_max_cid_spare
,
814 { "Spare","sndcpxid.rohc_max_cid_spare", FT_UINT8
, BASE_DEC
, NULL
, 0xC0, "Ignore", HFILL
}},
815 {&hf_sndcp_xid_rohc_max_cid_msb
,
816 { "Max CID MSB","sndcpxid.rohc_max_cid_msb", FT_UINT8
, BASE_HEX
, NULL
, 0x3F, "Data", HFILL
}},
817 {&hf_sndcp_xid_rohc_max_cid_lsb
,
818 { "Max CID LSB","sndcpxid.rohc_max_cid_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
819 {&hf_sndcp_xid_rohc_max_header
,
820 { "Max header","sndcpxid.rohc_max_header", FT_UINT8
, BASE_DEC
, NULL
, 0xFF, "Data", HFILL
}},
821 {&hf_sndcp_xid_rohc_profile_msb
,
822 { "Profile MSB","sndcpxid.rohc_profile_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
823 {&hf_sndcp_xid_rohc_profile_lsb
,
824 { "Profile LSB","sndcpxid.rohc_profile_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
825 {&hf_sndcp_xid_V42bis_p0_spare
,
826 { "Spare","sndcpxid.V42bis_p0spare", FT_UINT8
, BASE_DEC
, NULL
, 0xFC, "Ignore", HFILL
}},
827 {&hf_sndcp_xid_V42bis_p0
,
828 { "P0","sndcpxid.V42bis_p0", FT_UINT8
, BASE_HEX
, NULL
, 0x03, "Data", HFILL
}},
829 {&hf_sndcp_xid_V42bis_p1_msb
,
830 { "P1 MSB","sndcpxid.V42bis_p1_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
831 {&hf_sndcp_xid_V42bis_p1_lsb
,
832 { "P1 LSB","sndcpxid.V42bis_p1_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
833 {&hf_sndcp_xid_V42bis_p2
,
834 { "P2","sndcpxid.V42bis_p2", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
835 {&hf_sndcp_xid_V44_c0_spare
,
836 { "P2","sndcpxid.V44_c0_spare", FT_UINT8
, BASE_HEX
, NULL
, 0x3F, "Ignore", HFILL
}},
837 {&hf_sndcp_xid_V44_c0
,
838 { "P2","sndcpxid.V44_c0", FT_UINT8
, BASE_HEX
, NULL
, 0xC0, "Data", HFILL
}},
839 {&hf_sndcp_xid_V44_p0_spare
,
840 { "Spare","sndcpxid.V44_p0spare", FT_UINT8
, BASE_DEC
, NULL
, 0xFC, "Ignore", HFILL
}},
841 {&hf_sndcp_xid_V44_p0
,
842 { "P0","sndcpxid.V44_p0", FT_UINT8
, BASE_HEX
, NULL
, 0x03, "Data", HFILL
}},
843 {&hf_sndcp_xid_V44_p1t_msb
,
844 { "P1t MSB","sndcpxid.V44_p1t_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
845 {&hf_sndcp_xid_V44_p1t_lsb
,
846 { "P1t LSB","sndcpxid.V44_p1t_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
847 {&hf_sndcp_xid_V44_p1r_msb
,
848 { "P1r MSB","sndcpxid.V44_p1r_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
849 {&hf_sndcp_xid_V44_p1r_lsb
,
850 { "P1r LSB","sndcpxid.V44_p1r_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
851 {&hf_sndcp_xid_V44_p3t_msb
,
852 { "P3t MSB","sndcpxid.V44_p3t_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
853 {&hf_sndcp_xid_V44_p3t_lsb
,
854 { "P3t LSB","sndcpxid.V44_p3t_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
855 {&hf_sndcp_xid_V44_p3r_msb
,
856 { "P3r MSB","sndcpxid.V44_p3r_msb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
857 {&hf_sndcp_xid_V44_p3r_lsb
,
858 { "P3r LSB","sndcpxid.V44_p3r_lsb", FT_UINT8
, BASE_HEX
, NULL
, 0xFF, "Data", HFILL
}},
861 /* Setup protocol subtree array */
862 static gint
*ett
[] = {
864 &ett_sndcp_xid_version_field
,
865 &ett_sndcp_comp_field
868 /* Register the protocol name and description */
869 proto_sndcp_xid
= proto_register_protocol("Subnetwork Dependent Convergence Protocol XID",
870 "SNDCP XID", "sndcpxid");
872 /* Required function calls to register the header fields and subtrees used */
873 proto_register_field_array(proto_sndcp_xid
, hf
, array_length(hf
));
874 proto_register_subtree_array(ett
, array_length(ett
));
875 register_dissector("sndcpxid", dissect_sndcp_xid
, proto_sndcp_xid
);
878 /* If this dissector uses sub-dissector registration add a registration routine.
879 This format is required because a script is used to find these routines and
880 create the code that calls these routines.
883 proto_reg_handoff_sndcp_xid(void)