change the signature for the get_pdu_len() function pointer passed to tcp_dissect_pdu...
[obnox/wireshark/wip.git] / epan / dissectors / packet-s5066.c
1 /* packet-s5066.c
2  * Routines for STANAG 5066 SIS layer packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) 2005 by Menno Andriesse <s5066 [AT] nc3a.nato.int>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1999 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <gmodule.h>
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/emem.h>
35 #include <epan/dissectors/packet-tcp.h> /* For tcp_dissect_pdus() */
36
37 /* Forward reference */
38 /* Register functions */
39 void proto_register_s5066(void);
40 void proto_reg_handoff_s5066(void);
41 /* Main dissectors */
42 static void dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
43 static guint get_s5066_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset);
44 static void dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
45 /* Service type and address dissectors */
46 static guint dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree);
47 static guint dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source);
48 /* S-Primitive dissectors */
49 static guint dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree);
50 /* static guint dissect_s5066_02(tvbuff_t *tvb, guint offset, proto_tree *tree); */
51 static guint dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree);
52 static guint dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree);
53 static guint dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree);
54 static guint dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree);
55 static guint dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree);
56 static guint dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree);
57 static guint dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree);
58 static guint dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree);
59 static guint dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree);
60 static guint dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree);
61 static guint dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree);
62 static guint dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree);
63 /* static guint dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree); */
64 /* static guint dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree); */
65 /* static guint dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree); */
66 static guint dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
67 static guint dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
68 static guint dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree);
69 static guint dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
70 static guint dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree);
71 static guint dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree);
72 static guint dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree);
73 static guint dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
74 static guint dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree);
75 static guint dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree);
76
77 static gint proto_s5066 = -1;
78 static dissector_handle_t s5066_tcp_handle;
79 static dissector_handle_t data_handle;
80
81 /* Enable desegmentation of S5066 over TCP */
82 static gboolean s5066_desegment = TRUE;
83 /* Dissect old 'edition 1' of STANAG 5066 (It lacks the 'version' field.) */
84 static gboolean s5066_edition_one = FALSE;
85 /* This port is registered with IANA */
86 static gint global_s5066_port = 5066;
87 /* Size of header outside 'size' field */
88 static gint s5066_header_size = 5;
89 /* Offset of 'size' field */
90 static gint s5066_size_offset = 3;
91
92 /* Sync should be 0x90EB */
93 static gint hf_s5066_sync_word = -1;
94 /* Version should be 0x00 */
95 static gint hf_s5066_version = -1;
96 /* Total size of the PDU, excluding this size and previous fields */
97 /* So total size is this + 5 bytes (s5066_header_size) */
98 static gint hf_s5066_size = -1;
99 /* Th type of PDU */
100 static gint hf_s5066_type = -1;
101 static const value_string s5066_pdu_type[] = {
102         { 1, "S_BIND_REQUEST"},
103         { 2, "S_UNBIND_REQUEST"},
104         { 3, "S_BIND_ACCEPTED"},
105         { 4, "S_BIND_REJECTED"},
106         { 5, "S_UNBIND_INDICATION"},
107         { 6, "S_HARD_LINK_ESTABLISH"},
108         { 7, "S_HARD_LINK_TERMINATE"},
109         { 8, "S_HARD_LINK_ESTABLISHED"},
110         { 9, "S_HARD_LINK_REJECTED"},
111         {10, "S_HARD_LINK_TERMINATED"},
112         {11, "S_HARD_LINK_INDICATION"},
113         {12, "S_HARD_LINK_ACCEPT"},
114         {13, "S_HARD_LINK_REJECT"},
115         {14, "S_SUBNET_AVAILABILITY"},
116         {15, "S_DATAFLOW_ON"},
117         {16, "S_DATAFLOW_OFF"},
118         {17, "S_KEEP_ALIVE"},
119         {18, "S_MANAGEMENT_MESSAGE_REQUEST"},
120         {19, "S_MANAGEMENT_MESSAGE_INDICATION"},
121         {20, "S_UNIDATA_REQUEST"},
122         {21, "S_UNIDATA_INDICATION"},
123         {22, "S_UNIDATA_REQUEST_CONFIRM"},
124         {23, "S_UNIDATA_REQUEST_REJECTED"},
125         {24, "S_EXPEDITED_UNIDATA_REQUEST"},
126         {25, "S_EXPEDITED_UNIDATA_INDICATION"},
127         {26, "S_EXPEDITED_UNIDATA_REQUEST_CONFIRM"},
128         {27, "S_EXPEDITED_UNIDATA_REQUEST_REJECTED"},
129         { 0, NULL },
130 };
131
132 /* STANAG 5066 Address */
133 /* Size is defined in nibbles (4 bits) */
134 static gint hf_s5066_ad_size = -1;
135 /* Group flag: 0 = false, 1 = true */
136 static gint hf_s5066_ad_group = -1;
137 /* The remainder of the 4 bytes form the address */
138 static gint hf_s5066_ad_address = -1;
139
140 /* Service type */
141 /* Transmission mode: */
142 static gint hf_s5066_st_txmode = -1;
143 static const value_string s5066_st_txmode[] = {
144         { 0, "Ignore service type field"},
145         { 1, "ARQ"},
146         { 2, "Non-ARQ (Broacast)"},
147         { 3, "Non-ARQ (with errors)"},
148         { 4, "Other non-ARQ types"},
149         { 5, "Other non-ARQ types"},
150         { 6, "Other non-ARQ types"},
151         { 7, "Other non-ARQ types"},
152         { 8, "Other non-ARQ types"},
153         { 9, "Other non-ARQ types"},
154         {10, "Other non-ARQ types"},
155         {11, "Other non-ARQ types"},
156         {12, "Other non-ARQ types"},
157         {13, "Other non-ARQ types"},
158         {14, "Other non-ARQ types"},
159         {15, "Other non-ARQ types"},
160         { 0, NULL },
161 };
162 /* Delivery confirmation: */
163 static gint hf_s5066_st_delivery_confirmation = -1;
164 static const value_string s5066_st_delivery_confirmation[] = {
165         { 0, "No confirmation"},
166         { 1, "Node delivery confirmation"},
167         { 2, "Client delivery confirmation"},
168         { 3, "-- Not defined --"},
169         { 0, NULL },
170 };
171 /* Delivery order: */
172 static gint hf_s5066_st_delivery_order = -1;
173 static const value_string s5066_st_delivery_order[] = {
174         { 0, "In-order delivery"},
175         { 1, "As-they-arrive"},
176         { 0, NULL },
177 };
178 /* Extended field present: (Never in the current version.) */
179 static gint hf_s5066_st_extended = -1;
180 static const value_string s5066_st_extended[] = {
181         { 0, "No extended field"},
182         { 1, "Extended field follows"},
183         { 0, NULL },
184 };
185 /* Number of retransmissions when in Non-ARQ: */
186 static gint hf_s5066_st_retries = -1;
187
188 /* Type  1: S_BIND_REQUEST */
189 static gint hf_s5066_01_sapid = -1;
190 static gint hf_s5066_01_rank = -1;
191 static gint hf_s5066_01_unused = -1;
192
193 /* Type  2: S_UNBIND_REQUEST */
194 /*   --- no subfields ---   */
195
196 /* Type  3: S_BIND_ACCEPTED */
197 static gint hf_s5066_03_sapid = -1;
198 static gint hf_s5066_03_unused = -1;
199 static gint hf_s5066_03_mtu = -1;
200
201 /* Type  4: S_BIND_REJECTED */
202 static gint hf_s5066_04_reason = -1;
203 static const value_string s5066_04_reason[] = {
204         { 0, "Unknown reason"},
205         { 1, "Not enough resources"},
206         { 2, "Invalid Sap ID"},
207         { 3, "Sap ID already allocated"},
208         { 4, "ARQ mode unsupportable during broadcast session"},
209         { 0, NULL },
210 };
211
212 /* Type  5: S_UNBIND_INDICATION */
213 static gint hf_s5066_05_reason = -1;
214 static const value_string s5066_05_reason[] = {
215         { 0, "Unknown reason"},
216         { 1, "Connection pre-empted by higher ranking client"},
217         { 2, "Inactivity (failure to respond to 'Keep-alive')"},
218         { 3, "Too many invalid primitives"},
219         { 4, "Too many expedited data request primitives"},
220         { 5, "ARQ mode unsupportable during broadcast session"},
221         { 0, NULL },
222 };
223
224 /* Hard links: hardlinktype value string array. */
225 static const value_string s5066_hard_link_type[] = {
226         { 0, "Link reservation"},
227         { 1, "Partial Bandwidth reservation"},
228         { 2, "Full Bandwidth reservation"},
229         { 3, "--- undefined ---"},
230         { 0, NULL },
231 };
232
233 /* Type  6: S_HARD_LINK_ESTABLISH */
234 static gint hf_s5066_06_link_type = -1;
235 static gint hf_s5066_06_link_priority = -1;
236 static gint hf_s5066_06_sapid = -1;
237
238 /* Type  7: S_HARD_LINK_TERMINATE */
239 /* Only  remote node address */
240
241 /* Type  8: S_HARD_LINK_ESTABLISHED */
242 static gint hf_s5066_08_remote_status = -1;
243 static const value_string s5066_08_remote_status[] = {
244         { 0, "ERROR"},
245         { 1, "OK"},
246         { 0, NULL },
247 };
248 static gint hf_s5066_08_link_type = -1;
249 static gint hf_s5066_08_link_priority = -1;
250 static gint hf_s5066_08_sapid = -1;
251
252 /* Type  9: S_HARD_LINK_REJECTED */
253 static gint hf_s5066_09_reason = -1;
254 static const value_string s5066_09_reason[] = {
255         { 0, "--- undefined ---"},
256         { 1, "Remote node busy"},
257         { 2, "Higher priority link exists"},
258         { 3, "Remote node not responding"},
259         { 4, "Destination Sap ID not bound"},
260         { 5, "Requested Type-0 link exists"},
261         { 0, NULL },
262 };
263 static gint hf_s5066_09_link_type = -1;
264 static gint hf_s5066_09_link_priority = -1;
265 static gint hf_s5066_09_sapid = -1;
266
267 /* Type 10: S_HARD_LINK_TERMINATED */
268 static gint hf_s5066_10_reason = -1;
269 static const value_string s5066_10_reason[] = {
270         { 0, "--- undefined ---"},
271         { 1, "Link terminated by remote node"},
272         { 2, "Higher priority link requested"},
273         { 3, "Remote node not responding"},
274         { 4, "Destination Sap ID not bound"},
275         { 5, "Physical link broken"},
276         { 0, NULL },
277 };
278 static gint hf_s5066_10_link_type = -1;
279 static gint hf_s5066_10_link_priority = -1;
280 static gint hf_s5066_10_sapid = -1;
281
282 /* Type 11: S_HARD_LINK_INDICATION */
283 static gint hf_s5066_11_remote_status = -1;
284 static const value_string s5066_11_remote_status[] = {
285         { 0, "ERROR"},
286         { 1, "OK"},
287         { 0, NULL },
288 };
289 static gint hf_s5066_11_link_type = -1;
290 static gint hf_s5066_11_link_priority = -1;
291 static gint hf_s5066_11_sapid = -1;
292
293 /* Type 12: S_HARD_LINK_ACCEPT */
294 static gint hf_s5066_12_link_type = -1;
295 static gint hf_s5066_12_link_priority = -1;
296 static gint hf_s5066_12_sapid = -1;
297
298 /* Type 13: S_HARD_LINK_REJECT */
299 static gint hf_s5066_13_reason = -1;
300 static const value_string s5066_13_reason[] = {
301         { 0, "--- undefined ---"},
302         { 0, NULL },
303 };
304 static gint hf_s5066_13_link_type = -1;
305 static gint hf_s5066_13_link_priority = -1;
306 static gint hf_s5066_13_sapid = -1;
307
308 /* Type 14: S_SUBNET_AVAILABILITY */
309 static gint hf_s5066_14_status= -1;
310 static const value_string s5066_14_status[] = {
311         { 0, "Off"},
312         { 1, "On"},
313         { 2, "Receive only"},
314         { 3, "Half-duplex"},
315         { 4, "Full-duplex"},
316         { 0, NULL },
317 };
318 static gint hf_s5066_14_reason= -1;
319 static const value_string s5066_14_reason[] = {
320         { 0, "Unknown reason"},
321         { 1, "Local node in EMCON"},
322         { 2, "Higher priority link requested"},
323         { 0, NULL },
324 };
325
326 /* Type 15: S_DATAFLOW_ON */
327 /*   --- no subfields ---   */
328
329 /* Type 16: S_DATAFLOW_OFF */
330 /*   --- no subfields ---   */
331
332 /* Type 17: S_KEEP_ALIVE */
333 /*   --- no subfields ---   */
334
335 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
336 static gint hf_s5066_18_type = -1;
337 static gint hf_s5066_18_body = -1;
338
339 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
340 static gint hf_s5066_19_type = -1;
341 static gint hf_s5066_19_body = -1;
342
343 /* Type 20: S_UNIDATA_REQUEST */
344 static gint hf_s5066_20_priority = -1;
345 static gint hf_s5066_20_sapid = -1;
346 static gint hf_s5066_20_ttl = -1;
347 static gint hf_s5066_20_size = -1;
348
349 /* Type 21: S_UNIDATA_INDICATION */
350 static gint hf_s5066_21_priority = -1;
351 static gint hf_s5066_21_dest_sapid = -1;
352 static gint hf_s5066_21_tx_mode = -1;
353 static gint hf_s5066_21_src_sapid = -1;
354 static gint hf_s5066_21_size = -1;
355 static gint hf_s5066_21_err_blocks = -1;
356 static gint hf_s5066_21_err_ptr = -1;
357 static gint hf_s5066_21_err_size = -1;
358 static gint hf_s5066_21_nrx_blocks = -1;
359 static gint hf_s5066_21_nrx_ptr = -1;
360 static gint hf_s5066_21_nrx_size = -1;
361
362
363 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
364 static gint hf_s5066_22_unused = -1;
365 static gint hf_s5066_22_sapid = -1;
366 static gint hf_s5066_22_size = -1;
367 static gint hf_s5066_22_data = -1;
368
369 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
370 static gint hf_s5066_23_reason = -1;
371 static const value_string s5066_23_reason[] = {
372         { 0, "Unknown reason"},
373         { 1, "Time-To-Live expired"},
374         { 2, "Destination SapID not bound"},
375         { 3, "Destination node not responding"},
376         { 4, "U_PDU larger than MTU"},
377         { 5, "Transmission Mode not specified"},
378         { 0, NULL },
379 };
380 static gint hf_s5066_23_sapid = -1;
381 static gint hf_s5066_23_size = -1;
382 static gint hf_s5066_23_data = -1;
383
384 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
385 static gint hf_s5066_24_unused = -1;
386 static gint hf_s5066_24_sapid = -1;
387 static gint hf_s5066_24_ttl = -1;
388 static gint hf_s5066_24_size = -1;
389
390 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
391 static gint hf_s5066_25_unused = -1;
392 static gint hf_s5066_25_dest_sapid = -1;
393 static gint hf_s5066_25_tx_mode = -1;
394 static gint hf_s5066_25_src_sapid = -1;
395 static gint hf_s5066_25_size = -1;
396 static gint hf_s5066_25_err_blocks = -1;
397 static gint hf_s5066_25_err_ptr = -1;
398 static gint hf_s5066_25_err_size = -1;
399 static gint hf_s5066_25_nrx_blocks = -1;
400 static gint hf_s5066_25_nrx_ptr = -1;
401 static gint hf_s5066_25_nrx_size = -1;
402
403 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
404 static gint hf_s5066_26_unused = -1;
405 static gint hf_s5066_26_sapid = -1;
406 static gint hf_s5066_26_size = -1;
407 static gint hf_s5066_26_data = -1;
408
409 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
410 static gint hf_s5066_27_reason = -1;
411 static const value_string s5066_27_reason[] = {
412         { 0, "Unknown reason"},
413         { 1, "Time-To-Live expired"},
414         { 2, "Destination SapID not bound"},
415         { 3, "Destination node not responding"},
416         { 4, "U_PDU larger than MTU"},
417         { 5, "Transmission Mode not specified"},
418         { 0, NULL },
419 };
420 static gint hf_s5066_27_sapid = -1;
421 static gint hf_s5066_27_size = -1;
422 static gint hf_s5066_27_data = -1;
423
424
425 static gint ett_s5066 = -1;
426 static gint ett_s5066_pdu = -1;
427 static gint ett_s5066_servicetype = -1;
428 static gint ett_s5066_address = -1;
429
430 void
431 proto_register_s5066(void)
432 {
433         static hf_register_info hf[] = {
434                 { &hf_s5066_sync_word,
435                         { "Sync preample", "s5066.sync", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
436                 },
437                 { &hf_s5066_version,
438                         { "S5066 version", "s5066.version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
439                 },
440                 { &hf_s5066_size,
441                         { "S_Primitive size", "s5066.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
442                 },
443                 { &hf_s5066_type,
444                         { "PDU Type", "s5066.type", FT_UINT8, BASE_DEC, VALS(s5066_pdu_type), 0x0, "", HFILL }
445                 },
446                 /* STANAG 5066 Address */
447                 { &hf_s5066_ad_size,
448                         { "Address size (1/2 Bytes)", "s5066.address.size", FT_UINT8, BASE_HEX, NULL, 0xE0, "", HFILL }
449                 },
450                 { &hf_s5066_ad_group,
451                         { "Group address", "s5066.address.group", FT_UINT8, BASE_HEX, NULL, 0x10, "", HFILL }
452                 },
453                 { &hf_s5066_ad_address,
454                         { "Address", "s5066.address.address", FT_IPv4, BASE_NONE, NULL, 0, "", HFILL }
455                 },
456                 /* Service type */
457                 { &hf_s5066_st_txmode,
458                         { "Transmission mode", "s5066.st.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, "", HFILL }
459                 },
460                 { &hf_s5066_st_delivery_confirmation,
461                         { "Delivery confirmation", "s5066.st.confirm", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_confirmation),  0x0C, "", HFILL }
462                 },
463                 { &hf_s5066_st_delivery_order,
464                         { "Delivery order", "s5066.st.order", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_order), 0x02, "", HFILL }
465                 },
466                 { &hf_s5066_st_extended,
467                         { "Extended field", "s5066.st.extended", FT_UINT8, BASE_HEX, VALS(s5066_st_extended), 0x01, "", HFILL }
468                 },
469                 { &hf_s5066_st_retries,
470                         { "Minimum number of retransmissions", "s5066.st.retries", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
471                 },
472                 /* PDU Type 01: S_BIND_REQUEST */
473                 { &hf_s5066_01_sapid,
474                         { "Sap ID", "s5066.01.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
475                 },
476                 { &hf_s5066_01_rank,
477                         { "Rank", "s5066.01.rank", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
478                 },
479                 { &hf_s5066_01_unused,
480                         { "(Unused)", "s5066.01.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, "", HFILL }
481                 },
482                 /* PDU Type 02: S_UNBIND_REQUEST */
483                 /*     --- no subfields ---     */
484                 /* PDU Type 03: S_BIND_ACCEPTED */
485                 { &hf_s5066_03_sapid,
486                         { "Sap ID", "s5066.03.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
487                 },
488                 { &hf_s5066_03_unused,
489                         { "(Unused)", "s5066.03.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, "", HFILL }
490                 },
491                 { &hf_s5066_03_mtu,
492                         { "MTU", "s5066.03.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
493                 },
494                 /* PDU Type 04: S_BIND_REJECTED */
495                 { &hf_s5066_04_reason,
496                         { "Reason", "s5066.04.reason", FT_UINT8, BASE_DEC, VALS(s5066_04_reason), 0x0, "", HFILL }
497                 },
498                 /* PDU Type 05: S_UNBIND_INDICATION */
499                 { &hf_s5066_05_reason,
500                         { "Reason", "s5066.05.reason", FT_UINT8, BASE_DEC, VALS(s5066_05_reason), 0x0, "", HFILL }
501                 },
502                 /* Type  6: S_HARD_LINK_ESTABLISH */
503                 { &hf_s5066_06_link_type,
504                         { "Hardlink type", "s5066.06.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
505                 },
506                 { &hf_s5066_06_link_priority,
507                         { "Priority", "s5066.06.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
508                 },
509                 { &hf_s5066_06_sapid,
510                         { "Remote Sap ID", "s5066.06.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
511                 },
512                 /* Type  7: S_HARD_LINK_TERMINATE */
513                 /* --- Only remote node address --- */
514                 /* Type  8: S_HARD_LINK_ESTABLISHED */
515                 { &hf_s5066_08_remote_status,
516                         { "Remote node status", "s5066.08.status", FT_UINT8, BASE_DEC, VALS(s5066_08_remote_status), 0x0, "", HFILL }
517                 },
518                 { &hf_s5066_08_link_type,
519                         { "Hardlink type", "s5066.08.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
520                 },
521                 { &hf_s5066_08_link_priority,
522                         { "Priority", "s5066.08.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
523                 },
524                 { &hf_s5066_08_sapid,
525                         { "Remote Sap ID", "s5066.08.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
526                 },
527                 /* Type  9: S_HARD_LINK_REJECTED */
528                 { &hf_s5066_09_reason,
529                         { "Reason", "s5066.09.reason", FT_UINT8, BASE_DEC, VALS(s5066_09_reason), 0x0, "", HFILL }
530                 },
531                 { &hf_s5066_09_link_type,
532                         { "Hardlink type", "s5066.09.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
533                 },
534                 { &hf_s5066_09_link_priority,
535                         { "Priority", "s5066.09.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
536                 },
537                 { &hf_s5066_09_sapid,
538                         { "Remote Sap ID", "s5066.09.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
539                 },
540                 /* Type 10: S_HARD_LINK_TERMINATED */
541                 { &hf_s5066_10_reason,
542                         { "Reason", "s5066.10.reason", FT_UINT8, BASE_DEC, VALS(s5066_10_reason), 0x0, "", HFILL }
543                 },
544                 { &hf_s5066_10_link_type,
545                         { "Hardlink type", "s5066.10.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
546                 },
547                 { &hf_s5066_10_link_priority,
548                         { "Priority", "s5066.10.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
549                 },
550                 { &hf_s5066_10_sapid,
551                         { "Remote Sap ID", "s5066.10.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
552                 },
553                 /* Type 11: S_HARD_LINK_INDICATION */
554                 { &hf_s5066_11_remote_status,
555                         { "Remote node status", "s5066.11.status", FT_UINT8, BASE_DEC, VALS(s5066_11_remote_status), 0x0, "", HFILL }
556                 },
557                 { &hf_s5066_11_link_type,
558                         { "Hardlink type", "s5066.11.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
559                 },
560                 { &hf_s5066_11_link_priority,
561                         { "Priority", "s5066.11.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
562                 },
563                 { &hf_s5066_11_sapid,
564                         { "Remote Sap ID", "s5066.11.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
565                 },
566                 /* Type 12: S_HARD_LINK_ACCEPT */
567                 { &hf_s5066_12_link_type,
568                         { "Hardlink type", "s5066.12.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
569                 },
570                 { &hf_s5066_12_link_priority,
571                         { "Priority", "s5066.12.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
572                 },
573                 { &hf_s5066_12_sapid,
574                         { "Remote Sap ID", "s5066.12.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
575                 },
576                 /* Type 13: S_HARD_LINK_REJECT */
577                 { &hf_s5066_13_reason,
578                         { "Reason", "s5066.13.reason", FT_UINT8, BASE_DEC, VALS(s5066_13_reason), 0x0, "", HFILL }
579                 },
580                 { &hf_s5066_13_link_type,
581                         { "Hardlink type", "s5066.13.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, "", HFILL }
582                 },
583                 { &hf_s5066_13_link_priority,
584                         { "Priority", "s5066.13.priority", FT_UINT8, BASE_DEC, NULL, 0x30, "", HFILL }
585                 },
586                 { &hf_s5066_13_sapid,
587                         { "Remote Sap ID", "s5066.13.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
588                 },
589                 /* Type 14: S_SUBNET_AVAILABILITY */
590                 { &hf_s5066_14_status,
591                         { "Status", "s5066.14.status", FT_UINT8, BASE_DEC, VALS(s5066_14_status), 0x0, "", HFILL }
592                 },
593                 { &hf_s5066_14_reason,
594                         { "Reason", "s5066.14.reason", FT_UINT8, BASE_DEC, VALS(s5066_14_reason), 0x0, "", HFILL }
595                 },
596                 /* Type 15: S_DATAFLOW_ON */
597                 /*   --- no subfields ---   */
598                 /* Type 16: S_DATAFLOW_OFF */
599                 /*   --- no subfields ---   */
600                 /* Type 17: S_KEEP_ALIVE */
601                 /*   --- no subfields ---   */
602                 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
603                 { &hf_s5066_18_type,
604                         { "Message Type", "s5066.18.type", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
605                 },
606                 { &hf_s5066_18_body,
607                         { "Message Body", "s5066.18.body", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
608                 },
609                 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
610                 { &hf_s5066_19_type,
611                         { "Message Type", "s5066.19.type", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
612                 },
613                 { &hf_s5066_19_body,
614                         { "Message Body", "s5066.19.body", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
615                 },
616                 /* Type 20: S_UNIDATA_REQUEST */
617                 { &hf_s5066_20_priority,
618                         { "Priority", "s5066.20.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
619                 },
620                 { &hf_s5066_20_sapid,
621                         { "Destination Sap ID", "s5066.20.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
622                 },
623                 { &hf_s5066_20_ttl,
624                         { "Time-To-Live (x2 seconds)", "s5066.20.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, "", HFILL }
625                 },
626                 { &hf_s5066_20_size,
627                         { "U_PDU Size", "s5066.20.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
628                 },
629                 /* Type 21: S_UNIDATA_INDICATION */
630                 { &hf_s5066_21_priority,
631                         { "Priority", "s5066.21.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
632                 },
633                 { &hf_s5066_21_dest_sapid,
634                         { "Destination Sap ID", "s5066.21.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
635                 },
636                 { &hf_s5066_21_tx_mode,
637                         { "Transmission Mode", "s5066.21.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, "", HFILL }
638                 },
639                 { &hf_s5066_21_src_sapid,
640                         { "Source Sap ID", "s5066.21.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
641                 },
642                 { &hf_s5066_21_size,
643                         { "U_PDU Size", "s5066.21.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
644                 },
645                 { &hf_s5066_21_err_blocks,
646                         { "Number of errored blocks", "s5066.21.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
647                 },
648                 { &hf_s5066_21_err_ptr,
649                         { "Pointer to error block", "s5066.21.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
650                 },
651                 { &hf_s5066_21_err_size,
652                         { "Size of error block", "s5066.21.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
653                 },
654                 { &hf_s5066_21_nrx_blocks,
655                         { "Number of non-received blocks", "s5066.21.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
656                 },
657                 { &hf_s5066_21_nrx_ptr,
658                         { "Pointer to non-received block", "s5066.21.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
659                 },
660                 { &hf_s5066_21_nrx_size,
661                         { "Size of non-received block", "s5066.21.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
662                 },
663                 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
664                 { &hf_s5066_22_unused,
665                         { "(Unused)", "s5066.22.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
666                 },
667                 { &hf_s5066_22_sapid,
668                         { "Destination Sap ID", "s5066.22.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
669                 },
670                 { &hf_s5066_22_size,
671                         { "U_PDU Size", "s5066.22.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
672                 },
673                 { &hf_s5066_22_data,
674                         { "(Part of) Confirmed data", "s5066.22.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
675                 },
676                 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
677                 { &hf_s5066_23_reason,
678                         { "Reason", "s5066.23.reason", FT_UINT8, BASE_DEC, VALS(s5066_23_reason), 0xF0, "", HFILL }
679                 },
680                 { &hf_s5066_23_sapid,
681                         { "Destination Sap ID", "s5066.23.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
682                 },
683                 { &hf_s5066_23_size,
684                         { "U_PDU Size", "s5066.23.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
685                 },
686                 { &hf_s5066_23_data,
687                         { "(Part of) Rejected data", "s5066.23.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
688                 },
689                 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
690                 { &hf_s5066_24_unused,
691                         { "(Unused)", "s5066.24.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
692                 },
693                 { &hf_s5066_24_sapid,
694                         { "Destination Sap ID", "s5066.24.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
695                 },
696                 { &hf_s5066_24_ttl,
697                         { "Time-To-Live (x2 seconds)", "s5066.24.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, "", HFILL }
698                 },
699                 { &hf_s5066_24_size,
700                         { "U_PDU Size", "s5066.24.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
701                 },
702                 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
703                 { &hf_s5066_25_unused,
704                         { "(Unused)", "s5066.25.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
705                 },
706                 { &hf_s5066_25_dest_sapid,
707                         { "Destination Sap ID", "s5066.25.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
708                 },
709                 { &hf_s5066_25_tx_mode,
710                         { "Transmission Mode", "s5066.25.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, "", HFILL }
711                 },
712                 { &hf_s5066_25_src_sapid,
713                         { "Source Sap ID", "s5066.25.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
714                 },
715                 { &hf_s5066_25_size,
716                         { "U_PDU Size", "s5066.25.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
717                 },
718                 { &hf_s5066_25_err_blocks,
719                         { "Number of errored blocks", "s5066.25.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
720                 },
721                 { &hf_s5066_25_err_ptr,
722                         { "Pointer to error block", "s5066.25.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
723                 },
724                 { &hf_s5066_25_err_size,
725                         { "Size of error block", "s5066.25.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
726                 },
727                 { &hf_s5066_25_nrx_blocks,
728                         { "Number of non-received blocks", "s5066.25.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
729                 },
730                 { &hf_s5066_25_nrx_ptr,
731                         { "Pointer to non-received block", "s5066.25.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
732                 },
733                 { &hf_s5066_25_nrx_size,
734                         { "Size of non-received block", "s5066.25.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
735                 },
736                 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
737                 { &hf_s5066_26_unused,
738                         { "(Unused)", "s5066.26.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
739                 },
740                 { &hf_s5066_26_sapid,
741                         { "Destination Sap ID", "s5066.26.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
742                 },
743                 { &hf_s5066_26_size,
744                         { "U_PDU Size", "s5066.26.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
745                 },
746                 { &hf_s5066_26_data,
747                         { "(Part of) Confirmed data", "s5066.26.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
748                 },
749                 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
750                 { &hf_s5066_27_reason,
751                         { "Reason", "s5066.27.reason", FT_UINT8, BASE_DEC, VALS(s5066_27_reason), 0xF0, "", HFILL }
752                 },
753                 { &hf_s5066_27_sapid,
754                         { "Destination Sap ID", "s5066.27.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
755                 },
756                 { &hf_s5066_27_size,
757                         { "U_PDU Size", "s5066.27.size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
758                 },
759                 { &hf_s5066_27_data,
760                         { "(Part of) Rejected data", "s5066.27.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
761                 },
762
763         };
764
765         /* Setup protocol subtree array */
766         static gint *ett[] = {
767                 &ett_s5066,
768                 &ett_s5066_pdu,
769                 &ett_s5066_servicetype,
770                 &ett_s5066_address,
771         };
772
773         module_t *s5066_module;
774
775         if (proto_s5066 == -1) {
776                 proto_s5066 = proto_register_protocol (
777                         "STANAG 5066 (SIS layer)",      /* name */
778                         "STANAG 5066",                  /* short name*/
779                         "s5066"                         /* abbrev */
780                 );
781                 proto_register_field_array(proto_s5066, hf, array_length(hf));
782                 proto_register_subtree_array(ett, array_length(ett));
783         }
784
785         s5066_module = prefs_register_protocol(proto_s5066, proto_reg_handoff_s5066);
786         prefs_register_bool_preference(s5066_module, "desegment_pdus",
787                 "Reassemble S5066 PDUs spanning multiple TCP segments",
788                 "Whether the S5066 dissector should reassemble PDUs spanning multiple TCP segments."
789                 " The default is to use reassembly.",
790                 &s5066_desegment);
791         prefs_register_bool_preference(s5066_module, "edition_one",
792                 "Dissect edition 1.0 of STANAG 5066",
793                 "Whether the S5066 dissector should dissect editon 1 of the STANAG."
794                 " This editon was never formally approved and is very rare. The common edition is editon 1.2.",
795                 &s5066_edition_one);
796         prefs_register_uint_preference(s5066_module, "tcp.port",
797                 "STANAG 5066 TCP Port",
798                 "Set the port for STANAG 5066. (If other than the default 5066."
799                 " This number is registered with IANA.)",
800                 10, &global_s5066_port);
801 }
802
803 void
804 proto_reg_handoff_s5066(void)
805 {
806         static gint Initialized = FALSE;
807
808         if (!Initialized) {
809                 s5066_tcp_handle = create_dissector_handle(dissect_s5066_tcp, proto_s5066);
810                 dissector_add("tcp.port", global_s5066_port, s5066_tcp_handle);
811
812                 data_handle = find_dissector("data");
813                 Initialized = TRUE;
814         }
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;
821         }
822 }
823
824 static guint
825 dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source)
826 {
827         proto_item *ti = NULL;
828         proto_tree *s5066_tree_address = NULL;
829         guint32 address;
830
831         if (source) {
832                 ti = proto_tree_add_text(tree, tvb, offset, 4, "Source Address");
833         }
834         else {
835                 ti = proto_tree_add_text(tree, tvb, offset, 4, "Destination Address");
836         }
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, FALSE);
839         proto_tree_add_item(s5066_tree_address, hf_s5066_ad_group, tvb, offset, 1, FALSE);
840         address = tvb_get_ntohl(tvb, offset);
841         address = address & 0x1FFFFFFF;
842         proto_tree_add_ipv4(s5066_tree_address, hf_s5066_ad_address, tvb, offset, 4, g_htonl(address));
843
844         return offset += 4;
845 }
846
847 static guint
848 dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree)
849 {
850         proto_item *ti = NULL;
851         proto_tree *s5066_tree_servicetype = NULL;
852
853         ti = proto_tree_add_text(tree, tvb, offset, 2, "Service type");
854         s5066_tree_servicetype = proto_item_add_subtree(ti, ett_s5066_servicetype);
855
856         proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_txmode, tvb, offset, 1, FALSE);
857         proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_confirmation, tvb, offset, 1, FALSE);
858         proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_order, tvb, offset, 1, FALSE);
859         proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_extended, tvb, offset, 1, FALSE); offset++;
860         proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_retries, tvb, offset, 1, FALSE);
861
862         return offset;
863 }
864
865 /* S_BIND_REQUEST */
866 static guint
867 dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree)
868 {
869         proto_tree_add_item(tree, hf_s5066_01_sapid, tvb, offset, 1, FALSE);
870         proto_tree_add_item(tree, hf_s5066_01_rank, tvb, offset, 1, FALSE); offset++;
871
872         offset = dissect_s5066_servicetype(tvb, offset, tree);
873
874         proto_tree_add_item(tree, hf_s5066_01_unused, tvb, offset, 1, FALSE); offset++;
875         return offset;
876 }
877
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)
882 {
883         return offset;
884 }
885 */
886
887 /* S_BIND_ACCEPTED */
888 static guint
889 dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree)
890 {
891         proto_tree_add_item(tree, hf_s5066_03_sapid, tvb, offset, 1, FALSE);
892         proto_tree_add_item(tree, hf_s5066_03_unused, tvb, offset, 1, FALSE); offset++;
893         proto_tree_add_item(tree, hf_s5066_03_mtu, tvb, offset, 2, FALSE); offset +=2;
894         return offset;
895 }
896
897 /* S_BIND_REJECTED */
898 static guint
899 dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree)
900 {
901         proto_tree_add_item(tree, hf_s5066_04_reason, tvb, offset, 1, FALSE); offset++;
902         return offset;
903 }
904
905 /* S_UNBIND_INDICATION */
906 static guint
907 dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree)
908 {
909         proto_tree_add_item(tree, hf_s5066_05_reason, tvb, offset, 1, FALSE); offset++;
910         return offset;
911 }
912
913 /* S_HARD_LINK_ESTABLISH */
914 static guint
915 dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree)
916 {
917         proto_tree_add_item(tree, hf_s5066_06_link_type, tvb, offset, 1, FALSE);
918         proto_tree_add_item(tree, hf_s5066_06_link_priority, tvb, offset, 1, FALSE);
919         proto_tree_add_item(tree, hf_s5066_06_sapid, tvb, offset, 1, FALSE); offset++;
920         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
921         return offset;
922 }
923
924 /* S_HARD_LINK_TERMINATE */
925 static guint
926 dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree)
927 {
928         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
929         return offset;
930 }
931
932 /* S_HARD_LINK_ESTABLISHED */
933 static guint
934 dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree)
935 {
936         proto_tree_add_item(tree, hf_s5066_08_remote_status, tvb, offset, 1, FALSE); offset++;
937         proto_tree_add_item(tree, hf_s5066_08_link_type, tvb, offset, 1, FALSE);
938         proto_tree_add_item(tree, hf_s5066_08_link_priority, tvb, offset, 1, FALSE);
939         proto_tree_add_item(tree, hf_s5066_08_sapid, tvb, offset, 1, FALSE); offset++;
940         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
941         return offset;
942 }
943
944 /* S_HARD_LINK_REJECTED */
945 static guint
946 dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree)
947 {
948         proto_tree_add_item(tree, hf_s5066_09_reason, tvb, offset, 1, FALSE); offset++;
949         proto_tree_add_item(tree, hf_s5066_09_link_type, tvb, offset, 1, FALSE);
950         proto_tree_add_item(tree, hf_s5066_09_link_priority, tvb, offset, 1, FALSE);
951         proto_tree_add_item(tree, hf_s5066_09_sapid, tvb, offset, 1, FALSE); offset++;
952         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
953         return offset;
954 }
955
956 /* S_HARD_LINK_TERMINATED */
957 static guint
958 dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree)
959 {
960         proto_tree_add_item(tree, hf_s5066_10_reason, tvb, offset, 1, FALSE); offset++;
961         proto_tree_add_item(tree, hf_s5066_10_link_type, tvb, offset, 1, FALSE);
962         proto_tree_add_item(tree, hf_s5066_10_link_priority, tvb, offset, 1, FALSE);
963         proto_tree_add_item(tree, hf_s5066_10_sapid, tvb, offset, 1, FALSE); offset++;
964         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
965         return offset;
966 }
967
968 /* S_HARD_LINK_INDICATION */
969 static guint
970 dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree)
971 {
972         proto_tree_add_item(tree, hf_s5066_11_remote_status, tvb, offset, 1, FALSE); offset++;
973         proto_tree_add_item(tree, hf_s5066_11_link_type, tvb, offset, 1, FALSE);
974         proto_tree_add_item(tree, hf_s5066_11_link_priority, tvb, offset, 1, FALSE);
975         proto_tree_add_item(tree, hf_s5066_11_sapid, tvb, offset, 1, FALSE); offset++;
976         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
977         return offset;
978 }
979
980 /* S_HARD_LINK_ACCEPT */
981 static guint
982 dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree)
983 {
984         proto_tree_add_item(tree, hf_s5066_12_link_type, tvb, offset, 1, FALSE);
985         proto_tree_add_item(tree, hf_s5066_12_link_priority, tvb, offset, 1, FALSE);
986         proto_tree_add_item(tree, hf_s5066_12_sapid, tvb, offset, 1, FALSE); offset++;
987         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
988         return offset;
989 }
990
991 /* S_HARD_LINK_REJECT */
992 static guint
993 dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree)
994 {
995         proto_tree_add_item(tree, hf_s5066_13_reason, tvb, offset, 1, FALSE); offset++;
996         proto_tree_add_item(tree, hf_s5066_13_link_type, tvb, offset, 1, FALSE);
997         proto_tree_add_item(tree, hf_s5066_13_link_priority, tvb, offset, 1, FALSE);
998         proto_tree_add_item(tree, hf_s5066_13_sapid, tvb, offset, 1, FALSE); offset++;
999         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1000         return offset;
1001 }
1002
1003 /* S_SUBNET_AVAILABILITY */
1004 static guint
1005 dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree)
1006 {
1007         proto_tree_add_item(tree, hf_s5066_14_status, tvb, offset, 1, FALSE); offset++;
1008         proto_tree_add_item(tree, hf_s5066_14_reason, tvb, offset, 1, FALSE); offset++;
1009         return offset;
1010 }
1011
1012 /* Following three commented out: do nothing and cause <variable not used> messages. */
1013 /* S_DATA_FLOW_ON */
1014 /*
1015 static guint
1016 dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree)
1017 {
1018         return offset;
1019 }
1020 */
1021
1022 /* S_DATA_FLOW_OFF */
1023 /*
1024 static guint
1025 dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree)
1026 {
1027         return offset;
1028 }
1029 */
1030
1031 /* S_KEEP_ALIVE */
1032 /*
1033 static guint
1034 dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree)
1035 {
1036         return offset;
1037 }
1038 */
1039
1040 /* S_MANAGEMENT_MESSAGE_REQUEST */
1041 static guint
1042 dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1043 {
1044         guint body_size = 0;
1045         proto_tree_add_item(tree, hf_s5066_18_type, tvb, offset, 1, FALSE); offset++;
1046         body_size = pdu_size - offset;
1047         proto_tree_add_item(tree, hf_s5066_18_body, tvb, offset, body_size, FALSE); offset += body_size;
1048         return offset;
1049 }
1050
1051 /* S_MANAGEMENT_MESSAGE_INDICATION */
1052 static guint
1053 dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1054 {
1055         guint body_size = 0;
1056         proto_tree_add_item(tree, hf_s5066_19_type, tvb, offset, 1, FALSE); offset++;
1057         body_size = pdu_size - offset;
1058         proto_tree_add_item(tree, hf_s5066_19_body, tvb, offset, body_size, FALSE); offset += body_size;
1059         return offset;
1060 }
1061
1062 /* S_UNIDATA_REQUEST */
1063 static guint
1064 dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree)
1065 {
1066         proto_tree_add_item(tree, hf_s5066_20_priority, tvb, offset, 1, FALSE);
1067         proto_tree_add_item(tree, hf_s5066_20_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 3;
1071         proto_tree_add_item(tree, hf_s5066_20_size, tvb, offset, 2, FALSE); offset += 2;
1072
1073         return offset;
1074 }
1075
1076 /* S_UNIDATA_INDICATION */
1077 static guint
1078 dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1079 {
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;
1087
1088         proto_tree_add_item(tree, hf_s5066_21_priority, tvb, offset, 1, FALSE);
1089         proto_tree_add_item(tree, hf_s5066_21_dest_sapid, tvb, offset, 1, FALSE); offset++;
1090         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1091
1092         tx_mode = tvb_get_guint8(tvb, offset);
1093         tx_mode = (tx_mode & 0xF0) >> 4;
1094         if (tx_mode == 2) {
1095                 non_arq_w_errors = TRUE;
1096         }
1097
1098         proto_tree_add_item(tree, hf_s5066_21_tx_mode, tvb, offset, 1, FALSE);
1099         proto_tree_add_item(tree, hf_s5066_21_src_sapid, tvb, offset, 1, FALSE); offset++;
1100         offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1101
1102         d_pdu_size = tvb_get_ntohs(tvb, offset);
1103         proto_tree_add_item(tree, hf_s5066_21_size, tvb, offset, 2, FALSE); offset += 2;
1104
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, FALSE); 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, FALSE); offset += 2;
1110                 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1111         }
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, FALSE); 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, FALSE); offset += 2;
1118                         proto_tree_add_item(tree, hf_s5066_21_err_size, tvb, offset, 2, FALSE); offset += 2;
1119                 }
1120                 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1121                 proto_tree_add_item(tree, hf_s5066_21_nrx_blocks, tvb, offset, 2, FALSE); 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, FALSE); offset += 2;
1124                         proto_tree_add_item(tree, hf_s5066_21_nrx_size, tvb, offset, 2, FALSE); offset += 2;
1125                 }
1126         }
1127         return offset;
1128 }
1129
1130 /* S_UNIDATA_REQUEST_CONFIRM */
1131 static guint
1132 dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree)
1133 {
1134         guint pdu_size = 0;
1135         proto_tree_add_item(tree, hf_s5066_22_unused, tvb, offset, 1, FALSE);
1136         proto_tree_add_item(tree, hf_s5066_22_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 2;
1140         proto_tree_add_item(tree, hf_s5066_22_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1141
1142         return offset;
1143 }
1144
1145 /* S_UNIDATA_REQUEST_REJECTED */
1146 static guint
1147 dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree)
1148 {
1149         guint pdu_size = 0;
1150         proto_tree_add_item(tree, hf_s5066_23_reason, tvb, offset, 1, FALSE);
1151         proto_tree_add_item(tree, hf_s5066_23_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 2;
1155         proto_tree_add_item(tree, hf_s5066_23_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1156
1157         return offset;
1158 }
1159
1160 /* S_EXPEDITED_UNIDATA_REQUEST */
1161 static guint
1162 dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree)
1163 {
1164         proto_tree_add_item(tree, hf_s5066_24_unused, tvb, offset, 1, FALSE);
1165         proto_tree_add_item(tree, hf_s5066_24_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 3;
1169         proto_tree_add_item(tree, hf_s5066_24_size, tvb, offset, 2, FALSE); offset += 2;
1170
1171         return offset;
1172 }
1173
1174 /* S_EXPEDITED_UNIDATA_INDICATION */
1175 static guint
1176 dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1177 {
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;
1185
1186         proto_tree_add_item(tree, hf_s5066_25_unused, tvb, offset, 1, FALSE);
1187         proto_tree_add_item(tree, hf_s5066_25_dest_sapid, tvb, offset, 1, FALSE); offset++;
1188         offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1189
1190         tx_mode = tvb_get_guint8(tvb, offset);
1191         tx_mode = (tx_mode & 0xF0) >> 4;
1192         if (tx_mode == 2) {
1193                 non_arq_w_errors = TRUE;
1194         }
1195
1196         proto_tree_add_item(tree, hf_s5066_25_tx_mode, tvb, offset, 1, FALSE);
1197         proto_tree_add_item(tree, hf_s5066_25_src_sapid, tvb, offset, 1, FALSE); offset++;
1198         offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1199
1200         d_pdu_size = tvb_get_ntohs(tvb, offset);
1201         proto_tree_add_item(tree, hf_s5066_25_size, tvb, offset, 2, FALSE); offset += 2;
1202
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, FALSE); 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, FALSE); offset += 2;
1208                 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1209         }
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, FALSE); 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, FALSE); offset += 2;
1216                         proto_tree_add_item(tree, hf_s5066_25_err_size, tvb, offset, 2, FALSE); offset += 2;
1217                 }
1218                 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1219                 proto_tree_add_item(tree, hf_s5066_25_nrx_blocks, tvb, offset, 2, FALSE); 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, FALSE); offset += 2;
1222                         proto_tree_add_item(tree, hf_s5066_25_nrx_size, tvb, offset, 2, FALSE); offset += 2;
1223                 }
1224         }
1225         return offset;
1226 }
1227
1228 /* S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
1229 static guint
1230 dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree)
1231 {
1232         guint pdu_size = 0;
1233         proto_tree_add_item(tree, hf_s5066_26_unused, tvb, offset, 1, FALSE);
1234         proto_tree_add_item(tree, hf_s5066_26_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 2;
1238         proto_tree_add_item(tree, hf_s5066_26_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1239
1240         return offset;
1241 }
1242
1243 /* S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
1244 static guint
1245 dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree)
1246 {
1247         guint pdu_size = 0;
1248         proto_tree_add_item(tree, hf_s5066_27_reason, tvb, offset, 1, FALSE);
1249         proto_tree_add_item(tree, hf_s5066_27_sapid, tvb, offset, 1, FALSE); 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, FALSE); offset += 2;
1253         proto_tree_add_item(tree, hf_s5066_27_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1254
1255         return offset;
1256 }
1257
1258 static guint
1259 get_s5066_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1260 {
1261   guint16 plen;
1262
1263   /* Get the length of the S5066 PDU. */
1264   plen = tvb_get_ntohs(tvb, offset + s5066_size_offset);
1265
1266   /* That length doesn't include the sync, version and length fields; add that in. */
1267   return plen + s5066_header_size;
1268 }
1269
1270 static void
1271 dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1272 {
1273         /* Make sure there are enough bytes... */
1274         if (tvb_length(tvb) < 5)
1275                 return;
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;
1283         }
1284         tcp_dissect_pdus(tvb, pinfo, tree, s5066_desegment, s5066_header_size, get_s5066_pdu_len, dissect_s5066_common);
1285 }
1286
1287 static void
1288 dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1289 {
1290         guint offset = 0;
1291         guint pdu_size = 0;
1292         proto_item *ti_s5066 = NULL;
1293         proto_item *ti_pdu = NULL;
1294         tvbuff_t *next_tvb;
1295         gint available_length = 0;
1296         gint reported_length = 0;
1297
1298         /* Determine PDU type to display in INFO column */
1299         guint8 pdu_type = tvb_get_guint8(tvb, s5066_header_size);
1300
1301         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1302                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "S5066");
1303         }
1304         /* Clear out stuff in the info column, the add PDU type */
1305         if (check_col(pinfo->cinfo, COL_INFO)) {
1306                 col_clear(pinfo->cinfo, COL_INFO);
1307         }
1308         if (check_col(pinfo->cinfo, COL_INFO)) {
1309                 col_add_fstr(pinfo->cinfo, COL_INFO, "PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1310         }
1311
1312         if (tree) { /* We are being asked for details */
1313                 proto_tree *s5066_tree = NULL;
1314                 proto_tree *s5066_tree_pdu = NULL;
1315
1316                 pdu_size = tvb_get_ntohs(tvb, s5066_size_offset) + s5066_header_size;
1317
1318                 ti_s5066 = proto_tree_add_item(tree, proto_s5066, tvb, 0, -1, FALSE);
1319                 proto_item_append_text(ti_s5066, ", PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1320                 s5066_tree = proto_item_add_subtree(ti_s5066, ett_s5066);
1321                 proto_tree_add_item(s5066_tree, hf_s5066_sync_word, tvb, offset, 2, FALSE); offset +=2;
1322                 if (!s5066_edition_one) {
1323                         proto_tree_add_item(s5066_tree, hf_s5066_version,   tvb, offset, 1, FALSE); offset++;
1324                 }
1325                 proto_tree_add_item(s5066_tree, hf_s5066_size,      tvb, offset, 2, FALSE); offset +=2;
1326                 ti_pdu = proto_tree_add_item(s5066_tree, hf_s5066_type, tvb, offset, 1, FALSE); offset++;
1327                 s5066_tree_pdu = proto_item_add_subtree(ti_pdu, ett_s5066_pdu);
1328                 switch (pdu_type) {
1329                 case  1: offset = dissect_s5066_01(tvb, offset, s5066_tree_pdu); break;
1330                 /* case  2: offset = dissect_s5066_02(tvb, offset, s5066_tree_pdu); break; */
1331                 case  3: offset = dissect_s5066_03(tvb, offset, s5066_tree_pdu); break;
1332                 case  4: offset = dissect_s5066_04(tvb, offset, s5066_tree_pdu); break;
1333                 case  5: offset = dissect_s5066_05(tvb, offset, s5066_tree_pdu); break;
1334                 case  6: offset = dissect_s5066_06(tvb, offset, s5066_tree_pdu); break;
1335                 case  7: offset = dissect_s5066_07(tvb, offset, s5066_tree_pdu); break;
1336                 case  8: offset = dissect_s5066_08(tvb, offset, s5066_tree_pdu); break;
1337                 case  9: offset = dissect_s5066_09(tvb, offset, s5066_tree_pdu); break;
1338                 case 10: offset = dissect_s5066_10(tvb, offset, s5066_tree_pdu); break;
1339                 case 11: offset = dissect_s5066_11(tvb, offset, s5066_tree_pdu); break;
1340                 case 12: offset = dissect_s5066_12(tvb, offset, s5066_tree_pdu); break;
1341                 case 13: offset = dissect_s5066_13(tvb, offset, s5066_tree_pdu); break;
1342                 case 14: offset = dissect_s5066_14(tvb, offset, s5066_tree_pdu); break;
1343                 /* case 15: offset = dissect_s5066_15(tvb, offset, s5066_tree_pdu); break; */
1344                 /* case 16: offset = dissect_s5066_16(tvb, offset, s5066_tree_pdu); break; */
1345                 /* case 17: offset = dissect_s5066_17(tvb, offset, s5066_tree_pdu); break; */
1346                 case 18: offset = dissect_s5066_18(tvb, offset, s5066_tree_pdu, pdu_size); break;
1347                 case 19: offset = dissect_s5066_19(tvb, offset, s5066_tree_pdu, pdu_size); break;
1348                 case 20: offset = dissect_s5066_20(tvb, offset, s5066_tree_pdu); break;
1349                 case 21: offset = dissect_s5066_21(tvb, offset, s5066_tree_pdu, pdu_size); break;
1350                 case 22: offset = dissect_s5066_22(tvb, offset, s5066_tree_pdu); break;
1351                 case 23: offset = dissect_s5066_23(tvb, offset, s5066_tree_pdu); break;
1352                 case 24: offset = dissect_s5066_24(tvb, offset, s5066_tree_pdu); break;
1353                 case 25: offset = dissect_s5066_25(tvb, offset, s5066_tree_pdu, pdu_size); break;
1354                 case 26: offset = dissect_s5066_26(tvb, offset, s5066_tree_pdu); break;
1355                 case 27: offset = dissect_s5066_27(tvb, offset, s5066_tree_pdu); break;
1356                 }
1357         }
1358         proto_item_set_len(ti_s5066, offset);
1359
1360         /* Call sub dissector(s) */
1361         reported_length = pdu_size - offset;
1362         available_length = tvb_length(tvb) - offset;
1363
1364         next_tvb = tvb_new_subset(tvb, offset, MIN(available_length, reported_length), reported_length);
1365         call_dissector(data_handle, next_tvb, pinfo, tree);
1366
1367         return;
1368 }