3 * Routines for STANAG 4406 Direct Message Profile packet disassembly.
4 * A protocol for optimised transfer of time-critical short messages
5 * for use with a reliable bearer service. Checksum and retransmission
6 * mechanisms are activated when using unreliable bearer services.
8 * Copyright 2006, Stig Bjorlykke <stig@bjorlykke.org>, Thales Norway AS
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 * Ref: http://jcs.dtic.mil/j6/cceb/acps/acp123/
35 * - Dissect extended Restrictive security categories
36 * - Add Transmission/Retransmission statistics
46 #include <epan/packet.h>
47 #include <epan/address.h>
48 #include <epan/addr_resolv.h>
49 #include <epan/to_str.h>
50 #include <epan/prefs.h>
51 #include <epan/emem.h>
52 #include <epan/expert.h>
53 #include <epan/crc16-tvb.h>
54 #include <epan/asn1.h>
55 #include <epan/strutil.h>
58 #include "packet-p1.h"
59 #include "packet-p22.h"
61 #define PNAME "Direct Message Profile"
65 /* Default UDP Port Number */
66 #define DEFAULT_DMP_PORT_RANGE "5031"
68 /* Protocol Identifier */
72 /* Versions supported */
73 #define DMP_VERSION_1 1
74 #define DMP_VERSION_2 2
76 /* Message Type (dmp.msg_type) */
83 /* Message Identifier Type (dmp.msg_id_type) */
84 #define ONLY_DMP_ID 0x0
85 #define X400_MSG_ID 0x1
86 #define NAT_MSG_ID 0x2
88 /* Report Type (dmp.report_type) */
92 /* Notification Type (dmp.notif_type) */
97 /* Address Encoding (dmp.addr_enc) */
98 #define DIRECT_ADDR 0x0
99 #define EXTENDED_ADDR 0x1
101 /* Address type (internal values) */
105 #define ORIG_P2_ADDRESS 4
107 /* Extended Address Form (dmp_addr_form) */
108 #define P1_DIRECT 0x0
109 #define P2_DIRECT 0x1
110 #define P1_EXTENDED 0x2
111 #define P2_EXTENDED 0x3
112 #define P1_P2_DIRECT 0x4
113 #define P1_DIRECT_P2_EXTENDED 0x5
114 #define P1_EXTENDED_P2_DIRECT 0x6
115 #define P1_P2_EXTENDED 0x7
117 /* Extended Address Type */
121 /* Security Policy (dmp_sec_pol) */
124 #define EXTENDED_NATIONAL 0x6
125 #define EXTENDED_MISSION 0x7
127 #define SEC_CAT_EXT_NONE 0x0
128 #define SEC_CAT_EXT_PERMISSIVE 0x1
129 #define SEC_CAT_EXT_RESTRICTIVE 0x2
131 /* Body Format (dmp.body_format) */
132 #define FREE_TEXT 0x0
133 #define FREE_TEXT_SUBJECT 0x1
134 #define STRUCTURED 0x2
136 /* Encoded Information Types */
137 #define EIT_BILATERAL 0x3
139 /* Compression Algorithm */
140 #define ALGORITHM_NONE 0x0
141 #define ALGORITHM_ZLIB 0x1
143 /* Type of structured id to print */
144 #define STRUCT_ID_NONE 0
145 #define STRUCT_ID_UINT8 1
146 #define STRUCT_ID_UINT16 2
147 #define STRUCT_ID_UINT32 3
148 #define STRUCT_ID_UINT64 4
149 #define STRUCT_ID_STRING 5
150 #define STRUCT_ID_ZSTRING 6
152 #define NAT_DECODE_NONE 0
153 #define NAT_DECODE_DMP 1
154 #define NAT_DECODE_THALES 2
156 #define IPM_MODIFIER_X400 0
158 /* Internal values for not present and reserved time values */
159 #define DMP_TIME_NOT_PRESENT -1
160 #define DMP_TIME_RESERVED -2
162 #define ILLEGAL_FORMAT "<Illegal format>"
164 /* Maximum lengths */
165 #define MAX_SIC_LEN 30
167 void proto_reg_handoff_dmp (void);
169 static int proto_dmp = -1;
171 static int hf_dmp_id = -1;
172 static int hf_mts_id = -1;
173 static int hf_ipm_id = -1;
175 static int hf_envelope = -1;
176 static int hf_envelope_protocol_id = -1;
177 static int hf_envelope_version = -1;
178 static int hf_envelope_version_value = -1;
179 static int hf_envelope_hop_count = -1;
180 static int hf_envelope_hop_count_value = -1;
181 static int hf_envelope_rec_present = -1;
182 static int hf_envelope_addr_enc = -1;
183 static int hf_envelope_checksum = -1;
184 static int hf_envelope_extensions = -1;
185 static int hf_envelope_msg_id_type = -1;
186 static int hf_envelope_msg_id_length = -1;
187 static int hf_envelope_mts_id_length = -1;
188 static int hf_envelope_ipm_id_modifier = -1;
189 static int hf_envelope_ipm_id_length = -1;
190 static int hf_envelope_mts_id = -1;
191 static int hf_envelope_ipm_id = -1;
192 static int hf_envelope_type = -1;
193 static int hf_envelope_msg_id = -1;
194 static int hf_envelope_msg_id_12bit = -1;
195 static int hf_envelope_subm_time = -1;
196 static int hf_envelope_subm_time_value = -1;
197 static int hf_envelope_time_diff_present = -1;
198 static int hf_envelope_time_diff = -1;
199 static int hf_envelope_time_diff_value = -1;
200 static int hf_envelope_flags = -1;
201 static int hf_envelope_content_id_discarded = -1;
202 static int hf_envelope_recip_reassign_prohib = -1;
203 static int hf_envelope_dl_expansion_prohib = -1;
204 static int hf_envelope_recipients = -1;
205 static int hf_envelope_ext_recipients = -1;
207 static int hf_thales_ipm_id_modifier = -1;
209 static int hf_extensions = -1;
210 static int hf_extension = -1;
211 static int hf_extension_header = -1;
212 static int hf_extension_more = -1;
213 static int hf_extension_length = -1;
214 static int hf_extension_data = -1;
216 static int hf_message_content = -1;
217 static int hf_report_content = -1;
218 static int hf_notif_content = -1;
220 static int hf_addr_recipient = -1;
221 static int hf_addr_originator = -1;
222 static int hf_addr_reporting_name = -1;
223 static int hf_addr_dl_expanded = -1;
224 static int hf_addr_int_rec = -1;
225 static int hf_addr_dir_addr_ext = -1;
226 static int hf_addr_dir_rec_no = -1;
227 static int hf_addr_dir_rec_no1 = -1;
228 static int hf_addr_dir_rec_no2 = -1;
229 static int hf_addr_dir_rec_no3 = -1;
230 static int hf_addr_dir_rec_no_generated = -1;
231 static int hf_addr_dir_rep_req1 = -1;
232 static int hf_addr_dir_rep_req2 = -1;
233 static int hf_addr_dir_rep_req3 = -1;
234 static int hf_addr_dir_not_req1 = -1;
235 static int hf_addr_dir_not_req2 = -1;
236 static int hf_addr_dir_not_req3 = -1;
237 static int hf_addr_dir_action = -1;
238 static int hf_addr_dir_address = -1;
239 static int hf_addr_dir_address1 = -1;
240 static int hf_addr_dir_address2 = -1;
241 static int hf_addr_dir_address3 = -1;
242 static int hf_addr_dir_address_generated = -1;
244 static int hf_addr_ext_form = -1;
245 static int hf_addr_ext_form_orig_v1 = -1;
246 static int hf_addr_ext_form_orig = -1;
247 static int hf_addr_ext_action = -1;
248 static int hf_addr_ext_rep_req = -1;
249 static int hf_addr_ext_not_req = -1;
250 static int hf_addr_ext_rec_ext = -1;
251 static int hf_addr_ext_rec_no = -1;
252 static int hf_addr_ext_rec_no1 = -1;
253 static int hf_addr_ext_rec_no2 = -1;
254 static int hf_addr_ext_rec_no_generated = -1;
255 static int hf_addr_ext_address = -1;
256 static int hf_addr_ext_type = -1;
257 static int hf_addr_ext_type_ext = -1;
258 static int hf_addr_ext_length = -1;
259 static int hf_addr_ext_length1 = -1;
260 static int hf_addr_ext_length2 = -1;
261 static int hf_addr_ext_length_generated = -1;
262 static int hf_addr_ext_asn1_ber = -1;
263 static int hf_addr_ext_asn1_per = -1;
264 static int hf_addr_ext_unknown = -1;
266 static int hf_message_body = -1;
267 static int hf_message_st_type = -1;
268 static int hf_message_precedence = -1;
269 static int hf_message_importance = -1;
270 static int hf_message_body_format = -1;
271 static int hf_message_sec_class_val = -1;
272 static int hf_message_sec_pol = -1;
273 static int hf_message_heading_flags = -1;
274 static int hf_message_auth_users = -1;
275 static int hf_message_subject_disc = -1;
276 static int hf_message_national_policy_id = -1;
277 static int hf_message_mission_policy_id = -1;
278 static int hf_message_sec_label = -1;
279 static int hf_message_sec_cat_nat = -1;
280 static int hf_message_sec_cat_val = -1;
281 static int hf_message_sec_cat_cl = -1;
282 static int hf_message_sec_cat_cs = -1;
283 static int hf_message_sec_cat_ex = -1;
284 static int hf_message_sec_cat_ne = -1;
285 static int hf_message_sec_cat_permissive = -1;
286 static int hf_message_sec_cat_country_code = -1;
287 static int hf_message_sec_cat_restrictive = -1;
288 static int hf_message_sec_cat_extended = -1;
289 static int hf_message_sec_cat_bit0 = -1;
290 static int hf_message_sec_cat_bit1 = -1;
291 static int hf_message_sec_cat_bit2 = -1;
292 static int hf_message_sec_cat_bit3 = -1;
293 static int hf_message_sec_cat_bit4 = -1;
294 static int hf_message_sec_cat_bit5 = -1;
295 static int hf_message_sec_cat_bit6 = -1;
296 static int hf_message_sec_cat_bit7 = -1;
297 static int hf_message_exp_time = -1;
298 static int hf_message_exp_time_val = -1;
299 static int hf_message_dtg = -1;
300 static int hf_message_dtg_sign = -1;
301 static int hf_message_dtg_val = -1;
302 static int hf_message_sic = -1;
303 static int hf_message_sic_key = -1;
304 static int hf_message_sic_key_values = -1;
305 static int hf_message_sic_key_type = -1;
306 static int hf_message_sic_key_chars = -1;
307 static int hf_message_sic_key_num = -1;
308 static int hf_message_sic_bitmap = -1;
309 static int hf_message_sic_bits = -1;
310 static int hf_message_sic_bits_any = -1;
311 static int hf_message_subj_id = -1;
312 static int hf_message_subj_mts_id = -1;
313 static int hf_message_subj_ipm_id = -1;
315 static int hf_message_subject = -1;
316 static int hf_message_eit = -1;
317 static int hf_message_compr = -1;
318 static int hf_message_body_data = -1;
319 static int hf_message_body_plain = -1;
320 static int hf_message_bodyid_uint8 = -1;
321 static int hf_message_bodyid_uint16 = -1;
322 static int hf_message_bodyid_uint32 = -1;
323 static int hf_message_bodyid_uint64 = -1;
324 static int hf_message_bodyid_string = -1;
325 static int hf_message_bodyid_zstring = -1;
326 static int hf_message_body_structured = -1;
327 static int hf_message_body_uncompr = -1;
328 static int hf_message_body_uncompressed = -1;
330 static int hf_delivery_report = -1;
331 static int hf_non_delivery_report = -1;
332 static int hf_report_type = -1;
333 static int hf_report_info_present_dr = -1;
334 static int hf_report_addr_enc_dr = -1;
335 static int hf_report_del_time = -1;
336 static int hf_report_del_time_val = -1;
337 static int hf_report_addr_enc_ndr = -1;
338 static int hf_report_reason = -1;
339 static int hf_report_info_present_ndr = -1;
340 static int hf_report_diagn = -1;
341 static int hf_report_suppl_info_len = -1;
342 static int hf_report_suppl_info = -1;
344 static int hf_receipt_notif = -1;
345 static int hf_non_receipt_notif = -1;
346 static int hf_other_notif = -1;
347 static int hf_notif_type = -1;
348 static int hf_notif_rec_time = -1;
349 static int hf_notif_rec_time_val = -1;
350 static int hf_notif_suppl_info_len = -1;
351 static int hf_notif_suppl_info = -1;
352 static int hf_notif_non_rec_reason = -1;
353 static int hf_notif_discard_reason = -1;
354 static int hf_notif_on_type = -1;
355 static int hf_notif_acp127 = -1;
356 static int hf_notif_acp127recip = -1;
358 static int hf_ack = -1;
359 static int hf_ack_reason = -1;
360 static int hf_ack_diagnostic = -1;
361 static int hf_ack_recips = -1;
363 static int hf_checksum = -1;
364 static int hf_checksum_good = -1;
365 static int hf_checksum_bad = -1;
367 static int hf_analysis_ack_time = -1;
368 static int hf_analysis_total_time = -1;
369 static int hf_analysis_retrans_time = -1;
370 static int hf_analysis_total_retrans_time = -1;
371 static int hf_analysis_msg_num = -1;
372 static int hf_analysis_msg_missing = -1;
373 static int hf_analysis_retrans_no = -1;
374 static int hf_analysis_ack_num = -1;
375 static int hf_analysis_ack_missing = -1;
376 static int hf_analysis_ack_dup_no = -1;
377 static int hf_analysis_rep_num = -1;
378 static int hf_analysis_rep_time = -1;
379 static int hf_analysis_not_num = -1;
380 static int hf_analysis_not_time = -1;
381 static int hf_analysis_msg_resend_from = -1;
382 static int hf_analysis_rep_resend_from = -1;
383 static int hf_analysis_not_resend_from = -1;
384 static int hf_analysis_ack_resend_from = -1;
386 static int hf_reserved_0x01 = -1;
387 static int hf_reserved_0x02 = -1;
388 static int hf_reserved_0x04 = -1;
389 static int hf_reserved_0x07 = -1;
390 static int hf_reserved_0x08 = -1;
391 static int hf_reserved_0x0F = -1;
392 static int hf_reserved_0x1F = -1;
393 static int hf_reserved_0x20 = -1;
394 static int hf_reserved_0x40 = -1;
395 static int hf_reserved_0xC0 = -1;
396 static int hf_reserved_0xE0 = -1;
397 static int hf_reserved_0x8000 = -1;
399 static gint ett_dmp = -1;
400 static gint ett_envelope = -1;
401 static gint ett_envelope_version = -1;
402 static gint ett_envelope_hop_count = -1;
403 static gint ett_envelope_rec_present = -1;
404 static gint ett_envelope_addr_enc = -1;
405 static gint ett_envelope_checksum = -1;
406 static gint ett_envelope_extensions = -1;
407 static gint ett_envelope_msg_id_type = -1;
408 static gint ett_envelope_msg_id = -1;
409 static gint ett_envelope_mts_id_length = -1;
410 static gint ett_envelope_ipm_id_length = -1;
411 static gint ett_envelope_cont_type = -1;
412 static gint ett_envelope_subm_time = -1;
413 static gint ett_envelope_time_diff = -1;
414 static gint ett_envelope_flags = -1;
415 static gint ett_envelope_recipients = -1;
416 static gint ett_envelope_ext_recipients = -1;
417 static gint ett_envelope_addresses = -1;
419 static gint ett_address = -1;
420 static gint ett_address_direct = -1;
421 static gint ett_address_rec_no = -1;
422 static gint ett_address_extended = -1;
423 static gint ett_address_ext_form = -1;
424 static gint ett_address_ext_rec_no = -1;
425 static gint ett_address_ext_action = -1;
426 static gint ett_address_ext_rep_req = -1;
427 static gint ett_address_ext_not_req = -1;
428 static gint ett_address_ext_type = -1;
429 static gint ett_address_ext_length = -1;
431 static gint ett_extensions = -1;
432 static gint ett_extension = -1;
433 static gint ett_extension_header = -1;
435 static gint ett_content = -1;
437 static gint ett_message = -1;
438 static gint ett_message_st_type = -1;
439 static gint ett_message_reserved = -1;
440 static gint ett_message_precedence = -1;
441 static gint ett_message_importance = -1;
442 static gint ett_message_body_format = -1;
443 static gint ett_message_sec_class = -1;
444 static gint ett_message_sec_pol = -1;
445 static gint ett_message_sec_cat = -1;
446 static gint ett_message_heading_flags = -1;
447 static gint ett_message_exp_time = -1;
448 static gint ett_message_dtg = -1;
449 static gint ett_message_sic = -1;
450 static gint ett_message_sic_key = -1;
451 static gint ett_message_sic_bitmap = -1;
452 static gint ett_message_sic_bits = -1;
453 static gint ett_message_eit = -1;
454 static gint ett_message_compr = -1;
455 static gint ett_message_body_reserved = -1;
456 static gint ett_message_body = -1;
457 static gint ett_message_body_uncompr = -1;
459 static gint ett_report = -1;
460 static gint ett_report_type = -1;
461 static gint ett_report_info_present_dr = -1;
462 static gint ett_report_info_present_ndr = -1;
463 static gint ett_report_addr_enc_dr = -1;
464 static gint ett_report_addr_enc_ndr = -1;
465 static gint ett_report_reserved = -1;
466 static gint ett_report_del_time = -1;
467 static gint ett_report_reason = -1;
468 static gint ett_report_suppl_info = -1;
469 static gint ett_report_diagn = -1;
471 static gint ett_notif = -1;
472 static gint ett_notif_type = -1;
473 static gint ett_notif_rec_time = -1;
474 static gint ett_notif_suppl_info = -1;
475 static gint ett_notif_acp127recip = -1;
477 static gint ett_ack = -1;
478 static gint ett_ack_recips = -1;
480 static gint ett_checksum = -1;
482 static gint ett_analysis = -1;
484 static dissector_handle_t dmp_handle;
486 typedef struct _dmp_id_key {
492 typedef struct _dmp_id_val {
493 gint msg_type; /* Message type */
494 guint prev_msg_id; /* Previous message package num */
495 guint msg_id; /* Message package num */
496 guint ack_id; /* Acknowledgement package num */
497 guint rep_id; /* Report package num */
498 guint not_id; /* Notification package num */
499 nstime_t msg_time; /* Message receive time */
500 nstime_t first_msg_time; /* First message receive time */
501 nstime_t prev_msg_time; /* Previous message receive time */
502 nstime_t rep_not_msg_time; /* Report or Notification time */
503 guint32 msg_resend_count; /* Message resend counter */
504 guint32 ack_resend_count; /* Acknowledgement resend counter */
507 static GHashTable *dmp_id_hash_table = NULL;
508 static GHashTable *dmp_long_id_hash_table = NULL;
510 /* Global values used in several functions */
511 static struct dmp_data {
524 guint8 mts_id_length;
525 proto_item *mts_id_item;
533 gboolean ack_rec_present;
537 /* User definable values */
538 static range_t *global_dmp_port_range;
539 static gint dmp_nat_decode = NAT_DECODE_DMP;
540 static gint dmp_local_nation = 0;
541 static gboolean use_seq_ack_analysis = TRUE;
542 static gboolean dmp_align = FALSE;
543 static gboolean dmp_subject_as_id = FALSE;
544 static gint dmp_struct_format = STRUCT_ID_NONE;
545 static guint dmp_struct_offset = 0;
546 static guint dmp_struct_length = 1;
548 typedef struct _dmp_security_class_t {
552 } dmp_security_class_t;
554 static dmp_security_class_t *dmp_security_classes;
555 static guint num_dmp_security_classes;
557 static const true_false_string addr_enc = {
558 "Use Extended Encoding", "Use Direct Encoding"
561 static const true_false_string dtg_sign = {
565 static const true_false_string report_type = {
566 "Non-Delivery Report", "Delivery Report"
569 static const value_string version_vals[] = {
580 static const value_string type_vals[] = {
582 { 0x1, "Message (E-Mail)" },
584 { 0x3, "Notification" },
585 { 0x4, "Acknowledgement" },
586 { 0x5, "Unknown Content" },
587 { 0x6, "Unknown Content" },
588 { 0x7, "Unknown Content" },
591 static const value_string msg_id_type_vals[] = {
592 { 0x0, "DMP Identifiers only" },
593 { 0x1, "X.400 Message Identifiers" },
594 { 0x2, "Nationally-defined" },
598 static const value_string msg_id_length_vals[] = {
599 { 0x0, "Full (16 bits)" },
600 { 0x1, "Short (12 bits)" },
603 static const value_string report_vals[] = {
604 { 0x0, "No Report" },
605 { 0x1, "Non-Delivery Report" },
606 { 0x2, "Delivery Report" },
610 static const value_string report_vals_ext[] = {
611 { 0x0, "No Report" },
612 { 0x1, "Non-Delivery Report" },
613 { 0x2, "Delivery Report" },
614 { 0x3, "Recipient Number Extended" },
617 /* Note the space in front of these values */
618 static const value_string report_vals_short[] = {
623 static const value_string notif_vals[] = {
624 { 0x0, "No Notification" },
625 { 0x1, "Non-Receipt Notification" },
626 { 0x2, "Receipt Notification" },
630 static const value_string notif_vals_ext[] = {
631 { 0x0, "No Notification" },
632 { 0x1, "Non-Receipt Notification" },
633 { 0x2, "Receipt Notification" },
634 { 0x3, "Direct Address Extended" },
637 /* Note the space in front of these values */
638 static const value_string notif_vals_short[] = {
643 static const value_string notif_type [] = {
644 { 0x0, "Receipt Notification (RN)" },
645 { 0x1, "Non-Receipt Notification (NRN)" },
646 { 0x2, "Other Notification (ON)" },
647 { 0x3, "Unknown Notification" },
650 /* Note the space behind these values */
651 static const value_string addr_type_str [] = {
653 { P1_ADDRESS, "P1 " },
654 { P2_ADDRESS, "P22/P772 " },
655 { ORIG_P2_ADDRESS, "P22 " },
658 static const value_string addr_form [] = {
659 { 0x0, "P1 Direct" },
660 { 0x1, "P22/P772 Direct" },
661 { 0x2, "P1 Extended" },
662 { 0x3, "P22/P772 Extended" },
663 { 0x4, "P1 and P22/P772 Direct" },
664 { 0x5, "P1 Direct and P22/P772 Extended" },
665 { 0x6, "P1 Extended and P22/P772 Direct" },
666 { 0x7, "P1 and P22/P772 Extended" },
669 static const value_string addr_form_orig_v1 [] = {
680 static const value_string addr_form_orig [] = {
685 { 0x4, "Originator and P2 Direct" },
686 { 0x5, "Originator Direct and P2 Extended" },
687 { 0x6, "Originator Extended and P2 Direct" },
688 { 0x7, "Originator and P2 Extended" },
691 static const value_string ext_addr_type [] = {
692 { 0x0, "ASN.1 BER-encoded OR-name" },
693 { 0x1, "ASN.1 PER-encoded OR-name" },
699 { 0x7, "Address Length Extended" },
702 static const value_string ext_addr_type_ext [] = {
703 { 0x0, "ASN.1 BER-encoded OR-name" },
704 { 0x1, "ASN.1 PER-encoded OR-name" },
713 static const value_string ext_addr_type_short [] = {
714 { 0x0, "OR-name (BER)" },
715 { 0x1, "OR-name (PER)" },
724 static const value_string message_type_vals[] = {
725 { 0x0, "Operation" },
731 static const value_string precedence[] = {
735 { 0x3, "Immediate" },
738 { 0x6, "Priority, Info Precedence: Routine" },
739 { 0x7, "Immediate, Info Precedence: Routine" },
742 static const value_string importance[] = {
753 static const value_string sec_class[] = {
755 { 0x1, "Unclassified" },
756 /* { 0x2, "Reserved" }, */
757 { 0x3, "Restricted" },
758 /* { 0x4, "Reserved" }, */
759 { 0x5, "Confidential" },
761 { 0x7, "Top secret" },
764 static const value_string sec_pol[] = {
765 { 0x0, "Network defined" },
766 { 0x1, "Network defined" },
767 { 0x2, "Network defined" },
768 { 0x3, "Network defined" },
770 { 0x5, "National (nation of local server)" },
771 { 0x6, "Extended, National" },
772 { 0x7, "Extended, Mission Defined" },
775 #define MAX_NATIONAL_VALUES 56
776 /* Will be built in build_national_strings() */
777 static value_string nat_pol_id[MAX_NATIONAL_VALUES+1];
779 /* For name we use the ISO 3166-1 Alfa-3 value for the country,
780 * for description we use the Country Name and
781 * for value we use the DMP value for National Policy Identifier.
783 static enum_val_t dmp_national_values[MAX_NATIONAL_VALUES+1] = {
784 { "???", "None", 0x00 },
785 { "alb", "Albania", 0x1B },
786 { "arm", "Armenia", 0x20 },
787 { "aut", "Austria", 0x21 },
788 { "aze", "Azerbaijan", 0x22 },
789 { "blr", "Belarus", 0x23 },
790 { "bel", "Belgium", 0x01 },
791 { "bih", "Bosnia and Hercegowina", 0x24 },
792 { "bgr", "Bulgaria", 0x02 },
793 { "can", "Canada", 0x03 },
794 { "hrv", "Croatia", 0x1C },
795 { "cze", "Czech Republic", 0x04 },
796 { "dnk", "Denmark", 0x05 },
797 { "est", "Estonia", 0x06 },
798 { "eapc", "Euro-Atlantic Partnership Council (EAPC)", 0x3A },
799 { "eu", "European Union (EU)", 0x3B },
800 { "fin", "Finland", 0x25 },
801 { "mkd", "Former Yugoslav Republic of Macedonia", 0x26 },
802 { "fra", "France", 0x07 },
803 { "geo", "Georgia", 0x27 },
804 { "deu", "Germany", 0x08 },
805 { "grc", "Greece", 0x09 },
806 { "hun", "Hungary", 0x0A },
807 { "isl", "Iceland", 0x0B },
808 { "isaf", "International Security Assistance Force (ISAF)", 0x3C },
809 { "irl", "Ireland", 0x28 },
810 { "ita", "Italy", 0x0C },
811 { "kaz", "Kazakhstan", 0x29 },
812 { "kgz", "Kyrgyztan", 0x2A },
813 { "lva", "Latvia", 0x0D },
814 { "ltu", "Lithuania", 0x0E },
815 { "lux", "Luxembourg", 0x0F },
816 { "mlt", "Malta", 0x2B },
817 { "mda", "Moldova", 0x2C },
818 { "mne", "Montenegro", 0x2D },
819 { "nld", "Netherlands", 0x10 },
820 { "nor", "Norway", 0x11 },
821 { "pfp", "Partnership for Peace (PfP)", 0x3D },
822 { "pol", "Poland", 0x12 },
823 { "ptr", "Portugal", 0x13 },
824 { "rou", "Romania", 0x14 },
825 { "rus", "Russian Federation", 0x2E },
826 { "srb", "Serbia", 0x2F },
827 { "svk", "Slovakia", 0x15 },
828 { "svn", "Slovenia", 0x16 },
829 { "esp", "Spain", 0x17 },
830 { "swe", "Sweden", 0x30 },
831 { "che", "Switzerland", 0x31 },
832 { "tjk", "Tajikistan", 0x32 },
833 { "tur", "Turkey", 0x18 },
834 { "tkm", "Turkmenistan", 0x33 },
835 { "gbr", "United Kingdom", 0x19 },
836 { "usa", "United States", 0x1A },
837 { "ukr", "Ukraine", 0x34 },
838 { "uzb", "Uzbekistan", 0x35 },
839 { "weu", "Western European Union (WEU)", 0x3E },
843 static const value_string ext_sec_cat[] = {
844 { 0x0, "Not present" },
845 { 0x1, "Permissive category follows" },
846 { 0x2, "Restrictive category follows" },
850 static const value_string sic_key_type[] = {
851 { 0xc, "2 or more 3-character SICs" },
852 { 0xd, "1 or more 3-to-8 character SICs" },
855 static const true_false_string sic_key_chars = {
856 "Any", "[A-Z0-9] only"
859 static const value_string sic_key_num[] = {
871 static const value_string sic_bit_vals[] = {
872 { 0, "length:6, bytes:4" },
873 { 1, "length:6, bytes:4" },
874 { 2, "length:6, bytes:4" },
875 { 3, "length:6, bytes:4" },
876 { 4, "length:6, bytes:4" },
877 { 5, "length:6, bytes:4" },
878 { 6, "length:6, bytes:4" },
879 { 7, "length:6, bytes:4" },
880 { 8, "length:6, bytes:4" },
882 { 10, "length:5, bytes:4" },
883 { 11, "length:8, bytes:6" },
884 { 12, "length:4, bytes:3" },
885 { 13, "length:4, bytes:3" },
886 { 14, "length:7, bytes:5" },
887 { 15, "length:7, bytes:5" },
890 static const value_string sic_bit_any_vals[] = {
891 { 0, "length:5, bytes:4" },
892 { 1, "length:5, bytes:4" },
893 { 2, "length:5, bytes:4" },
894 { 3, "length:5, bytes:4" },
895 { 4, "length:5, bytes:4" },
896 { 5, "length:5, bytes:4" },
897 { 6, "length:5, bytes:4" },
898 { 7, "length:5, bytes:4" },
899 { 8, "length:5, bytes:4" },
900 { 9, "length:8, bytes:7" },
901 { 10, "length:4, bytes:4" },
902 { 11, "length:7, bytes:6" },
903 { 12, "length:6, bytes:5" },
904 { 13, "length:6, bytes:5" },
905 { 14, "length:6, bytes:5" },
906 { 15, "length:6, bytes:5" },
909 static const value_string body_format_vals[] = {
910 { 0x0, "Free text" },
911 { 0x1, "Free text including subject" },
912 { 0x2, "Structured" },
916 static const value_string eit_vals[] = {
919 { 0x2, "General text" },
920 { 0x3, "Bilaterally defined (binary data)" },
927 static const value_string compression_vals[] = {
928 { 0x0, "No compression" },
929 { 0x1, "ZLib compressed" },
934 static const value_string ack_reason [] = {
935 { 0x00, "Successful, positive acknowledgement" },
936 { 0x01, "Unspecified error" },
937 { 0x02, "Checksum incorrect" },
940 static const value_string non_del_reason [] = {
941 { 0x3D, "Unknown reason" },
942 { 0x3E, "Reason code greater than 0x3c (60)" },
943 { 0x3F, "Reserved" },
946 static const value_string non_del_diagn [] = {
947 { 0x7C, "Diagnostic not specified" },
948 { 0x7D, "Unknown diagnostic" },
949 { 0x7E, "Diagnostic code greater than 0x7b (123)" },
950 { 0x7F, "Reserved" },
953 static const value_string discard_reason [] = {
954 { 0xFE, "Discard Reason absent" },
955 { 0xFF, "Reserved" },
958 static const value_string on_type [] = {
959 { 0x00, "acp127-nn" },
960 { 0x01, "acp127-pn" },
961 { 0x02, "acp127-tn" },
964 static const value_string ack_msg_type [] = {
965 { STANAG, " (message)" },
966 { IPM, " (e-mail)" },
967 { REPORT, " (report)" },
968 { NOTIF, " (notif)" },
972 static enum_val_t struct_id_options[] = {
973 { "none", "None", STRUCT_ID_NONE },
974 { "1byte", "1 Byte value", STRUCT_ID_UINT8 },
975 { "2byte", "2 Byte value", STRUCT_ID_UINT16 },
976 { "4byte", "4 Byte value", STRUCT_ID_UINT32 },
977 { "8byte", "8 Byte value", STRUCT_ID_UINT64 },
978 { "fstring", "Fixed text string", STRUCT_ID_STRING },
979 { "zstring", "Zero terminated text string", STRUCT_ID_ZSTRING },
983 static enum_val_t national_decoding[] = {
984 { "none", "None (raw data)", NAT_DECODE_NONE },
985 { "dmp", "As for regular", NAT_DECODE_DMP },
986 { "thales", "Thales XOmail", NAT_DECODE_THALES },
990 static const value_string ipm_id_modifier[] = {
991 { 0x0, "X.400 IPM Identifier" },
992 { 0x1, "Nationally-defined" },
993 { 0x2, "Nationally-defined" },
994 { 0x3, "Nationally-defined" },
998 static const value_string thales_ipm_id_modifier[] = {
999 { 0x0, "X.400 IPM Identifier" },
1000 { 0x1, "3 or 5 digits" },
1001 { 0x2, "4 digits" },
1002 { 0x3, "5 digits" },
1006 UAT_VS_DEF(dmp_security_class, nation, dmp_security_class_t, 0, "None")
1007 UAT_DEC_CB_DEF(dmp_security_class, sec_class, dmp_security_class_t)
1008 UAT_CSTRING_CB_DEF(dmp_security_class, name, dmp_security_class_t)
1011 dmp_class_copy_cb(void *dest, const void *orig, size_t len _U_)
1013 dmp_security_class_t *u = (dmp_security_class_t *)dest;
1014 const dmp_security_class_t *o = (const dmp_security_class_t *)orig;
1016 u->nation = o->nation;
1017 u->sec_class = o->sec_class;
1018 u->name = g_strdup(o->name);
1024 dmp_class_free_cb(void *r)
1026 dmp_security_class_t *u = (dmp_security_class_t *)r;
1031 static gchar *dmp_national_sec_class (guint nation, guint dmp_sec_class)
1035 for (i = 0; i < num_dmp_security_classes; i++) {
1036 dmp_security_class_t *u = &(dmp_security_classes[i]);
1038 if (u->nation == nation && u->sec_class == dmp_sec_class) {
1046 static void build_national_strings (void)
1051 ** We use values from dmp_national_values to build value_string for nat_pol_id.
1053 while (dmp_national_values[i].name && i < MAX_NATIONAL_VALUES) {
1054 nat_pol_id[i].value = dmp_national_values[i].value;
1055 nat_pol_id[i].strptr = dmp_national_values[i].description;
1058 nat_pol_id[i].value = 0;
1059 nat_pol_id[i].strptr = NULL;
1062 static const gchar *get_nat_pol_id_short (gint nation)
1065 while (dmp_national_values[i].name) {
1066 if (dmp_national_values[i].value == nation) {
1067 return dmp_national_values[i].name;
1075 static const gchar *msg_type_to_str (void)
1077 const gchar *msg_type;
1078 gboolean have_msg = FALSE;
1080 switch (dmp.msg_type) {
1083 /* Include message type and precedence */
1084 msg_type = ep_strdup_printf ("%s (%s) [%s]",
1085 val_to_str (dmp.msg_type, type_vals, "Unknown"),
1086 val_to_str (dmp.st_type, message_type_vals, "Unknown"),
1087 (dmp.prec == 0x6 || dmp.prec == 0x7) ?
1088 val_to_str (dmp.prec-4, precedence, "Unknown") :
1089 val_to_str (dmp.prec, precedence, "Unknown"));
1093 /* Include importance */
1094 msg_type = ep_strdup_printf ("%s [%s]",
1095 val_to_str (dmp.msg_type, type_vals, "Unknown"),
1096 val_to_str (dmp.prec, importance, "Unknown"));
1100 /* Include report types included */
1101 msg_type = ep_strdup_printf ("Report (%s%s%s)",
1102 dmp.dr ? "DR" : "", (dmp.dr && dmp.ndr) ? " and " : "",
1103 dmp.ndr ? "NDR" : "");
1107 msg_type = val_to_str (dmp.notif_type, notif_type, "Unknown");
1111 /* If we have msg_time we have a matching packet */
1112 have_msg = (dmp.id_val &&
1113 (dmp.id_val->msg_time.secs>0 || dmp.id_val->msg_time.nsecs>0));
1114 msg_type = ep_strdup_printf ( "Acknowledgement%s%s",
1115 have_msg ? val_to_str (dmp.id_val->msg_type, ack_msg_type,
1116 " (unknown:%d)") : "",
1117 dmp.ack_reason ? " [negative]" : "");
1121 msg_type = "Unknown";
1128 static const gchar *non_del_reason_str (guint32 value)
1131 /* Standard values according to P1 */
1132 return val_to_str (value, p1_NonDeliveryReasonCode_vals, "Unknown");
1134 return val_to_str (value, non_del_reason, "Unknown");
1138 static const gchar *non_del_diagn_str (guint32 value)
1141 /* Standard values according to P1 */
1142 return val_to_str (value, p1_NonDeliveryDiagnosticCode_vals, "Unknown");
1144 return val_to_str (value, non_del_diagn, "Unknown");
1148 static const gchar *nrn_reason_str (guint32 value)
1150 /* Standard values according to P22 */
1151 return val_to_str (value, p22_NonReceiptReasonField_vals, "Reserved");
1154 static const gchar *discard_reason_str (guint32 value)
1157 /* Standard values according to P22 */
1158 return val_to_str (value, p22_DiscardReasonField_vals, "Reserved");
1160 return val_to_str (value, discard_reason, "Unknown");
1164 /* Ref chapter 6.2.8.10 TimeDifference */
1165 static gint32 dmp_dec_time_diff (guint8 dmp_time_diff)
1167 gint32 time_diff = 0;
1169 if (dmp_time_diff <= 0x01) {
1170 /* Reserved - low value */
1171 time_diff = DMP_TIME_RESERVED;
1172 } else if (dmp_time_diff <= 0x1D) {
1173 /* Number of 2-second units (2-58 seconds) */
1174 time_diff = dmp_time_diff * 2;
1175 } else if (dmp_time_diff <= 0x91) {
1176 /* Number of 15-second units (1 min - 29 min 45 sec) */
1177 time_diff = (dmp_time_diff - 0x1D + 3) * 15;
1178 } else if (dmp_time_diff <= 0xDF) {
1179 /* Number of 5-minute units (30 min - 6 hours 55 min) */
1180 time_diff = (dmp_time_diff - 0x91 + 5) * 5*60;
1181 } else if (dmp_time_diff <= 0xF7) {
1182 /* Number of 30-minute units (7 hours - 18 hours 30 min) */
1183 time_diff = (dmp_time_diff - 0xDF + 7) * 30*60;
1185 /* Reserved - high value */
1186 time_diff = DMP_TIME_RESERVED;
1193 * Ref chapter 6.3.7.2.10 ExpiryTime
1194 * and chapter 6.3.9.2.2 DeliveryTime
1196 static gint32 dmp_dec_exp_del_time (guint8 timev, gboolean expiry_time)
1198 gint32 time_value = 0;
1200 if (expiry_time && (timev == 0x00)) {
1201 /* No expiry time */
1202 time_value = DMP_TIME_NOT_PRESENT;
1203 } else if (timev <= 0x1D) {
1204 /* Number of 2-second units (2-58 seconds) */
1205 time_value = timev * 2;
1206 } else if (timev <= 0x91) {
1207 /* Number of 15-second units (1 min - 29 min 45 sec) */
1208 time_value = (timev - 0x1D + 3) * 15;
1209 } else if (timev <= 0xBB) {
1210 /* Number of 5-minute units (30 min - 3 hours 55 min) */
1211 time_value = (timev - 0x91 + 5) * 5*60;
1212 } else if (timev <= 0xE3) {
1213 /* Number of 30-minute units (4 hours - 23 hours 30 min) */
1214 time_value = (timev - 0xBB + 7) * 30*60;
1215 } else if (timev < 0xFF) {
1216 /* Number of 2-hour units (24 - 78 hours) */
1217 time_value = (timev - 0xE3 + 11) * 2*3600;
1220 time_value = DMP_TIME_RESERVED;
1226 static gint32 dmp_dec_exp_time (guint8 expiry_time)
1228 return dmp_dec_exp_del_time (expiry_time, TRUE);
1231 static gint32 dmp_dec_del_time (guint8 delivery_time)
1233 return dmp_dec_exp_del_time (delivery_time, FALSE);
1236 /* Ref chapter 6.3.7.2.11 DTG */
1237 static gint32 dmp_dec_dtg (guint32 dtg)
1243 value = DMP_TIME_NOT_PRESENT;
1244 } else if (dtg <= 0x3C) {
1245 /* Number of minutes (0-59 min) */
1246 value = (dtg - 1) * 60;
1247 } else if (dtg <= 0x64) {
1248 /* Number of 15-minute units (1 hour - 10 hours 45 min) */
1249 value = (dtg - 0x3C + 3) * 15 * 60;
1250 } else if (dtg < 0x7F) {
1251 /* Number of hours (11-36 hours) */
1252 value = (dtg - 0x64 + 10) * 3600;
1255 value = DMP_TIME_RESERVED;
1262 * Ref chapter 7.10.11.1 Submission time
1264 * start_time (current time)
1265 * delta1 = E (encoded submission time)
1266 * delta2 = C (encoded current time)
1267 * 0x01C2 = Pn + 15min (maximum point for S1)
1268 * 0x7E38 = Pn+1 - 15min (minimum point for S3)
1269 * 0x7FF8 = Pn+1 (length of P (period))
1271 static gint32 dmp_dec_subm_time (guint16 delta1, gint32 start_time)
1273 gint32 subm_time = start_time;
1276 delta2 = (guint16) ((subm_time / 2) % 0x7FF8);
1278 if ((delta1 < 0x01C2) && (delta2 >= delta1 + 0x7E38)) {
1279 subm_time += 2 * (0x7FF8 - delta2 + delta1);
1280 } else if ((delta1 >= 0x01C2) && (delta2 < delta1 - 0x01C2)) {
1281 subm_time -= 2 * (0x7FF8 - delta1 + delta2);
1283 subm_time -= 2 * (delta2 - delta1);
1289 /* Ref chapter 6.3.7.2.12 SIC */
1290 static gboolean dmp_dec_xbyte_sic (guint64 bin, gchar *sic,
1291 guint8 no_char, gboolean any)
1293 gboolean failure = FALSE;
1298 if (no_char >= MAX_SIC_LEN) {
1299 /* Illegal length */
1300 g_snprintf (sic, MAX_SIC_LEN, "Illegal length: %d", no_char);
1310 for (i = 0; i < no_char; i++) {
1311 p = (guint64) pow (multiplier, no_char - 1 - i);
1314 sic[i] = (gchar) tmp;
1317 } else if (sic[i] <= 35) {
1318 sic[i] += ('A' - 10);
1322 } else if (sic[i] <= 61) {
1323 sic[i] += ('a' - 36);
1324 } else if (sic[i] == 62) {
1326 } else if (sic[i] == 63) {
1328 } else if (sic[i] == 64) {
1330 } else if (sic[i] == 65) {
1332 } else if (sic[i] == 66) {
1334 } else if (sic[i] == 67) {
1336 } else if (sic[i] == 68) {
1338 } else if (sic[i] == 69) {
1340 } else if (sic[i] == 70) {
1342 } else if (sic[i] == 71) {
1344 } else if (sic[i] == 72) {
1346 } else if (sic[i] == 73) {
1358 static guint dmp_id_hash (gconstpointer k)
1360 dmp_id_key *dmpx=(dmp_id_key *)k;
1364 static gint dmp_id_hash_equal (gconstpointer k1, gconstpointer k2)
1366 dmp_id_key *dmp1=(dmp_id_key *)k1;
1367 dmp_id_key *dmp2=(dmp_id_key *)k2;
1368 if (dmp1->id != dmp2->id)
1371 return (ADDRESSES_EQUAL (&dmp1->src, &dmp2->src) &&
1372 ADDRESSES_EQUAL (&dmp1->dst, &dmp2->dst));
1375 static void register_dmp_id (packet_info *pinfo, guint8 reason)
1377 dmp_id_val *dmp_data = NULL, *pkg_data = NULL;
1378 dmp_id_key *dmp_key = NULL;
1382 if (pinfo->flags.in_error_pkt) {
1383 /* No analysis of error packets */
1387 nstime_set_zero(&msg_time);
1389 dmp_key = se_new (dmp_id_key);
1391 if (!pinfo->fd->flags.visited &&
1392 (dmp.msg_type == REPORT || dmp.msg_type == NOTIF))
1394 /* Try to match corresponding message */
1395 dmp_key->id = (guint) dmp.subj_id;
1396 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
1397 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
1399 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1403 if (dmp_data->prev_msg_id > 0) {
1404 msg_id = dmp_data->prev_msg_id;
1406 msg_id = dmp_data->msg_id;
1408 msg_time = dmp_data->msg_time;
1412 if (dmp.msg_type == ACK) {
1413 dmp_key->id = (guint) dmp.subj_id;
1414 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
1415 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
1417 dmp_key->id = (guint) dmp.msg_id;
1418 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->src));
1419 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->dst));
1422 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1424 if (!pinfo->fd->flags.visited) {
1426 if (dmp.msg_type == ACK) {
1427 /* Only save this data if positive ack */
1429 if (dmp_data->ack_id == 0) {
1430 /* Only save reference to first ACK */
1431 dmp_data->ack_id = pinfo->fd->num;
1433 /* Only count when resending */
1434 dmp_data->ack_resend_count++;
1438 /* Message resent */
1439 dmp_data->msg_resend_count++;
1440 dmp_data->prev_msg_id = pinfo->fd->num;
1441 dmp_data->prev_msg_time = dmp_data->msg_time;
1442 dmp_data->msg_time = pinfo->fd->abs_ts;
1446 dmp_data = se_new0 (dmp_id_val);
1447 dmp_data->msg_type = dmp.msg_type;
1449 if (dmp.msg_type == ACK) {
1450 /* No matching message for this ack */
1451 dmp_data->ack_id = pinfo->fd->num;
1453 dmp_data->first_msg_time = pinfo->fd->abs_ts;
1454 dmp_data->msg_time = pinfo->fd->abs_ts;
1456 if (dmp.msg_type == REPORT) {
1457 dmp_data->rep_id = pinfo->fd->num;
1458 dmp_data->msg_id = msg_id;
1459 dmp_data->rep_not_msg_time = msg_time;
1460 } else if (dmp.msg_type == NOTIF) {
1461 dmp_data->not_id = pinfo->fd->num;
1462 dmp_data->msg_id = msg_id;
1463 dmp_data->rep_not_msg_time = msg_time;
1465 dmp_data->msg_id = pinfo->fd->num;
1468 g_hash_table_insert (dmp_id_hash_table, dmp_key, dmp_data);
1472 pkg_data = se_new (dmp_id_val);
1473 *pkg_data = *dmp_data;
1474 p_add_proto_data (pinfo->fd, proto_dmp, pkg_data);
1476 /* Fetch last values from data saved in packet */
1477 pkg_data = (dmp_id_val *)p_get_proto_data (pinfo->fd, proto_dmp);
1479 if (dmp_data && pkg_data && dmp.msg_type != ACK && pkg_data->ack_id == 0) {
1480 pkg_data->ack_id = dmp_data->ack_id;
1484 DISSECTOR_ASSERT (pkg_data);
1485 dmp.id_val = pkg_data;
1488 static void dmp_add_seq_ack_analysis (tvbuff_t *tvb, packet_info *pinfo,
1489 proto_tree *dmp_tree, gint offset)
1491 proto_tree *analysis_tree = NULL;
1492 proto_item *en = NULL, *eh = NULL;
1495 if (dmp.msg_type > ACK || (dmp.msg_type < ACK && !dmp.checksum) ||
1496 dmp.id_val == NULL || pinfo->flags.in_error_pkt)
1498 /* No need for seq/ack analysis */
1502 en = proto_tree_add_text (dmp_tree, tvb, 0, 0, "SEQ/ACK analysis");
1503 PROTO_ITEM_SET_GENERATED (en);
1504 analysis_tree = proto_item_add_subtree (en, ett_analysis);
1506 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
1507 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) {
1508 if (dmp.id_val->ack_id) {
1509 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb,
1510 0, 0, dmp.id_val->ack_id);
1511 PROTO_ITEM_SET_GENERATED (en);
1512 if (!dmp.checksum) {
1513 proto_item_append_text (en, " (unexpected)");
1514 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1517 } else if (dmp.checksum && !dmp.id_val->msg_resend_count) {
1518 en = proto_tree_add_item (analysis_tree, hf_analysis_ack_missing, tvb, offset, 0, ENC_NA);
1519 if (pinfo->fd->flags.visited) {
1520 /* We do not know this on first visit and we do not want to
1521 add a entry in the "Expert Severity Info" for this note */
1522 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1523 "Acknowledgement missing");
1524 PROTO_ITEM_SET_GENERATED (en);
1528 if (dmp.msg_type == REPORT) {
1529 if (dmp.id_val->msg_id) {
1530 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1531 tvb, 0, 0, dmp.id_val->msg_id);
1532 PROTO_ITEM_SET_GENERATED (en);
1534 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
1535 en = proto_tree_add_time (analysis_tree, hf_analysis_rep_time,
1537 PROTO_ITEM_SET_GENERATED (en);
1539 en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
1540 PROTO_ITEM_SET_GENERATED (en);
1542 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1545 } else if (dmp.msg_type == NOTIF) {
1546 if (dmp.id_val->msg_id) {
1547 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1548 tvb, 0, 0, dmp.id_val->msg_id);
1549 PROTO_ITEM_SET_GENERATED (en);
1551 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
1552 en = proto_tree_add_time (analysis_tree, hf_analysis_not_time,
1554 PROTO_ITEM_SET_GENERATED (en);
1556 en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
1557 PROTO_ITEM_SET_GENERATED (en);
1559 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1564 if (dmp.id_val->msg_resend_count) {
1565 en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no,
1566 tvb, 0, 0, dmp.id_val->msg_resend_count);
1567 PROTO_ITEM_SET_GENERATED (en);
1569 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1570 "Retransmission #%d",
1571 dmp.id_val->msg_resend_count);
1573 if (dmp.msg_type == REPORT) {
1574 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_resend_from,
1575 tvb, 0, 0, dmp.id_val->rep_id);
1576 } else if (dmp.msg_type == NOTIF) {
1577 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_resend_from,
1578 tvb, 0, 0, dmp.id_val->not_id);
1580 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_resend_from,
1581 tvb, 0, 0, dmp.id_val->msg_id);
1583 PROTO_ITEM_SET_GENERATED (en);
1585 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->prev_msg_time);
1586 en = proto_tree_add_time (analysis_tree, hf_analysis_retrans_time,
1588 PROTO_ITEM_SET_GENERATED (en);
1590 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
1591 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_retrans_time,
1593 PROTO_ITEM_SET_GENERATED (eh);
1595 if (dmp.id_val->first_msg_time.secs == dmp.id_val->prev_msg_time.secs &&
1596 dmp.id_val->first_msg_time.nsecs == dmp.id_val->prev_msg_time.nsecs) {
1597 /* Time values does not differ, hide the total time */
1598 PROTO_ITEM_SET_HIDDEN (eh);
1601 } else if (dmp.msg_type == ACK) {
1602 if (dmp.id_val->msg_type != ACK) {
1603 if (dmp.id_val->msg_type == REPORT) {
1604 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_num,
1605 tvb, 0, 0, dmp.id_val->rep_id);
1606 } else if (dmp.id_val->msg_type == NOTIF) {
1607 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_num,
1608 tvb, 0, 0, dmp.id_val->not_id);
1610 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1611 tvb, 0, 0, dmp.id_val->msg_id);
1613 PROTO_ITEM_SET_GENERATED (en);
1615 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->msg_time);
1616 en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time,
1618 PROTO_ITEM_SET_GENERATED (en);
1620 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
1621 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time,
1623 PROTO_ITEM_SET_GENERATED (eh);
1625 if (dmp.id_val->first_msg_time.secs == dmp.id_val->msg_time.secs &&
1626 dmp.id_val->first_msg_time.nsecs == dmp.id_val->msg_time.nsecs) {
1627 /* Time values does not differ, hide the total time */
1628 PROTO_ITEM_SET_HIDDEN (eh);
1630 /* Different times, add a reference to the message we have ack'ed */
1631 proto_item_append_text (en, " (from frame %d)",
1632 dmp.id_val->prev_msg_id);
1635 en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
1636 PROTO_ITEM_SET_GENERATED (en);
1638 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1642 if (dmp.id_val->ack_resend_count) {
1643 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no,
1644 tvb, 0, 0, dmp.id_val->ack_resend_count);
1645 PROTO_ITEM_SET_GENERATED (en);
1647 expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
1648 "Dup ACK #%d", dmp.id_val->ack_resend_count);
1650 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from,
1651 tvb, 0, 0, dmp.id_val->ack_id);
1652 PROTO_ITEM_SET_GENERATED (en);
1657 static gchar *dissect_7bit_string (tvbuff_t *tvb, gint offset, gint length)
1659 guchar *encoded = tvb_get_ephemeral_string (tvb, offset, length);
1660 guchar *decoded = ep_alloc0 ((size_t)(length * 1.2) + 1);
1661 guchar rest = 0, bits = 1;
1664 for (i = 0; i < length; i++) {
1665 decoded[len++] = encoded[i] >> bits | rest;
1666 rest = (encoded[i] << (7 - bits) & 0x7F);
1668 decoded[len++] = rest;
1676 return (gchar *) decoded;
1679 static gchar *dissect_thales_mts_id (tvbuff_t *tvb, gint offset, gint length)
1681 /* Thales XOmail uses this format: "MTA-NAME/000000000000" */
1682 if (length >= 7 && length <= 22) {
1683 return ep_strdup_printf ("%s/%08X%04X",
1684 dissect_7bit_string (tvb, offset, length - 6),
1685 tvb_get_ntohl (tvb, offset + length - 6),
1686 tvb_get_ntohs (tvb, offset + length - 2));
1689 return ILLEGAL_FORMAT;
1692 static gchar *dissect_thales_ipm_id (tvbuff_t *tvb, gint offset, gint length, gint modifier)
1694 /* Thales XOmail uses this format: "<prefix>0000 YYMMDDhhmmssZ" */
1695 if (length >= 6 && length <= 20 && modifier >= 0 && modifier <= 2) {
1696 guint number = tvb_get_ntohs (tvb, offset + length - 6);
1697 guint8 number_len = modifier + 2;
1698 time_t time = tvb_get_ntohl(tvb, offset + length - 4);
1699 struct tm *tmp = gmtime(&time);
1701 if (modifier == 1 && number >= 1024) {
1702 /* The number is in the range 65536-99999 */
1704 number += (65536 - 1024);
1707 return ep_strdup_printf ("%s%0*d %02d%02d%02d%02d%02d%02dZ",
1708 (length == 6) ? "" : dissect_7bit_string (tvb, offset, length - 6),
1710 tmp->tm_year % 100, tmp->tm_mon + 1, tmp->tm_mday,
1711 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1714 return ILLEGAL_FORMAT;
1717 /* Ref chapter 6.3.7.2.12 SIC */
1718 static gint dissect_dmp_sic (tvbuff_t *tvb, packet_info *pinfo,
1719 proto_tree *message_tree, gint offset)
1721 proto_tree *sic_tree = NULL, *bitmap_tree = NULL, *key_tree = NULL;
1722 proto_item *sf = NULL, *bf = NULL, *kf = NULL;
1724 guint8 key, bitmap, no, i, length = 0;
1725 gboolean any, no_sic = FALSE, failure = FALSE;
1726 gint bytes = 0, boffset = offset;
1729 key = tvb_get_guint8 (tvb, offset);
1730 sic = ep_alloc (MAX_SIC_LEN);
1733 /* 2 bytes, single 3-character SIC, characters [A-Z0-9] only */
1735 value = tvb_get_ntohs (tvb, offset);
1736 failure = dmp_dec_xbyte_sic (value, sic, 3, FALSE);
1737 sf = proto_tree_add_string_format (message_tree, hf_message_sic, tvb,
1739 "SIC: %s [A-Z0-9 only]%s", sic,
1740 failure ? " (invalid)": "");
1742 expert_add_info_format (pinfo, sf, PI_UNDECODED, PI_NOTE, "Illegal SIC");
1746 } else if (key <= 0xBD) {
1747 /* 3 bytes, single 3-character SIC, any valid character */
1749 value = tvb_get_ntohl (tvb, offset);
1750 value = (value >> 8) & 0x48FFFF;
1751 failure = dmp_dec_xbyte_sic (value, sic, 3, TRUE);
1752 sf = proto_tree_add_string_format (message_tree, hf_message_sic, tvb,
1754 "SIC: %s [any character]%s", sic,
1755 failure ? " (invalid)": "");
1757 expert_add_info_format (pinfo, sf, PI_UNDECODED, PI_NOTE, "Illegal SIC");
1761 } else if (key <= 0xBF) {
1762 /* Reserved (not used) */
1763 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1766 } else if (key <= 0xCF) {
1767 /* 2 or more 3-character SICs */
1769 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1770 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1772 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1773 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1775 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1776 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1777 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1781 no = (key & 0x07) + 1;
1782 for (i = 0; i < no; i++) {
1784 value = tvb_get_ntohl (tvb, offset);
1785 value = (value >> 8) & 0x48FFFF;
1788 value = tvb_get_ntohs (tvb, offset);
1791 failure = dmp_dec_xbyte_sic (value, sic, 3, any);
1792 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1794 "SIC %d: %s%s", i + 1, sic,
1795 failure ? " (invalid)": "");
1797 expert_add_info_format (pinfo, bf, PI_UNDECODED, PI_NOTE,
1802 proto_item_append_text (sf, ": %d (3 %s character)", no,
1803 any ? "any" : "[A-Z0-9]");
1805 } else if (key <= 0xDF) {
1806 /* 1 or more 3 to 8 character SICs */
1808 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1809 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1811 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1812 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1814 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1815 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1816 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1819 bitmap = tvb_get_guint8 (tvb, offset);
1820 bf = proto_tree_add_uint_format (sic_tree, hf_message_sic_bitmap, tvb,
1822 "Length Bitmap: 0x%2.2x", bitmap);
1823 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bitmap);
1824 proto_tree_add_item (bitmap_tree, hf_message_sic_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
1827 no = (key & 0x07) + 1;
1830 for (i = 0; i < no; i++) {
1831 if (bitmap & (1 << (7 - i))) {
1832 /* 4 - 8 character */
1833 key = tvb_get_guint8 (tvb, offset);
1835 /* Any valid characters */
1836 if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1839 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1840 } else if ((key & 0xC0) == 0xC0) { /* bit 7-4: 11xx */
1843 value = ((guint64)key & 0x3F)<<32|tvb_get_ntohl (tvb, offset + 1);
1844 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1847 value = ((guint64)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
1848 tvb_get_ntohl (tvb, offset + 2);
1849 } else if ((key & 0xF0) == 0x90) { /* bit 7-4: 1001 */
1852 value = ((guint64)(tvb_get_ntohl (tvb, offset)>>8) & 0x0FFF)<<32 |
1853 tvb_get_ntohl (tvb, offset + 3);
1854 } else { /* bit 7-4: 0xxx or 1000 */
1857 value = tvb_get_ntohl (tvb, offset);
1860 /* Characterts [A-Z0-9] only */
1861 if ((key & 0xE0) == 0xC0) { /* bit 7-4: 110x */
1864 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x1FFFFF;
1865 } else if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1868 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1869 } else if ((key & 0xE0) == 0xE0) { /* bit 7-4: 111x */
1872 value = ((guint64)key & 0x1F)<<32 | tvb_get_ntohl (tvb, offset +1);
1873 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1876 value = ((guint64)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
1877 tvb_get_ntohl (tvb, offset + 2);
1878 } else { /* bit 7-4: 0xxx or 1000 */
1881 value = tvb_get_ntohl (tvb, offset);
1887 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x48FFFF;
1891 value = tvb_get_ntohs (tvb, offset);
1896 failure = dmp_dec_xbyte_sic (value, sic, length, any);
1897 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1899 "SIC %d: %s (%d bytes: %" G_GINT64_MODIFIER "x)%s",
1900 i + 1, sic, bytes, value,
1901 failure ? " (invalid)": "");
1902 if (bitmap & (1 << (7 - i))) {
1903 /* Only if 4 - 8 character */
1904 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bits);
1906 proto_tree_add_item (bitmap_tree, hf_message_sic_bits_any, tvb, offset, 1, ENC_BIG_ENDIAN);
1908 proto_tree_add_item (bitmap_tree, hf_message_sic_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
1912 expert_add_info_format (pinfo, bf, PI_UNDECODED, PI_NOTE,
1917 proto_item_append_text (sf, ": %d (3-to-8 %s character)", no,
1918 any ? "any" : "[A-Z0-9]");
1920 } else if (key == 0xFE) {
1922 g_snprintf (sic, MAX_SIC_LEN, "Not present");
1926 /* Resered (not used) */
1927 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1932 /* Not added any SIC, dump text value */
1933 sf = proto_tree_add_string (message_tree, hf_message_sic, tvb, offset, 1, sic);
1937 proto_item_set_len (sf, offset - boffset);
1942 /* Ref chapter 5.2.7.1 Direct Originator Encoding */
1943 static gint dissect_dmp_direct_addr (tvbuff_t *tvb, packet_info *pinfo,
1944 proto_tree *field_tree, proto_item *tf,
1945 gint offset, gint rec_no,
1946 gint rec_ofs, gint addr_type)
1948 proto_tree *addr_tree = NULL;
1949 proto_item *en = NULL;
1953 value = tvb_get_guint8 (tvb, offset);
1954 dir_addr = (value & 0x7F);
1956 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1, tvb,
1958 "%sDirect Address (bits 6-0): %d",
1959 val_to_str (addr_type, addr_type_str, ""),
1961 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1962 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1963 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1967 value = tvb_get_guint8 (tvb, offset);
1968 dir_addr |= ((value & 0x3F) << 7);
1969 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
1971 "%sDirect Address (bits 12-7): %d",
1972 val_to_str (addr_type, addr_type_str, ""),
1974 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1975 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1976 en = proto_tree_add_item (addr_tree, hf_reserved_0x40, tvb, offset, 1, ENC_BIG_ENDIAN);
1978 expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN,
1981 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
1986 value = tvb_get_guint8 (tvb, offset);
1987 dir_addr |= ((value & 0x3F) << 13);
1988 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
1990 "%sDirect Address (bits 18-13): %d",
1991 val_to_str (addr_type,addr_type_str,""),
1993 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1994 en = proto_tree_add_item (addr_tree, hf_reserved_0xC0, tvb, offset, 1, ENC_BIG_ENDIAN);
1996 expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN,
1999 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
2003 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
2004 tvb, offset, 0, dir_addr,
2005 "%sDirect Address: %d",
2006 val_to_str (addr_type, addr_type_str, ""),
2008 PROTO_ITEM_SET_GENERATED (en);
2010 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address, tvb,
2012 "%sDirect Address: %d",
2013 val_to_str (addr_type, addr_type_str, ""),
2015 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2016 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2017 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2022 proto_item_append_text (tf, " %d", rec_no);
2023 if (rec_ofs != -1) {
2024 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2027 proto_item_append_text (tf, ", %sDirect Address: %d",
2028 val_to_str (addr_type, addr_type_str, ""), dir_addr);
2033 /* Ref 5.3.14 Extended Address */
2034 static gint dissect_dmp_ext_addr (tvbuff_t *tvb, packet_info *pinfo,
2035 proto_tree *field_tree, proto_item *tf,
2036 gint offset, gint rec_no, gint rec_ofs,
2039 proto_tree *addr_tree = NULL, *ext_tree = NULL;
2040 proto_item *en = NULL, *ef = NULL;
2043 gint boffset = offset;
2044 gboolean addr_length_extended = FALSE;
2045 asn1_ctx_t asn1_ctx;
2047 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2049 value = tvb_get_guint8 (tvb, offset);
2050 type = (value & 0xE0) >> 5;
2051 length = (value & 0x1F);
2052 ef = proto_tree_add_none_format (field_tree, hf_addr_ext_address, tvb,
2053 offset, -1, "%sExtended Address",
2054 val_to_str (addr_type, addr_type_str, ""));
2055 ext_tree = proto_item_add_subtree (ef, ett_address_extended);
2057 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type, tvb,
2058 offset, 1, value, "Address Type: %s",
2059 val_to_str (type, ext_addr_type,
2061 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2062 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2065 addr_length_extended = TRUE;
2066 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length1, tvb,
2068 "Address Length (bits 4-0): %d", length);
2069 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2070 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2074 value = tvb_get_guint8 (tvb, offset);
2075 type = ((value & 0xE0) >> 5);
2076 length |= ((value & 0x1F) << 5);
2078 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type_ext, tvb,
2079 offset, 1, value, "Address Type Ext: %s",
2080 val_to_str (type, ext_addr_type_ext,
2082 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2083 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2085 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length2, tvb,
2087 "Address Length (bits 9-5): %d",
2089 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2090 proto_tree_add_item (addr_tree, hf_addr_ext_length2, tvb, offset, 1, ENC_BIG_ENDIAN);
2093 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length, tvb,
2094 offset, 1, value, "Address Length: %d",
2096 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2097 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2101 if (type == ASN1_BER) {
2102 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, length, length);
2104 dissect_p1_ORName (FALSE, next_tvb, 0, &asn1_ctx, ext_tree,
2105 hf_addr_ext_asn1_ber);
2106 } else if (type == ASN1_PER) {
2107 proto_tree_add_item (ext_tree, hf_addr_ext_asn1_per, tvb, offset, length, ENC_NA);
2109 proto_tree_add_item (ext_tree, hf_addr_ext_unknown, tvb, offset, length, ENC_NA);
2113 if (addr_length_extended) {
2114 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length_generated,
2115 tvb, offset, 0, length,
2116 "Address Length: %d", length);
2117 PROTO_ITEM_SET_GENERATED (en);
2120 proto_item_append_text (ef, ", Type: %s, Length: %d",
2121 val_to_str (type, ext_addr_type, "Reserved"),
2125 proto_item_append_text (tf, " %d", rec_no);
2126 if (rec_ofs != -1) {
2127 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2130 proto_item_append_text (tf, ", %sExtended Address Type: %s",
2131 val_to_str (addr_type, addr_type_str, ""),
2132 val_to_str (type, ext_addr_type_short, "Reserved"));
2134 proto_item_set_len (ef, offset - boffset);
2139 /* Ref chapter 5.2.8.1 Extended Originator Encoding */
2140 static gint dissect_dmp_originator (tvbuff_t *tvb, packet_info *pinfo,
2141 proto_tree *envelope_tree, gint offset)
2143 proto_tree *field_tree = NULL, *rec_tree = NULL;
2144 proto_item *en = NULL, *tf = NULL;
2145 guint8 value, dmp_addr_form;
2146 gint boffset = offset;
2147 gboolean p2_addr = FALSE;
2149 tf = proto_tree_add_item (envelope_tree, hf_addr_originator, tvb, offset, -1, ENC_NA);
2150 field_tree = proto_item_add_subtree (tf, ett_address);
2152 if (dmp.addr_enc == DIRECT_ADDR) {
2153 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf,
2154 offset, -1, -1, ORIGINATOR);
2156 value = tvb_get_guint8 (tvb, offset);
2157 dmp_addr_form = (value & 0xE0) >> 5;
2159 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2160 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig_v1, tvb,
2163 val_to_str (dmp_addr_form,
2164 addr_form_orig_v1, "Reserved"));
2165 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2166 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig_v1, tvb, offset, 1, ENC_BIG_ENDIAN);
2168 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig, tvb,
2171 val_to_str (dmp_addr_form,
2172 addr_form_orig, "Reserved"));
2173 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2174 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig, tvb, offset, 1, ENC_BIG_ENDIAN);
2177 en = proto_tree_add_item (rec_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
2179 expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN,
2184 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2185 switch (dmp_addr_form) {
2188 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2194 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2199 proto_item_append_text (tf, " (invalid address form)");
2204 switch (dmp_addr_form) {
2208 case P1_DIRECT_P2_EXTENDED:
2209 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2215 case P1_EXTENDED_P2_DIRECT:
2216 case P1_P2_EXTENDED:
2217 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2222 proto_item_append_text (tf, " (invalid address form)");
2227 switch (dmp_addr_form) {
2230 case P1_EXTENDED_P2_DIRECT:
2231 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2237 case P1_DIRECT_P2_EXTENDED:
2238 case P1_P2_EXTENDED:
2239 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2240 -1, ORIG_P2_ADDRESS);
2248 if (dmp.msg_type == NOTIF) {
2249 en = proto_tree_add_boolean (field_tree, hf_addr_int_rec, tvb,
2252 en = proto_tree_add_boolean (field_tree, hf_addr_dl_expanded, tvb,
2255 PROTO_ITEM_SET_GENERATED (en);
2258 proto_item_set_len (tf, offset - boffset);
2263 static void dmp_add_recipient_info (proto_item *tf, guint8 rep_req,
2264 guint8 not_req, gboolean action)
2266 if (rep_req || not_req) {
2267 proto_item_append_text (tf, ", Request:");
2270 proto_item_append_text (tf, "%s",
2271 val_to_str (rep_req, report_vals_short, ""));
2274 dmp.notif_req = TRUE;
2275 proto_item_append_text (tf, "%s",
2276 val_to_str (not_req, notif_vals_short, ""));
2279 if (dmp.msg_type == STANAG) {
2280 proto_item_append_text (tf, " (Action)");
2281 } else if (dmp.msg_type == IPM) {
2282 proto_item_append_text (tf, " (To)");
2285 if (dmp.msg_type == STANAG) {
2286 proto_item_append_text (tf, " (Info)");
2287 } else if (dmp.msg_type == IPM) {
2288 proto_item_append_text (tf, " (Cc)");
2293 /* Ref chapter 5.2.7 Direct Recipient Encoding */
2294 static gint dissect_dmp_direct_encoding (tvbuff_t *tvb, packet_info *pinfo,
2295 proto_tree *field_tree, proto_item *tf,
2296 gint offset, guint *prev_rec_no)
2299 proto_tree *addr_tree = NULL, *rec_tree = NULL;
2300 proto_item *en = NULL;
2301 guint8 rep_req = 0, not_req = 0, value;
2302 gint rec_no, rec_ofs = -1, dir_addr;
2303 gboolean action = FALSE, dir_addr_extended = FALSE;
2305 value = tvb_get_guint8 (tvb, offset);
2306 rec_no = (value & 0xF0) >> 4;
2307 rep_req = (value & 0x0C) >> 2;
2308 not_req = (value & 0x03);
2310 if (rep_req == 0x03) {
2311 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no1,
2312 tvb, offset, 1, value,
2313 "Recipient Number (bits 3-0): %d"
2314 " (offset from previous)",
2315 (value & 0xF0) >> 4);
2317 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no,
2318 tvb, offset, 1, value,
2319 "Recipient Number Offset: %d"
2320 " (offset from previous)",
2321 (value & 0xF0) >> 4);
2323 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2324 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2325 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2326 proto_tree_add_item (rec_tree, hf_addr_dir_not_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2329 value = tvb_get_guint8 (tvb, offset);
2330 dir_addr = (value & 0x7F);
2331 action = (value & 0x80);
2332 if (not_req == 0x03) {
2333 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1,
2334 tvb, offset, 1, value,
2335 "Direct Address (bits 6-0): %d",
2338 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address,
2339 tvb, offset, 1, value,
2340 "Direct Address: %d",
2343 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2344 proto_tree_add_item (addr_tree, hf_addr_dir_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2345 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2348 if (rep_req == 0x03) {
2349 /* Extended Recipient Number 1 */
2350 value = tvb_get_guint8 (tvb, offset);
2351 rec_no |= ((value & 0x3F) << 4);
2353 rep_req = (value & 0xC0) >> 6;
2355 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no2,
2356 tvb, offset, 1, value,
2357 "Recipient Number (bits 9-4): %d"
2358 " (offset from previous)",
2360 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2361 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2362 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2365 if (rep_req == 0x03) {
2366 /* Extended Recipient Number 2 */
2367 value = tvb_get_guint8 (tvb, offset);
2368 rec_no |= ((value & 0x1F) << 10);
2370 rep_req = (value & 0xC0) >> 6;
2372 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no3,
2373 tvb, offset, 1, value,
2374 "Recipient Number (bits 14-10): %d"
2375 " (offset from previous)",
2377 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2378 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2379 en = proto_tree_add_item (rec_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
2381 expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN,
2384 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no3, tvb, offset, 1, ENC_BIG_ENDIAN);
2389 if (not_req == 0x03) {
2390 /* Extended Direct Address 1 */
2391 dir_addr_extended = TRUE;
2392 value = tvb_get_guint8 (tvb, offset);
2393 dir_addr |= ((value & 0x3F) << 7);
2394 not_req = (value & 0xC0) >> 6;
2396 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
2398 "Direct Address (bits 12-7): %d",
2400 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2401 proto_tree_add_item (addr_tree, hf_addr_dir_not_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2402 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
2405 if (not_req == 0x03) {
2406 /* Extended Direct Address 2 */
2407 value = tvb_get_guint8 (tvb, offset);
2408 dir_addr |= ((value & 0x3F) << 13);
2409 not_req = (value & 0xC0) >> 6;
2411 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
2413 "Direct Address (bits 18-13): %d",
2415 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2416 proto_tree_add_item (addr_tree, hf_addr_dir_not_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2417 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
2422 rec_no += *prev_rec_no;
2423 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2426 *prev_rec_no = rec_no;
2428 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no_generated,
2429 tvb, offset, 0, rec_no,
2430 "Recipient Number: %d", rec_no);
2431 if (rec_no > 32767) {
2432 proto_item_append_text (en, " (maximum 32767)");
2433 expert_add_info_format (pinfo, en, PI_MALFORMED, PI_WARN,
2434 "Recipient number too big");
2436 PROTO_ITEM_SET_GENERATED (en);
2438 if (dir_addr_extended) {
2439 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
2440 tvb, offset, 0, dir_addr,
2441 "Direct Address: %d", dir_addr);
2442 PROTO_ITEM_SET_GENERATED (en);
2445 proto_item_append_text (tf, " %d", rec_no);
2446 if (rec_ofs != -1) {
2447 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2450 proto_item_append_text (tf, ", Direct Address: %d", dir_addr);
2451 dmp_add_recipient_info (tf, rep_req, not_req, action);
2456 /* Ref 5.2.8.2 Extended Recipient Encoding */
2457 static gint dissect_dmp_ext_encoding (tvbuff_t *tvb, packet_info *pinfo,
2458 proto_tree *field_tree,
2459 proto_item *tf, gint offset,
2462 proto_tree *addr_tree = NULL;
2463 proto_item *en = NULL;
2464 guint8 rep_req = 0, not_req = 0;
2465 guint8 value, dmp_addr_form;
2466 gboolean action = FALSE;
2467 gint rec_no, rec_ofs = -1;
2469 value = tvb_get_guint8 (tvb, offset);
2470 dmp_addr_form = (value & 0xE0) >> 5;
2471 action = (value & 0x10);
2472 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form, tvb,
2475 val_to_str (dmp_addr_form,
2476 addr_form, "Reserved"));
2477 addr_tree = proto_item_add_subtree (en, ett_address_ext_form);
2478 proto_tree_add_item (addr_tree, hf_addr_ext_form, tvb, offset, 1, ENC_BIG_ENDIAN);
2480 en = proto_tree_add_boolean_format (field_tree, hf_addr_ext_action, tvb,
2481 offset, 1, value, "Action: %s",
2482 action ? "Yes" : "No");
2483 addr_tree = proto_item_add_subtree (en, ett_address_ext_action);
2484 proto_tree_add_item (addr_tree, hf_addr_ext_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2486 rep_req = (value & 0x0C) >> 2;
2487 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rep_req, tvb,
2489 "Report Request: %s",
2490 val_to_str ((value & 0x0C) >> 2,
2491 report_vals, "Reserved"));
2492 addr_tree = proto_item_add_subtree (en, ett_address_ext_rep_req);
2493 proto_tree_add_item (addr_tree, hf_addr_ext_rep_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2495 not_req = (value & 0x03);
2496 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_not_req, tvb,
2498 "Notification Request: %s",
2499 val_to_str (value & 0x03,
2500 notif_vals, "Reserved"));
2501 addr_tree = proto_item_add_subtree (en, ett_address_ext_not_req);
2502 proto_tree_add_item (addr_tree, hf_addr_ext_not_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2505 value = tvb_get_guint8 (tvb, offset);
2506 rec_no = (value & 0x7F);
2508 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no1, tvb,
2510 "Recipient Number (bits 6-0): %d"
2511 " (offset from previous)",
2513 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2514 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2515 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2519 value = tvb_get_guint8 (tvb, offset);
2520 rec_no |= (value << 7);
2522 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no2, tvb,
2524 "Recipient Number (bits 14-7): %d"
2525 " (offset from previous)", value);
2526 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2527 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2531 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no, tvb,
2533 "Recipient Number Offset: %d"
2534 " (offset from previous)",
2536 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2537 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2538 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2543 rec_no += *prev_rec_no;
2544 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2547 *prev_rec_no = rec_no;
2549 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no_generated,
2550 tvb, offset, 0, rec_no,
2551 "Recipient Number: %d", rec_no);
2552 if (rec_no > 32767) {
2553 proto_item_append_text (en, " (maximum 32767)");
2554 expert_add_info_format (pinfo, en, PI_MALFORMED, PI_WARN,
2555 "Recipient number too big");
2557 PROTO_ITEM_SET_GENERATED (en);
2559 switch (dmp_addr_form) {
2563 case P1_DIRECT_P2_EXTENDED:
2564 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2565 rec_no, rec_ofs, P1_ADDRESS);
2569 case P1_EXTENDED_P2_DIRECT:
2570 case P1_P2_EXTENDED:
2571 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2572 rec_no, rec_ofs, P1_ADDRESS);
2577 switch (dmp_addr_form) {
2581 case P1_EXTENDED_P2_DIRECT:
2582 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2583 rec_no, rec_ofs, P2_ADDRESS);
2587 case P1_DIRECT_P2_EXTENDED:
2588 case P1_P2_EXTENDED:
2589 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2590 rec_no, rec_ofs, P2_ADDRESS);
2595 dmp_add_recipient_info (tf, rep_req, not_req, action);
2600 /* Ref chapter 5.2 Address encoding */
2601 static gint dissect_dmp_address (tvbuff_t *tvb, packet_info *pinfo,
2602 proto_tree *envelope_tree,
2603 gint offset, guint *prev_rec_no,
2604 gboolean reporting_name)
2606 proto_tree *field_tree = NULL;
2607 proto_item *tf = NULL;
2608 gint boffset = offset;
2610 if (reporting_name) {
2611 tf = proto_tree_add_item (envelope_tree, hf_addr_reporting_name, tvb, offset, -1, ENC_NA);
2613 tf = proto_tree_add_none_format (envelope_tree, hf_addr_recipient, tvb,
2614 offset, -1, "Recipient Number");
2616 field_tree = proto_item_add_subtree (tf, ett_address);
2618 if (dmp.addr_enc == DIRECT_ADDR) {
2619 offset = dissect_dmp_direct_encoding (tvb, pinfo, field_tree, tf,
2620 offset, prev_rec_no);
2622 offset = dissect_dmp_ext_encoding (tvb, pinfo, field_tree, tf, offset,
2626 proto_item_set_len (tf, offset - boffset);
2631 /* Ref chapter 6.2.9 Acknowledgement */
2632 static gint dissect_dmp_ack (tvbuff_t *tvb, packet_info *pinfo,
2633 proto_tree *dmp_tree, gint offset)
2635 proto_tree *ack_tree = NULL, *recip_tree = NULL;
2636 proto_item *en = NULL, *rt = NULL;
2637 proto_item *hidden_item;
2638 guint prev_rec_no = 0;
2639 gint rec_len, rec_no = 0;
2640 gint boffset = offset;
2642 en = proto_tree_add_item (dmp_tree, hf_ack, tvb, offset, 4, ENC_NA);
2643 ack_tree = proto_item_add_subtree (en, ett_ack);
2645 dmp.ack_reason = tvb_get_guint8 (tvb, offset);
2646 proto_item_append_text (en, ", Reason: %s",
2647 val_to_str (dmp.ack_reason, ack_reason, "Reserved"));
2649 rt = proto_tree_add_item (ack_tree, hf_ack_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
2650 if (dmp.ack_reason != 0) {
2651 expert_add_info_format (pinfo, rt, PI_RESPONSE_CODE, PI_NOTE, "ACK reason: %s",
2652 val_to_str (dmp.ack_reason, ack_reason, "Reserved"));
2656 proto_tree_add_item (ack_tree, hf_ack_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN);
2659 /* Subject Message Identifier */
2660 dmp.subj_id = tvb_get_ntohs (tvb, offset);
2661 proto_tree_add_item (ack_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2662 hidden_item = proto_tree_add_item (ack_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2663 PROTO_ITEM_SET_HIDDEN (hidden_item);
2666 if (use_seq_ack_analysis) {
2667 register_dmp_id (pinfo, dmp.ack_reason);
2670 if (dmp.ack_rec_present) {
2671 /* Recipient List */
2672 rec_len = tvb_length (tvb);
2676 if (offset < rec_len) {
2677 rt = proto_tree_add_item (ack_tree, hf_ack_recips, tvb, offset, -1, ENC_NA);
2678 recip_tree = proto_item_add_subtree (rt, ett_ack_recips);
2679 while (offset < rec_len) {
2680 offset = dissect_dmp_address (tvb, pinfo, recip_tree, offset,
2681 &prev_rec_no, FALSE);
2684 proto_item_append_text (rt, ", No Recipients: %d", rec_no);
2685 proto_item_set_len (rt, offset - boffset - 4);
2686 proto_item_set_len (en, offset - boffset);
2693 static gint dissect_mts_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2694 gint offset, gboolean subject)
2696 proto_item *hidden_item;
2699 if (dmp.msg_id_type == X400_MSG_ID || dmp_nat_decode == NAT_DECODE_DMP) {
2700 mts_id = dissect_7bit_string (tvb, offset, dmp.mts_id_length);
2701 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2702 mts_id = dissect_thales_mts_id (tvb, offset, dmp.mts_id_length);
2704 mts_id = tvb_bytes_to_str (tvb, offset, dmp.mts_id_length);
2706 proto_item_append_text (dmp.mts_id_item, " (%zu bytes decompressed)", strlen (mts_id));
2707 mts_id = format_text (mts_id, strlen (mts_id));
2709 proto_tree_add_string (tree, hf_message_subj_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2710 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2711 /* Read from hash, for analysis */
2712 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, mts_id));
2714 proto_tree_add_string (tree, hf_envelope_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2715 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2716 /* Insert into hash, for analysis */
2717 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (mts_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2719 PROTO_ITEM_SET_HIDDEN (hidden_item);
2720 offset += dmp.mts_id_length;
2725 static gint dissect_ipm_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2726 gint offset, gboolean subject)
2728 proto_tree *field_tree;
2729 proto_item *tf, *hidden_item;
2731 gint length, modifier, ipm_id_length;
2733 length = tvb_get_guint8 (tvb, offset);
2734 modifier = (length & 0xC0) >> 6;
2735 ipm_id_length = length & 0x3F;
2737 tf = proto_tree_add_uint_format (tree, hf_envelope_ipm_id_length,
2738 tvb, offset, 1, ipm_id_length,
2739 "IPM Identifier Length: %u",
2741 field_tree = proto_item_add_subtree (tf, ett_envelope_ipm_id_length);
2742 if ((dmp.msg_id_type == NAT_MSG_ID || modifier != IPM_MODIFIER_X400) && dmp_nat_decode == NAT_DECODE_THALES) {
2743 proto_tree_add_item (field_tree, hf_thales_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2745 proto_tree_add_item (field_tree, hf_envelope_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2747 proto_tree_add_item (field_tree, hf_envelope_ipm_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2750 if (modifier == IPM_MODIFIER_X400 || dmp_nat_decode == NAT_DECODE_DMP) {
2751 ipm_id = dissect_7bit_string (tvb, offset, ipm_id_length);
2752 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2753 ipm_id = dissect_thales_ipm_id (tvb, offset, ipm_id_length, modifier);
2755 ipm_id = tvb_bytes_to_str (tvb, offset, ipm_id_length);
2757 proto_item_append_text (tf, " (%zu bytes decompressed)", strlen (ipm_id));
2758 ipm_id = format_text (ipm_id, strlen (ipm_id));
2760 proto_tree_add_string (tree, hf_message_subj_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2761 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2762 /* Read from hash, for analysis */
2763 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, ipm_id));
2765 proto_tree_add_string (tree, hf_envelope_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2766 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2767 /* Insert into hash, for analysis */
2768 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (ipm_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2770 PROTO_ITEM_SET_HIDDEN (hidden_item);
2771 offset += ipm_id_length;
2776 /* Ref chapter 6.2.7 Envelope structure */
2777 static gint dissect_dmp_envelope (tvbuff_t *tvb, packet_info *pinfo,
2778 proto_tree *dmp_tree, gint offset)
2780 proto_tree *envelope_tree = NULL;
2781 proto_tree *field_tree = NULL;
2782 proto_item *en = NULL, *tf = NULL, *vf = NULL;
2783 proto_item *hidden_item;
2784 guint8 envelope, time_diff;
2785 guint16 subm_time, no_rec, value16;
2787 gchar *env_flags = NULL;
2788 guint prev_rec_no = 0;
2789 gint boffset = offset, i;
2790 gboolean using_short_id = FALSE;
2792 en = proto_tree_add_item (dmp_tree, hf_envelope, tvb, offset, 10, ENC_NA);
2793 envelope_tree = proto_item_add_subtree (en, ett_envelope);
2795 envelope = tvb_get_guint8 (tvb, offset);
2796 dmp.prot_id = (envelope & 0xF8) >> 3;
2797 dmp.version = (envelope & 0x07) + 1;
2799 /* Protocol Version */
2800 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_version,
2801 tvb, offset, 1, dmp.version,
2802 "Protocol Version: %d", dmp.version);
2804 field_tree = proto_item_add_subtree (tf, ett_envelope_version);
2805 vf = proto_tree_add_item (field_tree, hf_envelope_protocol_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2806 if (dmp.prot_id == PROT_NAT) {
2807 proto_item_append_text (vf, " (national version of DMP)");
2808 proto_item_append_text (tf, " (national)");
2809 } else if (dmp.prot_id == PROT_DMP) {
2810 proto_item_append_text (vf, " (correct)");
2812 proto_item_append_text (vf, " (incorrect, should be 0x1d)");
2814 vf = proto_tree_add_item (field_tree, hf_envelope_version_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2817 if (dmp.version > DMP_VERSION_2) {
2818 /* Unsupported DMP Version */
2819 proto_item_append_text (vf, " (unsupported)");
2820 proto_item_append_text (tf, " (unsupported)");
2821 expert_add_info_format (pinfo, vf, PI_UNDECODED, PI_ERROR,
2822 "Unsupported DMP Version: %d", dmp.version);
2826 envelope = tvb_get_guint8 (tvb, offset);
2827 dmp.addr_enc = ((envelope & 0x10) >> 4);
2828 dmp.checksum = ((envelope & 0x08) >> 3);
2829 dmp.msg_type = (envelope & 0x07);
2831 if (dmp.msg_type != ACK) {
2833 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_hop_count,
2834 tvb, offset, 1, envelope,
2835 "Hop Count: %d", (envelope & 0xE0) >> 5);
2836 field_tree = proto_item_add_subtree (tf, ett_envelope_hop_count);
2837 proto_tree_add_item (field_tree, hf_envelope_hop_count_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2839 if (dmp.version >= DMP_VERSION_2) {
2840 /* Extensions Present */
2841 dmp.extensions = (envelope & 0x80);
2842 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2843 tvb, offset, 1, envelope,
2845 (envelope & 0x80) ? "Present" : "Absent");
2846 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2847 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2850 /* Recipient Present */
2851 dmp.ack_rec_present = (envelope & 0x20);
2852 tf = proto_tree_add_boolean_format (envelope_tree,hf_envelope_rec_present,
2853 tvb, offset, 1, envelope,
2854 "Recipient Present: %s",
2855 (envelope & 0x20) ? "Present" : "Absent");
2856 field_tree = proto_item_add_subtree (tf, ett_envelope_rec_present);
2857 proto_tree_add_item (field_tree, hf_envelope_rec_present, tvb, offset, 1, ENC_BIG_ENDIAN);
2860 /* Address Encoding */
2861 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_addr_enc,
2862 tvb, offset, 1, envelope,
2863 "Address Encoding: %s",
2865 addr_enc.true_string :
2866 addr_enc.false_string);
2867 field_tree = proto_item_add_subtree (tf, ett_envelope_addr_enc);
2868 proto_tree_add_item (field_tree, hf_envelope_addr_enc, tvb, offset, 1, ENC_BIG_ENDIAN);
2870 /* Checksum Present */
2871 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_checksum,
2872 tvb, offset, 1, envelope,
2874 (envelope & 0x08) ? "Used" : "Not used");
2875 field_tree = proto_item_add_subtree (tf, ett_envelope_checksum);
2876 proto_tree_add_item (field_tree, hf_envelope_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
2879 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_type,
2880 tvb, offset, 1, envelope,
2881 "Content Type: %s (%d)",
2882 val_to_str (envelope & 0x07,
2883 type_vals, "Unknown"),
2885 field_tree = proto_item_add_subtree (tf, ett_envelope_cont_type);
2886 proto_tree_add_item (field_tree, hf_envelope_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2888 proto_item_append_text (en, ", Checksum %s", (envelope >> 3) & 0x01 ? "Used" : "Not used");
2891 if (dmp.msg_type >= ACK) {
2892 proto_item_set_len (en, offset - boffset);
2896 if (dmp.version >= DMP_VERSION_2) {
2897 envelope = tvb_get_guint8 (tvb, offset);
2898 /* Extensions Present */
2899 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2900 tvb, offset, 1, envelope,
2902 (envelope & 0x80) ? "Present" : "Absent");
2903 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2904 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2905 dmp.extensions = (envelope & 0x80);
2907 /* Message Identifier Type */
2908 dmp.msg_id_type = (envelope & 0x60) >> 5;
2909 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_msg_id_type,
2910 tvb, offset, 1, envelope,
2911 "Message Identifier Type: %s (%d)",
2912 val_to_str (dmp.msg_id_type, msg_id_type_vals, "Unknown"),
2914 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id_type);
2915 proto_tree_add_item (field_tree, hf_envelope_msg_id_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2917 if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
2918 /* MTS Identifier Length */
2919 dmp.mts_id_length = (envelope & 0x1F);
2920 dmp.mts_id_item = proto_tree_add_uint_format (envelope_tree, hf_envelope_mts_id_length,
2921 tvb, offset, 1, envelope,
2922 "MTS Identifier Length: %u",
2924 field_tree = proto_item_add_subtree (dmp.mts_id_item, ett_envelope_mts_id_length);
2925 proto_tree_add_item (field_tree, hf_envelope_mts_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2928 proto_tree_add_item (field_tree, hf_envelope_msg_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2929 if (envelope & 0x10) {
2930 /* Using Short Identifier (12 bits) */
2931 using_short_id = TRUE;
2933 tf = proto_tree_add_item (field_tree, hf_reserved_0x0F, tvb, offset, 1, ENC_BIG_ENDIAN);
2934 if (envelope & 0x0F) {
2935 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN, "Reserved value");
2942 /* Message Identifier */
2943 dmp.msg_id = tvb_get_ntohs (tvb, offset);
2944 if (using_short_id) {
2945 dmp.msg_id &= 0x0FFF;
2947 tf = proto_tree_add_uint (envelope_tree, hf_envelope_msg_id, tvb, offset, 2, dmp.msg_id);
2948 hidden_item = proto_tree_add_uint (envelope_tree, hf_dmp_id, tvb, offset, 2, dmp.msg_id);
2949 if (using_short_id) {
2950 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id);
2951 proto_tree_add_item (field_tree, hf_envelope_msg_id_12bit, tvb, offset, 2, ENC_BIG_ENDIAN);
2952 } else if (dmp.version >= DMP_VERSION_2 && dmp.msg_id_type == ONLY_DMP_ID && dmp.msg_id < 4096) {
2953 expert_add_info_format (pinfo, tf, PI_PROTOCOL, PI_NOTE, "Id < 4096 - should use ShortId");
2955 PROTO_ITEM_SET_HIDDEN (hidden_item);
2958 if (dmp.version >= DMP_VERSION_2) {
2959 if ((dmp.msg_type != REPORT) && (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID)) {
2960 offset = dissect_mts_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
2964 /* Submission Time */
2965 subm_time = tvb_get_ntohs (tvb, offset);
2966 dmp.subm_time = dmp_dec_subm_time ((guint16)(subm_time & 0x7FFF),
2967 (gint32) pinfo->fd->abs_ts.secs);
2968 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_subm_time, tvb,
2969 offset, 2, subm_time,
2970 "Submission time: %s",
2971 (subm_time & 0x7FFF) >= 0x7FF8 ?
2973 abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
2974 field_tree = proto_item_add_subtree (tf, ett_envelope_subm_time);
2975 proto_tree_add_item (field_tree, hf_envelope_time_diff_present, tvb, offset, 2, ENC_BIG_ENDIAN);
2976 proto_tree_add_item (field_tree, hf_envelope_subm_time_value, tvb, offset, 2, ENC_BIG_ENDIAN);
2979 if (subm_time & 0x8000) {
2980 /* Timed Difference */
2981 time_diff = tvb_get_guint8 (tvb, offset);
2982 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_time_diff,
2983 tvb, offset, 1, time_diff,
2984 "Time Difference: ");
2985 field_tree = proto_item_add_subtree (tf, ett_envelope_time_diff);
2986 proto_tree_add_item (field_tree, hf_envelope_time_diff_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2987 secs = dmp_dec_time_diff (time_diff);
2988 if (secs == DMP_TIME_RESERVED) {
2989 proto_item_append_text (tf, "Reserved (0x%2.2x)", time_diff);
2991 proto_item_append_text (tf, "%s", time_secs_to_str (secs));
2996 /* Envelope Flags */
2997 envelope = tvb_get_guint8 (tvb, offset);
2998 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_flags,
2999 tvb, offset, 1, envelope,
3002 field_tree = proto_item_add_subtree (tf, ett_envelope_flags);
3003 proto_tree_add_item (field_tree, hf_envelope_content_id_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
3004 proto_tree_add_item (field_tree, hf_envelope_recip_reassign_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
3005 proto_tree_add_item (field_tree, hf_envelope_dl_expansion_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
3007 if (envelope & 0xE0) {
3008 env_flags = ep_strdup_printf ("%s%s%s",
3009 (envelope & 0x80) ? ", ContId discarded" : "",
3010 (envelope & 0x40) ? ", Reass prohibited" : "",
3011 (envelope & 0x20) ? ", DLE prohibited" : "");
3012 proto_item_append_text (tf, ":%s", &env_flags[1]);
3014 proto_item_append_text (tf, " (none)");
3017 /* Recipient Count */
3018 no_rec = (envelope & 0x1F);
3019 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_recipients,
3020 tvb, offset, 1, envelope,
3021 "Recipient Count: %d", no_rec);
3023 field_tree = proto_item_add_subtree (tf, ett_envelope_recipients);
3024 proto_tree_add_item (field_tree, hf_envelope_recipients, tvb, offset, 1, ENC_BIG_ENDIAN);
3028 /* Extended Recipient Count */
3029 value16 = tvb_get_ntohs (tvb, offset);
3030 no_rec = value16 & 0x7FFF;
3031 tf = proto_tree_add_uint_format (envelope_tree,hf_envelope_ext_recipients,
3032 tvb, offset, 2, value16,
3033 "Extended Recipient Count: %d%s", no_rec,
3035 " (incorrect, reserved value)" : ""));
3037 field_tree = proto_item_add_subtree (tf, ett_envelope_ext_recipients);
3038 en = proto_tree_add_item (field_tree, hf_reserved_0x8000, tvb, offset, 2, ENC_BIG_ENDIAN);
3039 if (value16 & 0x8000) {
3040 expert_add_info_format (pinfo, en, PI_UNDECODED, PI_WARN,
3043 proto_tree_add_item (field_tree, hf_envelope_ext_recipients, tvb, offset, 2, ENC_BIG_ENDIAN);
3047 if (dmp.msg_type != REPORT) {
3048 /* Originator - Not present for reports */
3049 offset = dissect_dmp_originator (tvb, pinfo, envelope_tree, offset);
3052 for (i = 1; i <= no_rec; i++) {
3054 offset = dissect_dmp_address (tvb, pinfo, envelope_tree, offset,
3055 &prev_rec_no, FALSE);
3058 if (dmp.version >= DMP_VERSION_2) {
3059 if ((dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) &&
3060 dmp.notif_req && (dmp.msg_type == STANAG || dmp.msg_type == IPM))
3062 offset = dissect_ipm_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
3066 proto_item_set_len (en, offset - boffset);
3071 static void dissect_dmp_structured_id (tvbuff_t *tvb, proto_tree *body_tree,
3076 offset += dmp_struct_offset;
3077 switch (dmp_struct_format) {
3079 case STRUCT_ID_UINT8:
3080 dmp.struct_id = ep_strdup_printf ("%u", tvb_get_guint8 (tvb, offset));
3081 proto_tree_add_item (body_tree, hf_message_bodyid_uint8, tvb, offset, 1, ENC_BIG_ENDIAN);
3084 case STRUCT_ID_UINT16:
3085 dmp.struct_id = ep_strdup_printf ("%u", tvb_get_ntohs (tvb, offset));
3086 proto_tree_add_item (body_tree, hf_message_bodyid_uint16, tvb, offset, 2, ENC_BIG_ENDIAN);
3089 case STRUCT_ID_UINT32:
3090 dmp.struct_id = ep_strdup_printf ("%u", tvb_get_ntohl (tvb, offset));
3091 proto_tree_add_item (body_tree, hf_message_bodyid_uint32, tvb, offset, 4, ENC_BIG_ENDIAN);
3094 case STRUCT_ID_UINT64:
3095 dmp.struct_id = ep_strdup_printf ("%" G_GINT64_MODIFIER "u", tvb_get_ntoh64 (tvb, offset));
3096 proto_tree_add_item (body_tree, hf_message_bodyid_uint64, tvb, offset, 8, ENC_BIG_ENDIAN);
3099 case STRUCT_ID_STRING:
3100 dmp.struct_id = tvb_get_ephemeral_string (tvb, offset, (gint) dmp_struct_length);
3101 proto_tree_add_item (body_tree, hf_message_bodyid_string, tvb, offset, dmp_struct_length, ENC_ASCII|ENC_NA);
3104 case STRUCT_ID_ZSTRING:
3105 dmp.struct_id = tvb_get_ephemeral_stringz (tvb, offset, &length);
3106 proto_tree_add_item (body_tree, hf_message_bodyid_zstring, tvb, offset, length, ENC_ASCII|ENC_NA);
3113 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3114 * and chapter 6.3.8.1 IPM 88 message structure
3116 static gint dissect_dmp_message (tvbuff_t *tvb, packet_info *pinfo,
3117 proto_tree *dmp_tree, gint offset)
3119 tvbuff_t *next_tvb = NULL;
3120 proto_tree *message_tree = NULL;
3121 proto_tree *field_tree = NULL;
3122 proto_item *en = NULL, *tf = NULL, *tr = NULL;
3123 guint8 message, eit = 0, compr_alg = ALGORITHM_NONE;
3124 gint len, boffset = offset;
3126 en = proto_tree_add_item (dmp_tree, hf_message_body, tvb, offset, -1, ENC_NA);
3127 message_tree = proto_item_add_subtree (en, ett_message);
3129 if (dmp.body_format == FREE_TEXT_SUBJECT) {
3130 len = tvb_strsize (tvb, offset);
3131 if (dmp_subject_as_id) {
3132 dmp.struct_id = tvb_get_ephemeral_string (tvb, offset, len);
3134 proto_tree_add_item (message_tree, hf_message_subject, tvb, offset, len, ENC_ASCII|ENC_NA);
3138 if (dmp.body_format == FREE_TEXT || dmp.body_format == FREE_TEXT_SUBJECT) {
3139 message = tvb_get_guint8 (tvb, offset);
3140 eit = (message & 0xE0) >> 5;
3141 compr_alg = (message & 0x18) >> 3;
3142 /* Encoded Information Type */
3143 tf = proto_tree_add_uint_format (message_tree, hf_message_eit,
3144 tvb, offset, 1, message, "EIT: %s (%d)",
3145 val_to_str (eit, eit_vals, "Unknown"),
3147 field_tree = proto_item_add_subtree (tf, ett_message_eit);
3148 proto_tree_add_item (field_tree, hf_message_eit, tvb, offset, 1, ENC_BIG_ENDIAN);
3149 proto_item_append_text (en, ", Type: %s",
3150 val_to_str (eit, eit_vals, "Unknown"));
3152 /* Compression Algorithm */
3153 tf = proto_tree_add_uint_format (message_tree, hf_message_compr,
3154 tvb, offset, 1, message,
3155 "Compression Algorithm: %s (%d)",
3156 val_to_str (compr_alg, compression_vals,
3157 "Unknown"), compr_alg);
3158 field_tree = proto_item_add_subtree (tf, ett_message_compr);
3159 tr = proto_tree_add_item (field_tree, hf_message_compr, tvb, offset, 1, ENC_BIG_ENDIAN);
3160 if (compr_alg == ALGORITHM_ZLIB) {
3161 proto_item_append_text (en, " (compressed)");
3162 } else if (compr_alg != ALGORITHM_NONE) {
3163 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN,
3164 "Unknown compression algorithm");
3167 if (message & 0x07) {
3169 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x07,
3170 tvb, offset, 1, message,
3171 "Reserved: %d", message & 0x07);
3172 field_tree = proto_item_add_subtree (tf, ett_message_body_reserved);
3173 tf = proto_tree_add_item (field_tree, hf_reserved_0x07, tvb, offset, 1, ENC_BIG_ENDIAN);
3174 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3180 len = tvb_length_remaining (tvb, offset);
3185 tf = proto_tree_add_none_format (message_tree, hf_message_body_data, tvb,
3187 "%sUser data, Length: %d",
3188 (compr_alg == ALGORITHM_ZLIB) ?
3189 "Compressed " : "", len);
3190 field_tree = proto_item_add_subtree (tf, ett_message_body);
3192 if (dmp.body_format == STRUCTURED) {
3193 /* Structured Message ID */
3194 dissect_dmp_structured_id (tvb, field_tree, offset);
3195 proto_tree_add_item (field_tree, hf_message_body_structured, tvb, offset, len, ENC_NA);
3196 } else if (len > 0 && (dmp.body_format == FREE_TEXT ||
3197 dmp.body_format == FREE_TEXT_SUBJECT)) {
3198 if (compr_alg == ALGORITHM_ZLIB) {
3199 if ((next_tvb = tvb_child_uncompress (tvb, tvb, offset, len)) != NULL) {
3200 gint zlen = tvb_length (next_tvb);
3201 add_new_data_source (pinfo, next_tvb, "Uncompressed User data");
3202 tf = proto_tree_add_none_format (message_tree,
3203 hf_message_body_uncompr,
3205 "Uncompressed User data, "
3206 "Length: %d", zlen);
3207 field_tree = proto_item_add_subtree (tf, ett_message_body_uncompr);
3208 proto_tree_add_item (field_tree, hf_message_body_uncompressed, next_tvb, 0, -1, ENC_ASCII|ENC_NA);
3210 tf = proto_tree_add_text (message_tree, tvb, offset, -1,
3211 "Error: Unable to uncompress content");
3212 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3213 "Unable to uncompress content");
3215 } else if (eit != EIT_BILATERAL) {
3216 proto_tree_add_item (field_tree, hf_message_body_plain, tvb, offset, len, ENC_ASCII|ENC_NA);
3221 if (dmp.struct_id) {
3222 proto_item_append_text (en, ", Id: %s", format_text (dmp.struct_id, strlen (dmp.struct_id)));
3225 proto_item_set_len (en, offset - boffset);
3230 /* Ref chapter 6.3.9.1 Report structure */
3231 static gint dissect_dmp_report (tvbuff_t *tvb, packet_info *pinfo,
3232 proto_tree *dmp_tree, gint offset,
3233 guint *prev_rec_no, gint num)
3235 proto_tree *report_tree = NULL;
3236 proto_tree *field_tree = NULL;
3237 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3239 gboolean info_present;
3241 gint len, boffset = offset;
3244 report = tvb_get_guint8 (tvb, offset);
3245 rep_type = (report & 0x80) >> 7;
3247 en = proto_tree_add_item (dmp_tree, hf_non_delivery_report, tvb, offset, 4, ENC_NA);
3249 en = proto_tree_add_item (dmp_tree, hf_delivery_report, tvb, offset, 4, ENC_NA);
3251 proto_item_append_text (en, " (#%d)", num);
3253 report_tree = proto_item_add_subtree (en, ett_report);
3256 tf = proto_tree_add_boolean_format (report_tree, hf_report_type,
3257 tvb, offset, 1, report,
3258 "Report Type: %s", rep_type ?
3259 report_type.true_string :
3260 report_type.false_string);
3261 field_tree = proto_item_add_subtree (tf, ett_report_type);
3262 proto_tree_add_item (field_tree, hf_report_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3264 if (rep_type == DR) {
3267 info_present = (report & 0x40);
3268 tf = proto_tree_add_boolean_format (report_tree,hf_report_info_present_dr,
3269 tvb, offset, 1, report,
3270 "Info Present: %s", (report & 0x40) ? "Present" : "Absent");
3271 field_tree = proto_item_add_subtree (tf, ett_report_info_present_dr);
3272 proto_tree_add_item (field_tree, hf_report_info_present_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3274 /* Address Encoding */
3275 dmp.addr_enc = ((report & 0x20) >> 5);
3276 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_dr,
3277 tvb, offset, 1, report,
3278 "Address Encoding: %s",
3280 addr_enc.true_string :
3281 addr_enc.false_string);
3282 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_dr);
3283 proto_tree_add_item (field_tree, hf_report_addr_enc_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3285 if (report & 0x1F) {
3287 tf = proto_tree_add_uint_format (report_tree, hf_reserved_0x1F,
3288 tvb, offset, 1, report,
3289 "Reserved: %d", report & 0x1F);
3290 field_tree = proto_item_add_subtree (tf, ett_report_reserved);
3291 tf = proto_tree_add_item (field_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
3292 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3299 report = tvb_get_guint8 (tvb, offset);
3300 tf = proto_tree_add_uint_format (report_tree, hf_report_del_time,
3301 tvb, offset, 1, report,
3303 field_tree = proto_item_add_subtree (tf, ett_report_del_time);
3304 ei = proto_tree_add_item (field_tree, hf_report_del_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3305 secs = dmp_dec_del_time (report);
3306 if (secs == DMP_TIME_RESERVED) {
3307 proto_item_append_text (tf, "Reserved (0x%2.2x)", report);
3308 proto_item_append_text (ei, " (Reserved)");
3310 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3311 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3312 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3316 /* Address Encoding */
3317 dmp.addr_enc = ((report & 0x40) >> 6);
3318 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_ndr,
3319 tvb, offset, 1, report,
3320 "Address Encoding: %s",
3322 addr_enc.true_string :
3323 addr_enc.false_string);
3324 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_ndr);
3325 proto_tree_add_item (field_tree, hf_report_addr_enc_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3328 tf = proto_tree_add_uint_format (report_tree, hf_report_reason,
3329 tvb, offset, 1, report,
3330 "Reason%s: %s (%d)",
3331 ((report & 0x3F) < 0x3D) ? " (P1)":"",
3332 non_del_reason_str (report & 0x3F),
3334 field_tree = proto_item_add_subtree (tf, ett_report_reason);
3335 proto_tree_add_item (field_tree, hf_report_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
3339 report = tvb_get_guint8 (tvb, offset);
3340 info_present = (report & 0x80);
3341 tf = proto_tree_add_boolean_format (report_tree,
3342 hf_report_info_present_ndr,
3343 tvb, offset, 1, report,
3344 "Info Present: %s", (report & 0x80) ? "Present" : "Absent");
3345 field_tree = proto_item_add_subtree (tf, ett_report_info_present_ndr);
3346 proto_tree_add_item (field_tree, hf_report_info_present_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3349 tf = proto_tree_add_uint_format (report_tree, hf_report_diagn,
3350 tvb, offset, 1, report,
3351 "Diagnostic%s: %s (%d)",
3352 ((report & 0x7F) < 0x7C) ? " (P1)":"",
3353 non_del_diagn_str (report & 0x7F),
3355 field_tree = proto_item_add_subtree (tf, ett_report_diagn);
3356 proto_tree_add_item (field_tree, hf_report_diagn, tvb, offset, 1, ENC_BIG_ENDIAN);
3360 offset = dissect_dmp_address (tvb, pinfo, report_tree, offset,
3364 /* Supplementary Information */
3365 len = tvb_strsize (tvb, offset);
3366 tf = proto_tree_add_uint_format (report_tree, hf_report_suppl_info_len,
3367 tvb, offset, len, len,
3368 "Supplementary Information, Length: %d",
3371 if ((offset - boffset + len) > 128) {
3372 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3373 128 - (offset - boffset));
3375 field_tree = proto_item_add_subtree (tf, ett_report_suppl_info);
3376 proto_tree_add_item (field_tree, hf_report_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3381 proto_item_set_len (en, offset - boffset);
3386 /* Ref chapter 6.3.10.1 Notification structure */
3387 static gint dissect_dmp_notification (tvbuff_t *tvb, packet_info *pinfo _U_,
3388 proto_tree *dmp_tree, gint offset)
3390 proto_tree *notif_tree = NULL;
3391 proto_tree *field_tree = NULL;
3392 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3393 guint8 notif, rec_time, on_typex = 0xFF;
3394 gint len, boffset = offset;
3397 if (dmp.notif_type == RN) {
3398 en = proto_tree_add_item (dmp_tree, hf_receipt_notif, tvb, offset, 4, ENC_NA);
3399 } else if (dmp.notif_type == NRN) {
3400 en = proto_tree_add_item (dmp_tree, hf_non_receipt_notif, tvb, offset, 4, ENC_NA);
3401 } else if (dmp.notif_type == ON) {
3402 en = proto_tree_add_item (dmp_tree, hf_other_notif, tvb, offset, 4, ENC_NA);
3406 notif_tree = proto_item_add_subtree (en, ett_notif);
3408 if (dmp.notif_type == RN || dmp.notif_type == ON) {
3410 rec_time = tvb_get_guint8 (tvb, offset);
3411 tf = proto_tree_add_uint_format (notif_tree, hf_notif_rec_time,
3412 tvb, offset, 1, rec_time,
3414 field_tree = proto_item_add_subtree (tf, ett_notif_rec_time);
3415 ei = proto_tree_add_item (field_tree, hf_notif_rec_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3416 secs = dmp_dec_exp_time (rec_time);
3417 if (secs == DMP_TIME_NOT_PRESENT) {
3418 proto_item_append_text (tf, "Not present");
3419 proto_item_append_text (ei, " (not present)");
3420 } else if (secs == DMP_TIME_RESERVED) {
3421 proto_item_append_text (tf, "Reserved (0x%2.2x)", rec_time);
3422 proto_item_append_text (ei, " (Reserved)");
3424 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3425 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3426 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3430 if (dmp.notif_type == ON) {
3432 on_typex = tvb_get_guint8 (tvb, offset);
3433 proto_tree_add_item (notif_tree, hf_notif_on_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3437 /* Supplementary Information */
3438 len = tvb_strsize (tvb, offset);
3439 tf = proto_tree_add_uint_format (notif_tree, hf_notif_suppl_info_len,
3440 tvb, offset, len, len,
3441 "Supplementary Information, Length: %d",
3444 if ((offset - boffset + len) > 128) {
3445 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3446 128 - (offset - boffset));
3448 field_tree = proto_item_add_subtree (tf, ett_notif_suppl_info);
3449 proto_tree_add_item (field_tree, hf_notif_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3453 if ((dmp.notif_type == ON) && (on_typex < 0x03)) {
3454 /* ACP127 Receipient */
3455 len = tvb_strsize (tvb, offset);
3456 tf = proto_tree_add_uint_format (notif_tree, hf_notif_acp127,
3457 tvb, offset, len, len,
3458 "ACP127 Recipient, Length: %d",
3462 proto_item_append_text (tf, " (incorrect, must be less than 64)");
3464 field_tree = proto_item_add_subtree (tf, ett_notif_acp127recip);
3465 proto_tree_add_item (field_tree, hf_notif_acp127recip, tvb, offset, len, ENC_ASCII|ENC_NA);
3469 } else if (dmp.notif_type == NRN) {
3470 /* Non-Recipient Reason */
3471 notif = tvb_get_guint8 (tvb, offset);
3472 proto_tree_add_uint_format (notif_tree, hf_notif_non_rec_reason,
3473 tvb, offset, 1, notif,
3474 "Non-Receipt Reason%s: %s (%d)",
3475 (notif < 0x10) ? " (P22)" : "",
3476 nrn_reason_str (notif), notif);
3479 /* Discard Reason */
3480 notif = tvb_get_guint8 (tvb, offset);
3481 proto_tree_add_uint_format (notif_tree, hf_notif_discard_reason,
3482 tvb, offset, 1, notif,
3483 "Discard Reason%s: %s (%d)",
3484 (notif < 0x10) ? " (P22)" : "",
3485 discard_reason_str (notif), notif);
3489 proto_item_set_len (en, offset - boffset);
3494 /* Ref chapter 6.2.1.2.8 SecurityCategories */
3495 static gint dissect_dmp_security_category (tvbuff_t *tvb, packet_info *pinfo,
3496 proto_tree *tree, GString *label_string,
3497 gint offset, guint8 ext)
3499 proto_tree *field_tree = NULL;
3500 proto_item *tf = NULL, *tr = NULL;
3501 gchar *sec_cat = NULL;
3503 gboolean country_code = FALSE;
3505 message = tvb_get_guint8 (tvb, offset);
3506 tf = proto_tree_add_uint_format (tree, hf_message_sec_cat_nat, tvb,
3507 offset, 1, message, "Security Categories");
3508 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3512 case SEC_CAT_EXT_NONE:
3513 proto_tree_add_item (field_tree, hf_message_sec_cat_cl, tvb, offset, 1, ENC_BIG_ENDIAN);
3514 proto_tree_add_item (field_tree, hf_message_sec_cat_cs, tvb, offset, 1, ENC_BIG_ENDIAN);
3515 proto_tree_add_item (field_tree, hf_message_sec_cat_ex, tvb, offset, 1, ENC_BIG_ENDIAN);
3516 proto_tree_add_item (field_tree, hf_message_sec_cat_ne, tvb, offset, 1, ENC_BIG_ENDIAN);
3518 tr = proto_tree_add_item (field_tree, hf_reserved_0x08, tvb, offset, 1, ENC_BIG_ENDIAN);
3519 if (message & 0x08) {
3520 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3522 tr = proto_tree_add_item (field_tree, hf_reserved_0x04, tvb, offset, 1, ENC_BIG_ENDIAN);
3523 if (message & 0x04) {
3524 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3527 if (message & 0xF0) {
3528 sec_cat = ep_strdup_printf ("%s%s%s%s",
3529 (message & 0x80) ? ",cl" : "",
3530 (message & 0x40) ? ",cs" : "",
3531 (message & 0x20) ? ",ex" : "",
3532 (message & 0x10) ? ",ne" : "");
3533 proto_item_append_text (tf, ": %s", &sec_cat[1]);
3534 g_string_append (label_string, sec_cat);
3538 case SEC_CAT_EXT_PERMISSIVE:
3539 if ((message >> 2) == 0x3F) {
3540 /* Fake entry because nat_pol_id defines 0x3F as reserved */
3541 proto_tree_add_uint_format (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1,
3542 message, "1111 11.. = Next byte has Country Code (0x3F)");
3543 country_code = TRUE;
3545 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1, ENC_BIG_ENDIAN);
3546 proto_item_append_text (tf, ": rel-to-%s", get_nat_pol_id_short (message >> 2));
3547 g_string_append_printf (label_string, ",rel-to-%s", get_nat_pol_id_short (message >> 2));
3548 if ((message >> 2) == 0) {
3549 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3554 case SEC_CAT_EXT_RESTRICTIVE:
3555 proto_tree_add_item (field_tree, hf_message_sec_cat_restrictive, tvb, offset, 1, ENC_BIG_ENDIAN);
3556 proto_item_append_text (tf, " (restrictive: 0x%2.2x)", message >> 2);
3563 proto_item_append_text (tf, " (0x%2.2x)", message);
3565 if (dmp.version == 1) {
3566 tr = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3567 if (message & 0x02) {
3568 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3570 tr = proto_tree_add_item (field_tree, hf_reserved_0x01, tvb, offset, 1, ENC_BIG_ENDIAN);
3571 if (message & 0x01) {
3572 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3575 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_extended, tvb, offset, 1, ENC_BIG_ENDIAN);
3576 if ((message & 0x01) && (message & 0x02)) {
3577 expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN, "Reserved value");
3578 } else if (message & 0x01 || message & 0x02) {
3579 proto_item_append_text (tf, " (extended)");
3580 offset = dissect_dmp_security_category (tvb, pinfo, tree, label_string, offset+1, message & 0x03);
3584 proto_tree_add_item (field_tree, hf_message_sec_cat_country_code, tvb, offset+1, 1, ENC_BIG_ENDIAN);
3585 proto_item_append_text (tf, " (rel-to country-code: %d)", tvb_get_guint8 (tvb, offset+1));
3586 proto_item_set_len (tf, 2);
3595 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3596 * and chapter 6.3.8.1 IPM 88 message structure
3597 * and chapter 6.3.9.1 Report structure
3598 * and chapter 6.3.10.1 Notification structure
3600 static gint dissect_dmp_content (tvbuff_t *tvb, packet_info *pinfo,
3601 proto_tree *dmp_tree, gint offset)
3603 proto_tree *message_tree = NULL;
3604 proto_tree *field_tree = NULL;
3605 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3606 proto_item *hidden_item;
3607 GString *label_string = g_string_new ("");
3608 const gchar *class_name = NULL;
3609 guint8 message, dmp_sec_pol, dmp_sec_class, dmp_nation = 0, exp_time, dtg;
3611 guint prev_rec_no = 0;
3612 gint rep_len, rep_no = 1;
3613 gint loffset, boffset = offset;
3615 if (dmp.msg_type == REPORT) {
3616 en = proto_tree_add_item (dmp_tree, hf_report_content, tvb, offset, 7, ENC_NA);
3617 } else if (dmp.msg_type == NOTIF) {
3618 en = proto_tree_add_item (dmp_tree, hf_notif_content, tvb, offset, 7, ENC_NA);
3620 en = proto_tree_add_item (dmp_tree, hf_message_content, tvb, offset, 7, ENC_NA);
3622 message_tree = proto_item_add_subtree (en, ett_content);
3624 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3625 message = tvb_get_guint8 (tvb, offset);
3626 dmp.body_format = (message & 0x03);
3628 if (dmp.msg_type == STANAG) {
3630 dmp.st_type = (message & 0xC0) >> 6;
3631 tf = proto_tree_add_uint_format (message_tree, hf_message_st_type,
3632 tvb, offset, 1, message,
3633 "Message Type: %s (%d)",
3634 val_to_str (dmp.st_type,
3635 message_type_vals, ""),
3637 field_tree = proto_item_add_subtree (tf, ett_message_st_type);
3638 proto_tree_add_item (field_tree, hf_message_st_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3640 if ((message & 0x20) >> 5) {
3642 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x20,
3643 tvb, offset, 1, message,
3644 "Reserved: %d", (message & 0x20)>>5);
3645 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3646 tf = proto_tree_add_item (field_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
3647 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3652 dmp.prec = (message & 0x1C) >> 2;
3653 tf = proto_tree_add_uint_format (message_tree, hf_message_precedence,
3654 tvb, offset, 1, message,
3655 "Precedence: %s (%d)",
3656 val_to_str (dmp.prec, precedence, ""),
3658 field_tree = proto_item_add_subtree (tf, ett_message_precedence);
3659 proto_tree_add_item (field_tree, hf_message_precedence, tvb, offset, 1, ENC_BIG_ENDIAN);
3662 if ((message & 0xE0) >> 5) {
3664 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0xE0,
3665 tvb, offset, 1, message,
3666 "Reserved: %d", (message & 0xE0)>>5);
3667 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3668 tf = proto_tree_add_item (field_tree, hf_reserved_0xE0, tvb, offset, 1, ENC_BIG_ENDIAN);
3669 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3674 dmp.prec = (message & 0x1C) >> 2;
3675 tf = proto_tree_add_uint_format (message_tree, hf_message_importance,
3676 tvb, offset, 1, message,
3677 "Importance: %s (%d)",
3678 val_to_str (dmp.prec, importance, ""),
3680 field_tree = proto_item_add_subtree (tf, ett_message_importance);
3681 proto_tree_add_item (field_tree, hf_message_importance, tvb, offset, 1, ENC_BIG_ENDIAN);
3685 tf = proto_tree_add_uint_format (message_tree, hf_message_body_format,
3686 tvb, offset, 1, message,
3687 "Body Format: %s (%d)",
3688 val_to_str (message & 0x03,
3689 body_format_vals, ""),
3691 field_tree = proto_item_add_subtree (tf, ett_message_body_format);
3692 proto_tree_add_item (field_tree, hf_message_body_format, tvb, offset, 1, ENC_BIG_ENDIAN);
3696 message = tvb_get_guint8 (tvb, offset);
3697 /* Security Classification */
3698 dmp_sec_class = (message & 0xE0) >> 5;
3699 dmp_sec_pol = (message & 0x1C) >> 2;
3700 if (dmp_sec_pol == EXTENDED_NATIONAL) {
3701 dmp_nation = tvb_get_guint8 (tvb, offset + 1);
3704 loffset = offset; /* Offset to start of security label */
3705 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3706 class_name = dmp_national_sec_class (dmp_local_nation, dmp_sec_class);
3707 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3708 class_name = dmp_national_sec_class (dmp_nation, dmp_sec_class);
3710 if ((dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL) && !class_name) {
3711 class_name = val_to_str (dmp_sec_class, sec_class, "");
3713 if (class_name && class_name[0]) {
3714 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3715 tvb, offset, 1, message,
3716 "Security Classification: %s (%d)",
3717 class_name, dmp_sec_class);
3719 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3720 tvb, offset, 1, message,
3721 "Security Classification: %d",
3724 field_tree = proto_item_add_subtree (tf, ett_message_sec_class);
3725 tf = proto_tree_add_item (field_tree, hf_message_sec_class_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3727 proto_item_append_text (tf, " (%s)", class_name);
3728 g_string_append (label_string, class_name);
3731 /* Security Policy */
3732 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_pol,
3733 tvb, offset, 1, message,
3734 "Security Policy: %s (%d)",
3735 val_to_str (dmp_sec_pol, sec_pol, "%d"),
3737 field_tree = proto_item_add_subtree (tf, ett_message_sec_pol);
3738 proto_tree_add_item (field_tree, hf_message_sec_pol, tvb, offset, 1, ENC_BIG_ENDIAN);
3740 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3742 tf = proto_tree_add_item (message_tree, hf_message_heading_flags, tvb, offset, 1, ENC_NA);
3743 field_tree = proto_item_add_subtree (tf, ett_message_heading_flags);
3744 proto_tree_add_item (field_tree, hf_message_auth_users, tvb, offset, 1, ENC_BIG_ENDIAN);
3745 proto_tree_add_item (field_tree, hf_message_subject_disc, tvb, offset, 1, ENC_BIG_ENDIAN);
3746 if (message & 0x03) {
3747 proto_item_append_text (tf, ": %s%s%s discarded",
3748 (message & 0x02) ? "Authorizing users" : "",
3749 (message & 0x03) == 0x03 ? " and " : "",
3750 (message & 0x01) ? "Subject" : "");
3752 proto_item_append_text (tf, " (none)");
3754 } else if (dmp.msg_type == NOTIF) {
3755 /* Notification Type */
3756 dmp.notif_type = (message & 0x03);
3757 tf = proto_tree_add_uint_format (message_tree, hf_notif_type,
3758 tvb, offset, 1, message,
3759 "Notification Type: %s",
3760 val_to_str (dmp.notif_type, notif_type,
3762 field_tree = proto_item_add_subtree (tf, ett_notif_type);
3763 proto_tree_add_item (field_tree, hf_notif_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3764 } else if (message & 0x02) {
3766 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x02,
3767 tvb, offset, 1, message,
3768 "Reserved: %d", message & 0x02);
3769 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3770 tf = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3771 expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
3776 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3777 /* Show configured national policy */
3778 tf = proto_tree_add_uint (message_tree, hf_message_national_policy_id,
3779 tvb, offset, 0, dmp_local_nation);
3780 PROTO_ITEM_SET_GENERATED (tf);
3781 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3782 /* National Policy Identifier */
3783 proto_tree_add_item (message_tree, hf_message_national_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3785 } else if (dmp_sec_pol == EXTENDED_MISSION) {
3786 /* Mission Policy Identifier */
3787 message = tvb_get_guint8 (tvb, offset);
3788 if (message == 0xFF) {
3789 proto_tree_add_uint_format (message_tree, hf_message_mission_policy_id,
3790 tvb, offset, 1, message,
3791 "Mission Policy Identifier: Reserved (0xFF)");
3793 proto_tree_add_item (message_tree, hf_message_mission_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3798 /* Security Categories */
3799 if (dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL || dmp_sec_pol == EXTENDED_NATIONAL) {
3800 offset = dissect_dmp_security_category (tvb, pinfo, message_tree, label_string, offset, 0);
3801 proto_item_append_text (en, ", Security Label: %s", label_string->str);
3802 tf = proto_tree_add_string (message_tree, hf_message_sec_label, tvb, loffset,
3803 offset - loffset + 1, label_string->str);
3804 PROTO_ITEM_SET_GENERATED (tf);
3806 tf = proto_tree_add_item (message_tree, hf_message_sec_cat_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3807 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3809 proto_tree_add_item (field_tree, hf_message_sec_cat_bit7, tvb, offset, 1, ENC_BIG_ENDIAN);
3810 proto_tree_add_item (field_tree, hf_message_sec_cat_bit6, tvb, offset, 1, ENC_BIG_ENDIAN);
3811 proto_tree_add_item (field_tree, hf_message_sec_cat_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
3812 proto_tree_add_item (field_tree, hf_message_sec_cat_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
3813 proto_tree_add_item (field_tree, hf_message_sec_cat_bit3, tvb, offset, 1, ENC_BIG_ENDIAN);
3814 proto_tree_add_item (field_tree, hf_message_sec_cat_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
3815 proto_tree_add_item (field_tree, hf_message_sec_cat_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3816 proto_tree_add_item (field_tree, hf_message_sec_cat_bit0, tvb, offset, 1, ENC_BIG_ENDIAN);
3820 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3822 exp_time = tvb_get_guint8 (tvb, offset);
3823 tf = proto_tree_add_uint_format (message_tree, hf_message_exp_time,
3824 tvb, offset, 1, exp_time,
3826 field_tree = proto_item_add_subtree (tf, ett_message_exp_time);
3827 ei = proto_tree_add_item (field_tree, hf_message_exp_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3828 secs = dmp_dec_exp_time (exp_time);
3829 if (secs == DMP_TIME_NOT_PRESENT) {
3830 proto_item_append_text (tf, "Not present");
3831 proto_item_append_text (ei, " (not present)");
3832 } else if (secs == DMP_TIME_RESERVED) {
3833 proto_item_append_text (tf, "Reserved (0x%2.2x)", exp_time);
3834 proto_item_append_text (ei, " (Reserved)");
3836 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3837 abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE));
3838 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3843 if (dmp.msg_type == STANAG) {
3844 dtg = tvb_get_guint8 (tvb, offset);
3845 tf = proto_tree_add_uint_format (message_tree, hf_message_dtg, tvb, offset, 1, dtg, "DTG: ");
3846 field_tree = proto_item_add_subtree (tf, ett_message_dtg);
3847 proto_tree_add_item (field_tree, hf_message_dtg_sign, tvb, offset, 1, ENC_BIG_ENDIAN);
3848 proto_tree_add_item (field_tree, hf_message_dtg_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3849 secs = dmp_dec_dtg (dtg & 0x7F);
3850 if (secs == DMP_TIME_NOT_PRESENT) {
3851 proto_item_append_text (tf, "Not present");
3852 } else if (secs == DMP_TIME_RESERVED) {
3853 proto_item_append_text (tf, "Reserved (0x%2.2x)", dtg & 0x7F);
3854 } else if (secs == 0) {
3855 proto_item_append_text (tf, "0 minutes in the %s (%s)",
3856 (dtg & 0x80) ? dtg_sign.true_string :
3857 dtg_sign.false_string,
3858 abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
3860 proto_item_append_text (tf, "%s in the %s (%s)", time_secs_to_str(secs),
3861 (dtg & 0x80) ? dtg_sign.true_string :
3862 dtg_sign.false_string, (dtg & 0x80) ?
3863 abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE) :
3864 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3869 if (dmp.msg_type == STANAG) {
3871 offset = dissect_dmp_sic (tvb, pinfo, message_tree, offset);
3872 } else if (dmp.msg_type == REPORT || dmp.msg_type == NOTIF) {
3873 if (dmp.version == DMP_VERSION_1 || dmp.msg_id_type == ONLY_DMP_ID) {
3874 /* Subject Message Identifier */
3875 dmp.subj_id = tvb_get_ntohs (tvb, offset);
3876 proto_tree_add_item (message_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3877 hidden_item = proto_tree_add_item (message_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3878 PROTO_ITEM_SET_HIDDEN (hidden_item);
3880 } else if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
3881 if (dmp.msg_type == REPORT) {
3882 /* Subject MTS Identifier */
3883 offset = dissect_mts_identifier (tvb, pinfo, message_tree, offset, TRUE);
3885 /* Subject IPM Identifier */
3886 offset = dissect_ipm_identifier (tvb, pinfo, message_tree, offset, TRUE);
3889 tf = proto_tree_add_uint (message_tree, hf_message_subj_id, tvb, offset, 0, dmp.subj_id);
3890 PROTO_ITEM_SET_GENERATED (tf);
3891 hidden_item = proto_tree_add_uint (message_tree, hf_dmp_id, tvb, offset, 0, dmp.subj_id);
3892 PROTO_ITEM_SET_GENERATED (hidden_item);
3893 PROTO_ITEM_SET_HIDDEN (hidden_item);
3898 if (use_seq_ack_analysis) {
3899 register_dmp_id (pinfo, 0);
3902 proto_item_set_len (en, offset - boffset);
3904 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3906 offset = dissect_dmp_message (tvb, pinfo, dmp_tree, offset);
3907 } else if (dmp.msg_type == REPORT) {
3908 /* One or more Delivery Report or Non-Delivery Report Data */
3909 rep_len = tvb_length (tvb);
3913 while (offset < rep_len) {
3914 offset = dissect_dmp_report (tvb, pinfo, dmp_tree, offset, &prev_rec_no, rep_no++);
3916 } else if (dmp.msg_type == NOTIF) {
3917 /* Notification Data */
3918 offset = dissect_dmp_notification (tvb, pinfo, dmp_tree, offset);
3921 g_string_free (label_string, TRUE);
3926 static gint dissect_dmp_extensions (tvbuff_t *tvb, packet_info *pinfo _U_,
3927 proto_tree *dmp_tree, gint offset)
3929 proto_tree *exts_tree, *ext_tree, *hdr_tree;
3930 proto_item *exts_item, *en;
3931 guint8 ext_hdr, ext_length;
3932 gboolean more_extensions = TRUE;
3933 gint num_ext = 0, boffset = offset;
3935 exts_item = proto_tree_add_item (dmp_tree, hf_extensions, tvb, offset, -1, ENC_NA);
3936 exts_tree = proto_item_add_subtree (exts_item, ett_extensions);
3938 while (more_extensions) {
3939 /* Extensions Present */
3940 ext_hdr = tvb_get_guint8 (tvb, offset);
3941 more_extensions = (ext_hdr & 0x80);
3942 ext_length = (ext_hdr & 0x7F) + 1;
3944 en = proto_tree_add_none_format (exts_tree, hf_extension, tvb, offset, ext_length + 1,
3945 "Extension (#%d)", num_ext + 1);
3946 ext_tree = proto_item_add_subtree (en, ett_extension);
3948 en = proto_tree_add_none_format (ext_tree, hf_extension_header, tvb, offset, 1,
3949 "Extension Length: %u, More %s", ext_length,
3950 (ext_hdr & 0x80) ? "Present" : "Not present");
3951 hdr_tree = proto_item_add_subtree (en, ett_extension_header);
3952 proto_tree_add_item (hdr_tree, hf_extension_more, tvb, offset, 1, ENC_BIG_ENDIAN);
3953 proto_tree_add_item (hdr_tree, hf_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3956 proto_tree_add_item (ext_tree, hf_extension_data, tvb, offset, ext_length, ENC_NA);
3957 offset += ext_length;
3961 proto_item_append_text (exts_item, " (%d item%s)", num_ext, plurality (num_ext, "", "s"));
3962 proto_item_set_len (exts_item, offset - boffset);
3967 static void dissect_dmp (tvbuff_t *tvb, packet_info *pinfo,
3970 proto_tree *dmp_tree = NULL, *checksum_tree = NULL;
3971 proto_item *ti = NULL, *en = NULL;
3972 guint16 checksum1 = 0, checksum2 = 1;
3973 gint length, offset = 0;
3974 gboolean retrans_or_dup_ack = FALSE;
3976 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DMP");
3977 col_clear (pinfo->cinfo, COL_INFO);
3979 /* Initialize global data structure */
3980 memset (&dmp, 0, sizeof (dmp));
3982 ti = proto_tree_add_item (tree, proto_dmp, tvb, offset, -1, ENC_NA);
3983 dmp_tree = proto_item_add_subtree (ti, ett_dmp);
3985 offset = dissect_dmp_envelope (tvb, pinfo, dmp_tree, offset);
3987 if (dmp.version > DMP_VERSION_2) {
3988 /* Unsupported DMP Version, no point to continue */
3989 col_add_fstr (pinfo->cinfo, COL_INFO, "Unsupported Version: %d", dmp.version);
3993 if (dmp.extensions) {
3994 offset = dissect_dmp_extensions (tvb, pinfo, dmp_tree, offset);
3997 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3998 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
4000 offset = dissect_dmp_content (tvb, pinfo, dmp_tree, offset);
4001 } else if (dmp.msg_type == ACK) {
4002 offset = dissect_dmp_ack (tvb, pinfo, dmp_tree, offset);
4006 length = tvb_length (tvb);
4007 checksum1 = crc16_x25_ccitt_tvb (tvb, length - 2);
4008 checksum2 = tvb_get_ntohs (tvb, offset);
4010 en = proto_tree_add_item (dmp_tree, hf_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
4011 checksum_tree = proto_item_add_subtree (en, ett_checksum);
4012 if (checksum1 == checksum2) {
4013 proto_item_append_text (en, " (correct)");
4014 en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
4016 PROTO_ITEM_SET_GENERATED (en);
4017 en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
4019 PROTO_ITEM_SET_GENERATED (en);
4021 proto_item_append_text (en, " (incorrect, should be 0x%04x)",
4023 expert_add_info_format (pinfo, en, PI_CHECKSUM, PI_WARN, "Bad checksum");
4024 en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
4026 PROTO_ITEM_SET_GENERATED (en);
4027 en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
4029 PROTO_ITEM_SET_GENERATED (en);
4033 if (use_seq_ack_analysis) {
4034 dmp_add_seq_ack_analysis (tvb, pinfo, dmp_tree, offset);
4037 if (((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
4038 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) &&
4039 dmp.id_val && dmp.id_val->msg_resend_count)
4042 if (dmp.msg_type == REPORT) {
4043 retrans_num = dmp.id_val->rep_id;
4044 } else if (dmp.msg_type == NOTIF) {
4045 retrans_num = dmp.id_val->not_id;
4047 retrans_num = dmp.id_val->msg_id;
4049 col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ",
4050 retrans_num, dmp.id_val->msg_resend_count);
4051 retrans_or_dup_ack = TRUE;
4052 } else if (dmp.msg_type == ACK && dmp.id_val && dmp.id_val->ack_resend_count) {
4053 col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ",
4054 dmp.id_val->ack_id, dmp.id_val->ack_resend_count);
4055 retrans_or_dup_ack = TRUE;
4057 if (dmp_align && !retrans_or_dup_ack) {
4058 if (dmp.msg_type == ACK) {
4059 /* ACK does not have "Msg Id" */
4060 col_append_fstr (pinfo->cinfo, COL_INFO, "%-45.45s", msg_type_to_str ());
4062 col_append_fstr (pinfo->cinfo, COL_INFO, "%-31.31s", msg_type_to_str ());
4065 col_append_str (pinfo->cinfo, COL_INFO, msg_type_to_str ());
4067 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
4068 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
4070 if (dmp_align && !retrans_or_dup_ack) {
4071 col_append_fstr (pinfo->cinfo, COL_INFO, " Msg Id: %5d", dmp.msg_id);
4073 col_append_fstr (pinfo->cinfo, COL_INFO, ", Msg Id: %d", dmp.msg_id);
4076 if ((dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF) ||
4077 (dmp.msg_type == ACK))
4079 if (dmp_align && !retrans_or_dup_ack) {
4080 col_append_fstr (pinfo->cinfo, COL_INFO, " Subj Id: %5d",
4083 col_append_fstr (pinfo->cinfo, COL_INFO, ", Subj Id: %d",
4086 } else if (dmp.struct_id) {
4087 if (dmp_align && !retrans_or_dup_ack) {
4088 col_append_fstr (pinfo->cinfo, COL_INFO, " Body Id: %s",
4089 format_text (dmp.struct_id, strlen (dmp.struct_id)));
4091 col_append_fstr (pinfo->cinfo, COL_INFO, ", Body Id: %s",
4092 format_text (dmp.struct_id, strlen (dmp.struct_id)));
4095 if (dmp.checksum && (checksum1 != checksum2)) {
4096 col_append_str (pinfo->cinfo, COL_INFO, ", Checksum incorrect");
4099 proto_item_append_text (ti, ", Version: %d%s, %s", dmp.version,
4100 (dmp.prot_id == PROT_NAT ? " (national)" : ""),
4104 static void dmp_init_routine (void)
4106 if (dmp_id_hash_table) {
4107 g_hash_table_destroy (dmp_id_hash_table);
4109 if (dmp_long_id_hash_table) {
4110 g_hash_table_destroy (dmp_long_id_hash_table);
4113 dmp_id_hash_table = g_hash_table_new (dmp_id_hash, dmp_id_hash_equal);
4114 dmp_long_id_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
4117 void proto_register_dmp (void)
4119 static hf_register_info hf[] = {
4124 { "DMP Identifier", "dmp.id", FT_UINT16, BASE_DEC,
4125 NULL, 0x0, NULL, HFILL}},
4127 /* MTS Identifier */
4129 { "MTS Identifier", "dmp.mts", FT_STRING, BASE_NONE,
4130 NULL, 0x0, NULL, HFILL } },
4132 /* IPM Identifier */
4134 { "IPM Identifier", "dmp.ipm", FT_STRING, BASE_NONE,
4135 NULL, 0x0, NULL, HFILL } },
4141 { "Envelope", "dmp.envelope", FT_NONE, BASE_NONE,
4142 NULL, 0x0, NULL, HFILL}},
4145 { &hf_envelope_protocol_id,
4146 { "Protocol Identifier", "dmp.protocol_id", FT_UINT8,
4147 BASE_HEX, NULL, 0xF8, NULL, HFILL}},
4148 { &hf_envelope_version,
4149 { "Protocol Version", "dmp.version", FT_UINT8, BASE_DEC,
4150 VALS(version_vals), 0x07, NULL, HFILL } },
4151 { &hf_envelope_version_value,
4152 { "Protocol Version", "dmp.version_value", FT_UINT8, BASE_DEC,
4153 VALS(version_vals), 0x07, NULL, HFILL } },
4155 /* Envelope elements (byte 1) */
4156 { &hf_envelope_hop_count,
4157 { "Hop Count", "dmp.hop_count", FT_UINT8, BASE_DEC,
4158 NULL, 0xE0, NULL, HFILL } },
4159 { &hf_envelope_hop_count_value,
4160 { "Hop Count", "dmp.hop_count_value", FT_UINT8, BASE_DEC,
4161 NULL, 0xE0, NULL, HFILL } },
4162 { &hf_envelope_rec_present,
4163 { "Recipient Present", "dmp.rec_present", FT_BOOLEAN, 8,
4164 TFS (&tfs_present_absent), 0x20, NULL, HFILL } },
4165 { &hf_envelope_addr_enc,
4166 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4167 TFS (&addr_enc), 0x10, NULL, HFILL } },
4168 { &hf_envelope_checksum,
4169 { "Checksum", "dmp.checksum_used", FT_BOOLEAN, 8,
4170 TFS (&tfs_used_notused), 0x08, "Checksum Used", HFILL } },
4171 { &hf_envelope_type,
4172 { "Content Type", "dmp.content_type", FT_UINT8, BASE_DEC,
4173 VALS(type_vals), 0x07, NULL, HFILL } },
4175 /* Envelope elements (byte 2) */
4176 { &hf_envelope_extensions,
4177 { "Extensions", "dmp.extensions_used", FT_BOOLEAN, 8,
4178 TFS (&tfs_present_absent), 0x80, "Extensions Used", HFILL } },
4179 { &hf_envelope_msg_id_type,
4180 { "Message Identifier Type", "dmp.msg_id_type", FT_UINT8, BASE_DEC,
4181 VALS(msg_id_type_vals), 0x60, NULL, HFILL } },
4182 { &hf_envelope_msg_id_length,
4183 { "Message Identifier Length", "dmp.msg_id_short", FT_UINT8, BASE_DEC,
4184 VALS(msg_id_length_vals), 0x10, NULL, HFILL}},
4185 { &hf_envelope_mts_id_length,
4186 { "MTS Identifier Length", "dmp.mts_id_length", FT_UINT8, BASE_DEC,
4187 NULL, 0x1F, NULL, HFILL } },
4188 { &hf_envelope_ipm_id_modifier,
4189 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4190 VALS(ipm_id_modifier), 0xC0, NULL, HFILL } },
4191 { &hf_envelope_ipm_id_length,
4192 { "IPM Identifier Length", "dmp.ipm_id_length", FT_UINT8, BASE_DEC,
4193 NULL, 0x3F, NULL, HFILL } },
4195 { &hf_thales_ipm_id_modifier,
4196 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4197 VALS(thales_ipm_id_modifier), 0xC0, "Thales XOmail IPM Identifier Modifier", HFILL } },
4199 /* Message identifier */
4200 { &hf_envelope_msg_id,
4201 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4202 NULL, 0x0, NULL, HFILL}},
4203 { &hf_envelope_msg_id_12bit,
4204 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4205 NULL, 0x0FFF, NULL, HFILL}},
4207 /* MTS Identifier */
4208 { &hf_envelope_mts_id,
4209 { "MTS Identifier", "dmp.mts_id", FT_STRING, BASE_NONE,
4210 NULL, 0x0, NULL, HFILL } },
4212 /* IPM Identifier */
4213 { &hf_envelope_ipm_id,
4214 { "IPM Identifier", "dmp.ipm_id", FT_STRING, BASE_NONE,
4215 NULL, 0x0, NULL, HFILL } },
4219 { "Extensions", "dmp.extensions", FT_NONE, BASE_NONE,
4220 NULL, 0x0, NULL, HFILL}},
4222 { "Extension", "dmp.extension", FT_NONE, BASE_NONE,
4223 NULL, 0x0, NULL, HFILL } },
4224 { &hf_extension_header,
4225 { "Extension Header", "dmp.extension_header", FT_NONE, BASE_NONE,
4226 NULL, 0x0, NULL, HFILL}},
4227 { &hf_extension_more,
4228 { "More Extensions", "dmp.extension_more", FT_BOOLEAN, 8,
4229 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4230 { &hf_extension_length,
4231 { "Extension Length (minus one)", "dmp.extension_length", FT_UINT8, BASE_DEC,
4232 NULL, 0x7F, "Extension Length minus one", HFILL } },
4233 { &hf_extension_data,
4234 { "Extension Data", "dmp.extension_data", FT_BYTES, BASE_NONE,
4235 NULL, 0x0, NULL, HFILL } },
4237 /* Submission time */
4238 { &hf_envelope_subm_time,
4239 { "Submission Time", "dmp.subm_time", FT_UINT16, BASE_HEX,
4240 NULL, 0x0, NULL, HFILL } },
4241 { &hf_envelope_time_diff_present,
4242 { "Time Diff", "dmp.time_diff_present", FT_BOOLEAN, 16,
4243 TFS (&tfs_present_absent), 0x8000, "Time Diff Present", HFILL } },
4244 { &hf_envelope_subm_time_value,
4245 { "Submission Time Value", "dmp.subm_time_value", FT_UINT16,
4246 BASE_HEX, NULL, 0x7FFF, NULL, HFILL } },
4247 { &hf_envelope_time_diff,
4248 { "Time Difference", "dmp.time_diff", FT_UINT8, BASE_HEX,
4249 NULL, 0xFF, NULL, HFILL } },
4250 { &hf_envelope_time_diff_value,
4251 { "Time Difference Value", "dmp.time_diff_value", FT_UINT8,
4252 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4254 /* Envelope flags */
4255 { &hf_envelope_flags,
4256 { "Flags", "dmp.envelope_flags", FT_UINT8, BASE_DEC,
4257 NULL, 0x0, "Envelope Flags", HFILL}},
4258 { &hf_envelope_content_id_discarded,
4259 { "Content Identifier discarded", "dmp.cont_id_discarded",
4260 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
4262 { &hf_envelope_recip_reassign_prohib,
4263 { "Recipient reassign prohibited","dmp.recip_reassign_prohib",
4264 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
4266 { &hf_envelope_dl_expansion_prohib,
4267 { "DL expansion prohibited", "dmp.dl_expansion_prohib",
4268 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL,
4271 /* Recipient Count */
4272 { &hf_envelope_recipients,
4273 { "Recipient Count", "dmp.rec_count", FT_UINT8, BASE_DEC,
4274 NULL, 0x1F, NULL, HFILL}},
4275 { &hf_envelope_ext_recipients,
4276 { "Extended Recipient Count", "dmp.ext_rec_count", FT_UINT16,
4277 BASE_DEC, NULL, 0x7FFF, NULL, HFILL}},
4282 { &hf_addr_recipient,
4283 { "Recipient Number", "dmp.recipient", FT_NONE, BASE_NONE,
4284 NULL, 0x0, "Recipient", HFILL } },
4285 { &hf_addr_originator,
4286 { "Originator", "dmp.originator", FT_NONE, BASE_NONE,
4287 NULL, 0x0, NULL, HFILL } },
4288 { &hf_addr_reporting_name,
4289 { "Reporting Name Number", "dmp.reporting_name", FT_NONE,
4290 BASE_NONE, NULL, 0x0, "Reporting Name", HFILL } },
4291 { &hf_addr_dl_expanded,
4292 { "DL Expanded", "dmp.dl_expanded", FT_BOOLEAN, BASE_NONE,
4293 NULL, 0x0, "Message has been DL expanded", HFILL } },
4295 { "Intended Recipient", "dmp.int_rec", FT_BOOLEAN, BASE_NONE,
4296 NULL, 0x0, "Message has an intended recipient", HFILL } },
4301 { &hf_addr_dir_addr_ext,
4302 { "Address Extended", "dmp.addr_ext", FT_BOOLEAN, 8,
4303 NULL, 0x80, NULL, HFILL } },
4304 { &hf_addr_dir_rec_no,
4305 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4306 BASE_DEC, NULL, 0xF0, NULL, HFILL } },
4307 { &hf_addr_dir_rec_no_generated,
4308 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4309 BASE_DEC, NULL, 0x0, "Recipient Number Offset", HFILL } },
4310 { &hf_addr_dir_rec_no1,
4311 { "Recipient Number (bits 3-0)", "dmp.rec_no_offset1", FT_UINT8,
4312 BASE_DEC, NULL, 0xF0, "Recipient Number (bits 3-0) Offset", HFILL } },
4313 { &hf_addr_dir_rec_no2,
4314 { "Recipient Number (bits 9-4)", "dmp.rec_no_offset2", FT_UINT8,
4315 BASE_DEC, NULL, 0x3F, "Recipient Number (bits 9-4) Offset", HFILL } },
4316 { &hf_addr_dir_rec_no3,
4317 { "Recipient Number (bits 14-10)", "dmp.rec_no_offset3", FT_UINT8,
4318 BASE_DEC, NULL, 0x1F, "Recipient Number (bits 14-10) Offset",HFILL } },
4319 { &hf_addr_dir_rep_req1,
4320 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4321 VALS (report_vals_ext), 0x0C, NULL, HFILL } },
4322 { &hf_addr_dir_rep_req2,
4323 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4324 VALS (report_vals_ext), 0xC0, NULL, HFILL } },
4325 { &hf_addr_dir_rep_req3,
4326 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4327 VALS (report_vals), 0xC0, NULL, HFILL } },
4328 { &hf_addr_dir_not_req1,
4329 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4330 VALS (notif_vals_ext), 0x03, NULL, HFILL } },
4331 { &hf_addr_dir_not_req2,
4332 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4333 VALS (notif_vals_ext), 0xC0, NULL, HFILL } },
4334 { &hf_addr_dir_not_req3,
4335 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4336 VALS (notif_vals), 0xC0, NULL, HFILL } },
4337 { &hf_addr_dir_action,
4338 { "Action", "dmp.action", FT_BOOLEAN, 8,
4339 TFS (&tfs_yes_no), 0x80, NULL, HFILL } },
4340 { &hf_addr_dir_address,
4341 { "Direct Address", "dmp.direct_addr", FT_UINT8,
4342 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4343 { &hf_addr_dir_address_generated,
4344 { "Direct Address", "dmp.direct_addr", FT_UINT32,
4345 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4346 { &hf_addr_dir_address1,
4347 { "Direct Address (bits 6-0)", "dmp.direct_addr1", FT_UINT8,
4348 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4349 { &hf_addr_dir_address2,
4350 { "Direct Address (bits 12-7)", "dmp.direct_addr2", FT_UINT8,
4351 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4352 { &hf_addr_dir_address3,
4353 { "Direct Address (bits 18-13)", "dmp.direct_addr3", FT_UINT8,
4354 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4359 { &hf_addr_ext_form,
4360 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4361 VALS (&addr_form), 0xE0, NULL, HFILL } },
4362 { &hf_addr_ext_form_orig_v1,
4363 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4364 VALS (&addr_form_orig_v1), 0xE0, NULL, HFILL } },
4365 { &hf_addr_ext_form_orig,
4366 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4367 VALS (&addr_form_orig), 0xE0, NULL, HFILL } },
4368 { &hf_addr_ext_action,
4369 { "Action", "dmp.action", FT_BOOLEAN, 8,
4370 TFS (&tfs_yes_no), 0x10, NULL, HFILL } },
4371 { &hf_addr_ext_rep_req,
4372 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4373 VALS (report_vals), 0x0C, NULL, HFILL } },
4374 { &hf_addr_ext_not_req,
4375 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4376 VALS (notif_vals), 0x03, NULL, HFILL } },
4377 { &hf_addr_ext_rec_ext,
4378 { "Recipient Number Extended", "dmp.rec_no_ext", FT_BOOLEAN, 8,
4379 NULL, 0x80, NULL, HFILL } },
4380 { &hf_addr_ext_rec_no,
4381 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4382 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4383 { &hf_addr_ext_rec_no_generated,
4384 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4385 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4386 { &hf_addr_ext_rec_no1,
4387 { "Recipient Number (bits 6-0)", "dmp.rec_no_offset1", FT_UINT8,
4388 BASE_DEC, NULL, 0x7F, "Recipient Number (bits 6-0) Offset", HFILL } },
4389 { &hf_addr_ext_rec_no2,
4390 { "Recipient Number (bits 14-7)", "dmp.rec_no_offset2", FT_UINT8,
4391 BASE_DEC, NULL, 0xFF, "Recipient Number (bits 14-7) Offset", HFILL } },
4392 { &hf_addr_ext_address,
4393 { "Extended Address", "dmp.addr_form", FT_NONE, BASE_NONE,
4394 NULL, 0x0, NULL, HFILL } },
4395 { &hf_addr_ext_type,
4396 { "Address Type", "dmp.addr_type", FT_UINT8, BASE_DEC,
4397 VALS (&ext_addr_type), 0xE0, NULL, HFILL } },
4398 { &hf_addr_ext_type_ext,
4399 { "Address Type Extended", "dmp.addr_type_ext", FT_UINT8,
4400 BASE_DEC, VALS (&ext_addr_type_ext), 0xE0, NULL,
4402 { &hf_addr_ext_length,
4403 { "Address Length", "dmp.addr_length", FT_UINT8,
4404 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4405 { &hf_addr_ext_length_generated,
4406 { "Address Length", "dmp.addr_length", FT_UINT32,
4407 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4408 { &hf_addr_ext_length1,
4409 { "Address Length (bits 4-0)", "dmp.addr_length1", FT_UINT8,
4410 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4411 { &hf_addr_ext_length2,
4412 { "Address Length (bits 9-5)", "dmp.addr_length2", FT_UINT8,
4413 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4414 { &hf_addr_ext_asn1_ber,
4415 { "ASN.1 BER-encoded OR-name", "dmp.or_name", FT_NONE,
4416 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4417 { &hf_addr_ext_asn1_per,
4418 { "ASN.1 PER-encoded OR-name", "dmp.asn1_per", FT_BYTES,
4419 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4420 { &hf_addr_ext_unknown,
4421 { "Unknown encoded address", "dmp.addr_unknown", FT_BYTES,
4422 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4427 { &hf_message_content,
4428 { "Message Content", "dmp.message", FT_NONE, BASE_NONE,
4429 NULL, 0x0, NULL, HFILL } },
4430 { &hf_report_content,
4431 { "Report Content", "dmp.report", FT_NONE, BASE_NONE,
4432 NULL, 0x0, NULL, HFILL } },
4433 { &hf_notif_content,
4434 { "Notification Content", "dmp.notification", FT_NONE, BASE_NONE,
4435 NULL, 0x0, NULL, HFILL } },
4437 { &hf_message_st_type,
4438 { "Message type", "dmp.msg_type", FT_UINT8, BASE_DEC,
4439 VALS (message_type_vals), 0xC0, NULL, HFILL } },
4440 { &hf_message_precedence,
4441 { "Precedence", "dmp.precedence", FT_UINT8, BASE_DEC,
4442 VALS (precedence), 0x1C, NULL, HFILL } },
4443 { &hf_message_importance,
4444 { "Importance", "dmp.importance", FT_UINT8, BASE_DEC,
4445 VALS (importance), 0x1C, NULL, HFILL } },
4446 { &hf_message_body_format,
4447 { "Body format", "dmp.body_format", FT_UINT8, BASE_DEC,
4448 VALS (body_format_vals), 0x03, NULL, HFILL } },
4450 /* Security Values */
4451 { &hf_message_sec_label,
4452 { "Security Label", "dmp.sec_label", FT_STRING, BASE_NONE,
4453 NULL, 0x0, NULL, HFILL } },
4454 { &hf_message_sec_class_val,
4455 { "Security Classification", "dmp.sec_class", FT_UINT8,
4456 BASE_DEC, NULL, 0xE0, NULL, HFILL}},
4457 { &hf_message_sec_pol,
4458 { "Security Policy", "dmp.sec_pol", FT_UINT8, BASE_DEC,
4459 VALS (sec_pol), 0x1C, NULL, HFILL } },
4460 { &hf_message_heading_flags,
4461 { "Heading Flags", "dmp.heading_flags", FT_NONE, BASE_NONE,
4462 NULL, 0x0, NULL, HFILL } },
4463 { &hf_message_auth_users,
4464 { "Authorizing users discarded", "dmp.auth_discarded",
4465 FT_BOOLEAN, 8, TFS (&tfs_yes_no), 0x02,
4467 { &hf_message_subject_disc,
4468 { "Subject discarded", "dmp.subject_discarded", FT_BOOLEAN, 8,
4469 TFS (&tfs_yes_no), 0x01, NULL, HFILL } },
4471 /* National Policy Identifier */
4472 { &hf_message_national_policy_id,
4473 { "National Policy Identifier", "dmp.nat_pol_id", FT_UINT8,
4474 BASE_DEC, VALS(nat_pol_id), 0x0, NULL,
4477 /* Mission Policy Identifier */
4478 { &hf_message_mission_policy_id,
4479 { "Mission Policy Identifier", "dmp.mission_pol_id", FT_UINT8,
4480 BASE_DEC, NULL, 0x0, NULL,
4483 /* Security Categories */
4484 { &hf_message_sec_cat_nat,
4485 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4486 NULL, 0x0, NULL, HFILL } },
4487 { &hf_message_sec_cat_val,
4488 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4489 NULL, 0x0, NULL, HFILL } },
4490 { &hf_message_sec_cat_cl,
4491 { "Clear", "dmp.sec_cat.cl", FT_BOOLEAN, 8,
4492 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4493 { &hf_message_sec_cat_cs,
4494 { "Crypto Security", "dmp.sec_cat.cs", FT_BOOLEAN, 8,
4495 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4496 { &hf_message_sec_cat_ex,
4497 { "Exclusive", "dmp.sec_cat.ex", FT_BOOLEAN, 8,
4498 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4499 { &hf_message_sec_cat_ne,
4500 { "National Eyes Only", "dmp.sec_cat.ne", FT_BOOLEAN, 8,
4501 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4502 { &hf_message_sec_cat_permissive,
4503 { "Releasable to", "dmp.sec_cat.permissive", FT_UINT8, BASE_HEX,
4504 VALS (nat_pol_id), 0xFC, NULL, HFILL } },
4505 { &hf_message_sec_cat_country_code,
4506 { "Country Code", "dmp.sec_cat.country", FT_UINT8, BASE_DEC,
4507 NULL, 0x00, NULL, HFILL } },
4508 { &hf_message_sec_cat_restrictive,
4509 { "Restrictive", "dmp.sec_cat.restrictive", FT_UINT8, BASE_HEX,
4510 NULL, 0xFC, NULL, HFILL } },
4511 { &hf_message_sec_cat_extended,
4512 { "Extended", "dmp.sec_cat.extended", FT_UINT8, BASE_HEX,
4513 VALS (ext_sec_cat), 0x03, "Extended Security Category", HFILL } },
4514 { &hf_message_sec_cat_bit0,
4515 { "Bit 0", "dmp.sec_cat.bit0", FT_BOOLEAN, 8,
4516 TFS (&tfs_set_notset), 0x01, NULL, HFILL } },
4517 { &hf_message_sec_cat_bit1,
4518 { "Bit 1", "dmp.sec_cat.bit1", FT_BOOLEAN, 8,
4519 TFS (&tfs_set_notset), 0x02, NULL, HFILL } },
4520 { &hf_message_sec_cat_bit2,
4521 { "Bit 2", "dmp.sec_cat.bit2", FT_BOOLEAN, 8,
4522 TFS (&tfs_set_notset), 0x04, NULL, HFILL } },
4523 { &hf_message_sec_cat_bit3,
4524 { "Bit 3", "dmp.sec_cat.bit3", FT_BOOLEAN, 8,
4525 TFS (&tfs_set_notset), 0x08, NULL, HFILL } },
4526 { &hf_message_sec_cat_bit4,
4527 { "Bit 4", "dmp.sec_cat.bit4", FT_BOOLEAN, 8,
4528 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4529 { &hf_message_sec_cat_bit5,
4530 { "Bit 5", "dmp.sec_cat.bit5", FT_BOOLEAN, 8,
4531 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4532 { &hf_message_sec_cat_bit6,
4533 { "Bit 6", "dmp.sec_cat.bit6", FT_BOOLEAN, 8,
4534 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4535 { &hf_message_sec_cat_bit7,
4536 { "Bit 7", "dmp.sec_cat.bit7", FT_BOOLEAN, 8,
4537 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4540 { &hf_message_exp_time,
4541 { "Expiry Time", "dmp.expiry_time", FT_UINT8, BASE_HEX,
4542 NULL, 0x0, NULL, HFILL } },
4543 { &hf_message_exp_time_val,
4544 { "Expiry Time Value", "dmp.expiry_time_val", FT_UINT8, BASE_HEX,
4545 NULL, 0xFF, NULL, HFILL } },
4549 { "DTG", "dmp.dtg", FT_UINT8, BASE_HEX,
4550 NULL, 0xFF, NULL, HFILL } },
4551 { &hf_message_dtg_sign,
4552 { "DTG in the", "dmp.dtg.sign", FT_BOOLEAN, 8, TFS (&dtg_sign),
4553 0x80, "Sign", HFILL } },
4554 { &hf_message_dtg_val,
4555 { "DTG Value", "dmp.dtg.val", FT_UINT8, BASE_HEX, NULL,
4556 0x7F, NULL, HFILL } },
4560 { "SIC", "dmp.sic", FT_STRING, BASE_NONE,
4561 NULL, 0x0, NULL, HFILL } },
4562 { &hf_message_sic_key,
4563 { "SICs", "dmp.sic_key", FT_NONE, BASE_NONE,
4564 NULL, 0x0, "SIC Content", HFILL } },
4565 { &hf_message_sic_key_values,
4566 { "Content Byte", "dmp.sic_key.values", FT_UINT8, BASE_HEX,
4567 NULL, 0x0, "SIC Content Byte", HFILL } },
4568 { &hf_message_sic_key_type,
4569 { "Type", "dmp.sic_key.type", FT_UINT8, BASE_HEX,
4570 VALS (sic_key_type), 0xF0, "SIC Content Type", HFILL } },
4571 { &hf_message_sic_key_chars,
4572 { "Valid Characters", "dmp.sic_key.chars", FT_BOOLEAN, 8,
4573 TFS (&sic_key_chars), 0x08, "SIC Valid Characters", HFILL } },
4574 { &hf_message_sic_key_num,
4575 { "Number of SICs", "dmp.sic_key.num", FT_UINT8, BASE_HEX,
4576 VALS (sic_key_num), 0x07, NULL, HFILL } },
4577 { &hf_message_sic_bitmap,
4578 { "Length Bitmap (0 = 3 bytes, 1 = 4-8 bytes)", "dmp.sic_bitmap",
4579 FT_UINT8, BASE_HEX, NULL, 0xFF, "SIC Length Bitmap", HFILL } },
4580 { &hf_message_sic_bits,
4581 { "Bit 7-4", "dmp.sic_bits", FT_UINT8, BASE_HEX,
4582 VALS(sic_bit_vals), 0xF0, "SIC Bit 7-4, Characters [A-Z0-9] only",
4584 { &hf_message_sic_bits_any,
4585 { "Bit 7-4", "dmp.sic_bits_any", FT_UINT8, BASE_HEX,
4586 VALS(sic_bit_any_vals), 0xF0, "SIC Bit 7-4, Any valid characters",
4589 /* Subject Message Id */
4590 { &hf_message_subj_id,
4591 { "Subject Message Identifier", "dmp.subj_id", FT_UINT16,
4592 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4594 /* Subject MTS Identifier */
4595 { &hf_message_subj_mts_id,
4596 { "Subject MTS Identifier", "dmp.subj_mts_id", FT_STRING, BASE_NONE,
4597 NULL, 0x0, NULL, HFILL } },
4599 /* Subject IPM Identifier */
4600 { &hf_message_subj_ipm_id,
4601 { "Subject IPM Identifier", "dmp.subj_ipm_id", FT_STRING, BASE_NONE,
4602 NULL, 0x0, NULL, HFILL } },
4608 { "Message Body", "dmp.body", FT_NONE, BASE_NONE, NULL,
4613 { "EIT", "dmp.body.eit", FT_UINT8, BASE_DEC,
4614 VALS(eit_vals), 0xE0, "Encoded Information Type", HFILL } },
4615 { &hf_message_compr,
4616 { "Compression", "dmp.body.compression", FT_UINT8, BASE_DEC,
4617 VALS(compression_vals), 0x18, NULL, HFILL } },
4620 { &hf_message_subject,
4621 { "Subject", "dmp.subject", FT_STRINGZ, BASE_NONE,
4622 NULL, 0x0, NULL, HFILL } },
4625 { &hf_message_body_data,
4626 { "User data", "dmp.body.data", FT_NONE, BASE_NONE,
4627 NULL, 0x0, NULL, HFILL } },
4628 { &hf_message_body_plain,
4629 { "Message Body", "dmp.body.plain", FT_STRING, BASE_NONE,
4630 NULL, 0x0, NULL, HFILL } },
4631 { &hf_message_bodyid_uint8,
4632 { "Structured Id", "dmp.body.id", FT_UINT8, BASE_DEC,
4633 NULL, 0x0, "Structured Body Id (1 byte)", HFILL } },
4634 { &hf_message_bodyid_uint16,
4635 { "Structured Id", "dmp.body.id", FT_UINT16, BASE_DEC,
4636 NULL, 0x0, "Structured Body Id (2 bytes)", HFILL } },
4637 { &hf_message_bodyid_uint32,
4638 { "Structured Id", "dmp.body.id", FT_UINT32, BASE_DEC,
4639 NULL, 0x0, "Structured Body Id (4 bytes)", HFILL } },
4640 { &hf_message_bodyid_uint64,
4641 { "Structured Id", "dmp.body.id", FT_UINT64, BASE_DEC,
4642 NULL, 0x0, "Structured Body Id (8 bytes)", HFILL } },
4643 { &hf_message_bodyid_string,
4644 { "Structured Id", "dmp.body.id", FT_STRING, BASE_NONE,
4645 NULL, 0x0, "Structured Body Id (fixed text string)", HFILL } },
4646 { &hf_message_bodyid_zstring,
4647 { "Structured Id", "dmp.body.id", FT_STRINGZ, BASE_NONE,
4648 NULL, 0x0, "Structured Body Id (zero terminated text string)",
4650 { &hf_message_body_structured,
4651 { "Structured Body", "dmp.body.structured", FT_BYTES, BASE_NONE,
4652 NULL, 0x0, NULL, HFILL } },
4653 { &hf_message_body_uncompr,
4654 { "Uncompressed User data", "dmp.body.uncompressed", FT_NONE,
4655 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4656 { &hf_message_body_uncompressed,
4657 { "Uncompressed Message Body", "dmp.body.uncompressed",
4658 FT_STRING, BASE_NONE, NULL, 0x0, NULL,
4664 { &hf_delivery_report,
4665 { "Delivery Report", "dmp.dr", FT_NONE, BASE_NONE, NULL,
4667 { &hf_non_delivery_report,
4668 { "Non-Delivery Report", "dmp.ndr", FT_NONE, BASE_NONE, NULL,
4672 { "Report Type", "dmp.report_type", FT_BOOLEAN, 8,
4673 TFS (&report_type), 0x80, NULL, HFILL } },
4674 { &hf_report_info_present_dr,
4675 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4676 TFS (&tfs_present_absent), 0x40, NULL, HFILL } },
4677 { &hf_report_addr_enc_dr,
4678 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4679 TFS (&addr_enc), 0x20, NULL, HFILL } },
4680 { &hf_report_del_time,
4681 { "Delivery Time", "dmp.delivery_time", FT_UINT8, BASE_HEX,
4682 NULL, 0x0, NULL, HFILL } },
4683 { &hf_report_del_time_val,
4684 { "Delivery Time Value", "dmp.delivery_time_val", FT_UINT8,
4685 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4686 { &hf_report_addr_enc_ndr,
4687 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4688 TFS (&addr_enc), 0x40, NULL, HFILL } },
4689 { &hf_report_reason,
4690 { "Reason (P1)", "dmp.report_reason", FT_UINT8, BASE_DEC,
4691 VALS (p1_NonDeliveryReasonCode_vals), 0x3F,
4692 "Reason", HFILL } },
4693 { &hf_report_info_present_ndr,
4694 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4695 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4697 { "Diagnostic (P1)", "dmp.report_diagnostic", FT_UINT8, BASE_DEC,
4698 VALS (p1_NonDeliveryDiagnosticCode_vals), 0x7F,
4699 "Diagnostic", HFILL } },
4700 { &hf_report_suppl_info_len,
4701 { "Supplementary Information", "dmp.suppl_info_len", FT_UINT8,
4702 BASE_DEC, NULL, 0x0, "Supplementary Information Length", HFILL } },
4703 { &hf_report_suppl_info,
4704 { "Supplementary Information", "dmp.suppl_info", FT_STRINGZ,
4705 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4710 { &hf_receipt_notif,
4711 { "Receipt Notification (RN)", "dmp.rn", FT_NONE, BASE_NONE,
4712 NULL, 0x0, NULL, HFILL} },
4713 { &hf_non_receipt_notif,
4714 { "Non-Receipt Notification (NRN)", "dmp.nrn", FT_NONE, BASE_NONE,
4715 NULL, 0x0, NULL, HFILL} },
4717 { "Other Notification (ON)", "dmp.on", FT_NONE, BASE_NONE,
4718 NULL, 0x0, NULL, HFILL} },
4721 { "Notification Type", "dmp.notif_type", FT_UINT8, BASE_DEC,
4722 VALS (notif_type), 0x03, NULL, HFILL } },
4723 { &hf_notif_rec_time,
4724 { "Receipt Time", "dmp.receipt_time", FT_UINT8, BASE_HEX,
4725 NULL, 0x0, NULL, HFILL } },
4726 { &hf_notif_rec_time_val,
4727 { "Receipt Time Value", "dmp.receipt_time_val", FT_UINT8,
4728 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4729 { &hf_notif_suppl_info_len,
4730 { "Supplementary Information", "dmp.suppl_info_len",
4731 FT_UINT8, BASE_DEC, NULL, 0x0, "Supplementary Information Length",
4733 { &hf_notif_suppl_info,
4734 { "Supplementary Information", "dmp.suppl_info",
4735 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL,
4737 { &hf_notif_non_rec_reason,
4738 { "Non-Receipt Reason", "dmp.notif_non_rec_reason",
4739 FT_UINT8, BASE_DEC, VALS (p22_NonReceiptReasonField_vals), 0x0,
4741 { &hf_notif_discard_reason,
4742 { "Discard Reason", "dmp.notif_discard_reason", FT_UINT8,
4743 BASE_DEC, VALS (p22_DiscardReasonField_vals), 0x0,
4745 { &hf_notif_on_type,
4746 { "ON Type", "dmp.notif_on_type", FT_UINT8, BASE_DEC,
4747 VALS (on_type), 0x0, NULL, HFILL } },
4749 { "ACP127 Recipient", "dmp.acp127recip_len", FT_UINT8,
4750 BASE_DEC, NULL, 0x0, "ACP 127 Recipient Length", HFILL } },
4751 { &hf_notif_acp127recip,
4752 { "ACP127 Recipient", "dmp.acp127recip", FT_STRINGZ,
4753 BASE_NONE, NULL, 0x0, "ACP 127 Recipient", HFILL } },
4759 { "Acknowledgement", "dmp.ack", FT_NONE, BASE_NONE,
4760 NULL, 0x0, NULL, HFILL } },
4762 { "Ack Reason", "dmp.ack_reason", FT_UINT8, BASE_DEC,
4763 VALS (&ack_reason), 0x0, "Reason", HFILL } },
4764 { &hf_ack_diagnostic,
4765 { "Ack Diagnostic", "dmp.ack_diagnostic", FT_UINT8, BASE_DEC,
4766 NULL, 0x0, "Diagnostic", HFILL } },
4768 { "Recipient List", "dmp.ack_rec_list", FT_NONE, BASE_NONE,
4769 NULL, 0x0, NULL, HFILL } },
4775 { "Checksum", "dmp.checksum", FT_UINT16, BASE_HEX,
4776 NULL, 0x0, NULL, HFILL } },
4777 { &hf_checksum_good,
4778 { "Good", "dmp.checksum_good", FT_BOOLEAN, BASE_NONE,
4779 NULL, 0x0, "True: checksum matches packet content; False: doesn't match content or not checked", HFILL } },
4781 { "Bad", "dmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
4782 NULL, 0x0, "True: checksum doesn't match packet content; False: matches content or not checked", HFILL } },
4785 ** Ack matching / Resend
4787 { &hf_analysis_ack_time,
4788 { "Acknowledgement Time", "dmp.analysis.ack_time", FT_RELATIVE_TIME, BASE_NONE,
4789 NULL, 0x0, "The time between the Message and the Acknowledge", HFILL } },
4790 { &hf_analysis_rep_time,
4791 { "Report Reply Time", "dmp.analysis.report_time", FT_RELATIVE_TIME, BASE_NONE,
4792 NULL, 0x0, "The time between the Message and the Report", HFILL } },
4793 { &hf_analysis_not_time,
4794 { "Notification Reply Time", "dmp.analysis.notif_time", FT_RELATIVE_TIME, BASE_NONE,
4795 NULL, 0x0, "The time between the Message and the Notification", HFILL } },
4796 { &hf_analysis_total_time,
4797 { "Total Time", "dmp.analysis.total_time", FT_RELATIVE_TIME, BASE_NONE,
4798 NULL, 0x0, "The time between the first Message and the Acknowledge", HFILL } },
4799 { &hf_analysis_retrans_time,
4800 { "Retransmission Time", "dmp.analysis.retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4801 NULL, 0x0, "The time between the last Message and this Message", HFILL } },
4802 { &hf_analysis_total_retrans_time,
4803 { "Total Retransmission Time", "dmp.analysis.total_retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4804 NULL, 0x0, "The time between the first Message and this Message", HFILL } },
4805 { &hf_analysis_msg_num,
4806 { "Message in", "dmp.analysis.msg_in", FT_FRAMENUM, BASE_NONE,
4807 NULL, 0x0, "This packet has a Message in this frame", HFILL } },
4808 { &hf_analysis_ack_num,
4809 { "Acknowledgement in", "dmp.analysis.ack_in", FT_FRAMENUM, BASE_NONE,
4810 NULL, 0x0, "This packet has an Acknowledgement in this frame", HFILL } },
4811 { &hf_analysis_rep_num,
4812 { "Report in", "dmp.analysis.report_in", FT_FRAMENUM, BASE_NONE,
4813 NULL, 0x0, "This packet has a Report in this frame", HFILL } },
4814 { &hf_analysis_not_num,
4815 { "Notification in", "dmp.analysis.notif_in", FT_FRAMENUM, BASE_NONE,
4816 NULL, 0x0, "This packet has a Notification in this frame", HFILL } },
4817 { &hf_analysis_msg_missing,
4818 { "Message missing", "dmp.analysis.msg_missing", FT_NONE, BASE_NONE,
4819 NULL, 0x0, "The Message for this packet is missing", HFILL } },
4820 { &hf_analysis_ack_missing,
4821 { "Acknowledgement missing", "dmp.analysis.ack_missing", FT_NONE, BASE_NONE,
4822 NULL, 0x0, "The acknowledgement for this packet is missing", HFILL } },
4823 { &hf_analysis_retrans_no,
4824 { "Retransmission #", "dmp.analysis.retrans_no", FT_UINT32, BASE_DEC,
4825 NULL, 0x0, "Retransmission count", HFILL } },
4826 { &hf_analysis_ack_dup_no,
4827 { "Duplicate ACK #", "dmp.analysis.dup_ack_no", FT_UINT32, BASE_DEC,
4828 NULL, 0x0, "Duplicate Acknowledgement count", HFILL } },
4829 { &hf_analysis_msg_resend_from,
4830 { "Retransmission of Message sent in", "dmp.analysis.msg_first_sent_in",
4831 FT_FRAMENUM, BASE_NONE,
4832 NULL, 0x0, "This Message was first sent in this frame", HFILL } },
4833 { &hf_analysis_rep_resend_from,
4834 { "Retransmission of Report sent in", "dmp.analysis.report_first_sent_in",
4835 FT_FRAMENUM, BASE_NONE,
4836 NULL, 0x0, "This Report was first sent in this frame", HFILL } },
4837 { &hf_analysis_not_resend_from,
4838 { "Retransmission of Notification sent in", "dmp.analysis.notif_first_sent_in",
4839 FT_FRAMENUM, BASE_NONE,
4840 NULL, 0x0, "This Notification was first sent in this frame", HFILL } },
4841 { &hf_analysis_ack_resend_from,
4842 { "Retransmission of Acknowledgement sent in", "dmp.analysis.ack_first_sent_in",
4843 FT_FRAMENUM, BASE_NONE,
4844 NULL, 0x0, "This Acknowledgement was first sent in this frame", HFILL } },
4849 { &hf_reserved_0x01,
4850 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4851 NULL, 0x01, NULL, HFILL } },
4852 { &hf_reserved_0x02,
4853 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4854 NULL, 0x02, NULL, HFILL } },
4855 { &hf_reserved_0x04,
4856 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4857 NULL, 0x04, NULL, HFILL } },
4858 { &hf_reserved_0x07,
4859 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4860 NULL, 0x07, NULL, HFILL } },
4861 { &hf_reserved_0x08,
4862 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4863 NULL, 0x08, NULL, HFILL } },
4864 { &hf_reserved_0x0F,
4865 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4866 NULL, 0x0F, NULL, HFILL } },
4867 { &hf_reserved_0x1F,
4868 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4869 NULL, 0x1F, NULL, HFILL } },
4870 { &hf_reserved_0x20,
4871 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4872 NULL, 0x20, NULL, HFILL } },
4873 { &hf_reserved_0x40,
4874 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4875 NULL, 0x40, NULL, HFILL } },
4876 { &hf_reserved_0xC0,
4877 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4878 NULL, 0xC0, NULL, HFILL } },
4879 { &hf_reserved_0xE0,
4880 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4881 NULL, 0xE0, NULL, HFILL } },
4882 { &hf_reserved_0x8000,
4883 { "Reserved", "dmp.reserved", FT_UINT16, BASE_DEC,
4884 NULL, 0x8000, NULL, HFILL } },
4887 static gint *ett[] = {
4890 &ett_envelope_version,
4891 &ett_envelope_hop_count,
4892 &ett_envelope_rec_present,
4893 &ett_envelope_addr_enc,
4894 &ett_envelope_checksum,
4895 &ett_envelope_extensions,
4896 &ett_envelope_msg_id_type,
4897 &ett_envelope_msg_id,
4898 &ett_envelope_mts_id_length,
4899 &ett_envelope_ipm_id_length,
4900 &ett_envelope_cont_type,
4901 &ett_envelope_subm_time,
4902 &ett_envelope_time_diff,
4903 &ett_envelope_flags,
4904 &ett_envelope_recipients,
4905 &ett_envelope_ext_recipients,
4906 &ett_envelope_addresses,
4908 &ett_address_direct,
4909 &ett_address_rec_no,
4910 &ett_address_extended,
4911 &ett_address_ext_form,
4912 &ett_address_ext_rec_no,
4913 &ett_address_ext_action,
4914 &ett_address_ext_rep_req,
4915 &ett_address_ext_not_req,
4916 &ett_address_ext_type,
4917 &ett_address_ext_length,
4920 &ett_extension_header,
4923 &ett_message_st_type,
4924 &ett_message_reserved,
4925 &ett_message_precedence,
4926 &ett_message_importance,
4927 &ett_message_body_format,
4928 &ett_message_sec_class,
4929 &ett_message_sec_pol,
4930 &ett_message_sec_cat,
4931 &ett_message_heading_flags,
4932 &ett_message_exp_time,
4935 &ett_message_sic_key,
4936 &ett_message_sic_bitmap,
4937 &ett_message_sic_bits,
4940 &ett_message_body_reserved,
4942 &ett_message_body_uncompr,
4945 &ett_report_info_present_dr,
4946 &ett_report_info_present_ndr,
4947 &ett_report_addr_enc_dr,
4948 &ett_report_addr_enc_ndr,
4949 &ett_report_reserved,
4950 &ett_report_del_time,
4952 &ett_report_suppl_info,
4956 &ett_notif_rec_time,
4957 &ett_notif_suppl_info,
4958 &ett_notif_acp127recip,
4965 static uat_field_t attributes_flds[] = {
4966 UAT_FLD_VS(dmp_security_class,nation, "Nation", nat_pol_id, 0),
4967 UAT_FLD_DEC(dmp_security_class,sec_class, "Classification", "Security Classification"),
4968 UAT_FLD_CSTRING(dmp_security_class,name, "Name", "Classification Name"),
4972 uat_t *attributes_uat = uat_new("DMP Security Classifications",
4973 sizeof(dmp_security_class_t),
4974 "dmp_security_classifications",
4976 (void*) &dmp_security_classes,
4977 &num_dmp_security_classes,
4978 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4979 "ChDMPSecurityClassifications",
4986 module_t *dmp_module;
4988 proto_dmp = proto_register_protocol (PNAME, PSNAME, PFNAME);
4989 register_dissector(PFNAME, dissect_dmp, proto_dmp);
4991 proto_register_field_array (proto_dmp, hf, array_length (hf));
4992 proto_register_subtree_array (ett, array_length (ett));
4993 register_init_routine (&dmp_init_routine);
4995 /* Set default UDP ports */
4996 range_convert_str (&global_dmp_port_range, DEFAULT_DMP_PORT_RANGE,
4999 /* Build national values */
5000 build_national_strings ();
5002 /* Register our configuration options */
5003 dmp_module = prefs_register_protocol (proto_dmp, proto_reg_handoff_dmp);
5005 prefs_register_obsolete_preference (dmp_module, "udp_port");
5006 prefs_register_obsolete_preference (dmp_module, "udp_port_second");
5008 prefs_register_range_preference (dmp_module, "udp_ports",
5010 "Port numbers used for DMP traffic",
5011 &global_dmp_port_range, MAX_UDP_PORT);
5012 prefs_register_enum_preference (dmp_module, "national_decode",
5013 "National decoding",
5014 "Select the type of decoding for nationally-defined values",
5015 &dmp_nat_decode, national_decoding,
5017 prefs_register_enum_preference (dmp_module, "local_nation",
5018 "Nation of local server",
5019 "Select the nation of sending server. This is used when presenting"
5020 " security classification values in messages with security"
5021 " policy set to National (nation of local server)",
5022 &dmp_local_nation, dmp_national_values,
5024 prefs_register_uat_preference (dmp_module, "classes_table",
5025 "National Security Classifications",
5026 "Translation table for national security classifications. This is used"
5027 " when presenting security classification values in messages with"
5028 " security policy set to National or Extended National",
5030 prefs_register_bool_preference (dmp_module, "seq_ack_analysis",
5032 "Calculate sequence/acknowledgement analysis",
5033 &use_seq_ack_analysis);
5034 prefs_register_bool_preference (dmp_module, "align_ids",
5035 "Align identifiers in info list",
5036 "Align identifiers in info list"
5037 " (does not align when retransmission or"
5038 " duplicate acknowledgement indication)",
5040 prefs_register_bool_preference (dmp_module, "subject_as_id",
5041 "Print subject as body id",
5042 "Print subject as body id in free text "
5043 "messages with subject",
5044 &dmp_subject_as_id);
5045 prefs_register_enum_preference (dmp_module, "struct_print",
5046 "Structured message id format",
5047 "Format of the structured message id",
5048 &dmp_struct_format, struct_id_options,
5050 prefs_register_uint_preference (dmp_module, "struct_offset",
5051 "Offset to structured message id",
5052 "Used to set where the structured message "
5053 "id starts in the User Data",
5054 10, &dmp_struct_offset);
5056 prefs_register_uint_preference (dmp_module, "struct_length",
5057 "Fixed text string length",
5058 "Used to set length of fixed text string "
5059 "in the structured message id format "
5060 "(maximum 128 characters)",
5061 10, &dmp_struct_length);
5064 static void range_delete_callback (guint32 port)
5066 dissector_delete_uint ("udp.port", port, dmp_handle);
5069 static void range_add_callback (guint32 port)
5071 dissector_add_uint ("udp.port", port, dmp_handle);
5074 void proto_reg_handoff_dmp (void)
5076 static range_t *dmp_port_range;
5077 static gboolean dmp_prefs_initialized = FALSE;
5079 if (!dmp_prefs_initialized) {
5080 dmp_handle = find_dissector (PFNAME);
5081 dmp_prefs_initialized = TRUE;
5083 range_foreach (dmp_port_range, range_delete_callback);
5084 g_free (dmp_port_range);
5087 /* Save port number for later deletion */
5088 dmp_port_range = range_copy (global_dmp_port_range);
5090 range_foreach (dmp_port_range, range_add_callback);
5099 * indent-tabs-mode: nil
5102 * ex: set shiftwidth=2 tabstop=8 expandtab:
5103 * :indentSize=2:tabSize=8:noTabs=true: