Revert "Fixup: tvb_* -> tvb_captured"
[metze/wireshark/wip.git] / epan / dissectors / packet-s5066dts.c
1 /*
2  * packet-s5066dts.c
3  * Routines for STANAG 5066 DTS layer packet dissection
4  *
5  * Copyright (c) 2013
6  *  by Ibrahim Can Yuce <canyuce [at] gmail [dot] com>
7  *  by M. Baris Demiray <baris.demiray [at] gmail [dot] com>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <epan/prefs.h>
31 #include <epan/expert.h>
32 #include <epan/dissectors/packet-tcp.h> /* For tcp_dissect_pdus() */
33 #include <epan/crc16-tvb.h>
34 #include <epan/crc32-tvb.h>
35 #include <wiretap/wtap.h>
36
37 #define DISSECTOR_NAME                      "s5066dts"
38 /* STANAG 5066 DPDU properties */
39 #define S5066_DPDU_MAX_DPDU_SIZE            1070
40 #define S5066_DPDU_FRAME_HEADER_LEN         15
41 /* Header field index (in bytes) and size (in bits) constants */
42 #define S5066_DPDU_EOW_TYPE_INDEX           2
43 #define S5066_DPDU_EOW_CONTENT_INDEX        3
44 #define S5066_DPDU_EOT_INDEX                4
45 #define S5066_DPDU_SIZE_OF_ADDRESS_INDEX    5
46 #define S5066_DPDU_SIZE_OF_HEADER_INDEX     5
47 #define S5066_DPDU_SYNC_SEQUENCE_SIZE       2 /*bytes*/
48 /* D_PDU message types */
49 #define S5066_DPDU_DATA_ONLY                0
50 #define S5066_DPDU_ACK_ONLY                 1
51 #define S5066_DPDU_DATA_ACK                 2
52 #define S5066_DPDU_RESET_WIN_RESYNC         3
53 #define S5066_DPDU_EXP_DATA_ONLY            4
54 #define S5066_DPDU_EXP_ACK_ONLY             5
55 #define S5066_DPDU_MANAGEMENT               6
56 #define S5066_DPDU_NON_ARQ_DATA             7
57 #define S5066_DPDU_EXP_NON_ARQ_DATA         8
58 #define S5066_DPDU_WARNING                  15
59 /* EOW message types */
60 #define S5066_EOW_RESERVED                  0
61 #define S5066_EOW_DRC_REQUEST               1
62 #define S5066_EOW_DRC_RESPONSE              2
63 #define S5066_EOW_UNRECOGNIZED_TYPE         3
64 #define S5066_EOW_CAPABILITY                4
65 #define S5066_EOW_ALM_REQUEST               5
66 #define S5066_EOW_ALM_RESPONSE              6
67 #define S5066_EOW_HDR_DRC_REQUEST           7
68 #define S5066_EOW_HFTRP_TOKEN               15
69
70 void proto_register_s5066dts(void);
71
72 static gint proto_s5066dts = -1;
73
74 /* Configuration parameters */
75 static gboolean config_proto_desegment = TRUE;
76
77 /* Initialize expert fields */
78 static expert_field ei_s5066dts_eow_hdr_drc_request_invalid = EI_INIT;
79 static expert_field ei_s5066dts_eow_hftrp_invalid = EI_INIT;
80
81 /* TCP port that will be listened by the application that peer
82  * dts layers will be connected through
83  */
84 static guint config_s5066dts_port = 0;
85
86 static gint hf_s5066dts_sync_word = -1;
87 static gint hf_s5066dts_dpdu_type = -1;
88 static gint hf_s5066dts_eow_type = -1;
89 static gint hf_s5066dts_eow_data = -1;
90 static gint hf_s5066dts_eot = -1;
91 static gint hf_s5066dts_address_size = -1;
92 static gint hf_s5066dts_header_size = -1;
93 static gint hf_s5066dts_header_crc = -1;
94 static gint hf_s5066dts_cpdu_crc = -1;
95 static gint hf_s5066dts_segmented_cpdu = -1;
96
97 /* EOW TYPES */
98 /* { 1, "DRC_REQUEST"}, */
99 static gint hf_s5066dts_eow_drc_request_data_rate = -1;
100 static gint hf_s5066dts_eow_drc_request_interleaving = -1;
101 static gint hf_s5066dts_eow_drc_request_others = -1;
102 /* { 2, "DRC_RESPONSE"}, */
103 static gint hf_s5066dts_eow_drc_response_response = -1;
104 static gint hf_s5066dts_eow_drc_response_reason = -1;
105 /* { 3, "UNRECOGNIZED_TYPE"}, */
106 static gint hf_s5066dts_eow_unrec_type_response = -1;
107 static gint hf_s5066dts_eow_unrec_type_reason = -1;
108 /* { 4, "CAPABILITY"}, */
109 static gint hf_s5066dts_eow_capability_adaptive = -1;
110 static gint hf_s5066dts_eow_capability_stanag_4529 = -1;
111 static gint hf_s5066dts_eow_capability_mil_std_188_110a = -1;
112 static gint hf_s5066dts_eow_capability_extended = -1;
113 static gint hf_s5066dts_eow_capability_full_duplex = -1;
114 static gint hf_s5066dts_eow_capability_split_frequency = -1;
115 static gint hf_s5066dts_eow_capability_non_arcs_ale = -1;
116 static gint hf_s5066dts_eow_capability_arcs = -1;
117 /* { 5, "ALM_REQUEST"}, */
118 static gint hf_s5066dts_eow_alm_request_data_rate = -1;
119 static gint hf_s5066dts_eow_alm_request_interleaving = -1;
120 static gint hf_s5066dts_eow_alm_request_others = -1;
121 /* { 6, "ALM_RESPONSE"}, */
122 static gint hf_s5066dts_eow_alm_response_response = -1;
123 static gint hf_s5066dts_eow_alm_response_reason = -1;
124 /* { 7, "HDR_DRC_REQUEST"}, */
125 static gint hf_s5066dts_eow_hdr_drc_request_waveform = -1;
126 static gint hf_s5066dts_eow_hdr_drc_request_num_channels = -1;
127 static gint hf_s5066dts_eow_hdr_drc_request_data_rate = -1;
128 static gint hf_s5066dts_eow_hdr_drc_request_interleaver_length = -1;
129 /* {15, "HFTRP FRAME CONTROL"}, */
130 static gint hf_s5066dts_eow_hftrp_hftrp_token = -1;
131
132 /* DPDU TYPES */
133 /* { 0, "DATA_ONLY"}, */
134 static gint hf_s5066dts_data_only_cpdu_start = -1;
135 static gint hf_s5066dts_data_only_cpdu_end = -1;
136 static gint hf_s5066dts_data_only_deliver_in_order = -1;
137 static gint hf_s5066dts_data_only_drop_cpdu = -1;
138 static gint hf_s5066dts_data_only_tx_win_uwe = -1;
139 static gint hf_s5066dts_data_only_tx_win_lwe = -1;
140 static gint hf_s5066dts_data_only_segmented_cpdu_size = -1;
141 static gint hf_s5066dts_data_only_transmit_sequence_number = -1;
142 /* { 1, "ACK_ONLY"}, */
143 static gint hf_s5066dts_ack_only_rx_lwe = -1;
144 static gint hf_s5066dts_ack_only_acks = -1;
145 /* { 2, "DATA_ACK"}, */
146 static gint hf_s5066dts_data_ack_cpdu_start = -1;
147 static gint hf_s5066dts_data_ack_cpdu_end = -1;
148 static gint hf_s5066dts_data_ack_deliver_in_order = -1;
149 static gint hf_s5066dts_data_ack_drop_cpdu = -1;
150 static gint hf_s5066dts_data_ack_tx_win_uwe = -1;
151 static gint hf_s5066dts_data_ack_tx_win_lwe = -1;
152 static gint hf_s5066dts_data_ack_segmented_cpdu_size = -1;
153 static gint hf_s5066dts_data_ack_transmit_sequence_number = -1;
154 static gint hf_s5066dts_data_ack_rx_lwe = -1;
155 static gint hf_s5066dts_data_ack_acks = -1;
156 /* { 3, "RESET_WIN_RESYNC"}, */
157 static gint hf_s5066dts_reset_win_resync_unused = -1;
158 static gint hf_s5066dts_reset_win_resync_full_reset_command = -1;
159 static gint hf_s5066dts_reset_win_resync_reset_tx_win_rqst = -1;
160 static gint hf_s5066dts_reset_win_resync_reset_rx_win_cmnd = -1;
161 static gint hf_s5066dts_reset_win_resync_reset_ack = -1;
162 static gint hf_s5066dts_reset_win_resync_new_rx_lwe = -1;
163 static gint hf_s5066dts_reset_win_resync_reset_frame_id_number = -1;
164 /* { 4, "EXP_DATA_ONLY"}, */
165 static gint hf_s5066dts_exp_data_only_cpdu_start = -1;
166 static gint hf_s5066dts_exp_data_only_cpdu_end = -1;
167 static gint hf_s5066dts_exp_data_only_cpdu_id = -1;
168 static gint hf_s5066dts_exp_data_only_segmented_cpdu_size = -1;
169 static gint hf_s5066dts_exp_data_only_transmit_sequence_number = -1;
170 /* { 5, "EXP_ACK_ONLY"}, */
171 static gint hf_s5066dts_exp_ack_only_rx_lwe = -1;
172 static gint hf_s5066dts_exp_ack_only_acks = -1;
173 /* { 6, "MANAGEMENT"}, */
174 static gint hf_s5066dts_management_unused = -1;
175 static gint hf_s5066dts_management_extended_message_flag = -1;
176 static gint hf_s5066dts_management_message = -1;
177 static gint hf_s5066dts_management_ack = -1;
178 static gint hf_s5066dts_management_management_frame_id = -1;
179 static gint hf_s5066dts_management_extended_message = -1;
180 static gint hf_s5066dts_management_extended_message_hftrp_payload_size = -1;
181 static gint hf_s5066dts_management_extended_message_hftrp_ra = -1;
182 static gint hf_s5066dts_management_extended_message_hftrp_seq_id = -1;
183 static gint hf_s5066dts_management_extended_message_hftrp_gen_seq_id = -1;
184 static gint hf_s5066dts_management_extended_message_hftrp_new_successor_id = -1;
185 static gint hf_s5066dts_management_extended_message_hftrp_number_of_nodes = -1;
186 /* { 7, "NON_ARQ_DATA"}, */
187 static gint hf_s5066dts_non_arq_data_cpdu_id_1 = -1;
188 static gint hf_s5066dts_non_arq_data_deliver_in_order = -1;
189 static gint hf_s5066dts_non_arq_data_group_address = -1;
190 static gint hf_s5066dts_non_arq_data_cpdu_id_2 = -1;
191 static gint hf_s5066dts_non_arq_data_cpdu_size = -1;
192 static gint hf_s5066dts_non_arq_data_cpdu_segment_offset = -1;
193 static gint hf_s5066dts_non_arq_data_cpdu_reception_window = -1;
194 static gint hf_s5066dts_non_arq_data_segmented_cpdu_size = -1;
195 /* { 8, "EXP_NON_ARQ_DATA"}, */
196 static gint hf_s5066dts_exp_non_arq_data_cpdu_id_1 = -1;
197 static gint hf_s5066dts_exp_non_arq_data_deliver_in_order = -1;
198 static gint hf_s5066dts_exp_non_arq_data_group_address = -1;
199 static gint hf_s5066dts_exp_non_arq_data_cpdu_id_2 = -1;
200 static gint hf_s5066dts_exp_non_arq_data_cpdu_size = -1;
201 static gint hf_s5066dts_exp_non_arq_data_cpdu_segment_offset = -1;
202 static gint hf_s5066dts_exp_non_arq_data_cpdu_reception_window = -1;
203 static gint hf_s5066dts_exp_non_arq_data_segmented_cpdu_size = -1;
204 /* {15, "WARNING"}, */
205 static gint hf_s5066dts_warning_frame_type = -1;
206 static gint hf_s5066dts_warning_reason = -1;
207
208 static gint ett_s5066dts = -1;
209 static gint ett_s5066dts_eow = -1;
210 static gint ett_s5066dts_address = -1;
211 static gint ett_s5066dts_pdu = -1;
212 static gint ett_s5066dts_hftrp_token = -1;
213
214 static const value_string s5066dts_dpdu_type[] = {
215     { 0, "DATA_ONLY"},
216     { 1, "ACK_ONLY"},
217     { 2, "DATA_ACK"},
218     { 3, "RESET_WIN_RESYNC"},
219     { 4, "EXP_DATA_ONLY"},
220     { 5, "EXP_ACK_ONLY"},
221     { 6, "MANAGEMENT"},
222     { 7, "NON_ARQ_DATA"},
223     { 8, "EXP_NON_ARQ_DATA"},
224     {15, "WARNING"},
225     { 0, NULL},
226 };
227
228 static const value_string s5066dts_eow_type[] = {
229     {  0, "RESERVED"},
230     {  1, "DRC_REQUEST"},
231     {  2, "DRC_RESPONSE"},
232     {  3, "UNRECOGNIZED_TYPE"},
233     {  4, "CAPABILITY"},
234     {  5, "ALM_REQUEST"},
235     {  6, "ALM_RESPONSE"},
236     {  7, "HDR_DRC_REQUEST"},
237     { 15, "HFTRP_TOKEN"},
238     {  0, NULL},
239 };
240
241 static const value_string s5066dts_eow_data_rate[] = {
242     { 0, "75 bps"},
243     { 1, "150 bps"},
244     { 2, "300 bps"},
245     { 3, "600 bps"},
246     { 4, "1200 bps"},
247     { 5, "2400 bps"},
248     { 6, "3200 bps"},
249     { 7, "3600 bps"},
250     { 8, "4800 bps"},
251     { 9, "6400 bps"},
252     { 10, "8000 bps"},
253     { 11, "9600 bps"},
254     {  0, NULL},
255 };
256
257 static const value_string s5066dts_eow_interleaving[] = {
258     { 0, "No interleaving"},
259     { 1, "Short interleaving"},
260     { 2, "Long interleaving"},
261     { 3, "Reserved"},
262     { 0, NULL},
263 };
264
265 static const value_string s5066dts_eow_others[] = {
266     { 0, "Request: Master has independent data rate"},
267     { 1, "Request: Tx=Rx at master"},
268     { 2, "Advisory: Advising node has independent data rate"},
269     { 3, "Advisory: Tx=Rx at advising node"},
270     { 0, NULL},
271 };
272
273 static const value_string s5066dts_eow_response[] = {
274     { 0, "Accept"},
275     { 1, "Refuse"},
276     { 2, "Cancel"},
277     { 3, "Confirm"},
278     { 0, NULL},
279 };
280
281 static const value_string s5066dts_eow_reason[] = {
282     { 0, "No reason"},
283     { 1, "Tx and Rx parameters must be the same"},
284     { 2, "Not possible to change modem data rate"},
285     { 3, "Not possible to change modem interleaving"},
286     { 4, "Not possible to change modem data rate or interleaving"},
287     { 5, "Not consistent with local conditions"},
288     { 0, NULL},
289 };
290
291 static const value_string s5066dts_eow_waveform[] = {
292     { 0, "MS110A"},
293     { 1, "MS110B"},
294     { 2, "STANAG_4285"},
295     { 3, "STANAG_4539"},
296     { 4, "STANAG_4529"},
297     { 5, "STANAG_4415"},
298     { 6, "STANAG_4481_FSK"},
299     { 7, "USER_CONFIGURATION_OPTION_1"},
300     { 8, "USER_CONFIGURATION_OPTION_2"},
301     { 9, "USER_CONFIGURATION_OPTION_3"},
302     { 0, NULL},
303 };
304
305 /* Used in Packet List pane */
306 static const value_string s5066dts_eow_hftrp_frame_control_abbr[] = {
307     { 1, "RTT"},
308     { 2, "ACK"},
309     { 3, "SLS"},
310     { 4, "SET"},
311     { 5, "REL"},
312     { 6, "DEL"},
313     { 0, NULL},
314 };
315
316 /* Used in Packet Details pane */
317 static const value_string s5066dts_eow_hftrp_frame_control[] = {
318     { 1, "RTT - Right-to-transmit Token"},
319     { 2, "ACK - Acknowledgment Token"},
320     { 3, "SLS - Solicit Successor Token"},
321     { 4, "SET - Set Successor Token"},
322     { 5, "REL - Relayed Token"},
323     { 6, "DEL - Delete Token"},
324     { 0, NULL},
325 };
326
327 static const value_string s5066dts_alm_reason[] = {
328     { 0, "No reason"},
329     { 1, "Tx and Rx parameters must be the same"},
330     { 2, "Not possible to change modem data rate"},
331     { 3, "Not possible to change modem interleaving"},
332     { 4, "Not possible to change modem data rate or interleaving"},
333     { 5, "Not consistent with local conditions"},
334     { 6, "Not possible to change frequency"},
335     { 0, NULL},
336 };
337
338 /* Register functions' forward references */
339 void proto_reg_handoff_s5066dts(void);
340
341 /* { 1, "DRC_REQUEST"}, */
342 static void dissect_s5066dts_eow_drc_request(tvbuff_t *tvb, guint offset, proto_tree *tree)
343 {
344     proto_tree_add_item(tree, hf_s5066dts_eow_drc_request_data_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
345     proto_tree_add_item(tree, hf_s5066dts_eow_drc_request_interleaving, tvb, offset, 1, ENC_BIG_ENDIAN);
346     proto_tree_add_item(tree, hf_s5066dts_eow_drc_request_others, tvb, offset, 1, ENC_BIG_ENDIAN);
347 }
348
349 /* { 2, "DRC_RESPONSE"}, */
350 static void dissect_s5066dts_eow_drc_response(tvbuff_t *tvb, guint offset, proto_tree *tree)
351 {
352     proto_tree_add_item(tree, hf_s5066dts_eow_drc_response_response, tvb, offset, 1, ENC_BIG_ENDIAN);
353     proto_tree_add_item(tree, hf_s5066dts_eow_drc_response_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
354 }
355
356 /* { 3, "UNRECOGNIZED_TYPE"}, */
357 static void dissect_s5066dts_eow_unrec_type(tvbuff_t *tvb, guint offset, proto_tree *tree)
358 {
359     proto_tree_add_item(tree, hf_s5066dts_eow_unrec_type_response, tvb, offset, 1, ENC_BIG_ENDIAN);
360     proto_tree_add_item(tree, hf_s5066dts_eow_unrec_type_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
361 }
362
363 /* { 4, "CAPABILITY"}, */
364 static void dissect_s5066dts_eow_capability(tvbuff_t *tvb, guint offset, proto_tree *tree)
365 {
366     proto_tree_add_item(tree, hf_s5066dts_eow_capability_adaptive, tvb, offset, 1, ENC_BIG_ENDIAN);
367     proto_tree_add_item(tree, hf_s5066dts_eow_capability_stanag_4529, tvb, offset, 1, ENC_BIG_ENDIAN);
368     proto_tree_add_item(tree, hf_s5066dts_eow_capability_mil_std_188_110a, tvb, offset, 1, ENC_BIG_ENDIAN);
369     proto_tree_add_item(tree, hf_s5066dts_eow_capability_extended, tvb, offset, 1, ENC_BIG_ENDIAN);
370     proto_tree_add_item(tree, hf_s5066dts_eow_capability_full_duplex, tvb, offset, 1, ENC_BIG_ENDIAN);
371     proto_tree_add_item(tree, hf_s5066dts_eow_capability_split_frequency, tvb, offset, 1, ENC_BIG_ENDIAN);
372     proto_tree_add_item(tree, hf_s5066dts_eow_capability_non_arcs_ale, tvb, offset, 1, ENC_BIG_ENDIAN);
373     proto_tree_add_item(tree, hf_s5066dts_eow_capability_arcs, tvb, offset, 1, ENC_BIG_ENDIAN);
374 }
375
376 /* { 5, "ALM_REQUEST"}, */
377 static void dissect_s5066dts_eow_alm_request(tvbuff_t *tvb, guint offset, proto_tree *tree)
378 {
379     proto_tree_add_item(tree, hf_s5066dts_eow_alm_request_data_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
380     proto_tree_add_item(tree, hf_s5066dts_eow_alm_request_interleaving, tvb, offset, 1, ENC_BIG_ENDIAN);
381     proto_tree_add_item(tree, hf_s5066dts_eow_alm_request_others, tvb, offset, 1, ENC_BIG_ENDIAN);
382 }
383
384 /* { 6, "ALM_RESPONSE"}, */
385 static void dissect_s5066dts_eow_alm_response(tvbuff_t *tvb, guint offset, proto_tree *tree)
386 {
387     proto_tree_add_item(tree, hf_s5066dts_eow_alm_response_response, tvb, offset, 1, ENC_BIG_ENDIAN);
388     proto_tree_add_item(tree, hf_s5066dts_eow_alm_response_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
389 }
390
391 /* { 7, "HDR_DRC_REQUEST"}, */
392 static void dissect_s5066dts_eow_hdr_drc_request(tvbuff_t *tvb, packet_info * pinfo, guint offset,
393         proto_tree *tree, guint pdu_type)
394 {
395
396     if (pdu_type != S5066_DPDU_MANAGEMENT)
397     {
398         expert_add_info(pinfo, tree, &ei_s5066dts_eow_hdr_drc_request_invalid);
399         return;
400     }
401
402     proto_tree_add_item(tree, hf_s5066dts_eow_hdr_drc_request_waveform, tvb, offset, 1, ENC_BIG_ENDIAN);
403     proto_tree_add_item(tree, hf_s5066dts_eow_hdr_drc_request_num_channels, tvb, offset, 1, ENC_BIG_ENDIAN);
404
405 }
406
407 /* {15, "HFTRP FRAME CONTROL"}, */
408 static void dissect_s5066dts_eow_hftrp(tvbuff_t *tvb,  packet_info * pinfo, guint offset,
409         proto_tree *tree, guint pdu_type)
410 {
411     if (pdu_type != S5066_DPDU_MANAGEMENT)
412     {
413         expert_add_info(pinfo, tree, &ei_s5066dts_eow_hftrp_invalid);
414         return;
415     }
416
417     proto_tree_add_item(tree, hf_s5066dts_eow_hftrp_hftrp_token, tvb, offset, 1, ENC_BIG_ENDIAN);
418 }
419
420 /*
421  * Dissect EOW type according to C.5 EOW and Management Message Types
422  */
423 static guint dissect_s5066dts_eow(tvbuff_t *tvb,  packet_info * pinfo, guint offset, proto_tree *tree,
424         guint pdu_type)
425 {
426     proto_item *ti = NULL;
427     proto_tree *eow_tree = NULL;
428     guint eow_type;
429
430     eow_type = tvb_get_guint8(tvb, offset) & 0x0F;
431     ti = proto_tree_add_text(tree, tvb, offset, 2, "EOW Field");
432     eow_tree = proto_item_add_subtree(ti, ett_s5066dts_eow);
433     proto_tree_add_item(eow_tree, hf_s5066dts_eow_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
434
435     switch (eow_type)
436     {
437         case  S5066_EOW_RESERVED:
438             proto_tree_add_item(eow_tree, hf_s5066dts_eow_data, tvb, offset, 1, ENC_BIG_ENDIAN); break;
439         case  S5066_EOW_DRC_REQUEST:
440             dissect_s5066dts_eow_drc_request(tvb, offset, eow_tree); break;
441         case  S5066_EOW_DRC_RESPONSE:
442             dissect_s5066dts_eow_drc_response(tvb, offset, eow_tree); break;
443         case  S5066_EOW_UNRECOGNIZED_TYPE:
444             dissect_s5066dts_eow_unrec_type(tvb, offset, eow_tree); break;
445         case  S5066_EOW_CAPABILITY:
446             dissect_s5066dts_eow_capability(tvb, offset, eow_tree); break;
447         case  S5066_EOW_ALM_REQUEST:
448             dissect_s5066dts_eow_alm_request(tvb, offset, eow_tree); break;
449         case  S5066_EOW_ALM_RESPONSE:
450             dissect_s5066dts_eow_alm_response(tvb, offset, eow_tree); break;
451         case  S5066_EOW_HDR_DRC_REQUEST:
452             dissect_s5066dts_eow_hdr_drc_request(tvb, pinfo, offset, eow_tree, pdu_type); break;
453         case  S5066_EOW_HFTRP_TOKEN:
454             dissect_s5066dts_eow_hftrp(tvb, pinfo, offset, eow_tree, pdu_type); break;
455     }
456     return ++offset;
457 }
458
459 static guint dissect_s5066dts_address(tvbuff_t *tvb, guint offset, proto_tree *tree, packet_info *pinfo,
460         guint addr_size)
461 {
462     guint32 source_address = 0, destination_address = 0;
463     proto_item *ti;
464     proto_tree *address_tree = NULL;
465     unsigned int i;
466
467     for ( i = 0; i < addr_size; i++)
468     {
469         destination_address = (destination_address << 4) | ((!(i % 2)
470                 ? (tvb_get_guint8(tvb, offset + i / 2) >> 4)
471                 : (tvb_get_guint8(tvb, offset + i / 2))) & 0x0F);
472         source_address = (source_address << 4) | ((!((i + addr_size) % 2)
473                 ? (tvb_get_guint8(tvb, offset + (i + addr_size) / 2) >> 4)
474                 : (tvb_get_guint8(tvb, offset + (i + addr_size) / 2))) & 0x0F);
475     }
476
477     ti = proto_tree_add_text(tree, tvb, offset, addr_size, "Destination & Source Addresses");
478     address_tree = proto_item_add_subtree(ti, ett_s5066dts_address);
479
480     proto_tree_add_text(address_tree,
481             tvb,
482             offset,
483             addr_size - addr_size / 2,
484             "Destination Address: %d.%d.%d.%d",
485             destination_address >> 24, (destination_address >> 16) & 0xFF,
486             (destination_address >> 8) & 0xFF, destination_address & 0xFF);
487     proto_tree_add_text(address_tree,
488             tvb,
489             offset + addr_size / 2,
490             addr_size - addr_size / 2,
491             "Source Address: %d.%d.%d.%d",
492             source_address  >> 24,
493             (source_address >> 16) & 0xFF,
494             (source_address >> 8) & 0xFF,
495             source_address & 0xFF);
496
497     col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%d.%d.%d.%d",
498             source_address  >> 24,
499             (source_address >> 16) & 0xFF,
500             (source_address >> 8) & 0xFF,
501             source_address & 0xFF);
502
503     col_add_fstr(pinfo->cinfo, COL_DEF_DST, "%d.%d.%d.%d",
504             destination_address  >> 24,
505             (destination_address >> 16) & 0xFF,
506             (destination_address >> 8) & 0xFF,
507             destination_address & 0xFF);
508
509     offset += addr_size;
510     return offset;
511 }
512
513 static guint dissect_s5066dts_header_crc(tvbuff_t *tvb, guint offset, proto_tree *tree,
514         guint address_size, guint header_size)
515 {
516     guint16 header_crc;
517     proto_item *ti;
518
519     header_crc = crc16_0x9949_tvb_offset_seed(tvb, S5066_DPDU_SYNC_SEQUENCE_SIZE,
520                 header_size + address_size - S5066_DPDU_SYNC_SEQUENCE_SIZE, 0);
521
522     ti = proto_tree_add_item(tree, hf_s5066dts_header_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
523     if (header_crc == tvb_get_letohs(tvb, offset))
524         proto_item_append_text(ti, " (Correct)");
525     else
526         proto_item_append_text(ti, " (Incorrect, should be %x)", header_crc);
527
528     offset += 2;
529     return offset;
530 }
531
532 static guint dissect_s5066dts_cpdu_crc(tvbuff_t *tvb, guint offset, proto_tree *tree,
533         guint address_size, guint header_size, guint segmented_cpdu_size)
534 {
535     guint32 cpdu_crc;
536     proto_item *ti;
537
538     cpdu_crc = crc32_0x0AA725CF_tvb_offset_seed(tvb, header_size + address_size + S5066_DPDU_SYNC_SEQUENCE_SIZE,
539               segmented_cpdu_size, 0);
540
541     ti = proto_tree_add_item(tree, hf_s5066dts_cpdu_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
542     if (cpdu_crc == tvb_get_letohl(tvb, offset))
543         proto_item_append_text(ti, " (Correct)");
544     else
545         proto_item_append_text(ti, " (Incorrect, should be %x)", cpdu_crc);
546
547     offset +=4;
548     return offset;
549 }
550
551 /* { 0, "DATA_ONLY"}, */
552 static guint dissect_s5066dts_data_only(tvbuff_t *tvb, guint offset, proto_tree *tree)
553 {
554     proto_tree_add_item(tree, hf_s5066dts_data_only_cpdu_start, tvb, offset, 1, ENC_BIG_ENDIAN);
555     proto_tree_add_item(tree, hf_s5066dts_data_only_cpdu_end, tvb, offset, 1, ENC_BIG_ENDIAN);
556     proto_tree_add_item(tree, hf_s5066dts_data_only_deliver_in_order, tvb, offset, 1, ENC_BIG_ENDIAN);
557     proto_tree_add_item(tree, hf_s5066dts_data_only_drop_cpdu, tvb, offset, 1, ENC_BIG_ENDIAN);
558     proto_tree_add_item(tree, hf_s5066dts_data_only_tx_win_uwe, tvb, offset, 1, ENC_BIG_ENDIAN);
559     proto_tree_add_item(tree, hf_s5066dts_data_only_tx_win_lwe, tvb, offset, 1, ENC_BIG_ENDIAN);
560     proto_tree_add_item(tree, hf_s5066dts_data_only_segmented_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
561     proto_tree_add_item(tree, hf_s5066dts_data_only_transmit_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
562
563     return offset;
564 }
565
566 /* { 1, "ACK_ONLY"}, */
567 static guint dissect_s5066dts_ack_only(tvbuff_t *tvb, guint offset, proto_tree *tree,
568         guint header_size)
569 {
570     guint ack_size;
571     ack_size = header_size - 7;
572
573     proto_tree_add_item(tree, hf_s5066dts_ack_only_rx_lwe, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
574     if (ack_size > 0)
575         proto_tree_add_item(tree, hf_s5066dts_ack_only_acks, tvb, offset, ack_size, ENC_NA); offset += ack_size;
576
577     return offset;
578 }
579
580 /* { 2, "DATA_ACK"}, */
581 static guint dissect_s5066dts_data_ack(tvbuff_t *tvb, guint offset, proto_tree *tree,
582         guint header_size)
583 {
584     guint ack_size;
585     ack_size = header_size - 10;
586
587     proto_tree_add_item(tree, hf_s5066dts_data_ack_cpdu_start, tvb, offset, 1, ENC_BIG_ENDIAN);
588     proto_tree_add_item(tree, hf_s5066dts_data_ack_cpdu_end, tvb, offset, 1, ENC_BIG_ENDIAN);
589     proto_tree_add_item(tree, hf_s5066dts_data_ack_deliver_in_order, tvb, offset, 1, ENC_BIG_ENDIAN);
590     proto_tree_add_item(tree, hf_s5066dts_data_ack_drop_cpdu, tvb, offset, 1, ENC_BIG_ENDIAN);
591     proto_tree_add_item(tree, hf_s5066dts_data_ack_tx_win_uwe, tvb, offset, 1, ENC_BIG_ENDIAN);
592     proto_tree_add_item(tree, hf_s5066dts_data_ack_tx_win_lwe, tvb, offset, 1, ENC_BIG_ENDIAN);
593     proto_tree_add_item(tree, hf_s5066dts_data_ack_segmented_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
594     proto_tree_add_item(tree, hf_s5066dts_data_ack_transmit_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
595     proto_tree_add_item(tree, hf_s5066dts_data_ack_rx_lwe, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
596     if (ack_size > 0)
597         proto_tree_add_item(tree, hf_s5066dts_data_ack_acks, tvb, offset, ack_size, ENC_NA); offset += ack_size;
598
599     return offset;
600 }
601
602 /* { 3, "RESET_WIN_RESYNC"}, */
603 static guint dissect_s5066dts_reset_win_resync(tvbuff_t *tvb, guint offset, proto_tree *tree)
604 {
605     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
606     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_full_reset_command, tvb, offset, 1, ENC_BIG_ENDIAN);
607     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_reset_tx_win_rqst, tvb, offset, 1, ENC_BIG_ENDIAN);
608     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_reset_rx_win_cmnd, tvb, offset, 1, ENC_BIG_ENDIAN);
609     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_reset_ack, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
610     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_new_rx_lwe, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
611     proto_tree_add_item(tree, hf_s5066dts_reset_win_resync_reset_frame_id_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
612
613     return offset;
614 }
615
616 /* { 4, "EXP_DATA_ONLY"}, */
617 static guint dissect_s5066dts_exp_data_only(tvbuff_t *tvb, guint offset, proto_tree *tree)
618 {
619     proto_tree_add_item(tree, hf_s5066dts_exp_data_only_cpdu_start, tvb, offset, 1, ENC_BIG_ENDIAN);
620     proto_tree_add_item(tree, hf_s5066dts_exp_data_only_cpdu_end, tvb, offset, 1, ENC_BIG_ENDIAN);
621     proto_tree_add_item(tree, hf_s5066dts_exp_data_only_cpdu_id, tvb, offset, 1, ENC_BIG_ENDIAN);
622     proto_tree_add_item(tree, hf_s5066dts_exp_data_only_segmented_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
623     proto_tree_add_item(tree, hf_s5066dts_exp_data_only_transmit_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
624
625     return offset;
626 }
627
628 /* { 5, "EXP_ACK_ONLY"}, */
629 static guint dissect_s5066dts_exp_ack_only(tvbuff_t *tvb, guint offset, proto_tree *tree,
630         guint header_size)
631 {
632     guint ack_size;
633     ack_size = header_size - 7;
634
635     proto_tree_add_item(tree, hf_s5066dts_exp_ack_only_rx_lwe, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
636     if (ack_size > 0)
637         proto_tree_add_item(tree, hf_s5066dts_exp_ack_only_acks, tvb, offset, ack_size, ENC_NA);
638     offset += ack_size;
639
640     return offset;
641 }
642
643 /* { 6, "MANAGEMENT"}, */
644 static guint dissect_s5066dts_management(tvbuff_t *tvb, guint offset, proto_tree *tree, guint header_size)
645 {
646     guint8 eow_content;
647     proto_item *hftrp_proto_item = NULL;
648     proto_tree *hftrp_token_tree = NULL;
649     guint eow_type;
650     guint extended_message_size;
651
652     eow_type = tvb_get_guint8(tvb, offset) & 0x0F;
653     eow_content = tvb_get_guint8(tvb, S5066_DPDU_EOW_CONTENT_INDEX);
654     extended_message_size = header_size - 8;
655
656     proto_tree_add_item(tree, hf_s5066dts_management_unused, tvb, offset, 1, ENC_BIG_ENDIAN);
657     proto_tree_add_item(tree, hf_s5066dts_management_extended_message_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
658     proto_tree_add_item(tree, hf_s5066dts_management_message, tvb, offset, 1, ENC_BIG_ENDIAN);
659     proto_tree_add_item(tree, hf_s5066dts_management_ack, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
660     proto_tree_add_item(tree, hf_s5066dts_management_management_frame_id, tvb, offset, 1, ENC_BIG_ENDIAN);
661     offset++;
662
663     if (eow_type == S5066_EOW_HDR_DRC_REQUEST)
664     {
665         proto_tree_add_item(tree, hf_s5066dts_eow_hdr_drc_request_data_rate, tvb, offset, 4, ENC_BIG_ENDIAN);
666         offset += 4;
667
668         proto_tree_add_item(tree, hf_s5066dts_eow_hdr_drc_request_interleaver_length, tvb, offset, 2, ENC_BIG_ENDIAN);
669         offset += 2;
670     }
671     else if (extended_message_size > 0)
672     {
673         /* If eow type is 15 then parse HFTRP token details */
674         if (eow_type == S5066_EOW_HFTRP_TOKEN)
675         {
676             /* Add a new subtree for HFTRP token details */
677             hftrp_proto_item = proto_tree_add_text(tree, tvb, offset, extended_message_size, "HFTRP Token (%s)",
678                     val_to_str_const(eow_content, s5066dts_eow_hftrp_frame_control, "UNKNOWN_HFTRP_TOKEN"));
679             hftrp_token_tree = proto_item_add_subtree(hftrp_proto_item, ett_s5066dts_hftrp_token);
680             proto_tree_add_item(hftrp_token_tree,
681                     hf_s5066dts_management_extended_message_hftrp_payload_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
682             proto_tree_add_item(hftrp_token_tree,
683                     hf_s5066dts_management_extended_message_hftrp_ra, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;
684             proto_tree_add_item(hftrp_token_tree,
685                     hf_s5066dts_management_extended_message_hftrp_seq_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;
686             proto_tree_add_item(hftrp_token_tree,
687                     hf_s5066dts_management_extended_message_hftrp_gen_seq_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;
688             proto_tree_add_item(hftrp_token_tree,
689                     hf_s5066dts_management_extended_message_hftrp_new_successor_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;
690             proto_tree_add_item(hftrp_token_tree,
691                     hf_s5066dts_management_extended_message_hftrp_number_of_nodes, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
692         }
693         /* otherwise just display it as a byte stream */
694         else
695         {
696             proto_tree_add_item(tree, hf_s5066dts_management_extended_message, tvb, offset, extended_message_size, ENC_NA);
697             offset += extended_message_size;
698         }
699     }
700
701     return offset;
702 }
703
704 /* { 7, "NON_ARQ_DATA"}, */
705 static guint dissect_s5066dts_non_arq_data(tvbuff_t *tvb, guint offset, proto_tree *tree)
706 {
707     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_cpdu_id_1, tvb, offset, 1, ENC_BIG_ENDIAN);
708     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_deliver_in_order, tvb, offset, 1, ENC_BIG_ENDIAN);
709     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_group_address, tvb, offset, 1, ENC_BIG_ENDIAN);
710     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_segmented_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
711     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_cpdu_id_2, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
712     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
713     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_cpdu_segment_offset, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
714     proto_tree_add_item(tree, hf_s5066dts_non_arq_data_cpdu_reception_window, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
715
716     return offset;
717 }
718
719 /* { 8, "EXP_NON_ARQ_DATA"}, */
720 static guint dissect_s5066dts_exp_non_arq_data(tvbuff_t *tvb, guint offset, proto_tree *tree)
721 {
722     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_cpdu_id_1, tvb, offset, 1, ENC_BIG_ENDIAN);
723     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_deliver_in_order, tvb, offset, 1, ENC_BIG_ENDIAN);
724     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_group_address, tvb, offset, 1, ENC_BIG_ENDIAN);
725     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_segmented_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
726     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_cpdu_id_2, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
727     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_cpdu_size, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
728     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_cpdu_segment_offset, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
729     proto_tree_add_item(tree, hf_s5066dts_exp_non_arq_data_cpdu_reception_window, tvb, offset, 2, ENC_BIG_ENDIAN); offset +=2;
730
731     return offset;
732 }
733
734 /* {15, "WARNING"}, */
735 static guint dissect_s5066dts_warning(tvbuff_t *tvb, guint offset, proto_tree *tree)
736 {
737     proto_tree_add_item(tree, hf_s5066dts_warning_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN);
738     proto_tree_add_item(tree, hf_s5066dts_warning_reason, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
739
740     return offset;
741 }
742
743 static guint calculate_s5066dts_dpdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_)
744 {
745     guint pdu_type;
746     guint address_size;
747     guint header_size;
748     guint pdu_size;
749     guint segmented_cpdu_size;
750
751     if (tvb_get_guint8(tvb, 0) != 0x90)
752         return 1;
753     else if (tvb_get_guint8(tvb, 1) != 0xEB)
754         return 2;
755
756     pdu_type = (tvb_get_guint8(tvb, 2) & 0xF0) >> 4;
757     address_size = (tvb_get_guint8(tvb, S5066_DPDU_SIZE_OF_ADDRESS_INDEX) & 0xE0) >> 5;
758     header_size = tvb_get_guint8(tvb, S5066_DPDU_SIZE_OF_HEADER_INDEX) & 0x1F;
759     pdu_size = header_size + address_size + S5066_DPDU_SYNC_SEQUENCE_SIZE;
760
761     if (pdu_type == S5066_DPDU_DATA_ONLY || pdu_type == S5066_DPDU_DATA_ACK ||
762             pdu_type == S5066_DPDU_EXP_DATA_ONLY || pdu_type == S5066_DPDU_NON_ARQ_DATA ||
763             pdu_type == S5066_DPDU_EXP_NON_ARQ_DATA)
764     {
765         segmented_cpdu_size = tvb_get_ntohs(tvb, 6 + address_size) & 0x03FF;
766         pdu_size += segmented_cpdu_size + 4;
767     }
768     return pdu_size;
769 }
770
771 static int dissect_s5066dts(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
772 {
773     proto_tree *s5066dts_tree = NULL, *pdu_tree = NULL;
774     proto_item *ti = NULL;
775     guint offset = 0;
776     guint pdu_type;
777     guint address_size;
778     guint header_size;
779     guint segmented_cpdu_size;
780     /* Add EOW (Engineering OrderWire */
781     guint8 eow_type;
782     guint8 eow_content;
783
784     if (tvb_get_guint8(tvb, 0) != 0x90 || tvb_get_guint8(tvb, 1) != 0xEB) {
785         /* Cannot find sync pattern at dissect_s5066dts()! */
786         return 0;
787     }
788
789     col_set_str(pinfo->cinfo, COL_PROTOCOL, DISSECTOR_NAME);
790     pdu_type = (tvb_get_guint8(tvb, 2) & 0xF0) >> 4;
791
792     /* Add DPDU type and name */
793     col_add_fstr(pinfo->cinfo, COL_INFO, "DpduType=%d (%s)", pdu_type, val_to_str(pdu_type, s5066dts_dpdu_type,
794             "Unknown (0x%02x)"));
795
796     address_size = (tvb_get_guint8(tvb, S5066_DPDU_SIZE_OF_ADDRESS_INDEX) & 0xE0) >> 5;
797     eow_type = tvb_get_guint8(tvb, S5066_DPDU_EOW_TYPE_INDEX) & 0x0F;
798     eow_content = tvb_get_guint8(tvb, S5066_DPDU_EOW_CONTENT_INDEX);
799
800     switch (eow_type)
801     {
802         case S5066_EOW_RESERVED:
803             col_append_fstr(pinfo->cinfo, COL_INFO, " EowType=RESERVED");
804             break;
805         case S5066_EOW_DRC_REQUEST: /* Data Rate Change Request */
806         case S5066_EOW_DRC_RESPONSE: /* Data Rate Change Response */
807         case S5066_EOW_UNRECOGNIZED_TYPE: /* Unrecognized Type Error */
808         case S5066_EOW_CAPABILITY: /* Capability Advertisement */
809         case S5066_EOW_ALM_REQUEST: /* Frequency Change / ALM Request */
810         case S5066_EOW_ALM_RESPONSE: /* Frequency Change / ALM Response */
811         case S5066_EOW_HDR_DRC_REQUEST: /* High Data Rate (HDR) Change Request */
812             col_append_fstr(pinfo->cinfo, COL_INFO, " EowType=%d (%s)", eow_type,
813                     val_to_str_const(eow_type, s5066dts_eow_type, "UNKNOWN_EOW_TYPE"));
814             break;
815         case 8: /* Unspecified/User Defined */
816         case 9: /* Unspecified/User Defined */
817         case 10: /* Unspecified/User Defined */
818         case 11: /* Unspecified/User Defined */
819         case 12: /* Unspecified/User Defined */
820         case 13: /* Unspecified/User Defined */
821         case 14: /* Unspecified/User Defined */
822             col_append_fstr(pinfo->cinfo, COL_INFO, " EowType=UNSPECIFIED");
823             break;
824         case S5066_EOW_HFTRP_TOKEN:
825             col_append_fstr(pinfo->cinfo, COL_INFO, " EowType=%d (%s:%s)", eow_type,
826                     val_to_str_const(eow_type, s5066dts_eow_type, "UNKNOWN_EOW_TYPE"),
827                     val_to_str_const(eow_content, s5066dts_eow_hftrp_frame_control_abbr, "UNKNOWN_HFTRP_TOKEN"));
828             break;
829     }
830
831     /* Append EOT (End of Transmission) */
832     col_append_fstr(pinfo->cinfo, COL_INFO, " EOT=%d", tvb_get_guint8(tvb, S5066_DPDU_EOT_INDEX));
833
834     /* Append DPDU-specific information */
835     switch (pdu_type)
836     {
837         case S5066_DPDU_DATA_ONLY:
838         case S5066_DPDU_EXP_DATA_ONLY:
839             col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%d", tvb_get_guint8(tvb, 8 + address_size));
840             break;
841         case S5066_DPDU_ACK_ONLY:
842         case S5066_DPDU_EXP_ACK_ONLY:
843             col_append_fstr(pinfo->cinfo, COL_INFO, " RxLWE=%d", tvb_get_guint8(tvb, 6 + address_size));
844             break;
845         case S5066_DPDU_DATA_ACK:
846             col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%d RxLWE=%d",
847                     tvb_get_guint8(tvb, 8 + address_size),
848                     tvb_get_guint8(tvb, 9 + address_size));
849             break;
850         case S5066_DPDU_MANAGEMENT:
851             col_append_fstr(pinfo->cinfo, COL_INFO, " FrameID=%d", tvb_get_guint8(tvb, 7 + address_size));
852             break;
853     }
854
855     if (tree)
856     {
857         ti = proto_tree_add_protocol_format(tree, proto_s5066dts, tvb, 0, -1, "STANAG 5066 (DTS Layer)");
858         s5066dts_tree = proto_item_add_subtree(ti, ett_s5066dts);
859         proto_tree_add_item(s5066dts_tree, hf_s5066dts_sync_word, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;
860         proto_tree_add_item(s5066dts_tree, hf_s5066dts_dpdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
861         offset = dissect_s5066dts_eow(tvb, pinfo, offset, s5066dts_tree, pdu_type);
862
863         /*
864          * Append DPDU type to the root
865          */
866         proto_item_append_text(ti, ", DPDU Type %s ", val_to_str_const(pdu_type, s5066dts_dpdu_type, "UNKNOWN_DPDU_TYPE"));
867         proto_tree_add_item(s5066dts_tree, hf_s5066dts_eot, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
868         proto_tree_add_item(s5066dts_tree, hf_s5066dts_address_size, tvb, offset, 1, ENC_BIG_ENDIAN);
869         proto_tree_add_item(s5066dts_tree, hf_s5066dts_header_size, tvb, offset, 1, ENC_BIG_ENDIAN); offset++;
870         offset = dissect_s5066dts_address(tvb, offset, s5066dts_tree, pinfo, address_size);
871         header_size = tvb_get_guint8(tvb, S5066_DPDU_SIZE_OF_HEADER_INDEX) & 0x1F;
872         ti = proto_tree_add_text(s5066dts_tree, tvb, offset, header_size - 6, "D_PDU Type Specific Header");
873         pdu_tree = proto_item_add_subtree(ti, ett_s5066dts_pdu);
874
875         switch (pdu_type)
876         {
877             case  S5066_DPDU_DATA_ONLY: offset = dissect_s5066dts_data_only(tvb, offset, pdu_tree); break;
878             case  S5066_DPDU_ACK_ONLY: offset = dissect_s5066dts_ack_only(tvb, offset, pdu_tree, header_size); break;
879             case  S5066_DPDU_DATA_ACK: offset = dissect_s5066dts_data_ack(tvb, offset, pdu_tree, header_size); break;
880             case  S5066_DPDU_RESET_WIN_RESYNC: offset = dissect_s5066dts_reset_win_resync(tvb, offset, pdu_tree); break;
881             case  S5066_DPDU_EXP_DATA_ONLY: offset = dissect_s5066dts_exp_data_only(tvb, offset, pdu_tree); break;
882             case  S5066_DPDU_EXP_ACK_ONLY: offset = dissect_s5066dts_exp_ack_only(tvb, offset, pdu_tree, header_size); break;
883             case  S5066_DPDU_MANAGEMENT: offset = dissect_s5066dts_management(tvb, offset, pdu_tree, header_size); break;
884             case  S5066_DPDU_NON_ARQ_DATA: offset = dissect_s5066dts_non_arq_data(tvb, offset, pdu_tree); break;
885             case  S5066_DPDU_EXP_NON_ARQ_DATA: offset = dissect_s5066dts_exp_non_arq_data(tvb, offset, pdu_tree); break;
886             case  S5066_DPDU_WARNING: offset = dissect_s5066dts_warning(tvb, offset, pdu_tree); break;
887         }
888         offset = dissect_s5066dts_header_crc(tvb, offset, s5066dts_tree, address_size, header_size);
889         if (pdu_type == S5066_DPDU_DATA_ONLY || pdu_type == S5066_DPDU_DATA_ACK
890                 || pdu_type == S5066_DPDU_EXP_DATA_ONLY || pdu_type == S5066_DPDU_NON_ARQ_DATA
891                 || pdu_type == S5066_DPDU_EXP_NON_ARQ_DATA)
892         {
893             segmented_cpdu_size = tvb_get_ntohs(tvb, 6 + address_size) & 0x03FF;
894             proto_tree_add_item(s5066dts_tree, hf_s5066dts_segmented_cpdu, tvb, offset, segmented_cpdu_size, ENC_NA);
895             offset += segmented_cpdu_size;
896             /*offset = */dissect_s5066dts_cpdu_crc(tvb, offset, s5066dts_tree, address_size, header_size, segmented_cpdu_size);
897         }
898     }
899
900     return tvb_length(tvb);
901 }
902
903 static int dissect_s5066dts_raw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
904 {
905     guint b_length =  tvb_length(tvb);
906
907     /* Make sure there are enough bytes for a DPDU */
908     if ( b_length < S5066_DPDU_FRAME_HEADER_LEN){
909         /* "There are not enough bytes for a DPDU! */
910         return 0;
911     }
912
913     /* Check if the first two bytes are 0x90 and 0xEB
914      * If not then this is neither a DPDU nor an un-reassembled one
915      */
916     if ((tvb_get_guint8(tvb, 0) != 0x90) || (tvb_get_guint8(tvb, 1) != 0xEB)) {
917         /* Cannot find sync pattern at dissect_s5066dts_raw()! */
918         return 0;
919     }
920     calculate_s5066dts_dpdu_len(pinfo, tvb, 0);
921     dissect_s5066dts(tvb, pinfo, tree, NULL);
922
923     return b_length;
924 }
925
926 static int dissect_s5066dts_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
927 {
928     guint b_length = tvb_length(tvb);
929
930     /* Make sure there are enough bytes for a DPDU */
931     if ( b_length < S5066_DPDU_FRAME_HEADER_LEN){
932         /* "There are not enough bytes for a DPDU! */
933         return 0;
934     }
935
936     /* Check if the first two bytes are 0x90 and 0xEB
937      * If not then this is neitger a DPDU nor an un-reassembled one
938      */
939     if ((tvb_get_guint8(tvb, 0) != 0x90) || (tvb_get_guint8(tvb, 1) != 0xEB)) {
940         /* Cannot find sync pattern at dissect_s5066dts_tcp()! */
941         return 0;
942     }
943
944     /* Drop packets with port matches other than the destination port. */
945     if ( pinfo->destport != config_s5066dts_port) {
946         /* Configured to dissect TCP destination port matches only, dropping.. */
947         return 0;
948     }
949
950     tcp_dissect_pdus(tvb, pinfo, tree, config_proto_desegment, S5066_DPDU_FRAME_HEADER_LEN, calculate_s5066dts_dpdu_len,
951                 dissect_s5066dts, data);
952
953     return b_length;
954 }
955
956 void proto_register_s5066dts (void)
957 {
958     module_t *s5066dts_module;
959     static hf_register_info hf[] = {
960             { &hf_s5066dts_sync_word,
961                 { "Sync preamble", "s5066dts.sync", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
962             },
963             { &hf_s5066dts_dpdu_type,
964                 { "D_PDU type", "s5066dts.type", FT_UINT8, BASE_DEC, VALS(s5066dts_dpdu_type), 0xF0, "", HFILL }
965             },
966             { &hf_s5066dts_eow_type,
967                 { "EOW type", "s5066dts.eow.type", FT_UINT8, BASE_DEC, VALS(s5066dts_eow_type), 0x0F, "", HFILL }
968             },
969             { &hf_s5066dts_eow_data,
970                 { "EOW data", "s5066dts.eow.data", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
971             },
972             { &hf_s5066dts_eot,
973                 { "EOT", "s5066dts.eot", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
974             },
975             { &hf_s5066dts_address_size,
976                 { "Address size (1/2 bytes)", "s5066dts.address.size", FT_UINT8, BASE_DEC, NULL, 0xE0, "", HFILL }
977             },
978             { &hf_s5066dts_header_size,
979                 { "Header size", "s5066dts.header_size", FT_UINT8, BASE_DEC, NULL, 0x1F, "", HFILL }
980             },
981             { &hf_s5066dts_segmented_cpdu,
982                 { "C_PDU Segment", "s5066dts.segmented_cpdu", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
983             },
984             { &hf_s5066dts_header_crc,
985                 { "CRC on header", "s5066dts.header_crc", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
986             },
987             { &hf_s5066dts_cpdu_crc,
988                 { "CRC on C_PDU segment", "s5066dts.cpdu_crc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }
989             },
990             /* { 1, "DRC_REQUEST"}, */
991             { &hf_s5066dts_eow_drc_request_data_rate,
992                 { "Data Rate", "s5066dts.eow.drc_request.data_rate", FT_UINT8, BASE_DEC, VALS(s5066dts_eow_data_rate),
993                         0xF0, "", HFILL }
994             },
995             { &hf_s5066dts_eow_drc_request_interleaving,
996                 { "Interleaver parameter", "s5066dts.eow.drc_request.interleaving", FT_UINT8, BASE_DEC,
997                         VALS(s5066dts_eow_interleaving), 0x0C, "", HFILL }
998             },
999             { &hf_s5066dts_eow_drc_request_others,
1000                 { "Other parameters", "s5066dts.eow.drc_request.others", FT_UINT8, BASE_DEC,
1001                         VALS(s5066dts_eow_others), 0x03, "", HFILL }
1002             },
1003             /* { 2, "DRC_RESPONSE"}, */
1004             { &hf_s5066dts_eow_drc_response_response,
1005                 { "Response for DRC", "s5066dts.eow.drc_response.response", FT_UINT8, BASE_DEC,
1006                         VALS(s5066dts_eow_response), 0xE0, "", HFILL }
1007             },
1008             { &hf_s5066dts_eow_drc_response_reason,
1009                 { "Reason", "s5066dts.eow.drc_response.reason", FT_UINT8, BASE_DEC,
1010                         VALS(s5066dts_eow_reason), 0x1F, "", HFILL }
1011             },
1012             /* { 3, "UNRECOGNIZED_TYPE"}, */
1013             { &hf_s5066dts_eow_unrec_type_response,
1014                 { "This value should be set to 0", "s5066dts.eow.unrec_type.response", FT_UINT8, BASE_DEC,
1015                         NULL, 0xE0, "", HFILL }
1016             },
1017             { &hf_s5066dts_eow_unrec_type_reason,
1018                 { "Reason", "s5066dts.eow.unrec_type.reason", FT_UINT8, BASE_DEC, NULL, 0x1F, "", HFILL }
1019             },
1020             /* { 4, "CAPABILITY"}, */
1021             { &hf_s5066dts_eow_capability_adaptive,
1022                 { "Adaptive modem parameters capable", "s5066dts.eow.capability.adaptive", FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }
1023             },
1024             { &hf_s5066dts_eow_capability_stanag_4529,
1025                 { "STANAG 4529 available", "s5066dts.eow.capability.stanag_4529", FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }
1026             },
1027             { &hf_s5066dts_eow_capability_mil_std_188_110a,
1028                 { "MIL-STD-188-110A available", "s5066dts.eow.capability.mil_std_188_110a", FT_BOOLEAN, 8, NULL, 0x20, "", HFILL }
1029             },
1030             { &hf_s5066dts_eow_capability_extended,
1031                 { "Extended data rate available", "s5066dts.eow.capability.extended", FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }
1032             },
1033             { &hf_s5066dts_eow_capability_full_duplex,
1034                 { "Full duplex supported", "s5066dts.eow.capability.full_duplex", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1035             },
1036             { &hf_s5066dts_eow_capability_split_frequency,
1037                 { "Split frequency supported", "s5066dts.eow.capability.split_frequency", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1038             },
1039             { &hf_s5066dts_eow_capability_non_arcs_ale,
1040                 { "Non-ARCS ALE capable", "s5066dts.eow.capability.non_arcs_ale", FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }
1041             },
1042             { &hf_s5066dts_eow_capability_arcs,
1043                 { "ARCS capable", "s5066dts.eow.capability.arcs", FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }
1044             },
1045             /* { 5, "ALM_REQUEST"}, */
1046             { &hf_s5066dts_eow_alm_request_data_rate,
1047                 { "Data Rate", "s5066dts.eow.alm_request.data_rate", FT_UINT8, BASE_DEC,
1048                         VALS(s5066dts_eow_data_rate), 0xF0, "", HFILL }
1049             },
1050             { &hf_s5066dts_eow_alm_request_interleaving,
1051                 { "Interleaver parameter", "s5066dts.eow.alm_request.interleaving", FT_UINT8, BASE_DEC,
1052                         VALS(s5066dts_eow_interleaving), 0x0C, "", HFILL }
1053             },
1054             { &hf_s5066dts_eow_alm_request_others,
1055                 { "Other parameters", "s5066dts.eow.alm_request.others", FT_UINT8, BASE_DEC,
1056                         VALS(s5066dts_eow_others), 0x03, "", HFILL }
1057             },
1058             /* { 6, "ALM_RESPONSE"}, */
1059             { &hf_s5066dts_eow_alm_response_response,
1060                 { "Response for DRC", "s5066dts.eow.alm_response.response", FT_UINT8, BASE_DEC,
1061                         VALS(s5066dts_eow_response), 0xE0, "", HFILL }
1062             },
1063             { &hf_s5066dts_eow_alm_response_reason,
1064                 { "Reason", "s5066dts.eow.alm_response.reason", FT_UINT8, BASE_DEC, VALS(s5066dts_alm_reason), 0x1F, "", HFILL }
1065             },
1066             /* { 7, "HDR_DRC_REQUEST"}, */
1067             { &hf_s5066dts_eow_hdr_drc_request_waveform,
1068                 { "Modem waveform", "s5066dts.eow.hdr_drc_request.waveform", FT_UINT8, BASE_DEC,
1069                         VALS(s5066dts_eow_waveform), 0xF8, "", HFILL }
1070             },
1071             { &hf_s5066dts_eow_hdr_drc_request_num_channels,
1072                 { "Number of channels", "s5066dts.eow.hdr_drc_request.num_channels", FT_UINT8, BASE_DEC, NULL, 0x07, "", HFILL }
1073             },
1074             { &hf_s5066dts_eow_hdr_drc_request_data_rate,
1075                 { "Requested data rate for each channel", "s5066dts.eow.hdr_drc_request.data_rate",
1076                         FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1077             },
1078             { &hf_s5066dts_eow_hdr_drc_request_interleaver_length,
1079                 { "Interleaver length for each channel", "s5066dts.eow.hdr_drc_request.interleaver_length",
1080                         FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
1081             },
1082             /* { 15, "HFTRP FRAME CONTROL"}, */
1083             { &hf_s5066dts_eow_hftrp_hftrp_token,
1084                 { "HFTRP Token Type", "s5066dts.eow.hftrp.token_type", FT_UINT8, BASE_DEC, NULL, 0x00, "", HFILL }
1085             },
1086             /* { 0, "DATA_ONLY"}, */
1087             { &hf_s5066dts_data_only_cpdu_start,
1088                 { "C_PDU Start", "s5066dts.data_only.cpdu_start", FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }
1089             },
1090             { &hf_s5066dts_data_only_cpdu_end,
1091                 { "C_PDU End", "s5066dts.data_only.cpdu_end", FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }
1092             },
1093             { &hf_s5066dts_data_only_deliver_in_order,
1094                 { "C_PDU Deliver-in-Order", "s5066dts.data_only.deliver_in_order", FT_BOOLEAN, 8, NULL, 0x20, "", HFILL }
1095             },
1096             { &hf_s5066dts_data_only_drop_cpdu,
1097                 { "Drop C_PDU", "s5066dts.data_only.drop_cpdu", FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }
1098             },
1099             { &hf_s5066dts_data_only_tx_win_uwe,
1100                 { "TX WIN UWE", "s5066dts.data_only.tx_win_uwe", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1101             },
1102             { &hf_s5066dts_data_only_tx_win_lwe,
1103                 { "TX WIN LWE", "s5066dts.data_only.tx_win_lwe", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1104             },
1105             { &hf_s5066dts_data_only_segmented_cpdu_size,
1106                 { "Size of segmented C_PDU", "s5066dts.data_only.segmented_cpdu_size", FT_UINT16, BASE_DEC,
1107                         NULL, 0x03FF, "", HFILL }
1108             },
1109             { &hf_s5066dts_data_only_transmit_sequence_number,
1110                 { "TX Frame Sequence Number", "s5066dts.data_only.transmit_sequence_number", FT_UINT8, BASE_DEC,
1111                         NULL, 0x0, "", HFILL }
1112             },
1113             /* { 1, "ACK_ONLY"}, */
1114             { &hf_s5066dts_ack_only_rx_lwe,
1115                 { "RX LWE", "s5066dts.ack_only.rx_lwe", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1116             },
1117             { &hf_s5066dts_ack_only_acks,
1118                 { "Selective ACK", "s5066dts.ack_only.acks", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
1119             },
1120             /* { 2, "DATA_ACK"}, */
1121             { &hf_s5066dts_data_ack_cpdu_start,
1122                 { "C_PDU Start", "s5066dts.data_ack.cpdu_start", FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }
1123             },
1124             { &hf_s5066dts_data_ack_cpdu_end,
1125                 { "C_PDU End", "s5066dts.data_ack.cpdu_end", FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }
1126             },
1127             { &hf_s5066dts_data_ack_deliver_in_order,
1128                 { "C_PDU Deliver-in-Order", "s5066dts.data_ack.deliver_in_order", FT_BOOLEAN, 8, NULL, 0x20, "", HFILL }
1129             },
1130             { &hf_s5066dts_data_ack_drop_cpdu,
1131                 { "Drop C_PDU", "s5066dts.data_ack.drop_cpdu", FT_BOOLEAN, 8, NULL, 0x10, "", HFILL }
1132             },
1133             { &hf_s5066dts_data_ack_tx_win_uwe,
1134                 { "TX WIN UWE", "s5066dts.data_ack.tx_win_uwe", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1135             },
1136             { &hf_s5066dts_data_ack_tx_win_lwe,
1137                 { "TX WIN LWE", "s5066dts.data_ack.tx_win_lwe", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1138             },
1139             { &hf_s5066dts_data_ack_segmented_cpdu_size,
1140                 { "Size of segmented C_PDU", "s5066dts.data_ack.segmented_cpdu_size", FT_UINT16, BASE_DEC,
1141                         NULL, 0x03FF, "", HFILL }
1142             },
1143             { &hf_s5066dts_data_ack_transmit_sequence_number,
1144                 { "TX frame sequence number", "s5066dts.data_ack.transmit_sequence_number", FT_UINT8, BASE_DEC,
1145                         NULL, 0x0, "", HFILL }
1146             },
1147             { &hf_s5066dts_data_ack_rx_lwe,
1148                 { "RX LWE", "s5066dts.data_ack.rx_lwe", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1149             },
1150             { &hf_s5066dts_data_ack_acks,
1151                 { "Selective ACK", "s5066dts.data_ack.acks", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
1152             },
1153             /* { 3, "RESET_WIN_RESYNC"}, */
1154             { &hf_s5066dts_reset_win_resync_unused,
1155                 { "Unused", "s5066dts.reset_win_resync.unused", FT_UINT8, BASE_HEX, NULL, 0xF0, "", HFILL }
1156             },
1157             { &hf_s5066dts_reset_win_resync_full_reset_command,
1158                 { "Full reset command", "s5066dts.reset_win_resync.full_reset", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1159             },
1160             { &hf_s5066dts_reset_win_resync_reset_tx_win_rqst,
1161                 { "Reset TX-WIN request", "s5066dts.reset_win_resync.reset_tx_win", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1162             },
1163             { &hf_s5066dts_reset_win_resync_reset_rx_win_cmnd,
1164                 { "Reset RX-WIN command", "s5066dts.reset_win_resync.reset_rx_win", FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }
1165             },
1166             { &hf_s5066dts_reset_win_resync_reset_ack,
1167                 { "Reset acknowledgment", "s5066dts.reset_win_resync.reset_ack", FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }
1168             },
1169             { &hf_s5066dts_reset_win_resync_new_rx_lwe,
1170                 { "New receiver ARQ RX-LWE", "s5066dts.reset_win_resync.new_rx_lwe", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1171             },
1172             { &hf_s5066dts_reset_win_resync_reset_frame_id_number,
1173                 { "Reset frame ID number", "s5066dts.reset_win_resync.reset_frame_id", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1174             },
1175             /* { 4, "EXP_DATA_ONLY"}, */
1176             { &hf_s5066dts_exp_data_only_cpdu_start,
1177                 { "C_PDU Start", "s5066dts.exp_data_only.cpdu_start", FT_BOOLEAN, 8, NULL, 0x80, "", HFILL }
1178             },
1179             { &hf_s5066dts_exp_data_only_cpdu_end,
1180                 { "C_PDU End", "s5066dts.exp_data_only.cpdu_end", FT_BOOLEAN, 8, NULL, 0x40, "", HFILL }
1181             },
1182             { &hf_s5066dts_exp_data_only_cpdu_id,
1183                 { "Segmented C_PDU ID", "s5066dts.exp_data_only.cpdu_id", FT_UINT8, BASE_DEC, NULL, 0x3C, "", HFILL }
1184             },
1185             { &hf_s5066dts_exp_data_only_segmented_cpdu_size,
1186                 { "Size of segmented C_PDU", "s5066dts.exp_data_only.segmented_cpdu_size", FT_UINT16, BASE_DEC, NULL, 0x03FF, "", HFILL }
1187             },
1188             { &hf_s5066dts_exp_data_only_transmit_sequence_number,
1189                 { "TX frame sequence number", "s5066dts.exp_data_only.transmit_sequence_number", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1190             },
1191             /* { 5, "EXP_ACK_ONLY"}, */
1192             { &hf_s5066dts_exp_ack_only_rx_lwe,
1193                 { "RX LWE", "s5066dts.exp_ack_only.rx_lwe", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1194             },
1195             { &hf_s5066dts_exp_ack_only_acks,
1196                 { "Selective ACK", "s5066dts.exp_ack_only.acks", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }
1197             },
1198             /* { 6, "MANAGEMENT"}, */
1199             { &hf_s5066dts_management_unused,
1200                 { "Unused", "s5066dts.management.unused", FT_UINT8, BASE_HEX, NULL, 0xF8, "", HFILL }
1201             },
1202             { &hf_s5066dts_management_extended_message_flag,
1203                 { "Extended message flag", "s5066dts.management.extended_message_flag", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1204             },
1205             { &hf_s5066dts_management_message,
1206                 { "Valid message", "s5066dts.management.message", FT_BOOLEAN, 8, NULL, 0x02, "", HFILL }
1207             },
1208             { &hf_s5066dts_management_ack,
1209                 { "Acknowledgment", "s5066dts.management.ack", FT_BOOLEAN, 8, NULL, 0x01, "", HFILL }
1210             },
1211             { &hf_s5066dts_management_management_frame_id,
1212                 { "Management frame ID number", "s5066dts.management.manegement_frame_id", FT_UINT8, BASE_DEC,
1213                         NULL, 0x0, "", HFILL }
1214             },
1215             { &hf_s5066dts_management_extended_message,
1216                 { "Extended management message", "s5066dts.management.extended_message", FT_BYTES, BASE_NONE,
1217                         NULL, 0x0, "", HFILL }
1218             },
1219             { &hf_s5066dts_management_extended_message_hftrp_payload_size,
1220                 { "Payload Size", "s5066dts.management.extended_message.reserved", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
1221             },
1222             { &hf_s5066dts_management_extended_message_hftrp_ra,
1223                 { "Ring Address", "s5066dts.management.extended_message.ring_address", FT_IPv4, BASE_NONE, NULL, 0x0, "", HFILL }
1224             },
1225             { &hf_s5066dts_management_extended_message_hftrp_seq_id,
1226                 { "Sequence ID", "s5066dts.management.extended_message.sequence_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1227             },
1228             { &hf_s5066dts_management_extended_message_hftrp_gen_seq_id,
1229                 { "Generation Sequence ID", "s5066dts.management.extended_message.generation_sequence_id",
1230                         FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }
1231             },
1232             { &hf_s5066dts_management_extended_message_hftrp_new_successor_id,
1233                 { "New Successor ID", "s5066dts.management.extended_message.new_successor_id", FT_UINT32, BASE_DEC,
1234                         NULL, 0x0, "", HFILL }
1235             },
1236             { &hf_s5066dts_management_extended_message_hftrp_number_of_nodes,
1237                 { "Number of Nodes", "s5066dts.management.extended_message.number_of_nodes", FT_UINT16, BASE_DEC,
1238                         NULL, 0x0, "", HFILL }
1239             },
1240             /* { 7, "NON_ARQ_DATA"}, */
1241             { &hf_s5066dts_non_arq_data_cpdu_id_1,
1242                 { "C_PDU ID number (field 1)", "s5066dts.non_arq_data.cpdu_id_1", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
1243             },
1244             { &hf_s5066dts_non_arq_data_deliver_in_order,
1245                 { "C_PDU Deliver-in-Order", "s5066dts.non_arq_data.deliver_in_order", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1246             },
1247             { &hf_s5066dts_non_arq_data_group_address,
1248                 { "Group Address", "s5066dts.non_arq_data.group_address", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1249             },
1250             { &hf_s5066dts_non_arq_data_cpdu_id_2,
1251                 { "C_PDU ID number (field 2)", "s5066dts.non_arq_data.cpdu_id_2", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1252             },
1253             { &hf_s5066dts_non_arq_data_cpdu_size,
1254                 { "C_PDU size", "s5066dts.non_arq_data.cpdu_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
1255             },
1256             { &hf_s5066dts_non_arq_data_cpdu_segment_offset,
1257                 { "Offset of segmented C_PDU", "s5066dts.non_arq_data.cpdu_segment_offset", FT_UINT16, BASE_DEC,
1258                         NULL, 0x0, "", HFILL }
1259             },
1260             { &hf_s5066dts_non_arq_data_cpdu_reception_window,
1261                 { "C_PDU reception window", "s5066dts.non_arq_data.cpdu_reception_window", FT_UINT16, BASE_DEC,
1262                         NULL, 0x0, "", HFILL }
1263             },
1264             { &hf_s5066dts_non_arq_data_segmented_cpdu_size,
1265                 { "Size of segmented C_PDU", "s5066dts.non_arq_data.segmented_cpdu_size", FT_UINT16, BASE_DEC,
1266                         NULL, 0x03FF, "", HFILL }
1267             },
1268             /* { 8, "EXP_NON_ARQ_DATA"}, */
1269             { &hf_s5066dts_exp_non_arq_data_cpdu_id_1,
1270                 { "C_PDU ID number (field 1)", "s5066dts.exp_non_arq_data.cpdu_id_1", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
1271             },
1272             { &hf_s5066dts_exp_non_arq_data_deliver_in_order,
1273                 { "C_PDU Deliver-in-Order", "s5066dts.exp_non_arq_data.deliver_in_order", FT_BOOLEAN, 8, NULL, 0x08, "", HFILL }
1274             },
1275             { &hf_s5066dts_exp_non_arq_data_group_address,
1276                 { "Group Address", "s5066dts.exp_non_arq_data.group_address", FT_BOOLEAN, 8, NULL, 0x04, "", HFILL }
1277             },
1278             { &hf_s5066dts_exp_non_arq_data_cpdu_id_2,
1279                 { "C_PDU ID number (field 2)", "s5066dts.exp_non_arq_data.cpdu_id_2", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1280             },
1281             { &hf_s5066dts_exp_non_arq_data_cpdu_size,
1282                 { "C_PDU size", "s5066dts.exp_non_arq_data.cpdu_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
1283             },
1284             { &hf_s5066dts_exp_non_arq_data_cpdu_segment_offset,
1285                 { "Offset of segmented C_PDU ", "s5066dts.exp_non_arq_data.cpdu_segment_offset", FT_UINT16, BASE_DEC,
1286                         NULL, 0x0, "", HFILL }
1287             },
1288             { &hf_s5066dts_exp_non_arq_data_cpdu_reception_window,
1289                 { "C_PDU reception window", "s5066dts.exp_non_arq_data.cpdu_reception_window", FT_UINT16, BASE_DEC,
1290                         NULL, 0x0, "", HFILL }
1291             },
1292             { &hf_s5066dts_exp_non_arq_data_segmented_cpdu_size,
1293                 { "Size of segmented C_PDU", "s5066dts.exp_non_arq_data.segmented_cpdu_size", FT_UINT16, BASE_DEC,
1294                         NULL, 0x03FF, "", HFILL }
1295             },
1296             /* {15, "WARNING"}, */
1297             { &hf_s5066dts_warning_frame_type,
1298                 { "Received frame type", "s5066dts.warning.frame_type", FT_UINT8, BASE_DEC, NULL, 0xF0, "", HFILL }
1299             },
1300             { &hf_s5066dts_warning_reason,
1301                 { "Reason warning sent", "s5066dts.warning.reason", FT_UINT8, BASE_DEC, NULL, 0x0F, "", HFILL }
1302             },
1303     };
1304
1305     static gint *ett[] = {
1306             &ett_s5066dts,
1307             &ett_s5066dts_eow,
1308             &ett_s5066dts_address,
1309             &ett_s5066dts_pdu,
1310             &ett_s5066dts_hftrp_token,
1311     };
1312
1313     /* Setup protocol expert items */
1314     static ei_register_info ei[] = {
1315             { &ei_s5066dts_eow_hdr_drc_request_invalid, { "s5066dts.eow_hdr_drc_request.invalid", PI_MALFORMED, PI_ERROR,
1316                     "High data rate change request can only be made in Management D_PDU", EXPFILL }},
1317             { &ei_s5066dts_eow_hftrp_invalid, { "s5066dts.eow_hftrp.invalid", PI_MALFORMED, PI_ERROR,
1318                     "HFTRP tokens can only be carried with Management D_PDU", EXPFILL }},
1319         };
1320
1321     expert_module_t* expert_s5066dts;
1322
1323     if (proto_s5066dts == -1) /* do protocol initialization only once */
1324     {
1325         proto_s5066dts = proto_register_protocol ("STANAG 5066(DTS layer)", "STANAG 5066 DTS", "s5066dts");
1326         proto_register_field_array(proto_s5066dts, hf, array_length(hf));
1327         proto_register_subtree_array(ett, array_length(ett));
1328         expert_s5066dts = expert_register_protocol(proto_s5066dts);
1329         expert_register_field_array(expert_s5066dts, ei, array_length(ei));
1330         new_register_dissector(DISSECTOR_NAME, dissect_s5066dts_tcp, proto_s5066dts);
1331     }
1332
1333     s5066dts_module = prefs_register_protocol(proto_s5066dts, proto_reg_handoff_s5066dts);
1334
1335     prefs_register_bool_preference(s5066dts_module, "proto_desegment",
1336         "Reassemble STANAG 5066 DPDUs spanning multiple TCP segments",
1337         "Whether the STANAG 5066 DTS Layer dissector should reassemble DPDUs spanning multiple TCP segments",
1338         &config_proto_desegment);
1339
1340     prefs_register_uint_preference(s5066dts_module, "tcp.port",
1341         "STANAG 5066 DTS Layer TCP Port",
1342         "Set the port for STANAG 5066 DTS Layer. (If other than the default 5067.)",
1343         10, &config_s5066dts_port);
1344 }
1345
1346 /* Routine that will be called when s5066dts is handing off to the next dissector */
1347 void proto_reg_handoff_s5066dts(void)
1348 {
1349     static gint initialized = FALSE;
1350     static dissector_handle_t s5066dts_handle;
1351     static dissector_handle_t s5066dts_over_tcp_handle;
1352     static int currentPort;
1353
1354     if (!initialized) {
1355         s5066dts_handle = new_create_dissector_handle(dissect_s5066dts_raw, proto_s5066dts);
1356         dissector_add_uint("wtap_encap", WTAP_ENCAP_STANAG_5066_D_PDU, s5066dts_handle);
1357         s5066dts_over_tcp_handle = new_create_dissector_handle(dissect_s5066dts_tcp, proto_s5066dts);
1358         initialized = TRUE;
1359     }
1360     else {
1361         dissector_delete_uint("tcp.port", currentPort, s5066dts_over_tcp_handle);
1362     }
1363
1364     currentPort = config_s5066dts_port;
1365     dissector_add_uint("tcp.port", currentPort, s5066dts_over_tcp_handle);
1366 }
1367
1368 /*
1369  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1370  *
1371  * Local variables:
1372  * c-basic-offset: 4
1373  * tab-width: 8
1374  * indent-tabs-mode: nil
1375  * End:
1376  *
1377  * vi: set shiftwidth=4 tabstop=8 expandtab:
1378  * :indentSize=4:tabSize=8:noTabs=true:
1379  */