0fd10401716c2b441792abf75d8b6587bbd5d6c3
[metze/wireshark/wip.git] / epan / dissectors / packet-dtn.c
1 /* packet-dtn.c
2  * Copyright 2006-2007 The MITRE Corporation.
3  * All Rights Reserved.
4  * Approved for Public Release; Distribution Unlimited.
5  * Tracking Number 07-0090.
6  *
7  * The US Government will not be charged any license fee and/or royalties
8  * related to this software. Neither name of The MITRE Corporation; nor the
9  * names of its contributors may be used to endorse or promote products
10  * derived from this software without specific prior written permission.
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald@wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
16  * SPDX-License-Identifier: GPL-2.0-or-later
17  *
18  * Specification reference:
19  * RFC 5050
20  * http://tools.ietf.org/html/rfc5050
21  */
22
23 /*
24  *    Modifications were made to this file under designation MFS-33289-1 and
25  *    are Copyright 2015 United States Government as represented by NASA
26  *       Marshall Space Flight Center. All Rights Reserved.
27  *
28  *    Released under the GNU GPL with NASA legal approval granted 2016-06-10.
29  *
30  *    The subject software is provided "AS IS" WITHOUT ANY WARRANTY of any kind,
31  *    either expressed, implied or statutory and this agreement does not,
32  *    in any manner, constitute an endorsement by government agency of any
33  *    results, designs or products resulting from use of the subject software.
34  *    See the Agreement for the specific language governing permissions and
35  *    limitations.
36  */
37
38 #include "config.h"
39
40 #include <stdio.h>
41 #include <epan/packet.h>
42 #include <epan/reassemble.h>
43 #include <epan/expert.h>
44 #include "packet-dtn.h"
45 #include "packet-tcp.h"
46
47 static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo,
48                                 int offset, int payload_length, gboolean* success);
49
50 /* For Reassembling TCP Convergence Layer segments */
51 static reassembly_table msg_reassembly_table;
52
53 static const char magic[] = {'d', 't', 'n', '!'};
54
55 static int proto_bundle = -1;
56 static int proto_tcp_conv = -1;
57 static int hf_bundle_pdu_version = -1;
58
59 /* TCP Convergence Header Variables */
60 static int hf_tcp_convergence_pkt_type = -1;
61
62 static int hf_contact_hdr_version = -1;
63 static int hf_contact_hdr_flags = -1;
64 static int hf_contact_hdr_keep_alive = -1;
65 static int hf_contact_hdr_flags_ack_req = -1;
66 static int hf_contact_hdr_flags_frag_enable = -1;
67 static int hf_contact_hdr_flags_nak = -1;
68 static int hf_contact_hdr_magic = -1;
69 static int hf_contact_hdr_local_eid_length = -1;
70 static int hf_contact_hdr_local_eid = -1;
71
72 /* TCP Convergence Data Header Variables */
73 static int hf_tcp_convergence_data_procflags = -1;
74 static int hf_tcp_convergence_data_procflags_start = -1;
75 static int hf_tcp_convergence_data_procflags_end = -1;
76 static int hf_tcp_convergence_data_segment_length = -1;
77
78 /* TCP Convergence Ack Variables */
79 static int hf_tcp_convergence_ack_length = -1;
80
81 /* TCP Convergence Shutdown Header Variables */
82 static int hf_tcp_convergence_shutdown_flags = -1;
83 static int hf_tcp_convergence_shutdown_flags_reason = -1;
84 static int hf_tcp_convergence_shutdown_flags_delay = -1;
85 static int hf_tcp_convergence_shutdown_reason = -1;
86 static int hf_tcp_convergence_shutdown_delay = -1;
87
88 /*TCP Convergence Layer Reassembly boilerplate*/
89 static int hf_msg_fragments = -1;
90 static int hf_msg_fragment = -1;
91 static int hf_msg_fragment_overlap = -1;
92 static int hf_msg_fragment_overlap_conflicts = -1;
93 static int hf_msg_fragment_multiple_tails = -1;
94 static int hf_msg_fragment_too_long_fragment = -1;
95 static int hf_msg_fragment_error = -1;
96 static int hf_msg_fragment_count = -1;
97 static int hf_msg_reassembled_in = -1;
98 static int hf_msg_reassembled_length = -1;
99
100 /* Primary Header Processing Flag Variables */
101 static int hf_bundle_procflags = -1;
102 static int hf_bundle_procflags_fragment = -1;
103 static int hf_bundle_procflags_admin = -1;
104 static int hf_bundle_procflags_dont_fragment = -1;
105 static int hf_bundle_procflags_cust_xfer_req = -1;
106 static int hf_bundle_procflags_dest_singleton = -1;
107 static int hf_bundle_procflags_application_ack = -1;
108
109 /* Additions for Version 5 */
110 static int hf_bundle_control_flags = -1;
111 static int hf_bundle_procflags_general = -1;
112 static int hf_bundle_procflags_cos = -1;
113 static int hf_bundle_procflags_status = -1;
114
115 /* Primary Header COS Flag Variables */
116 static int hf_bundle_cosflags = -1;
117 static int hf_bundle_cosflags_priority = -1;
118
119 /* Primary Header Status Report Request Flag Variables */
120 static int hf_bundle_srrflags = -1;
121 static int hf_bundle_srrflags_report_receipt = -1;
122 static int hf_bundle_srrflags_report_cust_accept = -1;
123 static int hf_bundle_srrflags_report_forward = -1;
124 static int hf_bundle_srrflags_report_delivery = -1;
125 static int hf_bundle_srrflags_report_deletion = -1;
126 static int hf_bundle_srrflags_report_ack = -1;
127
128 /* Primary Header Fields*/
129 static int hf_bundle_primary_header_len = -1;
130 static int hf_bundle_primary_dictionary_len = -1;
131 static int hf_bundle_primary_timestamp = -1;
132 static int hf_bundle_primary_fragment_offset = -1;
133 static int hf_bundle_primary_total_adu_len = -1;
134 static int hf_bundle_primary_timestamp_seq_num64 = -1;
135 static int hf_bundle_primary_timestamp_seq_num32 = -1;
136
137 static int hf_bundle_dest_scheme_offset_u16 = -1;
138 static int hf_bundle_dest_scheme_offset_i32 = -1;
139 static int hf_bundle_dest_ssp_offset_u16 = -1;
140 static int hf_bundle_dest_ssp_offset_i32 = -1;
141 static int hf_bundle_source_scheme_offset_u16 = -1;
142 static int hf_bundle_source_scheme_offset_i32 = -1;
143 static int hf_bundle_source_ssp_offset_u16 = -1;
144 static int hf_bundle_source_ssp_offset_i32 = -1;
145 static int hf_bundle_report_scheme_offset_u16 = -1;
146 static int hf_bundle_report_scheme_offset_i32 = -1;
147 static int hf_bundle_report_ssp_offset_u16 = -1;
148 static int hf_bundle_report_ssp_offset_i32 = -1;
149 static int hf_bundle_cust_scheme_offset_u16 = -1;
150 static int hf_bundle_cust_scheme_offset_i32 = -1;
151 static int hf_bundle_cust_ssp_offset_u16 = -1;
152 static int hf_bundle_cust_ssp_offset_i32 = -1;
153
154 /* Dictionary EIDs */
155 static int hf_bundle_dest_scheme = -1;
156 static int hf_bundle_dest_ssp = -1;
157 static int hf_bundle_source_scheme = -1;
158 static int hf_bundle_source_ssp = -1;
159 static int hf_bundle_report_scheme = -1;
160 static int hf_bundle_report_ssp = -1;
161 static int hf_bundle_custodian_scheme = -1;
162 static int hf_bundle_custodian_ssp = -1;
163
164 /* Remaining Primary Header Fields */
165 static int hf_bundle_creation_timestamp = -1;
166 static int hf_bundle_lifetime = -1;
167 static int hf_bundle_lifetime_sdnv = -1;
168
169 /* Secondary Header Processing Flag Variables */
170 static int hf_bundle_payload_length = -1;
171 static int hf_bundle_payload_header_type = -1;
172 static int hf_bundle_payload_data = -1;
173 static int hf_bundle_payload_flags = -1;
174 static int hf_bundle_payload_flags_replicate_hdr = -1;
175 static int hf_bundle_payload_flags_xmit_report = -1;
176 static int hf_bundle_payload_flags_discard_on_fail = -1;
177 static int hf_bundle_payload_flags_last_header = -1;
178
179 /* Block Processing Control Flag Variables (Version 5) */
180 static int hf_block_control_flags = -1;
181 static int hf_block_control_flags_sdnv = -1;
182 static int hf_block_control_replicate = -1;
183 static int hf_block_control_transmit_status = -1;
184 static int hf_block_control_delete_bundle = -1;
185 static int hf_block_control_last_block = -1;
186 static int hf_block_control_discard_block = -1;
187 static int hf_block_control_not_processed = -1;
188 static int hf_block_control_eid_reference = -1;
189 static int hf_block_control_block_length = -1;
190 static int hf_block_control_block_cteb_custody_id = -1;
191 static int hf_block_control_block_cteb_creator_custodian_eid = -1;
192
193 /* Non-Primary Block Type Code Variable */
194 static int hf_bundle_block_type_code = -1;
195 static int hf_bundle_unprocessed_block_data = -1;
196
197 /* ECOS Flag Variables */
198 static int hf_ecos_flags = -1;
199 static int hf_ecos_flags_critical = -1;
200 static int hf_ecos_flags_streaming = -1;
201 static int hf_ecos_flags_flowlabel = -1;
202 static int hf_ecos_flags_reliable = -1;
203 static int hf_ecos_flow_label = -1;
204
205 static int hf_ecos_ordinal = -1;
206
207 /* Administrative Record Variables */
208 static int hf_bundle_admin_record_type = -1;
209 static int hf_bundle_admin_record_fragment = -1;
210 static int hf_bundle_admin_statflags = -1;
211 static int hf_bundle_admin_rcvd = -1;
212 static int hf_bundle_admin_accepted = -1;
213 static int hf_bundle_admin_forwarded = -1;
214 static int hf_bundle_admin_delivered = -1;
215 static int hf_bundle_admin_deleted = -1;
216 static int hf_bundle_admin_acked = -1;
217 static int hf_bundle_admin_fragment_offset = -1;
218 static int hf_bundle_admin_fragment_length = -1;
219 static int hf_bundle_admin_timestamp_seq_num64 = -1;
220 static int hf_bundle_admin_timestamp_seq_num32 = -1;
221 static int hf_bundle_admin_endpoint_length = -1;
222 static int hf_bundle_admin_endpoint_id = -1;
223
224 static int hf_bundle_admin_receipt_time = -1;
225 static int hf_bundle_admin_accept_time = -1;
226 static int hf_bundle_admin_forward_time = -1;
227 static int hf_bundle_admin_delivery_time = -1;
228 static int hf_bundle_admin_delete_time = -1;
229 static int hf_bundle_admin_ack_time = -1;
230 static int hf_bundle_admin_timestamp_copy = -1;
231 static int hf_bundle_admin_signal_time = -1;
232 static int hf_bundle_status_report_reason_code = -1;
233 static int hf_bundle_custody_trf_succ_flg = -1;
234 static int hf_bundle_custody_signal_reason = -1;
235 static int hf_bundle_custody_id_range_start = -1;
236 static int hf_bundle_custody_id_range_end = -1;
237
238 static int hf_bundle_age_extension_block_code = -1;
239 static int hf_bundle_block_previous_hop_scheme = -1;
240 static int hf_bundle_block_previous_hop_eid = -1;
241
242 /* Security Block Variables */
243 static int hf_bundle_target_block_type = -1;
244 static int hf_bundle_target_block_occurance = -1;
245 static int hf_bundle_ciphersuite_type = -1;
246 static int hf_bundle_ciphersuite_flags = -1;
247 static int hf_block_ciphersuite_params = -1;
248 static int hf_block_ciphersuite_params_length = -1;
249 static int hf_block_ciphersuite_params_item_length = -1;
250 static int hf_block_ciphersuite_param_type = -1;
251 static int hf_block_ciphersuite_param_data = -1;
252 static int hf_block_ciphersuite_result_length = -1;
253 static int hf_block_ciphersuite_result_item_length = -1;
254 static int hf_block_ciphersuite_result_type = -1;
255 static int hf_block_ciphersuite_result_data = -1;
256 static int hf_block_ciphersuite_range_offset = -1;
257 static int hf_block_ciphersuite_range_length = -1;
258
259 /* Tree Node Variables */
260 static gint ett_bundle = -1;
261 static gint ett_conv_flags = -1;
262 static gint ett_shutdown_flags = -1;
263 static gint ett_bundle_hdr = -1;
264 static gint ett_primary_hdr = -1;
265 static gint ett_proc_flags = -1;
266 static gint ett_gen_flags = -1;
267 static gint ett_cos_flags = -1;
268 static gint ett_srr_flags = -1;
269 static gint ett_dictionary = -1;
270 static gint ett_payload_hdr = -1;
271 static gint ett_payload_flags = -1;
272 static gint ett_block_flags = -1;
273 static gint ett_contact_hdr_flags = -1;
274 static gint ett_admin_record = -1;
275 static gint ett_admin_rec_status = -1;
276 static gint ett_metadata_hdr = -1;
277 static gint ett_sec_block_param_data = -1;
278
279 static gint ett_tcp_conv = -1;
280 static gint ett_tcp_conv_hdr = -1;
281 static gint ett_msg_fragment = -1;
282 static gint ett_msg_fragments = -1;
283
284 static expert_field ei_bundle_payload_length = EI_INIT;
285 static expert_field ei_bundle_control_flags_length = EI_INIT;
286 static expert_field ei_bundle_block_control_flags = EI_INIT;
287 static expert_field ei_bundle_sdnv_length = EI_INIT;
288 static expert_field ei_bundle_timestamp_seq_num = EI_INIT;
289 static expert_field ei_bundle_offset_error = EI_INIT;
290 static expert_field ei_block_control_block_cteb_invalid = EI_INIT;
291 static expert_field ei_block_control_block_cteb_valid = EI_INIT;
292
293 static expert_field ei_tcp_convergence_data_flags = EI_INIT;
294 static expert_field ei_tcp_convergence_segment_length = EI_INIT;
295 static expert_field ei_tcp_convergence_ack_length = EI_INIT;
296
297
298 static dissector_handle_t bundle_handle;
299
300 #define BUNDLE_PORT            4556
301
302 typedef struct dictionary_data {
303     int bundle_header_dict_length;
304
305     int dest_scheme_offset;
306     int dst_scheme_pos;
307     int dst_scheme_len;
308     int source_scheme_offset;
309     int src_scheme_pos;
310     int src_scheme_len;
311     int report_scheme_offset;
312     int rpt_scheme_pos;
313     int rpt_scheme_len;
314     int cust_scheme_offset;
315     int cust_scheme_pos;
316     int cust_scheme_len;
317     int dest_ssp_offset;
318     int dst_ssp_len;
319     int source_ssp_offset;
320     int src_ssp_len;
321     int report_ssp_offset;
322     int rpt_ssp_len;
323     int cust_ssp_offset;
324     int cust_ssp_len;
325
326 } dictionary_data_t;
327
328
329 static const value_string packet_type_vals[] = {
330     {((TCP_CONVERGENCE_DATA_SEGMENT>>4)  & 0x0F), "Data"},
331     {((TCP_CONVERGENCE_ACK_SEGMENT>>4)   & 0x0F), "Ack"},
332     {((TCP_CONVERGENCE_REFUSE_BUNDLE>>4) & 0x0F), "Refuse Bundle"},
333     {((TCP_CONVERGENCE_KEEP_ALIVE>>4)    & 0x0F), "Keep Alive"},
334     {((TCP_CONVERGENCE_SHUTDOWN>>4)      & 0x0F), "Shutdown"},
335     {0, NULL}
336 };
337
338 static const value_string admin_record_type_vals[] = {
339     {ADMIN_REC_TYPE_STATUS_REPORT, "Bundle Status Report"},
340     {ADMIN_REC_TYPE_CUSTODY_SIGNAL, "Custody Signal"},
341     {ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL, "Aggregate Custody Signal"},
342     {ADMIN_REC_TYPE_ANNOUNCE_BUNDLE, "Announce Record (Contact)"},
343     {0, NULL}
344 };
345
346 static const value_string custody_signal_reason_codes[] = {
347     {0x0, "No Additional Information"},
348     {0x3, "Redundant Reception"},
349     {0x4, "Depleted Storage"},
350     {0x5, "Destination Endpoint ID Unintelligible"},
351     {0x6, "No Known Route to Destination"},
352     {0x7, "No Timely Contact with Next Node on Route"},
353     {0x8, "Header Unintelligible"},
354     {0, NULL}
355 };
356
357 static const value_string status_report_reason_codes[] = {
358     {0x0, "No Additional Information"},
359     {0x1, "Lifetime Expired"},
360     {0x2, "Forwarded over Unidirectional Link"},
361     {0x3, "Transmission Cancelled"},
362     {0x4, "Depleted Storage"},
363     {0x5, "Destination Endpoint ID Unintelligible"},
364     {0x6, "No Known Route to Destination"},
365     {0x7, "No Timely Contact with Next Node on Route"},
366     {0x8, "Header Unintelligible"},
367     {0, NULL}
368 };
369
370 static const value_string bundle_block_type_codes[] = {
371     {0x01, "Bundle Payload Block"},
372     {0x02, "Bundle Authentication Block"},
373     {0x03, "Block Integrity Block"},
374     {0x04, "Block Confidentiality Block"},
375     {0x05, "Previous-Hop Insertion Block"},
376     {0x08, "Metadata Extension Block"},
377     {0x09, "Extension Security Block"},
378     {0x0a, "Custody Transfer Enhancement Block"},
379     {0x13, "Extended Class of Service Block"},
380     {0x14, "Bundle Age Extension Block"},
381     {0, NULL}
382 };
383
384 static const value_string cosflags_priority_vals[] = {
385     {0x00, "Bulk"},
386     {0x01, "Normal"},
387     {0x02, "Expedited"},
388     {0x03, "Invalid (Reserved)"},
389     {0, NULL}
390 };
391
392 static const value_string ciphersuite_types[] = {
393     {0x01, "HMAC_SHA1"},
394     {0x05, "HMAC_SHA256"},
395     {0x06, "ARC4_AES128"},
396     {0xD1, "HMAC_SHA384"},
397     {0xD2, "ECDSA_SHA256"},
398     {0xD3, "ECDSA_SHA384"},
399     {0xD4, "SHA256_AES128"},
400     {0xD5, "SHA384_AES256"},
401     {0, NULL}
402 };
403
404 static const value_string res_params_types[] = {
405     {0x01, "Initialization Vector"},
406     {0x03, "Key Information"},
407     {0x04, "Content Range"},
408     {0x05, "Integrity Signature"},
409     {0x07, "Salt"},
410     {0x08, "BCB Integrity Check Value"},
411     {0, NULL}
412 };
413
414 /*
415  * SDNV has a zero in high-order bit position of last byte. The high-order
416  * bit of all preceding bytes is set to one. This returns the numeric value
417  * in an integer and sets the value of the second argument to the number of
418  * bytes used to code the SDNV. A -1 is returned if the evaluation fails
419  * (value exceeds maximum for signed integer). 0 is an acceptable value.
420  */
421
422 #define SDNV_MASK       0x7f
423
424 static const fragment_items msg_frag_items = {
425     /*Fragment subtrees*/
426     &ett_msg_fragment,
427     &ett_msg_fragments,
428     /*Fragment Fields*/
429     &hf_msg_fragments,
430     &hf_msg_fragment,
431     &hf_msg_fragment_overlap,
432     &hf_msg_fragment_overlap_conflicts,
433     &hf_msg_fragment_multiple_tails,
434     &hf_msg_fragment_too_long_fragment,
435     &hf_msg_fragment_error,
436     &hf_msg_fragment_count,
437     /*Reassembled in field*/
438     &hf_msg_reassembled_in,
439     /*Reassembled length field*/
440     &hf_msg_reassembled_length,
441     /* Reassembled data field */
442     NULL,
443     /*Tag*/
444     "Message fragments"
445 };
446
447 /*
448  * Adds the result of 2 SDNVs to tree: First SDNV is seconds, next is nanoseconds.
449  * Returns bytes in both SDNVs or 0 if something goes wrong.
450  */
451 static int
452 add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_dtn_time)
453 {
454     nstime_t dtn_time;
455     int      sdnv_length, sdnv2_length;
456     int      sdnv_value;
457     int      orig_offset;
458
459     orig_offset = offset;
460
461     sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
462     if (sdnv_value < 0) {
463         return 0;
464     }
465
466     dtn_time.secs = (time_t)(sdnv_value + 946684800);
467     offset += sdnv_length;
468
469     dtn_time.nsecs = evaluate_sdnv(tvb, offset, &sdnv2_length);
470     if (dtn_time.nsecs < 0) {
471         return 0;
472     }
473
474     proto_tree_add_time(tree, hf_dtn_time, tvb, orig_offset, sdnv_length + sdnv2_length, &dtn_time);
475
476     return (sdnv_length + sdnv2_length);
477 }
478
479 /*
480  * Adds the result of SDNV which is a time since 2000 to tree.
481  * Returns bytes in SDNV or 0 if something goes wrong.
482  */
483 static int
484 add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time)
485 {
486     nstime_t dtn_time;
487     int      sdnv_length;
488     int      sdnv_value;
489
490     sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
491     if (sdnv_value < 0) {
492         return 0;
493     }
494
495     dtn_time.secs = (time_t)(sdnv_value + 946684800);
496     dtn_time.nsecs = 0;
497     proto_tree_add_time(tree, hf_sdnv_time, tvb, offset, sdnv_length, &dtn_time);
498
499     return sdnv_length;
500 }
501
502 static int
503 add_sdnv_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv)
504 {
505     proto_item *ti;
506     int         sdnv_length;
507     int         sdnv_value;
508
509     sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
510     ti = proto_tree_add_int(tree, hf_sdnv, tvb, offset, sdnv_length, sdnv_value);
511     if (sdnv_value < 0) {
512         expert_add_info(pinfo, ti, &ei_bundle_sdnv_length);
513         return 0;
514     }
515     return sdnv_length;
516 }
517
518 /*
519  * Pull out stuff from the dictionary
520  */
521 static int
522 dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, dictionary_data_t* dict_data,
523                     guint8 pri_hdr_procflags, gchar **bundle_custodian, int creation_timestamp, int timestamp_sequence)
524 {
525     proto_tree  *dict_tree;
526     const gchar* col_text;
527
528     col_text = col_get_text(pinfo->cinfo, COL_INFO);
529
530     dict_tree = proto_tree_add_subtree(tree, tvb, offset, dict_data->bundle_header_dict_length, ett_dictionary, NULL, "Dictionary");
531
532     /*
533      * If the dictionary length is 0, then the CBHE block compression method is applied. (RFC6260)
534      * So the scheme offset is the node number and the ssp offset is the service number.
535      * If destination scheme offset is 2 and destination ssp offset is 1, then the EID is
536      * ipn:2.1
537      */
538     if (dict_data->bundle_header_dict_length == 0)
539     {
540         const gchar *src_node, *dst_node;
541
542         /*
543          * Destination info
544          */
545         if (dict_data->dest_scheme_offset == 0 && dict_data->dest_ssp_offset == 0)
546         {
547             proto_tree_add_string(dict_tree, hf_bundle_dest_scheme, tvb, 0, 0, DTN_SCHEME_STR);
548             proto_tree_add_string(dict_tree, hf_bundle_dest_ssp, tvb, dict_data->dst_scheme_pos,
549                             dict_data->dst_scheme_len + dict_data->dst_ssp_len, "none");
550
551             dst_node = "dtn:none";
552         }
553         else
554         {
555             proto_tree_add_string(dict_tree, hf_bundle_dest_scheme, tvb, 0, 0, IPN_SCHEME_STR);
556             proto_tree_add_string(dict_tree, hf_bundle_dest_ssp, tvb, dict_data->dst_scheme_pos,
557                             dict_data->dst_scheme_len + dict_data->dst_ssp_len,
558                             wmem_strdup_printf(wmem_packet_scope(), "%d.%d",dict_data->dest_scheme_offset,dict_data->dest_ssp_offset));
559
560             dst_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR,
561                                           dict_data->dest_scheme_offset, dict_data->dest_ssp_offset);
562         }
563
564         /*
565          * Source info
566          */
567         if (dict_data->source_scheme_offset == 0 && dict_data->source_ssp_offset == 0)
568         {
569             proto_tree_add_string(dict_tree, hf_bundle_source_scheme, tvb, 0, 0, DTN_SCHEME_STR);
570             proto_tree_add_string(dict_tree, hf_bundle_source_ssp, tvb, dict_data->src_scheme_pos,
571                             dict_data->src_scheme_len + dict_data->src_ssp_len, "none");
572
573             src_node = "dtn:none";
574         }
575         else
576         {
577             proto_tree_add_string(dict_tree, hf_bundle_source_scheme, tvb, 0, 0, IPN_SCHEME_STR);
578             proto_tree_add_string(dict_tree, hf_bundle_source_ssp, tvb, dict_data->src_scheme_pos,
579                             dict_data->src_scheme_len + dict_data->src_ssp_len,
580                             wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->source_scheme_offset, dict_data->source_ssp_offset));
581
582             src_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR,
583                                           dict_data->source_scheme_offset, dict_data->source_ssp_offset);
584         }
585
586         /*
587          * Report to info
588          */
589         if (dict_data->report_scheme_offset == 0 && dict_data->report_ssp_offset == 0)
590         {
591             proto_tree_add_string(dict_tree, hf_bundle_report_scheme, tvb, 0, 0, DTN_SCHEME_STR);
592             proto_tree_add_string(dict_tree, hf_bundle_report_ssp, tvb, dict_data->rpt_scheme_pos,
593                             dict_data->rpt_scheme_len + dict_data->rpt_ssp_len, "none");
594         }
595         else
596         {
597             proto_tree_add_string(dict_tree, hf_bundle_report_scheme, tvb, 0, 0, IPN_SCHEME_STR);
598             proto_tree_add_string(dict_tree, hf_bundle_report_ssp, tvb, dict_data->rpt_scheme_pos,
599                             dict_data->rpt_scheme_len + dict_data->rpt_ssp_len,
600                             wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->report_scheme_offset, dict_data->report_ssp_offset));
601         }
602
603         /*
604          * Custodian info
605          */
606         if (dict_data->cust_scheme_offset == 0 && dict_data->cust_ssp_offset == 0)
607         {
608             proto_tree_add_string(dict_tree, hf_bundle_custodian_scheme, tvb, 0, 0, DTN_SCHEME_STR);
609             proto_tree_add_string(dict_tree, hf_bundle_custodian_ssp, tvb, dict_data->cust_scheme_pos,
610                             dict_data->cust_scheme_len + dict_data->cust_ssp_len, "none");
611         }
612         else
613         {
614             proto_tree_add_string(dict_tree, hf_bundle_custodian_scheme, tvb, 0, 0, IPN_SCHEME_STR);
615             proto_tree_add_string(dict_tree, hf_bundle_custodian_ssp, tvb, dict_data->cust_scheme_pos,
616                             dict_data->cust_scheme_len + dict_data->cust_ssp_len,
617                             wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->cust_scheme_offset, dict_data->cust_ssp_offset));
618         }
619
620         /* remember custodian, for use in checking cteb validity */
621         col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
622         col_clear_fence(pinfo->cinfo, COL_INFO);
623         if (col_text && strstr(col_text, " > ")) {
624             if (! strstr(col_text, "[multiple]")) {
625                 col_append_str(pinfo->cinfo, COL_INFO, ", [multiple]");
626             }
627         } else {
628             col_clear(pinfo->cinfo, COL_INFO);
629             col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s %d.%d", src_node, dst_node, creation_timestamp, timestamp_sequence);
630         }
631         col_set_fence(pinfo->cinfo, COL_INFO);
632
633         *bundle_custodian = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR,
634                                                dict_data->cust_scheme_offset, dict_data->cust_ssp_offset);
635     }
636
637     /*
638      * This pointer can be made to address outside the packet boundaries so we
639      * need to check for improperly formatted strings (no null termination).
640      */
641
642     else
643     {
644         /*
645          * Destination info
646          */
647
648         proto_tree_add_item(dict_tree, hf_bundle_dest_scheme,
649                             tvb, offset + dict_data->dest_scheme_offset, -1, ENC_ASCII|ENC_NA);
650         proto_tree_add_item(dict_tree, hf_bundle_dest_ssp,
651                             tvb, offset + dict_data->dest_ssp_offset, -1, ENC_ASCII|ENC_NA);
652
653         /*
654          * Source info
655          */
656
657         proto_tree_add_item(dict_tree, hf_bundle_source_scheme,
658                             tvb, offset + dict_data->source_scheme_offset, -1, ENC_ASCII|ENC_NA);
659         proto_tree_add_item(dict_tree, hf_bundle_source_ssp,
660                             tvb, offset + dict_data->source_ssp_offset, -1, ENC_ASCII|ENC_NA);
661
662         /*
663          * Report to info
664          */
665
666         proto_tree_add_item(dict_tree, hf_bundle_report_scheme,
667                             tvb, offset + dict_data->report_scheme_offset, -1, ENC_ASCII|ENC_NA);
668         proto_tree_add_item(dict_tree, hf_bundle_report_ssp,
669                             tvb, offset + dict_data->report_ssp_offset, -1, ENC_ASCII|ENC_NA);
670
671         /*
672          * Custodian info
673          */
674
675         proto_tree_add_item(dict_tree, hf_bundle_custodian_scheme, tvb, offset + dict_data->cust_scheme_offset, -1, ENC_ASCII|ENC_NA);
676         proto_tree_add_item(dict_tree, hf_bundle_custodian_ssp, tvb, offset + dict_data->cust_ssp_offset, -1, ENC_ASCII|ENC_NA);
677
678         /*
679          * Add Source/Destination to INFO Field
680          */
681
682         col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
683         col_clear_fence(pinfo->cinfo, COL_INFO);
684         if (col_text && strstr(col_text, " > "))
685             col_append_str(pinfo->cinfo, COL_INFO, ", [multiple]");
686         else {
687             col_clear(pinfo->cinfo, COL_INFO);
688             col_add_fstr(pinfo->cinfo, COL_INFO, "%s:%s > %s:%s %d.%d",
689                          tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_scheme_offset, NULL, ENC_ASCII),
690                          tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_ssp_offset, NULL, ENC_ASCII),
691                          tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_scheme_offset, NULL, ENC_ASCII),
692                          tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_ssp_offset, NULL, ENC_ASCII),
693                          creation_timestamp, timestamp_sequence);
694         }
695         col_set_fence(pinfo->cinfo, COL_INFO);
696
697
698         /* remember custodian, for use in checking cteb validity */
699         *bundle_custodian = wmem_strdup_printf(wmem_packet_scope(),
700                                                "%s:%s",
701                                                tvb_get_stringz_enc(wmem_packet_scope(),
702                                                                tvb, offset + dict_data->cust_scheme_offset,
703                                                                NULL, ENC_ASCII),
704                                                tvb_get_stringz_enc(wmem_packet_scope(),
705                                                                tvb, offset + dict_data->cust_ssp_offset,
706                                                                NULL, ENC_ASCII));
707     }
708     offset += dict_data->bundle_header_dict_length;        /*Skip over dictionary*/
709
710     /*
711      * Do this only if Fragment Flag is set
712      */
713
714     if (pri_hdr_procflags & BUNDLE_PROCFLAGS_FRAG_MASK) {
715         int sdnv_length;
716         sdnv_length = add_sdnv_to_tree(tree, tvb, pinfo, offset, hf_bundle_primary_fragment_offset);
717         if (sdnv_length < 0) {
718             return 0;
719         }
720         offset += sdnv_length;
721
722         sdnv_length = add_sdnv_to_tree(tree, tvb, pinfo, offset, hf_bundle_primary_total_adu_len);
723         if (sdnv_length < 0) {
724             return 0;
725         }
726         offset += sdnv_length;
727     }
728
729     return offset;
730 }
731
732 /*
733  * This routine returns 0 if header decoding fails, otherwise the length of the primary
734  * header, starting right after version number.
735  */
736 static int
737 dissect_version_4_primary_header(packet_info *pinfo, proto_tree *primary_tree, tvbuff_t *tvb,
738                                  guint8* pri_hdr_procflags, gchar **bundle_custodian)
739 {
740     int bundle_header_length;
741     int offset = 1;             /* Version Number already displayed */
742     int sdnv_length;
743     dictionary_data_t dict_data;
744
745     proto_item *ti;
746     proto_tree *srr_flag_tree, *proc_flag_tree, *cos_flag_tree;
747
748     /* Primary Header Processing Flags */
749     *pri_hdr_procflags = tvb_get_guint8(tvb, offset);
750     ti = proto_tree_add_item(primary_tree, hf_bundle_procflags, tvb,
751                                                 offset, 1, ENC_BIG_ENDIAN);
752     proc_flag_tree = proto_item_add_subtree(ti, ett_proc_flags);
753     proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_fragment,
754                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
755     proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_admin,
756                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
757     proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_dont_fragment,
758                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
759     proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_cust_xfer_req,
760                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
761     proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_dest_singleton,
762                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
763
764     /* Primary Header COS Flags */
765     ++offset;
766     ti = proto_tree_add_item(primary_tree, hf_bundle_cosflags, tvb,
767                                                 offset, 1, ENC_BIG_ENDIAN);
768     cos_flag_tree = proto_item_add_subtree(ti, ett_cos_flags);
769     proto_tree_add_item(cos_flag_tree, hf_bundle_cosflags_priority,
770                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
771     /* Status Report Request Flags */
772     ++offset;
773     ti = proto_tree_add_item(primary_tree, hf_bundle_srrflags, tvb,
774                                                 offset, 1, ENC_BIG_ENDIAN);
775     srr_flag_tree = proto_item_add_subtree(ti, ett_srr_flags);
776
777     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_receipt,
778                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
779     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_cust_accept,
780                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
781     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_forward,
782                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
783     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_delivery,
784                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
785     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_deletion,
786                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
787     proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_ack,
788                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
789     ++offset;
790
791     bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
792     ti = proto_tree_add_int(primary_tree, hf_bundle_primary_header_len, tvb, offset, sdnv_length,
793                             bundle_header_length);
794     if (bundle_header_length < 0) {
795         expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Bundle Header Length Error");
796         return 0;
797     }
798
799     offset += sdnv_length;
800
801     /* Ensure all fields have been initialized */
802     memset(&dict_data, 0, sizeof(dict_data));
803
804     /*
805      * Pick up offsets into dictionary (8 of them)
806      */
807
808     dict_data.dest_scheme_offset = tvb_get_ntohs(tvb, offset);
809     dict_data.dst_scheme_pos = offset;
810     dict_data.dst_scheme_len = 2;
811     proto_tree_add_item(primary_tree, hf_bundle_dest_scheme_offset_u16,
812                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
813     offset += 2;
814
815     dict_data.dest_ssp_offset = tvb_get_ntohs(tvb, offset);
816     dict_data.dst_ssp_len = 2;
817     proto_tree_add_item(primary_tree, hf_bundle_dest_ssp_offset_u16,
818                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
819     offset += 2;
820
821     dict_data.source_scheme_offset = tvb_get_ntohs(tvb, offset);
822     dict_data.src_scheme_pos = offset;
823     dict_data.src_scheme_len = 2;
824     proto_tree_add_item(primary_tree, hf_bundle_source_scheme_offset_u16,
825                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
826     offset += 2;
827
828     dict_data.source_ssp_offset = tvb_get_ntohs(tvb, offset);
829     dict_data.src_ssp_len = 2;
830     proto_tree_add_item(primary_tree, hf_bundle_source_ssp_offset_u16,
831                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
832     offset += 2;
833
834     dict_data.report_scheme_offset = tvb_get_ntohs(tvb, offset);
835     dict_data.rpt_scheme_pos = offset;
836     dict_data.rpt_scheme_len = 2;
837     proto_tree_add_item(primary_tree, hf_bundle_report_scheme_offset_u16,
838                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
839     offset += 2;
840
841     dict_data.report_ssp_offset = tvb_get_ntohs(tvb, offset);
842     dict_data.rpt_ssp_len = 2;
843     proto_tree_add_item(primary_tree, hf_bundle_report_ssp_offset_u16,
844                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
845     offset += 2;
846
847     dict_data.cust_scheme_offset = tvb_get_ntohs(tvb, offset);
848     dict_data.cust_scheme_pos = offset;
849     dict_data.cust_scheme_len = 2;
850     proto_tree_add_item(primary_tree, hf_bundle_cust_scheme_offset_u16,
851                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
852     offset += 2;
853
854     dict_data.cust_ssp_offset = tvb_get_ntohs(tvb, offset);
855     dict_data.cust_ssp_len = 2;
856     proto_tree_add_item(primary_tree, hf_bundle_cust_ssp_offset_u16,
857                                                         tvb, offset, 2, ENC_BIG_ENDIAN);
858     offset += 2;
859
860     proto_tree_add_item(primary_tree, hf_bundle_creation_timestamp,
861                                                         tvb, offset, 8, ENC_BIG_ENDIAN);
862     offset += 8;
863
864     proto_tree_add_item(primary_tree, hf_bundle_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN);
865     offset += 4;
866
867     dict_data.bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
868     ti = proto_tree_add_int(primary_tree, hf_bundle_primary_dictionary_len, tvb, offset, sdnv_length,
869                             dict_data.bundle_header_dict_length);
870     if (dict_data.bundle_header_dict_length < 0) {
871         expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Dictionary Header Length Error");
872         return 0;
873     }
874     offset += sdnv_length;
875
876     offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian, 0, 0);
877     return offset;
878 }
879
880
881 /*
882  * This routine returns 0 if header decoding fails, otherwise the length of the primary
883  * header, starting right after version number.
884  */
885
886 static int
887 dissect_version_5_and_6_primary_header(packet_info *pinfo,
888                                        proto_tree *primary_tree, tvbuff_t *tvb,
889                                        guint8* pri_hdr_procflags, gchar **bundle_custodian)
890 {
891     guint64            bundle_processing_control_flags;
892     guint8             cosflags;
893     int                bundle_header_length;
894     int                offset = 1; /* Version Number already displayed */
895     int                sdnv_length;
896     dictionary_data_t  dict_data;
897     int                timestamp_sequence;
898     int                creation_timestamp;
899     guint8             srrflags;
900     proto_item        *ti;
901     proto_item        *ti_dst_scheme_offset, *ti_dst_ssp_offset;
902     proto_item        *ti_src_scheme_offset, *ti_src_ssp_offset;
903     proto_item        *ti_cust_scheme_offset, *ti_cust_ssp_offset;
904     proto_item        *ti_rprt_scheme_offset, *ti_rprt_ssp_offset;
905     proto_tree        *gen_flag_tree, *srr_flag_tree, *proc_flag_tree, *cos_flag_tree;
906     static const int * pri_flags[] = {
907         &hf_bundle_procflags_fragment,
908         &hf_bundle_procflags_admin,
909         &hf_bundle_procflags_dont_fragment,
910         &hf_bundle_procflags_cust_xfer_req,
911         &hf_bundle_procflags_dest_singleton,
912         &hf_bundle_procflags_application_ack,
913         NULL
914     };
915
916     static const int * srr_flags[] = {
917         &hf_bundle_srrflags_report_receipt,
918         &hf_bundle_srrflags_report_cust_accept,
919         &hf_bundle_srrflags_report_forward,
920         &hf_bundle_srrflags_report_delivery,
921         &hf_bundle_srrflags_report_deletion,
922         NULL
923     };
924
925     bundle_processing_control_flags = evaluate_sdnv_64(tvb, offset, &sdnv_length);
926
927     /* Primary Header Processing Flags */
928     *pri_hdr_procflags = (guint8) (bundle_processing_control_flags & 0x7f);
929
930     if (sdnv_length < 1 || sdnv_length > 8) {
931         expert_add_info_format(pinfo, primary_tree, &ei_bundle_control_flags_length,
932                                "Wrong bundle control flag length: %d", sdnv_length);
933         return 0;
934     }
935     ti = proto_tree_add_item(primary_tree, hf_bundle_control_flags, tvb,
936                                                 offset, sdnv_length, ENC_BIG_ENDIAN);
937     proc_flag_tree = proto_item_add_subtree(ti, ett_proc_flags);
938
939     ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_general, tvb, offset,
940                                         sdnv_length, *pri_hdr_procflags);
941     gen_flag_tree = proto_item_add_subtree(ti, ett_gen_flags);
942
943     /* With the variability of sdnv_length, proto_tree_add_bitmask_value
944        can't be used */
945
946     proto_tree_add_bitmask_list_value(gen_flag_tree, tvb, offset, sdnv_length, pri_flags, *pri_hdr_procflags);
947
948     /* Primary Header COS Flags */
949     cosflags = (guint8) ((bundle_processing_control_flags >> 7) & 0x7f);
950     ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_cos, tvb, offset,
951                                         sdnv_length, cosflags);
952     cos_flag_tree = proto_item_add_subtree(ti, ett_cos_flags);
953     proto_tree_add_uint(cos_flag_tree, hf_bundle_cosflags_priority, tvb, offset,
954                                     sdnv_length, cosflags);
955
956     /* Status Report Request Flags */
957     srrflags = (guint8) ((bundle_processing_control_flags >> 14) & 0x7f);
958     ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_status, tvb, offset,
959                                         sdnv_length, srrflags);
960     srr_flag_tree = proto_item_add_subtree(ti, ett_srr_flags);
961
962     proto_tree_add_bitmask_list_value(srr_flag_tree, tvb, offset, sdnv_length, srr_flags, srrflags);
963     offset += sdnv_length;
964
965     /* -- hdr_length -- */
966     bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
967     ti = proto_tree_add_int(primary_tree, hf_bundle_primary_header_len, tvb, offset, sdnv_length,
968                             bundle_header_length);
969     if (bundle_header_length < 0) {
970         expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Bundle Header Length Error");
971         return 0;
972     }
973
974     offset += sdnv_length;
975
976     /*
977      * Pick up offsets into dictionary (8 of them). Do rough sanity check that SDNV
978      * hasn't told us to access way past the Primary Header.
979      */
980
981     /* Ensure all fields have been initialized */
982     memset(&dict_data, 0, sizeof(dict_data));
983
984     /* -- dest_scheme -- */
985     dict_data.dest_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
986     dict_data.dst_scheme_pos = offset;
987     dict_data.dst_scheme_len = sdnv_length;
988
989     ti_dst_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_dest_scheme_offset_i32, tvb, offset, sdnv_length,
990                             dict_data.dest_scheme_offset);
991     offset += sdnv_length;
992
993     /* -- dest_ssp -- */
994     dict_data.dest_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
995     dict_data.dst_ssp_len = sdnv_length;
996
997     ti_dst_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_dest_ssp_offset_i32, tvb, offset, sdnv_length,
998                             dict_data.dest_ssp_offset);
999     offset += sdnv_length;
1000
1001     /* -- source_scheme -- */
1002     dict_data.source_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1003     dict_data.src_scheme_pos = offset;
1004     dict_data.src_scheme_len = sdnv_length;
1005
1006     ti_src_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_source_scheme_offset_i32, tvb, offset, sdnv_length,
1007                             dict_data.source_scheme_offset);
1008     offset += sdnv_length;
1009
1010     /* -- source_ssp -- */
1011     dict_data.source_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1012     dict_data.src_ssp_len = sdnv_length;
1013
1014     ti_src_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_source_ssp_offset_i32, tvb, offset, sdnv_length,
1015                             dict_data.source_ssp_offset);
1016     offset += sdnv_length;
1017
1018     /* -- report_scheme -- */
1019     dict_data.report_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1020     dict_data.rpt_scheme_pos = offset;
1021     dict_data.rpt_scheme_len = sdnv_length;
1022
1023     ti_rprt_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_report_scheme_offset_i32, tvb, offset,
1024                             sdnv_length, dict_data.report_scheme_offset);
1025     offset += sdnv_length;
1026
1027     /* -- report_ssp -- */
1028     dict_data.report_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1029     dict_data.rpt_ssp_len = sdnv_length;
1030
1031     ti_rprt_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_report_ssp_offset_i32, tvb, offset, sdnv_length,
1032                             dict_data.report_ssp_offset);
1033     offset += sdnv_length;
1034
1035
1036     /* -- cust_scheme -- */
1037     dict_data.cust_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1038     dict_data.cust_scheme_pos = offset;
1039     dict_data.cust_scheme_len = sdnv_length;
1040
1041     ti_cust_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_cust_scheme_offset_i32, tvb, offset, sdnv_length,
1042                             dict_data.cust_scheme_offset);
1043     offset += sdnv_length;
1044
1045     /* -- cust_ssp -- */
1046     dict_data.cust_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1047     dict_data.cust_ssp_len = sdnv_length;
1048
1049     ti_cust_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_cust_ssp_offset_i32, tvb, offset, sdnv_length,
1050                             dict_data.cust_ssp_offset);
1051     offset += sdnv_length;
1052
1053
1054     creation_timestamp = evaluate_sdnv(tvb, offset, &sdnv_length);
1055     sdnv_length = add_sdnv_time_to_tree(primary_tree, tvb, offset, hf_bundle_primary_timestamp);
1056     if (sdnv_length == 0)
1057         return 0;
1058
1059     offset += sdnv_length;
1060
1061     /* -- timestamp_sequence -- */
1062     timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
1063     if (timestamp_sequence < 0) {
1064         gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
1065
1066         ti = proto_tree_add_int64(primary_tree, hf_bundle_primary_timestamp_seq_num64,
1067                                                         tvb, offset, sdnv_length, ts_seq);
1068         if (ts_seq < 0) {
1069             expert_add_info(pinfo, ti, &ei_bundle_timestamp_seq_num);
1070         }
1071     }
1072     else {
1073         proto_tree_add_int(primary_tree, hf_bundle_primary_timestamp_seq_num32,
1074                                                         tvb, offset, sdnv_length, timestamp_sequence);
1075     }
1076     offset += sdnv_length;
1077
1078     /* -- lifetime -- */
1079     sdnv_length = add_sdnv_to_tree(primary_tree, tvb, pinfo, offset, hf_bundle_lifetime_sdnv);
1080     offset += sdnv_length;
1081
1082     /* -- dict_length -- */
1083     dict_data.bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1084     ti = proto_tree_add_int(primary_tree, hf_bundle_primary_dictionary_len, tvb, offset, sdnv_length,
1085                             dict_data.bundle_header_dict_length);
1086     if (dict_data.bundle_header_dict_length < 0) {
1087         expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Dictionary Header Length Error");
1088         return 0;
1089     }
1090     offset += sdnv_length;
1091
1092     if ((dict_data.dest_scheme_offset < 0) ||
1093         (dict_data.bundle_header_dict_length > 0 && (dict_data.dest_scheme_offset > bundle_header_length))) {
1094         expert_add_info_format(pinfo, ti_dst_scheme_offset, &ei_bundle_offset_error, "Destination Scheme Offset Error");
1095     }
1096     if ((dict_data.dest_ssp_offset < 0) ||
1097         (dict_data.bundle_header_dict_length > 0 && (dict_data.dest_ssp_offset > bundle_header_length))) {
1098         expert_add_info_format(pinfo, ti_dst_ssp_offset, &ei_bundle_offset_error, "Destination SSP Offset Error");
1099     }
1100     if ((dict_data.source_scheme_offset < 0) ||
1101         (dict_data.bundle_header_dict_length > 0 && (dict_data.source_scheme_offset > bundle_header_length))) {
1102         expert_add_info_format(pinfo, ti_src_scheme_offset, &ei_bundle_offset_error, "Source Scheme Offset Error");
1103     }
1104     if ((dict_data.source_ssp_offset < 0) ||
1105         (dict_data.bundle_header_dict_length > 0 && (dict_data.source_ssp_offset > bundle_header_length))) {
1106         expert_add_info_format(pinfo, ti_src_ssp_offset, &ei_bundle_offset_error, "Source SSP Offset Error");
1107     }
1108     if ((dict_data.report_scheme_offset < 0) ||
1109         (dict_data.bundle_header_dict_length > 0 && (dict_data.report_scheme_offset > bundle_header_length))) {
1110         expert_add_info_format(pinfo, ti_rprt_scheme_offset, &ei_bundle_offset_error, "Report Scheme Offset Error");
1111     }
1112     if ((dict_data.report_ssp_offset < 0) ||
1113         (dict_data.bundle_header_dict_length > 0 && (dict_data.report_ssp_offset > bundle_header_length))) {
1114         expert_add_info_format(pinfo, ti_rprt_ssp_offset, &ei_bundle_offset_error, "Report SSP Offset Error");
1115     }
1116     if ((dict_data.cust_scheme_offset < 0) ||
1117         (dict_data.bundle_header_dict_length > 0 && (dict_data.cust_scheme_offset > bundle_header_length))) {
1118         expert_add_info_format(pinfo, ti_cust_scheme_offset, &ei_bundle_offset_error, "Custodian Scheme Offset Error");
1119     }
1120     if ((dict_data.cust_ssp_offset < 0) ||
1121         (dict_data.bundle_header_dict_length > 0 && (dict_data.cust_ssp_offset > bundle_header_length))) {
1122         expert_add_info_format(pinfo, ti_cust_ssp_offset, &ei_bundle_offset_error, "Custodian SSP Offset Error");
1123     }
1124
1125     offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian,
1126                                 creation_timestamp, timestamp_sequence);
1127     return offset;
1128 }
1129
1130 /*
1131  * offset is where the header starts.
1132  * Return new offset, and set lastheader if failure.
1133  */
1134 static int
1135 dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, guint8 version,
1136                        guint8 pri_hdr_procflags, gboolean *lastheader)
1137 {
1138     proto_item *payload_block, *payload_item, *ti;
1139     proto_tree *payload_block_tree, *payload_tree;
1140     int         sdnv_length, payload_length;
1141
1142     payload_block_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_payload_hdr, &payload_block, "Payload Block");
1143
1144     payload_tree = proto_tree_add_subtree(payload_block_tree, tvb, offset, -1, ett_payload_hdr, &payload_item, "Payload Header");
1145
1146     proto_tree_add_uint(payload_tree, hf_bundle_payload_header_type, tvb, offset, 1, 1);
1147     ++offset;
1148
1149     /* Add tree for processing flags */
1150     /* This is really a SDNV but there are only 7 bits defined so leave it this way*/
1151
1152     if (version == 4) {
1153         static const gint *flags[] = {
1154             &hf_bundle_payload_flags_replicate_hdr,
1155             &hf_bundle_payload_flags_xmit_report,
1156             &hf_bundle_payload_flags_discard_on_fail,
1157             &hf_bundle_payload_flags_last_header,
1158             NULL
1159         };
1160         guint8      procflags;
1161
1162         procflags = tvb_get_guint8(tvb, offset);
1163         if (procflags & HEADER_PROCFLAGS_LAST_HEADER) {
1164             *lastheader = TRUE;
1165         }
1166         else {
1167             *lastheader = FALSE;
1168         }
1169         proto_tree_add_bitmask(payload_tree, tvb, offset, hf_bundle_payload_flags,
1170                                ett_payload_flags, flags, ENC_BIG_ENDIAN);
1171         ++offset;
1172     }
1173     else {      /*Bundle Protocol Version 5*/
1174         int control_flags;
1175         proto_item *block_flag_item;
1176         proto_tree *block_flag_tree;
1177
1178         control_flags = evaluate_sdnv(tvb, offset, &sdnv_length);
1179         if (control_flags & BLOCK_CONTROL_LAST_BLOCK) {
1180             *lastheader = TRUE;
1181         }
1182         else {
1183             *lastheader = FALSE;
1184         }
1185         block_flag_item = proto_tree_add_item(payload_tree, hf_block_control_flags, tvb,
1186                                                 offset, sdnv_length, ENC_BIG_ENDIAN);
1187         block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
1188
1189         proto_tree_add_item(block_flag_tree, hf_block_control_replicate,
1190                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1191         proto_tree_add_item(block_flag_tree, hf_block_control_transmit_status,
1192                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1193         proto_tree_add_item(block_flag_tree, hf_block_control_delete_bundle,
1194                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1195         proto_tree_add_item(block_flag_tree, hf_block_control_last_block,
1196                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1197         proto_tree_add_item(block_flag_tree, hf_block_control_discard_block,
1198                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1199         proto_tree_add_item(block_flag_tree, hf_block_control_not_processed,
1200                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1201         proto_tree_add_item(block_flag_tree, hf_block_control_eid_reference,
1202                                         tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
1203         offset += sdnv_length;
1204     }
1205
1206     payload_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1207     ti = proto_tree_add_int(payload_tree, hf_bundle_payload_length, tvb, offset, sdnv_length, payload_length);
1208     if (payload_length < 0) {
1209         expert_add_info(pinfo, ti, &ei_bundle_payload_length);
1210         /* Force quiting */
1211         *lastheader = TRUE;
1212         return offset;
1213     }
1214
1215     proto_item_set_len(payload_item, 2 + sdnv_length);
1216     proto_item_set_len(payload_block, 2 + sdnv_length + payload_length);
1217
1218     offset += sdnv_length;
1219     if (pri_hdr_procflags & BUNDLE_PROCFLAGS_ADMIN_MASK) {
1220         gboolean success = FALSE;
1221
1222         /*
1223          * XXXX - Have not allowed for admin record spanning multiple segments!
1224          */
1225
1226         offset = dissect_admin_record(payload_block_tree, tvb, pinfo, offset, payload_length, &success);
1227         if (!success) {
1228             /* Force quiting */
1229             *lastheader = TRUE;
1230             return offset;
1231         }
1232     } else {
1233         proto_tree_add_item(payload_block_tree, hf_bundle_payload_data, tvb, offset, payload_length, ENC_ASCII);
1234         offset += payload_length;
1235     }
1236
1237     return offset;
1238 }
1239
1240 /*
1241  * Return the offset after the Administrative Record or set success = FALSE if analysis fails.
1242  */
1243 static int
1244 dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo,
1245                      int offset, int payload_length, gboolean* success)
1246 {
1247     proto_item *admin_record_item;
1248     proto_tree *admin_record_tree;
1249     proto_item *timestamp_sequence_item;
1250     guint8      record_type;
1251     guint8      status;
1252     int         start_offset = offset;
1253     int         sdnv_length;
1254     int         timestamp_sequence;
1255     int         endpoint_length;
1256
1257     *success = FALSE;
1258     admin_record_tree = proto_tree_add_subtree(primary_tree, tvb, offset, -1,
1259                         ett_admin_record, &admin_record_item, "Administrative Record");
1260     record_type = tvb_get_guint8(tvb, offset);
1261
1262     proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1263
1264     switch ((record_type >> 4) & 0xf)
1265     {
1266     case ADMIN_REC_TYPE_STATUS_REPORT:
1267     {
1268         proto_item *status_flag_item;
1269         proto_tree *status_flag_tree;
1270
1271         proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
1272         ++offset;
1273
1274         /* Decode Bundle Status Report Flags */
1275         status = tvb_get_guint8(tvb, offset);
1276         status_flag_item = proto_tree_add_item(admin_record_tree,
1277                                 hf_bundle_admin_statflags, tvb, offset, 1, ENC_BIG_ENDIAN);
1278         status_flag_tree = proto_item_add_subtree(status_flag_item,
1279                                                         ett_admin_rec_status);
1280         proto_tree_add_item(status_flag_tree, hf_bundle_admin_rcvd,
1281                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1282         proto_tree_add_item(status_flag_tree, hf_bundle_admin_accepted,
1283                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1284         proto_tree_add_item(status_flag_tree, hf_bundle_admin_forwarded,
1285                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1286         proto_tree_add_item(status_flag_tree, hf_bundle_admin_delivered,
1287                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1288         proto_tree_add_item(status_flag_tree, hf_bundle_admin_deleted,
1289                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1290         proto_tree_add_item(status_flag_tree, hf_bundle_admin_acked,
1291                                                 tvb, offset, 1, ENC_BIG_ENDIAN);
1292         ++offset;
1293
1294         proto_tree_add_item(admin_record_tree, hf_bundle_status_report_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1295         ++offset;
1296
1297         if (record_type & ADMIN_REC_FLAGS_FRAGMENT) {
1298             sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_offset);
1299             if (sdnv_length <= 0) {
1300                 return offset;
1301             }
1302             offset += sdnv_length;
1303             sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_length);
1304             if (sdnv_length <= 0) {
1305                 return offset;
1306             }
1307             offset += sdnv_length;
1308         }
1309         if (status & ADMIN_STATUS_FLAGS_RECEIVED) {
1310             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_receipt_time);
1311             if (sdnv_length <= 0) {
1312                 return offset;
1313             }
1314             offset += sdnv_length;
1315         }
1316         if (status & ADMIN_STATUS_FLAGS_ACCEPTED) {
1317             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_accept_time);
1318             if (sdnv_length <= 0) {
1319                 return offset;
1320             }
1321             offset += sdnv_length;
1322         }
1323         if (status & ADMIN_STATUS_FLAGS_FORWARDED) {
1324             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_forward_time);
1325             if (sdnv_length <= 0) {
1326                 return offset;
1327             }
1328             offset += sdnv_length;
1329         }
1330         if (status & ADMIN_STATUS_FLAGS_DELIVERED) {
1331             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_delivery_time);
1332             if (sdnv_length <= 0) {
1333                 return offset;
1334             }
1335             offset += sdnv_length;
1336         }
1337         if (status & ADMIN_STATUS_FLAGS_DELETED) {
1338             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_delete_time);
1339             if (sdnv_length <= 0) {
1340                 return offset;
1341             }
1342             offset += sdnv_length;
1343         }
1344         if (status & ADMIN_STATUS_FLAGS_ACKNOWLEDGED) {
1345             sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_ack_time);
1346             if (sdnv_length <= 0) {
1347                 return offset;
1348             }
1349             offset += sdnv_length;
1350         }
1351
1352         /* Get 2 SDNVs for Creation Timestamp */
1353         sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_timestamp_copy);
1354         if (sdnv_length <= 0) {
1355             return offset;
1356         }
1357         offset += sdnv_length;
1358
1359         timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
1360         if (timestamp_sequence < 0) {
1361             gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
1362
1363             timestamp_sequence_item = proto_tree_add_int64(admin_record_tree, hf_bundle_admin_timestamp_seq_num64,
1364                                                             tvb, offset, sdnv_length, ts_seq);
1365             if (ts_seq < 0) {
1366                 expert_add_info(pinfo, timestamp_sequence_item, &ei_bundle_timestamp_seq_num);
1367                return offset;
1368             }
1369         }
1370         else {
1371             proto_tree_add_int(admin_record_tree, hf_bundle_admin_timestamp_seq_num32,
1372                                                             tvb, offset, sdnv_length, timestamp_sequence);
1373         }
1374         offset += sdnv_length;
1375
1376         endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1377         if (endpoint_length < 0) {
1378             return offset;
1379         }
1380         proto_tree_add_int(admin_record_tree, hf_bundle_admin_endpoint_length, tvb, offset, sdnv_length, endpoint_length);
1381         offset += sdnv_length;
1382
1383         /*
1384          * Endpoint name may not be null terminated. This routine is supposed
1385          * to add the null at the end of the string buffer.
1386          */
1387         proto_tree_add_item(admin_record_tree, hf_bundle_admin_endpoint_id, tvb, offset, endpoint_length, ENC_NA|ENC_ASCII);
1388         offset += endpoint_length;
1389
1390         break;
1391     } /* case ADMIN_REC_TYPE_STATUS_REPORT */
1392     case ADMIN_REC_TYPE_CUSTODY_SIGNAL:
1393     {
1394         proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
1395         ++offset;
1396
1397         proto_tree_add_item(admin_record_tree, hf_bundle_custody_trf_succ_flg, tvb, offset, 1, ENC_BIG_ENDIAN);
1398         proto_tree_add_item(admin_record_tree, hf_bundle_custody_signal_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
1399         ++offset;
1400
1401         if (record_type & ADMIN_REC_FLAGS_FRAGMENT) {
1402             sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_offset);
1403             if (sdnv_length <= 0) {
1404                 return offset;
1405             }
1406             offset += sdnv_length;
1407             sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_length);
1408             if (sdnv_length <= 0) {
1409                 return offset;
1410             }
1411             offset += sdnv_length;
1412         }
1413
1414         /* Signal Time */
1415         sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_signal_time);
1416         if (sdnv_length <= 0) {
1417             return offset;
1418         }
1419         offset += sdnv_length;
1420
1421         /* Timestamp copy */
1422         sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_timestamp_copy);
1423         if (sdnv_length <= 0) {
1424             return offset;
1425         }
1426         offset += sdnv_length;
1427
1428         timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
1429         if (timestamp_sequence < 0) {
1430             gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
1431
1432             timestamp_sequence_item = proto_tree_add_int64(admin_record_tree, hf_bundle_admin_timestamp_seq_num64,
1433                                                             tvb, offset, sdnv_length, ts_seq);
1434             if (ts_seq < 0) {
1435                 expert_add_info(pinfo, timestamp_sequence_item, &ei_bundle_timestamp_seq_num);
1436                return offset;
1437             }
1438         }
1439         else {
1440             proto_tree_add_int(admin_record_tree, hf_bundle_admin_timestamp_seq_num32,
1441                                                             tvb, offset, sdnv_length, timestamp_sequence);
1442         }
1443         offset += sdnv_length;
1444
1445         endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1446         if (endpoint_length < 0) {
1447             return 0;
1448         }
1449         proto_tree_add_int(admin_record_tree, hf_bundle_admin_endpoint_length, tvb, offset, sdnv_length, endpoint_length);
1450         offset += sdnv_length;
1451         proto_tree_add_item(admin_record_tree, hf_bundle_admin_endpoint_id, tvb, offset, endpoint_length, ENC_NA|ENC_ASCII);
1452         offset += endpoint_length;
1453         break;
1454     } /* case ADMIN_REC_TYPE_CUSTODY_SIGNAL */
1455     case ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL:
1456     {
1457         proto_item *ti;
1458         int payload_bytes_processed = 0;
1459         int right_edge = -1;
1460         int fill_start;
1461         int fill_length = -1;
1462         int sdnv_length_start = -1;
1463         int sdnv_length_gap = -1;
1464         int sdnv_length_length = -1;
1465
1466         proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
1467         ++offset;
1468         ++payload_bytes_processed;
1469
1470         proto_tree_add_item(admin_record_tree, hf_bundle_custody_trf_succ_flg, tvb, offset, 1, ENC_BIG_ENDIAN);
1471         proto_tree_add_item(admin_record_tree, hf_bundle_custody_signal_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
1472         ++offset;
1473         ++payload_bytes_processed;
1474
1475         /* process the first fill */
1476         fill_start = evaluate_sdnv(tvb, offset, &sdnv_length_start);
1477         ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_start, tvb, offset, sdnv_length_start, fill_start);
1478         if (fill_start < 0 || sdnv_length_start < 0) {
1479             expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range start SDNV");
1480             return offset;
1481         }
1482         fill_length = evaluate_sdnv(tvb, offset + sdnv_length_start, &sdnv_length_length);
1483         ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_end, tvb, offset,
1484                                 sdnv_length_start + sdnv_length_length, fill_start + fill_length - 1);
1485         if (fill_length < 0 || sdnv_length_length < 0) {
1486             expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range length SDNV");
1487             return offset;
1488         }
1489
1490         right_edge = fill_start + fill_length;
1491         offset += sdnv_length_start + sdnv_length_length;
1492         payload_bytes_processed += sdnv_length_start + sdnv_length_length;
1493
1494         /* now attempt to consume all the rest of the data in the
1495          * payload as additional fills */
1496         while (payload_bytes_processed < payload_length) {
1497             int fill_gap;
1498             fill_gap = evaluate_sdnv(tvb, offset, &sdnv_length_gap);
1499             ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_start, tvb, offset, sdnv_length_gap, fill_gap);
1500             if (fill_gap < 0 || sdnv_length_gap < 0) {
1501                 expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range gap SDNV");
1502                 return offset;
1503             }
1504             fill_length = evaluate_sdnv(tvb, offset + sdnv_length_gap, &sdnv_length_length);
1505             ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_end, tvb, offset,
1506                                     sdnv_length_gap + sdnv_length_length, right_edge + fill_gap + fill_length - 1);
1507             if (fill_length < 0 || sdnv_length_length < 0) {
1508                 expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range length SDNV");
1509                 return offset;
1510             }
1511
1512             right_edge += fill_gap + fill_length;
1513             offset += sdnv_length_gap + sdnv_length_length;
1514             payload_bytes_processed += sdnv_length_gap + sdnv_length_length;
1515         }
1516
1517         if (payload_bytes_processed > payload_length) {
1518             expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "ACS: CTEB Custody ID Range data extends past payload length");
1519             return offset;
1520         }
1521
1522         break;
1523     } /* case ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL */
1524     case ADMIN_REC_TYPE_ANNOUNCE_BUNDLE:
1525     default:
1526         offset++;
1527         break;
1528     }   /* End Switch */
1529
1530     proto_item_set_len(admin_record_item, offset - start_offset);
1531     *success = TRUE;
1532     return offset;
1533 }
1534
1535 static int
1536 display_extension_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gchar *bundle_custodian, gboolean *lastheader)
1537 {
1538     proto_item   *block_item, *ti, *block_flag_replicate_item, *block_flag_eid_reference_item;
1539     proto_tree   *block_tree;
1540     int           sdnv_length;
1541     int           block_length;
1542     int           block_overhead;
1543     int           bundle_age;
1544     guint8        type;
1545     unsigned int  control_flags;
1546     proto_tree   *block_flag_tree;
1547     proto_item   *block_flag_item;
1548
1549     type = tvb_get_guint8(tvb, offset);
1550     block_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_metadata_hdr, &block_item, "Extension Block");
1551
1552     proto_tree_add_item(block_tree, hf_bundle_block_type_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1553     ++offset;
1554     block_overhead = 1;
1555
1556     control_flags = (unsigned int)evaluate_sdnv(tvb, offset, &sdnv_length);
1557     if (control_flags & BLOCK_CONTROL_LAST_BLOCK) {
1558         *lastheader = TRUE;
1559     } else {
1560         *lastheader = FALSE;
1561     }
1562     block_flag_item = proto_tree_add_uint(block_tree, hf_block_control_flags_sdnv, tvb,
1563                                             offset, sdnv_length, control_flags);
1564     block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
1565     block_flag_replicate_item = proto_tree_add_boolean(block_flag_tree, hf_block_control_replicate,
1566                            tvb, offset, sdnv_length, control_flags);
1567     proto_tree_add_boolean(block_flag_tree, hf_block_control_transmit_status,
1568                            tvb, offset, sdnv_length, control_flags);
1569     proto_tree_add_boolean(block_flag_tree, hf_block_control_delete_bundle,
1570                            tvb, offset, sdnv_length, control_flags);
1571     proto_tree_add_boolean(block_flag_tree, hf_block_control_last_block,
1572                            tvb, offset, sdnv_length, control_flags);
1573     proto_tree_add_boolean(block_flag_tree, hf_block_control_discard_block,
1574                            tvb, offset, sdnv_length, control_flags);
1575     proto_tree_add_boolean(block_flag_tree, hf_block_control_not_processed,
1576                            tvb, offset, sdnv_length, control_flags);
1577     block_flag_eid_reference_item = proto_tree_add_boolean(block_flag_tree, hf_block_control_eid_reference,
1578                            tvb, offset, sdnv_length, control_flags);
1579     offset += sdnv_length;
1580     block_overhead += sdnv_length;
1581
1582     /* TODO: if this block has EID references, add them to display tree */
1583     if (control_flags & BLOCK_CONTROL_EID_REFERENCE) {
1584         int i;
1585         int num_eid_ref;
1586
1587         num_eid_ref = evaluate_sdnv(tvb, offset, &sdnv_length);
1588         offset += sdnv_length;
1589         block_overhead += sdnv_length;
1590
1591         for (i = 0; i < num_eid_ref; i++)
1592         {
1593             if (evaluate_sdnv(tvb, offset, &sdnv_length) < 0)
1594                 break;
1595             offset += sdnv_length;
1596             block_overhead += sdnv_length;
1597
1598             if (evaluate_sdnv(tvb, offset, &sdnv_length) < 0)
1599                 break;
1600             offset += sdnv_length;
1601             block_overhead += sdnv_length;
1602         }
1603     }
1604
1605     block_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1606     ti = proto_tree_add_int(block_tree, hf_block_control_block_length, tvb, offset, sdnv_length, block_length);
1607     if (block_length < 0) {
1608         expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Metadata Block Length Error");
1609         /* Force quitting */
1610         *lastheader = TRUE;
1611         return offset;
1612     }
1613     offset += sdnv_length;
1614     block_overhead += sdnv_length;
1615
1616     /* now we have enough info to know total length of metadata block */
1617     proto_item_set_len(block_item, block_overhead + block_length);
1618
1619     switch (type)
1620     {
1621     case BUNDLE_BLOCK_TYPE_AUTHENTICATION:
1622     case BUNDLE_BLOCK_TYPE_METADATA_EXTENSION:
1623     case BUNDLE_BLOCK_TYPE_EXTENSION_SECURITY:
1624     {
1625         proto_tree_add_string(block_tree, hf_bundle_unprocessed_block_data, tvb, offset, block_length, "Block data");
1626         /* not yet dissected, skip past data */
1627         offset += block_length;
1628         break;
1629     }
1630     case BUNDLE_BLOCK_TYPE_BUNDLE_AGE:
1631     {
1632         bundle_age = evaluate_sdnv(tvb, offset, &sdnv_length);
1633         proto_tree_add_int(block_tree, hf_bundle_age_extension_block_code, tvb, offset, sdnv_length, bundle_age/1000000);
1634         offset += block_length;
1635         break;
1636     }
1637     case BUNDLE_BLOCK_TYPE_PREVIOUS_HOP_INSERT:
1638     {
1639         int scheme_length;
1640
1641         proto_tree_add_item_ret_length(block_tree, hf_bundle_block_previous_hop_scheme, tvb, offset, 4, ENC_ASCII, &scheme_length);
1642         offset += scheme_length;
1643         proto_tree_add_item(block_tree, hf_bundle_block_previous_hop_eid, tvb, offset, block_length-scheme_length, ENC_ASCII|ENC_NA);
1644         offset += block_length - scheme_length;
1645
1646         break;
1647     }
1648     case BUNDLE_BLOCK_TYPE_INTEGRITY:
1649     case BUNDLE_BLOCK_TYPE_CONFIDENTIALITY:
1650     {
1651         int target_block_type;
1652         int target_block_occurance;
1653         int ciphersuite_type;
1654         unsigned int ciphersuite_flags;
1655
1656         target_block_type = evaluate_sdnv(tvb, offset, &sdnv_length);
1657         proto_tree_add_int(block_tree, hf_bundle_target_block_type, tvb, offset, sdnv_length, target_block_type);
1658         offset += sdnv_length;
1659
1660         target_block_occurance = evaluate_sdnv(tvb, offset, &sdnv_length);
1661         proto_tree_add_int(block_tree, hf_bundle_target_block_occurance, tvb, offset, sdnv_length, target_block_occurance);
1662         offset += sdnv_length;
1663
1664         ciphersuite_type = evaluate_sdnv(tvb, offset, &sdnv_length);
1665         proto_tree_add_int(block_tree, hf_bundle_ciphersuite_type, tvb, offset, sdnv_length, ciphersuite_type);
1666         offset += sdnv_length;
1667
1668         ciphersuite_flags = (unsigned int)evaluate_sdnv(tvb, offset, &sdnv_length);
1669         block_flag_item = proto_tree_add_uint(block_tree, hf_bundle_ciphersuite_flags, tvb, offset, sdnv_length, ciphersuite_flags);
1670         block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
1671         proto_tree_add_boolean(block_flag_tree, hf_block_ciphersuite_params, tvb, offset, sdnv_length, ciphersuite_flags);
1672         offset += sdnv_length;
1673
1674         int range_offset;
1675         int range_length;
1676         if (ciphersuite_flags & BLOCK_CIPHERSUITE_PARAMS) {
1677             /* Decode cipher suite parameters */
1678             int params_length;
1679             int param_type;
1680             int item_length;
1681             proto_tree   *param_tree;
1682
1683             params_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1684             param_tree = proto_tree_add_subtree(block_tree, tvb, offset, params_length+1, ett_sec_block_param_data, NULL, "Ciphersuite Parameters Data");
1685             proto_tree_add_int(param_tree, hf_block_ciphersuite_params_length, tvb, offset, sdnv_length, params_length);
1686             offset += sdnv_length;
1687
1688             for(int i = 0; i < params_length; i+=item_length+2)
1689             {
1690                 param_type = evaluate_sdnv(tvb, offset, &sdnv_length);
1691                 proto_tree_add_int(param_tree, hf_block_ciphersuite_param_type, tvb, offset, sdnv_length, param_type);
1692                 offset += sdnv_length;
1693
1694                 item_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1695                 proto_tree_add_int(param_tree, hf_block_ciphersuite_params_item_length, tvb, offset, sdnv_length, item_length);
1696                 offset += sdnv_length;
1697
1698                 //display item data
1699                 switch (param_type)
1700                 {
1701                 case 1:
1702                 case 3:
1703                 case 5:
1704                 case 7:
1705                 case 8:
1706                     proto_tree_add_item(param_tree, hf_block_ciphersuite_param_data, tvb, offset, item_length, ENC_NA);
1707                     offset += item_length;
1708                     break;
1709                 case 4:
1710                     //pair of sdnvs offset and length
1711                     range_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1712                     proto_tree_add_int(param_tree, hf_block_ciphersuite_range_offset, tvb, offset, sdnv_length, range_offset);
1713                     offset += sdnv_length;
1714
1715                     range_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1716                     proto_tree_add_int(param_tree, hf_block_ciphersuite_range_length, tvb, offset, sdnv_length, range_length);
1717                     offset += sdnv_length;
1718                     break;
1719                 default:
1720                     break;
1721                 }
1722             }
1723         }
1724         /* Decode cipher suite results */
1725         int result_length;
1726         int result_type;
1727         int result_item_length;
1728         proto_tree   *result_tree;
1729
1730         result_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1731         result_tree = proto_tree_add_subtree(block_tree, tvb, offset, result_length+1, ett_sec_block_param_data, NULL, "Security Results Data");
1732         proto_tree_add_int(result_tree, hf_block_ciphersuite_result_length, tvb, offset, sdnv_length, result_length);
1733         offset += sdnv_length;
1734
1735         for(int i = 0; i < result_length; i+=result_item_length+2)
1736         {
1737             result_type = evaluate_sdnv(tvb, offset, &sdnv_length);
1738             proto_tree_add_int(result_tree, hf_block_ciphersuite_result_type, tvb, offset, sdnv_length, result_type);
1739             offset += sdnv_length;
1740
1741             result_item_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1742             proto_tree_add_int(result_tree, hf_block_ciphersuite_result_item_length, tvb, offset, sdnv_length, result_item_length);
1743             offset += sdnv_length;
1744
1745             //display item data
1746             switch (result_type)
1747             {
1748             case 1:
1749             case 3:
1750             case 5:
1751             case 7:
1752             case 8:
1753                 proto_tree_add_item(result_tree, hf_block_ciphersuite_result_data, tvb, offset, result_item_length, ENC_NA);
1754                 offset += result_item_length;
1755                 break;
1756             case 4:
1757                 //pair of sdnvs offset and length
1758                 range_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1759                 proto_tree_add_int(result_tree, hf_block_ciphersuite_range_offset, tvb, offset, sdnv_length, range_offset);
1760                 offset += sdnv_length;
1761
1762                 range_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1763                 proto_tree_add_int(result_tree, hf_block_ciphersuite_range_length, tvb, offset, sdnv_length, range_length);
1764                 offset += sdnv_length;
1765                 break;
1766             default:
1767                 break;
1768             }
1769
1770         }
1771         break;
1772
1773     }
1774     case BUNDLE_BLOCK_TYPE_CUSTODY_TRANSFER:
1775     {
1776         int custody_id;
1777         const guint8 *cteb_creator_custodian_eid;
1778         int cteb_creator_custodian_eid_length;
1779
1780         /* check requirements for Block Processing Control Flags */
1781         if ((control_flags & BLOCK_CONTROL_REPLICATE) != 0) {
1782             expert_add_info_format(pinfo, block_flag_replicate_item, &ei_bundle_block_control_flags, "ERROR: Replicate must be clear for CTEB");
1783         }
1784         if ((control_flags & BLOCK_CONTROL_EID_REFERENCE) != 0) {
1785             expert_add_info_format(pinfo, block_flag_eid_reference_item, &ei_bundle_block_control_flags, "ERROR: EID-Reference must be clear for CTEB");
1786         }
1787
1788         /* there are two elements in a CTEB, first is the custody ID */
1789         custody_id = evaluate_sdnv(tvb, offset, &sdnv_length);
1790         proto_tree_add_int(block_tree, hf_block_control_block_cteb_custody_id, tvb, offset, sdnv_length, custody_id);
1791         offset += sdnv_length;
1792
1793         /* and second is the creator custodian EID */
1794         cteb_creator_custodian_eid_length = block_length - sdnv_length;
1795         ti = proto_tree_add_item_ret_string(block_tree, hf_block_control_block_cteb_creator_custodian_eid, tvb, offset,
1796                                 cteb_creator_custodian_eid_length, ENC_ASCII, wmem_packet_scope(), &cteb_creator_custodian_eid);
1797
1798         /* also check if CTEB is valid, i.e. custodians match */
1799         if (bundle_custodian == NULL) {
1800             expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
1801                                 "CTEB Is NOT Valid (Bundle Custodian NULL)");
1802         }
1803         else if (strlen(cteb_creator_custodian_eid) != strlen(bundle_custodian)) {
1804             expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
1805                                 "CTEB Is NOT Valid (Bundle Custodian [%s] != CTEB Custodian [%s])",
1806                                 bundle_custodian, cteb_creator_custodian_eid);
1807         }
1808         else if (memcmp(cteb_creator_custodian_eid, bundle_custodian, strlen(bundle_custodian)) != 0) {
1809             expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
1810                                 "CTEB Is NOT Valid (Bundle Custodian [%s] != CTEB Custodian [%s])",
1811                                 bundle_custodian, cteb_creator_custodian_eid);
1812         }
1813         else {
1814             expert_add_info(pinfo, ti, &ei_block_control_block_cteb_valid);
1815         }
1816         offset += cteb_creator_custodian_eid_length;
1817
1818         break;
1819     }
1820     case BUNDLE_BLOCK_TYPE_EXTENDED_COS:
1821     {
1822         int flags;
1823         static const int * ecos_flags_fields[] = {
1824             &hf_ecos_flags_critical,
1825             &hf_ecos_flags_streaming,
1826             &hf_ecos_flags_flowlabel,
1827             &hf_ecos_flags_reliable,
1828             NULL
1829         };
1830
1831         /* check requirements for Block Processing Control Flags */
1832         if ((control_flags & BLOCK_CONTROL_REPLICATE) == 0) {
1833             expert_add_info_format(pinfo, block_flag_replicate_item, &ei_bundle_block_control_flags, "ERROR: Replicate must be set for ECOS");
1834         }
1835         if ((control_flags & BLOCK_CONTROL_EID_REFERENCE) != 0) {
1836             expert_add_info_format(pinfo, block_flag_eid_reference_item, &ei_bundle_block_control_flags, "ERROR: EID-Reference must be clear for ECOS");
1837         }
1838
1839         /* flags byte */
1840         flags = (int)tvb_get_guint8(tvb, offset);
1841         proto_tree_add_bitmask(block_tree, tvb, offset, hf_ecos_flags, ett_block_flags, ecos_flags_fields, ENC_BIG_ENDIAN);
1842         offset += 1;
1843
1844         /* ordinal byte */
1845         proto_tree_add_item(block_tree, hf_ecos_ordinal, tvb, offset, 1, ENC_BIG_ENDIAN);
1846         offset += 1;
1847
1848         /* optional flow label sdnv */
1849         if ((flags & ECOS_FLAGS_FLOWLABEL) != 0) {
1850             int flow_label;
1851             flow_label = evaluate_sdnv(tvb, offset, &sdnv_length);
1852             ti = proto_tree_add_int(block_tree, hf_ecos_flow_label, tvb, offset, sdnv_length, flow_label);
1853             if (flow_label < 0) {
1854                 expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ECOS Flow Label Error");
1855                 /* Force quitting */
1856                 *lastheader = TRUE;
1857                 return offset;
1858             }
1859             offset += sdnv_length;
1860         }
1861
1862         break;
1863     }
1864     default:
1865     {
1866         proto_tree_add_string(block_tree, hf_bundle_unprocessed_block_data, tvb, offset, block_length, "Block data");
1867         /* unknown bundle type, skip past data */
1868         offset += block_length;
1869         break;
1870     }
1871     }
1872
1873     return offset;
1874 }
1875
1876 /*3rd arg is number of bytes in field (returned)*/
1877 int
1878 evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount)
1879 {
1880     int    value = 0;
1881     guint8 curbyte;
1882
1883     *bytecount = 0;
1884
1885     if (!tvb_bytes_exist(tvb, offset, 1)) {
1886         return -1;
1887     }
1888
1889     /*
1890      * Get 1st byte and continue to get them while high-order bit is 1
1891      */
1892
1893     while ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
1894         if (*bytecount >= (int) sizeof(int)) {
1895             *bytecount = 0;
1896             return -1;
1897         }
1898         value = value << 7;
1899         value |= (curbyte & SDNV_MASK);
1900         ++offset;
1901         ++*bytecount;
1902
1903         if (!tvb_bytes_exist(tvb, offset, 1)) {
1904             return -1;
1905         }
1906     }
1907
1908     /*
1909      * Add in the byte whose high-order bit is 0 (last one)
1910      */
1911
1912     value = value << 7;
1913     value |= (curbyte & SDNV_MASK);
1914     ++*bytecount;
1915     return value;
1916 }
1917
1918 /* Special Function to evaluate 64 bit SDNVs */
1919 /*3rd arg is number of bytes in field (returned)*/
1920 gint64
1921 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount)
1922 {
1923     gint64 value = 0;
1924     guint8 curbyte;
1925
1926     *bytecount = 0;
1927
1928     if (!tvb_bytes_exist(tvb, offset, 1)) {
1929         return -1;
1930     }
1931
1932     /*
1933      * Get 1st byte and continue to get them while high-order bit is 1
1934      */
1935
1936     while ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
1937         if (*bytecount >= (int) sizeof(gint64)) {
1938             *bytecount = 0;
1939             return -1;
1940         }
1941         value = value << 7;
1942         value |= (curbyte & SDNV_MASK);
1943         ++offset;
1944         ++*bytecount;
1945
1946         if (!tvb_bytes_exist(tvb, offset, 1)) {
1947             return -1;
1948         }
1949     }
1950
1951     /*
1952      * Add in the byte whose high-order bit is 0 (last one)
1953      */
1954
1955     value = value << 7;
1956     value |= (curbyte & SDNV_MASK);
1957     ++*bytecount;
1958     return value;
1959 }
1960
1961 /* Special Function to evaluate 32 bit unsigned SDNVs with error indication
1962  *    bytecount returns the number bytes consumed
1963  *    value returns the actual value
1964  *
1965  *    result is TRUE (1) on success else FALSE (0)
1966  */
1967 int
1968 evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value)
1969 {
1970     int result;
1971     int num_bits_in_value;
1972     guint8 curbyte;
1973     guint8 high_bit;
1974
1975     *value = 0;
1976     *bytecount = 0;
1977
1978     result = FALSE;
1979     num_bits_in_value = 0;
1980
1981     if (tvb_bytes_exist(tvb, offset, 1)) {
1982         /*
1983          * Get 1st byte and continue to get them while high-order bit is 1
1984          */
1985         result = TRUE;
1986
1987         /* Determine number of non-zero bits in first SDNV byte */
1988         /* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */
1989         while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
1990             if (!tvb_bytes_exist(tvb, offset, 1)) {
1991                 result = FALSE;
1992                 break;
1993             } else {
1994                 num_bits_in_value = 7;
1995                 high_bit = 0x40;
1996                 while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) {
1997                     --num_bits_in_value;
1998                     high_bit = high_bit >> 1;
1999                 }
2000
2001                 *value |= (curbyte & SDNV_MASK);
2002                 ++offset;
2003                 ++*bytecount;
2004             }
2005         }
2006
2007
2008         /* Process additional bytes that have the high order bit set */
2009         while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
2010             /* Since the high order bit is set there must be 7 low order bits after this byte */
2011             if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (32 - 7))) {
2012                 result = FALSE;
2013             } else {
2014                 *value = *value << 7;
2015                 *value |= (curbyte & SDNV_MASK);
2016                 ++offset;
2017                 ++*bytecount;
2018             }
2019         }
2020
2021         if (result) {
2022             /*
2023              * Add in the byte whose high-order bit is 0 (last one)
2024              */
2025             *value = *value << 7;
2026             *value |= (curbyte & SDNV_MASK);
2027             ++*bytecount;
2028         } else {
2029             *bytecount = 0;
2030         }
2031     }
2032
2033     return result;
2034 }
2035
2036
2037 /* Special Function to evaluate 64 bit unsigned SDNVs with error indication
2038  *    bytecount returns the number bytes consumed or zero on error
2039  *    value returns the actual value
2040  *
2041  *    result is TRUE (1) on success else FALSE (0)
2042  */
2043 int
2044 evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value)
2045 {
2046     int result;
2047     int num_bits_in_value;
2048     guint8 curbyte;
2049     guint8 high_bit;
2050
2051     *value = 0;
2052     *bytecount = 0;
2053
2054     result = FALSE;
2055     num_bits_in_value = 0;
2056
2057     if (tvb_bytes_exist(tvb, offset, 1)) {
2058         /*
2059          * Get 1st byte and continue to get them while high-order bit is 1
2060          */
2061         result = TRUE;
2062
2063         /* Determine number of non-zero bits in first SDNV byte */
2064         /* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */
2065         while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
2066             if (!tvb_bytes_exist(tvb, offset, 1)) {
2067                 result = FALSE;
2068                 break;
2069             } else {
2070                 num_bits_in_value = 7;
2071                 high_bit = 0x40;
2072                 while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) {
2073                     --num_bits_in_value;
2074                     high_bit = high_bit >> 1;
2075                 }
2076
2077                 *value |= (curbyte & SDNV_MASK);
2078                 ++offset;
2079                 ++*bytecount;
2080             }
2081         }
2082
2083
2084         /* Process additional bytes that have the high order bit set */
2085         while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) {
2086             /* Since the high order bit is set there must be 7 low order bits after this byte */
2087             if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (64 - 7))) {
2088                 result = FALSE;
2089             } else {
2090                 *value = *value << 7;
2091                 *value |= (curbyte & SDNV_MASK);
2092                 ++offset;
2093                 ++*bytecount;
2094             }
2095         }
2096
2097         if (result) {
2098             /*
2099              * Add in the byte whose high-order bit is 0 (last one)
2100              */
2101             *value = *value << 7;
2102             *value |= (curbyte & SDNV_MASK);
2103             ++*bytecount;
2104         } else {
2105             *bytecount = 0;
2106         }
2107     }
2108
2109     return result;
2110 }
2111
2112
2113 static guint
2114 get_dtn_contact_header_len(packet_info *pinfo _U_, tvbuff_t *tvb,
2115                            int offset, void *data _U_)
2116 {
2117     int len, bytecount;
2118
2119     /* get length from sdnv */
2120     len = evaluate_sdnv(tvb, offset+8, &bytecount);
2121     if (len < 0)
2122         return 0;
2123
2124     return len+bytecount+8;
2125 }
2126
2127 static int
2128 dissect_dtn_contact_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2129 {
2130     proto_item *ti;
2131     proto_tree *conv_proto_tree, *conv_tree, *conv_flag_tree;
2132     int         eid_length, sdnv_length;
2133     int         offset = 0;
2134
2135     col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL");
2136     col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
2137     col_add_str(pinfo->cinfo, COL_INFO, "Contact Header");
2138
2139     ti = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
2140     conv_proto_tree = proto_item_add_subtree(ti, ett_tcp_conv);
2141
2142     conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, offset, -1, ett_tcp_conv, NULL, "Contact Header");
2143
2144     proto_tree_add_item(conv_tree, hf_contact_hdr_magic, tvb, offset, 4, ENC_NA|ENC_ASCII);
2145     offset += 4;
2146     proto_tree_add_item(conv_tree, hf_contact_hdr_version, tvb, offset, 1, ENC_BIG_ENDIAN);
2147     offset++;
2148
2149     /* Subtree to expand the bits in the Contact Header Flags */
2150     ti = proto_tree_add_item(conv_tree, hf_contact_hdr_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
2151     conv_flag_tree = proto_item_add_subtree(ti, ett_contact_hdr_flags);
2152     proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_ack_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2153     proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_frag_enable, tvb, offset, 1, ENC_BIG_ENDIAN);
2154     proto_tree_add_item(conv_flag_tree, hf_contact_hdr_flags_nak, tvb, offset, 1, ENC_BIG_ENDIAN);
2155     offset++;
2156
2157     proto_tree_add_item(conv_tree, hf_contact_hdr_keep_alive, tvb, offset, 2, ENC_BIG_ENDIAN);
2158     offset += 2;
2159
2160     /*
2161      * New format Contact header has length field followed by Bundle Header.
2162      */
2163     eid_length = evaluate_sdnv(tvb, offset, &sdnv_length);
2164     ti = proto_tree_add_int(tree, hf_contact_hdr_local_eid_length, tvb, offset, sdnv_length, eid_length);
2165     if (eid_length < 0) {
2166         expert_add_info(pinfo, ti, &ei_bundle_sdnv_length);
2167         return offset;
2168     }
2169
2170     proto_tree_add_item(conv_tree, hf_contact_hdr_local_eid, tvb, sdnv_length + offset, eid_length, ENC_NA|ENC_ASCII);
2171     return tvb_captured_length(tvb);
2172 }
2173
2174 static guint
2175 get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
2176 {
2177     int    len, bytecount;
2178     guint8 conv_hdr = tvb_get_guint8(tvb, offset);
2179
2180     switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
2181     {
2182     case TCP_CONVERGENCE_DATA_SEGMENT:
2183         /* get length from sdnv */
2184         len = evaluate_sdnv(tvb, offset+1, &bytecount);
2185         if (len < 0)
2186             return 0;
2187
2188         return len+bytecount+1;
2189
2190     case TCP_CONVERGENCE_ACK_SEGMENT:
2191         /* get length from sdnv */
2192         len = evaluate_sdnv(tvb, offset+1, &bytecount);
2193         if (len < 0)
2194             return 0;
2195
2196         return bytecount+1;
2197
2198     case TCP_CONVERGENCE_KEEP_ALIVE:
2199     case TCP_CONVERGENCE_REFUSE_BUNDLE:
2200         /* always 1 byte */
2201         return 1;
2202     case TCP_CONVERGENCE_SHUTDOWN:
2203         len = 1;
2204
2205         if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
2206             len += 1;
2207         }
2208         if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
2209             len += 2;
2210         }
2211
2212         return len;
2213     }
2214
2215     /* This probably isn't a TCPCL/Bundle packet, so just stop dissection */
2216     return -1;
2217 }
2218
2219 static int
2220 dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2221 {
2222     guint8         conv_hdr;
2223     int            offset = 0;
2224     int            sdnv_length, segment_length, convergence_hdr_size;
2225     proto_item    *ci, *sub_item;
2226     proto_tree    *conv_proto_tree, *conv_tree, *sub_tree;
2227     fragment_head *frag_msg;
2228     tvbuff_t      *new_tvb;
2229     gboolean       more_frags;
2230     int            processed_length = 0;
2231     const gchar*   col_text;
2232     gboolean       bundle_in_col_info;
2233
2234     static guint32 frag_id = 0;
2235     static guint32 last_frame = 0;
2236     static int last_raw_offset = 0;
2237
2238     if (last_frame != pinfo->fd->num || tvb_raw_offset(tvb) < last_raw_offset)
2239         frag_id = 0;
2240     last_frame = pinfo->fd->num;
2241     last_raw_offset = tvb_raw_offset(tvb);
2242
2243     col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL");
2244     col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
2245
2246     col_text = col_get_text(pinfo->cinfo, COL_INFO);
2247     bundle_in_col_info = (col_text && strstr(col_text, " > "));
2248
2249     ci = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA);
2250     conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv);
2251
2252     conv_tree = proto_tree_add_subtree(conv_proto_tree, tvb, 0, -1, ett_tcp_conv_hdr, NULL, "TCP Convergence Header");
2253
2254     conv_hdr = tvb_get_guint8(tvb, offset);
2255     proto_tree_add_item(conv_tree, hf_tcp_convergence_pkt_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2256     col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((conv_hdr>>4)&0xF, packet_type_vals, "Unknown"));
2257
2258     switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
2259     {
2260     case TCP_CONVERGENCE_DATA_SEGMENT:
2261         sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_data_procflags, tvb,
2262                                                     offset, 1, ENC_BIG_ENDIAN);
2263         sub_tree = proto_item_add_subtree(sub_item, ett_conv_flags);
2264         proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_start,
2265                                                     tvb, offset, 1, ENC_BIG_ENDIAN);
2266         proto_tree_add_item(sub_tree, hf_tcp_convergence_data_procflags_end,
2267                                                     tvb, offset, 1, ENC_BIG_ENDIAN);
2268
2269         /* Only Start and End flags (bits 0 & 1) are valid in Data Segment */
2270         if ((conv_hdr & ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_DATA_FLAGS)) != 0) {
2271             expert_add_info(pinfo, sub_item, &ei_tcp_convergence_data_flags);
2272         }
2273
2274         segment_length = evaluate_sdnv(tvb, 1, &sdnv_length);
2275         sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_data_segment_length, tvb, 1, sdnv_length, segment_length);
2276         if (segment_length < 0) {
2277             expert_add_info(pinfo, sub_item, &ei_tcp_convergence_segment_length);
2278             return 1;
2279         }
2280
2281         convergence_hdr_size = sdnv_length + 1;
2282
2283         /*
2284             * 1/11/2006 - If I got here, I should have a complete convergence layer
2285             * "segment" beginning at frame_offset. However that might not be a
2286             * complete bundle. Or there might be a complete bundle plus one or more
2287             * additional convergence layer headers.
2288             */
2289
2290         new_tvb  = NULL;
2291         sub_tree = NULL;
2292         if ((conv_hdr & TCP_CONVERGENCE_DATA_END_FLAG) == TCP_CONVERGENCE_DATA_END_FLAG) {
2293             more_frags = FALSE;
2294         }
2295         else {
2296             more_frags = TRUE;
2297         }
2298
2299         frag_msg = fragment_add_seq_next(&msg_reassembly_table,
2300                                          tvb, offset + convergence_hdr_size,
2301                                          pinfo, frag_id, data,
2302                                          segment_length, more_frags);
2303
2304         if (!more_frags) ++frag_id;
2305
2306         processed_length = convergence_hdr_size + segment_length;
2307
2308         if (frag_msg && !more_frags) {
2309
2310             int save_fd_head_layer = frag_msg->reas_in_layer_num;
2311             frag_msg->reas_in_layer_num = pinfo->curr_layer_num;
2312
2313             sub_item = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA);
2314             sub_tree = proto_item_add_subtree(sub_item, ett_bundle);
2315
2316             new_tvb = process_reassembled_data(tvb, offset + convergence_hdr_size,
2317                                                 pinfo, "Reassembled DTN", frag_msg,
2318                                                 &msg_frag_items, NULL, sub_tree);
2319
2320             frag_msg->reas_in_layer_num = save_fd_head_layer;
2321         }
2322
2323         if (new_tvb) {
2324             if (0 == call_dissector_with_data(bundle_handle, new_tvb, pinfo, sub_tree, data)) {
2325                 /*Couldn't parse bundle, treat as raw data */
2326                 call_data_dissector(new_tvb, pinfo, sub_tree);
2327                 return tvb_captured_length(tvb);
2328             }
2329         }
2330         else {
2331
2332             /*
2333             * If there are 2 segments, the second of which is very short, this
2334             * gets displayed instead of the usual Source EID/Destination EID in
2335             * the Bundle Dissection frame. If these statements are left out entirely,
2336             * nothing is displayed, i.e., there seems to be no way to get the
2337             * Source/Destination in the 2-segment case. I'll leave it in because I
2338             * think it is informative in the multi-segment case although confusing in the
2339             * 2-segment case.
2340             */
2341             col_add_str(pinfo->cinfo, COL_INFO, "[Bundle TCPCL Segment]");
2342         }
2343         break;
2344     case TCP_CONVERGENCE_ACK_SEGMENT:
2345         if (bundle_in_col_info) {
2346             if (!strstr(col_text, ", TCPL ACK")) {
2347                 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL ACK Segment(s)");
2348             }
2349         } else {
2350             col_set_str(pinfo->cinfo, COL_INFO, "TCPL ACK Segment(s)");
2351         }
2352         segment_length = evaluate_sdnv(tvb, offset+1, &sdnv_length);
2353         sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_ack_length, tvb, offset+1, sdnv_length, segment_length);
2354         if (segment_length < 0) {
2355             expert_add_info(pinfo, sub_item, &ei_tcp_convergence_ack_length);
2356             processed_length = tvb_captured_length(tvb);
2357         } else {
2358             processed_length = sdnv_length + 1;
2359         }
2360         break;
2361     case TCP_CONVERGENCE_KEEP_ALIVE:
2362         if (bundle_in_col_info) {
2363             if (!strstr(col_text, ", TCPL KEEPALIVE")) {
2364                 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL KEEPALIVE Segment");
2365             }
2366         } else {
2367             col_set_str(pinfo->cinfo, COL_INFO, "TCPL KEEPALIVE Segment");
2368         }
2369         /*No valid flags in Keep Alive*/
2370         processed_length = 1;
2371         break;
2372
2373     case TCP_CONVERGENCE_SHUTDOWN:
2374         if (bundle_in_col_info) {
2375             if (!strstr(col_text, ", TCPL SHUTDOWN")) {
2376                 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL SHUTDOWN Segment");
2377             }
2378         } else {
2379             col_set_str(pinfo->cinfo, COL_INFO, "TCPL SHUTDOWN Segment");
2380         }
2381         /* Add tree for Shutdown Flags */
2382         sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_shutdown_flags, tvb,
2383                                         offset, 1, ENC_BIG_ENDIAN);
2384         sub_tree = proto_item_add_subtree(sub_item, ett_shutdown_flags);
2385
2386         proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_reason,
2387                                         tvb, offset, 1, ENC_BIG_ENDIAN);
2388         proto_tree_add_item(sub_tree, hf_tcp_convergence_shutdown_flags_delay,
2389                                         tvb, offset, 1, ENC_BIG_ENDIAN);
2390
2391         offset += 1;
2392         if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
2393             proto_tree_add_item(conv_tree,
2394                                         hf_tcp_convergence_shutdown_reason, tvb,
2395                                         offset, 1, ENC_BIG_ENDIAN);
2396             offset += 1;
2397         }
2398         if (conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
2399             proto_tree_add_item(conv_tree,
2400                                         hf_tcp_convergence_shutdown_delay, tvb,
2401                                         offset, 2, ENC_BIG_ENDIAN);
2402         }
2403         break;
2404     case TCP_CONVERGENCE_REFUSE_BUNDLE:
2405         if (bundle_in_col_info) {
2406             if (!strstr(col_text, ", TCPL REFUSE")) {
2407                 col_add_str(pinfo->cinfo, COL_INFO, ", TCPL REFUSE_BUNDLE Segment");
2408             }
2409         } else {
2410             col_set_str(pinfo->cinfo, COL_INFO, "TCPL REFUSE_BUNDLE Segment");
2411         }
2412         /*No valid flags*/
2413         processed_length = tvb_captured_length(tvb);
2414         break;
2415     }
2416
2417     return processed_length;
2418 }
2419
2420 static int
2421 dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2422 {
2423     guint8  conv_hdr;
2424     int     offset, bytecount;
2425     int processed_length;
2426
2427     /* Make sure we have a convergence header byte */
2428     if (!tvb_bytes_exist(tvb, 0, 1))
2429         return 0;
2430
2431     conv_hdr = tvb_get_guint8(tvb, 0);
2432     switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK)
2433     {
2434     case TCP_CONVERGENCE_DATA_SEGMENT:
2435     case TCP_CONVERGENCE_ACK_SEGMENT:
2436         /* ensure sdnv */
2437         offset = 1;
2438         bytecount = 1;
2439
2440         if (!tvb_bytes_exist(tvb, offset, 1)) {
2441             pinfo->desegment_offset = 0;
2442             pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2443             return 0;
2444         }
2445
2446         while (tvb_get_guint8(tvb, offset) & ~SDNV_MASK) {
2447             if (bytecount > (int)sizeof(int)) {
2448                 /* invalid length field */
2449                 return 0;
2450             }
2451
2452             bytecount++;
2453             offset++;
2454
2455             if (!tvb_bytes_exist(tvb, offset, 1)) {
2456                 pinfo->desegment_offset = 0;
2457                 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2458                 return 0;
2459             }
2460         }
2461         break;
2462     case TCP_CONVERGENCE_KEEP_ALIVE:
2463     case TCP_CONVERGENCE_REFUSE_BUNDLE:
2464         /* always 1 byte */
2465         break;
2466     case TCP_CONVERGENCE_SHUTDOWN:
2467         if ((conv_hdr &
2468                 ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_SHUTDOWN_FLAGS)) != 0) {
2469             /* Not for us */
2470             return 0;
2471         }
2472         break;
2473     default:
2474         if (conv_hdr == (guint8)magic[0]) {
2475             if (!tvb_bytes_exist(tvb, 0, 4) || tvb_memeql(tvb, 0, magic, 4)) {
2476                 /* Not for us */
2477                 return 0;
2478             }
2479
2480             tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_dtn_contact_header_len, dissect_dtn_contact_header, data);
2481             return tvb_captured_length(tvb);
2482         }
2483
2484         /* Not for us */
2485         return 0;
2486     };
2487
2488     processed_length = get_tcpcl_pdu_len(pinfo, tvb, 0, data);
2489
2490     tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 1, get_tcpcl_pdu_len, dissect_tcpcl_pdu, data);
2491
2492     return processed_length;
2493 }
2494
2495 static int
2496 dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2497 {
2498     proto_item *ti, *ti_bundle_protocol;
2499     proto_tree *bundle_tree, *primary_tree;
2500     int         primary_header_size;
2501     gboolean    lastheader = FALSE;
2502     int         offset = 0;
2503     guint8      version, pri_hdr_procflags;
2504     /* Custodian from Primary Block, used to validate CTEB */
2505     gchar      *bundle_custodian = NULL;
2506
2507
2508     version = tvb_get_guint8(tvb, offset);  /* Primary Header Version */
2509     if ((version != 4) && (version != 5) && (version != 6)) {
2510         return 0;
2511     }
2512
2513     col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bundle");
2514     /* Clear out stuff in the info column */
2515     col_clear(pinfo->cinfo,COL_INFO);
2516
2517     ti_bundle_protocol = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA);
2518
2519     bundle_tree = proto_item_add_subtree(ti_bundle_protocol, ett_bundle);
2520
2521     primary_tree = proto_tree_add_subtree(bundle_tree, tvb, offset, -1, ett_primary_hdr, &ti, "Primary Bundle Header");
2522
2523     proto_tree_add_item(primary_tree, hf_bundle_pdu_version, tvb, offset, 1, ENC_BIG_ENDIAN);
2524     if (version == 4) {
2525         primary_header_size = dissect_version_4_primary_header(pinfo, primary_tree, tvb,
2526                                 &pri_hdr_procflags, &bundle_custodian);
2527     }
2528     else {
2529         primary_header_size = dissect_version_5_and_6_primary_header(pinfo, primary_tree, tvb,
2530                                 &pri_hdr_procflags, &bundle_custodian);
2531     }
2532
2533     if (primary_header_size == 0) {      /*Couldn't parse primary header*/
2534         col_add_str(pinfo->cinfo, COL_INFO, "Protocol Error");
2535         return(0);      /*Give up*/
2536     }
2537
2538     proto_item_set_len(ti, primary_header_size);
2539     offset = primary_header_size;
2540
2541     /*
2542      * Done with primary header; decode the remaining headers
2543      */
2544
2545     while (lastheader == FALSE) {
2546         guint8 next_header_type;
2547
2548         next_header_type = tvb_get_guint8(tvb, offset);
2549         if (next_header_type == BUNDLE_BLOCK_TYPE_PAYLOAD) {
2550
2551             /*
2552              * Returns payload size or 0 if can't parse payload
2553              */
2554             offset = dissect_payload_header(bundle_tree, tvb, pinfo, offset, version, pri_hdr_procflags, &lastheader);
2555         }
2556         else {  /*Assume anything else is a Metadata Block*/
2557             offset = display_extension_block(bundle_tree, tvb, pinfo, offset, bundle_custodian, &lastheader);
2558         }
2559     }
2560
2561     proto_item_set_len(ti_bundle_protocol, offset);
2562
2563     return(offset);
2564 }
2565
2566
2567 void proto_reg_handoff_bundle(void);
2568 void proto_register_bundle(void);
2569
2570 void
2571 proto_register_bundle(void)
2572 {
2573
2574     static hf_register_info hf[] = {
2575         {&hf_bundle_pdu_version,
2576          {"Bundle Version", "bundle.version",
2577           FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
2578         },
2579         {&hf_msg_fragments,
2580          {"Message Fragments", "bundle.msg.fragments",
2581           FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
2582         },
2583         {&hf_msg_fragment,
2584          {"Message Fragment", "bundle.msg.fragment",
2585           FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
2586         },
2587         {&hf_msg_fragment_overlap,
2588          {"Message fragment overlap", "bundle.msg.fragment.overlap",
2589           FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
2590         },
2591         {&hf_msg_fragment_overlap_conflicts,
2592          {"Message fragment overlapping with conflicting data",
2593           "bundle.msg.fragment.overlap.conflicts",
2594           FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
2595         },
2596         {&hf_msg_fragment_multiple_tails,
2597          {"Message has multiple tails", "bundle.msg.fragment.multiple_tails",
2598           FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
2599         },
2600         {&hf_msg_fragment_too_long_fragment,
2601          {"Message fragment too long", "bundle.msg.fragment.too_long_fragment",
2602           FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
2603         },
2604         {&hf_msg_fragment_error,
2605          {"Message defragmentation error", "bundle.msg.fragment.error",
2606           FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
2607         },
2608         {&hf_msg_fragment_count,
2609          {"Message fragment count", "bundle.msg.fragment.count",
2610           FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2611         },
2612         {&hf_msg_reassembled_in,
2613          {"Reassembled in", "bundle.msg.reassembled.in",
2614           FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
2615         },
2616         {&hf_msg_reassembled_length,
2617          {"Reassembled DTN length", "bundle.msg.reassembled.length",
2618           FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2619         },
2620         {&hf_bundle_procflags,
2621          {"Primary Header Processing Flags", "bundle.primary.proc.flag",
2622           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2623         },
2624         {&hf_bundle_procflags_fragment,
2625          {"Bundle is a Fragment", "bundle.primary.proc.frag",
2626           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_FRAG_MASK, NULL, HFILL}
2627         },
2628         {&hf_bundle_procflags_admin,
2629          {"Administrative Record", "bundle.primary.proc.admin",
2630           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_ADMIN_MASK, NULL, HFILL}
2631         },
2632         {&hf_bundle_procflags_dont_fragment,
2633          {"Do Not Fragment Bundle", "bundle.primary.proc.dontfrag",
2634           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_DONTFRAG_MASK, NULL, HFILL}
2635         },
2636         {&hf_bundle_procflags_cust_xfer_req,
2637          {"Request Custody Transfer", "bundle.primary.proc.xferreq",
2638           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_XFERREQ_MASK, NULL, HFILL}
2639         },
2640         {&hf_bundle_procflags_dest_singleton,
2641          {"Destination is Singleton", "bundle.primary.proc.single",
2642           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_SINGLETON_MASK, NULL, HFILL}
2643         },
2644         {&hf_bundle_procflags_application_ack,
2645          {"Request Acknowledgement by Application", "bundle.primary.proc.ack",
2646           FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_APP_ACK_MASK, NULL, HFILL}
2647         },
2648         {&hf_bundle_control_flags,
2649          {"Bundle Processing Control Flags", "bundle.primary.proc.flag",
2650           FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2651         },
2652         {&hf_bundle_procflags_general,
2653          {"General Flags", "bundle.primary.proc.gen",
2654           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2655         },
2656         {&hf_bundle_procflags_cos,
2657          {"Class of Service Flags", "bundle.primary.proc.cos",
2658           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2659         },
2660         {&hf_bundle_procflags_status,
2661          {"Status Report Flags", "bundle.primary.proc.status",
2662           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2663         },
2664         {&hf_bundle_cosflags,
2665          {"Primary Header COS Flags", "bundle.primary.cos.flags",
2666           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2667         },
2668         {&hf_bundle_cosflags_priority,
2669          {"Priority", "bundle.primary.cos.priority",
2670           FT_UINT8, BASE_DEC, VALS(cosflags_priority_vals), BUNDLE_COSFLAGS_PRIORITY_MASK, NULL, HFILL}
2671         },
2672         {&hf_bundle_srrflags,
2673          {"Primary Header Report Request Flags", "bundle.primary.srr.flag",
2674           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2675         },
2676         {&hf_bundle_srrflags_report_receipt,
2677          {"Request Reception Report", "bundle.primary.srr.report",
2678           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_REPORT_MASK, NULL, HFILL}
2679         },
2680         {&hf_bundle_srrflags_report_cust_accept,
2681          {"Request Report of Custody Acceptance", "bundle.primary.srr.custaccept",
2682           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_CUSTODY_MASK, NULL, HFILL}
2683         },
2684         {&hf_bundle_srrflags_report_forward,
2685          {"Request Report of Bundle Forwarding", "bundle.primary.srr.forward",
2686           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_FORWARD_MASK, NULL, HFILL}
2687         },
2688         {&hf_bundle_srrflags_report_delivery,
2689          {"Request Report of Bundle Delivery", "bundle.primary.srr.delivery",
2690           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELIVERY_MASK, NULL, HFILL}
2691         },
2692         {&hf_bundle_srrflags_report_deletion,
2693          {"Request Report of Bundle Deletion", "bundle.primary.srr.delete",
2694           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELETION_MASK, NULL, HFILL}
2695         },
2696         {&hf_bundle_srrflags_report_ack,
2697          {"Request Report of Application Ack", "bundle.primary.srr.ack",
2698           FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_ACK_MASK, NULL, HFILL}
2699         },
2700         {&hf_bundle_primary_header_len,
2701          {"Bundle Header Length", "bundle.primary.len",
2702           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2703         },
2704         {&hf_bundle_primary_dictionary_len,
2705          {"Dictionary Length", "bundle.primary.dictionary_len",
2706           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2707         },
2708         {&hf_bundle_primary_fragment_offset,
2709          {"Fragment Offset", "bundle.primary.fragment_offset",
2710           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2711         },
2712         {&hf_bundle_primary_total_adu_len,
2713          {"Total Application Data Unit Length", "bundle.primary.total_adu_len",
2714           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2715         },
2716         {&hf_bundle_primary_timestamp_seq_num64,
2717          {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num",
2718           FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
2719         },
2720         {&hf_bundle_primary_timestamp_seq_num32,
2721          {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num",
2722           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2723         },
2724         {&hf_bundle_primary_timestamp,
2725          {"Timestamp", "bundle.primary.timestamp",
2726           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2727         },
2728         {&hf_bundle_dest_scheme_offset_u16,
2729          {"Destination Scheme Offset", "bundle.primary.destschemeoff",
2730           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2731         },
2732         {&hf_bundle_dest_scheme_offset_i32,
2733          {"Destination Scheme Offset", "bundle.primary.destschemeoff",
2734           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2735         },
2736         {&hf_bundle_dest_ssp_offset_u16,
2737          {"Destination SSP Offset", "bundle.primary.destssspoff",
2738           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2739         },
2740         {&hf_bundle_dest_ssp_offset_i32,
2741          {"Destination SSP Offset", "bundle.primary.destssspoff",
2742           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2743         },
2744         {&hf_bundle_source_scheme_offset_u16,
2745          {"Source Scheme Offset", "bundle.primary.srcschemeoff",
2746           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2747         },
2748         {&hf_bundle_source_scheme_offset_i32,
2749          {"Source Scheme Offset", "bundle.primary.srcschemeoff",
2750           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2751         },
2752         {&hf_bundle_source_ssp_offset_u16,
2753          {"Source SSP Offset", "bundle.primary.srcsspoff",
2754           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2755         },
2756         {&hf_bundle_source_ssp_offset_i32,
2757          {"Source SSP Offset", "bundle.primary.srcsspoff",
2758           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2759         },
2760         {&hf_bundle_report_scheme_offset_u16,
2761          {"Report Scheme Offset", "bundle.primary.rptschemeoff",
2762           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2763         },
2764         {&hf_bundle_report_scheme_offset_i32,
2765          {"Report Scheme Offset", "bundle.primary.rptschemeoff",
2766           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2767         },
2768         {&hf_bundle_report_ssp_offset_u16,
2769          {"Report SSP Offset", "bundle.primary.rptsspoff",
2770           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2771         },
2772         {&hf_bundle_report_ssp_offset_i32,
2773          {"Report SSP Offset", "bundle.primary.rptsspoff",
2774           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2775         },
2776         {&hf_bundle_cust_scheme_offset_u16,
2777          {"Custodian Scheme Offset", "bundle.primary.custschemeoff",
2778           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2779         },
2780         {&hf_bundle_cust_scheme_offset_i32,
2781          {"Custodian Scheme Offset", "bundle.primary.custschemeoff",
2782           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2783         },
2784         {&hf_bundle_cust_ssp_offset_u16,
2785          {"Custodian SSP Offset", "bundle.primary.custsspoff",
2786           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2787         },
2788         {&hf_bundle_cust_ssp_offset_i32,
2789          {"Custodian SSP Offset", "bundle.primary.custsspoff",
2790           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2791         },
2792         {&hf_bundle_dest_scheme,
2793          {"Destination Scheme", "bundle.primary.destination_scheme",
2794           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2795         },
2796         {&hf_bundle_dest_ssp,
2797          {"Destination", "bundle.primary.destination",
2798           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2799         },
2800         {&hf_bundle_source_scheme,
2801          {"Source Scheme", "bundle.primary.source_scheme",
2802           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2803         },
2804         {&hf_bundle_source_ssp,
2805          {"Source", "bundle.primary.source",
2806           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2807         },
2808         {&hf_bundle_report_scheme,
2809          {"Report Scheme", "bundle.primary.report_scheme",
2810           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2811         },
2812         {&hf_bundle_report_ssp,
2813          {"Report", "bundle.primary.report",
2814           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2815         },
2816         {&hf_bundle_custodian_scheme,
2817          {"Custodian Scheme", "bundle.primary.custodian_scheme",
2818           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2819         },
2820         {&hf_bundle_custodian_ssp,
2821          {"Custodian", "bundle.primary.custodian",
2822           FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
2823         },
2824         {&hf_bundle_creation_timestamp,
2825          {"Creation Timestamp", "bundle.primary.creation_timestamp",
2826           FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2827         },
2828         {&hf_bundle_lifetime,
2829          {"Lifetime", "bundle.primary.lifetime",
2830           FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2831         },
2832         {&hf_bundle_lifetime_sdnv,
2833          {"Lifetime", "bundle.primary.lifetime",
2834           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2835         },
2836         {&hf_bundle_payload_length,
2837          {"Payload Length", "bundle.payload.length",
2838           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2839         },
2840         {&hf_bundle_payload_flags,
2841          {"Payload Header Processing Flags", "bundle.payload.proc.flag",
2842           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2843         },
2844         {&hf_bundle_payload_header_type,
2845          {"Header Type", "bundle.payload.proc.header_type",
2846           FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
2847         },
2848         {&hf_bundle_payload_data,
2849          {"Payload Data", "bundle.payload.data",
2850           FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
2851         },
2852         {&hf_bundle_payload_flags_replicate_hdr,
2853          {"Replicate Header in Every Fragment", "bundle.payload.proc.replicate",
2854           FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_REPLICATE_MASK, NULL, HFILL}
2855         },
2856         {&hf_bundle_payload_flags_xmit_report,
2857          {"Report if Can't Process Header", "bundle.payload.proc.report",
2858           FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_XMIT_STATUS, NULL, HFILL}
2859         },
2860         {&hf_bundle_payload_flags_discard_on_fail,
2861          {"Discard if Can't Process Header", "bundle.payload.proc.discard",
2862           FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_DISCARD_FAILURE, NULL, HFILL}
2863         },
2864         {&hf_bundle_payload_flags_last_header,
2865          {"Last Header", "bundle.payload.proc.lastheader",
2866           FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_LAST_HEADER, NULL, HFILL}
2867         },
2868         {&hf_bundle_admin_record_type,
2869          {"Administrative Record Type", "bundle.admin.record_type",
2870           FT_UINT8, BASE_DEC, VALS(admin_record_type_vals), 0xF0, NULL, HFILL}
2871         },
2872         {&hf_bundle_admin_record_fragment,
2873          {"Administrative Record for Fragment", "bundle.admin.record_fragment",
2874           FT_BOOLEAN, 8, TFS(&tfs_yes_no), ADMIN_REC_FLAGS_FRAGMENT, NULL, HFILL}
2875         },
2876         {&hf_bundle_admin_statflags,
2877          {"Administrative Record Status Flags", "bundle.admin.status.flag",
2878           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2879         },
2880         {&hf_bundle_admin_rcvd,
2881          {"Reporting Node Received Bundle", "bundle.admin.status.rcvd",
2882           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_RECEIVED, NULL, HFILL}
2883         },
2884         {&hf_bundle_admin_accepted,
2885          {"Reporting Node Accepted Custody", "bundle.admin.status.accept",
2886           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACCEPTED, NULL, HFILL}
2887         },
2888         {&hf_bundle_admin_forwarded,
2889          {"Reporting Node Forwarded Bundle", "bundle.admin.status.forward",
2890           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_FORWARDED, NULL, HFILL}
2891         },
2892         {&hf_bundle_admin_delivered,
2893          {"Reporting Node Delivered Bundle", "bundle.admin.status.delivered",
2894           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELIVERED, NULL, HFILL}
2895         },
2896         {&hf_bundle_admin_deleted,
2897          {"Reporting Node Deleted Bundle", "bundle.admin.status.delete",
2898           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELETED, NULL, HFILL}
2899         },
2900         {&hf_bundle_admin_acked,
2901          {"Acknowledged by Application", "bundle.admin.status.ack",
2902           FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACKNOWLEDGED, NULL, HFILL}
2903         },
2904         {&hf_bundle_admin_fragment_offset,
2905          {"Fragment Offset", "bundle.admin.fragment_offset",
2906           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2907         },
2908         {&hf_bundle_admin_fragment_length,
2909          {"Fragment Length", "bundle.admin.fragment_length",
2910           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2911         },
2912         {&hf_bundle_admin_timestamp_seq_num64,
2913          {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num",
2914           FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
2915         },
2916         {&hf_bundle_admin_timestamp_seq_num32,
2917          {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num",
2918           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2919         },
2920         {&hf_bundle_admin_endpoint_length,
2921          {"Endpoint Length", "bundle.admin.endpoint_length",
2922           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2923         },
2924         {&hf_bundle_admin_endpoint_id,
2925          {"Bundle Endpoint ID", "bundle.admin.endpoint_id",
2926           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2927         },
2928         {&hf_bundle_admin_receipt_time,
2929          {"Bundle Received Time", "bundle.admin.status.receipttime",
2930           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2931         },
2932         {&hf_bundle_admin_accept_time,
2933          {"Bundle Accepted Time", "bundle.admin.status.accepttime",
2934           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2935         },
2936         {&hf_bundle_admin_forward_time,
2937          {"Bundle Forwarded Time", "bundle.admin.status.forwardtime",
2938           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2939         },
2940         {&hf_bundle_admin_delivery_time,
2941          {"Bundle Delivered Time", "bundle.admin.status.deliverytime",
2942           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2943         },
2944         {&hf_bundle_admin_delete_time,
2945          {"Bundle Deleted Time", "bundle.admin.status.deletetime",
2946           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2947         },
2948         {&hf_bundle_admin_ack_time,
2949          {"Bundle Acknowledged Time", "bundle.admin.status.acktime",
2950           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2951         },
2952         {&hf_bundle_admin_timestamp_copy,
2953          {"Bundle Creation Timestamp", "bundle.admin.status.timecopy",
2954           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2955         },
2956         {&hf_bundle_admin_signal_time,
2957          {"Bundle Signal Time", "bundle.admin.signal.time",
2958           FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
2959         },
2960         {&hf_block_control_flags,
2961          {"Block Processing Control Flags", "bundle.block.control.flags",
2962           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2963         },
2964         {&hf_block_control_flags_sdnv,
2965          {"Block Processing Control Flags", "bundle.block.control.flags",
2966           FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
2967         },
2968         {&hf_block_control_block_length,
2969          {"Block Length", "bundle.block.length",
2970           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2971         },
2972         {&hf_block_control_block_cteb_custody_id,
2973          {"CTEB Custody ID", "bundle.block.cteb_custody_id",
2974           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2975         },
2976         {&hf_block_control_block_cteb_creator_custodian_eid,
2977          {"CTEB Creator Custodian EID", "bundle.block.cteb_creator_custodian_eid",
2978           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2979         },
2980         {&hf_block_control_replicate,
2981          {"Replicate Block in Every Fragment", "bundle.block.control.replicate",
2982           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_REPLICATE, NULL, HFILL}
2983         },
2984         {&hf_block_control_transmit_status,
2985          {"Transmit Status if Block Can't be Processeed", "bundle.block.control.status",
2986           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_TRANSMIT_STATUS, NULL, HFILL}
2987         },
2988         {&hf_block_control_delete_bundle,
2989          {"Delete Bundle if Block Can't be Processeed", "bundle.block.control.delete",
2990           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DELETE_BUNDLE, NULL, HFILL}
2991         },
2992         {&hf_block_control_last_block,
2993          {"Last Block", "bundle.block.control.last",
2994           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_LAST_BLOCK, NULL, HFILL}
2995         },
2996         {&hf_block_control_discard_block,
2997          {"Discard Block If Can't Process", "bundle.block.control.discard",
2998           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DISCARD_BLOCK, NULL, HFILL}
2999         },
3000         {&hf_block_control_not_processed,
3001          {"Block Was Forwarded Without Processing", "bundle.block.control.process",
3002           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_NOT_PROCESSED, NULL, HFILL}
3003         },
3004         {&hf_block_control_eid_reference,
3005          {"Block Contains an EID-reference Field", "bundle.block.control.eid",
3006           FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_EID_REFERENCE, NULL, HFILL}
3007         },
3008         {&hf_bundle_status_report_reason_code,
3009          {"Status Report Reason Code", "bundle.status_report_reason_code",
3010           FT_UINT8, BASE_DEC, VALS(status_report_reason_codes), 0x0, NULL, HFILL}
3011         },
3012         {&hf_bundle_custody_trf_succ_flg,
3013          {"Custody Transfer Succeeded Flag", "bundle.custody_trf_succ_flg",
3014           FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}
3015         },
3016         {&hf_bundle_custody_signal_reason,
3017          {"Custody Signal Reason Code", "bundle.custody_signal_reason_code",
3018           FT_UINT8, BASE_DEC, VALS(custody_signal_reason_codes), ADMIN_REC_CUSTODY_REASON_MASK, NULL, HFILL}
3019         },
3020         {&hf_bundle_custody_id_range_start,
3021          {"CTEB Custody ID Range Start", "bundle.custody_id_range_start",
3022           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3023         },
3024         {&hf_bundle_custody_id_range_end,
3025          {"CTEB Custody ID Range End", "bundle.custody_id_range_end",
3026           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3027         },
3028         {&hf_bundle_block_type_code,
3029          {"Block Type Code", "bundle.block_type_code",
3030           FT_UINT8, BASE_DEC, VALS(bundle_block_type_codes), 0x0, NULL, HFILL}
3031         },
3032         {&hf_bundle_unprocessed_block_data,
3033          {"Block Data", "bundle.block_data",
3034           FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
3035         },
3036         {&hf_ecos_flags,
3037          {"ECOS Flags", "bundle.block.ecos.flags",
3038           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
3039         },
3040         {&hf_ecos_flags_critical,
3041          {"Critical", "bundle.block.ecos.flags.critical",
3042           FT_BOOLEAN, 8, NULL, ECOS_FLAGS_CRITICAL, NULL, HFILL}
3043         },
3044         {&hf_ecos_flags_streaming,
3045          {"Streaming", "bundle.block.ecos.flags.streaming",
3046           FT_BOOLEAN, 8, NULL, ECOS_FLAGS_STREAMING, NULL, HFILL}
3047         },
3048         {&hf_ecos_flags_flowlabel,
3049          {"Flow Label", "bundle.block.ecos.flags.flowlabel",
3050           FT_BOOLEAN, 8, NULL, ECOS_FLAGS_FLOWLABEL, NULL, HFILL}
3051         },
3052         {&hf_ecos_flags_reliable,
3053          {"Reliable", "bundle.block.ecos.flags.reliable",
3054           FT_BOOLEAN, 8, NULL, ECOS_FLAGS_RELIABLE, NULL, HFILL}
3055         },
3056         {&hf_ecos_flow_label,
3057          {"ECOS Flow Label", "bundle.block.ecos.flow_label",
3058           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3059         },
3060         {&hf_ecos_ordinal,
3061          {"ECOS Ordinal", "bundle.block.ecos.ordinal",
3062           FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3063         },
3064         {&hf_bundle_age_extension_block_code,
3065          {"Bundle Age in seconds", "bundle.age_extension_block_code",
3066           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3067         },
3068         {&hf_bundle_block_previous_hop_scheme,
3069          {"Previous Hop Secheme", "bundle.block.previous_hop_scheme",
3070           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
3071         },
3072         {&hf_bundle_block_previous_hop_eid,
3073          {"Previous Hop EID", "bundle.block.previous_hop_eid",
3074           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
3075         },
3076         {&hf_bundle_target_block_type,
3077          {"Target Block Type", "bundle.target_block_type",
3078           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3079         },
3080         {&hf_bundle_target_block_occurance,
3081          {"Target Block Occurance", "bundle.target_block_occurance",
3082           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3083         },
3084         {&hf_bundle_ciphersuite_type,
3085          {"Ciphersuite Type", "bundle.ciphersuite_type",
3086           FT_INT32, BASE_DEC, VALS(ciphersuite_types), 0x0, NULL, HFILL}
3087         },
3088         {&hf_bundle_ciphersuite_flags,
3089          {"Ciphersuite Flags", "bundle.ciphersuite_flags",
3090           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
3091         },
3092         {&hf_block_ciphersuite_params,
3093          {"Block Contains Ciphersuite Parameters", "bundle.block.ciphersuite_params",
3094           FT_BOOLEAN, 8, NULL, BLOCK_CIPHERSUITE_PARAMS, NULL, HFILL}
3095         },
3096         {&hf_block_ciphersuite_params_length,
3097          {"Ciphersuite Parameters Length", "bundle.block.ciphersuite_params_length",
3098           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3099         },
3100         {&hf_block_ciphersuite_params_item_length,
3101          {"Parameter Length", "bundle.block.ciphersuite_params_item_length",
3102           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3103         },
3104         {&hf_block_ciphersuite_param_type,
3105          {"Ciphersuite Parameter Type", "bundle.block.ciphersuite_param_type",
3106           FT_INT8, BASE_DEC, VALS(res_params_types), 0x0, NULL, HFILL}
3107         },
3108         {&hf_block_ciphersuite_param_data,
3109          {"Ciphersuite Parameter Data", "bundle.block.ciphersuite_param_data",
3110           FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
3111         },
3112         {&hf_block_ciphersuite_result_length,
3113          {"Security Results Length", "bundle.block.ciphersuite_result_length",
3114           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3115         },
3116         {&hf_block_ciphersuite_result_item_length,
3117          {"Security Result Item Length", "bundle.block.ciphersuite_result_item_length",
3118           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3119         },
3120         {&hf_block_ciphersuite_result_type,
3121          {"Security Result Item Type", "bundle.block.ciphersuite_result_type",
3122           FT_INT8, BASE_DEC, VALS(res_params_types), 0x0, NULL, HFILL}
3123         },
3124         {&hf_block_ciphersuite_result_data,
3125          {"Security Result Item Data", "bundle.block.ciphersuite_result_data",
3126           FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
3127         },
3128         {&hf_block_ciphersuite_range_offset,
3129          {"Content Range Offset", "bundle.block.ciphersuite_range_offset",
3130           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3131         },
3132         {&hf_block_ciphersuite_range_length,
3133          {"Content Range Length", "bundle.block.ciphersuite_range_length",
3134           FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3135         },
3136     };
3137
3138     static hf_register_info hf_tcpcl[] = {
3139         {&hf_tcp_convergence_pkt_type,
3140          {"Pkt Type", "tcpcl.pkt_type",
3141           FT_UINT8, BASE_DEC, VALS(packet_type_vals), 0xF0, NULL, HFILL}
3142         },
3143         {&hf_tcp_convergence_data_procflags,
3144          {"TCP Convergence Data Flags", "tcpcl.data.proc.flag",
3145           FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_DATA_FLAGS, NULL, HFILL}
3146         },
3147         {&hf_tcp_convergence_data_procflags_start,
3148          {"Segment contains start of bundle", "tcpcl.data.proc.start",
3149           FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_START_FLAG, NULL, HFILL}
3150         },
3151         {&hf_tcp_convergence_data_procflags_end,
3152          {"Segment contains end of Bundle", "tcpcl.data.proc.end",
3153           FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_END_FLAG, NULL, HFILL}
3154         },
3155         {&hf_tcp_convergence_data_segment_length,
3156          {"Segment Length", "tcpcl.data.length",
3157           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3158         },
3159         {&hf_tcp_convergence_shutdown_flags,
3160          {"TCP Convergence Shutdown Flags", "tcpcl.shutdown.flags",
3161           FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_SHUTDOWN_FLAGS, NULL, HFILL}
3162         },
3163         {&hf_tcp_convergence_shutdown_flags_reason,
3164          {"Shutdown includes Reason Code", "tcpcl.shutdown.reason.flag",
3165           FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_REASON, NULL, HFILL}
3166         },
3167         {&hf_tcp_convergence_shutdown_flags_delay,
3168          {"Shutdown includes Reconnection Delay", "tcpcl.shutdown.delay.flag",
3169           FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_DELAY, NULL, HFILL}
3170         },
3171         {&hf_tcp_convergence_shutdown_reason,
3172          {"Shutdown Reason Code", "tcpcl.shutdown.reason",
3173           FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3174         },
3175         {&hf_tcp_convergence_shutdown_delay,
3176          {"Shutdown Reconnection Delay", "tcpcl.shutdown.delay",
3177           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
3178         },
3179         {&hf_tcp_convergence_ack_length,
3180          {"Ack Length", "tcpcl.ack.length",
3181           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3182         },
3183         {&hf_contact_hdr_version,
3184          {"Version", "tcpcl.contact_hdr.version",
3185           FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
3186         },
3187         {&hf_contact_hdr_flags,
3188          {"Flags", "tcpcl.contact_hdr.flags",
3189           FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
3190         },
3191         {&hf_contact_hdr_flags_ack_req,
3192          {"Bundle Acks Requested", "tcpcl.contact_hdr.flags.ackreq",
3193           FT_BOOLEAN, 8, NULL, TCP_CONV_BUNDLE_ACK_FLAG, NULL, HFILL}
3194         },
3195         {&hf_contact_hdr_flags_frag_enable,
3196          {"Reactive Fragmentation Enabled", "tcpcl.contact_hdr.flags.fragen",
3197           FT_BOOLEAN, 8, NULL, TCP_CONV_REACTIVE_FRAG_FLAG, NULL, HFILL}
3198         },
3199         {&hf_contact_hdr_flags_nak,
3200          {"Support Negative Acknowledgements", "tcpcl.contact_hdr.flags.nak",
3201           FT_BOOLEAN, 8, NULL, TCP_CONV_CONNECTOR_RCVR_FLAG, NULL, HFILL}
3202         },
3203         {&hf_contact_hdr_keep_alive,
3204          {"Keep Alive", "tcpcl.contact_hdr.keep_alive",
3205           FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
3206         },
3207         {&hf_contact_hdr_magic,
3208          {"Magic", "tcpcl.contact_hdr.magic",
3209           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
3210         },
3211         {&hf_contact_hdr_local_eid,
3212          {"Local EID", "tcpcl.contact_hdr.local_eid",
3213           FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
3214         },
3215         {&hf_contact_hdr_local_eid_length,
3216          {"Local EID Length", "tcpcl.contact_hdr.local_eid_length",
3217           FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
3218         },
3219     };
3220
3221     static gint *ett[] = {
3222         &ett_bundle,
3223         &ett_bundle_hdr,
3224         &ett_primary_hdr,
3225         &ett_proc_flags,
3226         &ett_gen_flags,
3227         &ett_cos_flags,
3228         &ett_srr_flags,
3229         &ett_dictionary,
3230         &ett_payload_hdr,
3231         &ett_payload_flags,
3232         &ett_block_flags,
3233         &ett_contact_hdr_flags,
3234         &ett_conv_flags,
3235         &ett_shutdown_flags,
3236         &ett_admin_record,
3237         &ett_admin_rec_status,
3238         &ett_metadata_hdr,
3239         &ett_sec_block_param_data
3240     };
3241
3242     static gint *ett_tcpcl[] = {
3243         &ett_tcp_conv,
3244         &ett_tcp_conv_hdr,
3245         &ett_msg_fragment,
3246         &ett_msg_fragments,
3247     };
3248
3249     static ei_register_info ei[] = {
3250         { &ei_bundle_control_flags_length,
3251           { "bundle.block.control.flags.length", PI_UNDECODED, PI_WARN, "Wrong bundle control flag length", EXPFILL }
3252         },
3253         { &ei_bundle_payload_length,
3254           { "bundle.payload.length.invalid", PI_PROTOCOL, PI_ERROR, "Payload length error", EXPFILL }
3255         },
3256         { &ei_bundle_sdnv_length,
3257           { "bundle.sdnv_length_invalid", PI_PROTOCOL, PI_ERROR, "SDNV length error", EXPFILL }
3258         },
3259         { &ei_bundle_timestamp_seq_num,
3260           { "bundle.timestamp_seq_num_invalid", PI_PROTOCOL, PI_ERROR, "Timestamp Sequence Number error", EXPFILL }
3261         },
3262         { &ei_bundle_offset_error,
3263           { "bundle.offset_error", PI_PROTOCOL, PI_WARN, "Offset field error", EXPFILL }
3264         },
3265         { &ei_bundle_block_control_flags,
3266           { "bundle.block.control.flags.error", PI_PROTOCOL, PI_WARN, "Control flag error", EXPFILL }
3267         },
3268         { &ei_block_control_block_cteb_invalid,
3269           { "bundle.block.control.cteb_invalid", PI_PROTOCOL, PI_WARN, "CTEB Is Invalid", EXPFILL }
3270         },
3271         { &ei_block_control_block_cteb_valid,
3272           { "bundle.block.control.cteb_valid", PI_PROTOCOL, PI_NOTE, "CTEB Is Valid", EXPFILL }
3273         },
3274     };
3275
3276     static ei_register_info ei_tcpcl[] = {
3277         { &ei_tcp_convergence_data_flags,
3278           { "tcpcl.data.flags.invalid", PI_PROTOCOL, PI_WARN, "Invalid TCP CL Data Segment Flags", EXPFILL }
3279         },
3280         { &ei_tcp_convergence_segment_length,
3281           { "tcpcl.data.length.invalid", PI_PROTOCOL, PI_ERROR, "Invalid Data Length", EXPFILL }
3282         },
3283         { &ei_tcp_convergence_ack_length,
3284           { "tcpcl.ack.length.error", PI_PROTOCOL, PI_WARN, "Ack Length: Error", EXPFILL }
3285         },
3286     };
3287
3288     expert_module_t *expert_bundle, *expert_tcpcl;
3289
3290     proto_bundle  = proto_register_protocol("Bundle Protocol", "Bundle", "bundle");
3291     bundle_handle = register_dissector("bundle", dissect_bundle, proto_bundle);
3292
3293     proto_tcp_conv = proto_register_protocol ("DTN TCP Convergence Layer Protocol", "TCPCL", "tcpcl");
3294
3295     proto_register_field_array(proto_bundle, hf, array_length(hf));
3296     proto_register_subtree_array(ett, array_length(ett));
3297     expert_bundle = expert_register_protocol(proto_bundle);
3298     expert_register_field_array(expert_bundle, ei, array_length(ei));
3299
3300     proto_register_field_array(proto_tcp_conv, hf_tcpcl, array_length(hf_tcpcl));
3301     proto_register_subtree_array(ett_tcpcl, array_length(ett_tcpcl));
3302     expert_tcpcl = expert_register_protocol(proto_tcp_conv);
3303     expert_register_field_array(expert_tcpcl, ei_tcpcl, array_length(ei_tcpcl));
3304
3305     reassembly_table_register(&msg_reassembly_table,
3306                           &addresses_reassembly_table_functions);
3307
3308 }
3309
3310 void
3311 proto_reg_handoff_bundle(void)
3312 {
3313     dissector_handle_t tcpcl_handle;
3314
3315     tcpcl_handle = create_dissector_handle(dissect_tcpcl, proto_bundle);
3316     dissector_add_uint_with_preference("tcp.port", BUNDLE_PORT, tcpcl_handle);
3317     dissector_add_uint_with_preference("udp.port", BUNDLE_PORT, bundle_handle);
3318 }
3319
3320 /*
3321  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
3322  *
3323  * Local variables:
3324  * c-basic-offset: 4
3325  * tab-width: 8
3326  * indent-tabs-mode: nil
3327  * End:
3328  *
3329  * vi: set shiftwidth=4 tabstop=8 expandtab:
3330  * :indentSize=4:tabSize=8:noTabs=true:
3331  */