epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-sndcp.c
blob329f0ab5139f61d7e52ac5f42d83336ee3f61269
1 /* packet-sndcp.c
2 * Routines for Subnetwork Dependent Convergence Protocol (SNDCP) dissection
3 * Copyright 2000, Christian Falckenberg <christian.falckenberg@nortelnetworks.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/reassemble.h>
16 #include <epan/tfs.h>
17 #include <wsutil/array.h>
19 /* Bitmasks for the bits in the address field
21 #define MASK_X 0x80
22 #define MASK_F 0x40
23 #define MASK_T 0x20
24 #define MASK_M 0x10
26 void proto_register_sndcp(void);
27 void proto_reg_handoff_sndcp(void);
29 /* Initialize the protocol and registered fields
31 static int proto_sndcp;
32 static int hf_sndcp_x;
33 static int hf_sndcp_f;
34 static int hf_sndcp_t;
35 static int hf_sndcp_m;
36 static int hf_sndcp_nsapi;
37 static int hf_sndcp_nsapib;
38 static int hf_sndcp_dcomp;
39 static int hf_sndcp_pcomp;
40 static int hf_sndcp_segment;
41 static int hf_sndcp_npdu1;
42 static int hf_sndcp_npdu2;
43 static int hf_sndcp_payload;
45 /* These fields are used when reassembling N-PDU fragments
47 static int hf_npdu_fragments;
48 static int hf_npdu_fragment;
49 static int hf_npdu_fragment_overlap;
50 static int hf_npdu_fragment_overlap_conflict;
51 static int hf_npdu_fragment_multiple_tails;
52 static int hf_npdu_fragment_too_long_fragment;
53 static int hf_npdu_fragment_error;
54 static int hf_npdu_fragment_count;
55 static int hf_npdu_reassembled_in;
56 static int hf_npdu_reassembled_length;
58 /* Initialize the subtree pointers
60 static int ett_sndcp;
61 static int ett_sndcp_address_field;
62 static int ett_sndcp_compression_field;
63 static int ett_sndcp_npdu_field;
64 static int ett_npdu_fragment;
65 static int ett_npdu_fragments;
67 /* Structure needed for the fragmentation routines in reassemble.c
69 static const fragment_items npdu_frag_items = {
70 &ett_npdu_fragment,
71 &ett_npdu_fragments,
72 &hf_npdu_fragments,
73 &hf_npdu_fragment,
74 &hf_npdu_fragment_overlap,
75 &hf_npdu_fragment_overlap_conflict,
76 &hf_npdu_fragment_multiple_tails,
77 &hf_npdu_fragment_too_long_fragment,
78 &hf_npdu_fragment_error,
79 &hf_npdu_fragment_count,
80 &hf_npdu_reassembled_in,
81 &hf_npdu_reassembled_length,
82 /* Reassembled data field */
83 NULL,
84 "fragments"
87 /* dissectors for the data portion of this protocol
89 static dissector_handle_t ip_handle;
90 static dissector_handle_t sndcp_handle;
93 /* reassembly of N-PDU
95 static reassembly_table npdu_reassembly_table;
97 /* value strings
99 static const value_string nsapi_t[] = {
100 { 0, "Escape mechanism for future extensions"},
101 { 1, "Point-to-Multipoint (PTM-M) Information" },
102 { 2, "Reserved for future use" },
103 { 3, "Reserved for future use" },
104 { 4, "Reserved for future use" },
105 { 5, "Dynamically allocated"},
106 { 6, "Dynamically allocated"},
107 { 7, "Dynamically allocated"},
108 { 8, "Dynamically allocated"},
109 { 9, "Dynamically allocated"},
110 { 10, "Dynamically allocated"},
111 { 11, "Dynamically allocated"},
112 { 12, "Dynamically allocated"},
113 { 13, "Dynamically allocated"},
114 { 14, "Dynamically allocated"},
115 { 15, "Dynamically allocated"},
116 { 0, NULL },
119 static const value_string nsapi_abrv[] = {
120 { 0, "0"},
121 { 1, "PTM-M" },
122 { 2, "2" },
123 { 3, "3"},
124 { 4, "4" },
125 { 5, "DYN5" },
126 { 6, "DYN6" },
127 { 7, "DYN7" },
128 { 8, "DYN8" },
129 { 9, "DYN9" },
130 { 10, "DYN10" },
131 { 11, "DYN11" },
132 { 12, "DYN12" },
133 { 13, "DYN13" },
134 { 14, "DYN14" },
135 { 15, "DYN15" },
136 { 0, NULL },
139 static const value_string compression_vals[] = {
140 { 0, "No compression"},
141 { 1, "Pointer to selected protocol/data compression mechanism" },
142 { 2, "Pointer to selected protocol/data compression mechanism" },
143 { 3, "Pointer to selected protocol/data compression mechanism" },
144 { 4, "Pointer to selected protocol/data compression mechanism" },
145 { 5, "Pointer to selected protocol/data compression mechanism" },
146 { 6, "Pointer to selected protocol/data compression mechanism" },
147 { 7, "Pointer to selected protocol/data compression mechanism" },
148 { 8, "Pointer to selected protocol/data compression mechanism" },
149 { 9, "Pointer to selected protocol/data compression mechanism" },
150 { 10, "Pointer to selected protocol/data compression mechanism" },
151 { 11, "Pointer to selected protocol/data compression mechanism" },
152 { 12, "Pointer to selected protocol/data compression mechanism" },
153 { 13, "Pointer to selected protocol/data compression mechanism" },
154 { 14, "Pointer to selected protocol/data compression mechanism" },
155 { 15, "Pointer to selected protocol/data compression mechanism" },
156 { 0, NULL },
159 static const true_false_string x_bit = {
160 "Invalid",
161 "Set to 0 by transmitting SNDCP entity (ignored by receiver)"
163 static const true_false_string f_bit = {
164 "This SN-PDU is the first segment of an N-PDU",
165 "This SN-PDU is not the first segment of an N-PDU"
167 static const true_false_string t_bit = {
168 "SN-UNITDATA PDU",
169 "SN-DATA PDU"
171 static const true_false_string m_bit = {
172 "Not the last segment of N-PDU, more segments to follow",
173 "Last segment of N-PDU"
176 /* Code to actually dissect the packets
178 static int
179 dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
181 uint8_t addr_field, comp_field, npdu_field1, dcomp=0, pcomp=0;
182 uint16_t offset=0, npdu=0, segment=0, npdu_field2;
183 tvbuff_t *next_tvb, *npdu_tvb;
184 int len;
185 bool first, more_frags, unack;
186 static int * const addr_fields[] = {
187 &hf_sndcp_x,
188 &hf_sndcp_f,
189 &hf_sndcp_t,
190 &hf_sndcp_m,
191 &hf_sndcp_nsapib,
192 NULL
195 /* Set up structures needed to add the protocol subtree and manage it
197 proto_item *ti;
198 proto_tree *sndcp_tree, *compression_field_tree, *npdu_field_tree;
200 /* Make entries in Protocol column and clear Info column on summary display
202 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNDCP");
203 col_clear(pinfo->cinfo, COL_INFO);
205 /* create display subtree for the protocol
207 ti = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, ENC_NA);
208 sndcp_tree = proto_item_add_subtree(ti, ett_sndcp);
210 /* get address field from next byte
212 addr_field = tvb_get_uint8(tvb,offset);
213 first = addr_field & MASK_F;
214 more_frags = addr_field & MASK_M;
215 unack = addr_field & MASK_T;
217 /* add subtree for the address field
219 proto_tree_add_bitmask_with_flags(sndcp_tree, tvb, offset, hf_sndcp_nsapi,
220 ett_sndcp_address_field, addr_fields, ENC_NA, BMT_NO_APPEND);
221 offset++;
223 /* get compression pointers from next byte if this is the first segment
225 if (first) {
226 comp_field = tvb_get_uint8(tvb,offset);
227 dcomp = comp_field & 0xF0;
228 pcomp = comp_field & 0x0F;
230 /* add subtree for the compression field
232 if (tree) {
233 if (!pcomp) {
234 if (!dcomp) {
235 compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "No compression");
237 else {
238 compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Data compression");
241 else {
242 if (!dcomp) {
243 compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Protocol compression");
245 else {
246 compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Data and Protocol compression");
249 proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field );
250 proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field );
252 offset++;
254 /* get N-PDU number from next byte for acknowledged mode (only for first segment)
256 if (!unack) {
257 npdu = npdu_field1 = tvb_get_uint8(tvb,offset);
258 col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1);
259 if (tree) {
260 npdu_field_tree = proto_tree_add_subtree_format(sndcp_tree, tvb, offset, 1, ett_sndcp_npdu_field, NULL, "Acknowledged mode, N-PDU %d", npdu_field1 );
261 proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 );
263 offset++;
267 /* get segment and N-PDU number from next two bytes for unacknowledged mode
269 if (unack) {
270 npdu_field2 = tvb_get_ntohs(tvb, offset);
271 segment = (npdu_field2 & 0xF000) >> 12;
272 npdu = (npdu_field2 & 0x0FFF);
273 col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment);
274 if (tree) {
275 npdu_field_tree = proto_tree_add_subtree_format(sndcp_tree, tvb, offset, 2, ett_sndcp_npdu_field, NULL,
276 "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment );
277 proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 );
278 proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 );
280 offset += 2;
283 /* handle N-PDU data, reassemble if necessary
285 if (first && !more_frags) {
286 next_tvb = tvb_new_subset_remaining (tvb, offset);
288 if (!dcomp && !pcomp) {
289 call_dissector(ip_handle, next_tvb, pinfo, tree);
291 else {
292 call_data_dissector(next_tvb, pinfo, tree);
295 else {
296 /* Try reassembling fragments
298 fragment_head *fd_npdu = NULL;
299 uint32_t reassembled_in = 0;
300 bool save_fragmented = pinfo->fragmented;
302 len = tvb_captured_length_remaining(tvb, offset);
303 if(len<=0){
304 return offset;
307 pinfo->fragmented = true;
309 if (unack)
310 fd_npdu = fragment_add_seq_check(&npdu_reassembly_table, tvb, offset,
311 pinfo, npdu, NULL, segment, len, more_frags);
312 else
313 fd_npdu = fragment_add(&npdu_reassembly_table, tvb, offset, pinfo, npdu, NULL,
314 offset, len, more_frags);
316 npdu_tvb = process_reassembled_data(tvb, offset, pinfo,
317 "Reassembled N-PDU", fd_npdu, &npdu_frag_items,
318 NULL, sndcp_tree);
319 if (fd_npdu) {
320 /* Reassembled
322 reassembled_in = fd_npdu->reassembled_in;
323 if (pinfo->num == reassembled_in) {
324 /* Reassembled in this very packet:
325 * We can safely hand the tvb to the IP dissector
327 call_dissector(ip_handle, npdu_tvb, pinfo, tree);
329 else {
330 /* Not reassembled in this packet
332 col_append_fstr(pinfo->cinfo, COL_INFO,
333 " (N-PDU payload reassembled in packet %u)",
334 fd_npdu->reassembled_in);
335 proto_tree_add_item(sndcp_tree, hf_sndcp_payload, tvb, offset, -1, ENC_NA);
337 } else {
338 /* Not reassembled yet, or not reassembled at all
340 if (unack)
341 col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment);
342 else
343 col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)");
345 proto_tree_add_item(sndcp_tree, hf_sndcp_payload, tvb, offset, -1, ENC_NA);
347 /* Now reset fragmentation information in pinfo
349 pinfo->fragmented = save_fragmented;
351 return tvb_captured_length(tvb);
355 /* Register the protocol with Wireshark
356 this format is required because a script is used to build the C function
357 that calls all the protocol registration.
360 void
361 proto_register_sndcp(void)
363 /* Setup list of header fields
365 static hf_register_info hf[] = {
366 { &hf_sndcp_nsapi,
367 { "Address field NSAPI",
368 "sndcp.nsapi",
369 FT_UINT8, BASE_DEC, VALS(nsapi_abrv), 0x0,
370 "Network Layer Service Access Point Identifier", HFILL
373 { &hf_sndcp_x,
374 { "Spare bit",
375 "sndcp.x",
376 FT_BOOLEAN,8, TFS(&x_bit), MASK_X,
377 "Spare bit (should be 0)", HFILL
380 { &hf_sndcp_f,
381 { "First segment indicator bit",
382 "sndcp.f",
383 FT_BOOLEAN,8, TFS(&f_bit), MASK_F,
384 NULL, HFILL
387 { &hf_sndcp_t,
388 { "Type",
389 "sndcp.t",
390 FT_BOOLEAN,8, TFS(&t_bit), MASK_T,
391 "SN-PDU Type", HFILL
394 { &hf_sndcp_m,
395 { "More bit",
396 "sndcp.m",
397 FT_BOOLEAN,8, TFS(&m_bit), MASK_M,
398 NULL, HFILL
401 { &hf_sndcp_dcomp,
402 { "DCOMP",
403 "sndcp.dcomp",
404 FT_UINT8, BASE_DEC, VALS(compression_vals), 0xF0,
405 "Data compression coding", HFILL
408 { &hf_sndcp_pcomp,
409 { "PCOMP",
410 "sndcp.pcomp",
411 FT_UINT8, BASE_DEC, VALS(compression_vals), 0x0F,
412 "Protocol compression coding", HFILL
415 { &hf_sndcp_nsapib,
416 { "NSAPI",
417 "sndcp.nsapib",
418 FT_UINT8, BASE_DEC , VALS(nsapi_t), 0xf,
419 "Network Layer Service Access Point Identifier",HFILL
422 { &hf_sndcp_segment,
423 { "Segment",
424 "sndcp.segment",
425 FT_UINT16, BASE_DEC, NULL, 0xF000,
426 "Segment number", HFILL
429 { &hf_sndcp_npdu1,
430 { "N-PDU",
431 "sndcp.npdu",
432 FT_UINT8, BASE_DEC, NULL, 0,
433 NULL, HFILL
436 { &hf_sndcp_npdu2,
437 { "N-PDU",
438 "sndcp.npdu",
439 FT_UINT16, BASE_DEC, NULL, 0x0FFF,
440 NULL, HFILL
443 { &hf_sndcp_payload,
444 { "Payload",
445 "sndcp.payload",
446 FT_BYTES, BASE_NONE, NULL, 0x0,
447 NULL, HFILL
451 /* Fragment fields
453 { &hf_npdu_fragment_overlap,
454 { "Fragment overlap",
455 "sndcp.npdu.fragment.overlap",
456 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
457 "Fragment overlaps with other fragments", HFILL
460 { &hf_npdu_fragment_overlap_conflict,
461 { "Conflicting data in fragment overlap",
462 "sndcp.npdu.fragment.overlap.conflict",
463 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
464 "Overlapping fragments contained conflicting data", HFILL
467 { &hf_npdu_fragment_multiple_tails,
468 { "Multiple tail fragments found",
469 "sndcp.npdu.fragment.multipletails",
470 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
471 "Several tails were found when defragmenting the packet", HFILL
474 { &hf_npdu_fragment_too_long_fragment,
475 { "Fragment too long",
476 "sndcp.npdu.fragment.toolongfragment",
477 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
478 "Fragment contained data past end of packet", HFILL
481 { &hf_npdu_fragment_error,
482 { "Defragmentation error",
483 "sndcp.npdu.fragment.error",
484 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
485 "Defragmentation error due to illegal fragments", HFILL
488 { &hf_npdu_fragment_count,
489 { "Fragment count",
490 "sndcp.npdu.fragment.count",
491 FT_UINT32, BASE_DEC, NULL, 0x0,
492 NULL, HFILL
495 { &hf_npdu_reassembled_in,
496 { "Reassembled in",
497 "sndcp.npdu.reassembled.in",
498 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
499 "N-PDU fragments are reassembled in the given packet", HFILL
502 { &hf_npdu_reassembled_length,
503 { "Reassembled N-PDU length",
504 "sndcp.npdu.reassembled.length",
505 FT_UINT32, BASE_DEC, NULL, 0x0,
506 "The total length of the reassembled payload", HFILL
509 { &hf_npdu_fragment,
510 { "N-PDU Fragment",
511 "sndcp.npdu.fragment",
512 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
513 NULL, HFILL
516 { &hf_npdu_fragments,
517 { "N-PDU Fragments",
518 "sndcp.npdu.fragments",
519 FT_NONE, BASE_NONE, NULL, 0x0,
520 NULL, HFILL
525 /* Setup protocol subtree array */
526 static int *ett[] = {
527 &ett_sndcp ,
528 &ett_sndcp_address_field,
529 &ett_sndcp_compression_field,
530 &ett_sndcp_npdu_field,
531 &ett_npdu_fragment,
532 &ett_npdu_fragments,
535 /* Register the protocol name and description */
536 proto_sndcp = proto_register_protocol("Subnetwork Dependent Convergence Protocol",
537 "SNDCP", "sndcp");
539 /* Required function calls to register the header fields and subtrees used */
540 proto_register_field_array(proto_sndcp, hf, array_length(hf));
541 proto_register_subtree_array(ett, array_length(ett));
542 sndcp_handle = register_dissector("sndcp", dissect_sndcp, proto_sndcp);
543 reassembly_table_register(&npdu_reassembly_table, &addresses_reassembly_table_functions);
546 /* If this dissector uses sub-dissector registration add a registration routine.
547 This format is required because a script is used to find these routines and
548 create the code that calls these routines.
550 void
551 proto_reg_handoff_sndcp(void)
553 /* Register SNDCP dissector with LLC layer for SAPI 3,5,9 and 11
555 dissector_add_uint("llcgprs.sapi", 3, sndcp_handle);
556 dissector_add_uint("llcgprs.sapi", 5, sndcp_handle);
557 dissector_add_uint("llcgprs.sapi", 9, sndcp_handle);
558 dissector_add_uint("llcgprs.sapi", 11, sndcp_handle);
560 /* Find IP and data handle for upper layer dissectors
562 ip_handle = find_dissector_add_dependency("ip", proto_sndcp);
566 * Editor modelines - https://www.wireshark.org/tools/modelines.html
568 * Local Variables:
569 * c-basic-offset: 2
570 * tab-width: 8
571 * indent-tabs-mode: nil
572 * End:
574 * ex: set shiftwidth=2 tabstop=8 expandtab:
575 * :indentSize=2:tabSize=8:noTabs=true: