HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-s5066sis.c
blob352f116d06b01f08301d5d15d7f8018f952d4835
1 /* packet-s5066sis.c
2 * Routines to dissect STANAG 5066 Subnetwork Interface Sublayer (SIS)
3 * packets, as described in Annex A of STANAG 5066.
5 * $Id$
7 * Copyright (c) 2005 by Menno Andriesse <s5066 [AT] nc3a.nato.int>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1999 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/dissectors/packet-tcp.h> /* For tcp_dissect_pdus() */
35 /* Forward reference */
36 /* Register functions */
37 void proto_reg_handoff_s5066(void);
38 /* Main dissectors */
39 static int dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
40 static guint get_s5066_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset);
41 static int dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_);
42 /* Service type and address dissectors */
43 static guint dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree);
44 static guint dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source);
45 /* S-Primitive dissectors */
46 static guint dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree);
47 /* static guint dissect_s5066_02(tvbuff_t *tvb, guint offset, proto_tree *tree); */
48 static guint dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree);
49 static guint dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree);
50 static guint dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree);
51 static guint dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree);
52 static guint dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree);
53 static guint dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree);
54 static guint dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree);
55 static guint dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree);
56 static guint dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree);
57 static guint dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree);
58 static guint dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree);
59 static guint dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree);
60 /* static guint dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree); */
61 /* static guint dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree); */
62 /* static guint dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree); */
63 static guint dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
64 static guint dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
65 static guint dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree);
66 static guint dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
67 static guint dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree);
68 static guint dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree);
69 static guint dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree);
70 static guint dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
71 static guint dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree);
72 static guint dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree);
74 static gint proto_s5066 = -1;
75 static dissector_handle_t data_handle;
77 /* Enable desegmentation of S5066 over TCP */
78 static gboolean s5066_desegment = TRUE;
79 /* Dissect old 'edition 1' of STANAG 5066 (It lacks the 'version' field.) */
80 static gboolean s5066_edition_one = FALSE;
81 /* This port is registered with IANA */
82 static guint global_s5066_port = 5066;
83 /* Size of header outside 'size' field */
84 static gint s5066_header_size = 5;
85 /* Offset of 'size' field */
86 static gint s5066_size_offset = 3;
88 /* Sync should be 0x90EB */
89 static gint hf_s5066_sync_word = -1;
90 /* Version should be 0x00 */
91 static gint hf_s5066_version = -1;
92 /* Total size of the PDU, excluding this size and previous fields */
93 /* So total size is this + 5 bytes (s5066_header_size) */
94 static gint hf_s5066_size = -1;
95 /* Th type of PDU */
96 static gint hf_s5066_type = -1;
97 static const value_string s5066_pdu_type[] = {
98 { 1, "S_BIND_REQUEST"},
99 { 2, "S_UNBIND_REQUEST"},
100 { 3, "S_BIND_ACCEPTED"},
101 { 4, "S_BIND_REJECTED"},
102 { 5, "S_UNBIND_INDICATION"},
103 { 6, "S_HARD_LINK_ESTABLISH"},
104 { 7, "S_HARD_LINK_TERMINATE"},
105 { 8, "S_HARD_LINK_ESTABLISHED"},
106 { 9, "S_HARD_LINK_REJECTED"},
107 {10, "S_HARD_LINK_TERMINATED"},
108 {11, "S_HARD_LINK_INDICATION"},
109 {12, "S_HARD_LINK_ACCEPT"},
110 {13, "S_HARD_LINK_REJECT"},
111 {14, "S_SUBNET_AVAILABILITY"},
112 {15, "S_DATAFLOW_ON"},
113 {16, "S_DATAFLOW_OFF"},
114 {17, "S_KEEP_ALIVE"},
115 {18, "S_MANAGEMENT_MESSAGE_REQUEST"},
116 {19, "S_MANAGEMENT_MESSAGE_INDICATION"},
117 {20, "S_UNIDATA_REQUEST"},
118 {21, "S_UNIDATA_INDICATION"},
119 {22, "S_UNIDATA_REQUEST_CONFIRM"},
120 {23, "S_UNIDATA_REQUEST_REJECTED"},
121 {24, "S_EXPEDITED_UNIDATA_REQUEST"},
122 {25, "S_EXPEDITED_UNIDATA_INDICATION"},
123 {26, "S_EXPEDITED_UNIDATA_REQUEST_CONFIRM"},
124 {27, "S_EXPEDITED_UNIDATA_REQUEST_REJECTED"},
125 { 0, NULL },
128 /* STANAG 5066 Address */
129 /* Size is defined in nibbles (4 bits) */
130 static gint hf_s5066_ad_size = -1;
131 /* Group flag: 0 = false, 1 = true */
132 static gint hf_s5066_ad_group = -1;
133 /* The remainder of the 4 bytes form the address */
134 static gint hf_s5066_ad_address = -1;
136 /* Service type */
137 /* Transmission mode: */
138 static gint hf_s5066_st_txmode = -1;
139 static const value_string s5066_st_txmode[] = {
140 { 0, "Ignore service type field"},
141 { 1, "ARQ"},
142 { 2, "Non-ARQ (Broadcast)"},
143 { 3, "Non-ARQ (with errors)"},
144 { 4, "Other non-ARQ types"},
145 { 5, "Other non-ARQ types"},
146 { 6, "Other non-ARQ types"},
147 { 7, "Other non-ARQ types"},
148 { 8, "Other non-ARQ types"},
149 { 9, "Other non-ARQ types"},
150 {10, "Other non-ARQ types"},
151 {11, "Other non-ARQ types"},
152 {12, "Other non-ARQ types"},
153 {13, "Other non-ARQ types"},
154 {14, "Other non-ARQ types"},
155 {15, "Other non-ARQ types"},
156 { 0, NULL },
158 /* Delivery confirmation: */
159 static gint hf_s5066_st_delivery_confirmation = -1;
160 static const value_string s5066_st_delivery_confirmation[] = {
161 { 0, "No confirmation"},
162 { 1, "Node delivery confirmation"},
163 { 2, "Client delivery confirmation"},
164 { 3, "-- Not defined --"},
165 { 0, NULL },
167 /* Delivery order: */
168 static gint hf_s5066_st_delivery_order = -1;
169 static const value_string s5066_st_delivery_order[] = {
170 { 0, "In-order delivery"},
171 { 1, "As-they-arrive"},
172 { 0, NULL },
174 /* Extended field present: (Never in the current version.) */
175 static gint hf_s5066_st_extended = -1;
176 static const value_string s5066_st_extended[] = {
177 { 0, "No extended field"},
178 { 1, "Extended field follows"},
179 { 0, NULL },
181 /* Number of retransmissions when in Non-ARQ: */
182 static gint hf_s5066_st_retries = -1;
184 /* Type 1: S_BIND_REQUEST */
185 static gint hf_s5066_01_sapid = -1;
186 static gint hf_s5066_01_rank = -1;
187 static gint hf_s5066_01_unused = -1;
189 /* Type 2: S_UNBIND_REQUEST */
190 /* --- no subfields --- */
192 /* Type 3: S_BIND_ACCEPTED */
193 static gint hf_s5066_03_sapid = -1;
194 static gint hf_s5066_03_unused = -1;
195 static gint hf_s5066_03_mtu = -1;
197 /* Type 4: S_BIND_REJECTED */
198 static gint hf_s5066_04_reason = -1;
199 static const value_string s5066_04_reason[] = {
200 { 0, "Unknown reason"},
201 { 1, "Not enough resources"},
202 { 2, "Invalid Sap ID"},
203 { 3, "Sap ID already allocated"},
204 { 4, "ARQ mode unsupportable during broadcast session"},
205 { 0, NULL },
208 /* Type 5: S_UNBIND_INDICATION */
209 static gint hf_s5066_05_reason = -1;
210 static const value_string s5066_05_reason[] = {
211 { 0, "Unknown reason"},
212 { 1, "Connection pre-empted by higher ranking client"},
213 { 2, "Inactivity (failure to respond to 'Keep-alive')"},
214 { 3, "Too many invalid primitives"},
215 { 4, "Too many expedited data request primitives"},
216 { 5, "ARQ mode unsupportable during broadcast session"},
217 { 0, NULL },
220 /* Hard links: hardlinktype value string array. */
221 static const value_string s5066_hard_link_type[] = {
222 { 0, "Link reservation"},
223 { 1, "Partial Bandwidth reservation"},
224 { 2, "Full Bandwidth reservation"},
225 { 3, "--- undefined ---"},
226 { 0, NULL },
229 /* Type 6: S_HARD_LINK_ESTABLISH */
230 static gint hf_s5066_06_link_type = -1;
231 static gint hf_s5066_06_link_priority = -1;
232 static gint hf_s5066_06_sapid = -1;
234 /* Type 7: S_HARD_LINK_TERMINATE */
235 /* Only remote node address */
237 /* Type 8: S_HARD_LINK_ESTABLISHED */
238 static gint hf_s5066_08_remote_status = -1;
239 static const value_string s5066_08_remote_status[] = {
240 { 0, "ERROR"},
241 { 1, "OK"},
242 { 0, NULL },
244 static gint hf_s5066_08_link_type = -1;
245 static gint hf_s5066_08_link_priority = -1;
246 static gint hf_s5066_08_sapid = -1;
248 /* Type 9: S_HARD_LINK_REJECTED */
249 static gint hf_s5066_09_reason = -1;
250 static const value_string s5066_09_reason[] = {
251 { 0, "--- undefined ---"},
252 { 1, "Remote node busy"},
253 { 2, "Higher priority link exists"},
254 { 3, "Remote node not responding"},
255 { 4, "Destination Sap ID not bound"},
256 { 5, "Requested Type-0 link exists"},
257 { 0, NULL },
259 static gint hf_s5066_09_link_type = -1;
260 static gint hf_s5066_09_link_priority = -1;
261 static gint hf_s5066_09_sapid = -1;
263 /* Type 10: S_HARD_LINK_TERMINATED */
264 static gint hf_s5066_10_reason = -1;
265 static const value_string s5066_10_reason[] = {
266 { 0, "--- undefined ---"},
267 { 1, "Link terminated by remote node"},
268 { 2, "Higher priority link requested"},
269 { 3, "Remote node not responding"},
270 { 4, "Destination Sap ID not bound"},
271 { 5, "Physical link broken"},
272 { 0, NULL },
274 static gint hf_s5066_10_link_type = -1;
275 static gint hf_s5066_10_link_priority = -1;
276 static gint hf_s5066_10_sapid = -1;
278 /* Type 11: S_HARD_LINK_INDICATION */
279 static gint hf_s5066_11_remote_status = -1;
280 static const value_string s5066_11_remote_status[] = {
281 { 0, "ERROR"},
282 { 1, "OK"},
283 { 0, NULL },
285 static gint hf_s5066_11_link_type = -1;
286 static gint hf_s5066_11_link_priority = -1;
287 static gint hf_s5066_11_sapid = -1;
289 /* Type 12: S_HARD_LINK_ACCEPT */
290 static gint hf_s5066_12_link_type = -1;
291 static gint hf_s5066_12_link_priority = -1;
292 static gint hf_s5066_12_sapid = -1;
294 /* Type 13: S_HARD_LINK_REJECT */
295 static gint hf_s5066_13_reason = -1;
296 static const value_string s5066_13_reason[] = {
297 { 0, "--- undefined ---"},
298 { 0, NULL },
300 static gint hf_s5066_13_link_type = -1;
301 static gint hf_s5066_13_link_priority = -1;
302 static gint hf_s5066_13_sapid = -1;
304 /* Type 14: S_SUBNET_AVAILABILITY */
305 static gint hf_s5066_14_status= -1;
306 static const value_string s5066_14_status[] = {
307 { 0, "Off"},
308 { 1, "On"},
309 { 2, "Receive only"},
310 { 3, "Half-duplex"},
311 { 4, "Full-duplex"},
312 { 0, NULL },
314 static gint hf_s5066_14_reason= -1;
315 static const value_string s5066_14_reason[] = {
316 { 0, "Unknown reason"},
317 { 1, "Local node in EMCON"},
318 { 2, "Higher priority link requested"},
319 { 0, NULL },
322 /* Type 15: S_DATAFLOW_ON */
323 /* --- no subfields --- */
325 /* Type 16: S_DATAFLOW_OFF */
326 /* --- no subfields --- */
328 /* Type 17: S_KEEP_ALIVE */
329 /* --- no subfields --- */
331 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
332 static gint hf_s5066_18_type = -1;
333 static gint hf_s5066_18_body = -1;
335 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
336 static gint hf_s5066_19_type = -1;
337 static gint hf_s5066_19_body = -1;
339 /* Type 20: S_UNIDATA_REQUEST */
340 static gint hf_s5066_20_priority = -1;
341 static gint hf_s5066_20_sapid = -1;
342 static gint hf_s5066_20_ttl = -1;
343 static gint hf_s5066_20_size = -1;
345 /* Type 21: S_UNIDATA_INDICATION */
346 static gint hf_s5066_21_priority = -1;
347 static gint hf_s5066_21_dest_sapid = -1;
348 static gint hf_s5066_21_tx_mode = -1;
349 static gint hf_s5066_21_src_sapid = -1;
350 static gint hf_s5066_21_size = -1;
351 static gint hf_s5066_21_err_blocks = -1;
352 static gint hf_s5066_21_err_ptr = -1;
353 static gint hf_s5066_21_err_size = -1;
354 static gint hf_s5066_21_nrx_blocks = -1;
355 static gint hf_s5066_21_nrx_ptr = -1;
356 static gint hf_s5066_21_nrx_size = -1;
359 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
360 static gint hf_s5066_22_unused = -1;
361 static gint hf_s5066_22_sapid = -1;
362 static gint hf_s5066_22_size = -1;
363 static gint hf_s5066_22_data = -1;
365 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
366 static gint hf_s5066_23_reason = -1;
367 static const value_string s5066_23_reason[] = {
368 { 0, "Unknown reason"},
369 { 1, "Time-To-Live expired"},
370 { 2, "Destination SapID not bound"},
371 { 3, "Destination node not responding"},
372 { 4, "U_PDU larger than MTU"},
373 { 5, "Transmission Mode not specified"},
374 { 0, NULL },
376 static gint hf_s5066_23_sapid = -1;
377 static gint hf_s5066_23_size = -1;
378 static gint hf_s5066_23_data = -1;
380 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
381 static gint hf_s5066_24_unused = -1;
382 static gint hf_s5066_24_sapid = -1;
383 static gint hf_s5066_24_ttl = -1;
384 static gint hf_s5066_24_size = -1;
386 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
387 static gint hf_s5066_25_unused = -1;
388 static gint hf_s5066_25_dest_sapid = -1;
389 static gint hf_s5066_25_tx_mode = -1;
390 static gint hf_s5066_25_src_sapid = -1;
391 static gint hf_s5066_25_size = -1;
392 static gint hf_s5066_25_err_blocks = -1;
393 static gint hf_s5066_25_err_ptr = -1;
394 static gint hf_s5066_25_err_size = -1;
395 static gint hf_s5066_25_nrx_blocks = -1;
396 static gint hf_s5066_25_nrx_ptr = -1;
397 static gint hf_s5066_25_nrx_size = -1;
399 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
400 static gint hf_s5066_26_unused = -1;
401 static gint hf_s5066_26_sapid = -1;
402 static gint hf_s5066_26_size = -1;
403 static gint hf_s5066_26_data = -1;
405 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
406 static gint hf_s5066_27_reason = -1;
407 static const value_string s5066_27_reason[] = {
408 { 0, "Unknown reason"},
409 { 1, "Time-To-Live expired"},
410 { 2, "Destination SapID not bound"},
411 { 3, "Destination node not responding"},
412 { 4, "U_PDU larger than MTU"},
413 { 5, "Transmission Mode not specified"},
414 { 0, NULL },
416 static gint hf_s5066_27_sapid = -1;
417 static gint hf_s5066_27_size = -1;
418 static gint hf_s5066_27_data = -1;
421 static gint ett_s5066 = -1;
422 static gint ett_s5066_pdu = -1;
423 static gint ett_s5066_servicetype = -1;
424 static gint ett_s5066_address = -1;
426 void
427 proto_register_s5066(void)
429 static hf_register_info hf[] = {
430 { &hf_s5066_sync_word,
431 { "Sync preamble", "s5066sis.sync", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
433 { &hf_s5066_version,
434 { "S5066 version", "s5066sis.version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
436 { &hf_s5066_size,
437 { "S_Primitive size", "s5066sis.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
439 { &hf_s5066_type,
440 { "PDU Type", "s5066sis.type", FT_UINT8, BASE_DEC, VALS(s5066_pdu_type), 0x0, NULL, HFILL }
442 /* STANAG 5066 Address */
443 { &hf_s5066_ad_size,
444 { "Address size (1/2 Bytes)", "s5066sis.address.size", FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL }
446 { &hf_s5066_ad_group,
447 { "Group address", "s5066sis.address.group", FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
449 { &hf_s5066_ad_address,
450 { "Address", "s5066sis.address.address", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
452 /* Service type */
453 { &hf_s5066_st_txmode,
454 { "Transmission mode", "s5066sis.st.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
456 { &hf_s5066_st_delivery_confirmation,
457 { "Delivery confirmation", "s5066sis.st.confirm", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_confirmation), 0x0C, NULL, HFILL }
459 { &hf_s5066_st_delivery_order,
460 { "Delivery order", "s5066sis.st.order", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_order), 0x02, NULL, HFILL }
462 { &hf_s5066_st_extended,
463 { "Extended field", "s5066sis.st.extended", FT_UINT8, BASE_HEX, VALS(s5066_st_extended), 0x01, NULL, HFILL }
465 { &hf_s5066_st_retries,
466 { "Minimum number of retransmissions", "s5066sis.st.retries", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
468 /* PDU Type 01: S_BIND_REQUEST */
469 { &hf_s5066_01_sapid,
470 { "Sap ID", "s5066sis.01.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
472 { &hf_s5066_01_rank,
473 { "Rank", "s5066sis.01.rank", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
475 { &hf_s5066_01_unused,
476 { "(Unused)", "s5066sis.01.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
478 /* PDU Type 02: S_UNBIND_REQUEST */
479 /* --- no subfields --- */
480 /* PDU Type 03: S_BIND_ACCEPTED */
481 { &hf_s5066_03_sapid,
482 { "Sap ID", "s5066sis.03.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
484 { &hf_s5066_03_unused,
485 { "(Unused)", "s5066sis.03.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
487 { &hf_s5066_03_mtu,
488 { "MTU", "s5066sis.03.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
490 /* PDU Type 04: S_BIND_REJECTED */
491 { &hf_s5066_04_reason,
492 { "Reason", "s5066sis.04.reason", FT_UINT8, BASE_DEC, VALS(s5066_04_reason), 0x0, NULL, HFILL }
494 /* PDU Type 05: S_UNBIND_INDICATION */
495 { &hf_s5066_05_reason,
496 { "Reason", "s5066sis.05.reason", FT_UINT8, BASE_DEC, VALS(s5066_05_reason), 0x0, NULL, HFILL }
498 /* Type 6: S_HARD_LINK_ESTABLISH */
499 { &hf_s5066_06_link_type,
500 { "Hardlink type", "s5066sis.06.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
502 { &hf_s5066_06_link_priority,
503 { "Priority", "s5066sis.06.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
505 { &hf_s5066_06_sapid,
506 { "Remote Sap ID", "s5066sis.06.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
508 /* Type 7: S_HARD_LINK_TERMINATE */
509 /* --- Only remote node address --- */
510 /* Type 8: S_HARD_LINK_ESTABLISHED */
511 { &hf_s5066_08_remote_status,
512 { "Remote node status", "s5066sis.08.status", FT_UINT8, BASE_DEC, VALS(s5066_08_remote_status), 0x0, NULL, HFILL }
514 { &hf_s5066_08_link_type,
515 { "Hardlink type", "s5066sis.08.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
517 { &hf_s5066_08_link_priority,
518 { "Priority", "s5066sis.08.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
520 { &hf_s5066_08_sapid,
521 { "Remote Sap ID", "s5066sis.08.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
523 /* Type 9: S_HARD_LINK_REJECTED */
524 { &hf_s5066_09_reason,
525 { "Reason", "s5066sis.09.reason", FT_UINT8, BASE_DEC, VALS(s5066_09_reason), 0x0, NULL, HFILL }
527 { &hf_s5066_09_link_type,
528 { "Hardlink type", "s5066sis.09.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
530 { &hf_s5066_09_link_priority,
531 { "Priority", "s5066sis.09.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
533 { &hf_s5066_09_sapid,
534 { "Remote Sap ID", "s5066sis.09.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
536 /* Type 10: S_HARD_LINK_TERMINATED */
537 { &hf_s5066_10_reason,
538 { "Reason", "s5066sis.10.reason", FT_UINT8, BASE_DEC, VALS(s5066_10_reason), 0x0, NULL, HFILL }
540 { &hf_s5066_10_link_type,
541 { "Hardlink type", "s5066sis.10.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
543 { &hf_s5066_10_link_priority,
544 { "Priority", "s5066sis.10.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
546 { &hf_s5066_10_sapid,
547 { "Remote Sap ID", "s5066sis.10.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
549 /* Type 11: S_HARD_LINK_INDICATION */
550 { &hf_s5066_11_remote_status,
551 { "Remote node status", "s5066sis.11.status", FT_UINT8, BASE_DEC, VALS(s5066_11_remote_status), 0x0, NULL, HFILL }
553 { &hf_s5066_11_link_type,
554 { "Hardlink type", "s5066sis.11.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
556 { &hf_s5066_11_link_priority,
557 { "Priority", "s5066sis.11.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
559 { &hf_s5066_11_sapid,
560 { "Remote Sap ID", "s5066sis.11.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
562 /* Type 12: S_HARD_LINK_ACCEPT */
563 { &hf_s5066_12_link_type,
564 { "Hardlink type", "s5066sis.12.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
566 { &hf_s5066_12_link_priority,
567 { "Priority", "s5066sis.12.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
569 { &hf_s5066_12_sapid,
570 { "Remote Sap ID", "s5066sis.12.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
572 /* Type 13: S_HARD_LINK_REJECT */
573 { &hf_s5066_13_reason,
574 { "Reason", "s5066sis.13.reason", FT_UINT8, BASE_DEC, VALS(s5066_13_reason), 0x0, NULL, HFILL }
576 { &hf_s5066_13_link_type,
577 { "Hardlink type", "s5066sis.13.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
579 { &hf_s5066_13_link_priority,
580 { "Priority", "s5066sis.13.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
582 { &hf_s5066_13_sapid,
583 { "Remote Sap ID", "s5066sis.13.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
585 /* Type 14: S_SUBNET_AVAILABILITY */
586 { &hf_s5066_14_status,
587 { "Status", "s5066sis.14.status", FT_UINT8, BASE_DEC, VALS(s5066_14_status), 0x0, NULL, HFILL }
589 { &hf_s5066_14_reason,
590 { "Reason", "s5066sis.14.reason", FT_UINT8, BASE_DEC, VALS(s5066_14_reason), 0x0, NULL, HFILL }
592 /* Type 15: S_DATAFLOW_ON */
593 /* --- no subfields --- */
594 /* Type 16: S_DATAFLOW_OFF */
595 /* --- no subfields --- */
596 /* Type 17: S_KEEP_ALIVE */
597 /* --- no subfields --- */
598 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
599 { &hf_s5066_18_type,
600 { "Message Type", "s5066sis.18.type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
602 { &hf_s5066_18_body,
603 { "Message Body", "s5066sis.18.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
605 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
606 { &hf_s5066_19_type,
607 { "Message Type", "s5066sis.19.type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
609 { &hf_s5066_19_body,
610 { "Message Body", "s5066sis.19.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
612 /* Type 20: S_UNIDATA_REQUEST */
613 { &hf_s5066_20_priority,
614 { "Priority", "s5066sis.20.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
616 { &hf_s5066_20_sapid,
617 { "Destination Sap ID", "s5066sis.20.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
619 { &hf_s5066_20_ttl,
620 { "Time-To-Live (x2 seconds)", "s5066sis.20.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, NULL, HFILL }
622 { &hf_s5066_20_size,
623 { "U_PDU Size", "s5066sis.20.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
625 /* Type 21: S_UNIDATA_INDICATION */
626 { &hf_s5066_21_priority,
627 { "Priority", "s5066sis.21.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
629 { &hf_s5066_21_dest_sapid,
630 { "Destination Sap ID", "s5066sis.21.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
632 { &hf_s5066_21_tx_mode,
633 { "Transmission Mode", "s5066sis.21.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
635 { &hf_s5066_21_src_sapid,
636 { "Source Sap ID", "s5066sis.21.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
638 { &hf_s5066_21_size,
639 { "U_PDU Size", "s5066sis.21.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
641 { &hf_s5066_21_err_blocks,
642 { "Number of errored blocks", "s5066sis.21.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
644 { &hf_s5066_21_err_ptr,
645 { "Pointer to error block", "s5066sis.21.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
647 { &hf_s5066_21_err_size,
648 { "Size of error block", "s5066sis.21.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
650 { &hf_s5066_21_nrx_blocks,
651 { "Number of non-received blocks", "s5066sis.21.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
653 { &hf_s5066_21_nrx_ptr,
654 { "Pointer to non-received block", "s5066sis.21.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
656 { &hf_s5066_21_nrx_size,
657 { "Size of non-received block", "s5066sis.21.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
659 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
660 { &hf_s5066_22_unused,
661 { "(Unused)", "s5066sis.22.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
663 { &hf_s5066_22_sapid,
664 { "Destination Sap ID", "s5066sis.22.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
666 { &hf_s5066_22_size,
667 { "U_PDU Size", "s5066sis.22.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
669 { &hf_s5066_22_data,
670 { "(Part of) Confirmed data", "s5066sis.22.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
672 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
673 { &hf_s5066_23_reason,
674 { "Reason", "s5066sis.23.reason", FT_UINT8, BASE_DEC, VALS(s5066_23_reason), 0xF0, NULL, HFILL }
676 { &hf_s5066_23_sapid,
677 { "Destination Sap ID", "s5066sis.23.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
679 { &hf_s5066_23_size,
680 { "U_PDU Size", "s5066sis.23.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
682 { &hf_s5066_23_data,
683 { "(Part of) Rejected data", "s5066sis.23.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
685 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
686 { &hf_s5066_24_unused,
687 { "(Unused)", "s5066sis.24.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
689 { &hf_s5066_24_sapid,
690 { "Destination Sap ID", "s5066sis.24.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
692 { &hf_s5066_24_ttl,
693 { "Time-To-Live (x2 seconds)", "s5066sis.24.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, NULL, HFILL }
695 { &hf_s5066_24_size,
696 { "U_PDU Size", "s5066sis.24.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
698 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
699 { &hf_s5066_25_unused,
700 { "(Unused)", "s5066sis.25.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
702 { &hf_s5066_25_dest_sapid,
703 { "Destination Sap ID", "s5066sis.25.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
705 { &hf_s5066_25_tx_mode,
706 { "Transmission Mode", "s5066sis.25.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
708 { &hf_s5066_25_src_sapid,
709 { "Source Sap ID", "s5066sis.25.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
711 { &hf_s5066_25_size,
712 { "U_PDU Size", "s5066sis.25.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
714 { &hf_s5066_25_err_blocks,
715 { "Number of errored blocks", "s5066sis.25.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
717 { &hf_s5066_25_err_ptr,
718 { "Pointer to error block", "s5066sis.25.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
720 { &hf_s5066_25_err_size,
721 { "Size of error block", "s5066sis.25.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
723 { &hf_s5066_25_nrx_blocks,
724 { "Number of non-received blocks", "s5066sis.25.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
726 { &hf_s5066_25_nrx_ptr,
727 { "Pointer to non-received block", "s5066sis.25.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
729 { &hf_s5066_25_nrx_size,
730 { "Size of non-received block", "s5066sis.25.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
732 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
733 { &hf_s5066_26_unused,
734 { "(Unused)", "s5066sis.26.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
736 { &hf_s5066_26_sapid,
737 { "Destination Sap ID", "s5066sis.26.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
739 { &hf_s5066_26_size,
740 { "U_PDU Size", "s5066sis.26.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
742 { &hf_s5066_26_data,
743 { "(Part of) Confirmed data", "s5066sis.26.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
745 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
746 { &hf_s5066_27_reason,
747 { "Reason", "s5066sis.27.reason", FT_UINT8, BASE_DEC, VALS(s5066_27_reason), 0xF0, NULL, HFILL }
749 { &hf_s5066_27_sapid,
750 { "Destination Sap ID", "s5066sis.27.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
752 { &hf_s5066_27_size,
753 { "U_PDU Size", "s5066sis.27.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
755 { &hf_s5066_27_data,
756 { "(Part of) Rejected data", "s5066sis.27.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
761 /* Setup protocol subtree array */
762 static gint *ett[] = {
763 &ett_s5066,
764 &ett_s5066_pdu,
765 &ett_s5066_servicetype,
766 &ett_s5066_address,
769 module_t *s5066_module;
771 proto_s5066 = proto_register_protocol (
772 "STANAG 5066 (SIS layer)", /* name */
773 "STANAG 5066 SIS", /* short name*/
774 "s5066sis" /* abbrev */
776 proto_register_field_array(proto_s5066, hf, array_length(hf));
777 proto_register_subtree_array(ett, array_length(ett));
779 s5066_module = prefs_register_protocol(proto_s5066, proto_reg_handoff_s5066);
780 prefs_register_bool_preference(s5066_module, "desegment_pdus",
781 "Reassemble S5066 SIS PDUs spanning multiple TCP segments",
782 "Whether the S5066 SIS dissector should reassemble PDUs spanning multiple TCP segments."
783 " The default is to use reassembly.",
784 &s5066_desegment);
785 prefs_register_bool_preference(s5066_module, "edition_one",
786 "Dissect edition 1.0 of STANAG 5066",
787 "Whether the S5066 SIS dissector should dissect this edition of the STANAG."
788 " This edition was never formally approved and is very rare. The common edition is edition 1.2.",
789 &s5066_edition_one);
790 prefs_register_uint_preference(s5066_module, "tcp.port",
791 "STANAG 5066 SIS TCP Port",
792 "Set the port for STANAG 5066 SIS. (If other than the default 5066."
793 " This number is registered with IANA.)",
794 10, &global_s5066_port);
797 void
798 proto_reg_handoff_s5066(void)
800 static gboolean Initialized = FALSE;
801 static dissector_handle_t s5066_tcp_handle;
802 static guint saved_s5066_port;
804 if (!Initialized) {
805 s5066_tcp_handle = new_create_dissector_handle(dissect_s5066_tcp, proto_s5066);
806 data_handle = find_dissector("data");
807 Initialized = TRUE;
808 } else {
809 dissector_delete_uint("tcp.port", saved_s5066_port, s5066_tcp_handle);
812 dissector_add_uint("tcp.port", global_s5066_port, s5066_tcp_handle);
813 saved_s5066_port = global_s5066_port;
815 if (!s5066_edition_one) {
816 s5066_header_size = 5;
817 s5066_size_offset = 3;
818 } else {
819 s5066_header_size = 4;
820 s5066_size_offset = 2;
824 static guint
825 dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source)
827 proto_item *ti = NULL;
828 proto_tree *s5066_tree_address = NULL;
829 guint32 addr;
831 if (source) {
832 ti = proto_tree_add_text(tree, tvb, offset, 4, "Source Address");
834 else {
835 ti = proto_tree_add_text(tree, tvb, offset, 4, "Destination Address");
837 s5066_tree_address = proto_item_add_subtree(ti, ett_s5066_address);
838 proto_tree_add_item(s5066_tree_address, hf_s5066_ad_size, tvb, offset, 1, ENC_BIG_ENDIAN);
839 proto_tree_add_item(s5066_tree_address, hf_s5066_ad_group, tvb, offset, 1, ENC_BIG_ENDIAN);
840 addr = tvb_get_ntohl(tvb, offset);
841 addr = addr & 0x1FFFFFFF;
842 proto_tree_add_ipv4(s5066_tree_address, hf_s5066_ad_address, tvb, offset, 4, g_htonl(addr));
844 return offset + 4;
847 static guint
848 dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree)
850 proto_item *ti = NULL;
851 proto_tree *s5066_tree_servicetype = NULL;
853 ti = proto_tree_add_text(tree, tvb, offset, 2, "Service type");
854 s5066_tree_servicetype = proto_item_add_subtree(ti, ett_s5066_servicetype);
856 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_txmode, tvb, offset, 1, ENC_BIG_ENDIAN);
857 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_confirmation, tvb, offset, 1, ENC_BIG_ENDIAN);
858 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_order, tvb, offset, 1, ENC_BIG_ENDIAN);
859 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_extended, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
860 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_retries, tvb, offset, 1, ENC_BIG_ENDIAN);
862 return offset;
865 /* S_BIND_REQUEST */
866 static guint
867 dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree)
869 proto_tree_add_item(tree, hf_s5066_01_sapid, tvb, offset, 1, ENC_BIG_ENDIAN);
870 proto_tree_add_item(tree, hf_s5066_01_rank, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
872 offset = dissect_s5066_servicetype(tvb, offset, tree);
874 proto_tree_add_item(tree, hf_s5066_01_unused, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
875 return offset;
878 /* S_UNBIND_REQUEST */
879 /* Commented out: does nothing and causes <variable not used> messages.
880 static guint
881 dissect_s5066_02(tvbuff_t *tvb, guint offset, proto_tree *tree)
883 return offset;
887 /* S_BIND_ACCEPTED */
888 static guint
889 dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree)
891 proto_tree_add_item(tree, hf_s5066_03_sapid, tvb, offset, 1, ENC_BIG_ENDIAN);
892 proto_tree_add_item(tree, hf_s5066_03_unused, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
893 proto_tree_add_item(tree, hf_s5066_03_mtu, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
894 return offset;
897 /* S_BIND_REJECTED */
898 static guint
899 dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree)
901 proto_tree_add_item(tree, hf_s5066_04_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
902 return offset;
905 /* S_UNBIND_INDICATION */
906 static guint
907 dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree)
909 proto_tree_add_item(tree, hf_s5066_05_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
910 return offset;
913 /* S_HARD_LINK_ESTABLISH */
914 static guint
915 dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree)
917 proto_tree_add_item(tree, hf_s5066_06_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
918 proto_tree_add_item(tree, hf_s5066_06_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
919 proto_tree_add_item(tree, hf_s5066_06_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
920 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
921 return offset;
924 /* S_HARD_LINK_TERMINATE */
925 static guint
926 dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree)
928 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
929 return offset;
932 /* S_HARD_LINK_ESTABLISHED */
933 static guint
934 dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree)
936 proto_tree_add_item(tree, hf_s5066_08_remote_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
937 proto_tree_add_item(tree, hf_s5066_08_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
938 proto_tree_add_item(tree, hf_s5066_08_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
939 proto_tree_add_item(tree, hf_s5066_08_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
940 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
941 return offset;
944 /* S_HARD_LINK_REJECTED */
945 static guint
946 dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree)
948 proto_tree_add_item(tree, hf_s5066_09_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
949 proto_tree_add_item(tree, hf_s5066_09_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
950 proto_tree_add_item(tree, hf_s5066_09_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
951 proto_tree_add_item(tree, hf_s5066_09_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
952 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
953 return offset;
956 /* S_HARD_LINK_TERMINATED */
957 static guint
958 dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree)
960 proto_tree_add_item(tree, hf_s5066_10_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
961 proto_tree_add_item(tree, hf_s5066_10_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
962 proto_tree_add_item(tree, hf_s5066_10_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
963 proto_tree_add_item(tree, hf_s5066_10_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
964 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
965 return offset;
968 /* S_HARD_LINK_INDICATION */
969 static guint
970 dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree)
972 proto_tree_add_item(tree, hf_s5066_11_remote_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
973 proto_tree_add_item(tree, hf_s5066_11_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
974 proto_tree_add_item(tree, hf_s5066_11_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
975 proto_tree_add_item(tree, hf_s5066_11_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
976 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
977 return offset;
980 /* S_HARD_LINK_ACCEPT */
981 static guint
982 dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree)
984 proto_tree_add_item(tree, hf_s5066_12_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
985 proto_tree_add_item(tree, hf_s5066_12_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
986 proto_tree_add_item(tree, hf_s5066_12_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
987 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
988 return offset;
991 /* S_HARD_LINK_REJECT */
992 static guint
993 dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree)
995 proto_tree_add_item(tree, hf_s5066_13_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
996 proto_tree_add_item(tree, hf_s5066_13_link_type, tvb, offset, 1, ENC_BIG_ENDIAN);
997 proto_tree_add_item(tree, hf_s5066_13_link_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
998 proto_tree_add_item(tree, hf_s5066_13_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
999 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1000 return offset;
1003 /* S_SUBNET_AVAILABILITY */
1004 static guint
1005 dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree)
1007 proto_tree_add_item(tree, hf_s5066_14_status, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1008 proto_tree_add_item(tree, hf_s5066_14_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1009 return offset;
1012 /* Following three commented out: do nothing and cause <variable not used> messages. */
1013 /* S_DATA_FLOW_ON */
1015 static guint
1016 dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree)
1018 return offset;
1022 /* S_DATA_FLOW_OFF */
1024 static guint
1025 dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree)
1027 return offset;
1031 /* S_KEEP_ALIVE */
1033 static guint
1034 dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree)
1036 return offset;
1040 /* S_MANAGEMENT_MESSAGE_REQUEST */
1041 static guint
1042 dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1044 guint body_size = 0;
1045 proto_tree_add_item(tree, hf_s5066_18_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1046 body_size = pdu_size - offset;
1047 proto_tree_add_item(tree, hf_s5066_18_body, tvb, offset, body_size, ENC_NA); offset += body_size;
1048 return offset;
1051 /* S_MANAGEMENT_MESSAGE_INDICATION */
1052 static guint
1053 dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1055 guint body_size = 0;
1056 proto_tree_add_item(tree, hf_s5066_19_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1057 body_size = pdu_size - offset;
1058 proto_tree_add_item(tree, hf_s5066_19_body, tvb, offset, body_size, ENC_NA); offset += body_size;
1059 return offset;
1062 /* S_UNIDATA_REQUEST */
1063 static guint
1064 dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree)
1066 proto_tree_add_item(tree, hf_s5066_20_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
1067 proto_tree_add_item(tree, hf_s5066_20_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1068 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1069 offset = dissect_s5066_servicetype(tvb, offset, tree);
1070 proto_tree_add_item(tree, hf_s5066_20_ttl, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3;
1071 proto_tree_add_item(tree, hf_s5066_20_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1073 return offset;
1076 /* S_UNIDATA_INDICATION */
1077 static guint
1078 dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1080 guint i=0;
1081 proto_item *ti = NULL;
1082 guint d_pdu_size = 0;
1083 guint8 tx_mode = 0;
1084 guint16 no_err_blocks = 0;
1085 guint16 no_nrx_blocks = 0;
1086 gboolean non_arq_w_errors = FALSE;
1088 proto_tree_add_item(tree, hf_s5066_21_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
1089 proto_tree_add_item(tree, hf_s5066_21_dest_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1090 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1092 tx_mode = tvb_get_guint8(tvb, offset);
1093 tx_mode = (tx_mode & 0xF0) >> 4;
1094 if (tx_mode == 3) {
1095 non_arq_w_errors = TRUE;
1098 proto_tree_add_item(tree, hf_s5066_21_tx_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1099 proto_tree_add_item(tree, hf_s5066_21_src_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1100 offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1102 d_pdu_size = tvb_get_ntohs(tvb, offset);
1103 proto_tree_add_item(tree, hf_s5066_21_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1105 /* Handle RockwellCollins (<= v2.1) 4-byte offset */
1106 if ( (pdu_size - offset) == (d_pdu_size + 4) ) {
1107 ti = proto_tree_add_item(tree, hf_s5066_21_err_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1108 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1109 ti = proto_tree_add_item(tree, hf_s5066_21_nrx_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1110 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1112 /* Handle Non-ARQ with errors */
1113 if ( non_arq_w_errors ) {
1114 no_err_blocks = tvb_get_ntohs(tvb, offset);
1115 proto_tree_add_item(tree, hf_s5066_21_err_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1116 for (i=0; i<no_err_blocks; i++) {
1117 proto_tree_add_item(tree, hf_s5066_21_err_ptr, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1118 proto_tree_add_item(tree, hf_s5066_21_err_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1120 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1121 proto_tree_add_item(tree, hf_s5066_21_nrx_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1122 for (i=0; i<no_nrx_blocks; i++) {
1123 proto_tree_add_item(tree, hf_s5066_21_nrx_ptr, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1124 proto_tree_add_item(tree, hf_s5066_21_nrx_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1127 return offset;
1130 /* S_UNIDATA_REQUEST_CONFIRM */
1131 static guint
1132 dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree)
1134 guint pdu_size = 0;
1135 proto_tree_add_item(tree, hf_s5066_22_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
1136 proto_tree_add_item(tree, hf_s5066_22_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1137 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1138 pdu_size = tvb_get_ntohs(tvb, offset);
1139 proto_tree_add_item(tree, hf_s5066_22_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1140 proto_tree_add_item(tree, hf_s5066_22_data, tvb, offset, pdu_size, ENC_NA); offset += pdu_size;
1142 return offset;
1145 /* S_UNIDATA_REQUEST_REJECTED */
1146 static guint
1147 dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree)
1149 guint pdu_size = 0;
1150 proto_tree_add_item(tree, hf_s5066_23_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
1151 proto_tree_add_item(tree, hf_s5066_23_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1152 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1153 pdu_size = tvb_get_ntohs(tvb, offset);
1154 proto_tree_add_item(tree, hf_s5066_23_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1155 proto_tree_add_item(tree, hf_s5066_23_data, tvb, offset, pdu_size, ENC_NA); offset += pdu_size;
1157 return offset;
1160 /* S_EXPEDITED_UNIDATA_REQUEST */
1161 static guint
1162 dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree)
1164 proto_tree_add_item(tree, hf_s5066_24_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
1165 proto_tree_add_item(tree, hf_s5066_24_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1166 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1167 offset = dissect_s5066_servicetype(tvb, offset, tree);
1168 proto_tree_add_item(tree, hf_s5066_24_ttl, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 3;
1169 proto_tree_add_item(tree, hf_s5066_24_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1171 return offset;
1174 /* S_EXPEDITED_UNIDATA_INDICATION */
1175 static guint
1176 dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1178 guint i=0;
1179 proto_item *ti = NULL;
1180 guint d_pdu_size = 0;
1181 guint8 tx_mode = 0;
1182 guint16 no_err_blocks = 0;
1183 guint16 no_nrx_blocks = 0;
1184 gboolean non_arq_w_errors = FALSE;
1186 proto_tree_add_item(tree, hf_s5066_25_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
1187 proto_tree_add_item(tree, hf_s5066_25_dest_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1188 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1190 tx_mode = tvb_get_guint8(tvb, offset);
1191 tx_mode = (tx_mode & 0xF0) >> 4;
1192 if (tx_mode == 3) {
1193 non_arq_w_errors = TRUE;
1196 proto_tree_add_item(tree, hf_s5066_25_tx_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
1197 proto_tree_add_item(tree, hf_s5066_25_src_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1198 offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1200 d_pdu_size = tvb_get_ntohs(tvb, offset);
1201 proto_tree_add_item(tree, hf_s5066_25_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1203 /* Handle RockwellCollins (<= v2.1) 4-byte offset */
1204 if ( (pdu_size - offset) == (d_pdu_size + 4) ) {
1205 ti = proto_tree_add_item(tree, hf_s5066_25_err_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1206 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1207 ti = proto_tree_add_item(tree, hf_s5066_25_nrx_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1208 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1210 /* Handle Non-ARQ with errors */
1211 if ( non_arq_w_errors ) {
1212 no_err_blocks = tvb_get_ntohs(tvb, offset);
1213 proto_tree_add_item(tree, hf_s5066_25_err_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1214 for (i=0; i<no_err_blocks; i++) {
1215 proto_tree_add_item(tree, hf_s5066_25_err_ptr, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1216 proto_tree_add_item(tree, hf_s5066_25_err_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1218 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1219 proto_tree_add_item(tree, hf_s5066_25_nrx_blocks, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1220 for (i=0; i<no_nrx_blocks; i++) {
1221 proto_tree_add_item(tree, hf_s5066_25_nrx_ptr, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1222 proto_tree_add_item(tree, hf_s5066_25_nrx_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1225 return offset;
1228 /* S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
1229 static guint
1230 dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree)
1232 guint pdu_size = 0;
1233 proto_tree_add_item(tree, hf_s5066_26_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
1234 proto_tree_add_item(tree, hf_s5066_26_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1235 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1236 pdu_size = tvb_get_ntohs(tvb, offset);
1237 proto_tree_add_item(tree, hf_s5066_26_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1238 proto_tree_add_item(tree, hf_s5066_26_data, tvb, offset, pdu_size, ENC_NA); offset += pdu_size;
1240 return offset;
1243 /* S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
1244 static guint
1245 dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree)
1247 guint pdu_size = 0;
1248 proto_tree_add_item(tree, hf_s5066_27_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
1249 proto_tree_add_item(tree, hf_s5066_27_sapid, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1250 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1251 pdu_size = tvb_get_ntohs(tvb, offset);
1252 proto_tree_add_item(tree, hf_s5066_27_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
1253 proto_tree_add_item(tree, hf_s5066_27_data, tvb, offset, pdu_size, ENC_NA); offset += pdu_size;
1255 return offset;
1258 static guint
1259 get_s5066_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1261 guint16 plen;
1263 /* Get the length of the S5066 PDU. */
1264 plen = tvb_get_ntohs(tvb, offset + s5066_size_offset);
1266 /* That length doesn't include the sync, version and length fields; add that in. */
1267 return plen + s5066_header_size;
1270 static int
1271 dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1273 /* Make sure there are enough bytes... */
1274 if (tvb_length(tvb) < 5)
1275 return 0;
1276 /* Check if the first two bytes are 0x90 0xEB: if not,
1277 then this is not a S5066 PDU or an unreassembled one.
1278 The third byte is the STANAG 5066 version: Right now only 0x00 is defined. */
1279 if( (tvb_get_guint8(tvb, 0) != 0x90) ||
1280 (tvb_get_guint8(tvb, 1) != 0xEB) ||
1281 (tvb_get_guint8(tvb, 2) != 0x00) ) {
1282 return 0;
1284 tcp_dissect_pdus(tvb, pinfo, tree, s5066_desegment, s5066_header_size, get_s5066_pdu_len, dissect_s5066_common, data);
1285 return tvb_length(tvb);
1288 static int
1289 dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1291 guint offset = 0;
1292 guint pdu_size = 0;
1293 proto_item *ti_s5066 = NULL;
1294 proto_item *ti_pdu = NULL;
1295 tvbuff_t *next_tvb;
1296 gint available_length = 0;
1297 gint reported_length = 0;
1299 /* Determine PDU type to display in INFO column */
1300 guint8 pdu_type = tvb_get_guint8(tvb, s5066_header_size);
1302 col_set_str(pinfo->cinfo, COL_PROTOCOL, "S5066");
1303 /* Clear out stuff in the info column, the add PDU type */
1304 col_add_fstr(pinfo->cinfo, COL_INFO, "PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1306 if (tree) { /* We are being asked for details */
1307 proto_tree *s5066_tree = NULL;
1308 proto_tree *s5066_tree_pdu = NULL;
1310 pdu_size = tvb_get_ntohs(tvb, s5066_size_offset) + s5066_header_size;
1312 ti_s5066 = proto_tree_add_item(tree, proto_s5066, tvb, 0, -1, ENC_NA);
1313 proto_item_append_text(ti_s5066, ", PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1314 s5066_tree = proto_item_add_subtree(ti_s5066, ett_s5066);
1315 proto_tree_add_item(s5066_tree, hf_s5066_sync_word, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
1316 if (!s5066_edition_one) {
1317 proto_tree_add_item(s5066_tree, hf_s5066_version, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1319 proto_tree_add_item(s5066_tree, hf_s5066_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
1320 ti_pdu = proto_tree_add_item(s5066_tree, hf_s5066_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
1321 s5066_tree_pdu = proto_item_add_subtree(ti_pdu, ett_s5066_pdu);
1322 switch (pdu_type) {
1323 case 1: offset = dissect_s5066_01(tvb, offset, s5066_tree_pdu); break;
1324 /* case 2: offset = dissect_s5066_02(tvb, offset, s5066_tree_pdu); break; */
1325 case 3: offset = dissect_s5066_03(tvb, offset, s5066_tree_pdu); break;
1326 case 4: offset = dissect_s5066_04(tvb, offset, s5066_tree_pdu); break;
1327 case 5: offset = dissect_s5066_05(tvb, offset, s5066_tree_pdu); break;
1328 case 6: offset = dissect_s5066_06(tvb, offset, s5066_tree_pdu); break;
1329 case 7: offset = dissect_s5066_07(tvb, offset, s5066_tree_pdu); break;
1330 case 8: offset = dissect_s5066_08(tvb, offset, s5066_tree_pdu); break;
1331 case 9: offset = dissect_s5066_09(tvb, offset, s5066_tree_pdu); break;
1332 case 10: offset = dissect_s5066_10(tvb, offset, s5066_tree_pdu); break;
1333 case 11: offset = dissect_s5066_11(tvb, offset, s5066_tree_pdu); break;
1334 case 12: offset = dissect_s5066_12(tvb, offset, s5066_tree_pdu); break;
1335 case 13: offset = dissect_s5066_13(tvb, offset, s5066_tree_pdu); break;
1336 case 14: offset = dissect_s5066_14(tvb, offset, s5066_tree_pdu); break;
1337 /* case 15: offset = dissect_s5066_15(tvb, offset, s5066_tree_pdu); break; */
1338 /* case 16: offset = dissect_s5066_16(tvb, offset, s5066_tree_pdu); break; */
1339 /* case 17: offset = dissect_s5066_17(tvb, offset, s5066_tree_pdu); break; */
1340 case 18: offset = dissect_s5066_18(tvb, offset, s5066_tree_pdu, pdu_size); break;
1341 case 19: offset = dissect_s5066_19(tvb, offset, s5066_tree_pdu, pdu_size); break;
1342 case 20: offset = dissect_s5066_20(tvb, offset, s5066_tree_pdu); break;
1343 case 21: offset = dissect_s5066_21(tvb, offset, s5066_tree_pdu, pdu_size); break;
1344 case 22: offset = dissect_s5066_22(tvb, offset, s5066_tree_pdu); break;
1345 case 23: offset = dissect_s5066_23(tvb, offset, s5066_tree_pdu); break;
1346 case 24: offset = dissect_s5066_24(tvb, offset, s5066_tree_pdu); break;
1347 case 25: offset = dissect_s5066_25(tvb, offset, s5066_tree_pdu, pdu_size); break;
1348 case 26: offset = dissect_s5066_26(tvb, offset, s5066_tree_pdu); break;
1349 case 27: offset = dissect_s5066_27(tvb, offset, s5066_tree_pdu); break;
1352 proto_item_set_len(ti_s5066, offset);
1354 /* Call sub dissector(s) */
1355 reported_length = pdu_size - offset;
1356 available_length = tvb_length(tvb) - offset;
1358 next_tvb = tvb_new_subset(tvb, offset, MIN(available_length, reported_length), reported_length);
1359 call_dissector(data_handle, next_tvb, pinfo, tree);
1361 return tvb_length(tvb);