/src/wireshark/epan/dissectors/packet-sndcp.c
Line | Count | Source |
1 | | /* packet-sndcp.c |
2 | | * Routines for Subnetwork Dependent Convergence Protocol (SNDCP) dissection |
3 | | * Copyright 2000, Christian Falckenberg <christian.falckenberg@nortelnetworks.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/packet.h> |
15 | | #include <epan/reassemble.h> |
16 | | #include <epan/tfs.h> |
17 | | #include <wsutil/array.h> |
18 | | |
19 | | /* Bitmasks for the bits in the address field |
20 | | */ |
21 | 16 | #define MASK_X 0x80 |
22 | 207 | #define MASK_F 0x40 |
23 | 207 | #define MASK_T 0x20 |
24 | 207 | #define MASK_M 0x10 |
25 | | |
26 | | void proto_register_sndcp(void); |
27 | | void proto_reg_handoff_sndcp(void); |
28 | | |
29 | | /* Initialize the protocol and registered fields |
30 | | */ |
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; |
44 | | |
45 | | /* These fields are used when reassembling N-PDU fragments |
46 | | */ |
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; |
57 | | |
58 | | /* Initialize the subtree pointers |
59 | | */ |
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; |
66 | | |
67 | | /* Structure needed for the fragmentation routines in reassemble.c |
68 | | */ |
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" |
85 | | }; |
86 | | |
87 | | /* dissectors for the data portion of this protocol |
88 | | */ |
89 | | static dissector_handle_t ip_handle; |
90 | | static dissector_handle_t sndcp_handle; |
91 | | |
92 | | |
93 | | /* reassembly of N-PDU |
94 | | */ |
95 | | static reassembly_table npdu_reassembly_table; |
96 | | |
97 | | /* value strings |
98 | | */ |
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 }, |
117 | | }; |
118 | | |
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 }, |
137 | | }; |
138 | | |
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 }, |
157 | | }; |
158 | | |
159 | | static const true_false_string x_bit = { |
160 | | "Invalid", |
161 | | "Set to 0 by transmitting SNDCP entity (ignored by receiver)" |
162 | | }; |
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" |
166 | | }; |
167 | | static const true_false_string t_bit = { |
168 | | "SN-UNITDATA PDU", |
169 | | "SN-DATA PDU" |
170 | | }; |
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" |
174 | | }; |
175 | | |
176 | | /* Code to actually dissect the packets |
177 | | */ |
178 | | static int |
179 | | dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
180 | 191 | { |
181 | 191 | uint8_t addr_field, comp_field, npdu_field1, dcomp=0, pcomp=0; |
182 | 191 | uint16_t offset=0, npdu=0, segment=0, npdu_field2; |
183 | 191 | tvbuff_t *next_tvb, *npdu_tvb; |
184 | 191 | int len; |
185 | 191 | bool first, more_frags, unack; |
186 | 191 | static int * const addr_fields[] = { |
187 | 191 | &hf_sndcp_x, |
188 | 191 | &hf_sndcp_f, |
189 | 191 | &hf_sndcp_t, |
190 | 191 | &hf_sndcp_m, |
191 | 191 | &hf_sndcp_nsapib, |
192 | 191 | NULL |
193 | 191 | }; |
194 | | |
195 | | /* Set up structures needed to add the protocol subtree and manage it |
196 | | */ |
197 | 191 | proto_item *ti; |
198 | 191 | proto_tree *sndcp_tree, *compression_field_tree, *npdu_field_tree; |
199 | | |
200 | | /* Make entries in Protocol column and clear Info column on summary display |
201 | | */ |
202 | 191 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SNDCP"); |
203 | 191 | col_clear(pinfo->cinfo, COL_INFO); |
204 | | |
205 | | /* create display subtree for the protocol |
206 | | */ |
207 | 191 | ti = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, ENC_NA); |
208 | 191 | sndcp_tree = proto_item_add_subtree(ti, ett_sndcp); |
209 | | |
210 | | /* get address field from next byte |
211 | | */ |
212 | 191 | addr_field = tvb_get_uint8(tvb,offset); |
213 | 191 | first = addr_field & MASK_F; |
214 | 191 | more_frags = addr_field & MASK_M; |
215 | 191 | unack = addr_field & MASK_T; |
216 | | |
217 | | /* add subtree for the address field |
218 | | */ |
219 | 191 | proto_tree_add_bitmask_with_flags(sndcp_tree, tvb, offset, hf_sndcp_nsapi, |
220 | 191 | ett_sndcp_address_field, addr_fields, ENC_NA, BMT_NO_APPEND); |
221 | 191 | offset++; |
222 | | |
223 | | /* get compression pointers from next byte if this is the first segment |
224 | | */ |
225 | 191 | if (first) { |
226 | 76 | comp_field = tvb_get_uint8(tvb,offset); |
227 | 76 | dcomp = comp_field & 0xF0; |
228 | 76 | pcomp = comp_field & 0x0F; |
229 | | |
230 | | /* add subtree for the compression field |
231 | | */ |
232 | 76 | if (tree) { |
233 | 76 | if (!pcomp) { |
234 | 11 | if (!dcomp) { |
235 | 6 | compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "No compression"); |
236 | 6 | } |
237 | 5 | else { |
238 | 5 | compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Data compression"); |
239 | 5 | } |
240 | 11 | } |
241 | 65 | else { |
242 | 65 | if (!dcomp) { |
243 | 43 | compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Protocol compression"); |
244 | 43 | } |
245 | 22 | else { |
246 | 22 | compression_field_tree = proto_tree_add_subtree(sndcp_tree, tvb, offset, 1, ett_sndcp_compression_field, NULL, "Data and Protocol compression"); |
247 | 22 | } |
248 | 65 | } |
249 | 76 | proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field ); |
250 | 76 | proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field ); |
251 | 76 | } |
252 | 76 | offset++; |
253 | | |
254 | | /* get N-PDU number from next byte for acknowledged mode (only for first segment) |
255 | | */ |
256 | 76 | if (!unack) { |
257 | 23 | npdu = npdu_field1 = tvb_get_uint8(tvb,offset); |
258 | 23 | col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1); |
259 | 23 | if (tree) { |
260 | 23 | 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 | 23 | proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 ); |
262 | 23 | } |
263 | 23 | offset++; |
264 | 23 | } |
265 | 76 | } |
266 | | |
267 | | /* get segment and N-PDU number from next two bytes for unacknowledged mode |
268 | | */ |
269 | 191 | if (unack) { |
270 | 119 | npdu_field2 = tvb_get_ntohs(tvb, offset); |
271 | 119 | segment = (npdu_field2 & 0xF000) >> 12; |
272 | 119 | npdu = (npdu_field2 & 0x0FFF); |
273 | 119 | col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment); |
274 | 119 | if (tree) { |
275 | 118 | npdu_field_tree = proto_tree_add_subtree_format(sndcp_tree, tvb, offset, 2, ett_sndcp_npdu_field, NULL, |
276 | 118 | "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment ); |
277 | 118 | proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 ); |
278 | 118 | proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 ); |
279 | 118 | } |
280 | 119 | offset += 2; |
281 | 119 | } |
282 | | |
283 | | /* handle N-PDU data, reassemble if necessary |
284 | | */ |
285 | 191 | if (first && !more_frags) { |
286 | 49 | next_tvb = tvb_new_subset_remaining (tvb, offset); |
287 | | |
288 | 49 | if (!dcomp && !pcomp) { |
289 | 3 | call_dissector(ip_handle, next_tvb, pinfo, tree); |
290 | 3 | } |
291 | 46 | else { |
292 | 46 | call_data_dissector(next_tvb, pinfo, tree); |
293 | 46 | } |
294 | 49 | } |
295 | 142 | else { |
296 | | /* Try reassembling fragments |
297 | | */ |
298 | 142 | fragment_head *fd_npdu = NULL; |
299 | 142 | uint32_t reassembled_in = 0; |
300 | 142 | bool save_fragmented = pinfo->fragmented; |
301 | | |
302 | 142 | len = tvb_captured_length_remaining(tvb, offset); |
303 | 142 | if(len<=0){ |
304 | 3 | return offset; |
305 | 3 | } |
306 | | |
307 | 139 | pinfo->fragmented = true; |
308 | | |
309 | 139 | if (unack) |
310 | 75 | fd_npdu = fragment_add_seq_check(&npdu_reassembly_table, tvb, offset, |
311 | 75 | pinfo, npdu, NULL, segment, len, more_frags); |
312 | 64 | else |
313 | 64 | fd_npdu = fragment_add(&npdu_reassembly_table, tvb, offset, pinfo, npdu, NULL, |
314 | 64 | offset, len, more_frags); |
315 | | |
316 | 139 | npdu_tvb = process_reassembled_data(tvb, offset, pinfo, |
317 | 139 | "Reassembled N-PDU", fd_npdu, &npdu_frag_items, |
318 | 139 | NULL, sndcp_tree); |
319 | 139 | if (fd_npdu) { |
320 | | /* Reassembled |
321 | | */ |
322 | 20 | reassembled_in = fd_npdu->reassembled_in; |
323 | 20 | if (pinfo->num == reassembled_in) { |
324 | | /* Reassembled in this very packet: |
325 | | * We can safely hand the tvb to the IP dissector |
326 | | */ |
327 | 10 | call_dissector(ip_handle, npdu_tvb, pinfo, tree); |
328 | 10 | } |
329 | 10 | else { |
330 | | /* Not reassembled in this packet |
331 | | */ |
332 | 10 | col_append_fstr(pinfo->cinfo, COL_INFO, |
333 | 10 | " (N-PDU payload reassembled in packet %u)", |
334 | 10 | fd_npdu->reassembled_in); |
335 | 10 | proto_tree_add_item(sndcp_tree, hf_sndcp_payload, tvb, offset, -1, ENC_NA); |
336 | 10 | } |
337 | 119 | } else { |
338 | | /* Not reassembled yet, or not reassembled at all |
339 | | */ |
340 | 119 | if (unack) |
341 | 68 | col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment); |
342 | 51 | else |
343 | 51 | col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)"); |
344 | | |
345 | 119 | proto_tree_add_item(sndcp_tree, hf_sndcp_payload, tvb, offset, -1, ENC_NA); |
346 | 119 | } |
347 | | /* Now reset fragmentation information in pinfo |
348 | | */ |
349 | 139 | pinfo->fragmented = save_fragmented; |
350 | 139 | } |
351 | 188 | return tvb_captured_length(tvb); |
352 | 191 | } |
353 | | |
354 | | |
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. |
358 | | */ |
359 | | |
360 | | void |
361 | | proto_register_sndcp(void) |
362 | 16 | { |
363 | | /* Setup list of header fields |
364 | | */ |
365 | 16 | static hf_register_info hf[] = { |
366 | 16 | { &hf_sndcp_nsapi, |
367 | 16 | { "Address field NSAPI", |
368 | 16 | "sndcp.nsapi", |
369 | 16 | FT_UINT8, BASE_DEC, VALS(nsapi_abrv), 0x0, |
370 | 16 | "Network Layer Service Access Point Identifier", HFILL |
371 | 16 | } |
372 | 16 | }, |
373 | 16 | { &hf_sndcp_x, |
374 | 16 | { "Spare bit", |
375 | 16 | "sndcp.x", |
376 | 16 | FT_BOOLEAN,8, TFS(&x_bit), MASK_X, |
377 | 16 | "Spare bit (should be 0)", HFILL |
378 | 16 | } |
379 | 16 | }, |
380 | 16 | { &hf_sndcp_f, |
381 | 16 | { "First segment indicator bit", |
382 | 16 | "sndcp.f", |
383 | 16 | FT_BOOLEAN,8, TFS(&f_bit), MASK_F, |
384 | 16 | NULL, HFILL |
385 | 16 | } |
386 | 16 | }, |
387 | 16 | { &hf_sndcp_t, |
388 | 16 | { "Type", |
389 | 16 | "sndcp.t", |
390 | 16 | FT_BOOLEAN,8, TFS(&t_bit), MASK_T, |
391 | 16 | "SN-PDU Type", HFILL |
392 | 16 | } |
393 | 16 | }, |
394 | 16 | { &hf_sndcp_m, |
395 | 16 | { "More bit", |
396 | 16 | "sndcp.m", |
397 | 16 | FT_BOOLEAN,8, TFS(&m_bit), MASK_M, |
398 | 16 | NULL, HFILL |
399 | 16 | } |
400 | 16 | }, |
401 | 16 | { &hf_sndcp_dcomp, |
402 | 16 | { "DCOMP", |
403 | 16 | "sndcp.dcomp", |
404 | 16 | FT_UINT8, BASE_DEC, VALS(compression_vals), 0xF0, |
405 | 16 | "Data compression coding", HFILL |
406 | 16 | } |
407 | 16 | }, |
408 | 16 | { &hf_sndcp_pcomp, |
409 | 16 | { "PCOMP", |
410 | 16 | "sndcp.pcomp", |
411 | 16 | FT_UINT8, BASE_DEC, VALS(compression_vals), 0x0F, |
412 | 16 | "Protocol compression coding", HFILL |
413 | 16 | } |
414 | 16 | }, |
415 | 16 | { &hf_sndcp_nsapib, |
416 | 16 | { "NSAPI", |
417 | 16 | "sndcp.nsapib", |
418 | 16 | FT_UINT8, BASE_DEC , VALS(nsapi_t), 0xf, |
419 | 16 | "Network Layer Service Access Point Identifier",HFILL |
420 | 16 | } |
421 | 16 | }, |
422 | 16 | { &hf_sndcp_segment, |
423 | 16 | { "Segment", |
424 | 16 | "sndcp.segment", |
425 | 16 | FT_UINT16, BASE_DEC, NULL, 0xF000, |
426 | 16 | "Segment number", HFILL |
427 | 16 | } |
428 | 16 | }, |
429 | 16 | { &hf_sndcp_npdu1, |
430 | 16 | { "N-PDU", |
431 | 16 | "sndcp.npdu", |
432 | 16 | FT_UINT8, BASE_DEC, NULL, 0, |
433 | 16 | NULL, HFILL |
434 | 16 | } |
435 | 16 | }, |
436 | 16 | { &hf_sndcp_npdu2, |
437 | 16 | { "N-PDU", |
438 | 16 | "sndcp.npdu", |
439 | 16 | FT_UINT16, BASE_DEC, NULL, 0x0FFF, |
440 | 16 | NULL, HFILL |
441 | 16 | } |
442 | 16 | }, |
443 | 16 | { &hf_sndcp_payload, |
444 | 16 | { "Payload", |
445 | 16 | "sndcp.payload", |
446 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
447 | 16 | NULL, HFILL |
448 | 16 | } |
449 | 16 | }, |
450 | | |
451 | | /* Fragment fields |
452 | | */ |
453 | 16 | { &hf_npdu_fragment_overlap, |
454 | 16 | { "Fragment overlap", |
455 | 16 | "sndcp.npdu.fragment.overlap", |
456 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
457 | 16 | "Fragment overlaps with other fragments", HFILL |
458 | 16 | } |
459 | 16 | }, |
460 | 16 | { &hf_npdu_fragment_overlap_conflict, |
461 | 16 | { "Conflicting data in fragment overlap", |
462 | 16 | "sndcp.npdu.fragment.overlap.conflict", |
463 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
464 | 16 | "Overlapping fragments contained conflicting data", HFILL |
465 | 16 | } |
466 | 16 | }, |
467 | 16 | { &hf_npdu_fragment_multiple_tails, |
468 | 16 | { "Multiple tail fragments found", |
469 | 16 | "sndcp.npdu.fragment.multipletails", |
470 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
471 | 16 | "Several tails were found when defragmenting the packet", HFILL |
472 | 16 | } |
473 | 16 | }, |
474 | 16 | { &hf_npdu_fragment_too_long_fragment, |
475 | 16 | { "Fragment too long", |
476 | 16 | "sndcp.npdu.fragment.toolongfragment", |
477 | 16 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
478 | 16 | "Fragment contained data past end of packet", HFILL |
479 | 16 | } |
480 | 16 | }, |
481 | 16 | { &hf_npdu_fragment_error, |
482 | 16 | { "Defragmentation error", |
483 | 16 | "sndcp.npdu.fragment.error", |
484 | 16 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
485 | 16 | "Defragmentation error due to illegal fragments", HFILL |
486 | 16 | } |
487 | 16 | }, |
488 | 16 | { &hf_npdu_fragment_count, |
489 | 16 | { "Fragment count", |
490 | 16 | "sndcp.npdu.fragment.count", |
491 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
492 | 16 | NULL, HFILL |
493 | 16 | } |
494 | 16 | }, |
495 | 16 | { &hf_npdu_reassembled_in, |
496 | 16 | { "Reassembled in", |
497 | 16 | "sndcp.npdu.reassembled.in", |
498 | 16 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
499 | 16 | "N-PDU fragments are reassembled in the given packet", HFILL |
500 | 16 | } |
501 | 16 | }, |
502 | 16 | { &hf_npdu_reassembled_length, |
503 | 16 | { "Reassembled N-PDU length", |
504 | 16 | "sndcp.npdu.reassembled.length", |
505 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
506 | 16 | "The total length of the reassembled payload", HFILL |
507 | 16 | } |
508 | 16 | }, |
509 | 16 | { &hf_npdu_fragment, |
510 | 16 | { "N-PDU Fragment", |
511 | 16 | "sndcp.npdu.fragment", |
512 | 16 | FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
513 | 16 | NULL, HFILL |
514 | 16 | } |
515 | 16 | }, |
516 | 16 | { &hf_npdu_fragments, |
517 | 16 | { "N-PDU Fragments", |
518 | 16 | "sndcp.npdu.fragments", |
519 | 16 | FT_NONE, BASE_NONE, NULL, 0x0, |
520 | 16 | NULL, HFILL |
521 | 16 | } |
522 | 16 | }, |
523 | 16 | }; |
524 | | |
525 | | /* Setup protocol subtree array */ |
526 | 16 | static int *ett[] = { |
527 | 16 | &ett_sndcp , |
528 | 16 | &ett_sndcp_address_field, |
529 | 16 | &ett_sndcp_compression_field, |
530 | 16 | &ett_sndcp_npdu_field, |
531 | 16 | &ett_npdu_fragment, |
532 | 16 | &ett_npdu_fragments, |
533 | 16 | }; |
534 | | |
535 | | /* Register the protocol name and description */ |
536 | 16 | proto_sndcp = proto_register_protocol("Subnetwork Dependent Convergence Protocol", |
537 | 16 | "SNDCP", "sndcp"); |
538 | | |
539 | | /* Required function calls to register the header fields and subtrees used */ |
540 | 16 | proto_register_field_array(proto_sndcp, hf, array_length(hf)); |
541 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
542 | 16 | sndcp_handle = register_dissector("sndcp", dissect_sndcp, proto_sndcp); |
543 | 16 | reassembly_table_register(&npdu_reassembly_table, &addresses_reassembly_table_functions); |
544 | 16 | } |
545 | | |
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. |
549 | | */ |
550 | | void |
551 | | proto_reg_handoff_sndcp(void) |
552 | 16 | { |
553 | | /* Register SNDCP dissector with LLC layer for SAPI 3,5,9 and 11 |
554 | | */ |
555 | 16 | dissector_add_uint("llcgprs.sapi", 3, sndcp_handle); |
556 | 16 | dissector_add_uint("llcgprs.sapi", 5, sndcp_handle); |
557 | 16 | dissector_add_uint("llcgprs.sapi", 9, sndcp_handle); |
558 | 16 | dissector_add_uint("llcgprs.sapi", 11, sndcp_handle); |
559 | | |
560 | | /* Find IP and data handle for upper layer dissectors |
561 | | */ |
562 | 16 | ip_handle = find_dissector_add_dependency("ip", proto_sndcp); |
563 | 16 | } |
564 | | |
565 | | /* |
566 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
567 | | * |
568 | | * Local Variables: |
569 | | * c-basic-offset: 2 |
570 | | * tab-width: 8 |
571 | | * indent-tabs-mode: nil |
572 | | * End: |
573 | | * |
574 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
575 | | * :indentSize=2:tabSize=8:noTabs=true: |
576 | | */ |