2 * Routines for STANAG 5066 SIS layer packet disassembly
6 * Copyright (c) 2005 by Menno Andriesse <s5066 [AT] nc3a.nato.int>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1999 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/dissectors/packet-tcp.h> /* For tcp_dissect_pdus() */
36 /* Forward reference */
37 /* Register functions */
38 void proto_reg_handoff_s5066(void);
40 static void dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
41 static guint get_s5066_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset);
42 static void dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
43 /* Service type and address dissectors */
44 static guint dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree);
45 static guint dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source);
46 /* S-Primitive dissectors */
47 static guint dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree);
48 /* static guint dissect_s5066_02(tvbuff_t *tvb, guint offset, proto_tree *tree); */
49 static guint dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree);
50 static guint dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree);
51 static guint dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree);
52 static guint dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree);
53 static guint dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree);
54 static guint dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree);
55 static guint dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree);
56 static guint dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree);
57 static guint dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree);
58 static guint dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree);
59 static guint dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree);
60 static guint dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree);
61 /* static guint dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree); */
62 /* static guint dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree); */
63 /* static guint dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree); */
64 static guint dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
65 static guint dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
66 static guint dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree);
67 static guint dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
68 static guint dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree);
69 static guint dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree);
70 static guint dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree);
71 static guint dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size);
72 static guint dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree);
73 static guint dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree);
75 static gint proto_s5066 = -1;
76 static dissector_handle_t data_handle;
78 /* Enable desegmentation of S5066 over TCP */
79 static gboolean s5066_desegment = TRUE;
80 /* Dissect old 'edition 1' of STANAG 5066 (It lacks the 'version' field.) */
81 static gboolean s5066_edition_one = FALSE;
82 /* This port is registered with IANA */
83 static guint global_s5066_port = 5066;
84 /* Size of header outside 'size' field */
85 static gint s5066_header_size = 5;
86 /* Offset of 'size' field */
87 static gint s5066_size_offset = 3;
89 /* Sync should be 0x90EB */
90 static gint hf_s5066_sync_word = -1;
91 /* Version should be 0x00 */
92 static gint hf_s5066_version = -1;
93 /* Total size of the PDU, excluding this size and previous fields */
94 /* So total size is this + 5 bytes (s5066_header_size) */
95 static gint hf_s5066_size = -1;
97 static gint hf_s5066_type = -1;
98 static const value_string s5066_pdu_type[] = {
99 { 1, "S_BIND_REQUEST"},
100 { 2, "S_UNBIND_REQUEST"},
101 { 3, "S_BIND_ACCEPTED"},
102 { 4, "S_BIND_REJECTED"},
103 { 5, "S_UNBIND_INDICATION"},
104 { 6, "S_HARD_LINK_ESTABLISH"},
105 { 7, "S_HARD_LINK_TERMINATE"},
106 { 8, "S_HARD_LINK_ESTABLISHED"},
107 { 9, "S_HARD_LINK_REJECTED"},
108 {10, "S_HARD_LINK_TERMINATED"},
109 {11, "S_HARD_LINK_INDICATION"},
110 {12, "S_HARD_LINK_ACCEPT"},
111 {13, "S_HARD_LINK_REJECT"},
112 {14, "S_SUBNET_AVAILABILITY"},
113 {15, "S_DATAFLOW_ON"},
114 {16, "S_DATAFLOW_OFF"},
115 {17, "S_KEEP_ALIVE"},
116 {18, "S_MANAGEMENT_MESSAGE_REQUEST"},
117 {19, "S_MANAGEMENT_MESSAGE_INDICATION"},
118 {20, "S_UNIDATA_REQUEST"},
119 {21, "S_UNIDATA_INDICATION"},
120 {22, "S_UNIDATA_REQUEST_CONFIRM"},
121 {23, "S_UNIDATA_REQUEST_REJECTED"},
122 {24, "S_EXPEDITED_UNIDATA_REQUEST"},
123 {25, "S_EXPEDITED_UNIDATA_INDICATION"},
124 {26, "S_EXPEDITED_UNIDATA_REQUEST_CONFIRM"},
125 {27, "S_EXPEDITED_UNIDATA_REQUEST_REJECTED"},
129 /* STANAG 5066 Address */
130 /* Size is defined in nibbles (4 bits) */
131 static gint hf_s5066_ad_size = -1;
132 /* Group flag: 0 = false, 1 = true */
133 static gint hf_s5066_ad_group = -1;
134 /* The remainder of the 4 bytes form the address */
135 static gint hf_s5066_ad_address = -1;
138 /* Transmission mode: */
139 static gint hf_s5066_st_txmode = -1;
140 static const value_string s5066_st_txmode[] = {
141 { 0, "Ignore service type field"},
143 { 2, "Non-ARQ (Broadcast)"},
144 { 3, "Non-ARQ (with errors)"},
145 { 4, "Other non-ARQ types"},
146 { 5, "Other non-ARQ types"},
147 { 6, "Other non-ARQ types"},
148 { 7, "Other non-ARQ types"},
149 { 8, "Other non-ARQ types"},
150 { 9, "Other non-ARQ types"},
151 {10, "Other non-ARQ types"},
152 {11, "Other non-ARQ types"},
153 {12, "Other non-ARQ types"},
154 {13, "Other non-ARQ types"},
155 {14, "Other non-ARQ types"},
156 {15, "Other non-ARQ types"},
159 /* Delivery confirmation: */
160 static gint hf_s5066_st_delivery_confirmation = -1;
161 static const value_string s5066_st_delivery_confirmation[] = {
162 { 0, "No confirmation"},
163 { 1, "Node delivery confirmation"},
164 { 2, "Client delivery confirmation"},
165 { 3, "-- Not defined --"},
168 /* Delivery order: */
169 static gint hf_s5066_st_delivery_order = -1;
170 static const value_string s5066_st_delivery_order[] = {
171 { 0, "In-order delivery"},
172 { 1, "As-they-arrive"},
175 /* Extended field present: (Never in the current version.) */
176 static gint hf_s5066_st_extended = -1;
177 static const value_string s5066_st_extended[] = {
178 { 0, "No extended field"},
179 { 1, "Extended field follows"},
182 /* Number of retransmissions when in Non-ARQ: */
183 static gint hf_s5066_st_retries = -1;
185 /* Type 1: S_BIND_REQUEST */
186 static gint hf_s5066_01_sapid = -1;
187 static gint hf_s5066_01_rank = -1;
188 static gint hf_s5066_01_unused = -1;
190 /* Type 2: S_UNBIND_REQUEST */
191 /* --- no subfields --- */
193 /* Type 3: S_BIND_ACCEPTED */
194 static gint hf_s5066_03_sapid = -1;
195 static gint hf_s5066_03_unused = -1;
196 static gint hf_s5066_03_mtu = -1;
198 /* Type 4: S_BIND_REJECTED */
199 static gint hf_s5066_04_reason = -1;
200 static const value_string s5066_04_reason[] = {
201 { 0, "Unknown reason"},
202 { 1, "Not enough resources"},
203 { 2, "Invalid Sap ID"},
204 { 3, "Sap ID already allocated"},
205 { 4, "ARQ mode unsupportable during broadcast session"},
209 /* Type 5: S_UNBIND_INDICATION */
210 static gint hf_s5066_05_reason = -1;
211 static const value_string s5066_05_reason[] = {
212 { 0, "Unknown reason"},
213 { 1, "Connection pre-empted by higher ranking client"},
214 { 2, "Inactivity (failure to respond to 'Keep-alive')"},
215 { 3, "Too many invalid primitives"},
216 { 4, "Too many expedited data request primitives"},
217 { 5, "ARQ mode unsupportable during broadcast session"},
221 /* Hard links: hardlinktype value string array. */
222 static const value_string s5066_hard_link_type[] = {
223 { 0, "Link reservation"},
224 { 1, "Partial Bandwidth reservation"},
225 { 2, "Full Bandwidth reservation"},
226 { 3, "--- undefined ---"},
230 /* Type 6: S_HARD_LINK_ESTABLISH */
231 static gint hf_s5066_06_link_type = -1;
232 static gint hf_s5066_06_link_priority = -1;
233 static gint hf_s5066_06_sapid = -1;
235 /* Type 7: S_HARD_LINK_TERMINATE */
236 /* Only remote node address */
238 /* Type 8: S_HARD_LINK_ESTABLISHED */
239 static gint hf_s5066_08_remote_status = -1;
240 static const value_string s5066_08_remote_status[] = {
245 static gint hf_s5066_08_link_type = -1;
246 static gint hf_s5066_08_link_priority = -1;
247 static gint hf_s5066_08_sapid = -1;
249 /* Type 9: S_HARD_LINK_REJECTED */
250 static gint hf_s5066_09_reason = -1;
251 static const value_string s5066_09_reason[] = {
252 { 0, "--- undefined ---"},
253 { 1, "Remote node busy"},
254 { 2, "Higher priority link exists"},
255 { 3, "Remote node not responding"},
256 { 4, "Destination Sap ID not bound"},
257 { 5, "Requested Type-0 link exists"},
260 static gint hf_s5066_09_link_type = -1;
261 static gint hf_s5066_09_link_priority = -1;
262 static gint hf_s5066_09_sapid = -1;
264 /* Type 10: S_HARD_LINK_TERMINATED */
265 static gint hf_s5066_10_reason = -1;
266 static const value_string s5066_10_reason[] = {
267 { 0, "--- undefined ---"},
268 { 1, "Link terminated by remote node"},
269 { 2, "Higher priority link requested"},
270 { 3, "Remote node not responding"},
271 { 4, "Destination Sap ID not bound"},
272 { 5, "Physical link broken"},
275 static gint hf_s5066_10_link_type = -1;
276 static gint hf_s5066_10_link_priority = -1;
277 static gint hf_s5066_10_sapid = -1;
279 /* Type 11: S_HARD_LINK_INDICATION */
280 static gint hf_s5066_11_remote_status = -1;
281 static const value_string s5066_11_remote_status[] = {
286 static gint hf_s5066_11_link_type = -1;
287 static gint hf_s5066_11_link_priority = -1;
288 static gint hf_s5066_11_sapid = -1;
290 /* Type 12: S_HARD_LINK_ACCEPT */
291 static gint hf_s5066_12_link_type = -1;
292 static gint hf_s5066_12_link_priority = -1;
293 static gint hf_s5066_12_sapid = -1;
295 /* Type 13: S_HARD_LINK_REJECT */
296 static gint hf_s5066_13_reason = -1;
297 static const value_string s5066_13_reason[] = {
298 { 0, "--- undefined ---"},
301 static gint hf_s5066_13_link_type = -1;
302 static gint hf_s5066_13_link_priority = -1;
303 static gint hf_s5066_13_sapid = -1;
305 /* Type 14: S_SUBNET_AVAILABILITY */
306 static gint hf_s5066_14_status= -1;
307 static const value_string s5066_14_status[] = {
310 { 2, "Receive only"},
315 static gint hf_s5066_14_reason= -1;
316 static const value_string s5066_14_reason[] = {
317 { 0, "Unknown reason"},
318 { 1, "Local node in EMCON"},
319 { 2, "Higher priority link requested"},
323 /* Type 15: S_DATAFLOW_ON */
324 /* --- no subfields --- */
326 /* Type 16: S_DATAFLOW_OFF */
327 /* --- no subfields --- */
329 /* Type 17: S_KEEP_ALIVE */
330 /* --- no subfields --- */
332 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
333 static gint hf_s5066_18_type = -1;
334 static gint hf_s5066_18_body = -1;
336 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
337 static gint hf_s5066_19_type = -1;
338 static gint hf_s5066_19_body = -1;
340 /* Type 20: S_UNIDATA_REQUEST */
341 static gint hf_s5066_20_priority = -1;
342 static gint hf_s5066_20_sapid = -1;
343 static gint hf_s5066_20_ttl = -1;
344 static gint hf_s5066_20_size = -1;
346 /* Type 21: S_UNIDATA_INDICATION */
347 static gint hf_s5066_21_priority = -1;
348 static gint hf_s5066_21_dest_sapid = -1;
349 static gint hf_s5066_21_tx_mode = -1;
350 static gint hf_s5066_21_src_sapid = -1;
351 static gint hf_s5066_21_size = -1;
352 static gint hf_s5066_21_err_blocks = -1;
353 static gint hf_s5066_21_err_ptr = -1;
354 static gint hf_s5066_21_err_size = -1;
355 static gint hf_s5066_21_nrx_blocks = -1;
356 static gint hf_s5066_21_nrx_ptr = -1;
357 static gint hf_s5066_21_nrx_size = -1;
360 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
361 static gint hf_s5066_22_unused = -1;
362 static gint hf_s5066_22_sapid = -1;
363 static gint hf_s5066_22_size = -1;
364 static gint hf_s5066_22_data = -1;
366 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
367 static gint hf_s5066_23_reason = -1;
368 static const value_string s5066_23_reason[] = {
369 { 0, "Unknown reason"},
370 { 1, "Time-To-Live expired"},
371 { 2, "Destination SapID not bound"},
372 { 3, "Destination node not responding"},
373 { 4, "U_PDU larger than MTU"},
374 { 5, "Transmission Mode not specified"},
377 static gint hf_s5066_23_sapid = -1;
378 static gint hf_s5066_23_size = -1;
379 static gint hf_s5066_23_data = -1;
381 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
382 static gint hf_s5066_24_unused = -1;
383 static gint hf_s5066_24_sapid = -1;
384 static gint hf_s5066_24_ttl = -1;
385 static gint hf_s5066_24_size = -1;
387 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
388 static gint hf_s5066_25_unused = -1;
389 static gint hf_s5066_25_dest_sapid = -1;
390 static gint hf_s5066_25_tx_mode = -1;
391 static gint hf_s5066_25_src_sapid = -1;
392 static gint hf_s5066_25_size = -1;
393 static gint hf_s5066_25_err_blocks = -1;
394 static gint hf_s5066_25_err_ptr = -1;
395 static gint hf_s5066_25_err_size = -1;
396 static gint hf_s5066_25_nrx_blocks = -1;
397 static gint hf_s5066_25_nrx_ptr = -1;
398 static gint hf_s5066_25_nrx_size = -1;
400 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
401 static gint hf_s5066_26_unused = -1;
402 static gint hf_s5066_26_sapid = -1;
403 static gint hf_s5066_26_size = -1;
404 static gint hf_s5066_26_data = -1;
406 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
407 static gint hf_s5066_27_reason = -1;
408 static const value_string s5066_27_reason[] = {
409 { 0, "Unknown reason"},
410 { 1, "Time-To-Live expired"},
411 { 2, "Destination SapID not bound"},
412 { 3, "Destination node not responding"},
413 { 4, "U_PDU larger than MTU"},
414 { 5, "Transmission Mode not specified"},
417 static gint hf_s5066_27_sapid = -1;
418 static gint hf_s5066_27_size = -1;
419 static gint hf_s5066_27_data = -1;
422 static gint ett_s5066 = -1;
423 static gint ett_s5066_pdu = -1;
424 static gint ett_s5066_servicetype = -1;
425 static gint ett_s5066_address = -1;
428 proto_register_s5066(void)
430 static hf_register_info hf[] = {
431 { &hf_s5066_sync_word,
432 { "Sync preamble", "s5066.sync", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
435 { "S5066 version", "s5066.version", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
438 { "S_Primitive size", "s5066.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
441 { "PDU Type", "s5066.type", FT_UINT8, BASE_DEC, VALS(s5066_pdu_type), 0x0, NULL, HFILL }
443 /* STANAG 5066 Address */
445 { "Address size (1/2 Bytes)", "s5066.address.size", FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL }
447 { &hf_s5066_ad_group,
448 { "Group address", "s5066.address.group", FT_UINT8, BASE_HEX, NULL, 0x10, NULL, HFILL }
450 { &hf_s5066_ad_address,
451 { "Address", "s5066.address.address", FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }
454 { &hf_s5066_st_txmode,
455 { "Transmission mode", "s5066.st.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
457 { &hf_s5066_st_delivery_confirmation,
458 { "Delivery confirmation", "s5066.st.confirm", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_confirmation), 0x0C, NULL, HFILL }
460 { &hf_s5066_st_delivery_order,
461 { "Delivery order", "s5066.st.order", FT_UINT8, BASE_HEX, VALS(s5066_st_delivery_order), 0x02, NULL, HFILL }
463 { &hf_s5066_st_extended,
464 { "Extended field", "s5066.st.extended", FT_UINT8, BASE_HEX, VALS(s5066_st_extended), 0x01, NULL, HFILL }
466 { &hf_s5066_st_retries,
467 { "Minimum number of retransmissions", "s5066.st.retries", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
469 /* PDU Type 01: S_BIND_REQUEST */
470 { &hf_s5066_01_sapid,
471 { "Sap ID", "s5066.01.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
474 { "Rank", "s5066.01.rank", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
476 { &hf_s5066_01_unused,
477 { "(Unused)", "s5066.01.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
479 /* PDU Type 02: S_UNBIND_REQUEST */
480 /* --- no subfields --- */
481 /* PDU Type 03: S_BIND_ACCEPTED */
482 { &hf_s5066_03_sapid,
483 { "Sap ID", "s5066.03.sapid", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
485 { &hf_s5066_03_unused,
486 { "(Unused)", "s5066.03.unused", FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }
489 { "MTU", "s5066.03.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
491 /* PDU Type 04: S_BIND_REJECTED */
492 { &hf_s5066_04_reason,
493 { "Reason", "s5066.04.reason", FT_UINT8, BASE_DEC, VALS(s5066_04_reason), 0x0, NULL, HFILL }
495 /* PDU Type 05: S_UNBIND_INDICATION */
496 { &hf_s5066_05_reason,
497 { "Reason", "s5066.05.reason", FT_UINT8, BASE_DEC, VALS(s5066_05_reason), 0x0, NULL, HFILL }
499 /* Type 6: S_HARD_LINK_ESTABLISH */
500 { &hf_s5066_06_link_type,
501 { "Hardlink type", "s5066.06.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
503 { &hf_s5066_06_link_priority,
504 { "Priority", "s5066.06.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
506 { &hf_s5066_06_sapid,
507 { "Remote Sap ID", "s5066.06.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
509 /* Type 7: S_HARD_LINK_TERMINATE */
510 /* --- Only remote node address --- */
511 /* Type 8: S_HARD_LINK_ESTABLISHED */
512 { &hf_s5066_08_remote_status,
513 { "Remote node status", "s5066.08.status", FT_UINT8, BASE_DEC, VALS(s5066_08_remote_status), 0x0, NULL, HFILL }
515 { &hf_s5066_08_link_type,
516 { "Hardlink type", "s5066.08.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
518 { &hf_s5066_08_link_priority,
519 { "Priority", "s5066.08.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
521 { &hf_s5066_08_sapid,
522 { "Remote Sap ID", "s5066.08.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
524 /* Type 9: S_HARD_LINK_REJECTED */
525 { &hf_s5066_09_reason,
526 { "Reason", "s5066.09.reason", FT_UINT8, BASE_DEC, VALS(s5066_09_reason), 0x0, NULL, HFILL }
528 { &hf_s5066_09_link_type,
529 { "Hardlink type", "s5066.09.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
531 { &hf_s5066_09_link_priority,
532 { "Priority", "s5066.09.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
534 { &hf_s5066_09_sapid,
535 { "Remote Sap ID", "s5066.09.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
537 /* Type 10: S_HARD_LINK_TERMINATED */
538 { &hf_s5066_10_reason,
539 { "Reason", "s5066.10.reason", FT_UINT8, BASE_DEC, VALS(s5066_10_reason), 0x0, NULL, HFILL }
541 { &hf_s5066_10_link_type,
542 { "Hardlink type", "s5066.10.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
544 { &hf_s5066_10_link_priority,
545 { "Priority", "s5066.10.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
547 { &hf_s5066_10_sapid,
548 { "Remote Sap ID", "s5066.10.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
550 /* Type 11: S_HARD_LINK_INDICATION */
551 { &hf_s5066_11_remote_status,
552 { "Remote node status", "s5066.11.status", FT_UINT8, BASE_DEC, VALS(s5066_11_remote_status), 0x0, NULL, HFILL }
554 { &hf_s5066_11_link_type,
555 { "Hardlink type", "s5066.11.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
557 { &hf_s5066_11_link_priority,
558 { "Priority", "s5066.11.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
560 { &hf_s5066_11_sapid,
561 { "Remote Sap ID", "s5066.11.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
563 /* Type 12: S_HARD_LINK_ACCEPT */
564 { &hf_s5066_12_link_type,
565 { "Hardlink type", "s5066.12.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
567 { &hf_s5066_12_link_priority,
568 { "Priority", "s5066.12.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
570 { &hf_s5066_12_sapid,
571 { "Remote Sap ID", "s5066.12.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
573 /* Type 13: S_HARD_LINK_REJECT */
574 { &hf_s5066_13_reason,
575 { "Reason", "s5066.13.reason", FT_UINT8, BASE_DEC, VALS(s5066_13_reason), 0x0, NULL, HFILL }
577 { &hf_s5066_13_link_type,
578 { "Hardlink type", "s5066.13.type", FT_UINT8, BASE_DEC, VALS(s5066_hard_link_type), 0xC0, NULL, HFILL }
580 { &hf_s5066_13_link_priority,
581 { "Priority", "s5066.13.priority", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL }
583 { &hf_s5066_13_sapid,
584 { "Remote Sap ID", "s5066.13.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
586 /* Type 14: S_SUBNET_AVAILABILITY */
587 { &hf_s5066_14_status,
588 { "Status", "s5066.14.status", FT_UINT8, BASE_DEC, VALS(s5066_14_status), 0x0, NULL, HFILL }
590 { &hf_s5066_14_reason,
591 { "Reason", "s5066.14.reason", FT_UINT8, BASE_DEC, VALS(s5066_14_reason), 0x0, NULL, HFILL }
593 /* Type 15: S_DATAFLOW_ON */
594 /* --- no subfields --- */
595 /* Type 16: S_DATAFLOW_OFF */
596 /* --- no subfields --- */
597 /* Type 17: S_KEEP_ALIVE */
598 /* --- no subfields --- */
599 /* Type 18: S_MANAGEMENT_MESSAGE_REQUEST */
601 { "Message Type", "s5066.18.type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
604 { "Message Body", "s5066.18.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
606 /* Type 19: S_MANAGEMENT_MESSAGE_INDICATION */
608 { "Message Type", "s5066.19.type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
611 { "Message Body", "s5066.19.body", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
613 /* Type 20: S_UNIDATA_REQUEST */
614 { &hf_s5066_20_priority,
615 { "Priority", "s5066.20.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
617 { &hf_s5066_20_sapid,
618 { "Destination Sap ID", "s5066.20.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
621 { "Time-To-Live (x2 seconds)", "s5066.20.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, NULL, HFILL }
624 { "U_PDU Size", "s5066.20.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
626 /* Type 21: S_UNIDATA_INDICATION */
627 { &hf_s5066_21_priority,
628 { "Priority", "s5066.21.priority", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
630 { &hf_s5066_21_dest_sapid,
631 { "Destination Sap ID", "s5066.21.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
633 { &hf_s5066_21_tx_mode,
634 { "Transmission Mode", "s5066.21.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
636 { &hf_s5066_21_src_sapid,
637 { "Source Sap ID", "s5066.21.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
640 { "U_PDU Size", "s5066.21.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
642 { &hf_s5066_21_err_blocks,
643 { "Number of errored blocks", "s5066.21.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
645 { &hf_s5066_21_err_ptr,
646 { "Pointer to error block", "s5066.21.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
648 { &hf_s5066_21_err_size,
649 { "Size of error block", "s5066.21.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
651 { &hf_s5066_21_nrx_blocks,
652 { "Number of non-received blocks", "s5066.21.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
654 { &hf_s5066_21_nrx_ptr,
655 { "Pointer to non-received block", "s5066.21.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
657 { &hf_s5066_21_nrx_size,
658 { "Size of non-received block", "s5066.21.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
660 /* Type 22: S_UNIDATA_REQUEST_CONFIRM */
661 { &hf_s5066_22_unused,
662 { "(Unused)", "s5066.22.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
664 { &hf_s5066_22_sapid,
665 { "Destination Sap ID", "s5066.22.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
668 { "U_PDU Size", "s5066.22.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
671 { "(Part of) Confirmed data", "s5066.22.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
673 /* Type 23: S_UNIDATA_REQUEST_REJECTED */
674 { &hf_s5066_23_reason,
675 { "Reason", "s5066.23.reason", FT_UINT8, BASE_DEC, VALS(s5066_23_reason), 0xF0, NULL, HFILL }
677 { &hf_s5066_23_sapid,
678 { "Destination Sap ID", "s5066.23.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
681 { "U_PDU Size", "s5066.23.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
684 { "(Part of) Rejected data", "s5066.23.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
686 /* Type 24: S_EXPEDITED_UNIDATA_REQUEST */
687 { &hf_s5066_24_unused,
688 { "(Unused)", "s5066.24.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
690 { &hf_s5066_24_sapid,
691 { "Destination Sap ID", "s5066.24.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
694 { "Time-To-Live (x2 seconds)", "s5066.24.ttl", FT_UINT24, BASE_DEC, NULL, 0x0FFFFF, NULL, HFILL }
697 { "U_PDU Size", "s5066.24.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
699 /* Type 25: S_EXPEDITED_UNIDATA_INDICATION */
700 { &hf_s5066_25_unused,
701 { "(Unused)", "s5066.25.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
703 { &hf_s5066_25_dest_sapid,
704 { "Destination Sap ID", "s5066.25.dest_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
706 { &hf_s5066_25_tx_mode,
707 { "Transmission Mode", "s5066.25.txmode", FT_UINT8, BASE_HEX, VALS(s5066_st_txmode), 0xF0, NULL, HFILL }
709 { &hf_s5066_25_src_sapid,
710 { "Source Sap ID", "s5066.25.src_sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
713 { "U_PDU Size", "s5066.25.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
715 { &hf_s5066_25_err_blocks,
716 { "Number of errored blocks", "s5066.25.err_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
718 { &hf_s5066_25_err_ptr,
719 { "Pointer to error block", "s5066.25.err_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
721 { &hf_s5066_25_err_size,
722 { "Size of error block", "s5066.25.err_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
724 { &hf_s5066_25_nrx_blocks,
725 { "Number of non-received blocks", "s5066.25.nrx_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
727 { &hf_s5066_25_nrx_ptr,
728 { "Pointer to non-received block", "s5066.25.nrx_ptr", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
730 { &hf_s5066_25_nrx_size,
731 { "Size of non-received block", "s5066.25.nrx_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
733 /* Type 26: S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
734 { &hf_s5066_26_unused,
735 { "(Unused)", "s5066.26.unused", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }
737 { &hf_s5066_26_sapid,
738 { "Destination Sap ID", "s5066.26.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
741 { "U_PDU Size", "s5066.26.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
744 { "(Part of) Confirmed data", "s5066.26.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
746 /* Type 27: S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
747 { &hf_s5066_27_reason,
748 { "Reason", "s5066.27.reason", FT_UINT8, BASE_DEC, VALS(s5066_27_reason), 0xF0, NULL, HFILL }
750 { &hf_s5066_27_sapid,
751 { "Destination Sap ID", "s5066.27.sapid", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }
754 { "U_PDU Size", "s5066.27.size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
757 { "(Part of) Rejected data", "s5066.27.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
762 /* Setup protocol subtree array */
763 static gint *ett[] = {
766 &ett_s5066_servicetype,
770 module_t *s5066_module;
772 proto_s5066 = proto_register_protocol (
773 "STANAG 5066 (SIS layer)", /* name */
774 "STANAG 5066", /* short name*/
777 proto_register_field_array(proto_s5066, hf, array_length(hf));
778 proto_register_subtree_array(ett, array_length(ett));
780 s5066_module = prefs_register_protocol(proto_s5066, proto_reg_handoff_s5066);
781 prefs_register_bool_preference(s5066_module, "desegment_pdus",
782 "Reassemble S5066 PDUs spanning multiple TCP segments",
783 "Whether the S5066 dissector should reassemble PDUs spanning multiple TCP segments."
784 " The default is to use reassembly.",
786 prefs_register_bool_preference(s5066_module, "edition_one",
787 "Dissect edition 1.0 of STANAG 5066",
788 "Whether the S5066 dissector should dissect this edition of the STANAG."
789 " This edition was never formally approved and is very rare. The common edition is edition 1.2.",
791 prefs_register_uint_preference(s5066_module, "tcp.port",
792 "STANAG 5066 TCP Port",
793 "Set the port for STANAG 5066. (If other than the default 5066."
794 " This number is registered with IANA.)",
795 10, &global_s5066_port);
799 proto_reg_handoff_s5066(void)
801 static gboolean Initialized = FALSE;
802 static dissector_handle_t s5066_tcp_handle;
803 static guint saved_s5066_port;
806 s5066_tcp_handle = create_dissector_handle(dissect_s5066_tcp, proto_s5066);
807 data_handle = find_dissector("data");
810 dissector_delete("tcp.port", saved_s5066_port, s5066_tcp_handle);
813 dissector_add("tcp.port", global_s5066_port, s5066_tcp_handle);
814 saved_s5066_port = global_s5066_port;
816 if (!s5066_edition_one) {
817 s5066_header_size = 5;
818 s5066_size_offset = 3;
820 s5066_header_size = 4;
821 s5066_size_offset = 2;
826 dissect_s5066_address(tvbuff_t *tvb, guint offset, proto_tree *tree, gint source)
828 proto_item *ti = NULL;
829 proto_tree *s5066_tree_address = NULL;
833 ti = proto_tree_add_text(tree, tvb, offset, 4, "Source Address");
836 ti = proto_tree_add_text(tree, tvb, offset, 4, "Destination Address");
838 s5066_tree_address = proto_item_add_subtree(ti, ett_s5066_address);
839 proto_tree_add_item(s5066_tree_address, hf_s5066_ad_size, tvb, offset, 1, FALSE);
840 proto_tree_add_item(s5066_tree_address, hf_s5066_ad_group, tvb, offset, 1, FALSE);
841 address = tvb_get_ntohl(tvb, offset);
842 address = address & 0x1FFFFFFF;
843 proto_tree_add_ipv4(s5066_tree_address, hf_s5066_ad_address, tvb, offset, 4, g_htonl(address));
849 dissect_s5066_servicetype(tvbuff_t *tvb, guint offset, proto_tree *tree)
851 proto_item *ti = NULL;
852 proto_tree *s5066_tree_servicetype = NULL;
854 ti = proto_tree_add_text(tree, tvb, offset, 2, "Service type");
855 s5066_tree_servicetype = proto_item_add_subtree(ti, ett_s5066_servicetype);
857 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_txmode, tvb, offset, 1, FALSE);
858 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_confirmation, tvb, offset, 1, FALSE);
859 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_delivery_order, tvb, offset, 1, FALSE);
860 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_extended, tvb, offset, 1, FALSE); offset++;
861 proto_tree_add_item(s5066_tree_servicetype, hf_s5066_st_retries, tvb, offset, 1, FALSE);
868 dissect_s5066_01(tvbuff_t *tvb, guint offset, proto_tree *tree)
870 proto_tree_add_item(tree, hf_s5066_01_sapid, tvb, offset, 1, FALSE);
871 proto_tree_add_item(tree, hf_s5066_01_rank, tvb, offset, 1, FALSE); offset++;
873 offset = dissect_s5066_servicetype(tvb, offset, tree);
875 proto_tree_add_item(tree, hf_s5066_01_unused, tvb, offset, 1, FALSE); offset++;
879 /* S_UNBIND_REQUEST */
880 /* Commented out: does nothing and causes <variable not used> messages.
882 dissect_s5066_02(tvbuff_t *tvb, guint offset, proto_tree *tree)
888 /* S_BIND_ACCEPTED */
890 dissect_s5066_03(tvbuff_t *tvb, guint offset, proto_tree *tree)
892 proto_tree_add_item(tree, hf_s5066_03_sapid, tvb, offset, 1, FALSE);
893 proto_tree_add_item(tree, hf_s5066_03_unused, tvb, offset, 1, FALSE); offset++;
894 proto_tree_add_item(tree, hf_s5066_03_mtu, tvb, offset, 2, FALSE); offset +=2;
898 /* S_BIND_REJECTED */
900 dissect_s5066_04(tvbuff_t *tvb, guint offset, proto_tree *tree)
902 proto_tree_add_item(tree, hf_s5066_04_reason, tvb, offset, 1, FALSE); offset++;
906 /* S_UNBIND_INDICATION */
908 dissect_s5066_05(tvbuff_t *tvb, guint offset, proto_tree *tree)
910 proto_tree_add_item(tree, hf_s5066_05_reason, tvb, offset, 1, FALSE); offset++;
914 /* S_HARD_LINK_ESTABLISH */
916 dissect_s5066_06(tvbuff_t *tvb, guint offset, proto_tree *tree)
918 proto_tree_add_item(tree, hf_s5066_06_link_type, tvb, offset, 1, FALSE);
919 proto_tree_add_item(tree, hf_s5066_06_link_priority, tvb, offset, 1, FALSE);
920 proto_tree_add_item(tree, hf_s5066_06_sapid, tvb, offset, 1, FALSE); offset++;
921 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
925 /* S_HARD_LINK_TERMINATE */
927 dissect_s5066_07(tvbuff_t *tvb, guint offset, proto_tree *tree)
929 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
933 /* S_HARD_LINK_ESTABLISHED */
935 dissect_s5066_08(tvbuff_t *tvb, guint offset, proto_tree *tree)
937 proto_tree_add_item(tree, hf_s5066_08_remote_status, tvb, offset, 1, FALSE); offset++;
938 proto_tree_add_item(tree, hf_s5066_08_link_type, tvb, offset, 1, FALSE);
939 proto_tree_add_item(tree, hf_s5066_08_link_priority, tvb, offset, 1, FALSE);
940 proto_tree_add_item(tree, hf_s5066_08_sapid, tvb, offset, 1, FALSE); offset++;
941 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
945 /* S_HARD_LINK_REJECTED */
947 dissect_s5066_09(tvbuff_t *tvb, guint offset, proto_tree *tree)
949 proto_tree_add_item(tree, hf_s5066_09_reason, tvb, offset, 1, FALSE); offset++;
950 proto_tree_add_item(tree, hf_s5066_09_link_type, tvb, offset, 1, FALSE);
951 proto_tree_add_item(tree, hf_s5066_09_link_priority, tvb, offset, 1, FALSE);
952 proto_tree_add_item(tree, hf_s5066_09_sapid, tvb, offset, 1, FALSE); offset++;
953 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
957 /* S_HARD_LINK_TERMINATED */
959 dissect_s5066_10(tvbuff_t *tvb, guint offset, proto_tree *tree)
961 proto_tree_add_item(tree, hf_s5066_10_reason, tvb, offset, 1, FALSE); offset++;
962 proto_tree_add_item(tree, hf_s5066_10_link_type, tvb, offset, 1, FALSE);
963 proto_tree_add_item(tree, hf_s5066_10_link_priority, tvb, offset, 1, FALSE);
964 proto_tree_add_item(tree, hf_s5066_10_sapid, tvb, offset, 1, FALSE); offset++;
965 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
969 /* S_HARD_LINK_INDICATION */
971 dissect_s5066_11(tvbuff_t *tvb, guint offset, proto_tree *tree)
973 proto_tree_add_item(tree, hf_s5066_11_remote_status, tvb, offset, 1, FALSE); offset++;
974 proto_tree_add_item(tree, hf_s5066_11_link_type, tvb, offset, 1, FALSE);
975 proto_tree_add_item(tree, hf_s5066_11_link_priority, tvb, offset, 1, FALSE);
976 proto_tree_add_item(tree, hf_s5066_11_sapid, tvb, offset, 1, FALSE); offset++;
977 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
981 /* S_HARD_LINK_ACCEPT */
983 dissect_s5066_12(tvbuff_t *tvb, guint offset, proto_tree *tree)
985 proto_tree_add_item(tree, hf_s5066_12_link_type, tvb, offset, 1, FALSE);
986 proto_tree_add_item(tree, hf_s5066_12_link_priority, tvb, offset, 1, FALSE);
987 proto_tree_add_item(tree, hf_s5066_12_sapid, tvb, offset, 1, FALSE); offset++;
988 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
992 /* S_HARD_LINK_REJECT */
994 dissect_s5066_13(tvbuff_t *tvb, guint offset, proto_tree *tree)
996 proto_tree_add_item(tree, hf_s5066_13_reason, tvb, offset, 1, FALSE); offset++;
997 proto_tree_add_item(tree, hf_s5066_13_link_type, tvb, offset, 1, FALSE);
998 proto_tree_add_item(tree, hf_s5066_13_link_priority, tvb, offset, 1, FALSE);
999 proto_tree_add_item(tree, hf_s5066_13_sapid, tvb, offset, 1, FALSE); offset++;
1000 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1004 /* S_SUBNET_AVAILABILITY */
1006 dissect_s5066_14(tvbuff_t *tvb, guint offset, proto_tree *tree)
1008 proto_tree_add_item(tree, hf_s5066_14_status, tvb, offset, 1, FALSE); offset++;
1009 proto_tree_add_item(tree, hf_s5066_14_reason, tvb, offset, 1, FALSE); offset++;
1013 /* Following three commented out: do nothing and cause <variable not used> messages. */
1014 /* S_DATA_FLOW_ON */
1017 dissect_s5066_15(tvbuff_t *tvb, guint offset, proto_tree *tree)
1023 /* S_DATA_FLOW_OFF */
1026 dissect_s5066_16(tvbuff_t *tvb, guint offset, proto_tree *tree)
1035 dissect_s5066_17(tvbuff_t *tvb, guint offset, proto_tree *tree)
1041 /* S_MANAGEMENT_MESSAGE_REQUEST */
1043 dissect_s5066_18(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1045 guint body_size = 0;
1046 proto_tree_add_item(tree, hf_s5066_18_type, tvb, offset, 1, FALSE); offset++;
1047 body_size = pdu_size - offset;
1048 proto_tree_add_item(tree, hf_s5066_18_body, tvb, offset, body_size, FALSE); offset += body_size;
1052 /* S_MANAGEMENT_MESSAGE_INDICATION */
1054 dissect_s5066_19(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1056 guint body_size = 0;
1057 proto_tree_add_item(tree, hf_s5066_19_type, tvb, offset, 1, FALSE); offset++;
1058 body_size = pdu_size - offset;
1059 proto_tree_add_item(tree, hf_s5066_19_body, tvb, offset, body_size, FALSE); offset += body_size;
1063 /* S_UNIDATA_REQUEST */
1065 dissect_s5066_20(tvbuff_t *tvb, guint offset, proto_tree *tree)
1067 proto_tree_add_item(tree, hf_s5066_20_priority, tvb, offset, 1, FALSE);
1068 proto_tree_add_item(tree, hf_s5066_20_sapid, tvb, offset, 1, FALSE); offset++;
1069 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1070 offset = dissect_s5066_servicetype(tvb, offset, tree);
1071 proto_tree_add_item(tree, hf_s5066_20_ttl, tvb, offset, 3, FALSE); offset += 3;
1072 proto_tree_add_item(tree, hf_s5066_20_size, tvb, offset, 2, FALSE); offset += 2;
1077 /* S_UNIDATA_INDICATION */
1079 dissect_s5066_21(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1082 proto_item *ti = NULL;
1083 guint d_pdu_size = 0;
1085 guint16 no_err_blocks = 0;
1086 guint16 no_nrx_blocks = 0;
1087 gboolean non_arq_w_errors = FALSE;
1089 proto_tree_add_item(tree, hf_s5066_21_priority, tvb, offset, 1, FALSE);
1090 proto_tree_add_item(tree, hf_s5066_21_dest_sapid, tvb, offset, 1, FALSE); offset++;
1091 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1093 tx_mode = tvb_get_guint8(tvb, offset);
1094 tx_mode = (tx_mode & 0xF0) >> 4;
1096 non_arq_w_errors = TRUE;
1099 proto_tree_add_item(tree, hf_s5066_21_tx_mode, tvb, offset, 1, FALSE);
1100 proto_tree_add_item(tree, hf_s5066_21_src_sapid, tvb, offset, 1, FALSE); offset++;
1101 offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1103 d_pdu_size = tvb_get_ntohs(tvb, offset);
1104 proto_tree_add_item(tree, hf_s5066_21_size, tvb, offset, 2, FALSE); offset += 2;
1106 /* Handle RockwellCollins (<= v2.1) 4-byte offset */
1107 if ( (pdu_size - offset) == (d_pdu_size + 4) ) {
1108 ti = proto_tree_add_item(tree, hf_s5066_21_err_blocks, tvb, offset, 2, FALSE); offset += 2;
1109 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1110 ti = proto_tree_add_item(tree, hf_s5066_21_nrx_blocks, tvb, offset, 2, FALSE); offset += 2;
1111 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1113 /* Handle Non-ARQ with errors */
1114 if ( non_arq_w_errors ) {
1115 no_err_blocks = tvb_get_ntohs(tvb, offset);
1116 proto_tree_add_item(tree, hf_s5066_21_err_blocks, tvb, offset, 2, FALSE); offset += 2;
1117 for (i=0; i<no_err_blocks; i++) {
1118 proto_tree_add_item(tree, hf_s5066_21_err_ptr, tvb, offset, 2, FALSE); offset += 2;
1119 proto_tree_add_item(tree, hf_s5066_21_err_size, tvb, offset, 2, FALSE); offset += 2;
1121 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1122 proto_tree_add_item(tree, hf_s5066_21_nrx_blocks, tvb, offset, 2, FALSE); offset += 2;
1123 for (i=0; i<no_nrx_blocks; i++) {
1124 proto_tree_add_item(tree, hf_s5066_21_nrx_ptr, tvb, offset, 2, FALSE); offset += 2;
1125 proto_tree_add_item(tree, hf_s5066_21_nrx_size, tvb, offset, 2, FALSE); offset += 2;
1131 /* S_UNIDATA_REQUEST_CONFIRM */
1133 dissect_s5066_22(tvbuff_t *tvb, guint offset, proto_tree *tree)
1136 proto_tree_add_item(tree, hf_s5066_22_unused, tvb, offset, 1, FALSE);
1137 proto_tree_add_item(tree, hf_s5066_22_sapid, tvb, offset, 1, FALSE); offset++;
1138 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1139 pdu_size = tvb_get_ntohs(tvb, offset);
1140 proto_tree_add_item(tree, hf_s5066_22_size, tvb, offset, 2, FALSE); offset += 2;
1141 proto_tree_add_item(tree, hf_s5066_22_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1146 /* S_UNIDATA_REQUEST_REJECTED */
1148 dissect_s5066_23(tvbuff_t *tvb, guint offset, proto_tree *tree)
1151 proto_tree_add_item(tree, hf_s5066_23_reason, tvb, offset, 1, FALSE);
1152 proto_tree_add_item(tree, hf_s5066_23_sapid, tvb, offset, 1, FALSE); offset++;
1153 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1154 pdu_size = tvb_get_ntohs(tvb, offset);
1155 proto_tree_add_item(tree, hf_s5066_23_size, tvb, offset, 2, FALSE); offset += 2;
1156 proto_tree_add_item(tree, hf_s5066_23_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1161 /* S_EXPEDITED_UNIDATA_REQUEST */
1163 dissect_s5066_24(tvbuff_t *tvb, guint offset, proto_tree *tree)
1165 proto_tree_add_item(tree, hf_s5066_24_unused, tvb, offset, 1, FALSE);
1166 proto_tree_add_item(tree, hf_s5066_24_sapid, tvb, offset, 1, FALSE); offset++;
1167 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1168 offset = dissect_s5066_servicetype(tvb, offset, tree);
1169 proto_tree_add_item(tree, hf_s5066_24_ttl, tvb, offset, 3, FALSE); offset += 3;
1170 proto_tree_add_item(tree, hf_s5066_24_size, tvb, offset, 2, FALSE); offset += 2;
1175 /* S_EXPEDITED_UNIDATA_INDICATION */
1177 dissect_s5066_25(tvbuff_t *tvb, guint offset, proto_tree *tree, guint pdu_size)
1180 proto_item *ti = NULL;
1181 guint d_pdu_size = 0;
1183 guint16 no_err_blocks = 0;
1184 guint16 no_nrx_blocks = 0;
1185 gboolean non_arq_w_errors = FALSE;
1187 proto_tree_add_item(tree, hf_s5066_25_unused, tvb, offset, 1, FALSE);
1188 proto_tree_add_item(tree, hf_s5066_25_dest_sapid, tvb, offset, 1, FALSE); offset++;
1189 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1191 tx_mode = tvb_get_guint8(tvb, offset);
1192 tx_mode = (tx_mode & 0xF0) >> 4;
1194 non_arq_w_errors = TRUE;
1197 proto_tree_add_item(tree, hf_s5066_25_tx_mode, tvb, offset, 1, FALSE);
1198 proto_tree_add_item(tree, hf_s5066_25_src_sapid, tvb, offset, 1, FALSE); offset++;
1199 offset = dissect_s5066_address(tvb, offset, tree, TRUE);
1201 d_pdu_size = tvb_get_ntohs(tvb, offset);
1202 proto_tree_add_item(tree, hf_s5066_25_size, tvb, offset, 2, FALSE); offset += 2;
1204 /* Handle RockwellCollins (<= v2.1) 4-byte offset */
1205 if ( (pdu_size - offset) == (d_pdu_size + 4) ) {
1206 ti = proto_tree_add_item(tree, hf_s5066_25_err_blocks, tvb, offset, 2, FALSE); offset += 2;
1207 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1208 ti = proto_tree_add_item(tree, hf_s5066_25_nrx_blocks, tvb, offset, 2, FALSE); offset += 2;
1209 proto_item_append_text(ti, ", (Field should not be present. Rockwell Collins v2.1 or earlier.) ");
1211 /* Handle Non-ARQ with errors */
1212 if ( non_arq_w_errors ) {
1213 no_err_blocks = tvb_get_ntohs(tvb, offset);
1214 proto_tree_add_item(tree, hf_s5066_25_err_blocks, tvb, offset, 2, FALSE); offset += 2;
1215 for (i=0; i<no_err_blocks; i++) {
1216 proto_tree_add_item(tree, hf_s5066_25_err_ptr, tvb, offset, 2, FALSE); offset += 2;
1217 proto_tree_add_item(tree, hf_s5066_25_err_size, tvb, offset, 2, FALSE); offset += 2;
1219 no_nrx_blocks = tvb_get_ntohs(tvb, offset);
1220 proto_tree_add_item(tree, hf_s5066_25_nrx_blocks, tvb, offset, 2, FALSE); offset += 2;
1221 for (i=0; i<no_nrx_blocks; i++) {
1222 proto_tree_add_item(tree, hf_s5066_25_nrx_ptr, tvb, offset, 2, FALSE); offset += 2;
1223 proto_tree_add_item(tree, hf_s5066_25_nrx_size, tvb, offset, 2, FALSE); offset += 2;
1229 /* S_EXPEDITED_UNIDATA_REQUEST_CONFIRM */
1231 dissect_s5066_26(tvbuff_t *tvb, guint offset, proto_tree *tree)
1234 proto_tree_add_item(tree, hf_s5066_26_unused, tvb, offset, 1, FALSE);
1235 proto_tree_add_item(tree, hf_s5066_26_sapid, tvb, offset, 1, FALSE); offset++;
1236 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1237 pdu_size = tvb_get_ntohs(tvb, offset);
1238 proto_tree_add_item(tree, hf_s5066_26_size, tvb, offset, 2, FALSE); offset += 2;
1239 proto_tree_add_item(tree, hf_s5066_26_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1244 /* S_EXPEDITED_UNIDATA_REQUEST_REJECTED */
1246 dissect_s5066_27(tvbuff_t *tvb, guint offset, proto_tree *tree)
1249 proto_tree_add_item(tree, hf_s5066_27_reason, tvb, offset, 1, FALSE);
1250 proto_tree_add_item(tree, hf_s5066_27_sapid, tvb, offset, 1, FALSE); offset++;
1251 offset = dissect_s5066_address(tvb, offset, tree, FALSE);
1252 pdu_size = tvb_get_ntohs(tvb, offset);
1253 proto_tree_add_item(tree, hf_s5066_27_size, tvb, offset, 2, FALSE); offset += 2;
1254 proto_tree_add_item(tree, hf_s5066_27_data, tvb, offset, pdu_size, FALSE); offset += pdu_size;
1260 get_s5066_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1264 /* Get the length of the S5066 PDU. */
1265 plen = tvb_get_ntohs(tvb, offset + s5066_size_offset);
1267 /* That length doesn't include the sync, version and length fields; add that in. */
1268 return plen + s5066_header_size;
1272 dissect_s5066_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1274 /* Make sure there are enough bytes... */
1275 if (tvb_length(tvb) < 5)
1277 /* Check if the first two bytes are 0x90 0xEB: if not,
1278 then this is not a S5066 PDU or an unreassembled one.
1279 The third byte is the STANAG 5066 version: Right now only 0x00 is defined. */
1280 if( (tvb_get_guint8(tvb, 0) != 0x90) ||
1281 (tvb_get_guint8(tvb, 1) != 0xEB) ||
1282 (tvb_get_guint8(tvb, 2) != 0x00) ) {
1285 tcp_dissect_pdus(tvb, pinfo, tree, s5066_desegment, s5066_header_size, get_s5066_pdu_len, dissect_s5066_common);
1289 dissect_s5066_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1293 proto_item *ti_s5066 = NULL;
1294 proto_item *ti_pdu = NULL;
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_clear(pinfo->cinfo, COL_INFO);
1305 if (check_col(pinfo->cinfo, COL_INFO)) {
1306 col_add_fstr(pinfo->cinfo, COL_INFO, "PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1309 if (tree) { /* We are being asked for details */
1310 proto_tree *s5066_tree = NULL;
1311 proto_tree *s5066_tree_pdu = NULL;
1313 pdu_size = tvb_get_ntohs(tvb, s5066_size_offset) + s5066_header_size;
1315 ti_s5066 = proto_tree_add_item(tree, proto_s5066, tvb, 0, -1, FALSE);
1316 proto_item_append_text(ti_s5066, ", PDU type %s", val_to_str(pdu_type, s5066_pdu_type, "Unknown (0x%02x)"));
1317 s5066_tree = proto_item_add_subtree(ti_s5066, ett_s5066);
1318 proto_tree_add_item(s5066_tree, hf_s5066_sync_word, tvb, offset, 2, FALSE); offset +=2;
1319 if (!s5066_edition_one) {
1320 proto_tree_add_item(s5066_tree, hf_s5066_version, tvb, offset, 1, FALSE); offset++;
1322 proto_tree_add_item(s5066_tree, hf_s5066_size, tvb, offset, 2, FALSE); offset +=2;
1323 ti_pdu = proto_tree_add_item(s5066_tree, hf_s5066_type, tvb, offset, 1, FALSE); offset++;
1324 s5066_tree_pdu = proto_item_add_subtree(ti_pdu, ett_s5066_pdu);
1326 case 1: offset = dissect_s5066_01(tvb, offset, s5066_tree_pdu); break;
1327 /* case 2: offset = dissect_s5066_02(tvb, offset, s5066_tree_pdu); break; */
1328 case 3: offset = dissect_s5066_03(tvb, offset, s5066_tree_pdu); break;
1329 case 4: offset = dissect_s5066_04(tvb, offset, s5066_tree_pdu); break;
1330 case 5: offset = dissect_s5066_05(tvb, offset, s5066_tree_pdu); break;
1331 case 6: offset = dissect_s5066_06(tvb, offset, s5066_tree_pdu); break;
1332 case 7: offset = dissect_s5066_07(tvb, offset, s5066_tree_pdu); break;
1333 case 8: offset = dissect_s5066_08(tvb, offset, s5066_tree_pdu); break;
1334 case 9: offset = dissect_s5066_09(tvb, offset, s5066_tree_pdu); break;
1335 case 10: offset = dissect_s5066_10(tvb, offset, s5066_tree_pdu); break;
1336 case 11: offset = dissect_s5066_11(tvb, offset, s5066_tree_pdu); break;
1337 case 12: offset = dissect_s5066_12(tvb, offset, s5066_tree_pdu); break;
1338 case 13: offset = dissect_s5066_13(tvb, offset, s5066_tree_pdu); break;
1339 case 14: offset = dissect_s5066_14(tvb, offset, s5066_tree_pdu); break;
1340 /* case 15: offset = dissect_s5066_15(tvb, offset, s5066_tree_pdu); break; */
1341 /* case 16: offset = dissect_s5066_16(tvb, offset, s5066_tree_pdu); break; */
1342 /* case 17: offset = dissect_s5066_17(tvb, offset, s5066_tree_pdu); break; */
1343 case 18: offset = dissect_s5066_18(tvb, offset, s5066_tree_pdu, pdu_size); break;
1344 case 19: offset = dissect_s5066_19(tvb, offset, s5066_tree_pdu, pdu_size); break;
1345 case 20: offset = dissect_s5066_20(tvb, offset, s5066_tree_pdu); break;
1346 case 21: offset = dissect_s5066_21(tvb, offset, s5066_tree_pdu, pdu_size); break;
1347 case 22: offset = dissect_s5066_22(tvb, offset, s5066_tree_pdu); break;
1348 case 23: offset = dissect_s5066_23(tvb, offset, s5066_tree_pdu); break;
1349 case 24: offset = dissect_s5066_24(tvb, offset, s5066_tree_pdu); break;
1350 case 25: offset = dissect_s5066_25(tvb, offset, s5066_tree_pdu, pdu_size); break;
1351 case 26: offset = dissect_s5066_26(tvb, offset, s5066_tree_pdu); break;
1352 case 27: offset = dissect_s5066_27(tvb, offset, s5066_tree_pdu); break;
1355 proto_item_set_len(ti_s5066, offset);
1357 /* Call sub dissector(s) */
1358 reported_length = pdu_size - offset;
1359 available_length = tvb_length(tvb) - offset;
1361 next_tvb = tvb_new_subset(tvb, offset, MIN(available_length, reported_length), reported_length);
1362 call_dissector(data_handle, next_tvb, pinfo, tree);