2 * Copyright 2006-2007 The MITRE Corporation.
4 * Approved for Public Release; Distribution Unlimited.
5 * Tracking Number 07-0090.
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.
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include <epan/packet.h>
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
44 #include "packet-dtn.h"
46 void proto_reg_handoff_bundle(void);
47 static void dissect_tcp_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
48 static void dissect_udp_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
49 static int dissect_complete_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
50 static int dissect_primary_header(packet_info *pinfo, proto_tree *primary_tree, tvbuff_t *tvb);
51 static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, int offset);
52 static int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount);
53 static gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
54 static int dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, int bundle_offset, int *lastheader);
55 static int display_metadata_block(proto_tree *tree, tvbuff_t *tvb, int bundle_offset, int *lastheader);
56 static int dissect_contact_header(tvbuff_t *tvb, packet_info *pinfo,
57 proto_tree *conv_tree, proto_item *conv_item);
58 static int dissect_tcp_convergence_data_header(tvbuff_t *tvb, proto_tree *tree);
59 static int dissect_version_5_primary_header(packet_info *pinfo,
60 proto_tree *primary_tree, tvbuff_t *tvb);
61 static int add_sdnv_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id);
62 static int add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id);
63 static int add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id);
65 /* For Reassembling TCP Convergence Layer segments */
66 static GHashTable *msg_fragment_table = NULL;
67 static GHashTable *msg_reassembled_table = NULL;
69 static int segment_length;
70 static int bundle_header_length;
71 static int bundle_header_dict_length;
73 static char magic[] = {'d', 't', 'n', '!'};
75 static int proto_bundle = -1;
76 static int proto_tcp_conv = -1;
77 static int hf_bundle_pdu_version = -1;
79 /* TCP Convergence Header Variables */
80 static int hf_contact_hdr_version = -1;
81 static int hf_contact_hdr_flags = -1;
82 static int hf_contact_hdr_keep_alive = -1;
83 static int hf_contact_hdr_flags_ack_req = -1;
84 static int hf_contact_hdr_flags_frag_enable = -1;
85 static int hf_contact_hdr_flags_nak = -1;
87 /* TCP Convergence Data Header Variables */
88 static int hf_tcp_convergence_data_procflags = -1;
89 static int hf_tcp_convergence_data_procflags_start = -1;
90 static int hf_tcp_convergence_data_procflags_end = -1;
92 /* TCP Convergence Shutdown Header Variables */
93 static int hf_tcp_convergence_shutdown_flags = -1;
94 static int hf_tcp_convergence_shutdown_flags_reason = -1;
95 static int hf_tcp_convergence_shutdown_flags_delay = -1;
96 static int hf_tcp_convergence_shutdown_reason = -1;
97 static int hf_tcp_convergence_shutdown_delay = -1;
99 /*TCP Convergence Layer Reassembly boilerplate*/
100 static int hf_msg_fragments = -1;
101 static int hf_msg_fragment = -1;
102 static int hf_msg_fragment_overlap = -1;
103 static int hf_msg_fragment_overlap_conflicts = -1;
104 static int hf_msg_fragment_multiple_tails = -1;
105 static int hf_msg_fragment_too_long_fragment = -1;
106 static int hf_msg_fragment_error = -1;
107 static int hf_msg_reassembled_in = -1;
109 /* Primary Header Processing Flag Variables */
110 static guint8 pri_hdr_procflags; /*This is global to allow processing Payload Header*/
111 static int hf_bundle_procflags = -1;
112 static int hf_bundle_procflags_fragment = -1;
113 static int hf_bundle_procflags_admin = -1;
114 static int hf_bundle_procflags_dont_fragment = -1;
115 static int hf_bundle_procflags_cust_xfer_req = -1;
116 static int hf_bundle_procflags_dest_singleton = -1;
117 static int hf_bundle_procflags_application_ack = -1;
119 /* Additions for Version 5 */
120 static int hf_bundle_control_flags = -1;
121 static int hf_bundle_procflags_general = -1;
122 static int hf_bundle_procflags_cos = -1;
123 static int hf_bundle_procflags_status = -1;
125 /* Primary Header COS Flag Variables */
126 static int hf_bundle_cosflags = -1;
127 static int hf_bundle_cosflags_priority = -1;
129 /* Primary Header Status Report Request Flag Variables */
130 static int hf_bundle_srrflags = -1;
131 static int hf_bundle_srrflags_report_receipt = -1;
132 static int hf_bundle_srrflags_report_cust_accept = -1;
133 static int hf_bundle_srrflags_report_forward = -1;
134 static int hf_bundle_srrflags_report_delivery = -1;
135 static int hf_bundle_srrflags_report_deletion = -1;
136 static int hf_bundle_srrflags_report_ack = -1;
138 /* Primary Header Length Fields*/
139 static int hf_bundle_primary_header_len = -1;
140 static int hf_bundle_dest_scheme_offset = -1;
141 static int hf_bundle_dest_ssp_offset = -1;
142 static int hf_bundle_source_scheme_offset = -1;
143 static int hf_bundle_source_ssp_offset = -1;
144 static int hf_bundle_report_scheme_offset = -1;
145 static int hf_bundle_report_ssp_offset = -1;
146 static int hf_bundle_cust_scheme_offset = -1;
147 static int hf_bundle_cust_ssp_offset = -1;
149 /* Dictionary EIDs */
150 static int hf_bundle_dest_scheme = -1;
151 static int hf_bundle_dest_ssp = -1;
152 static int hf_bundle_source_scheme = -1;
153 static int hf_bundle_source_ssp = -1;
154 static int hf_bundle_report_scheme = -1;
155 static int hf_bundle_report_ssp = -1;
156 static int hf_bundle_custodian_scheme = -1;
157 static int hf_bundle_custodian_ssp = -1;
159 /* Remaining Primary Header Fields */
160 static int hf_bundle_creation_timestamp = -1;
161 static int hf_bundle_lifetime = -1;
163 /* Secondary Header Processing Flag Variables */
164 static int hf_bundle_payload_flags = -1;
165 static int hf_bundle_payload_flags_replicate_hdr = -1;
166 static int hf_bundle_payload_flags_xmit_report = -1;
167 static int hf_bundle_payload_flags_discard_on_fail = -1;
168 static int hf_bundle_payload_flags_last_header = -1;
170 /* Block Processing Control Flag Variables (Version 5) */
171 static int hf_block_control_flags = -1;
172 static int hf_block_control_replicate = -1;
173 static int hf_block_control_transmit_status = -1;
174 static int hf_block_control_delete_bundle = -1;
175 static int hf_block_control_last_block = -1;
176 static int hf_block_control_discard_block = -1;
177 static int hf_block_control_not_processed = -1;
178 static int hf_block_control_eid_reference = -1;
180 /* Administrative Record Variables */
181 static int hf_bundle_admin_statflags = -1;
182 static int hf_bundle_admin_rcvd = -1;
183 static int hf_bundle_admin_accepted = -1;
184 static int hf_bundle_admin_forwarded = -1;
185 static int hf_bundle_admin_delivered = -1;
186 static int hf_bundle_admin_deleted = -1;
187 static int hf_bundle_admin_acked = -1;
188 static int hf_bundle_admin_receipt_time = -1;
189 static int hf_bundle_admin_accept_time = -1;
190 static int hf_bundle_admin_forward_time = -1;
191 static int hf_bundle_admin_delivery_time = -1;
192 static int hf_bundle_admin_delete_time = -1;
193 static int hf_bundle_admin_ack_time = -1;
194 static int hf_bundle_admin_timestamp_copy = -1;
195 static int hf_bundle_admin_signal_time = -1;
197 /* Tree Node Variables */
198 static gint ett_bundle = -1;
199 static gint ett_tcp_conv = -1;
200 static gint ett_tcp_conv_hdr = -1;
201 static gint ett_conv_flags = -1;
202 static gint ett_shutdown_flags = -1;
203 static gint ett_msg_fragment = -1;
204 static gint ett_msg_fragments = -1;
205 static gint ett_bundle_hdr = -1;
206 static gint ett_primary_hdr = -1;
207 static gint ett_proc_flags = -1;
208 static gint ett_gen_flags = -1;
209 static gint ett_cos_flags = -1;
210 static gint ett_srr_flags = -1;
211 static gint ett_dictionary = -1;
212 static gint ett_payload_hdr = -1;
213 static gint ett_payload_flags = -1;
214 static gint ett_block_flags = -1;
215 static gint ett_contact_hdr_flags = -1;
216 static gint ett_admin_record = -1;
217 static gint ett_admin_rec_status = -1;
218 static gint ett_metadata_hdr = -1;
220 static guint bundle_tcp_port = 4556;
221 static guint bundle_udp_port = 4556;
223 /* Needed to allow entering port option */
224 static guint tcp_port = 0;
225 static guint udp_port = 0;
227 static const value_string custody_signal_reason_codes[] = {
228 {0x3, "Redundant Reception"},
229 {0x4, "Depleted Storage"},
230 {0x5, "Destination Endpoint ID Unintelligible"},
231 {0x6, "No Known Route to Destination"},
232 {0x7, "No Timely Contact with Next Node on Route"},
233 {0x8, "Header Unintelligible"},
237 static const value_string status_report_reason_codes[] = {
238 {0x1, "Lifetime Expired"},
239 {0x2, "Forwarded over Unidirectional Link"},
240 {0x3, "Transmission Cancelled"},
241 {0x4, "Depleted Storage"},
242 {0x5, "Destination Endpoint ID Unintelligible"},
243 {0x6, "No Known Route to Destination"},
244 {0x7, "No Timely Contact with Next Node on Route"},
245 {0x8, "Header Unintelligible"},
249 static const fragment_items msg_frag_items = {
250 /*Fragment subtrees*/
256 &hf_msg_fragment_overlap,
257 &hf_msg_fragment_overlap_conflicts,
258 &hf_msg_fragment_multiple_tails,
259 &hf_msg_fragment_too_long_fragment,
260 &hf_msg_fragment_error,
261 /*Reassembled in field*/
262 &hf_msg_reassembled_in,
268 static void dissect_tcp_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
271 proto_item *ti = NULL;
272 proto_tree *bundle_tree = NULL;
273 proto_item *ci = NULL;
274 proto_tree *conv_proto_tree = NULL;
275 int buffer_size; /*Number of bytes in buffer that can be processed*/
280 int frame_offset; /*To handle the case of > 1 bundle in an Ethernet Frame*/
281 int convergence_hdr_size;
285 buffer_size = tvb_reported_length(tvb);
287 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bundle");
288 col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */
290 while(frame_offset < buffer_size) {
292 fragment_data *frag_msg = NULL;
293 gboolean more_frags = TRUE;
295 conv_hdr = tvb_get_guint8(tvb, frame_offset);
296 if((conv_hdr & TCP_CONVERGENCE_TYPE_MASK) == TCP_CONVERGENCE_DATA_SEGMENT) {
298 /* Only Start and End flags (bits 0 & 1) are valid in Data Segment */
299 if((conv_hdr & ~(TCP_CONVERGENCE_TYPE_MASK | TCP_CONVERGENCE_DATA_FLAGS)) != 0) {
300 col_set_str(pinfo->cinfo, COL_INFO, "Invalid TCP CL Data Segment Flags");
304 segment_length = evaluate_sdnv(tvb, fixed + frame_offset, &sdnv_length);
305 if(segment_length < 0) {
306 col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error (Length)");
309 convergence_hdr_size = sdnv_length + fixed;
310 if((buffer_size - frame_offset - convergence_hdr_size) < segment_length) {
311 /*Segment not complete -- wait for the rest of it*/
312 pinfo->desegment_len =
313 segment_length - (buffer_size - frame_offset
314 - convergence_hdr_size);
315 pinfo->desegment_offset = frame_offset;
320 * 1/11/2006 - If I got here, I should have a complete convergence layer
321 * "segment" beginning at frame_offset. However that might not be a
322 * complete bundle. Or there might be a complete bundle plus one or more
323 * additional convergence layer headers.
327 if((conv_hdr & TCP_CONVERGENCE_DATA_END_FLAG) ==
328 TCP_CONVERGENCE_DATA_END_FLAG) {
334 ci = proto_tree_add_item(tree, proto_tcp_conv, tvb,
335 frame_offset, -1, FALSE);
336 conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv);
337 dissect_tcp_convergence_data_header(tvb, conv_proto_tree);
340 * Note: The reassembled bundle will only include the first
341 * Convergence layer header.
344 frag_msg = fragment_add_seq_next(tvb, frame_offset + convergence_hdr_size,
345 pinfo, 0, msg_fragment_table,
346 msg_reassembled_table, segment_length,
348 if(frag_msg && !more_frags) {
349 ti = proto_tree_add_item(tree, proto_bundle, tvb,
350 frame_offset, -1, FALSE);
351 bundle_tree = proto_item_add_subtree(ti, ett_bundle);
352 new_tvb = process_reassembled_data(tvb,
353 frame_offset + convergence_hdr_size,
354 pinfo, "Reassembled Message", frag_msg,
355 &msg_frag_items, NULL, bundle_tree);
358 bundle_size = dissect_complete_bundle(new_tvb, pinfo, bundle_tree);
359 if(bundle_size == 0) { /*Couldn't parse bundle*/
360 col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed");
367 * If there are 2 segments, the second of which is very short, this
368 * gets displayed instead of the usual Source EID/Destination EID in
369 * the Bundle Dissection frame. If these statements are left out entirely,
370 * nothing is displayed, i.e., there seems to be no way to get the
371 * Source/Destination in the 2-segment case. I'll leave it in because I
372 * think it is informative in the multi-segment case although confusing in the
376 col_set_str(pinfo->cinfo, COL_INFO, "[Reassembled Segment of a Bundle]");
380 * If we could be sure that the current tvb buffer ended with the CL segment,
381 * we could return here. But the buffer could contain multiple complete segments
382 * or bundles or a bundle plus other CL messages. In order to process whatever
383 * follow the current segment, we have to continue through the buffer until
384 * frame_offset indicates everything in the buffer has been processed.
387 frame_offset += (segment_length + convergence_hdr_size);
389 else { /*Else this is not a Data Segment*/
391 proto_item *conv_item = NULL;
392 proto_tree *conv_tree = NULL;
394 if(frame_offset == 0) {
395 ci = proto_tree_add_item(tree, proto_tcp_conv, tvb,
396 frame_offset, -1, FALSE);
397 conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv);
401 * Other Convergence Layer messages are short; assume they won't need
402 * reassembly. Start with the Convergence Layer Tree.
405 conv_item = proto_tree_add_text(conv_proto_tree, tvb, frame_offset, -1,
406 "TCP Convergence Header");
407 conv_tree = proto_item_add_subtree(conv_item, ett_tcp_conv_hdr);
409 if(conv_hdr == magic[0]) {
410 sptr = (char *) tvb_get_ephemeral_string(tvb, frame_offset, 4);
411 if(!memcmp(sptr, magic, 4)){
412 dissect_contact_header(tvb, pinfo, conv_tree, conv_item);
413 return; /*Assumes Contact Header is alone in segment*/
416 if(conv_hdr == TCP_CONVERGENCE_ACK_SEGMENT) { /*No valid flags in Ack*/
418 proto_item *ack_length_item = NULL;
420 proto_tree_add_text(conv_tree, tvb, frame_offset, 1, "Pkt Type: Ack");
422 ack_length = evaluate_sdnv(tvb, frame_offset + fixed, &sdnv_length);
423 ack_length_item = proto_tree_add_text(conv_tree, tvb,
424 frame_offset + fixed, sdnv_length, " ");
426 proto_item_set_text(ack_length_item, "Ack Length: Error");
429 proto_item_set_text(ack_length_item, "Ack Length: %d", ack_length);
430 /*return (sdnv_length + fixed);*/
431 frame_offset += (sdnv_length + fixed);
432 proto_item_set_len(conv_item, sdnv_length + fixed);
434 else if(conv_hdr == TCP_CONVERGENCE_KEEP_ALIVE) { /*No valid flags in Keep Alive*/
435 proto_item_set_len(conv_item, 1);
436 proto_tree_add_text(conv_tree, tvb, frame_offset, 1, "Pkt Type: Keep Alive");
439 else if((conv_hdr & TCP_CONVERGENCE_TYPE_MASK) ==
440 TCP_CONVERGENCE_SHUTDOWN) {
441 proto_item *shutdown_flag_item = NULL;
442 proto_tree *shutdown_flag_tree = NULL;
443 guint8 shutdown_flags;
444 proto_item *shutdown_reason_item = NULL;
445 proto_item *shutdown_delay_item = NULL;
449 ~(TCP_CONVERGENCE_TYPE_MASK || TCP_CONVERGENCE_SHUTDOWN_FLAGS)) != 0) {
450 proto_tree_add_text(conv_tree, tvb, frame_offset,
451 -1, "Invalid Convergence Layer Shutdown Packet");
454 proto_item_set_len(conv_item, 1);
455 proto_tree_add_text(conv_tree, tvb, 0, 1, "Pkt Type: Shutdown");
457 /* Add tree for Shutdown Flags */
458 shutdown_flags = conv_hdr;
459 shutdown_flag_item = proto_tree_add_item(conv_tree,
460 hf_tcp_convergence_shutdown_flags, tvb,
461 frame_offset, 1, FALSE);
462 shutdown_flag_tree = proto_item_add_subtree(shutdown_flag_item,
464 proto_tree_add_boolean(shutdown_flag_tree,
465 hf_tcp_convergence_shutdown_flags_reason,
466 tvb, frame_offset, 1, shutdown_flags);
467 proto_tree_add_boolean(shutdown_flag_tree,
468 hf_tcp_convergence_shutdown_flags_delay,
469 tvb, frame_offset, 1, shutdown_flags);
473 if(conv_hdr & TCP_CONVERGENCE_SHUTDOWN_REASON) {
474 shutdown_reason_item = proto_tree_add_item(conv_tree,
475 hf_tcp_convergence_shutdown_reason, tvb,
476 frame_offset, 1, FALSE);
480 if(conv_hdr & TCP_CONVERGENCE_SHUTDOWN_DELAY) {
481 shutdown_delay_item = proto_tree_add_item(conv_tree,
482 hf_tcp_convergence_shutdown_delay, tvb,
483 frame_offset, 2, FALSE);
487 proto_item_set_len(conv_item, field_length);
489 else if(conv_hdr == TCP_CONVERGENCE_REFUSE_BUNDLE) { /*No valid flags*/
490 proto_item_set_len(conv_item, 1);
491 proto_tree_add_text(conv_tree, tvb, frame_offset,
492 1, "Pkt Type: Refuse Bundle");
496 proto_tree_add_text(conv_tree, tvb, frame_offset,
497 -1, "Invalid/Partial Convergence Layer Packet");
506 dissect_udp_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
509 int buffer_size; /*Number of bytes in buffer that can be processed*/
512 guint8 next_header_type;
513 proto_item *ti = NULL;
514 proto_tree *bundle_tree = NULL;
515 proto_item *primary_item = NULL;
516 proto_tree *primary_tree = NULL;
518 buffer_size = tvb_reported_length_remaining(tvb, 0);
519 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bundle");
520 /* Clear out stuff in the info column */
521 col_clear(pinfo->cinfo,COL_INFO);
523 ti = proto_tree_add_item(tree, proto_bundle, tvb, 0, -1, FALSE);
524 bundle_tree = proto_item_add_subtree(ti, ett_bundle);
526 primary_item = proto_tree_add_text(bundle_tree, tvb, 0, -1,
527 "Primary Bundle Header");
528 primary_tree = proto_item_add_subtree(primary_item, ett_primary_hdr);
529 hdr_offset = dissect_primary_header(pinfo, primary_tree, tvb);
530 if(hdr_offset == 0) {
531 col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
534 proto_item_set_len(primary_item, hdr_offset);
537 * Done with primary header; decode the remaining headers
541 while((hdr_offset > 0) && (buffer_size > hdr_offset)) {
542 next_header_type = tvb_get_guint8(tvb, hdr_offset);
543 if(next_header_type == PAYLOAD_HEADER_TYPE) {
545 dissect_payload_header(bundle_tree, tvb, hdr_offset, &lasthdrflag);
547 else { /*Assume anything else is a Metadata Block*/
548 hdr_offset += display_metadata_block(bundle_tree, tvb,
549 hdr_offset, &lasthdrflag);
551 if(hdr_offset == 0) {
552 col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
563 dissect_tcp_convergence_data_header(tvbuff_t *tvb, proto_tree *tree)
565 proto_item *conv_item = NULL;
566 proto_tree *conv_tree = NULL;
567 int buflen = tvb_length(tvb);
570 proto_item *conv_flag_item = NULL;
571 proto_tree *conv_flag_tree = NULL;
572 guint8 tcp_convergence_hdr_procflags;
574 conv_item = proto_tree_add_text(tree, tvb, 0, -1, "TCP Convergence Header");
575 conv_tree = proto_item_add_subtree(conv_item, ett_tcp_conv_hdr);
576 proto_tree_add_text(conv_tree, tvb, 0, 1, "Pkt Type: Data");
578 /* Add tree for Start/End bits */
579 tcp_convergence_hdr_procflags = tvb_get_guint8(tvb, 0);
580 conv_flag_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_data_procflags, tvb,
582 conv_flag_tree = proto_item_add_subtree(conv_flag_item, ett_conv_flags);
583 proto_tree_add_boolean(conv_flag_tree, hf_tcp_convergence_data_procflags_start,
584 tvb, 0, 1, tcp_convergence_hdr_procflags);
585 proto_tree_add_boolean(conv_flag_tree, hf_tcp_convergence_data_procflags_end,
586 tvb, 0, 1, tcp_convergence_hdr_procflags);
588 segment_length = evaluate_sdnv(tvb, 1, &sdnv_length);
589 proto_tree_add_text(conv_tree, tvb, 1, sdnv_length, "Segment Length: %d", segment_length);
590 proto_item_set_len(conv_item, sdnv_length + 1);
595 * Dissect a complete bundle starting at offset 0 in tvb. Return 0 on failure,
596 * otherwise the length of the bundle.
600 dissect_complete_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
602 proto_item *primary_item = NULL;
603 proto_tree *primary_tree = NULL;
604 int primary_header_size;
605 int payload_size = 0;
608 guint8 next_header_type;
610 primary_item = proto_tree_add_text(tree, tvb, 0, -1,
611 "Primary Bundle Header");
612 primary_tree = proto_item_add_subtree(primary_item, ett_primary_hdr);
613 primary_header_size = dissect_primary_header(pinfo, primary_tree, tvb);
614 if(primary_header_size == 0) { /*Couldn't parse primary header*/
615 col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error");
616 return(0); /*Give up*/
618 proto_item_set_len(primary_item, primary_header_size);
619 offset = primary_header_size;
622 * Done with primary header; decode the remaining headers
625 while(lastheader == 0) {
626 next_header_type = tvb_get_guint8(tvb, offset);
627 if(next_header_type == PAYLOAD_HEADER_TYPE) {
630 * Returns payload size or 0 if can't parse payload
633 payload_size = dissect_payload_header(tree, tvb, offset, &lastheader);
635 else { /*Assume anything else is a Metadata Block*/
636 payload_size = display_metadata_block(tree, tvb,
637 offset, &lastheader);
639 if(payload_size == 0) { /*Payload header parse failed*/
641 col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed");
644 offset += payload_size;
650 * This routine returns 0 if header decoding fails, otherwise the length of the primary
651 * header. The bundle starts right at the beginning of the tvbuff.
655 dissect_primary_header(packet_info *pinfo, proto_tree *primary_tree, tvbuff_t *tvb)
661 int offset; /*Total offset into frame (frame_offset + convergence layer size)*/
663 int dest_scheme_offset, dest_ssp_offset, source_scheme_offset, source_ssp_offset;
664 int report_scheme_offset, report_ssp_offset, cust_scheme_offset, cust_ssp_offset;
665 int fragment_offset, total_adu_length;
669 proto_item *srr_flag_item = NULL;
670 proto_tree *srr_flag_tree = NULL;
672 proto_item *proc_flag_item = NULL;
673 proto_tree *proc_flag_tree = NULL;
674 proto_item *cos_flag_item = NULL;
675 proto_tree *cos_flag_tree = NULL;
676 proto_item *hdr_length_item = NULL;
677 proto_item *dict_length_item = NULL;
678 proto_item *dict_item = NULL;
679 proto_tree *dict_tree = NULL;
680 proto_item *dest_item = NULL;
681 proto_item *source_scheme_item = NULL;
682 proto_item *source_item = NULL;
683 proto_item *rpt_scheme_item = NULL;
684 proto_item *rpt_item = NULL;
685 proto_item *cust_scheme_item = NULL;
686 proto_item *cust_item = NULL;
690 version = tvb_get_guint8(tvb, offset);
691 /* Primary Header Version */
692 if((version != 4) && (version != 5) && (version != 6)) {
693 proto_tree_add_text(primary_tree, tvb, offset, 1, "Invalid Version Number");
696 proto_tree_add_item(primary_tree, hf_bundle_pdu_version, tvb, offset, 1, FALSE);
697 if((version == 5) || (version == 6)) {
698 return dissect_version_5_primary_header(pinfo, primary_tree, tvb);
701 /* Primary Header Processing Flags */
703 pri_hdr_procflags = tvb_get_guint8(tvb, offset);
704 proc_flag_item = proto_tree_add_item(primary_tree, hf_bundle_procflags, tvb,
706 proc_flag_tree = proto_item_add_subtree(proc_flag_item, ett_proc_flags);
707 proto_tree_add_boolean(proc_flag_tree, hf_bundle_procflags_fragment,
708 tvb, offset, 1, pri_hdr_procflags);
709 proto_tree_add_boolean(proc_flag_tree, hf_bundle_procflags_admin,
710 tvb, offset, 1, pri_hdr_procflags);
711 proto_tree_add_boolean(proc_flag_tree, hf_bundle_procflags_dont_fragment,
712 tvb, offset, 1, pri_hdr_procflags);
713 proto_tree_add_boolean(proc_flag_tree, hf_bundle_procflags_cust_xfer_req,
714 tvb, offset, 1, pri_hdr_procflags);
715 proto_tree_add_boolean(proc_flag_tree, hf_bundle_procflags_dest_singleton,
716 tvb, offset, 1, pri_hdr_procflags);
718 /* Primary Header COS Flags */
720 cosflags = tvb_get_guint8(tvb, offset);
721 cos_flag_item = proto_tree_add_item(primary_tree, hf_bundle_cosflags, tvb,
723 cos_flag_tree = proto_item_add_subtree(cos_flag_item, ett_cos_flags);
724 proto_tree_add_uint(cos_flag_tree, hf_bundle_cosflags_priority,
725 tvb, offset, 1, cosflags);
726 /* Status Report Request Flags */
728 srrflags = tvb_get_guint8(tvb, offset);
729 srr_flag_item = proto_tree_add_item(primary_tree, hf_bundle_srrflags, tvb,
731 srr_flag_tree = proto_item_add_subtree(srr_flag_item, ett_srr_flags);
733 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_receipt,
734 tvb, offset, 1, srrflags);
735 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_cust_accept,
736 tvb, offset, 1, srrflags);
737 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_forward,
738 tvb, offset, 1, srrflags);
739 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_delivery,
740 tvb, offset, 1, srrflags);
741 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_deletion,
742 tvb, offset, 1, srrflags);
743 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_ack,
744 tvb, offset, 1, srrflags);
746 bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
747 hdr_length_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
748 if(bundle_header_length < 0) {
749 proto_item_set_text(hdr_length_item, "Bundle Header Length: Error");
752 proto_item_set_text(hdr_length_item,
753 "Bundle Header Length: %d", bundle_header_length);
754 tvb_ensure_bytes_exist(tvb, offset + sdnv_length, bundle_header_length);
755 offset += sdnv_length;
758 * Pick up offsets into dictionary (8 of them)
761 dest_scheme_offset = tvb_get_ntohs(tvb, offset);
762 proto_tree_add_item(primary_tree, hf_bundle_dest_scheme_offset,
763 tvb, offset, 2, FALSE);
766 dest_ssp_offset = tvb_get_ntohs(tvb, offset);
767 proto_tree_add_item(primary_tree, hf_bundle_dest_ssp_offset,
768 tvb, offset, 2, FALSE);
771 source_scheme_offset = tvb_get_ntohs(tvb, offset);
772 proto_tree_add_item(primary_tree, hf_bundle_source_scheme_offset,
773 tvb, offset, 2, FALSE);
776 source_ssp_offset = tvb_get_ntohs(tvb, offset);
777 proto_tree_add_item(primary_tree, hf_bundle_source_ssp_offset,
778 tvb, offset, 2, FALSE);
781 report_scheme_offset = tvb_get_ntohs(tvb, offset);
782 proto_tree_add_item(primary_tree, hf_bundle_report_scheme_offset,
783 tvb, offset, 2, FALSE);
786 report_ssp_offset = tvb_get_ntohs(tvb, offset);
787 proto_tree_add_item(primary_tree, hf_bundle_report_ssp_offset,
788 tvb, offset, 2, FALSE);
791 cust_scheme_offset = tvb_get_ntohs(tvb, offset);
792 proto_tree_add_item(primary_tree, hf_bundle_cust_scheme_offset,
793 tvb, offset, 2, FALSE);
796 cust_ssp_offset = tvb_get_ntohs(tvb, offset);
797 proto_tree_add_item(primary_tree, hf_bundle_cust_ssp_offset,
798 tvb, offset, 2, FALSE);
801 proto_tree_add_item(primary_tree, hf_bundle_creation_timestamp,
802 tvb, offset, 8, FALSE);
805 proto_tree_add_item(primary_tree, hf_bundle_lifetime, tvb, offset, 4, FALSE);
808 bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
809 dict_length_item = proto_tree_add_text(primary_tree,
810 tvb, offset, sdnv_length, " ");
811 if(bundle_header_dict_length < 0) {
812 proto_item_set_text(dict_length_item, "Dictionary Length: Error");
815 proto_item_set_text(dict_length_item, "Dictionary Length: %d",
816 bundle_header_dict_length);
817 offset += sdnv_length;
818 tvb_ensure_bytes_exist(tvb, offset, bundle_header_dict_length);
821 * Pull out stuff from the dictionary
824 dict_item = proto_tree_add_text(primary_tree, tvb, offset,
825 bundle_header_dict_length, "Dictionary");
826 dict_tree = proto_item_add_subtree(dict_item, ett_dictionary);
827 dict_ptr = (guint8 *) tvb_get_ptr(tvb, offset, bundle_header_dict_length);
830 * This pointer can be made to address outside the packet boundaries so we
831 * need to check for improperly formatted strings (no null termination).
838 string_ptr = tvb_get_ephemeral_stringz(tvb, offset + dest_scheme_offset, &string_length);
840 proto_tree_add_text(dict_tree, tvb, offset + dest_scheme_offset,
841 (gint)strlen((char *) (dict_ptr + dest_scheme_offset)),
842 "Destination Scheme: %s", string_ptr);
843 string_ptr = tvb_get_ephemeral_stringz(tvb, offset + dest_ssp_offset, &string_length);
844 dest_item = proto_tree_add_text(dict_tree, tvb, offset + dest_ssp_offset,
845 (gint)strlen((char *) (dict_ptr + dest_ssp_offset)), " ");
846 proto_item_set_text(dest_item, "Destination: %s", string_ptr);
852 string_ptr = tvb_get_ephemeral_stringz(tvb,
853 offset + source_scheme_offset, &string_length);
854 source_scheme_item = proto_tree_add_text(dict_tree, tvb, offset+source_scheme_offset,
855 (gint)strlen((char *) (dict_ptr + source_scheme_offset)), " ");
856 proto_item_set_text(source_scheme_item, "Source Scheme: %s", string_ptr);
857 string_ptr = tvb_get_ephemeral_stringz(tvb,
858 offset + source_ssp_offset, &string_length);
859 source_item = proto_tree_add_text(dict_tree, tvb, offset + source_ssp_offset,
860 (gint)strlen((char *) (dict_ptr + source_ssp_offset)), " ");
861 proto_item_set_text(source_item, "Source: %s", string_ptr);
867 string_ptr = tvb_get_ephemeral_stringz(tvb,
868 offset + report_scheme_offset, &string_length);
869 rpt_scheme_item = proto_tree_add_text(dict_tree, tvb, offset + report_scheme_offset,
870 (gint)strlen((char *) (dict_ptr + report_scheme_offset)), " ");
871 proto_item_set_text(rpt_scheme_item, "Report To Scheme: %s", string_ptr);
872 string_ptr = tvb_get_ephemeral_stringz(tvb,
873 offset + report_ssp_offset, &string_length);
874 rpt_item = proto_tree_add_text(dict_tree, tvb, offset + report_ssp_offset,
875 (gint)strlen((char *) (dict_ptr + report_ssp_offset)), " ");
876 proto_item_set_text(rpt_item, "Report To: %s", string_ptr);
882 string_ptr = tvb_get_ephemeral_stringz(tvb,
883 offset + cust_scheme_offset, &string_length);
884 cust_scheme_item = proto_tree_add_text(dict_tree, tvb, offset + cust_scheme_offset,
885 (gint)strlen((char *) (dict_ptr + cust_scheme_offset)), " ");
886 proto_item_set_text(cust_scheme_item, "Custodian Scheme: %s", string_ptr);
887 string_ptr = tvb_get_ephemeral_stringz(tvb,
888 offset + cust_ssp_offset, &string_length);
889 cust_item = proto_tree_add_text(dict_tree, tvb, offset + cust_ssp_offset,
890 (gint)strlen((char *) (dict_ptr + cust_ssp_offset)), " ");
891 proto_item_set_text(cust_item, "Custodian: %s", string_ptr);
894 * Add Source/Destination to INFO Field
897 col_add_fstr(pinfo->cinfo, COL_INFO, "%s:%s > %s:%s",
898 dict_ptr + source_scheme_offset, dict_ptr + source_ssp_offset,
899 dict_ptr + dest_scheme_offset, dict_ptr + dest_ssp_offset);
900 offset += bundle_header_dict_length; /*Skip over dictionary*/
903 * Do this only if Fragment Flag is set
906 if(pri_hdr_procflags & BUNDLE_PROCFLAGS_FRAG_MASK) {
907 fragment_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
908 if(fragment_offset < 0) {
911 proto_tree_add_text(primary_tree, tvb, offset, sdnv_length,
912 "Fragment Offset: %d", fragment_offset);
913 offset += sdnv_length;
915 total_adu_length = evaluate_sdnv(tvb, offset, &sdnv_length);
916 if(total_adu_length < 0) {
919 proto_tree_add_text(primary_tree, tvb, offset, sdnv_length,
920 "Total Application Data Unit Length: %d", fragment_offset);
921 offset += sdnv_length;
928 * This routine returns 0 if header decoding fails, otherwise the length of the primary
929 * header. The bundle starts right at the beginning of the tvbuff.
933 dissect_version_5_primary_header(packet_info *pinfo,
934 proto_tree *primary_tree, tvbuff_t *tvb)
936 int bundle_processing_control_flags;
939 int offset; /*Total offset into frame (frame_offset + convergence layer size)*/
941 int dest_scheme_offset, dest_ssp_offset, source_scheme_offset, source_ssp_offset;
942 int report_scheme_offset, report_ssp_offset, cust_scheme_offset, cust_ssp_offset;
943 int fragment_offset, total_adu_length;
945 time_t time_since_2000;
946 int timestamp_sequence;
950 proto_item *srr_flag_item = NULL;
951 proto_tree *srr_flag_tree = NULL;
952 proto_item *gen_flag_item = NULL;
953 proto_tree *gen_flag_tree = NULL;
955 proto_item *proc_flag_item = NULL;
956 proto_tree *proc_flag_tree = NULL;
957 proto_item *cos_flag_item = NULL;
958 proto_item *cos_flag_value = NULL;
959 proto_tree *cos_flag_tree = NULL;
960 proto_item *hdr_length_item = NULL;
961 proto_item *dict_length_item = NULL;
962 proto_item *dict_item = NULL;
963 proto_tree *dict_tree = NULL;
965 proto_item *timestamp_item = NULL;
966 proto_item *timestamp_sequence_item = NULL;
967 proto_item *lifetime_item = NULL;
968 proto_item *dest_scheme_offset_item = NULL;
969 proto_item *dest_ssp_offset_item = NULL;
970 proto_item *source_scheme_offset_item = NULL;
971 proto_item *source_ssp_offset_item = NULL;
972 proto_item *report_scheme_offset_item = NULL;
973 proto_item *report_ssp_offset_item = NULL;
974 proto_item *cust_scheme_offset_item = NULL;
975 proto_item *cust_ssp_offset_item = NULL;
977 offset = 1; /*Already displayed Version Number*/
978 bundle_processing_control_flags = evaluate_sdnv(tvb, offset, &sdnv_length);
980 /* Primary Header Processing Flags */
981 pri_hdr_procflags = (guint8) (bundle_processing_control_flags & 0x7f);
983 proc_flag_item = proto_tree_add_item(primary_tree, hf_bundle_control_flags, tvb,
984 offset, sdnv_length, FALSE);
985 proc_flag_tree = proto_item_add_subtree(proc_flag_item, ett_proc_flags);
987 gen_flag_item = proto_tree_add_text(proc_flag_tree, tvb, offset,
988 sdnv_length, "General Flags");
989 gen_flag_tree = proto_item_add_subtree(gen_flag_item, ett_gen_flags);
991 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_fragment,
992 tvb, offset, sdnv_length, pri_hdr_procflags);
993 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_admin,
994 tvb, offset, sdnv_length, pri_hdr_procflags);
995 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_dont_fragment,
996 tvb, offset, sdnv_length, pri_hdr_procflags);
997 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_cust_xfer_req,
998 tvb, offset, sdnv_length, pri_hdr_procflags);
999 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_dest_singleton,
1000 tvb, offset, sdnv_length, pri_hdr_procflags);
1001 proto_tree_add_boolean(gen_flag_tree, hf_bundle_procflags_application_ack,
1002 tvb, offset, sdnv_length, pri_hdr_procflags);
1004 /* Primary Header COS Flags */
1005 cosflags = (guint8) ((bundle_processing_control_flags >> 7) & 0x7f);
1006 cos_flag_item = proto_tree_add_text(proc_flag_tree, tvb, offset,
1007 sdnv_length, "Class of Service Flags");
1008 cos_flag_tree = proto_item_add_subtree(cos_flag_item, ett_cos_flags);
1009 if((cosflags & BUNDLE_COSFLAGS_PRIORITY_MASK) == BUNDLE_COSFLAGS_PRIORITY_BULK) {
1010 cos_flag_value = proto_tree_add_text(cos_flag_tree, tvb, offset,
1011 sdnv_length, "00 -- Priority = Bulk");
1013 else if((cosflags & BUNDLE_COSFLAGS_PRIORITY_MASK) ==
1014 BUNDLE_COSFLAGS_PRIORITY_NORMAL) {
1015 cos_flag_value = proto_tree_add_text(cos_flag_tree, tvb, offset,
1016 sdnv_length, "01 -- Priority = Normal");
1018 else if((cosflags & BUNDLE_COSFLAGS_PRIORITY_MASK) ==
1019 BUNDLE_COSFLAGS_PRIORITY_EXP) {
1020 cos_flag_value = proto_tree_add_text(cos_flag_tree, tvb, offset,
1021 sdnv_length, "10 -- Priority = Expedited");
1024 cos_flag_value = proto_tree_add_text(cos_flag_tree, tvb, offset,
1025 sdnv_length, "11 -- Invalid (Reserved)");
1029 /* Status Report Request Flags */
1030 srrflags = (guint8) ((bundle_processing_control_flags >> 14) & 0x7f);
1031 srr_flag_item = proto_tree_add_text(proc_flag_tree, tvb, offset,
1032 sdnv_length, "Status Report Request Flags");
1033 srr_flag_tree = proto_item_add_subtree(srr_flag_item, ett_srr_flags);
1035 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_receipt,
1036 tvb, offset, sdnv_length, srrflags);
1037 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_cust_accept,
1038 tvb, offset, sdnv_length, srrflags);
1039 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_forward,
1040 tvb, offset, sdnv_length, srrflags);
1041 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_delivery,
1042 tvb, offset, sdnv_length, srrflags);
1043 proto_tree_add_boolean(srr_flag_tree, hf_bundle_srrflags_report_deletion,
1044 tvb, offset, sdnv_length, srrflags);
1045 offset += sdnv_length;
1047 bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1048 hdr_length_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1049 if(bundle_header_length < 0) {
1050 proto_item_set_text(hdr_length_item, "Bundle Header Length: Error");
1053 proto_item_set_text(hdr_length_item,
1054 "Bundle Header Length: %d", bundle_header_length);
1055 tvb_ensure_bytes_exist(tvb, offset + sdnv_length, bundle_header_length);
1056 offset += sdnv_length;
1059 * Pick up offsets into dictionary (8 of them). Do rough sanity check that SDNV
1060 * hasn't told us to access way past the Primary Header.
1063 dest_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1064 dest_scheme_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1065 if((dest_scheme_offset < 0) || (dest_scheme_offset > bundle_header_length)) {
1066 proto_item_set_text(dest_scheme_offset_item, "Destination Scheme Offset: Error");
1069 proto_item_set_text(dest_scheme_offset_item,
1070 "Destination Scheme Offset: %d", dest_scheme_offset);
1071 offset += sdnv_length;
1073 dest_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1074 dest_ssp_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1075 if((dest_ssp_offset < 0) || (dest_ssp_offset > bundle_header_length)) {
1076 proto_item_set_text(dest_ssp_offset_item, "Destination SSP Offset: Error");
1079 proto_item_set_text(dest_ssp_offset_item,
1080 "Destination SSP Offset: %d", dest_ssp_offset);
1081 offset += sdnv_length;
1083 source_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1084 source_scheme_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1085 if((source_scheme_offset < 0) || (source_scheme_offset > bundle_header_length)) {
1086 proto_item_set_text(source_scheme_offset_item, "Source Scheme Offset: Error");
1089 proto_item_set_text(source_scheme_offset_item,
1090 "Source Scheme Offset: %d", source_scheme_offset);
1091 offset += sdnv_length;
1093 source_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1094 source_ssp_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1095 if((source_ssp_offset < 0) || (source_ssp_offset > bundle_header_length)) {
1096 proto_item_set_text(source_ssp_offset_item, "Source SSP Offset: Error");
1099 proto_item_set_text(source_ssp_offset_item,
1100 "Source SSP Offset: %d", source_ssp_offset);
1101 offset += sdnv_length;
1103 report_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1104 report_scheme_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1105 if((report_scheme_offset < 0) || (report_scheme_offset > bundle_header_length)) {
1106 proto_item_set_text(report_scheme_offset_item, "Report Scheme Offset: Error");
1109 proto_item_set_text(report_scheme_offset_item,
1110 "Report Scheme Offset: %d", report_scheme_offset);
1111 offset += sdnv_length;
1113 report_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1114 report_ssp_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1115 if((report_ssp_offset < 0) || (report_ssp_offset > bundle_header_length)) {
1116 proto_item_set_text(report_ssp_offset_item, "Report SSP Offset: Error");
1119 proto_item_set_text(report_ssp_offset_item,
1120 "Report SSP Offset: %d", report_ssp_offset);
1121 offset += sdnv_length;
1123 cust_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1124 cust_scheme_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1125 if((cust_scheme_offset < 0) || (cust_scheme_offset > bundle_header_length)) {
1126 proto_item_set_text(cust_scheme_offset_item, "Custodian Scheme Offset: Error");
1129 proto_item_set_text(cust_scheme_offset_item,
1130 "Custodian Scheme Offset: %d", cust_scheme_offset);
1131 offset += sdnv_length;
1133 cust_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1134 cust_ssp_offset_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1135 if((cust_ssp_offset < 0) || (cust_ssp_offset > bundle_header_length)) {
1136 proto_item_set_text(cust_ssp_offset_item, "Custodian SSP Offset: Error");
1139 proto_item_set_text(cust_ssp_offset_item,
1140 "Custodian SSP Offset: %d", cust_ssp_offset);
1141 offset += sdnv_length;
1143 timestamp = evaluate_sdnv(tvb, offset, &sdnv_length);
1144 timestamp_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1146 proto_item_set_text(timestamp_item, "Timestamp: Error");
1149 time_since_2000 = (time_t) (timestamp + 946684800);
1150 time_string = ctime(&time_since_2000);
1151 time_string[strlen(time_string) - 1] = 0; /*Remove Newline at enc*/
1152 proto_item_set_text(timestamp_item,
1153 "Timestamp: 0x%x [%s]", timestamp, time_string);
1154 offset += sdnv_length;
1156 timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
1157 timestamp_sequence_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1159 if(timestamp_sequence < 0) {
1162 if((ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length)) < 0) {
1163 proto_item_set_text(timestamp_sequence_item, "Timestamp Sequence Number: Error");
1166 proto_item_set_text(timestamp_sequence_item,
1167 "Timestamp Sequence Number: 0x%" G_GINT64_MODIFIER "x", ts_seq);
1170 proto_item_set_text(timestamp_sequence_item,
1171 "Timestamp Sequence Number: %d", timestamp_sequence);
1173 offset += sdnv_length;
1175 lifetime = evaluate_sdnv(tvb, offset, &sdnv_length);
1176 lifetime_item = proto_tree_add_text(primary_tree, tvb, offset, sdnv_length, " ");
1178 proto_item_set_text(lifetime_item, "Lifetime: Error");
1181 proto_item_set_text(lifetime_item, "Lifetime: %d", lifetime);
1182 offset += sdnv_length;
1184 bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1185 dict_length_item = proto_tree_add_text(primary_tree,
1186 tvb, offset, sdnv_length, " ");
1187 if(bundle_header_dict_length < 0) {
1188 proto_item_set_text(dict_length_item, "Dictionary Length: Error");
1191 proto_item_set_text(dict_length_item, "Dictionary Length: %d",
1192 bundle_header_dict_length);
1193 offset += sdnv_length;
1194 tvb_ensure_bytes_exist(tvb, offset, bundle_header_dict_length);
1197 * Pull out stuff from the dictionary
1200 dict_item = proto_tree_add_text(primary_tree, tvb, offset,
1201 bundle_header_dict_length, "Dictionary");
1202 dict_tree = proto_item_add_subtree(dict_item, ett_dictionary);
1203 dict_ptr = (guint8 *) tvb_get_ptr(tvb, offset, bundle_header_dict_length);
1206 * This pointer can be made to address outside the packet boundaries so we
1207 * need to check for improperly formatted strings (no null termination).
1214 tvb_ensure_bytes_exist(tvb, offset, dest_scheme_offset);
1215 proto_tree_add_item(dict_tree, hf_bundle_dest_scheme, tvb, offset + dest_scheme_offset,
1216 (gint)strlen((char *) (dict_ptr + dest_scheme_offset)), FALSE);
1217 tvb_ensure_bytes_exist(tvb, offset, dest_ssp_offset);
1218 proto_tree_add_item(dict_tree, hf_bundle_dest_ssp, tvb, offset + dest_ssp_offset,
1219 (gint)strlen((char *) (dict_ptr + dest_ssp_offset)), FALSE);
1225 tvb_ensure_bytes_exist(tvb, offset, source_scheme_offset);
1226 proto_tree_add_item(dict_tree, hf_bundle_source_scheme, tvb, offset + source_scheme_offset,
1227 (gint)strlen((char *) (dict_ptr + source_scheme_offset)), FALSE);
1228 tvb_ensure_bytes_exist(tvb, offset, source_ssp_offset);
1229 proto_tree_add_item(dict_tree, hf_bundle_source_ssp, tvb, offset + source_ssp_offset,
1230 (gint)strlen((char *) (dict_ptr + source_ssp_offset)), FALSE);
1236 tvb_ensure_bytes_exist(tvb, offset, report_scheme_offset);
1237 proto_tree_add_item(dict_tree, hf_bundle_report_scheme, tvb, offset + report_scheme_offset,
1238 (gint)strlen((char *) (dict_ptr + report_scheme_offset)), FALSE);
1239 tvb_ensure_bytes_exist(tvb, offset, report_ssp_offset);
1240 proto_tree_add_item(dict_tree, hf_bundle_report_ssp, tvb, offset + report_ssp_offset,
1241 (gint)strlen((char *) (dict_ptr + report_ssp_offset)), FALSE);
1247 tvb_ensure_bytes_exist(tvb, offset, cust_scheme_offset);
1248 proto_tree_add_item(dict_tree, hf_bundle_custodian_scheme, tvb, offset + cust_scheme_offset,
1249 (gint)strlen((char *) (dict_ptr + cust_scheme_offset)), FALSE);
1251 tvb_ensure_bytes_exist(tvb, offset, cust_ssp_offset);
1252 proto_tree_add_item(dict_tree, hf_bundle_custodian_ssp, tvb, offset + cust_ssp_offset,
1253 (gint)strlen((char *) (dict_ptr + cust_ssp_offset)), FALSE);
1256 * Add Source/Destination to INFO Field
1259 if(check_col(pinfo->cinfo, COL_INFO)) {
1260 col_add_fstr(pinfo->cinfo, COL_INFO, "%s:%s > %s:%s",
1261 dict_ptr + source_scheme_offset, dict_ptr + source_ssp_offset,
1262 dict_ptr + dest_scheme_offset, dict_ptr + dest_ssp_offset);
1264 offset += bundle_header_dict_length; /*Skip over dictionary*/
1267 * Do this only if Fragment Flag is set
1270 if(pri_hdr_procflags & BUNDLE_PROCFLAGS_FRAG_MASK) {
1271 fragment_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
1272 if(fragment_offset < 0) {
1275 proto_tree_add_text(primary_tree, tvb, offset, sdnv_length,
1276 "Fragment Offset: %d", fragment_offset);
1277 offset += sdnv_length;
1279 total_adu_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1280 if(total_adu_length < 0) {
1283 proto_tree_add_text(primary_tree, tvb, offset, sdnv_length,
1284 "Total Application Data Unit Length: %d", fragment_offset);
1285 offset += sdnv_length;
1291 * bundle_offset is offset into this bundle where header starts.
1292 * Return size of payload (including payload header) or 0 on failure.
1296 dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, int offset, int *lastheader)
1298 proto_item *payload_item = NULL;
1299 proto_tree *payload_tree = NULL;
1300 proto_item *proc_flag_item = NULL;
1301 proto_tree *proc_flag_tree = NULL;
1302 proto_item *hdr_length_item = NULL;
1303 proto_item *type_item = NULL;
1309 header_start = offset; /*Used to compute total payload length*/
1310 payload_item = proto_tree_add_text(tree, tvb, offset, -1, "Payload Header");
1311 payload_tree = proto_item_add_subtree(payload_item, ett_payload_hdr);
1313 type_item = proto_tree_add_text(payload_tree, tvb, offset, 1, "Header Type: 1");
1316 /* Add tree for processing flags */
1317 /* This is really a SDNV but there are only 7 bits defined so leave it this way*/
1319 if(hf_bundle_pdu_version == 4) {
1320 procflags = tvb_get_guint8(tvb, offset);
1321 if(procflags & HEADER_PROCFLAGS_LAST_HEADER) {
1327 proc_flag_item = proto_tree_add_item(payload_tree, hf_bundle_payload_flags, tvb,
1329 proc_flag_tree = proto_item_add_subtree(proc_flag_item, ett_payload_flags);
1330 proto_tree_add_boolean(proc_flag_tree, hf_bundle_payload_flags_replicate_hdr,
1331 tvb, offset, 1, procflags);
1332 proto_tree_add_boolean(proc_flag_tree, hf_bundle_payload_flags_xmit_report,
1333 tvb, offset, 1, procflags);
1334 proto_tree_add_boolean(proc_flag_tree, hf_bundle_payload_flags_discard_on_fail,
1335 tvb, offset, 1, procflags);
1336 proto_tree_add_boolean(proc_flag_tree, hf_bundle_payload_flags_last_header,
1337 tvb, offset, 1, procflags);
1340 else { /*Bundle Protocol Version 5*/
1342 proto_item *block_flag_item = NULL;
1343 proto_tree *block_flag_tree = NULL;
1345 control_flags = evaluate_sdnv(tvb, offset, &sdnv_length);
1346 if(control_flags & BLOCK_CONTROL_LAST_BLOCK) {
1352 block_flag_item = proto_tree_add_item(payload_tree, hf_block_control_flags, tvb,
1353 offset, sdnv_length, FALSE);
1354 block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
1356 proto_tree_add_boolean(block_flag_tree, hf_block_control_replicate,
1357 tvb, offset, sdnv_length, control_flags);
1358 proto_tree_add_boolean(block_flag_tree, hf_block_control_transmit_status,
1359 tvb, offset, sdnv_length, control_flags);
1360 proto_tree_add_boolean(block_flag_tree, hf_block_control_delete_bundle,
1361 tvb, offset, sdnv_length, control_flags);
1362 proto_tree_add_boolean(block_flag_tree, hf_block_control_last_block,
1363 tvb, offset, sdnv_length, control_flags);
1364 proto_tree_add_boolean(block_flag_tree, hf_block_control_discard_block,
1365 tvb, offset, sdnv_length, control_flags);
1366 proto_tree_add_boolean(block_flag_tree, hf_block_control_not_processed,
1367 tvb, offset, sdnv_length, control_flags);
1368 proto_tree_add_boolean(block_flag_tree, hf_block_control_eid_reference,
1369 tvb, offset, sdnv_length, control_flags);
1370 offset += sdnv_length;
1372 payload_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1373 proto_item_set_len(payload_item, 2 + sdnv_length);
1374 hdr_length_item = proto_tree_add_text(payload_tree, tvb, offset, sdnv_length, " ");
1375 if(payload_length < 0) {
1376 proto_item_set_text(hdr_length_item, "Payload Length: Error");
1379 proto_item_set_text(hdr_length_item, "Payload Length: %d", payload_length);
1381 offset += sdnv_length;
1382 if(pri_hdr_procflags & BUNDLE_PROCFLAGS_ADMIN_MASK) {
1386 * XXXX - Have not allowed for admin record spanning multiple segments!
1389 admin_size = dissect_admin_record(payload_tree, tvb, offset);
1390 if(admin_size == 0) {
1394 return (payload_length + (offset - header_start));
1398 * Return the length of the Administrative Record or 0 if analysis fails.
1402 dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, int offset)
1404 proto_item *admin_record_item = NULL;
1405 proto_tree *admin_record_tree = NULL;
1406 proto_item *status_flag_item = NULL;
1407 proto_tree *status_flag_tree = NULL;
1408 proto_item *admin_record_type = NULL;
1412 int record_size = 0;
1414 int endpoint_length;
1418 admin_record_item = proto_tree_add_text(primary_tree, tvb, offset, -1,
1419 "Administrative Record");
1420 admin_record_tree = proto_item_add_subtree(admin_record_item, ett_admin_record);
1421 record_type = tvb_get_guint8(tvb, offset);
1423 if(record_type == (0x05 << 4)) {
1424 proto_tree_add_text(admin_record_tree, tvb, offset, 1, "Announce Record (Contact)");
1425 return 1; /*Special case for poxy TCP Convergence Layer Announce Bundle*/
1427 if(record_type & ADMIN_REC_FLAGS_FRAGMENT) {
1428 proto_tree_add_text(admin_record_tree, tvb, offset, 1, "Record is for a Fragment");
1431 proto_tree_add_text(admin_record_tree,
1432 tvb, offset, 1, "Record is not for a Fragment");
1435 switch((record_type >> 4) & 0xf)
1438 case ADMIN_REC_TYPE_STATUS_REPORT:
1439 admin_record_type = proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1440 "Administrative Record Type: Bundle Status Report");
1441 ++record_size; ++offset;
1443 /* Decode Bundle Status Report Flags */
1444 status = tvb_get_guint8(tvb, offset);
1445 status_flag_item = proto_tree_add_item(admin_record_tree,
1446 hf_bundle_admin_statflags, tvb, offset, 1, FALSE);
1447 status_flag_tree = proto_item_add_subtree(status_flag_item,
1448 ett_admin_rec_status);
1449 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_rcvd,
1450 tvb, offset, 1, status);
1451 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_accepted,
1452 tvb, offset, 1, status);
1453 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_forwarded,
1454 tvb, offset, 1, status);
1455 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_delivered,
1456 tvb, offset, 1, status);
1457 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_deleted,
1458 tvb, offset, 1, status);
1459 proto_tree_add_boolean(status_flag_tree, hf_bundle_admin_acked,
1460 tvb, offset, 1, status);
1461 ++record_size; ++offset;
1463 reason = tvb_get_guint8(tvb, offset);
1465 proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1466 "Reason Code: 0 (No Additional Information)");
1469 proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1470 "Reason Code: 0x%x (%s)", reason,
1471 val_to_str(reason, status_report_reason_codes,
1474 ++record_size; ++offset;
1475 if(record_type & ADMIN_REC_FLAGS_FRAGMENT) {
1476 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1478 if(sdnv_length <= 0) {
1481 offset += sdnv_length; record_size += sdnv_length;
1482 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1484 if(sdnv_length <= 0) {
1487 offset += sdnv_length; record_size += sdnv_length;
1489 if(status & ADMIN_STATUS_FLAGS_RECEIVED) {
1490 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1491 "Bundle Received Time");
1492 if(sdnv_length <= 0) {
1495 offset += sdnv_length; record_size += sdnv_length;
1497 if(status & ADMIN_STATUS_FLAGS_ACCEPTED) {
1498 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1499 "Bundle Accepted Time");
1500 if(sdnv_length <= 0) {
1503 offset += sdnv_length; record_size += sdnv_length;
1505 if(status & ADMIN_STATUS_FLAGS_FORWARDED) {
1506 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1507 "Bundle Forwarded Time");
1508 if(sdnv_length <= 0) {
1511 offset += sdnv_length; record_size += sdnv_length;
1513 if(status & ADMIN_STATUS_FLAGS_DELIVERED) {
1514 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1515 "Bundle Delivered Time");
1516 if(sdnv_length <= 0) {
1519 offset += sdnv_length; record_size += sdnv_length;
1521 if(status & ADMIN_STATUS_FLAGS_DELETED) {
1522 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1523 "Bundle Deleted Time");
1524 if(sdnv_length <= 0) {
1527 offset += sdnv_length; record_size += sdnv_length;
1529 if(status & ADMIN_STATUS_FLAGS_ACKNOWLEDGED) {
1530 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1531 "Bundle Acknowledged Time");
1532 if(sdnv_length <= 0) {
1535 offset += sdnv_length; record_size += sdnv_length;
1538 /* Get 2 SDNVs for Creation Timestamp */
1539 sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset,
1540 "Bundle Creation Timestamp");
1541 if(sdnv_length <= 0) {
1544 offset += sdnv_length; record_size += sdnv_length;
1545 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1546 "Bundle Creation Timestamp Sequence");
1547 if(sdnv_length <= 0) {
1550 offset += sdnv_length; record_size += sdnv_length;
1552 endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1553 if(endpoint_length < 0) {
1556 proto_tree_add_text(admin_record_tree, tvb, offset, sdnv_length,
1557 "Endpoint Length: %d", endpoint_length);
1558 offset += sdnv_length; record_size += sdnv_length;
1561 * Endpoint name may not be null terminated. This routine is supposed
1562 * to add the null at the end of the string buffer.
1565 string_ptr = tvb_get_ephemeral_string(tvb, offset, endpoint_length);
1566 proto_tree_add_text(admin_record_tree, tvb, offset, endpoint_length,
1567 "Bundle Endpoint ID: %s", string_ptr);
1568 offset += endpoint_length; record_size += endpoint_length;
1572 case ADMIN_REC_TYPE_CUSTODY_SIGNAL:
1573 admin_record_type = proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1574 "Administrative Record Type: Custody Signal");
1575 ++record_size; ++offset;
1577 status = tvb_get_guint8(tvb, offset);
1578 proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1579 "Custody Transfer Succeeded Flag: %d", (status >> 7) & 0x01);
1580 if((status & ADMIN_REC_CUSTODY_REASON_MASK) == 0) {
1581 proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1582 "Reason Code: 0 (No Additional Information)");
1585 proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1586 "Reason Code: 0x%x (%s)",
1587 status & ADMIN_REC_CUSTODY_REASON_MASK,
1588 val_to_str(status & ADMIN_REC_CUSTODY_REASON_MASK,
1589 custody_signal_reason_codes, "Invalid"));
1591 ++record_size; ++offset;
1592 if(record_type & ADMIN_REC_FLAGS_FRAGMENT) {
1593 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1595 if(sdnv_length <= 0) {
1598 offset += sdnv_length; record_size += sdnv_length;
1599 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1601 if(sdnv_length <= 0) {
1604 offset += sdnv_length; record_size += sdnv_length;
1608 sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset,
1609 "Bundle Signal Time");
1610 if(sdnv_length <= 0) {
1613 offset += sdnv_length; record_size += sdnv_length;
1615 /* Timestamp copy */
1616 sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset,
1617 "Bundle Creation Timestamp");
1618 if(sdnv_length <= 0) {
1621 offset += sdnv_length; record_size += sdnv_length;
1622 sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, offset,
1623 "Bundle Creation Timestamp Sequence");
1624 if(sdnv_length <= 0) {
1627 offset += sdnv_length; record_size += sdnv_length;
1629 endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
1630 if(endpoint_length < 0) {
1633 proto_tree_add_text(admin_record_tree, tvb, offset, sdnv_length,
1634 "Endpoint Length: %d", endpoint_length);
1635 offset += sdnv_length; record_size += sdnv_length;
1636 string_ptr = tvb_get_ephemeral_stringz(tvb, offset, &string_length);
1637 proto_tree_add_text(admin_record_tree, tvb, offset, endpoint_length,
1638 "Bundle Endpoint ID: %s", string_ptr);
1639 offset += string_length; record_size += string_length;
1644 admin_record_type = proto_tree_add_text(admin_record_tree, tvb, offset, 1,
1645 "Administrative Record Type: Unknown");
1650 * Return length of contact header or 0 on failure
1654 dissect_contact_header(tvbuff_t *tvb, packet_info *pinfo,
1655 proto_tree *conv_tree, proto_item *conv_item)
1657 guint8 contact_hdr_flags;
1658 proto_item *contact_hdr_flag_item = NULL;
1659 proto_tree *contact_hdr_flag_tree = NULL;
1660 proto_item *eid_item = NULL;
1666 * I'm going to assume that if this is a contact header, the buffer
1667 * contains the complete header and that there are no other packets
1671 proto_tree_add_text(conv_tree, tvb, 0, 4, "Pkt Type: Contact Header");
1672 proto_tree_add_item(conv_tree, hf_contact_hdr_version, tvb, 4, 1, FALSE);
1674 /* Subtree to expand the bits in the Contact Header Flags */
1675 contact_hdr_flags = tvb_get_guint8(tvb, 5);
1676 contact_hdr_flag_item =
1677 proto_tree_add_item(conv_tree, hf_contact_hdr_flags, tvb, 5, 1, FALSE);
1678 contact_hdr_flag_tree =
1679 proto_item_add_subtree(contact_hdr_flag_item, ett_contact_hdr_flags);
1680 proto_tree_add_boolean(contact_hdr_flag_tree, hf_contact_hdr_flags_ack_req,
1681 tvb, 5, 1, contact_hdr_flags);
1682 proto_tree_add_boolean(contact_hdr_flag_tree, hf_contact_hdr_flags_frag_enable,
1683 tvb, 5, 1, contact_hdr_flags);
1684 proto_tree_add_boolean(contact_hdr_flag_tree, hf_contact_hdr_flags_nak,
1685 tvb, 5, 1, contact_hdr_flags);
1686 proto_tree_add_item(conv_tree, hf_contact_hdr_keep_alive, tvb, 6, 2, FALSE);
1689 * New format Contact header has length field followed by Bundle Header.
1692 eid_length = evaluate_sdnv(tvb, 8, &sdnv_length);
1693 if(eid_length < 0) {
1694 col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error (Local EID Length)");
1697 proto_tree_add_text(conv_tree, tvb, 8, sdnv_length,
1698 "Local EID Length: %d", eid_length);
1699 proto_item_set_len(conv_item, sdnv_length + eid_length + 8);
1700 eid_item = proto_tree_add_text(conv_tree, tvb, sdnv_length + 8, eid_length, " ");
1701 sptr = (char *) tvb_get_ephemeral_string(tvb, sdnv_length + 8, eid_length);
1702 proto_item_set_text(eid_item, "Local EID: %s", sptr);
1703 return(sdnv_length + eid_length + 8);
1707 display_metadata_block(proto_tree *tree, tvbuff_t *tvb, int offset, int *lastheader)
1709 proto_item *block_item = NULL;
1710 proto_tree *block_tree = NULL;
1711 proto_item *hdr_length_item = NULL;
1712 proto_item *type_item = NULL;
1718 proto_item *block_flag_item = NULL;
1720 type = tvb_get_guint8(tvb, offset);
1721 header_start = offset; /*Used to compute total payload length*/
1723 block_item = proto_tree_add_text(tree, tvb,
1724 header_start + offset, -1, "Metadata Block");
1725 block_tree = proto_item_add_subtree(block_item, ett_metadata_hdr);
1727 type_item = proto_tree_add_text(block_tree, tvb, header_start + offset, 1, " ");
1728 proto_item_set_text(type_item, "Block Type: %d", type);
1731 control_flags = evaluate_sdnv(tvb, header_start + offset, &sdnv_length);
1732 if(control_flags & BLOCK_CONTROL_LAST_BLOCK) {
1738 block_flag_item = proto_tree_add_text(block_tree, tvb, header_start + offset, 1, " ");
1739 proto_item_set_text(block_flag_item, "Block Flags: 0x%x", control_flags);
1740 offset += sdnv_length;
1742 block_length = evaluate_sdnv(tvb, header_start + offset, &sdnv_length);
1743 proto_item_set_len(block_item, offset + sdnv_length + block_length);
1744 hdr_length_item = proto_tree_add_text(block_tree, tvb,
1745 header_start + offset, sdnv_length, " ");
1746 if(block_length < 0) {
1747 proto_item_set_text(hdr_length_item, "Metadata Block Length: Error");
1750 proto_item_set_text(hdr_length_item, "Block Length: %d", block_length);
1751 offset += (sdnv_length + block_length);
1756 * SDNV has a zero in high-order bit position of last byte. The high-order
1757 * bit of all preceding bytes is set to one. This returns the numeric value
1758 * in an integer and sets the value of the second argument to the number of
1759 * bytes used to code the SDNV. A -1 is returned if the evaluation fails
1760 * (value exceeds maximum for signed integer). 0 is an acceptable value.
1763 #define SDNV_MASK 0x7f
1765 /*3rd arg is number of bytes in field (returned)*/
1767 evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount)
1775 * Get 1st byte and continue to get them while high-order bit is 1
1778 while((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
1779 if(*bytecount >= (int) sizeof(int)) {
1784 value |= (curbyte & SDNV_MASK);
1790 * Add in the byte whose high-order bit is 0 (last one)
1794 value |= (curbyte & SDNV_MASK);
1799 /* Special Function to evaluate 64 bit SDNVs */
1801 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount)
1809 * Get 1st byte and continue to get them while high-order bit is 1
1812 while((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK) {
1813 if(*bytecount >= (int) sizeof(gint64)) {
1818 value |= (curbyte & SDNV_MASK);
1824 * Add in the byte whose high-order bit is 0 (last one)
1828 value |= (curbyte & SDNV_MASK);
1834 add_sdnv_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id)
1839 sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
1840 if(sdnv_value < 0) {
1843 proto_tree_add_text(tree, tvb, offset, sdnv_length, "%s: %d", field_id, sdnv_value);
1848 * Adds the result of 2 SDNVs to tree: First SDNV is seconds, next is nanoseconds.
1849 * Returns bytes in both SDNVs or 0 if something goes wrong.
1852 add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id)
1854 int sdnv_length, sdnv2_length;
1856 time_t time_since_2000;
1859 sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
1860 if(sdnv_value < 0) {
1863 time_since_2000 = (time_t) (sdnv_value + 946684800);
1864 time_string = ctime(&time_since_2000);
1865 time_string[strlen(time_string) - 1] = 0; /*Remove Newline at enc*/
1866 proto_tree_add_text(tree, tvb, offset, sdnv_length,
1867 "%s (sec): %d [%s]", field_id, sdnv_value, time_string);
1868 offset += sdnv_length;
1870 sdnv_value = evaluate_sdnv(tvb, offset, &sdnv2_length);
1871 if(sdnv_value < 0) {
1874 proto_tree_add_text(tree, tvb, offset, sdnv2_length,
1875 "%s (ns): %d", field_id, sdnv_value);
1876 return (sdnv_length + sdnv2_length);
1880 * Adds the result of SDNV which is a time since 2000 to tree.
1881 * Returns bytes in SDNV or 0 if something goes wrong.
1884 add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, char *field_id)
1888 time_t time_since_2000;
1891 sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
1892 if(sdnv_value < 0) {
1895 time_since_2000 = (time_t) (sdnv_value + 946684800);
1896 time_string = ctime(&time_since_2000);
1897 time_string[strlen(time_string) - 1] = 0; /*Remove Newline at enc*/
1898 proto_tree_add_text(tree, tvb, offset, sdnv_length,
1899 "%s: %d [%s]", field_id, sdnv_value, time_string);
1904 bundle_defragment_init(void) {
1905 fragment_table_init(&msg_fragment_table);
1906 reassembled_table_init(&msg_reassembled_table);
1910 proto_register_bundle(void)
1913 static hf_register_info hf[] = {
1914 {&hf_bundle_pdu_version,
1915 {"Bundle Version", "bundle.version",
1916 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
1918 {&hf_contact_hdr_version,
1919 {"Version", "bundle.tcp_conv.contact_hdr.version",
1920 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
1922 {&hf_contact_hdr_flags,
1923 {"Flags", "bundle.tcp_conv.contact_hdr.flags",
1924 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
1926 {&hf_contact_hdr_flags_ack_req,
1927 {"Bundle Acks Requested", "bundle.tcp_conv.contact_hdr.flags.ackreq",
1928 FT_BOOLEAN, 8, NULL, TCP_CONV_BUNDLE_ACK_FLAG, NULL, HFILL}
1930 {&hf_contact_hdr_flags_frag_enable,
1931 {"Reactive Fragmentation Enabled", "bundle.tcp_conv.contact_hdr.flags.fragen",
1932 FT_BOOLEAN, 8, NULL, TCP_CONV_REACTIVE_FRAG_FLAG, NULL, HFILL}
1934 {&hf_contact_hdr_flags_nak,
1935 {"Support Negative Acknowledgements", "bundle.tcp_conv.contact_hdr.flags.nak",
1936 FT_BOOLEAN, 8, NULL, TCP_CONV_CONNECTOR_RCVR_FLAG, NULL, HFILL}
1938 {&hf_contact_hdr_keep_alive,
1939 {"Keep Alive", "bundle.tcp_conv.contact_hdr.keep_alive",
1940 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
1942 {&hf_tcp_convergence_data_procflags,
1943 {"TCP Convergence Data Flags", "bundle.tcp_conv.data.proc.flag",
1944 FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_DATA_FLAGS, NULL, HFILL}
1946 {&hf_tcp_convergence_data_procflags_start,
1947 {"Segment contains start of bundle", "bundle.tcp_conv.data.proc.start",
1948 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_START_FLAG, NULL, HFILL}
1950 {&hf_tcp_convergence_data_procflags_end,
1951 {"Segment contains end of Bundle", "bundle.tcp_conv.data.proc.end",
1952 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_DATA_END_FLAG, NULL, HFILL}
1954 {&hf_tcp_convergence_shutdown_flags,
1955 {"TCP Convergence Shutdown Flags", "bundle.tcp_conv.shutdown.flags",
1956 FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_SHUTDOWN_FLAGS, NULL, HFILL}
1958 {&hf_tcp_convergence_shutdown_flags_reason,
1959 {"Shutdown includes Reason Code", "bundle.tcp_conv.shutdown.reason.flag",
1960 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_REASON, NULL, HFILL}
1962 {&hf_tcp_convergence_shutdown_flags_delay,
1963 {"Shutdown includes Reconnection Delay", "bundle.tcp_conv.shutdown.delay.flag",
1964 FT_BOOLEAN, 8, NULL, TCP_CONVERGENCE_SHUTDOWN_DELAY, NULL, HFILL}
1966 {&hf_tcp_convergence_shutdown_reason,
1967 {"Shutdown Reason Code", "bundle.tcp_conv.shutdown.reason",
1968 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
1970 {&hf_tcp_convergence_shutdown_delay,
1971 {"Shutdown Reconnection Delay", "bundle.tcp_conv.shutdown.delay",
1972 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
1976 {"Message Fragments", "bundle.msg.fragments",
1977 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
1980 {"Message Fragment", "bundle.msg.fragment",
1981 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
1983 {&hf_msg_fragment_overlap,
1984 {"Message fragment overlap", "bundle.msg.fragment.overlap",
1985 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
1987 {&hf_msg_fragment_overlap_conflicts,
1988 {"Message fragment overlapping with conflicting data",
1989 "bundle.msg.fragment.overlap.conflicts",
1990 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
1992 {&hf_msg_fragment_multiple_tails,
1993 {"Message has multiple tails", "bundle.msg.fragment.multiple_tails",
1994 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
1996 {&hf_msg_fragment_too_long_fragment,
1997 {"Message fragment too long", "bundle.msg.fragment.too_long_fragment",
1998 FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL}
2000 {&hf_msg_fragment_error,
2001 {"Message defragmentation error", "bundle.msg.fragment.error",
2002 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
2004 {&hf_msg_reassembled_in,
2005 {"Reassembled in", "bundle.msg.reassembled.in",
2006 FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL}
2008 {&hf_bundle_procflags,
2009 {"Primary Header Processing Flags", "bundle.primary.proc.flag",
2010 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2012 {&hf_bundle_procflags_fragment,
2013 {"Bundle is a Fragment", "bundle.primary.proc.frag",
2014 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_FRAG_MASK, NULL, HFILL}
2016 {&hf_bundle_procflags_admin,
2017 {"Administrative Record", "bundle.primary.proc.admin",
2018 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_ADMIN_MASK, NULL, HFILL}
2020 {&hf_bundle_procflags_dont_fragment,
2021 {"Do Not Fragment Bundle", "bundle.primary.proc.dontfrag",
2022 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_DONTFRAG_MASK, NULL, HFILL}
2024 {&hf_bundle_procflags_cust_xfer_req,
2025 {"Request Custody Transfer", "bundle.primary.proc.xferreq",
2026 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_XFERREQ_MASK, NULL, HFILL}
2028 {&hf_bundle_procflags_dest_singleton,
2029 {"Destination is Singleton", "bundle.primary.proc.single",
2030 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_SINGLETON_MASK, NULL, HFILL}
2032 {&hf_bundle_procflags_application_ack,
2033 {"Request Acknowledgement by Application", "bundle.primary.proc.ack",
2034 FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_APP_ACK_MASK, NULL, HFILL}
2036 {&hf_bundle_control_flags,
2037 {"Bundle Processing Control Flags", "bundle.primary.proc.flag",
2038 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2040 {&hf_bundle_procflags_general,
2041 {"General Flags", "bundle.primary.proc.gen",
2042 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2044 {&hf_bundle_procflags_cos,
2045 {"Cloass of Service Flags", "bundle.primary.proc.cos",
2046 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2048 {&hf_bundle_procflags_status,
2049 {"Status Report Flags", "bundle.primary.proc.status",
2050 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2052 {&hf_bundle_cosflags,
2053 {"Primary Header COS Flags", "bundle.primary.cos.flags",
2054 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2056 {&hf_bundle_cosflags_priority,
2057 {"Priority", "bundle.primary.cos.priority",
2058 FT_UINT8, BASE_DEC, NULL, BUNDLE_COSFLAGS_PRIORITY_MASK, NULL, HFILL}
2060 {&hf_bundle_srrflags,
2061 {"Primary Header Report Request Flags", "bundle.primary.srr.flag",
2062 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2064 {&hf_bundle_srrflags_report_receipt,
2065 {"Request Reception Report", "bundle.primary.srr.report",
2066 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_REPORT_MASK, NULL, HFILL}
2068 {&hf_bundle_srrflags_report_cust_accept,
2069 {"Request Report of Custody Acceptance", "bundle.primary.srr.custaccept",
2070 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_CUSTODY_MASK, NULL, HFILL}
2072 {&hf_bundle_srrflags_report_forward,
2073 {"Request Report of Bundle Forwarding", "bundle.primary.srr.forward",
2074 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_FORWARD_MASK, NULL, HFILL}
2076 {&hf_bundle_srrflags_report_delivery,
2077 {"Request Report of Bundle Delivery", "bundle.primary.srr.delivery",
2078 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELIVERY_MASK, NULL, HFILL}
2080 {&hf_bundle_srrflags_report_deletion,
2081 {"Request Report of Bundle Deletion", "bundle.primary.srr.delete",
2082 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELETION_MASK, NULL, HFILL}
2084 {&hf_bundle_srrflags_report_ack,
2085 {"Request Report of Application Ack", "bundle.primary.srr.ack",
2086 FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_ACK_MASK, NULL, HFILL}
2088 {&hf_bundle_primary_header_len,
2089 {"Bundle Header Length", "bundle.primary.len",
2090 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2092 {&hf_bundle_dest_scheme_offset,
2093 {"Destination Scheme Offset", "bundle.primary.destschemeoff",
2094 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2096 {&hf_bundle_dest_ssp_offset,
2097 {"Destination SSP Offset", "bundle.primary.destssspoff",
2098 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2100 {&hf_bundle_source_scheme_offset,
2101 {"Source Scheme Offset", "bundle.primary.srcschemeoff",
2102 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2104 {&hf_bundle_source_ssp_offset,
2105 {"Source SSP Offset", "bundle.primary.srcsspoff",
2106 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2108 {&hf_bundle_report_scheme_offset,
2109 {"Report Scheme Offset", "bundle.primary.rptschemeoff",
2110 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2112 {&hf_bundle_report_ssp_offset,
2113 {"Report SSP Offset", "bundle.primary.rptsspoff",
2114 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2116 {&hf_bundle_cust_scheme_offset,
2117 {"Custodian Scheme Offset", "bundle.primary.custschemeoff",
2118 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2120 {&hf_bundle_cust_ssp_offset,
2121 {"Custodian SSP Offset", "bundle.primary.custsspoff",
2122 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
2124 {&hf_bundle_dest_scheme,
2125 {"Destination Scheme", "bundle.primary.destination_scheme",
2126 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2128 {&hf_bundle_dest_ssp,
2129 {"Destination", "bundle.primary.destination",
2130 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2132 {&hf_bundle_source_scheme,
2133 {"Source Scheme", "bundle.primary.source_scheme",
2134 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2136 {&hf_bundle_source_ssp,
2137 {"Source", "bundle.primary.source",
2138 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2140 {&hf_bundle_report_scheme,
2141 {"Report Scheme", "bundle.primary.report_scheme",
2142 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2144 {&hf_bundle_report_ssp,
2145 {"Report", "bundle.primary.report",
2146 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2148 {&hf_bundle_custodian_scheme,
2149 {"Custodian Scheme", "bundle.primary.custodian_scheme",
2150 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2152 {&hf_bundle_custodian_ssp,
2153 {"Custodian", "bundle.primary.custodian",
2154 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
2156 {&hf_bundle_creation_timestamp,
2157 {"Creation Timestamp", "bundle.primary.timestamp",
2158 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2160 {&hf_bundle_lifetime,
2161 {"Lifetime", "bundle.primary.lifetime",
2162 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
2164 {&hf_bundle_payload_flags,
2165 {"Payload Header Processing Flags", "bundle.payload.proc.flag",
2166 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2168 {&hf_bundle_payload_flags_replicate_hdr,
2169 {"Replicate Header in Every Fragment", "bundle.payload.proc.replicate",
2170 FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_REPLICATE_MASK, NULL, HFILL}
2172 {&hf_bundle_payload_flags_xmit_report,
2173 {"Report if Can't Process Header", "bundle.payload.proc.report",
2174 FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_XMIT_STATUS, NULL, HFILL}
2176 {&hf_bundle_payload_flags_discard_on_fail,
2177 {"Discard if Can't Process Header", "bundle.payload.proc.discard",
2178 FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_DISCARD_FAILURE, NULL, HFILL}
2180 {&hf_bundle_payload_flags_last_header,
2181 {"Last Header", "bundle.payload.proc.lastheader",
2182 FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_LAST_HEADER, NULL, HFILL}
2184 {&hf_bundle_admin_statflags,
2185 {"Administrative Record Status Flags", "bundle.admin.status.flag",
2186 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2188 {&hf_bundle_admin_rcvd,
2189 {"Reporting Node Received Bundle", "bundle.admin.status.rcvd",
2190 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_RECEIVED, NULL, HFILL}
2192 {&hf_bundle_admin_accepted,
2193 {"Reporting Node Accepted Custody", "bundle.admin.status.accept",
2194 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACCEPTED, NULL, HFILL}
2196 {&hf_bundle_admin_forwarded,
2197 {"Reporting Node Forwarded Bundle", "bundle.admin.status.forward",
2198 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_FORWARDED, NULL, HFILL}
2200 {&hf_bundle_admin_delivered,
2201 {"Reporting Node Delivered Bundle", "bundle.admin.status.delivered",
2202 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELIVERED, NULL, HFILL}
2204 {&hf_bundle_admin_deleted,
2205 {"Reporting Node Deleted Bundle", "bundle.admin.status.delete",
2206 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELETED, NULL, HFILL}
2208 {&hf_bundle_admin_acked,
2209 {"Acknowledged by Application", "bundle.admin.status.ack",
2210 FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACKNOWLEDGED, NULL, HFILL}
2212 {&hf_bundle_admin_receipt_time,
2213 {"Time of Receipt", "bundle.admin.status.receipttime",
2214 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2216 {&hf_bundle_admin_accept_time,
2217 {"Time of Custody Acceptance", "bundle.admin.status.accepttime",
2218 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2220 {&hf_bundle_admin_forward_time,
2221 {"Time of Forwarding", "bundle.admin.status.forwardtime",
2222 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2224 {&hf_bundle_admin_delivery_time,
2225 {"Time of Delivery", "bundle.admin.status.deliverytime",
2226 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2228 {&hf_bundle_admin_delete_time,
2229 {"Time of Deletion", "bundle.admin.status.deletetime",
2230 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2232 {&hf_bundle_admin_ack_time,
2233 {"Time of Acknowledgement", "bundle.admin.status.acktime",
2234 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2236 {&hf_bundle_admin_timestamp_copy,
2237 {"Copy of Creation Timestamp", "bundle.admin.status.timecopy",
2238 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2240 {&hf_bundle_admin_signal_time,
2241 {"Time of Signal", "bundle.admin.signal.time",
2242 FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
2244 {&hf_block_control_flags,
2245 {"Block Processing Control Flags", "bundle.block.control.flags",
2246 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
2248 {&hf_block_control_replicate,
2249 {"Replicate Block in Every Fragment", "bundle.block.control.replicate",
2250 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_REPLICATE, NULL, HFILL}
2252 {&hf_block_control_transmit_status,
2253 {"Transmit Status if Block Can't be Processeed", "bundle.block.control.status",
2254 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_TRANSMIT_STATUS, NULL, HFILL}
2256 {&hf_block_control_delete_bundle,
2257 {"Delete Bundle if Block Can't be Processeed", "bundle.block.control.delete",
2258 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DELETE_BUNDLE, NULL, HFILL}
2260 {&hf_block_control_last_block,
2261 {"Last Block", "bundle.block.control.last",
2262 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_LAST_BLOCK, NULL, HFILL}
2264 {&hf_block_control_discard_block,
2265 {"Discard Block If Can't Process", "bundle.block.control.discard",
2266 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DISCARD_BLOCK, NULL, HFILL}
2268 {&hf_block_control_not_processed,
2269 {"Block Was Forwarded Without Processing", "bundle.block.control.process",
2270 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_NOT_PROCESSED, NULL, HFILL}
2272 {&hf_block_control_eid_reference,
2273 {"Block Contains an EID-reference Field", "bundle.block.control.eid",
2274 FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_EID_REFERENCE, NULL, HFILL}
2278 static gint *ett[] = {
2294 &ett_contact_hdr_flags,
2296 &ett_shutdown_flags,
2298 &ett_admin_rec_status,
2302 module_t *bundle_module;
2304 proto_bundle = proto_register_protocol (
2309 bundle_module = prefs_register_protocol(proto_bundle, proto_reg_handoff_bundle);
2311 proto_tcp_conv = proto_register_protocol (
2312 "DTN TCP Convergence Layer Protocol",
2317 prefs_register_uint_preference(bundle_module, "tcp.port",
2318 "Bundle Protocol TCP Port",
2319 "TCP Port to Accept Bundle Protocol Connections",
2323 prefs_register_uint_preference(bundle_module, "udp.port",
2324 "Bundle Protocol UDP Port",
2325 "UDP Port to Accept Bundle Protocol Connections",
2329 proto_register_field_array(proto_bundle, hf, array_length(hf));
2330 proto_register_subtree_array(ett, array_length(ett));
2331 register_init_routine(bundle_defragment_init);
2335 proto_reg_handoff_bundle(void)
2337 static dissector_handle_t tcp_bundle_handle;
2338 static dissector_handle_t udp_bundle_handle;
2339 static int Initialized = FALSE;
2342 tcp_bundle_handle = create_dissector_handle(dissect_tcp_bundle, proto_bundle);
2343 udp_bundle_handle = create_dissector_handle(dissect_udp_bundle, proto_bundle);
2347 dissector_delete("tcp.port", tcp_port, tcp_bundle_handle);
2348 dissector_delete("udp.port", udp_port, udp_bundle_handle);
2350 tcp_port = bundle_tcp_port;
2351 udp_port = bundle_udp_port;
2352 dissector_add("tcp.port", tcp_port, tcp_bundle_handle);
2353 dissector_add("udp.port", udp_port, udp_bundle_handle);