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
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 * Ref: http://jcs.dtic.mil/j6/cceb/acps/acp123/
33 * - Dissect extended Restrictive security categories
34 * - Add Transmission/Retransmission statistics
41 #include <epan/packet.h>
42 #include <epan/to_str.h>
43 #include <epan/prefs.h>
44 #include <epan/expert.h>
45 #include <epan/crc16-tvb.h>
46 #include <epan/asn1.h>
47 #include <epan/strutil.h>
49 #include <epan/proto_data.h>
51 #include <wsutil/str_util.h>
53 #include "packet-p1.h"
54 #include "packet-p22.h"
55 #include "packet-s5066sis.h"
57 void proto_register_dmp(void);
58 void proto_reg_handoff_dmp(void);
60 #define PNAME "Direct Message Profile"
64 /* Default UDP Port Number */
65 #define DEFAULT_DMP_PORT_RANGE "5031"
67 /* Protocol Identifier */
71 /* Versions supported */
72 #define DMP_VERSION_1 1
73 #define DMP_VERSION_2 2
75 /* Message Type (dmp.msg_type) */
82 /* Message Identifier Type (dmp.msg_id_type) */
83 #define ONLY_DMP_ID 0x0
84 #define X400_MSG_ID 0x1
85 #define NAT_MSG_ID 0x2
87 /* Report Type (dmp.report_type) */
91 /* Notification Type (dmp.notif_type) */
96 /* Address Encoding (dmp.addr_enc) */
97 #define DIRECT_ADDR 0x0
98 #define EXTENDED_ADDR 0x1
100 /* Address type (internal values) */
104 #define ORIG_P2_ADDRESS 4
106 /* Extended Address Form (dmp_addr_form) */
107 #define P1_DIRECT 0x0
108 #define P2_DIRECT 0x1
109 #define P1_EXTENDED 0x2
110 #define P2_EXTENDED 0x3
111 #define P1_P2_DIRECT 0x4
112 #define P1_DIRECT_P2_EXTENDED 0x5
113 #define P1_EXTENDED_P2_DIRECT 0x6
114 #define P1_P2_EXTENDED 0x7
116 /* Extended Address Type */
120 /* Security Policy (dmp_sec_pol) */
123 #define EXTENDED_NATIONAL 0x6
124 #define EXTENDED_MISSION 0x7
126 #define SEC_CAT_EXT_NONE 0x0
127 #define SEC_CAT_EXT_PERMISSIVE 0x1
128 #define SEC_CAT_EXT_RESTRICTIVE 0x2
130 /* Body Format (dmp.body_format) */
131 #define FREE_TEXT 0x0
132 #define FREE_TEXT_SUBJECT 0x1
133 #define STRUCTURED 0x2
135 /* Encoded Information Types */
136 #define EIT_BILATERAL 0x3
138 /* Compression Algorithm */
139 #define ALGORITHM_NONE 0x0
140 #define ALGORITHM_ZLIB 0x1
142 /* National Decoding */
143 #define NAT_DECODE_NONE 0
144 #define NAT_DECODE_DMP 1
145 #define NAT_DECODE_THALES 2
147 #define IPM_MODIFIER_X400 0
149 /* Internal values for not present and reserved time values */
150 #define DMP_TIME_NOT_PRESENT -1
151 #define DMP_TIME_RESERVED -2
153 #define ILLEGAL_FORMAT "<Illegal format>"
154 #define TIME_NOT_REPRESENTABLE "<Time not representable>"
156 /* Maximum lengths */
157 #define MAX_SIC_LEN 30
159 static int proto_dmp = -1;
161 static int hf_dmp_id = -1;
162 static int hf_mts_id = -1;
163 static int hf_ipm_id = -1;
165 static int hf_envelope = -1;
166 static int hf_envelope_protocol_id = -1;
167 static int hf_envelope_version = -1;
168 static int hf_envelope_version_value = -1;
169 static int hf_envelope_hop_count = -1;
170 static int hf_envelope_hop_count_value = -1;
171 static int hf_envelope_rec_present = -1;
172 static int hf_envelope_addr_enc = -1;
173 static int hf_envelope_checksum = -1;
174 static int hf_envelope_extensions = -1;
175 static int hf_envelope_msg_id_type = -1;
176 static int hf_envelope_msg_id_length = -1;
177 static int hf_envelope_mts_id_length = -1;
178 static int hf_envelope_ipm_id_modifier = -1;
179 static int hf_envelope_ipm_id_length = -1;
180 static int hf_envelope_mts_id = -1;
181 static int hf_envelope_ipm_id = -1;
182 static int hf_envelope_type = -1;
183 static int hf_envelope_msg_id = -1;
184 static int hf_envelope_msg_id_12bit = -1;
185 static int hf_envelope_subm_time = -1;
186 static int hf_envelope_subm_time_value = -1;
187 static int hf_envelope_time_diff_present = -1;
188 static int hf_envelope_time_diff = -1;
189 static int hf_envelope_time_diff_value = -1;
190 static int hf_envelope_flags = -1;
191 static int hf_envelope_content_id_discarded = -1;
192 static int hf_envelope_recip_reassign_prohib = -1;
193 static int hf_envelope_dl_expansion_prohib = -1;
194 static int hf_envelope_recipients = -1;
195 static int hf_envelope_ext_recipients = -1;
197 static int hf_thales_ipm_id_modifier = -1;
199 static int hf_extensions = -1;
200 static int hf_extension = -1;
201 static int hf_extension_header = -1;
202 static int hf_extension_more = -1;
203 static int hf_extension_length = -1;
204 static int hf_extension_data = -1;
206 static int hf_message_content = -1;
207 static int hf_report_content = -1;
208 static int hf_notif_content = -1;
210 static int hf_addr_recipient = -1;
211 static int hf_addr_originator = -1;
212 static int hf_addr_reporting_name = -1;
213 static int hf_addr_dl_expanded = -1;
214 static int hf_addr_int_rec = -1;
215 static int hf_addr_dir_addr_ext = -1;
216 static int hf_addr_dir_rec_no = -1;
217 static int hf_addr_dir_rec_no1 = -1;
218 static int hf_addr_dir_rec_no2 = -1;
219 static int hf_addr_dir_rec_no3 = -1;
220 static int hf_addr_dir_rec_no_generated = -1;
221 static int hf_addr_dir_rep_req1 = -1;
222 static int hf_addr_dir_rep_req2 = -1;
223 static int hf_addr_dir_rep_req3 = -1;
224 static int hf_addr_dir_not_req1 = -1;
225 static int hf_addr_dir_not_req2 = -1;
226 static int hf_addr_dir_not_req3 = -1;
227 static int hf_addr_dir_action = -1;
228 static int hf_addr_dir_address = -1;
229 static int hf_addr_dir_address1 = -1;
230 static int hf_addr_dir_address2 = -1;
231 static int hf_addr_dir_address3 = -1;
232 static int hf_addr_dir_address_generated = -1;
234 static int hf_addr_ext_form = -1;
235 static int hf_addr_ext_form_orig_v1 = -1;
236 static int hf_addr_ext_form_orig = -1;
237 static int hf_addr_ext_action = -1;
238 static int hf_addr_ext_rep_req = -1;
239 static int hf_addr_ext_not_req = -1;
240 static int hf_addr_ext_rec_ext = -1;
241 static int hf_addr_ext_rec_no = -1;
242 static int hf_addr_ext_rec_no1 = -1;
243 static int hf_addr_ext_rec_no2 = -1;
244 static int hf_addr_ext_rec_no_generated = -1;
245 static int hf_addr_ext_address = -1;
246 static int hf_addr_ext_type = -1;
247 static int hf_addr_ext_type_ext = -1;
248 static int hf_addr_ext_length = -1;
249 static int hf_addr_ext_length1 = -1;
250 static int hf_addr_ext_length2 = -1;
251 static int hf_addr_ext_length_generated = -1;
252 static int hf_addr_ext_asn1_ber = -1;
253 static int hf_addr_ext_asn1_per = -1;
254 static int hf_addr_ext_unknown = -1;
256 static int hf_message_body = -1;
257 static int hf_message_st_type = -1;
258 static int hf_message_precedence = -1;
259 static int hf_message_importance = -1;
260 static int hf_message_body_format = -1;
261 static int hf_message_sec_class_val = -1;
262 static int hf_message_sec_pol = -1;
263 static int hf_message_heading_flags = -1;
264 static int hf_message_auth_users = -1;
265 static int hf_message_subject_disc = -1;
266 static int hf_message_national_policy_id = -1;
267 static int hf_message_mission_policy_id = -1;
268 static int hf_message_sec_label = -1;
269 static int hf_message_sec_cat_nat = -1;
270 static int hf_message_sec_cat_val = -1;
271 static int hf_message_sec_cat_cl = -1;
272 static int hf_message_sec_cat_cs = -1;
273 static int hf_message_sec_cat_ex = -1;
274 static int hf_message_sec_cat_ne = -1;
275 static int hf_message_sec_cat_permissive = -1;
276 static int hf_message_sec_cat_country_code = -1;
277 static int hf_message_sec_cat_restrictive = -1;
278 static int hf_message_sec_cat_extended = -1;
279 static int hf_message_sec_cat_bit0 = -1;
280 static int hf_message_sec_cat_bit1 = -1;
281 static int hf_message_sec_cat_bit2 = -1;
282 static int hf_message_sec_cat_bit3 = -1;
283 static int hf_message_sec_cat_bit4 = -1;
284 static int hf_message_sec_cat_bit5 = -1;
285 static int hf_message_sec_cat_bit6 = -1;
286 static int hf_message_sec_cat_bit7 = -1;
287 static int hf_message_exp_time = -1;
288 static int hf_message_exp_time_val = -1;
289 static int hf_message_dtg = -1;
290 static int hf_message_dtg_sign = -1;
291 static int hf_message_dtg_val = -1;
292 static int hf_message_sic = -1;
293 static int hf_message_sic_key = -1;
294 static int hf_message_sic_key_values = -1;
295 static int hf_message_sic_key_type = -1;
296 static int hf_message_sic_key_chars = -1;
297 static int hf_message_sic_key_num = -1;
298 static int hf_message_sic_bitmap = -1;
299 static int hf_message_sic_bits = -1;
300 static int hf_message_sic_bits_any = -1;
301 static int hf_message_subj_id = -1;
302 static int hf_message_subj_mts_id = -1;
303 static int hf_message_subj_ipm_id = -1;
305 static int hf_message_subject = -1;
306 static int hf_message_eit = -1;
307 static int hf_message_compr = -1;
308 static int hf_message_body_data = -1;
309 static int hf_message_body_compressed = -1;
310 static int hf_message_body_plain = -1;
311 static int hf_message_body_structured = -1;
313 static int hf_delivery_report = -1;
314 static int hf_non_delivery_report = -1;
315 static int hf_report_type = -1;
316 static int hf_report_info_present_dr = -1;
317 static int hf_report_addr_enc_dr = -1;
318 static int hf_report_del_time = -1;
319 static int hf_report_del_time_val = -1;
320 static int hf_report_addr_enc_ndr = -1;
321 static int hf_report_reason = -1;
322 static int hf_report_info_present_ndr = -1;
323 static int hf_report_diagn = -1;
324 static int hf_report_suppl_info_len = -1;
325 static int hf_report_suppl_info = -1;
327 static int hf_receipt_notif = -1;
328 static int hf_non_receipt_notif = -1;
329 static int hf_other_notif = -1;
330 static int hf_notif_type = -1;
331 static int hf_notif_rec_time = -1;
332 static int hf_notif_rec_time_val = -1;
333 static int hf_notif_suppl_info_len = -1;
334 static int hf_notif_suppl_info = -1;
335 static int hf_notif_non_rec_reason = -1;
336 static int hf_notif_discard_reason = -1;
337 static int hf_notif_on_type = -1;
338 static int hf_notif_acp127 = -1;
339 static int hf_notif_acp127recip = -1;
341 static int hf_ack = -1;
342 static int hf_ack_reason = -1;
343 static int hf_ack_diagnostic = -1;
344 static int hf_ack_recips = -1;
346 static int hf_checksum = -1;
347 static int hf_checksum_status = -1;
349 static int hf_analysis_ack_time = -1;
350 static int hf_analysis_total_time = -1;
351 static int hf_analysis_retrans_time = -1;
352 static int hf_analysis_total_retrans_time = -1;
353 static int hf_analysis_msg_num = -1;
354 static int hf_analysis_acks_msg_num = -1;
355 static int hf_analysis_retrans_no = -1;
356 static int hf_analysis_ack_num = -1;
357 static int hf_analysis_ack_missing = -1;
358 static int hf_analysis_ack_dup_no = -1;
359 /* static int hf_analysis_rep_num = -1; */
360 static int hf_analysis_acks_rep_num = -1;
361 static int hf_analysis_rep_time = -1;
362 /* static int hf_analysis_not_num = -1; */
363 static int hf_analysis_acks_not_num = -1;
364 static int hf_analysis_not_time = -1;
365 static int hf_analysis_msg_resend_from = -1;
366 static int hf_analysis_rep_resend_from = -1;
367 static int hf_analysis_not_resend_from = -1;
368 static int hf_analysis_ack_resend_from = -1;
370 static int hf_reserved_0x01 = -1;
371 static int hf_reserved_0x02 = -1;
372 static int hf_reserved_0x04 = -1;
373 static int hf_reserved_0x07 = -1;
374 static int hf_reserved_0x08 = -1;
375 static int hf_reserved_0x0F = -1;
376 static int hf_reserved_0x1F = -1;
377 static int hf_reserved_0x20 = -1;
378 static int hf_reserved_0x40 = -1;
379 static int hf_reserved_0xC0 = -1;
380 static int hf_reserved_0xE0 = -1;
381 static int hf_reserved_0x8000 = -1;
383 static gint ett_dmp = -1;
384 static gint ett_envelope = -1;
385 static gint ett_envelope_version = -1;
386 static gint ett_envelope_hop_count = -1;
387 static gint ett_envelope_rec_present = -1;
388 static gint ett_envelope_addr_enc = -1;
389 static gint ett_envelope_checksum = -1;
390 static gint ett_envelope_extensions = -1;
391 static gint ett_envelope_msg_id_type = -1;
392 static gint ett_envelope_msg_id = -1;
393 static gint ett_envelope_mts_id_length = -1;
394 static gint ett_envelope_ipm_id_length = -1;
395 static gint ett_envelope_cont_type = -1;
396 static gint ett_envelope_subm_time = -1;
397 static gint ett_envelope_time_diff = -1;
398 static gint ett_envelope_flags = -1;
399 static gint ett_envelope_recipients = -1;
400 static gint ett_envelope_ext_recipients = -1;
401 static gint ett_envelope_addresses = -1;
403 static gint ett_address = -1;
404 static gint ett_address_direct = -1;
405 static gint ett_address_rec_no = -1;
406 static gint ett_address_extended = -1;
407 static gint ett_address_ext_form = -1;
408 static gint ett_address_ext_rec_no = -1;
409 static gint ett_address_ext_action = -1;
410 static gint ett_address_ext_rep_req = -1;
411 static gint ett_address_ext_not_req = -1;
412 static gint ett_address_ext_type = -1;
413 static gint ett_address_ext_length = -1;
415 static gint ett_extensions = -1;
416 static gint ett_extension = -1;
417 static gint ett_extension_header = -1;
419 static gint ett_content = -1;
421 static gint ett_message = -1;
422 static gint ett_message_st_type = -1;
423 static gint ett_message_reserved = -1;
424 static gint ett_message_precedence = -1;
425 static gint ett_message_importance = -1;
426 static gint ett_message_body_format = -1;
427 static gint ett_message_sec_class = -1;
428 static gint ett_message_sec_pol = -1;
429 static gint ett_message_sec_cat = -1;
430 static gint ett_message_heading_flags = -1;
431 static gint ett_message_exp_time = -1;
432 static gint ett_message_dtg = -1;
433 static gint ett_message_sic = -1;
434 static gint ett_message_sic_key = -1;
435 static gint ett_message_sic_bitmap = -1;
436 static gint ett_message_sic_bits = -1;
437 static gint ett_message_eit = -1;
438 static gint ett_message_compr = -1;
439 static gint ett_message_body_reserved = -1;
440 static gint ett_message_body = -1;
442 static gint ett_report = -1;
443 static gint ett_report_type = -1;
444 static gint ett_report_info_present_dr = -1;
445 static gint ett_report_info_present_ndr = -1;
446 static gint ett_report_addr_enc_dr = -1;
447 static gint ett_report_addr_enc_ndr = -1;
448 static gint ett_report_reserved = -1;
449 static gint ett_report_del_time = -1;
450 static gint ett_report_reason = -1;
451 static gint ett_report_suppl_info = -1;
452 static gint ett_report_diagn = -1;
454 static gint ett_notif = -1;
455 static gint ett_notif_type = -1;
456 static gint ett_notif_rec_time = -1;
457 static gint ett_notif_suppl_info = -1;
458 static gint ett_notif_acp127recip = -1;
460 static gint ett_ack = -1;
461 static gint ett_ack_recips = -1;
463 static gint ett_analysis = -1;
465 static expert_field ei_reserved_value = EI_INIT;
466 static expert_field ei_message_sic_illegal = EI_INIT;
467 static expert_field ei_envelope_version_value = EI_INIT;
468 static expert_field ei_message_compr = EI_INIT;
469 static expert_field ei_ack_reason = EI_INIT;
470 static expert_field ei_addr_dir_rec_no_generated = EI_INIT;
471 static expert_field ei_checksum_bad = EI_INIT;
472 static expert_field ei_message_body_uncompress = EI_INIT;
473 static expert_field ei_addr_ext_rec_no_generated = EI_INIT;
474 static expert_field ei_envelope_msg_id = EI_INIT;
475 static expert_field ei_7bit_string_unused_bits = EI_INIT;
476 static expert_field ei_analysis_ack_missing = EI_INIT;
477 static expert_field ei_analysis_ack_dup_no = EI_INIT;
478 static expert_field ei_analysis_ack_unexpected = EI_INIT;
479 static expert_field ei_analysis_msg_missing = EI_INIT;
480 static expert_field ei_analysis_retrans_no = EI_INIT;
482 static dissector_handle_t dmp_handle;
484 typedef struct _dmp_id_key {
490 typedef struct _dmp_id_val {
491 gint msg_type; /* Message type */
492 guint prev_msg_id; /* Previous message package num */
493 guint msg_id; /* Message package num */
494 guint ack_id; /* Acknowledgement package num */
495 guint rep_id; /* Report package num */
496 guint not_id; /* Notification package num */
497 nstime_t msg_time; /* Message receive time */
498 nstime_t first_msg_time; /* First message receive time */
499 nstime_t prev_msg_time; /* Previous message receive time */
500 nstime_t rep_not_msg_time; /* Report or Notification time */
501 guint32 msg_resend_count; /* Message resend counter */
502 guint32 ack_resend_count; /* Acknowledgement resend counter */
505 static GHashTable *dmp_id_hash_table = NULL;
506 static GHashTable *dmp_long_id_hash_table = NULL;
508 /* Global values used in several functions */
509 static struct dmp_data {
521 guint8 mts_id_length;
522 proto_item *mts_id_item;
530 gboolean ack_rec_present;
534 /* User definable values */
535 static gint dmp_nat_decode = NAT_DECODE_DMP;
536 static gint dmp_local_nation = 0;
537 static gboolean use_seq_ack_analysis = TRUE;
538 static gboolean dmp_align = FALSE;
540 typedef struct _dmp_security_class_t {
544 } dmp_security_class_t;
546 static dmp_security_class_t *dmp_security_classes;
547 static guint num_dmp_security_classes;
549 static const true_false_string addr_enc = {
550 "Use Extended Encoding", "Use Direct Encoding"
553 static const true_false_string dtg_sign = {
557 static const true_false_string report_type = {
558 "Non-Delivery Report", "Delivery Report"
561 static const value_string version_vals[] = {
572 static const value_string type_vals[] = {
574 { 0x1, "Message (E-Mail)" },
576 { 0x3, "Notification" },
577 { 0x4, "Acknowledgement" },
578 { 0x5, "Unknown Content" },
579 { 0x6, "Unknown Content" },
580 { 0x7, "Unknown Content" },
583 static const value_string msg_id_type_vals[] = {
584 { 0x0, "DMP Identifiers only" },
585 { 0x1, "X.400 Message Identifiers" },
586 { 0x2, "Nationally-defined" },
590 static const value_string msg_id_length_vals[] = {
591 { 0x0, "Full (16 bits)" },
592 { 0x1, "Short (12 bits)" },
595 static const value_string report_vals[] = {
596 { 0x0, "No Report" },
597 { 0x1, "Non-Delivery Report" },
598 { 0x2, "Delivery Report" },
602 static const value_string report_vals_ext[] = {
603 { 0x0, "No Report" },
604 { 0x1, "Non-Delivery Report" },
605 { 0x2, "Delivery Report" },
606 { 0x3, "Recipient Number Extended" },
609 /* Note the space in front of these values */
610 static const value_string report_vals_short[] = {
615 static const value_string notif_vals[] = {
616 { 0x0, "No Notification" },
617 { 0x1, "Non-Receipt Notification" },
618 { 0x2, "Receipt Notification" },
622 static const value_string notif_vals_ext[] = {
623 { 0x0, "No Notification" },
624 { 0x1, "Non-Receipt Notification" },
625 { 0x2, "Receipt Notification" },
626 { 0x3, "Direct Address Extended" },
629 /* Note the space in front of these values */
630 static const value_string notif_vals_short[] = {
635 static const value_string notif_type [] = {
636 { 0x0, "Receipt Notification (RN)" },
637 { 0x1, "Non-Receipt Notification (NRN)" },
638 { 0x2, "Other Notification (ON)" },
639 { 0x3, "Unknown Notification" },
642 /* Note the space behind these values */
643 static const value_string addr_type_str [] = {
645 { P1_ADDRESS, "P1 " },
646 { P2_ADDRESS, "P22/P772 " },
647 { ORIG_P2_ADDRESS, "P22 " },
650 static const value_string addr_form [] = {
651 { 0x0, "P1 Direct" },
652 { 0x1, "P22/P772 Direct" },
653 { 0x2, "P1 Extended" },
654 { 0x3, "P22/P772 Extended" },
655 { 0x4, "P1 and P22/P772 Direct" },
656 { 0x5, "P1 Direct and P22/P772 Extended" },
657 { 0x6, "P1 Extended and P22/P772 Direct" },
658 { 0x7, "P1 and P22/P772 Extended" },
661 static const value_string addr_form_orig_v1 [] = {
672 static const value_string addr_form_orig [] = {
677 { 0x4, "Originator and P2 Direct" },
678 { 0x5, "Originator Direct and P2 Extended" },
679 { 0x6, "Originator Extended and P2 Direct" },
680 { 0x7, "Originator and P2 Extended" },
683 static const value_string ext_addr_type [] = {
684 { 0x0, "ASN.1 BER-encoded OR-name" },
685 { 0x1, "ASN.1 PER-encoded OR-name" },
691 { 0x7, "Address Length Extended" },
694 static const value_string ext_addr_type_ext [] = {
695 { 0x0, "ASN.1 BER-encoded OR-name" },
696 { 0x1, "ASN.1 PER-encoded OR-name" },
705 static const value_string ext_addr_type_short [] = {
706 { 0x0, "OR-name (BER)" },
707 { 0x1, "OR-name (PER)" },
716 static const value_string message_type_vals[] = {
717 { 0x0, "Operation" },
723 static const value_string precedence[] = {
727 { 0x3, "Immediate" },
730 { 0x6, "Priority, Info Precedence: Routine" },
731 { 0x7, "Immediate, Info Precedence: Routine" },
734 static const value_string importance[] = {
745 static const value_string sec_class[] = {
747 { 0x1, "Unclassified" },
748 /* { 0x2, "Reserved" }, */
749 { 0x3, "Restricted" },
750 /* { 0x4, "Reserved" }, */
751 { 0x5, "Confidential" },
753 { 0x7, "Top secret" },
756 static const value_string sec_pol[] = {
757 { 0x0, "Network defined" },
758 { 0x1, "Network defined" },
759 { 0x2, "Network defined" },
760 { 0x3, "Network defined" },
762 { 0x5, "National (nation of local server)" },
763 { 0x6, "Extended, National" },
764 { 0x7, "Extended, Mission Defined" },
767 #define MAX_NATIONAL_VALUES 56
768 /* Will be built in build_national_strings() */
769 static value_string nat_pol_id[MAX_NATIONAL_VALUES+1];
771 /* For name we use the ISO 3166-1 Alfa-3 value for the country,
772 * for description we use the Country Name and
773 * for value we use the DMP value for National Policy Identifier.
775 static const enum_val_t dmp_national_values[MAX_NATIONAL_VALUES+1] = {
776 { "???", "None", 0x00 },
777 { "alb", "Albania", 0x1B },
778 { "arm", "Armenia", 0x20 },
779 { "aut", "Austria", 0x21 },
780 { "aze", "Azerbaijan", 0x22 },
781 { "blr", "Belarus", 0x23 },
782 { "bel", "Belgium", 0x01 },
783 { "bih", "Bosnia and Hercegowina", 0x24 },
784 { "bgr", "Bulgaria", 0x02 },
785 { "can", "Canada", 0x03 },
786 { "hrv", "Croatia", 0x1C },
787 { "cze", "Czech Republic", 0x04 },
788 { "dnk", "Denmark", 0x05 },
789 { "est", "Estonia", 0x06 },
790 { "eapc", "Euro-Atlantic Partnership Council (EAPC)", 0x3A },
791 { "eu", "European Union (EU)", 0x3B },
792 { "fin", "Finland", 0x25 },
793 { "mkd", "Former Yugoslav Republic of Macedonia", 0x26 },
794 { "fra", "France", 0x07 },
795 { "geo", "Georgia", 0x27 },
796 { "deu", "Germany", 0x08 },
797 { "grc", "Greece", 0x09 },
798 { "hun", "Hungary", 0x0A },
799 { "isl", "Iceland", 0x0B },
800 { "isaf", "International Security Assistance Force (ISAF)", 0x3C },
801 { "irl", "Ireland", 0x28 },
802 { "ita", "Italy", 0x0C },
803 { "kaz", "Kazakhstan", 0x29 },
804 { "kgz", "Kyrgyztan", 0x2A },
805 { "lva", "Latvia", 0x0D },
806 { "ltu", "Lithuania", 0x0E },
807 { "lux", "Luxembourg", 0x0F },
808 { "mlt", "Malta", 0x2B },
809 { "mda", "Moldova", 0x2C },
810 { "mne", "Montenegro", 0x2D },
811 { "nld", "Netherlands", 0x10 },
812 { "nor", "Norway", 0x11 },
813 { "pfp", "Partnership for Peace (PfP)", 0x3D },
814 { "pol", "Poland", 0x12 },
815 { "ptr", "Portugal", 0x13 },
816 { "rou", "Romania", 0x14 },
817 { "rus", "Russian Federation", 0x2E },
818 { "srb", "Serbia", 0x2F },
819 { "svk", "Slovakia", 0x15 },
820 { "svn", "Slovenia", 0x16 },
821 { "esp", "Spain", 0x17 },
822 { "swe", "Sweden", 0x30 },
823 { "che", "Switzerland", 0x31 },
824 { "tjk", "Tajikistan", 0x32 },
825 { "tur", "Turkey", 0x18 },
826 { "tkm", "Turkmenistan", 0x33 },
827 { "gbr", "United Kingdom", 0x19 },
828 { "usa", "United States", 0x1A },
829 { "ukr", "Ukraine", 0x34 },
830 { "uzb", "Uzbekistan", 0x35 },
831 { "weu", "Western European Union (WEU)", 0x3E },
835 static const value_string ext_sec_cat[] = {
836 { 0x0, "Not present" },
837 { 0x1, "Permissive category follows" },
838 { 0x2, "Restrictive category follows" },
842 static const value_string sic_key_type[] = {
843 { 0xc, "2 or more 3-character SICs" },
844 { 0xd, "1 or more 3-to-8 character SICs" },
847 static const true_false_string sic_key_chars = {
848 "Any", "[A-Z0-9] only"
851 static const value_string sic_key_num[] = {
863 static const value_string sic_bit_vals[] = {
864 { 0, "length:6, bytes:4" },
865 { 1, "length:6, bytes:4" },
866 { 2, "length:6, bytes:4" },
867 { 3, "length:6, bytes:4" },
868 { 4, "length:6, bytes:4" },
869 { 5, "length:6, bytes:4" },
870 { 6, "length:6, bytes:4" },
871 { 7, "length:6, bytes:4" },
872 { 8, "length:6, bytes:4" },
874 { 10, "length:5, bytes:4" },
875 { 11, "length:8, bytes:6" },
876 { 12, "length:4, bytes:3" },
877 { 13, "length:4, bytes:3" },
878 { 14, "length:7, bytes:5" },
879 { 15, "length:7, bytes:5" },
882 static const value_string sic_bit_any_vals[] = {
883 { 0, "length:5, bytes:4" },
884 { 1, "length:5, bytes:4" },
885 { 2, "length:5, bytes:4" },
886 { 3, "length:5, bytes:4" },
887 { 4, "length:5, bytes:4" },
888 { 5, "length:5, bytes:4" },
889 { 6, "length:5, bytes:4" },
890 { 7, "length:5, bytes:4" },
891 { 8, "length:5, bytes:4" },
892 { 9, "length:8, bytes:7" },
893 { 10, "length:4, bytes:4" },
894 { 11, "length:7, bytes:6" },
895 { 12, "length:6, bytes:5" },
896 { 13, "length:6, bytes:5" },
897 { 14, "length:6, bytes:5" },
898 { 15, "length:6, bytes:5" },
901 static const value_string body_format_vals[] = {
902 { 0x0, "Free text" },
903 { 0x1, "Free text including subject" },
904 { 0x2, "Structured" },
908 static const value_string eit_vals[] = {
911 { 0x2, "General text" },
912 { 0x3, "Bilaterally defined (binary data)" },
919 static const value_string compression_vals[] = {
920 { 0x0, "No compression" },
921 { 0x1, "ZLib compressed" },
926 static const value_string ack_reason [] = {
927 { 0x00, "Successful, positive acknowledgement" },
928 { 0x01, "Unspecified error" },
929 { 0x02, "Checksum incorrect" },
932 static const value_string non_del_reason [] = {
933 { 0x3D, "Unknown reason" },
934 { 0x3E, "Reason code greater than 0x3c (60)" },
935 { 0x3F, "Reserved" },
938 static const value_string non_del_diagn [] = {
939 { 0x7C, "Diagnostic not specified" },
940 { 0x7D, "Unknown diagnostic" },
941 { 0x7E, "Diagnostic code greater than 0x7b (123)" },
942 { 0x7F, "Reserved" },
945 static const value_string discard_reason [] = {
946 { 0xFE, "Discard Reason absent" },
947 { 0xFF, "Reserved" },
950 static const value_string on_type [] = {
951 { 0x00, "acp127-nn" },
952 { 0x01, "acp127-pn" },
953 { 0x02, "acp127-tn" },
956 static const value_string ack_msg_type [] = {
957 { STANAG, " (message)" },
958 { IPM, " (e-mail)" },
959 { REPORT, " (report)" },
960 { NOTIF, " (notif)" },
964 static const enum_val_t national_decoding[] = {
965 { "none", "None (raw data)", NAT_DECODE_NONE },
966 { "dmp", "As for regular", NAT_DECODE_DMP },
967 { "thales", "Thales XOmail", NAT_DECODE_THALES },
971 static const value_string ipm_id_modifier[] = {
972 { 0x0, "X.400 IPM Identifier" },
973 { 0x1, "Nationally-defined" },
974 { 0x2, "Nationally-defined" },
975 { 0x3, "Nationally-defined" },
979 static const value_string thales_ipm_id_modifier[] = {
980 { 0x0, "X.400 IPM Identifier" },
981 { 0x1, "3 or 5 digits" },
987 UAT_VS_DEF(dmp_security_class, nation, dmp_security_class_t, guint, 0, "None")
988 UAT_DEC_CB_DEF(dmp_security_class, sec_class, dmp_security_class_t)
989 UAT_CSTRING_CB_DEF(dmp_security_class, name, dmp_security_class_t)
992 dmp_class_copy_cb(void *dest, const void *orig, size_t len _U_)
994 dmp_security_class_t *u = (dmp_security_class_t *)dest;
995 const dmp_security_class_t *o = (const dmp_security_class_t *)orig;
997 u->nation = o->nation;
998 u->sec_class = o->sec_class;
999 u->name = g_strdup(o->name);
1005 dmp_class_free_cb(void *r)
1007 dmp_security_class_t *u = (dmp_security_class_t *)r;
1012 static gchar *dmp_national_sec_class (guint nation, guint dmp_sec_class)
1016 for (i = 0; i < num_dmp_security_classes; i++) {
1017 dmp_security_class_t *u = &(dmp_security_classes[i]);
1019 if (u->nation == nation && u->sec_class == dmp_sec_class) {
1027 static void build_national_strings (void)
1032 ** We use values from dmp_national_values to build value_string for nat_pol_id.
1034 while (dmp_national_values[i].name && i < MAX_NATIONAL_VALUES) {
1035 nat_pol_id[i].value = dmp_national_values[i].value;
1036 nat_pol_id[i].strptr = dmp_national_values[i].description;
1039 nat_pol_id[i].value = 0;
1040 nat_pol_id[i].strptr = NULL;
1043 static const gchar *get_nat_pol_id_short (gint nation)
1046 while (dmp_national_values[i].name) {
1047 if (dmp_national_values[i].value == nation) {
1048 return dmp_national_values[i].name;
1056 static const gchar *msg_type_to_str (void)
1058 const gchar *msg_type;
1059 gboolean have_msg = FALSE;
1061 switch (dmp.msg_type) {
1064 /* Include message type and precedence */
1065 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s (%s) [%s]",
1066 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1067 val_to_str_const (dmp.st_type, message_type_vals, "Unknown"),
1068 (dmp.prec == 0x6 || dmp.prec == 0x7) ?
1069 val_to_str_const (dmp.prec-4, precedence, "Unknown") :
1070 val_to_str_const (dmp.prec, precedence, "Unknown"));
1074 /* Include importance */
1075 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s [%s]",
1076 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1077 val_to_str_const (dmp.prec, importance, "Unknown"));
1081 /* Include report types included */
1082 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Report (%s%s%s)",
1083 dmp.dr ? "DR" : "", (dmp.dr && dmp.ndr) ? " and " : "",
1084 dmp.ndr ? "NDR" : "");
1088 msg_type = val_to_str_const (dmp.notif_type, notif_type, "Unknown");
1092 /* If we have msg_time we have a matching packet */
1093 have_msg = (dmp.id_val &&
1094 (dmp.id_val->msg_time.secs>0 || dmp.id_val->msg_time.nsecs>0));
1095 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Acknowledgement%s%s",
1096 have_msg ? val_to_str (dmp.id_val->msg_type, ack_msg_type,
1097 " (unknown:%d)") : "",
1098 dmp.ack_reason ? " [negative]" : "");
1102 msg_type = "Unknown";
1109 static const gchar *non_del_reason_str (guint32 value)
1112 /* Standard values according to P1 */
1113 return val_to_str_const (value, p1_NonDeliveryReasonCode_vals, "Unknown");
1115 return val_to_str_const (value, non_del_reason, "Unknown");
1119 static const gchar *non_del_diagn_str (guint32 value)
1122 /* Standard values according to P1 */
1123 return val_to_str_const (value, p1_NonDeliveryDiagnosticCode_vals, "Unknown");
1125 return val_to_str_const (value, non_del_diagn, "Unknown");
1129 static const gchar *nrn_reason_str (guint32 value)
1131 /* Standard values according to P22 */
1132 return val_to_str_const (value, p22_NonReceiptReasonField_vals, "Reserved");
1135 static const gchar *discard_reason_str (guint32 value)
1138 /* Standard values according to P22 */
1139 return val_to_str_const (value, p22_DiscardReasonField_vals, "Reserved");
1141 return val_to_str_const (value, discard_reason, "Unknown");
1145 /* Ref chapter 6.2.8.10 TimeDifference */
1146 static gint32 dmp_dec_time_diff (guint8 dmp_time_diff)
1148 gint32 time_diff = 0;
1150 if (dmp_time_diff <= 0x01) {
1151 /* Reserved - low value */
1152 time_diff = DMP_TIME_RESERVED;
1153 } else if (dmp_time_diff <= 0x1D) {
1154 /* Number of 2-second units (2-58 seconds) */
1155 time_diff = dmp_time_diff * 2;
1156 } else if (dmp_time_diff <= 0x91) {
1157 /* Number of 15-second units (1 min - 29 min 45 sec) */
1158 time_diff = (dmp_time_diff - 0x1D + 3) * 15;
1159 } else if (dmp_time_diff <= 0xDF) {
1160 /* Number of 5-minute units (30 min - 6 hours 55 min) */
1161 time_diff = (dmp_time_diff - 0x91 + 5) * 5*60;
1162 } else if (dmp_time_diff <= 0xF7) {
1163 /* Number of 30-minute units (7 hours - 18 hours 30 min) */
1164 time_diff = (dmp_time_diff - 0xDF + 7) * 30*60;
1166 /* Reserved - high value */
1167 time_diff = DMP_TIME_RESERVED;
1174 * Ref chapter 6.3.7.2.10 ExpiryTime
1175 * and chapter 6.3.9.2.2 DeliveryTime
1177 static gint32 dmp_dec_exp_del_time (guint8 timev, gboolean expiry_time)
1179 gint32 time_value = 0;
1181 if (expiry_time && (timev == 0x00)) {
1182 /* No expiry time */
1183 time_value = DMP_TIME_NOT_PRESENT;
1184 } else if (timev <= 0x1D) {
1185 /* Number of 2-second units (2-58 seconds) */
1186 time_value = timev * 2;
1187 } else if (timev <= 0x91) {
1188 /* Number of 15-second units (1 min - 29 min 45 sec) */
1189 time_value = (timev - 0x1D + 3) * 15;
1190 } else if (timev <= 0xBB) {
1191 /* Number of 5-minute units (30 min - 3 hours 55 min) */
1192 time_value = (timev - 0x91 + 5) * 5*60;
1193 } else if (timev <= 0xE3) {
1194 /* Number of 30-minute units (4 hours - 23 hours 30 min) */
1195 time_value = (timev - 0xBB + 7) * 30*60;
1196 } else if (timev < 0xFF) {
1197 /* Number of 2-hour units (24 - 78 hours) */
1198 time_value = (timev - 0xE3 + 11) * 2*3600;
1201 time_value = DMP_TIME_RESERVED;
1207 static gint32 dmp_dec_exp_time (guint8 expiry_time)
1209 return dmp_dec_exp_del_time (expiry_time, TRUE);
1212 static gint32 dmp_dec_del_time (guint8 delivery_time)
1214 return dmp_dec_exp_del_time (delivery_time, FALSE);
1217 /* Ref chapter 6.3.7.2.11 DTG */
1218 static gint32 dmp_dec_dtg (guint32 dtg)
1224 value = DMP_TIME_NOT_PRESENT;
1225 } else if (dtg <= 0x3C) {
1226 /* Number of minutes (0-59 min) */
1227 value = (dtg - 1) * 60;
1228 } else if (dtg <= 0x64) {
1229 /* Number of 15-minute units (1 hour - 10 hours 45 min) */
1230 value = (dtg - 0x3C + 3) * 15 * 60;
1231 } else if (dtg < 0x7F) {
1232 /* Number of hours (11-36 hours) */
1233 value = (dtg - 0x64 + 10) * 3600;
1236 value = DMP_TIME_RESERVED;
1243 * Ref chapter 7.10.11.1 Submission time
1245 * start_time (current time)
1246 * delta1 = E (encoded submission time)
1247 * delta2 = C (encoded current time)
1248 * 0x01C2 = Pn + 15min (maximum point for S1)
1249 * 0x7E38 = Pn+1 - 15min (minimum point for S3)
1250 * 0x7FF8 = Pn+1 (length of P (period))
1252 static gint32 dmp_dec_subm_time (guint16 delta1, gint32 start_time)
1254 gint32 subm_time = start_time;
1257 delta2 = (guint16) ((subm_time / 2) % 0x7FF8);
1259 if ((delta1 < 0x01C2) && (delta2 >= delta1 + 0x7E38)) {
1260 subm_time += 2 * (0x7FF8 - delta2 + delta1);
1261 } else if ((delta1 >= 0x01C2) && (delta2 < delta1 - 0x01C2)) {
1262 subm_time -= 2 * (0x7FF8 - delta1 + delta2);
1264 subm_time -= 2 * (delta2 - delta1);
1270 /* Ref chapter 6.3.7.2.12 SIC */
1271 static gboolean dmp_dec_xbyte_sic (guint64 bin, gchar *sic,
1272 guint8 no_char, gboolean any)
1274 gboolean failure = FALSE;
1279 if (no_char >= MAX_SIC_LEN) {
1280 /* Illegal length */
1281 g_snprintf (sic, MAX_SIC_LEN, "Illegal length: %d", no_char);
1291 for (i = 0; i < no_char; i++) {
1292 p = (guint64) pow (multiplier, no_char - 1 - i);
1295 sic[i] = (gchar) tmp;
1298 } else if (sic[i] <= 35) {
1299 sic[i] += ('A' - 10);
1303 } else if (sic[i] <= 61) {
1304 sic[i] += ('a' - 36);
1305 } else if (sic[i] == 62) {
1307 } else if (sic[i] == 63) {
1309 } else if (sic[i] == 64) {
1311 } else if (sic[i] == 65) {
1313 } else if (sic[i] == 66) {
1315 } else if (sic[i] == 67) {
1317 } else if (sic[i] == 68) {
1319 } else if (sic[i] == 69) {
1321 } else if (sic[i] == 70) {
1323 } else if (sic[i] == 71) {
1325 } else if (sic[i] == 72) {
1327 } else if (sic[i] == 73) {
1339 static guint dmp_id_hash (gconstpointer k)
1341 const dmp_id_key *dmpx=(const dmp_id_key *)k;
1345 static gint dmp_id_hash_equal (gconstpointer k1, gconstpointer k2)
1347 const dmp_id_key *dmp1=(const dmp_id_key *)k1;
1348 const dmp_id_key *dmp2=(const dmp_id_key *)k2;
1349 if (dmp1->id != dmp2->id)
1352 return (addresses_equal (&dmp1->src, &dmp2->src) &&
1353 addresses_equal (&dmp1->dst, &dmp2->dst));
1356 static void register_dmp_id (packet_info *pinfo, guint8 reason)
1358 dmp_id_val *dmp_data = NULL, *pkg_data = NULL;
1359 dmp_id_key *dmp_key = NULL;
1363 if (pinfo->flags.in_error_pkt) {
1364 /* No analysis of error packets */
1368 nstime_set_zero(&msg_time);
1370 dmp_key = wmem_new (wmem_file_scope(), dmp_id_key);
1372 if (!pinfo->fd->flags.visited &&
1373 (dmp.msg_type == REPORT || dmp.msg_type == NOTIF))
1375 /* Try to match corresponding message */
1376 dmp_key->id = (guint) dmp.subj_id;
1377 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->dst));
1378 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->src));
1380 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1384 if (dmp_data->prev_msg_id > 0) {
1385 msg_id = dmp_data->prev_msg_id;
1387 msg_id = dmp_data->msg_id;
1389 msg_time = dmp_data->msg_time;
1393 if (dmp.msg_type == ACK) {
1394 dmp_key->id = (guint) dmp.subj_id;
1395 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->dst));
1396 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->src));
1398 dmp_key->id = (guint) dmp.msg_id;
1399 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->src));
1400 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->dst));
1403 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1405 if (!pinfo->fd->flags.visited) {
1407 if (dmp.msg_type == ACK) {
1408 /* Only save this data if positive ack */
1410 if (dmp_data->ack_id == 0) {
1411 /* Only save reference to first ACK */
1412 dmp_data->ack_id = pinfo->num;
1414 /* Only count when resending */
1415 dmp_data->ack_resend_count++;
1419 /* Message resent */
1420 dmp_data->msg_resend_count++;
1421 dmp_data->prev_msg_id = pinfo->num;
1422 dmp_data->prev_msg_time = dmp_data->msg_time;
1423 dmp_data->msg_time = pinfo->abs_ts;
1427 dmp_data = wmem_new0 (wmem_file_scope(), dmp_id_val);
1428 dmp_data->msg_type = dmp.msg_type;
1430 if (dmp.msg_type == ACK) {
1431 /* No matching message for this ack */
1432 dmp_data->ack_id = pinfo->num;
1434 dmp_data->first_msg_time = pinfo->abs_ts;
1435 dmp_data->msg_time = pinfo->abs_ts;
1437 if (dmp.msg_type == REPORT) {
1438 dmp_data->rep_id = pinfo->num;
1439 dmp_data->msg_id = msg_id;
1440 dmp_data->rep_not_msg_time = msg_time;
1441 } else if (dmp.msg_type == NOTIF) {
1442 dmp_data->not_id = pinfo->num;
1443 dmp_data->msg_id = msg_id;
1444 dmp_data->rep_not_msg_time = msg_time;
1446 dmp_data->msg_id = pinfo->num;
1449 g_hash_table_insert (dmp_id_hash_table, dmp_key, dmp_data);
1453 pkg_data = wmem_new (wmem_file_scope(), dmp_id_val);
1454 *pkg_data = *dmp_data;
1455 p_add_proto_data(wmem_file_scope(), pinfo, proto_dmp, 0, pkg_data);
1457 /* Fetch last values from data saved in packet */
1458 pkg_data = (dmp_id_val *)p_get_proto_data(wmem_file_scope(), pinfo, proto_dmp, 0);
1460 if (dmp_data && pkg_data && dmp.msg_type != ACK && pkg_data->ack_id == 0) {
1461 pkg_data->ack_id = dmp_data->ack_id;
1465 DISSECTOR_ASSERT (pkg_data);
1466 dmp.id_val = pkg_data;
1469 static void dmp_add_seq_ack_analysis (tvbuff_t *tvb, packet_info *pinfo,
1470 proto_tree *dmp_tree, gint offset)
1472 proto_tree *analysis_tree = NULL;
1473 proto_item *en = NULL, *eh = NULL;
1476 if (dmp.msg_type > ACK || (dmp.msg_type < ACK && !dmp.checksum) ||
1477 dmp.id_val == NULL || pinfo->flags.in_error_pkt)
1479 /* No need for seq/ack analysis */
1483 analysis_tree = proto_tree_add_subtree(dmp_tree, tvb, 0, 0, ett_analysis, &en, "SEQ/ACK analysis");
1484 PROTO_ITEM_SET_GENERATED (en);
1486 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
1487 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) {
1488 if (dmp.id_val->ack_id) {
1489 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb,
1490 0, 0, dmp.id_val->ack_id);
1491 PROTO_ITEM_SET_GENERATED (en);
1492 if (!dmp.checksum) {
1493 proto_item_append_text (en, " (unexpected)");
1494 expert_add_info(pinfo, en, &ei_analysis_ack_unexpected);
1496 } else if (dmp.checksum && !dmp.id_val->msg_resend_count) {
1497 en = proto_tree_add_item (analysis_tree, hf_analysis_ack_missing, tvb, offset, 0, ENC_NA);
1498 if (pinfo->fd->flags.visited) {
1499 /* We do not know this on first visit and we do not want to
1500 add a entry in the "Expert Severity Info" for this note */
1501 expert_add_info(pinfo, en, &ei_analysis_ack_missing);
1502 PROTO_ITEM_SET_GENERATED (en);
1506 if (dmp.msg_type == REPORT) {
1507 if (dmp.id_val->msg_id) {
1508 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1509 tvb, 0, 0, dmp.id_val->msg_id);
1510 PROTO_ITEM_SET_GENERATED (en);
1512 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->rep_not_msg_time);
1513 en = proto_tree_add_time (analysis_tree, hf_analysis_rep_time,
1515 PROTO_ITEM_SET_GENERATED (en);
1517 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1519 } else if (dmp.msg_type == NOTIF) {
1520 if (dmp.id_val->msg_id) {
1521 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1522 tvb, 0, 0, dmp.id_val->msg_id);
1523 PROTO_ITEM_SET_GENERATED (en);
1525 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->rep_not_msg_time);
1526 en = proto_tree_add_time (analysis_tree, hf_analysis_not_time,
1528 PROTO_ITEM_SET_GENERATED (en);
1530 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1534 if (dmp.id_val->msg_resend_count) {
1535 en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no,
1536 tvb, 0, 0, dmp.id_val->msg_resend_count);
1537 PROTO_ITEM_SET_GENERATED (en);
1539 expert_add_info_format(pinfo, en, &ei_analysis_retrans_no, "Retransmission #%d", dmp.id_val->msg_resend_count);
1541 if (dmp.msg_type == REPORT) {
1542 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_resend_from,
1543 tvb, 0, 0, dmp.id_val->rep_id);
1544 } else if (dmp.msg_type == NOTIF) {
1545 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_resend_from,
1546 tvb, 0, 0, dmp.id_val->not_id);
1548 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_resend_from,
1549 tvb, 0, 0, dmp.id_val->msg_id);
1551 PROTO_ITEM_SET_GENERATED (en);
1553 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->prev_msg_time);
1554 en = proto_tree_add_time (analysis_tree, hf_analysis_retrans_time,
1556 PROTO_ITEM_SET_GENERATED (en);
1558 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->first_msg_time);
1559 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_retrans_time,
1561 PROTO_ITEM_SET_GENERATED (eh);
1563 if (dmp.id_val->first_msg_time.secs == dmp.id_val->prev_msg_time.secs &&
1564 dmp.id_val->first_msg_time.nsecs == dmp.id_val->prev_msg_time.nsecs) {
1565 /* Time values does not differ, hide the total time */
1566 PROTO_ITEM_SET_HIDDEN (eh);
1569 } else if (dmp.msg_type == ACK) {
1570 if (dmp.id_val->msg_type != ACK) {
1571 if (dmp.id_val->msg_type == REPORT) {
1572 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_rep_num,
1573 tvb, 0, 0, dmp.id_val->rep_id);
1574 } else if (dmp.id_val->msg_type == NOTIF) {
1575 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_not_num,
1576 tvb, 0, 0, dmp.id_val->not_id);
1578 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_msg_num,
1579 tvb, 0, 0, dmp.id_val->msg_id);
1581 PROTO_ITEM_SET_GENERATED (en);
1583 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->msg_time);
1584 en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time,
1586 PROTO_ITEM_SET_GENERATED (en);
1588 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->first_msg_time);
1589 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time,
1591 PROTO_ITEM_SET_GENERATED (eh);
1593 if (dmp.id_val->first_msg_time.secs == dmp.id_val->msg_time.secs &&
1594 dmp.id_val->first_msg_time.nsecs == dmp.id_val->msg_time.nsecs) {
1595 /* Time values does not differ, hide the total time */
1596 PROTO_ITEM_SET_HIDDEN (eh);
1598 /* Different times, add a reference to the message we have ack'ed */
1599 proto_item_append_text (en, " (from frame %d)",
1600 dmp.id_val->prev_msg_id);
1603 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1606 if (dmp.id_val->ack_resend_count) {
1607 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no,
1608 tvb, 0, 0, dmp.id_val->ack_resend_count);
1609 PROTO_ITEM_SET_GENERATED (en);
1611 expert_add_info_format(pinfo, en, &ei_analysis_ack_dup_no, "Dup ACK #%d", dmp.id_val->ack_resend_count);
1613 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from,
1614 tvb, 0, 0, dmp.id_val->ack_id);
1615 PROTO_ITEM_SET_GENERATED (en);
1620 static gchar *dissect_7bit_string (tvbuff_t *tvb, gint offset, gint length, guchar *byte_rest)
1622 guchar *encoded = (guchar *)tvb_memdup (wmem_packet_scope(), tvb, offset, length);
1623 guchar *decoded = (guchar *)wmem_alloc0 (wmem_packet_scope(), (size_t)(length * 1.2) + 1);
1624 guchar rest = 0, bits = 1;
1627 for (i = 0; i < length; i++) {
1628 decoded[len++] = encoded[i] >> bits | rest;
1629 rest = (encoded[i] << (7 - bits) & 0x7F);
1631 decoded[len++] = rest;
1643 return (gchar *) decoded;
1646 static const gchar *dissect_thales_mts_id (tvbuff_t *tvb, gint offset, gint length, guchar *byte_rest)
1648 /* Thales XOmail uses this format: "MTA-NAME/000000000000" */
1649 if (length >= 7 && length <= 22) {
1650 return wmem_strdup_printf (wmem_packet_scope(), "%s/%08X%04X",
1651 dissect_7bit_string (tvb, offset, length - 6, byte_rest),
1652 tvb_get_ntohl (tvb, offset + length - 6),
1653 tvb_get_ntohs (tvb, offset + length - 2));
1656 return ILLEGAL_FORMAT;
1659 static const gchar *dissect_thales_ipm_id (tvbuff_t *tvb, gint offset, gint length, gint modifier, guchar *byte_rest)
1661 /* Thales XOmail uses this format: "<prefix>0000 YYMMDDhhmmssZ" */
1662 if (length >= 6 && length <= 20 && modifier >= 0 && modifier <= 2) {
1663 guint number = tvb_get_ntohs (tvb, offset + length - 6);
1664 guint8 number_len = modifier + 2;
1665 time_t timev = tvb_get_ntohl(tvb, offset + length - 4);
1666 struct tm *tmp = gmtime(&timev);
1669 return TIME_NOT_REPRESENTABLE;
1671 if (modifier == 1 && number >= 1024) {
1672 /* The number is in the range 65536-99999 */
1674 number += (65536 - 1024);
1677 return wmem_strdup_printf (wmem_packet_scope(), "%s%0*d %02d%02d%02d%02d%02d%02dZ",
1678 (length == 6) ? "" : dissect_7bit_string (tvb, offset, length - 6, byte_rest),
1680 tmp->tm_year % 100, tmp->tm_mon + 1, tmp->tm_mday,
1681 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1684 return ILLEGAL_FORMAT;
1687 /* Ref chapter 6.3.7.2.12 SIC */
1688 static gint dissect_dmp_sic (tvbuff_t *tvb, packet_info *pinfo,
1689 proto_tree *message_tree, gint offset)
1691 proto_tree *sic_tree = NULL, *bitmap_tree = NULL, *key_tree = NULL;
1692 proto_item *sf = NULL, *bf = NULL, *kf = NULL;
1694 guint8 key, bitmap, no, i, length = 0;
1695 gboolean any, no_sic = FALSE, failure = FALSE;
1696 gint bytes = 0, boffset = offset;
1699 key = tvb_get_guint8 (tvb, offset);
1700 sic = (gchar *)wmem_alloc (wmem_packet_scope(), MAX_SIC_LEN);
1703 /* 2 bytes, single 3-character SIC, characters [A-Z0-9] only */
1705 value = tvb_get_ntohs (tvb, offset);
1706 failure = dmp_dec_xbyte_sic (value, sic, 3, FALSE);
1707 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1709 "%s [A-Z0-9 only]%s", sic,
1710 failure ? " (invalid)": "");
1712 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1716 } else if (key <= 0xBD) {
1717 /* 3 bytes, single 3-character SIC, any valid character */
1719 value = tvb_get_ntohl (tvb, offset);
1720 value = (value >> 8) & 0x48FFFF;
1721 failure = dmp_dec_xbyte_sic (value, sic, 3, TRUE);
1722 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1724 "%s [any character]%s", sic,
1725 failure ? " (invalid)": "");
1727 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1731 } else if (key <= 0xBF) {
1732 /* Reserved (not used) */
1733 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1736 } else if (key <= 0xCF) {
1737 /* 2 or more 3-character SICs */
1739 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1740 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1742 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1743 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1745 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1746 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1747 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1751 no = (key & 0x07) + 1;
1752 for (i = 0; i < no; i++) {
1754 value = tvb_get_ntohl (tvb, offset);
1755 value = (value >> 8) & 0x48FFFF;
1758 value = tvb_get_ntohs (tvb, offset);
1761 failure = dmp_dec_xbyte_sic (value, sic, 3, any);
1762 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1764 "SIC %d: %s%s", i + 1, sic,
1765 failure ? " (invalid)": "");
1767 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1771 proto_item_append_text (sf, ": %d (3 %s character)", no,
1772 any ? "any" : "[A-Z0-9]");
1774 } else if (key <= 0xDF) {
1775 /* 1 or more 3 to 8 character SICs */
1777 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1778 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1780 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1781 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1783 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1784 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1785 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1788 bitmap = tvb_get_guint8 (tvb, offset);
1789 bf = proto_tree_add_uint_format (sic_tree, hf_message_sic_bitmap, tvb,
1791 "Length Bitmap: 0x%2.2x", bitmap);
1792 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bitmap);
1793 proto_tree_add_item (bitmap_tree, hf_message_sic_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
1796 no = (key & 0x07) + 1;
1799 for (i = 0; i < no; i++) {
1800 if (bitmap & (1 << (7 - i))) {
1801 /* 4 - 8 character */
1802 key = tvb_get_guint8 (tvb, offset);
1804 /* Any valid characters */
1805 if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1808 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1809 } else if ((key & 0xC0) == 0xC0) { /* bit 7-4: 11xx */
1812 value = ((guint64)key & 0x3F)<<32|tvb_get_ntohl (tvb, offset + 1);
1813 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1816 value = ((guint64)(tvb_get_ntohs (tvb, offset) & 0x0FFF)) << 32 |
1817 tvb_get_ntohl (tvb, offset + 2);
1818 } else if ((key & 0xF0) == 0x90) { /* bit 7-4: 1001 */
1821 value = ((guint64)((tvb_get_ntohl (tvb, offset)>>8) & 0x0FFF))<<32 |
1822 tvb_get_ntohl (tvb, offset + 3);
1823 } else { /* bit 7-4: 0xxx or 1000 */
1826 value = tvb_get_ntohl (tvb, offset);
1829 /* Characterts [A-Z0-9] only */
1830 if ((key & 0xE0) == 0xC0) { /* bit 7-4: 110x */
1833 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x1FFFFF;
1834 } else if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1837 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1838 } else if ((key & 0xE0) == 0xE0) { /* bit 7-4: 111x */
1841 value = ((guint64)key & 0x1F)<<32 | tvb_get_ntohl (tvb, offset +1);
1842 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1845 value = ((guint64)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
1846 tvb_get_ntohl (tvb, offset + 2);
1847 } else { /* bit 7-4: 0xxx or 1000 */
1850 value = tvb_get_ntohl (tvb, offset);
1856 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x48FFFF;
1860 value = tvb_get_ntohs (tvb, offset);
1865 failure = dmp_dec_xbyte_sic (value, sic, length, any);
1866 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1868 "SIC %d: %s (%d bytes: %" G_GINT64_MODIFIER "x)%s",
1869 i + 1, sic, bytes, value,
1870 failure ? " (invalid)": "");
1871 if (bitmap & (1 << (7 - i))) {
1872 /* Only if 4 - 8 character */
1873 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bits);
1875 proto_tree_add_item (bitmap_tree, hf_message_sic_bits_any, tvb, offset, 1, ENC_BIG_ENDIAN);
1877 proto_tree_add_item (bitmap_tree, hf_message_sic_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
1881 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1885 proto_item_append_text (sf, ": %d (3-to-8 %s character)", no,
1886 any ? "any" : "[A-Z0-9]");
1888 } else if (key == 0xFE) {
1890 g_snprintf (sic, MAX_SIC_LEN, "Not present");
1894 /* Resered (not used) */
1895 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1900 /* Not added any SIC, dump text value */
1901 sf = proto_tree_add_string (message_tree, hf_message_sic, tvb, offset, 1, sic);
1905 proto_item_set_len (sf, offset - boffset);
1910 /* Ref chapter 5.2.7.1 Direct Originator Encoding */
1911 static gint dissect_dmp_direct_addr (tvbuff_t *tvb, packet_info *pinfo,
1912 proto_tree *field_tree, proto_item *tf,
1913 gint offset, gint rec_no,
1914 gint rec_ofs, gint addr_type)
1916 proto_tree *addr_tree = NULL;
1917 proto_item *en = NULL;
1921 value = tvb_get_guint8 (tvb, offset);
1922 dir_addr = (value & 0x7F);
1924 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1, tvb,
1926 "%sDirect Address (bits 6-0): %d",
1927 val_to_str_const (addr_type, addr_type_str, ""),
1929 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1930 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1931 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1935 value = tvb_get_guint8 (tvb, offset);
1936 dir_addr |= ((value & 0x3F) << 7);
1937 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
1939 "%sDirect Address (bits 12-7): %d",
1940 val_to_str_const (addr_type, addr_type_str, ""),
1942 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1943 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1944 en = proto_tree_add_item (addr_tree, hf_reserved_0x40, tvb, offset, 1, ENC_BIG_ENDIAN);
1946 expert_add_info(pinfo, en, &ei_reserved_value);
1948 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
1953 value = tvb_get_guint8 (tvb, offset);
1954 dir_addr |= ((value & 0x3F) << 13);
1955 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
1957 "%sDirect Address (bits 18-13): %d",
1958 val_to_str_const (addr_type,addr_type_str,""),
1960 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1961 en = proto_tree_add_item (addr_tree, hf_reserved_0xC0, tvb, offset, 1, ENC_BIG_ENDIAN);
1963 expert_add_info(pinfo, en, &ei_reserved_value);
1965 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
1969 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
1970 tvb, offset, 0, dir_addr,
1971 "%sDirect Address: %d",
1972 val_to_str_const (addr_type, addr_type_str, ""),
1974 PROTO_ITEM_SET_GENERATED (en);
1976 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address, tvb,
1978 "%sDirect Address: %d",
1979 val_to_str_const (addr_type, addr_type_str, ""),
1981 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1982 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1983 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1988 proto_item_append_text (tf, " %d", rec_no);
1989 if (rec_ofs != -1) {
1990 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
1993 proto_item_append_text (tf, ", %sDirect Address: %d",
1994 val_to_str_const (addr_type, addr_type_str, ""), dir_addr);
1999 /* Ref 5.3.14 Extended Address */
2000 static gint dissect_dmp_ext_addr (tvbuff_t *tvb, packet_info *pinfo,
2001 proto_tree *field_tree, proto_item *tf,
2002 gint offset, gint rec_no, gint rec_ofs,
2005 proto_tree *addr_tree = NULL, *ext_tree = NULL;
2006 proto_item *en = NULL, *ef = NULL;
2009 gint boffset = offset;
2010 gboolean addr_length_extended = FALSE;
2011 asn1_ctx_t asn1_ctx;
2013 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2015 value = tvb_get_guint8 (tvb, offset);
2016 type = (value & 0xE0) >> 5;
2017 length = (value & 0x1F);
2018 ef = proto_tree_add_none_format (field_tree, hf_addr_ext_address, tvb,
2019 offset, -1, "%sExtended Address",
2020 val_to_str_const (addr_type, addr_type_str, ""));
2021 ext_tree = proto_item_add_subtree (ef, ett_address_extended);
2023 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type, tvb,
2024 offset, 1, value, "Address Type: %s",
2025 val_to_str_const (type, ext_addr_type,
2027 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2028 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2031 addr_length_extended = TRUE;
2032 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length1, tvb,
2034 "Address Length (bits 4-0): %d", length);
2035 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2036 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2040 value = tvb_get_guint8 (tvb, offset);
2041 type = ((value & 0xE0) >> 5);
2042 length |= ((value & 0x1F) << 5);
2044 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type_ext, tvb,
2045 offset, 1, value, "Address Type Ext: %s",
2046 val_to_str_const (type, ext_addr_type_ext,
2048 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2049 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2051 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length2, tvb,
2053 "Address Length (bits 9-5): %d",
2055 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2056 proto_tree_add_item (addr_tree, hf_addr_ext_length2, tvb, offset, 1, ENC_BIG_ENDIAN);
2059 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length, tvb,
2060 offset, 1, value, "Address Length: %d",
2062 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2063 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2067 if (type == ASN1_BER) {
2068 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, length);
2070 dissect_p1_ORName (FALSE, next_tvb, 0, &asn1_ctx, ext_tree,
2071 hf_addr_ext_asn1_ber);
2072 } else if (type == ASN1_PER) {
2073 proto_tree_add_item (ext_tree, hf_addr_ext_asn1_per, tvb, offset, length, ENC_NA);
2075 proto_tree_add_item (ext_tree, hf_addr_ext_unknown, tvb, offset, length, ENC_NA);
2079 if (addr_length_extended) {
2080 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length_generated,
2081 tvb, offset, 0, length,
2082 "Address Length: %d", length);
2083 PROTO_ITEM_SET_GENERATED (en);
2086 proto_item_append_text (ef, ", Type: %s, Length: %d",
2087 val_to_str_const (type, ext_addr_type, "Reserved"),
2091 proto_item_append_text (tf, " %d", rec_no);
2092 if (rec_ofs != -1) {
2093 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2096 proto_item_append_text (tf, ", %sExtended Address Type: %s",
2097 val_to_str_const (addr_type, addr_type_str, ""),
2098 val_to_str_const (type, ext_addr_type_short, "Reserved"));
2100 proto_item_set_len (ef, offset - boffset);
2105 /* Ref chapter 5.2.8.1 Extended Originator Encoding */
2106 static gint dissect_dmp_originator (tvbuff_t *tvb, packet_info *pinfo,
2107 proto_tree *envelope_tree, gint offset)
2109 proto_tree *field_tree = NULL, *rec_tree = NULL;
2110 proto_item *en = NULL, *tf = NULL;
2111 guint8 value, dmp_addr_form;
2112 gint boffset = offset;
2113 gboolean p2_addr = FALSE;
2115 tf = proto_tree_add_item (envelope_tree, hf_addr_originator, tvb, offset, -1, ENC_NA);
2116 field_tree = proto_item_add_subtree (tf, ett_address);
2118 if (dmp.addr_enc == DIRECT_ADDR) {
2119 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf,
2120 offset, -1, -1, ORIGINATOR);
2122 value = tvb_get_guint8 (tvb, offset);
2123 dmp_addr_form = (value & 0xE0) >> 5;
2125 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2126 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig_v1, tvb,
2129 val_to_str_const (dmp_addr_form,
2130 addr_form_orig_v1, "Reserved"));
2131 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2132 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig_v1, tvb, offset, 1, ENC_BIG_ENDIAN);
2134 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig, tvb,
2137 val_to_str_const (dmp_addr_form,
2138 addr_form_orig, "Reserved"));
2139 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2140 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig, tvb, offset, 1, ENC_BIG_ENDIAN);
2143 en = proto_tree_add_item (rec_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
2145 expert_add_info(pinfo, en, &ei_reserved_value);
2149 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2150 switch (dmp_addr_form) {
2153 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2159 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2164 proto_item_append_text (tf, " (invalid address form)");
2169 switch (dmp_addr_form) {
2173 case P1_DIRECT_P2_EXTENDED:
2174 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2180 case P1_EXTENDED_P2_DIRECT:
2181 case P1_P2_EXTENDED:
2182 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2187 proto_item_append_text (tf, " (invalid address form)");
2192 switch (dmp_addr_form) {
2195 case P1_EXTENDED_P2_DIRECT:
2196 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2202 case P1_DIRECT_P2_EXTENDED:
2203 case P1_P2_EXTENDED:
2204 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2205 -1, ORIG_P2_ADDRESS);
2213 if (dmp.msg_type == NOTIF) {
2214 en = proto_tree_add_boolean (field_tree, hf_addr_int_rec, tvb,
2217 en = proto_tree_add_boolean (field_tree, hf_addr_dl_expanded, tvb,
2220 PROTO_ITEM_SET_GENERATED (en);
2223 proto_item_set_len (tf, offset - boffset);
2228 static void dmp_add_recipient_info (proto_item *tf, guint8 rep_req,
2229 guint8 not_req, gboolean action)
2231 if (rep_req || not_req) {
2232 proto_item_append_text (tf, ", Request:");
2235 proto_item_append_text (tf, "%s",
2236 val_to_str_const (rep_req, report_vals_short, ""));
2239 dmp.notif_req = TRUE;
2240 proto_item_append_text (tf, "%s",
2241 val_to_str_const (not_req, notif_vals_short, ""));
2244 if (dmp.msg_type == STANAG) {
2245 proto_item_append_text (tf, " (Action)");
2246 } else if (dmp.msg_type == IPM) {
2247 proto_item_append_text (tf, " (To)");
2250 if (dmp.msg_type == STANAG) {
2251 proto_item_append_text (tf, " (Info)");
2252 } else if (dmp.msg_type == IPM) {
2253 proto_item_append_text (tf, " (Cc)");
2258 /* Ref chapter 5.2.7 Direct Recipient Encoding */
2259 static gint dissect_dmp_direct_encoding (tvbuff_t *tvb, packet_info *pinfo,
2260 proto_tree *field_tree, proto_item *tf,
2261 gint offset, guint *prev_rec_no)
2264 proto_tree *addr_tree = NULL, *rec_tree = NULL;
2265 proto_item *en = NULL;
2266 guint8 rep_req = 0, not_req = 0, value;
2267 gint rec_no, rec_ofs = -1, dir_addr;
2268 gboolean action = FALSE, dir_addr_extended = FALSE;
2270 value = tvb_get_guint8 (tvb, offset);
2271 rec_no = (value & 0xF0) >> 4;
2272 rep_req = (value & 0x0C) >> 2;
2273 not_req = (value & 0x03);
2275 if (rep_req == 0x03) {
2276 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no1,
2277 tvb, offset, 1, value,
2278 "Recipient Number (bits 3-0): %d"
2279 " (offset from previous)",
2280 (value & 0xF0) >> 4);
2282 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no,
2283 tvb, offset, 1, value,
2284 "Recipient Number Offset: %d"
2285 " (offset from previous)",
2286 (value & 0xF0) >> 4);
2288 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2289 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2290 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2291 proto_tree_add_item (rec_tree, hf_addr_dir_not_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2294 value = tvb_get_guint8 (tvb, offset);
2295 dir_addr = (value & 0x7F);
2296 action = (value & 0x80);
2297 if (not_req == 0x03) {
2298 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1,
2299 tvb, offset, 1, value,
2300 "Direct Address (bits 6-0): %d",
2303 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address,
2304 tvb, offset, 1, value,
2305 "Direct Address: %d",
2308 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2309 proto_tree_add_item (addr_tree, hf_addr_dir_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2310 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2313 if (rep_req == 0x03) {
2314 /* Extended Recipient Number 1 */
2315 value = tvb_get_guint8 (tvb, offset);
2316 rec_no |= ((value & 0x3F) << 4);
2318 rep_req = (value & 0xC0) >> 6;
2320 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no2,
2321 tvb, offset, 1, value,
2322 "Recipient Number (bits 9-4): %d"
2323 " (offset from previous)",
2325 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2326 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2327 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2330 if (rep_req == 0x03) {
2331 /* Extended Recipient Number 2 */
2332 value = tvb_get_guint8 (tvb, offset);
2333 rec_no |= ((value & 0x1F) << 10);
2335 rep_req = (value & 0xC0) >> 6;
2337 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no3,
2338 tvb, offset, 1, value,
2339 "Recipient Number (bits 14-10): %d"
2340 " (offset from previous)",
2342 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2343 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2344 en = proto_tree_add_item (rec_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
2346 expert_add_info(pinfo, en, &ei_reserved_value);
2348 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no3, tvb, offset, 1, ENC_BIG_ENDIAN);
2353 if (not_req == 0x03) {
2354 /* Extended Direct Address 1 */
2355 dir_addr_extended = TRUE;
2356 value = tvb_get_guint8 (tvb, offset);
2357 dir_addr |= ((value & 0x3F) << 7);
2358 not_req = (value & 0xC0) >> 6;
2360 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
2362 "Direct Address (bits 12-7): %d",
2364 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2365 proto_tree_add_item (addr_tree, hf_addr_dir_not_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2366 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
2369 if (not_req == 0x03) {
2370 /* Extended Direct Address 2 */
2371 value = tvb_get_guint8 (tvb, offset);
2372 dir_addr |= ((value & 0x3F) << 13);
2373 not_req = (value & 0xC0) >> 6;
2375 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
2377 "Direct Address (bits 18-13): %d",
2379 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2380 proto_tree_add_item (addr_tree, hf_addr_dir_not_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2381 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
2386 rec_no += *prev_rec_no;
2387 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2390 *prev_rec_no = rec_no;
2392 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no_generated,
2393 tvb, offset, 0, rec_no,
2394 "Recipient Number: %d", rec_no);
2395 if (rec_no > 32767) {
2396 proto_item_append_text (en, " (maximum 32767)");
2397 expert_add_info(pinfo, en, &ei_addr_dir_rec_no_generated);
2399 PROTO_ITEM_SET_GENERATED (en);
2401 if (dir_addr_extended) {
2402 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
2403 tvb, offset, 0, dir_addr,
2404 "Direct Address: %d", dir_addr);
2405 PROTO_ITEM_SET_GENERATED (en);
2408 proto_item_append_text (tf, " %d", rec_no);
2409 if (rec_ofs != -1) {
2410 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2413 proto_item_append_text (tf, ", Direct Address: %d", dir_addr);
2414 dmp_add_recipient_info (tf, rep_req, not_req, action);
2419 /* Ref 5.2.8.2 Extended Recipient Encoding */
2420 static gint dissect_dmp_ext_encoding (tvbuff_t *tvb, packet_info *pinfo,
2421 proto_tree *field_tree,
2422 proto_item *tf, gint offset,
2425 proto_tree *addr_tree = NULL;
2426 proto_item *en = NULL;
2427 guint8 rep_req = 0, not_req = 0;
2428 guint8 value, dmp_addr_form;
2429 gboolean action = FALSE;
2430 gint rec_no, rec_ofs = -1;
2432 value = tvb_get_guint8 (tvb, offset);
2433 dmp_addr_form = (value & 0xE0) >> 5;
2434 action = (value & 0x10);
2435 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form, tvb,
2438 val_to_str_const (dmp_addr_form,
2439 addr_form, "Reserved"));
2440 addr_tree = proto_item_add_subtree (en, ett_address_ext_form);
2441 proto_tree_add_item (addr_tree, hf_addr_ext_form, tvb, offset, 1, ENC_BIG_ENDIAN);
2443 en = proto_tree_add_boolean_format (field_tree, hf_addr_ext_action, tvb,
2444 offset, 1, value, "Action: %s",
2445 action ? "Yes" : "No");
2446 addr_tree = proto_item_add_subtree (en, ett_address_ext_action);
2447 proto_tree_add_item (addr_tree, hf_addr_ext_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2449 rep_req = (value & 0x0C) >> 2;
2450 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rep_req, tvb,
2452 "Report Request: %s",
2453 val_to_str_const ((value & 0x0C) >> 2,
2454 report_vals, "Reserved"));
2455 addr_tree = proto_item_add_subtree (en, ett_address_ext_rep_req);
2456 proto_tree_add_item (addr_tree, hf_addr_ext_rep_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2458 not_req = (value & 0x03);
2459 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_not_req, tvb,
2461 "Notification Request: %s",
2462 val_to_str_const (value & 0x03,
2463 notif_vals, "Reserved"));
2464 addr_tree = proto_item_add_subtree (en, ett_address_ext_not_req);
2465 proto_tree_add_item (addr_tree, hf_addr_ext_not_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2468 value = tvb_get_guint8 (tvb, offset);
2469 rec_no = (value & 0x7F);
2471 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no1, tvb,
2473 "Recipient Number (bits 6-0): %d"
2474 " (offset from previous)",
2476 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2477 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2478 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2482 value = tvb_get_guint8 (tvb, offset);
2483 rec_no |= (value << 7);
2485 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no2, tvb,
2487 "Recipient Number (bits 14-7): %d"
2488 " (offset from previous)", value);
2489 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2490 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2494 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no, tvb,
2496 "Recipient Number Offset: %d"
2497 " (offset from previous)",
2499 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2500 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2501 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2506 rec_no += *prev_rec_no;
2507 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2510 *prev_rec_no = rec_no;
2512 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no_generated,
2513 tvb, offset, 0, rec_no,
2514 "Recipient Number: %d", rec_no);
2515 if (rec_no > 32767) {
2516 proto_item_append_text (en, " (maximum 32767)");
2517 expert_add_info(pinfo, en, &ei_addr_ext_rec_no_generated);
2519 PROTO_ITEM_SET_GENERATED (en);
2521 switch (dmp_addr_form) {
2525 case P1_DIRECT_P2_EXTENDED:
2526 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2527 rec_no, rec_ofs, P1_ADDRESS);
2531 case P1_EXTENDED_P2_DIRECT:
2532 case P1_P2_EXTENDED:
2533 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2534 rec_no, rec_ofs, P1_ADDRESS);
2539 switch (dmp_addr_form) {
2543 case P1_EXTENDED_P2_DIRECT:
2544 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2545 rec_no, rec_ofs, P2_ADDRESS);
2549 case P1_DIRECT_P2_EXTENDED:
2550 case P1_P2_EXTENDED:
2551 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2552 rec_no, rec_ofs, P2_ADDRESS);
2557 dmp_add_recipient_info (tf, rep_req, not_req, action);
2562 /* Ref chapter 5.2 Address encoding */
2563 static gint dissect_dmp_address (tvbuff_t *tvb, packet_info *pinfo,
2564 proto_tree *envelope_tree,
2565 gint offset, guint *prev_rec_no,
2566 gboolean reporting_name)
2568 proto_tree *field_tree = NULL;
2569 proto_item *tf = NULL;
2570 gint boffset = offset;
2572 if (reporting_name) {
2573 tf = proto_tree_add_item (envelope_tree, hf_addr_reporting_name, tvb, offset, -1, ENC_NA);
2575 tf = proto_tree_add_none_format (envelope_tree, hf_addr_recipient, tvb,
2576 offset, -1, "Recipient Number");
2578 field_tree = proto_item_add_subtree (tf, ett_address);
2580 if (dmp.addr_enc == DIRECT_ADDR) {
2581 offset = dissect_dmp_direct_encoding (tvb, pinfo, field_tree, tf,
2582 offset, prev_rec_no);
2584 offset = dissect_dmp_ext_encoding (tvb, pinfo, field_tree, tf, offset,
2588 proto_item_set_len (tf, offset - boffset);
2593 /* Ref chapter 6.2.9 Acknowledgement */
2594 static gint dissect_dmp_ack (tvbuff_t *tvb, packet_info *pinfo,
2595 proto_tree *dmp_tree, gint offset)
2597 proto_tree *ack_tree = NULL, *recip_tree = NULL;
2598 proto_item *en = NULL, *rt = NULL;
2599 proto_item *hidden_item;
2600 guint prev_rec_no = 0;
2601 gint rec_len, rec_no = 0;
2602 gint boffset = offset;
2604 en = proto_tree_add_item (dmp_tree, hf_ack, tvb, offset, 4, ENC_NA);
2605 ack_tree = proto_item_add_subtree (en, ett_ack);
2607 dmp.ack_reason = tvb_get_guint8 (tvb, offset);
2608 proto_item_append_text (en, ", Reason: %s",
2609 val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2611 rt = proto_tree_add_item (ack_tree, hf_ack_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
2612 if (dmp.ack_reason != 0) {
2613 expert_add_info_format(pinfo, rt, &ei_ack_reason, "ACK reason: %s", val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2617 proto_tree_add_item (ack_tree, hf_ack_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN);
2620 /* Subject Message Identifier */
2621 dmp.subj_id = tvb_get_ntohs (tvb, offset);
2622 proto_tree_add_item (ack_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2623 hidden_item = proto_tree_add_item (ack_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2624 PROTO_ITEM_SET_HIDDEN (hidden_item);
2627 if (use_seq_ack_analysis) {
2628 register_dmp_id (pinfo, dmp.ack_reason);
2631 if (dmp.ack_rec_present) {
2632 /* Recipient List */
2633 rec_len = tvb_reported_length (tvb);
2637 if (offset < rec_len) {
2638 rt = proto_tree_add_item (ack_tree, hf_ack_recips, tvb, offset, -1, ENC_NA);
2639 recip_tree = proto_item_add_subtree (rt, ett_ack_recips);
2640 while (offset < rec_len) {
2641 offset = dissect_dmp_address (tvb, pinfo, recip_tree, offset,
2642 &prev_rec_no, FALSE);
2645 proto_item_append_text (rt, ", No Recipients: %d", rec_no);
2646 proto_item_set_len (rt, offset - boffset - 4);
2647 proto_item_set_len (en, offset - boffset);
2654 static gint dissect_mts_identifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2655 gint offset, gboolean subject)
2657 proto_item *ti, *hidden_item;
2658 const gchar *mts_id;
2659 guchar byte_rest = 0;
2661 if (dmp.msg_id_type == X400_MSG_ID || dmp_nat_decode == NAT_DECODE_DMP) {
2662 mts_id = dissect_7bit_string (tvb, offset, dmp.mts_id_length, &byte_rest);
2663 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2664 mts_id = dissect_thales_mts_id (tvb, offset, dmp.mts_id_length, &byte_rest);
2666 mts_id = tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, dmp.mts_id_length);
2668 proto_item_append_text (dmp.mts_id_item, " (%zu bytes decompressed)", strlen(mts_id));
2669 mts_id = format_text (mts_id, strlen(mts_id));
2671 ti = proto_tree_add_string (tree, hf_message_subj_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2672 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2673 /* Read from hash, for analysis */
2674 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, mts_id));
2676 ti = proto_tree_add_string (tree, hf_envelope_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2677 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2678 /* Insert into hash, for analysis */
2679 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (mts_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2681 PROTO_ITEM_SET_HIDDEN (hidden_item);
2682 offset += dmp.mts_id_length;
2685 expert_add_info (pinfo, ti, &ei_7bit_string_unused_bits);
2691 static gint dissect_ipm_identifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2692 gint offset, gboolean subject)
2694 proto_tree *field_tree;
2695 proto_item *ti, *tf, *hidden_item;
2696 const gchar *ipm_id;
2697 gint length, modifier, ipm_id_length;
2698 guchar byte_rest = 0;
2700 length = tvb_get_guint8 (tvb, offset);
2701 modifier = (length & 0xC0) >> 6;
2702 ipm_id_length = length & 0x3F;
2704 tf = proto_tree_add_uint_format (tree, hf_envelope_ipm_id_length,
2705 tvb, offset, 1, ipm_id_length,
2706 "IPM Identifier Length: %u",
2708 field_tree = proto_item_add_subtree (tf, ett_envelope_ipm_id_length);
2709 if ((dmp.msg_id_type == NAT_MSG_ID || modifier != IPM_MODIFIER_X400) && dmp_nat_decode == NAT_DECODE_THALES) {
2710 proto_tree_add_item (field_tree, hf_thales_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2712 proto_tree_add_item (field_tree, hf_envelope_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2714 proto_tree_add_item (field_tree, hf_envelope_ipm_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2717 if (modifier == IPM_MODIFIER_X400 || dmp_nat_decode == NAT_DECODE_DMP) {
2718 ipm_id = dissect_7bit_string (tvb, offset, ipm_id_length, &byte_rest);
2719 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2720 ipm_id = dissect_thales_ipm_id (tvb, offset, ipm_id_length, modifier, &byte_rest);
2722 ipm_id = tvb_bytes_to_str(wmem_packet_scope(), tvb, offset, ipm_id_length);
2724 proto_item_append_text (tf, " (%zu bytes decompressed)", strlen(ipm_id));
2725 ipm_id = format_text (ipm_id, strlen(ipm_id));
2727 ti = proto_tree_add_string (tree, hf_message_subj_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2728 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2729 /* Read from hash, for analysis */
2730 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, ipm_id));
2732 ti = proto_tree_add_string (tree, hf_envelope_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2733 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2734 /* Insert into hash, for analysis */
2735 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (ipm_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2737 PROTO_ITEM_SET_HIDDEN (hidden_item);
2738 offset += ipm_id_length;
2741 expert_add_info (pinfo, ti, &ei_7bit_string_unused_bits);
2747 /* Ref chapter 6.2.7 Envelope structure */
2748 static gint dissect_dmp_envelope (tvbuff_t *tvb, packet_info *pinfo,
2749 proto_tree *dmp_tree, gint offset)
2751 proto_tree *envelope_tree = NULL;
2752 proto_tree *field_tree = NULL;
2753 proto_item *en = NULL, *tf = NULL, *vf = NULL;
2754 proto_item *hidden_item;
2755 guint8 envelope, time_diff;
2756 guint16 subm_time, no_rec, value16;
2758 gchar *env_flags = NULL;
2759 guint prev_rec_no = 0;
2760 gint boffset = offset, i;
2761 gboolean using_short_id = FALSE;
2763 en = proto_tree_add_item (dmp_tree, hf_envelope, tvb, offset, 10, ENC_NA);
2764 envelope_tree = proto_item_add_subtree (en, ett_envelope);
2766 envelope = tvb_get_guint8 (tvb, offset);
2767 dmp.prot_id = (envelope & 0xF8) >> 3;
2768 dmp.version = (envelope & 0x07) + 1;
2770 /* Protocol Version */
2771 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_version,
2772 tvb, offset, 1, dmp.version,
2773 "Protocol Version: %d", dmp.version);
2775 field_tree = proto_item_add_subtree (tf, ett_envelope_version);
2776 vf = proto_tree_add_item (field_tree, hf_envelope_protocol_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2777 if (dmp.prot_id == PROT_NAT) {
2778 proto_item_append_text (vf, " (national version of DMP)");
2779 proto_item_append_text (tf, " (national)");
2780 } else if (dmp.prot_id == PROT_DMP) {
2781 proto_item_append_text (vf, " (correct)");
2783 proto_item_append_text (vf, " (incorrect, should be 0x1d)");
2785 vf = proto_tree_add_item (field_tree, hf_envelope_version_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2788 if (dmp.version > DMP_VERSION_2) {
2789 /* Unsupported DMP Version */
2790 proto_item_append_text (vf, " (unsupported)");
2791 proto_item_append_text (tf, " (unsupported)");
2792 expert_add_info_format(pinfo, vf, &ei_envelope_version_value, "Unsupported DMP Version: %d", dmp.version);
2796 envelope = tvb_get_guint8 (tvb, offset);
2797 dmp.addr_enc = ((envelope & 0x10) >> 4);
2798 dmp.checksum = ((envelope & 0x08) >> 3);
2799 dmp.msg_type = (envelope & 0x07);
2801 if (dmp.msg_type != ACK) {
2803 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_hop_count,
2804 tvb, offset, 1, envelope,
2805 "Hop Count: %d", (envelope & 0xE0) >> 5);
2806 field_tree = proto_item_add_subtree (tf, ett_envelope_hop_count);
2807 proto_tree_add_item (field_tree, hf_envelope_hop_count_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2809 if (dmp.version >= DMP_VERSION_2) {
2810 /* Extensions Present */
2811 dmp.extensions = (envelope & 0x80);
2812 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2813 tvb, offset, 1, envelope,
2815 (envelope & 0x80) ? "Present" : "Absent");
2816 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2817 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2820 /* Recipient Present */
2821 dmp.ack_rec_present = (envelope & 0x20);
2822 tf = proto_tree_add_boolean_format (envelope_tree,hf_envelope_rec_present,
2823 tvb, offset, 1, envelope,
2824 "Recipient Present: %s",
2825 (envelope & 0x20) ? "Present" : "Absent");
2826 field_tree = proto_item_add_subtree (tf, ett_envelope_rec_present);
2827 proto_tree_add_item (field_tree, hf_envelope_rec_present, tvb, offset, 1, ENC_BIG_ENDIAN);
2830 /* Address Encoding */
2831 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_addr_enc,
2832 tvb, offset, 1, envelope,
2833 "Address Encoding: %s",
2835 addr_enc.true_string :
2836 addr_enc.false_string);
2837 field_tree = proto_item_add_subtree (tf, ett_envelope_addr_enc);
2838 proto_tree_add_item (field_tree, hf_envelope_addr_enc, tvb, offset, 1, ENC_BIG_ENDIAN);
2840 /* Checksum Present */
2841 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_checksum,
2842 tvb, offset, 1, envelope,
2844 (envelope & 0x08) ? "Used" : "Not used");
2845 field_tree = proto_item_add_subtree (tf, ett_envelope_checksum);
2846 proto_tree_add_item (field_tree, hf_envelope_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
2849 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_type,
2850 tvb, offset, 1, envelope,
2851 "Content Type: %s (%d)",
2852 val_to_str_const (envelope & 0x07,
2853 type_vals, "Unknown"),
2855 field_tree = proto_item_add_subtree (tf, ett_envelope_cont_type);
2856 proto_tree_add_item (field_tree, hf_envelope_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2858 proto_item_append_text (en, ", Checksum %s", (envelope >> 3) & 0x01 ? "Used" : "Not used");
2861 if (dmp.msg_type >= ACK) {
2862 proto_item_set_len (en, offset - boffset);
2866 if (dmp.version >= DMP_VERSION_2) {
2867 envelope = tvb_get_guint8 (tvb, offset);
2868 /* Extensions Present */
2869 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2870 tvb, offset, 1, envelope,
2872 (envelope & 0x80) ? "Present" : "Absent");
2873 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2874 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2875 dmp.extensions = (envelope & 0x80);
2877 /* Message Identifier Type */
2878 dmp.msg_id_type = (envelope & 0x60) >> 5;
2879 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_msg_id_type,
2880 tvb, offset, 1, envelope,
2881 "Message Identifier Type: %s (%d)",
2882 val_to_str_const (dmp.msg_id_type, msg_id_type_vals, "Unknown"),
2884 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id_type);
2885 proto_tree_add_item (field_tree, hf_envelope_msg_id_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2887 if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
2888 /* MTS Identifier Length */
2889 dmp.mts_id_length = (envelope & 0x1F);
2890 dmp.mts_id_item = proto_tree_add_uint_format (envelope_tree, hf_envelope_mts_id_length,
2891 tvb, offset, 1, envelope,
2892 "MTS Identifier Length: %u",
2894 field_tree = proto_item_add_subtree (dmp.mts_id_item, ett_envelope_mts_id_length);
2895 proto_tree_add_item (field_tree, hf_envelope_mts_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2898 proto_tree_add_item (field_tree, hf_envelope_msg_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2899 if (envelope & 0x10) {
2900 /* Using Short Identifier (12 bits) */
2901 using_short_id = TRUE;
2903 tf = proto_tree_add_item (field_tree, hf_reserved_0x0F, tvb, offset, 1, ENC_BIG_ENDIAN);
2904 if (envelope & 0x0F) {
2905 expert_add_info(pinfo, tf, &ei_reserved_value);
2912 /* Message Identifier */
2913 dmp.msg_id = tvb_get_ntohs (tvb, offset);
2914 if (using_short_id) {
2915 dmp.msg_id &= 0x0FFF;
2917 tf = proto_tree_add_uint (envelope_tree, hf_envelope_msg_id, tvb, offset, 2, dmp.msg_id);
2918 hidden_item = proto_tree_add_uint (envelope_tree, hf_dmp_id, tvb, offset, 2, dmp.msg_id);
2919 if (using_short_id) {
2920 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id);
2921 proto_tree_add_item (field_tree, hf_envelope_msg_id_12bit, tvb, offset, 2, ENC_BIG_ENDIAN);
2922 } else if (dmp.version >= DMP_VERSION_2 && dmp.msg_id_type == ONLY_DMP_ID && dmp.msg_id < 4096) {
2923 expert_add_info(pinfo, tf, &ei_envelope_msg_id);
2925 PROTO_ITEM_SET_HIDDEN (hidden_item);
2928 if (dmp.version >= DMP_VERSION_2) {
2929 if ((dmp.msg_type != REPORT) && (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID)) {
2930 offset = dissect_mts_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
2934 /* Submission Time */
2935 subm_time = tvb_get_ntohs (tvb, offset);
2936 dmp.subm_time = dmp_dec_subm_time ((guint16)(subm_time & 0x7FFF),
2937 (gint32) pinfo->abs_ts.secs);
2938 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_subm_time, tvb,
2939 offset, 2, subm_time,
2940 "Submission time: %s",
2941 (subm_time & 0x7FFF) >= 0x7FF8 ?
2943 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
2944 field_tree = proto_item_add_subtree (tf, ett_envelope_subm_time);
2945 proto_tree_add_item (field_tree, hf_envelope_time_diff_present, tvb, offset, 2, ENC_BIG_ENDIAN);
2946 proto_tree_add_item (field_tree, hf_envelope_subm_time_value, tvb, offset, 2, ENC_BIG_ENDIAN);
2949 if (subm_time & 0x8000) {
2950 /* Timed Difference */
2951 time_diff = tvb_get_guint8 (tvb, offset);
2952 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_time_diff,
2953 tvb, offset, 1, time_diff,
2954 "Time Difference: ");
2955 field_tree = proto_item_add_subtree (tf, ett_envelope_time_diff);
2956 proto_tree_add_item (field_tree, hf_envelope_time_diff_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2957 secs = dmp_dec_time_diff (time_diff);
2958 if (secs == DMP_TIME_RESERVED) {
2959 proto_item_append_text (tf, "Reserved (0x%2.2x)", time_diff);
2961 proto_item_append_text (tf, "%s", signed_time_secs_to_str(wmem_packet_scope(), secs));
2966 /* Envelope Flags */
2967 envelope = tvb_get_guint8 (tvb, offset);
2968 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_flags,
2969 tvb, offset, 1, envelope,
2972 field_tree = proto_item_add_subtree (tf, ett_envelope_flags);
2973 proto_tree_add_item (field_tree, hf_envelope_content_id_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
2974 proto_tree_add_item (field_tree, hf_envelope_recip_reassign_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2975 proto_tree_add_item (field_tree, hf_envelope_dl_expansion_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2977 if (envelope & 0xE0) {
2978 env_flags = wmem_strdup_printf (wmem_packet_scope(), "%s%s%s",
2979 (envelope & 0x80) ? ", ContId discarded" : "",
2980 (envelope & 0x40) ? ", Reass prohibited" : "",
2981 (envelope & 0x20) ? ", DLE prohibited" : "");
2982 proto_item_append_text (tf, ":%s", &env_flags[1]);
2984 proto_item_append_text (tf, " (none)");
2987 /* Recipient Count */
2988 no_rec = (envelope & 0x1F);
2989 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_recipients,
2990 tvb, offset, 1, envelope,
2991 "Recipient Count: %d", no_rec);
2993 field_tree = proto_item_add_subtree (tf, ett_envelope_recipients);
2994 proto_tree_add_item (field_tree, hf_envelope_recipients, tvb, offset, 1, ENC_BIG_ENDIAN);
2998 /* Extended Recipient Count */
2999 value16 = tvb_get_ntohs (tvb, offset);
3000 no_rec = value16 & 0x7FFF;
3001 tf = proto_tree_add_uint_format (envelope_tree,hf_envelope_ext_recipients,
3002 tvb, offset, 2, value16,
3003 "Extended Recipient Count: %d%s", no_rec,
3005 " (incorrect, reserved value)" : ""));
3007 field_tree = proto_item_add_subtree (tf, ett_envelope_ext_recipients);
3008 en = proto_tree_add_item (field_tree, hf_reserved_0x8000, tvb, offset, 2, ENC_BIG_ENDIAN);
3009 if (value16 & 0x8000) {
3010 expert_add_info(pinfo, en, &ei_reserved_value);
3012 proto_tree_add_item (field_tree, hf_envelope_ext_recipients, tvb, offset, 2, ENC_BIG_ENDIAN);
3016 if (dmp.msg_type != REPORT) {
3017 /* Originator - Not present for reports */
3018 offset = dissect_dmp_originator (tvb, pinfo, envelope_tree, offset);
3021 for (i = 0; i < no_rec; i++) {
3023 offset = dissect_dmp_address (tvb, pinfo, envelope_tree, offset,
3024 &prev_rec_no, FALSE);
3027 if (dmp.version >= DMP_VERSION_2) {
3028 if ((dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) &&
3029 dmp.notif_req && (dmp.msg_type == STANAG || dmp.msg_type == IPM))
3031 offset = dissect_ipm_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
3035 proto_item_set_len (en, offset - boffset);
3041 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3042 * and chapter 6.3.8.1 IPM 88 message structure
3044 static gint dissect_dmp_message (tvbuff_t *tvb, packet_info *pinfo,
3045 proto_tree *dmp_tree, gint offset)
3047 tvbuff_t *body_tvb = NULL;
3048 proto_tree *message_tree = NULL;
3049 proto_tree *field_tree = NULL;
3050 proto_item *en = NULL, *tf = NULL, *tr = NULL;
3051 guint8 message, eit = 0, compr_alg = ALGORITHM_NONE;
3052 gint len, boffset = offset, body_offset = 0, body_len = 0;
3054 en = proto_tree_add_item (dmp_tree, hf_message_body, tvb, offset, -1, ENC_NA);
3055 message_tree = proto_item_add_subtree (en, ett_message);
3057 if (dmp.body_format == FREE_TEXT_SUBJECT) {
3058 len = tvb_strsize (tvb, offset);
3059 proto_tree_add_item (message_tree, hf_message_subject, tvb, offset, len, ENC_ASCII|ENC_NA);
3063 if (dmp.body_format == FREE_TEXT || dmp.body_format == FREE_TEXT_SUBJECT) {
3064 message = tvb_get_guint8 (tvb, offset);
3065 eit = (message & 0xE0) >> 5;
3066 compr_alg = (message & 0x18) >> 3;
3067 /* Encoded Information Type */
3068 tf = proto_tree_add_uint_format (message_tree, hf_message_eit,
3069 tvb, offset, 1, message, "EIT: %s (%d)",
3070 val_to_str_const (eit, eit_vals, "Unknown"),
3072 field_tree = proto_item_add_subtree (tf, ett_message_eit);
3073 proto_tree_add_item (field_tree, hf_message_eit, tvb, offset, 1, ENC_BIG_ENDIAN);
3074 proto_item_append_text (en, ", Type: %s",
3075 val_to_str_const (eit, eit_vals, "Unknown"));
3077 /* Compression Algorithm */
3078 tf = proto_tree_add_uint_format (message_tree, hf_message_compr,
3079 tvb, offset, 1, message,
3080 "Compression Algorithm: %s (%d)",
3081 val_to_str_const (compr_alg, compression_vals, "Unknown"),
3083 field_tree = proto_item_add_subtree (tf, ett_message_compr);
3084 tr = proto_tree_add_item (field_tree, hf_message_compr, tvb, offset, 1, ENC_BIG_ENDIAN);
3085 if (compr_alg == ALGORITHM_ZLIB) {
3086 proto_item_append_text (en, " (compressed)");
3087 } else if (compr_alg != ALGORITHM_NONE) {
3088 expert_add_info(pinfo, tr, &ei_message_compr);
3091 if (message & 0x07) {
3093 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x07,
3094 tvb, offset, 1, message,
3095 "Reserved: %d", message & 0x07);
3096 field_tree = proto_item_add_subtree (tf, ett_message_body_reserved);
3097 tf = proto_tree_add_item (field_tree, hf_reserved_0x07, tvb, offset, 1, ENC_BIG_ENDIAN);
3098 expert_add_info(pinfo, tf, &ei_reserved_value);
3103 len = tvb_reported_length_remaining (tvb, offset);
3108 if (compr_alg == ALGORITHM_ZLIB) {
3109 tf = proto_tree_add_item (message_tree, hf_message_body_compressed,
3110 tvb, offset, len, ENC_NA);
3111 proto_item_append_text (tf, ", Length: %d", len);
3113 tf = proto_tree_add_item (message_tree, hf_message_body_data,
3114 tvb, offset, len, ENC_NA);
3115 proto_item_set_text (tf, "User data, Length: %d", len);
3118 if (dmp.body_format == STRUCTURED) {
3119 /* Structured Message ID */
3120 field_tree = proto_item_add_subtree (tf, ett_message_body);
3121 proto_tree_add_item (field_tree, hf_message_body_structured, tvb, offset, len, ENC_NA);
3122 } else if (len > 0 && (dmp.body_format == FREE_TEXT ||
3123 dmp.body_format == FREE_TEXT_SUBJECT)) {
3124 if (compr_alg == ALGORITHM_ZLIB) {
3125 if ((body_tvb = tvb_child_uncompress (tvb, tvb, offset, len)) != NULL) {
3126 body_len = tvb_captured_length (body_tvb);
3127 add_new_data_source (pinfo, body_tvb, "Uncompressed User data");
3128 tf = proto_tree_add_item (message_tree, hf_message_body_data,
3129 body_tvb, 0, body_len, ENC_NA);
3130 proto_item_set_text (tf, "User data, Length: %d", body_len);
3131 PROTO_ITEM_SET_GENERATED (tf);
3133 proto_tree_add_expert (message_tree, pinfo, &ei_message_body_uncompress, tvb, offset, len);
3137 body_offset = offset;
3141 if (eit != EIT_BILATERAL && body_len > 0) {
3142 field_tree = proto_item_add_subtree (tf, ett_message_body);
3143 proto_tree_add_item (field_tree, hf_message_body_plain, body_tvb,
3144 body_offset, body_len, ENC_ASCII|ENC_NA);
3149 proto_item_set_len (en, offset - boffset);
3154 /* Ref chapter 6.3.9.1 Report structure */
3155 static gint dissect_dmp_report (tvbuff_t *tvb, packet_info *pinfo,
3156 proto_tree *dmp_tree, gint offset,
3157 guint *prev_rec_no, gint num)
3159 proto_tree *report_tree = NULL;
3160 proto_tree *field_tree = NULL;
3161 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3163 gboolean info_present;
3165 gint len, boffset = offset;
3168 report = tvb_get_guint8 (tvb, offset);
3169 rep_type = (report & 0x80) >> 7;
3171 en = proto_tree_add_item (dmp_tree, hf_non_delivery_report, tvb, offset, 4, ENC_NA);
3173 en = proto_tree_add_item (dmp_tree, hf_delivery_report, tvb, offset, 4, ENC_NA);
3175 proto_item_append_text (en, " (#%d)", num);
3177 report_tree = proto_item_add_subtree (en, ett_report);
3180 tf = proto_tree_add_boolean_format (report_tree, hf_report_type,
3181 tvb, offset, 1, report,
3182 "Report Type: %s", rep_type ?
3183 report_type.true_string :
3184 report_type.false_string);
3185 field_tree = proto_item_add_subtree (tf, ett_report_type);
3186 proto_tree_add_item (field_tree, hf_report_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3188 if (rep_type == DR) {
3191 info_present = (report & 0x40);
3192 tf = proto_tree_add_boolean_format (report_tree,hf_report_info_present_dr,
3193 tvb, offset, 1, report,
3194 "Info Present: %s", (report & 0x40) ? "Present" : "Absent");
3195 field_tree = proto_item_add_subtree (tf, ett_report_info_present_dr);
3196 proto_tree_add_item (field_tree, hf_report_info_present_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3198 /* Address Encoding */
3199 dmp.addr_enc = ((report & 0x20) >> 5);
3200 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_dr,
3201 tvb, offset, 1, report,
3202 "Address Encoding: %s",
3204 addr_enc.true_string :
3205 addr_enc.false_string);
3206 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_dr);
3207 proto_tree_add_item (field_tree, hf_report_addr_enc_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3209 if (report & 0x1F) {
3211 tf = proto_tree_add_uint_format (report_tree, hf_reserved_0x1F,
3212 tvb, offset, 1, report,
3213 "Reserved: %d", report & 0x1F);
3214 field_tree = proto_item_add_subtree (tf, ett_report_reserved);
3215 tf = proto_tree_add_item (field_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
3216 expert_add_info(pinfo, tf, &ei_reserved_value);
3222 report = tvb_get_guint8 (tvb, offset);
3223 tf = proto_tree_add_uint_format (report_tree, hf_report_del_time,
3224 tvb, offset, 1, report,
3226 field_tree = proto_item_add_subtree (tf, ett_report_del_time);
3227 ei = proto_tree_add_item (field_tree, hf_report_del_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3228 secs = dmp_dec_del_time (report);
3229 if (secs == DMP_TIME_RESERVED) {
3230 proto_item_append_text (tf, "Reserved (0x%2.2x)", report);
3231 proto_item_append_text (ei, " (Reserved)");
3233 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(wmem_packet_scope(), secs),
3234 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3235 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(wmem_packet_scope(), secs));
3239 /* Address Encoding */
3240 dmp.addr_enc = ((report & 0x40) >> 6);
3241 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_ndr,
3242 tvb, offset, 1, report,
3243 "Address Encoding: %s",
3245 addr_enc.true_string :
3246 addr_enc.false_string);
3247 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_ndr);
3248 proto_tree_add_item (field_tree, hf_report_addr_enc_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3251 tf = proto_tree_add_uint_format (report_tree, hf_report_reason,
3252 tvb, offset, 1, report,
3253 "Reason%s: %s (%d)",
3254 ((report & 0x3F) < 0x3D) ? " (P1)":"",
3255 non_del_reason_str (report & 0x3F),
3257 field_tree = proto_item_add_subtree (tf, ett_report_reason);
3258 proto_tree_add_item (field_tree, hf_report_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
3262 report = tvb_get_guint8 (tvb, offset);
3263 info_present = (report & 0x80);
3264 tf = proto_tree_add_boolean_format (report_tree,
3265 hf_report_info_present_ndr,
3266 tvb, offset, 1, report,
3267 "Info Present: %s", (report & 0x80) ? "Present" : "Absent");
3268 field_tree = proto_item_add_subtree (tf, ett_report_info_present_ndr);
3269 proto_tree_add_item (field_tree, hf_report_info_present_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3272 tf = proto_tree_add_uint_format (report_tree, hf_report_diagn,
3273 tvb, offset, 1, report,
3274 "Diagnostic%s: %s (%d)",
3275 ((report & 0x7F) < 0x7C) ? " (P1)":"",
3276 non_del_diagn_str (report & 0x7F),
3278 field_tree = proto_item_add_subtree (tf, ett_report_diagn);
3279 proto_tree_add_item (field_tree, hf_report_diagn, tvb, offset, 1, ENC_BIG_ENDIAN);
3283 offset = dissect_dmp_address (tvb, pinfo, report_tree, offset,
3287 /* Supplementary Information */
3288 len = tvb_strsize (tvb, offset);
3289 tf = proto_tree_add_uint_format (report_tree, hf_report_suppl_info_len,
3290 tvb, offset, len, len,
3291 "Supplementary Information, Length: %d",
3294 if ((offset - boffset + len) > 128) {
3295 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3296 128 - (offset - boffset));
3298 field_tree = proto_item_add_subtree (tf, ett_report_suppl_info);
3299 proto_tree_add_item (field_tree, hf_report_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3304 proto_item_set_len (en, offset - boffset);
3309 /* Ref chapter 6.3.10.1 Notification structure */
3310 static gint dissect_dmp_notification (tvbuff_t *tvb, packet_info *pinfo _U_,
3311 proto_tree *dmp_tree, gint offset)
3313 proto_tree *notif_tree = NULL;
3314 proto_tree *field_tree = NULL;
3315 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3316 guint8 notif, rec_time, on_typex = 0xFF;
3317 gint len, boffset = offset;
3320 if (dmp.notif_type == RN) {
3321 en = proto_tree_add_item (dmp_tree, hf_receipt_notif, tvb, offset, 4, ENC_NA);
3322 } else if (dmp.notif_type == NRN) {
3323 en = proto_tree_add_item (dmp_tree, hf_non_receipt_notif, tvb, offset, 4, ENC_NA);
3324 } else if (dmp.notif_type == ON) {
3325 en = proto_tree_add_item (dmp_tree, hf_other_notif, tvb, offset, 4, ENC_NA);
3329 notif_tree = proto_item_add_subtree (en, ett_notif);
3331 if (dmp.notif_type == RN || dmp.notif_type == ON) {
3333 rec_time = tvb_get_guint8 (tvb, offset);
3334 tf = proto_tree_add_uint_format (notif_tree, hf_notif_rec_time,
3335 tvb, offset, 1, rec_time,
3337 field_tree = proto_item_add_subtree (tf, ett_notif_rec_time);
3338 ei = proto_tree_add_item (field_tree, hf_notif_rec_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3339 secs = dmp_dec_exp_time (rec_time);
3340 if (secs == DMP_TIME_NOT_PRESENT) {
3341 proto_item_append_text (tf, "Not present");
3342 proto_item_append_text (ei, " (not present)");
3343 } else if (secs == DMP_TIME_RESERVED) {
3344 proto_item_append_text (tf, "Reserved (0x%2.2x)", rec_time);
3345 proto_item_append_text (ei, " (Reserved)");
3347 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(wmem_packet_scope(), secs),
3348 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3349 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(wmem_packet_scope(), secs));
3353 if (dmp.notif_type == ON) {
3355 on_typex = tvb_get_guint8 (tvb, offset);
3356 proto_tree_add_item (notif_tree, hf_notif_on_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3360 /* Supplementary Information */
3361 len = tvb_strsize (tvb, offset);
3362 tf = proto_tree_add_uint_format (notif_tree, hf_notif_suppl_info_len,
3363 tvb, offset, len, len,
3364 "Supplementary Information, Length: %d",
3367 if ((offset - boffset + len) > 128) {
3368 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3369 128 - (offset - boffset));
3371 field_tree = proto_item_add_subtree (tf, ett_notif_suppl_info);
3372 proto_tree_add_item (field_tree, hf_notif_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3376 if ((dmp.notif_type == ON) && (on_typex < 0x03)) {
3377 /* ACP127 Receipient */
3378 len = tvb_strsize (tvb, offset);
3379 tf = proto_tree_add_uint_format (notif_tree, hf_notif_acp127,
3380 tvb, offset, len, len,
3381 "ACP127 Recipient, Length: %d",
3385 proto_item_append_text (tf, " (incorrect, must be less than 64)");
3387 field_tree = proto_item_add_subtree (tf, ett_notif_acp127recip);
3388 proto_tree_add_item (field_tree, hf_notif_acp127recip, tvb, offset, len, ENC_ASCII|ENC_NA);
3392 } else if (dmp.notif_type == NRN) {
3393 /* Non-Recipient Reason */
3394 notif = tvb_get_guint8 (tvb, offset);
3395 proto_tree_add_uint_format (notif_tree, hf_notif_non_rec_reason,
3396 tvb, offset, 1, notif,
3397 "Non-Receipt Reason%s: %s (%d)",
3398 (notif < 0x10) ? " (P22)" : "",
3399 nrn_reason_str (notif), notif);
3402 /* Discard Reason */
3403 notif = tvb_get_guint8 (tvb, offset);
3404 proto_tree_add_uint_format (notif_tree, hf_notif_discard_reason,
3405 tvb, offset, 1, notif,
3406 "Discard Reason%s: %s (%d)",
3407 (notif < 0x10) ? " (P22)" : "",
3408 discard_reason_str (notif), notif);
3412 proto_item_set_len (en, offset - boffset);
3417 /* Ref chapter 6.2.1.2.8 SecurityCategories */
3418 static gint dissect_dmp_security_category (tvbuff_t *tvb, packet_info *pinfo,
3420 const gchar **label_string,
3421 gint offset, guint8 ext)
3423 proto_tree *field_tree = NULL;
3424 proto_item *tf = NULL, *tr = NULL;
3425 gchar *sec_cat = NULL;
3427 gboolean country_code = FALSE;
3429 message = tvb_get_guint8 (tvb, offset);
3430 tf = proto_tree_add_uint_format (tree, hf_message_sec_cat_nat, tvb,
3431 offset, 1, message, "Security Categories");
3432 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3436 case SEC_CAT_EXT_NONE:
3437 proto_tree_add_item (field_tree, hf_message_sec_cat_cl, tvb, offset, 1, ENC_BIG_ENDIAN);
3438 proto_tree_add_item (field_tree, hf_message_sec_cat_cs, tvb, offset, 1, ENC_BIG_ENDIAN);
3439 proto_tree_add_item (field_tree, hf_message_sec_cat_ex, tvb, offset, 1, ENC_BIG_ENDIAN);
3440 proto_tree_add_item (field_tree, hf_message_sec_cat_ne, tvb, offset, 1, ENC_BIG_ENDIAN);
3442 tr = proto_tree_add_item (field_tree, hf_reserved_0x08, tvb, offset, 1, ENC_BIG_ENDIAN);
3443 if (message & 0x08) {
3444 expert_add_info(pinfo, tr, &ei_reserved_value);
3446 tr = proto_tree_add_item (field_tree, hf_reserved_0x04, tvb, offset, 1, ENC_BIG_ENDIAN);
3447 if (message & 0x04) {
3448 expert_add_info(pinfo, tr, &ei_reserved_value);
3451 if (message & 0xF0) {
3452 sec_cat = wmem_strdup_printf (wmem_packet_scope(), "%s%s%s%s",
3453 (message & 0x80) ? ",cl" : "",
3454 (message & 0x40) ? ",cs" : "",
3455 (message & 0x20) ? ",ex" : "",
3456 (message & 0x10) ? ",ne" : "");
3457 proto_item_append_text (tf, ": %s", &sec_cat[1]);
3458 *label_string = wmem_strconcat(wmem_packet_scope(), *label_string, sec_cat, NULL);
3462 case SEC_CAT_EXT_PERMISSIVE:
3463 if ((message >> 2) == 0x3F) {
3464 /* Fake entry because nat_pol_id defines 0x3F as reserved */
3465 proto_tree_add_uint_format (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1,
3466 message, "1111 11.. = Next byte has Country Code (0x3F)");
3467 country_code = TRUE;
3469 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1, ENC_BIG_ENDIAN);
3470 proto_item_append_text (tf, ": rel-to-%s", get_nat_pol_id_short (message >> 2));
3471 *label_string = wmem_strdup_printf(wmem_packet_scope(), "%s,rel-to-%s", *label_string, get_nat_pol_id_short (message >> 2));
3472 if ((message >> 2) == 0) {
3473 expert_add_info(pinfo, tr, &ei_reserved_value);
3478 case SEC_CAT_EXT_RESTRICTIVE:
3479 proto_tree_add_item (field_tree, hf_message_sec_cat_restrictive, tvb, offset, 1, ENC_BIG_ENDIAN);
3480 proto_item_append_text (tf, " (restrictive: 0x%2.2x)", message >> 2);
3487 proto_item_append_text (tf, " (0x%2.2x)", message);
3489 if (dmp.version == 1) {
3490 tr = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3491 if (message & 0x02) {
3492 expert_add_info(pinfo, tr, &ei_reserved_value);
3494 tr = proto_tree_add_item (field_tree, hf_reserved_0x01, tvb, offset, 1, ENC_BIG_ENDIAN);
3495 if (message & 0x01) {
3496 expert_add_info(pinfo, tr, &ei_reserved_value);
3499 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_extended, tvb, offset, 1, ENC_BIG_ENDIAN);
3500 if ((message & 0x01) && (message & 0x02)) {
3501 expert_add_info(pinfo, tr, &ei_reserved_value);
3502 } else if (message & 0x01 || message & 0x02) {
3503 proto_item_append_text (tf, " (extended)");
3504 offset = dissect_dmp_security_category (tvb, pinfo, tree, label_string, offset+1, message & 0x03);
3508 proto_tree_add_item (field_tree, hf_message_sec_cat_country_code, tvb, offset+1, 1, ENC_BIG_ENDIAN);
3509 proto_item_append_text (tf, " (rel-to country-code: %d)", tvb_get_guint8 (tvb, offset+1));
3510 proto_item_set_len (tf, 2);
3519 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3520 * and chapter 6.3.8.1 IPM 88 message structure
3521 * and chapter 6.3.9.1 Report structure
3522 * and chapter 6.3.10.1 Notification structure
3524 static gint dissect_dmp_content (tvbuff_t *tvb, packet_info *pinfo,
3525 proto_tree *dmp_tree, gint offset)
3527 proto_tree *message_tree = NULL;
3528 proto_tree *field_tree = NULL;
3529 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3530 proto_item *hidden_item;
3531 const char *label_string = wmem_strdup (wmem_packet_scope(), "");
3532 const gchar *class_name = NULL;
3533 guint8 message, dmp_sec_pol, dmp_sec_class, dmp_nation = 0, exp_time, dtg;
3535 guint prev_rec_no = 0;
3536 gint rep_len, rep_no = 1;
3537 gint loffset, boffset = offset;
3539 if (dmp.msg_type == REPORT) {
3540 en = proto_tree_add_item (dmp_tree, hf_report_content, tvb, offset, 7, ENC_NA);
3541 } else if (dmp.msg_type == NOTIF) {
3542 en = proto_tree_add_item (dmp_tree, hf_notif_content, tvb, offset, 7, ENC_NA);
3544 en = proto_tree_add_item (dmp_tree, hf_message_content, tvb, offset, 7, ENC_NA);
3546 message_tree = proto_item_add_subtree (en, ett_content);
3548 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3549 message = tvb_get_guint8 (tvb, offset);
3550 dmp.body_format = (message & 0x03);
3552 if (dmp.msg_type == STANAG) {
3554 dmp.st_type = (message & 0xC0) >> 6;
3555 tf = proto_tree_add_uint_format (message_tree, hf_message_st_type,
3556 tvb, offset, 1, message,
3557 "Message Type: %s (%d)",
3558 val_to_str_const (dmp.st_type,
3559 message_type_vals, ""),
3561 field_tree = proto_item_add_subtree (tf, ett_message_st_type);
3562 proto_tree_add_item (field_tree, hf_message_st_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3564 if ((message & 0x20) >> 5) {
3566 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x20,
3567 tvb, offset, 1, message,
3568 "Reserved: %d", (message & 0x20)>>5);
3569 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3570 tf = proto_tree_add_item (field_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
3571 expert_add_info(pinfo, tf, &ei_reserved_value);
3575 dmp.prec = (message & 0x1C) >> 2;
3576 tf = proto_tree_add_uint_format (message_tree, hf_message_precedence,
3577 tvb, offset, 1, message,
3578 "Precedence: %s (%d)",
3579 val_to_str_const (dmp.prec, precedence, ""),
3581 field_tree = proto_item_add_subtree (tf, ett_message_precedence);
3582 proto_tree_add_item (field_tree, hf_message_precedence, tvb, offset, 1, ENC_BIG_ENDIAN);
3585 if ((message & 0xE0) >> 5) {
3587 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0xE0,
3588 tvb, offset, 1, message,
3589 "Reserved: %d", (message & 0xE0)>>5);
3590 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3591 tf = proto_tree_add_item (field_tree, hf_reserved_0xE0, tvb, offset, 1, ENC_BIG_ENDIAN);
3592 expert_add_info(pinfo, tf, &ei_reserved_value);
3596 dmp.prec = (message & 0x1C) >> 2;
3597 tf = proto_tree_add_uint_format (message_tree, hf_message_importance,
3598 tvb, offset, 1, message,
3599 "Importance: %s (%d)",
3600 val_to_str_const (dmp.prec, importance, ""),
3602 field_tree = proto_item_add_subtree (tf, ett_message_importance);
3603 proto_tree_add_item (field_tree, hf_message_importance, tvb, offset, 1, ENC_BIG_ENDIAN);
3607 tf = proto_tree_add_uint_format (message_tree, hf_message_body_format,
3608 tvb, offset, 1, message,
3609 "Body Format: %s (%d)",
3610 val_to_str_const (message & 0x03,
3611 body_format_vals, ""),
3613 field_tree = proto_item_add_subtree (tf, ett_message_body_format);
3614 proto_tree_add_item (field_tree, hf_message_body_format, tvb, offset, 1, ENC_BIG_ENDIAN);
3618 message = tvb_get_guint8 (tvb, offset);
3619 /* Security Classification */
3620 dmp_sec_class = (message & 0xE0) >> 5;
3621 dmp_sec_pol = (message & 0x1C) >> 2;
3622 if (dmp_sec_pol == EXTENDED_NATIONAL) {
3623 dmp_nation = tvb_get_guint8 (tvb, offset + 1);
3626 loffset = offset; /* Offset to start of security label */
3627 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3628 class_name = dmp_national_sec_class (dmp_local_nation, dmp_sec_class);
3629 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3630 class_name = dmp_national_sec_class (dmp_nation, dmp_sec_class);
3632 if ((dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL) && !class_name) {
3633 class_name = val_to_str_const (dmp_sec_class, sec_class, "");
3635 if (class_name && class_name[0]) {
3636 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3637 tvb, offset, 1, message,
3638 "Security Classification: %s (%d)",
3639 class_name, dmp_sec_class);
3641 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3642 tvb, offset, 1, message,
3643 "Security Classification: %d",
3646 field_tree = proto_item_add_subtree (tf, ett_message_sec_class);
3647 tf = proto_tree_add_item (field_tree, hf_message_sec_class_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3649 proto_item_append_text (tf, " (%s)", class_name);
3650 label_string = wmem_strconcat(wmem_packet_scope(), label_string, class_name, NULL);
3653 /* Security Policy */
3654 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_pol,
3655 tvb, offset, 1, message,
3656 "Security Policy: %s (%d)",
3657 val_to_str (dmp_sec_pol, sec_pol, "%d"),
3659 field_tree = proto_item_add_subtree (tf, ett_message_sec_pol);
3660 proto_tree_add_item (field_tree, hf_message_sec_pol, tvb, offset, 1, ENC_BIG_ENDIAN);
3662 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3664 tf = proto_tree_add_item (message_tree, hf_message_heading_flags, tvb, offset, 1, ENC_NA);
3665 field_tree = proto_item_add_subtree (tf, ett_message_heading_flags);
3666 proto_tree_add_item (field_tree, hf_message_auth_users, tvb, offset, 1, ENC_BIG_ENDIAN);
3667 proto_tree_add_item (field_tree, hf_message_subject_disc, tvb, offset, 1, ENC_BIG_ENDIAN);
3668 if (message & 0x03) {
3669 proto_item_append_text (tf, ": %s%s%s discarded",
3670 (message & 0x02) ? "Authorizing users" : "",
3671 (message & 0x03) == 0x03 ? " and " : "",
3672 (message & 0x01) ? "Subject" : "");
3674 proto_item_append_text (tf, " (none)");
3676 } else if (dmp.msg_type == NOTIF) {
3677 /* Notification Type */
3678 dmp.notif_type = (message & 0x03);
3679 tf = proto_tree_add_uint_format (message_tree, hf_notif_type,
3680 tvb, offset, 1, message,
3681 "Notification Type: %s",
3682 val_to_str_const (dmp.notif_type, notif_type,
3684 field_tree = proto_item_add_subtree (tf, ett_notif_type);
3685 proto_tree_add_item (field_tree, hf_notif_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3686 } else if (message & 0x02) {
3688 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x02,
3689 tvb, offset, 1, message,
3690 "Reserved: %d", message & 0x02);
3691 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3692 tf = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3693 expert_add_info(pinfo, tf, &ei_reserved_value);
3697 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3698 /* Show configured national policy */
3699 tf = proto_tree_add_uint (message_tree, hf_message_national_policy_id,
3700 tvb, offset, 0, dmp_local_nation);
3701 PROTO_ITEM_SET_GENERATED (tf);
3702 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3703 /* National Policy Identifier */
3704 proto_tree_add_item (message_tree, hf_message_national_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3706 } else if (dmp_sec_pol == EXTENDED_MISSION) {
3707 /* Mission Policy Identifier */
3708 message = tvb_get_guint8 (tvb, offset);
3709 if (message == 0xFF) {
3710 proto_tree_add_uint_format_value (message_tree, hf_message_mission_policy_id,
3711 tvb, offset, 1, message,
3714 proto_tree_add_item (message_tree, hf_message_mission_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3719 /* Security Categories */
3720 if (dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL || dmp_sec_pol == EXTENDED_NATIONAL) {
3721 offset = dissect_dmp_security_category (tvb, pinfo, message_tree, &label_string, offset, 0);
3722 proto_item_append_text (en, ", Security Label: %s", label_string);
3723 tf = proto_tree_add_string (message_tree, hf_message_sec_label, tvb, loffset,
3724 offset - loffset + 1, label_string);
3725 PROTO_ITEM_SET_GENERATED (tf);
3727 tf = proto_tree_add_item (message_tree, hf_message_sec_cat_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3728 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3730 proto_tree_add_item (field_tree, hf_message_sec_cat_bit7, tvb, offset, 1, ENC_BIG_ENDIAN);
3731 proto_tree_add_item (field_tree, hf_message_sec_cat_bit6, tvb, offset, 1, ENC_BIG_ENDIAN);
3732 proto_tree_add_item (field_tree, hf_message_sec_cat_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
3733 proto_tree_add_item (field_tree, hf_message_sec_cat_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
3734 proto_tree_add_item (field_tree, hf_message_sec_cat_bit3, tvb, offset, 1, ENC_BIG_ENDIAN);
3735 proto_tree_add_item (field_tree, hf_message_sec_cat_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
3736 proto_tree_add_item (field_tree, hf_message_sec_cat_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3737 proto_tree_add_item (field_tree, hf_message_sec_cat_bit0, tvb, offset, 1, ENC_BIG_ENDIAN);
3741 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3743 exp_time = tvb_get_guint8 (tvb, offset);
3744 tf = proto_tree_add_uint_format (message_tree, hf_message_exp_time,
3745 tvb, offset, 1, exp_time,
3747 field_tree = proto_item_add_subtree (tf, ett_message_exp_time);
3748 ei = proto_tree_add_item (field_tree, hf_message_exp_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3749 secs = dmp_dec_exp_time (exp_time);
3750 if (secs == DMP_TIME_NOT_PRESENT) {
3751 proto_item_append_text (tf, "Not present");
3752 proto_item_append_text (ei, " (not present)");
3753 } else if (secs == DMP_TIME_RESERVED) {
3754 proto_item_append_text (tf, "Reserved (0x%2.2x)", exp_time);
3755 proto_item_append_text (ei, " (Reserved)");
3757 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(wmem_packet_scope(), secs),
3758 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE));
3759 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(wmem_packet_scope(), secs));
3764 if (dmp.msg_type == STANAG) {
3765 dtg = tvb_get_guint8 (tvb, offset);
3766 tf = proto_tree_add_uint_format (message_tree, hf_message_dtg, tvb, offset, 1, dtg, "DTG: ");
3767 field_tree = proto_item_add_subtree (tf, ett_message_dtg);
3768 proto_tree_add_item (field_tree, hf_message_dtg_sign, tvb, offset, 1, ENC_BIG_ENDIAN);
3769 proto_tree_add_item (field_tree, hf_message_dtg_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3770 secs = dmp_dec_dtg (dtg & 0x7F);
3771 if (secs == DMP_TIME_NOT_PRESENT) {
3772 proto_item_append_text (tf, "Not present");
3773 } else if (secs == DMP_TIME_RESERVED) {
3774 proto_item_append_text (tf, "Reserved (0x%2.2x)", dtg & 0x7F);
3775 } else if (secs == 0) {
3776 proto_item_append_text (tf, "0 minutes in the %s (%s)",
3777 (dtg & 0x80) ? dtg_sign.true_string :
3778 dtg_sign.false_string,
3779 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
3781 proto_item_append_text (tf, "%s in the %s (%s)", signed_time_secs_to_str(wmem_packet_scope(), secs),
3782 (dtg & 0x80) ? dtg_sign.true_string :
3783 dtg_sign.false_string, (dtg & 0x80) ?
3784 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE) :
3785 abs_time_secs_to_str (wmem_packet_scope(), dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3790 if (dmp.msg_type == STANAG) {
3792 offset = dissect_dmp_sic (tvb, pinfo, message_tree, offset);
3793 } else if (dmp.msg_type == REPORT || dmp.msg_type == NOTIF) {
3794 if (dmp.version == DMP_VERSION_1 || dmp.msg_id_type == ONLY_DMP_ID) {
3795 /* Subject Message Identifier */
3796 dmp.subj_id = tvb_get_ntohs (tvb, offset);
3797 proto_tree_add_item (message_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3798 hidden_item = proto_tree_add_item (message_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3799 PROTO_ITEM_SET_HIDDEN (hidden_item);
3801 } else if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
3802 if (dmp.msg_type == REPORT) {
3803 /* Subject MTS Identifier */
3804 offset = dissect_mts_identifier (tvb, pinfo, message_tree, offset, TRUE);
3806 /* Subject IPM Identifier */
3807 offset = dissect_ipm_identifier (tvb, pinfo, message_tree, offset, TRUE);
3810 tf = proto_tree_add_uint (message_tree, hf_message_subj_id, tvb, offset, 0, dmp.subj_id);
3811 PROTO_ITEM_SET_GENERATED (tf);
3812 hidden_item = proto_tree_add_uint (message_tree, hf_dmp_id, tvb, offset, 0, dmp.subj_id);
3813 PROTO_ITEM_SET_GENERATED (hidden_item);
3814 PROTO_ITEM_SET_HIDDEN (hidden_item);
3819 if (use_seq_ack_analysis) {
3820 register_dmp_id (pinfo, 0);
3823 proto_item_set_len (en, offset - boffset);
3825 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3827 offset = dissect_dmp_message (tvb, pinfo, dmp_tree, offset);
3828 } else if (dmp.msg_type == REPORT) {
3829 /* One or more Delivery Report or Non-Delivery Report Data */
3830 rep_len = tvb_reported_length (tvb);
3834 while (offset < rep_len) {
3835 offset = dissect_dmp_report (tvb, pinfo, dmp_tree, offset, &prev_rec_no, rep_no++);
3837 } else if (dmp.msg_type == NOTIF) {
3838 /* Notification Data */
3839 offset = dissect_dmp_notification (tvb, pinfo, dmp_tree, offset);
3845 static gint dissect_dmp_extensions (tvbuff_t *tvb, packet_info *pinfo _U_,
3846 proto_tree *dmp_tree, gint offset)
3848 proto_tree *exts_tree, *ext_tree, *hdr_tree;
3849 proto_item *exts_item, *en;
3850 guint8 ext_hdr, ext_length;
3851 gboolean more_extensions = TRUE;
3852 gint num_ext = 0, boffset = offset;
3854 exts_item = proto_tree_add_item (dmp_tree, hf_extensions, tvb, offset, -1, ENC_NA);
3855 exts_tree = proto_item_add_subtree (exts_item, ett_extensions);
3857 while (more_extensions) {
3858 /* Extensions Present */
3859 ext_hdr = tvb_get_guint8 (tvb, offset);
3860 more_extensions = (ext_hdr & 0x80);
3861 ext_length = (ext_hdr & 0x7F) + 1;
3863 en = proto_tree_add_none_format (exts_tree, hf_extension, tvb, offset, ext_length + 1,
3864 "Extension (#%d)", num_ext + 1);
3865 ext_tree = proto_item_add_subtree (en, ett_extension);
3867 en = proto_tree_add_none_format (ext_tree, hf_extension_header, tvb, offset, 1,
3868 "Extension Length: %u, More %s", ext_length,
3869 (ext_hdr & 0x80) ? "Present" : "Not present");
3870 hdr_tree = proto_item_add_subtree (en, ett_extension_header);
3871 proto_tree_add_item (hdr_tree, hf_extension_more, tvb, offset, 1, ENC_BIG_ENDIAN);
3872 proto_tree_add_item (hdr_tree, hf_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3875 proto_tree_add_item (ext_tree, hf_extension_data, tvb, offset, ext_length, ENC_NA);
3876 offset += ext_length;
3880 proto_item_append_text (exts_item, " (%d item%s)", num_ext, plurality (num_ext, "", "s"));
3881 proto_item_set_len (exts_item, offset - boffset);
3886 static int dissect_dmp (tvbuff_t *tvb, packet_info *pinfo,
3887 proto_tree *tree, void *data _U_)
3889 proto_tree *dmp_tree;
3891 guint16 checksum1 = 0, checksum2 = 1;
3892 gint length, offset = 0;
3893 gboolean retrans_or_dup_ack = FALSE;
3895 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DMP");
3896 col_clear (pinfo->cinfo, COL_INFO);
3898 /* Initialize global data structure */
3899 memset (&dmp, 0, sizeof (dmp));
3901 ti = proto_tree_add_item (tree, proto_dmp, tvb, offset, -1, ENC_NA);
3902 dmp_tree = proto_item_add_subtree (ti, ett_dmp);
3904 offset = dissect_dmp_envelope (tvb, pinfo, dmp_tree, offset);
3906 if (dmp.version > DMP_VERSION_2) {
3907 /* Unsupported DMP Version, no point to continue */
3908 col_add_fstr (pinfo->cinfo, COL_INFO, "Unsupported Version: %d", dmp.version);
3912 if (dmp.extensions) {
3913 offset = dissect_dmp_extensions (tvb, pinfo, dmp_tree, offset);
3916 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3917 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3919 offset = dissect_dmp_content (tvb, pinfo, dmp_tree, offset);
3920 } else if (dmp.msg_type == ACK) {
3921 offset = dissect_dmp_ack (tvb, pinfo, dmp_tree, offset);
3925 length = tvb_captured_length (tvb);
3926 checksum1 = crc16_x25_ccitt_tvb (tvb, length - 2);
3927 checksum2 = tvb_get_ntohs (tvb, offset);
3929 proto_tree_add_checksum(dmp_tree, tvb, offset, hf_checksum, hf_checksum_status, &ei_checksum_bad, pinfo, checksum1, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
3933 if (use_seq_ack_analysis) {
3934 dmp_add_seq_ack_analysis (tvb, pinfo, dmp_tree, offset);
3937 if (((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3938 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) &&
3939 dmp.id_val && dmp.id_val->msg_resend_count)
3942 if (dmp.msg_type == REPORT) {
3943 retrans_num = dmp.id_val->rep_id;
3944 } else if (dmp.msg_type == NOTIF) {
3945 retrans_num = dmp.id_val->not_id;
3947 retrans_num = dmp.id_val->msg_id;
3949 col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ",
3950 retrans_num, dmp.id_val->msg_resend_count);
3951 retrans_or_dup_ack = TRUE;
3952 } else if (dmp.msg_type == ACK && dmp.id_val && dmp.id_val->ack_resend_count) {
3953 col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ",
3954 dmp.id_val->ack_id, dmp.id_val->ack_resend_count);
3955 retrans_or_dup_ack = TRUE;
3957 if (dmp_align && !retrans_or_dup_ack) {
3958 if (dmp.msg_type == ACK) {
3959 /* ACK does not have "Msg Id" */
3960 col_append_fstr (pinfo->cinfo, COL_INFO, "%-45.45s", msg_type_to_str ());
3962 col_append_fstr (pinfo->cinfo, COL_INFO, "%-31.31s", msg_type_to_str ());
3965 col_append_str (pinfo->cinfo, COL_INFO, msg_type_to_str ());
3967 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3968 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3970 if (dmp_align && !retrans_or_dup_ack) {
3971 col_append_fstr (pinfo->cinfo, COL_INFO, " Msg Id: %5d", dmp.msg_id);
3973 col_append_fstr (pinfo->cinfo, COL_INFO, ", Msg Id: %d", dmp.msg_id);
3976 if ((dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF) ||
3977 (dmp.msg_type == ACK))
3979 if (dmp_align && !retrans_or_dup_ack) {
3980 col_append_fstr (pinfo->cinfo, COL_INFO, " Subj Id: %5d",
3983 col_append_fstr (pinfo->cinfo, COL_INFO, ", Subj Id: %d",
3987 if (dmp.checksum && (checksum1 != checksum2)) {
3988 col_append_str (pinfo->cinfo, COL_INFO, ", Checksum incorrect");
3991 proto_item_append_text (ti, ", Version: %d%s, %s", dmp.version,
3992 (dmp.prot_id == PROT_NAT ? " (national)" : ""),
3998 static void dmp_init_routine (void)
4000 dmp_id_hash_table = g_hash_table_new (dmp_id_hash, dmp_id_hash_equal);
4001 dmp_long_id_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
4004 static void dmp_cleanup_routine (void)
4006 g_hash_table_destroy(dmp_id_hash_table);
4007 g_hash_table_destroy(dmp_long_id_hash_table);
4010 void proto_register_dmp (void)
4012 static hf_register_info hf[] = {
4017 { "DMP Identifier", "dmp.id", FT_UINT16, BASE_DEC,
4018 NULL, 0x0, NULL, HFILL} },
4020 /* MTS Identifier */
4022 { "MTS Identifier", "dmp.mts", FT_STRING, BASE_NONE,
4023 NULL, 0x0, NULL, HFILL } },
4025 /* IPM Identifier */
4027 { "IPM Identifier", "dmp.ipm", FT_STRING, BASE_NONE,
4028 NULL, 0x0, NULL, HFILL } },
4034 { "Envelope", "dmp.envelope", FT_NONE, BASE_NONE,
4035 NULL, 0x0, NULL, HFILL} },
4038 { &hf_envelope_protocol_id,
4039 { "Protocol Identifier", "dmp.protocol_id", FT_UINT8,
4040 BASE_HEX, NULL, 0xF8, NULL, HFILL} },
4041 { &hf_envelope_version,
4042 { "Protocol Version", "dmp.version", FT_UINT8, BASE_DEC,
4043 VALS(version_vals), 0x07, NULL, HFILL } },
4044 { &hf_envelope_version_value,
4045 { "Protocol Version", "dmp.version_value", FT_UINT8, BASE_DEC,
4046 VALS(version_vals), 0x07, NULL, HFILL } },
4048 /* Envelope elements (byte 1) */
4049 { &hf_envelope_hop_count,
4050 { "Hop Count", "dmp.hop_count", FT_UINT8, BASE_DEC,
4051 NULL, 0xE0, NULL, HFILL } },
4052 { &hf_envelope_hop_count_value,
4053 { "Hop Count", "dmp.hop_count_value", FT_UINT8, BASE_DEC,
4054 NULL, 0xE0, NULL, HFILL } },
4055 { &hf_envelope_rec_present,
4056 { "Recipient Present", "dmp.rec_present", FT_BOOLEAN, 8,
4057 TFS (&tfs_present_absent), 0x20, NULL, HFILL } },
4058 { &hf_envelope_addr_enc,
4059 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4060 TFS (&addr_enc), 0x10, NULL, HFILL } },
4061 { &hf_envelope_checksum,
4062 { "Checksum", "dmp.checksum_used", FT_BOOLEAN, 8,
4063 TFS (&tfs_used_notused), 0x08, "Checksum Used", HFILL } },
4064 { &hf_envelope_type,
4065 { "Content Type", "dmp.content_type", FT_UINT8, BASE_DEC,
4066 VALS(type_vals), 0x07, NULL, HFILL } },
4068 /* Envelope elements (byte 2) */
4069 { &hf_envelope_extensions,
4070 { "Extensions", "dmp.extensions_used", FT_BOOLEAN, 8,
4071 TFS (&tfs_present_absent), 0x80, "Extensions Used", HFILL } },
4072 { &hf_envelope_msg_id_type,
4073 { "Message Identifier Type", "dmp.msg_id_type", FT_UINT8, BASE_DEC,
4074 VALS(msg_id_type_vals), 0x60, NULL, HFILL } },
4075 { &hf_envelope_msg_id_length,
4076 { "Message Identifier Length", "dmp.msg_id_short", FT_UINT8, BASE_DEC,
4077 VALS(msg_id_length_vals), 0x10, NULL, HFILL} },
4078 { &hf_envelope_mts_id_length,
4079 { "MTS Identifier Length", "dmp.mts_id_length", FT_UINT8, BASE_DEC,
4080 NULL, 0x1F, NULL, HFILL } },
4081 { &hf_envelope_ipm_id_modifier,
4082 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4083 VALS(ipm_id_modifier), 0xC0, NULL, HFILL } },
4084 { &hf_envelope_ipm_id_length,
4085 { "IPM Identifier Length", "dmp.ipm_id_length", FT_UINT8, BASE_DEC,
4086 NULL, 0x3F, NULL, HFILL } },
4088 { &hf_thales_ipm_id_modifier,
4089 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4090 VALS(thales_ipm_id_modifier), 0xC0, "Thales XOmail IPM Identifier Modifier", HFILL } },
4092 /* Message identifier */
4093 { &hf_envelope_msg_id,
4094 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4095 NULL, 0x0, NULL, HFILL} },
4096 { &hf_envelope_msg_id_12bit,
4097 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4098 NULL, 0x0FFF, NULL, HFILL} },
4100 /* MTS Identifier */
4101 { &hf_envelope_mts_id,
4102 { "MTS Identifier", "dmp.mts_id", FT_STRING, BASE_NONE,
4103 NULL, 0x0, NULL, HFILL } },
4105 /* IPM Identifier */
4106 { &hf_envelope_ipm_id,
4107 { "IPM Identifier", "dmp.ipm_id", FT_STRING, BASE_NONE,
4108 NULL, 0x0, NULL, HFILL } },
4112 { "Extensions", "dmp.extensions", FT_NONE, BASE_NONE,
4113 NULL, 0x0, NULL, HFILL} },
4115 { "Extension", "dmp.extension", FT_NONE, BASE_NONE,
4116 NULL, 0x0, NULL, HFILL } },
4117 { &hf_extension_header,
4118 { "Extension Header", "dmp.extension_header", FT_NONE, BASE_NONE,
4119 NULL, 0x0, NULL, HFILL} },
4120 { &hf_extension_more,
4121 { "More Extensions", "dmp.extension_more", FT_BOOLEAN, 8,
4122 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4123 { &hf_extension_length,
4124 { "Extension Length (minus one)", "dmp.extension_length", FT_UINT8, BASE_DEC,
4125 NULL, 0x7F, "Extension Length minus one", HFILL } },
4126 { &hf_extension_data,
4127 { "Extension Data", "dmp.extension_data", FT_BYTES, BASE_NONE,
4128 NULL, 0x0, NULL, HFILL } },
4130 /* Submission time */
4131 { &hf_envelope_subm_time,
4132 { "Submission Time", "dmp.subm_time", FT_UINT16, BASE_HEX,
4133 NULL, 0x0, NULL, HFILL } },
4134 { &hf_envelope_time_diff_present,
4135 { "Time Diff", "dmp.time_diff_present", FT_BOOLEAN, 16,
4136 TFS (&tfs_present_absent), 0x8000, "Time Diff Present", HFILL } },
4137 { &hf_envelope_subm_time_value,
4138 { "Submission Time Value", "dmp.subm_time_value", FT_UINT16,
4139 BASE_HEX, NULL, 0x7FFF, NULL, HFILL } },
4140 { &hf_envelope_time_diff,
4141 { "Time Difference", "dmp.time_diff", FT_UINT8, BASE_HEX,
4142 NULL, 0xFF, NULL, HFILL } },
4143 { &hf_envelope_time_diff_value,
4144 { "Time Difference Value", "dmp.time_diff_value", FT_UINT8,
4145 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4147 /* Envelope flags */
4148 { &hf_envelope_flags,
4149 { "Flags", "dmp.envelope_flags", FT_UINT8, BASE_DEC,
4150 NULL, 0x0, "Envelope Flags", HFILL} },
4151 { &hf_envelope_content_id_discarded,
4152 { "Content Identifier discarded", "dmp.cont_id_discarded",
4153 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
4155 { &hf_envelope_recip_reassign_prohib,
4156 { "Recipient reassign prohibited","dmp.recip_reassign_prohib",
4157 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
4159 { &hf_envelope_dl_expansion_prohib,
4160 { "DL expansion prohibited", "dmp.dl_expansion_prohib",
4161 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL,
4164 /* Recipient Count */
4165 { &hf_envelope_recipients,
4166 { "Recipient Count", "dmp.rec_count", FT_UINT8, BASE_DEC,
4167 NULL, 0x1F, NULL, HFILL} },
4168 { &hf_envelope_ext_recipients,
4169 { "Extended Recipient Count", "dmp.ext_rec_count", FT_UINT16,
4170 BASE_DEC, NULL, 0x7FFF, NULL, HFILL} },
4175 { &hf_addr_recipient,
4176 { "Recipient Number", "dmp.recipient", FT_NONE, BASE_NONE,
4177 NULL, 0x0, "Recipient", HFILL } },
4178 { &hf_addr_originator,
4179 { "Originator", "dmp.originator", FT_NONE, BASE_NONE,
4180 NULL, 0x0, NULL, HFILL } },
4181 { &hf_addr_reporting_name,
4182 { "Reporting Name Number", "dmp.reporting_name", FT_NONE,
4183 BASE_NONE, NULL, 0x0, "Reporting Name", HFILL } },
4184 { &hf_addr_dl_expanded,
4185 { "DL Expanded", "dmp.dl_expanded", FT_BOOLEAN, BASE_NONE,
4186 NULL, 0x0, "Message has been DL expanded", HFILL } },
4188 { "Intended Recipient", "dmp.int_rec", FT_BOOLEAN, BASE_NONE,
4189 NULL, 0x0, "Message has an intended recipient", HFILL } },
4194 { &hf_addr_dir_addr_ext,
4195 { "Address Extended", "dmp.addr_ext", FT_BOOLEAN, 8,
4196 NULL, 0x80, NULL, HFILL } },
4197 { &hf_addr_dir_rec_no,
4198 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4199 BASE_DEC, NULL, 0xF0, NULL, HFILL } },
4200 { &hf_addr_dir_rec_no_generated,
4201 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4202 BASE_DEC, NULL, 0x0, "Recipient Number Offset", HFILL } },
4203 { &hf_addr_dir_rec_no1,
4204 { "Recipient Number (bits 3-0)", "dmp.rec_no_offset1", FT_UINT8,
4205 BASE_DEC, NULL, 0xF0, "Recipient Number (bits 3-0) Offset", HFILL } },
4206 { &hf_addr_dir_rec_no2,
4207 { "Recipient Number (bits 9-4)", "dmp.rec_no_offset2", FT_UINT8,
4208 BASE_DEC, NULL, 0x3F, "Recipient Number (bits 9-4) Offset", HFILL } },
4209 { &hf_addr_dir_rec_no3,
4210 { "Recipient Number (bits 14-10)", "dmp.rec_no_offset3", FT_UINT8,
4211 BASE_DEC, NULL, 0x1F, "Recipient Number (bits 14-10) Offset",HFILL } },
4212 { &hf_addr_dir_rep_req1,
4213 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4214 VALS (report_vals_ext), 0x0C, NULL, HFILL } },
4215 { &hf_addr_dir_rep_req2,
4216 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4217 VALS (report_vals_ext), 0xC0, NULL, HFILL } },
4218 { &hf_addr_dir_rep_req3,
4219 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4220 VALS (report_vals), 0xC0, NULL, HFILL } },
4221 { &hf_addr_dir_not_req1,
4222 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4223 VALS (notif_vals_ext), 0x03, NULL, HFILL } },
4224 { &hf_addr_dir_not_req2,
4225 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4226 VALS (notif_vals_ext), 0xC0, NULL, HFILL } },
4227 { &hf_addr_dir_not_req3,
4228 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4229 VALS (notif_vals), 0xC0, NULL, HFILL } },
4230 { &hf_addr_dir_action,
4231 { "Action", "dmp.action", FT_BOOLEAN, 8,
4232 TFS (&tfs_yes_no), 0x80, NULL, HFILL } },
4233 { &hf_addr_dir_address,
4234 { "Direct Address", "dmp.direct_addr", FT_UINT8,
4235 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4236 { &hf_addr_dir_address_generated,
4237 { "Direct Address", "dmp.direct_addr", FT_UINT32,
4238 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4239 { &hf_addr_dir_address1,
4240 { "Direct Address (bits 6-0)", "dmp.direct_addr1", FT_UINT8,
4241 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4242 { &hf_addr_dir_address2,
4243 { "Direct Address (bits 12-7)", "dmp.direct_addr2", FT_UINT8,
4244 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4245 { &hf_addr_dir_address3,
4246 { "Direct Address (bits 18-13)", "dmp.direct_addr3", FT_UINT8,
4247 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4252 { &hf_addr_ext_form,
4253 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4254 VALS (addr_form), 0xE0, NULL, HFILL } },
4255 { &hf_addr_ext_form_orig_v1,
4256 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4257 VALS (addr_form_orig_v1), 0xE0, NULL, HFILL } },
4258 { &hf_addr_ext_form_orig,
4259 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4260 VALS (addr_form_orig), 0xE0, NULL, HFILL } },
4261 { &hf_addr_ext_action,
4262 { "Action", "dmp.action", FT_BOOLEAN, 8,
4263 TFS (&tfs_yes_no), 0x10, NULL, HFILL } },
4264 { &hf_addr_ext_rep_req,
4265 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4266 VALS (report_vals), 0x0C, NULL, HFILL } },
4267 { &hf_addr_ext_not_req,
4268 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4269 VALS (notif_vals), 0x03, NULL, HFILL } },
4270 { &hf_addr_ext_rec_ext,
4271 { "Recipient Number Extended", "dmp.rec_no_ext", FT_BOOLEAN, 8,
4272 NULL, 0x80, NULL, HFILL } },
4273 { &hf_addr_ext_rec_no,
4274 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4275 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4276 { &hf_addr_ext_rec_no_generated,
4277 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4278 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4279 { &hf_addr_ext_rec_no1,
4280 { "Recipient Number (bits 6-0)", "dmp.rec_no_offset1", FT_UINT8,
4281 BASE_DEC, NULL, 0x7F, "Recipient Number (bits 6-0) Offset", HFILL } },
4282 { &hf_addr_ext_rec_no2,
4283 { "Recipient Number (bits 14-7)", "dmp.rec_no_offset2", FT_UINT8,
4284 BASE_DEC, NULL, 0xFF, "Recipient Number (bits 14-7) Offset", HFILL } },
4285 { &hf_addr_ext_address,
4286 { "Extended Address", "dmp.addr_form_ext", FT_NONE, BASE_NONE,
4287 NULL, 0x0, NULL, HFILL } },
4288 { &hf_addr_ext_type,
4289 { "Address Type", "dmp.addr_type", FT_UINT8, BASE_DEC,
4290 VALS (ext_addr_type), 0xE0, NULL, HFILL } },
4291 { &hf_addr_ext_type_ext,
4292 { "Address Type Extended", "dmp.addr_type_ext", FT_UINT8,
4293 BASE_DEC, VALS (ext_addr_type_ext), 0xE0, NULL,
4295 { &hf_addr_ext_length,
4296 { "Address Length", "dmp.addr_length", FT_UINT8,
4297 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4298 { &hf_addr_ext_length_generated,
4299 { "Address Length", "dmp.addr_length", FT_UINT32,
4300 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4301 { &hf_addr_ext_length1,
4302 { "Address Length (bits 4-0)", "dmp.addr_length1", FT_UINT8,
4303 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4304 { &hf_addr_ext_length2,
4305 { "Address Length (bits 9-5)", "dmp.addr_length2", FT_UINT8,
4306 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4307 { &hf_addr_ext_asn1_ber,
4308 { "ASN.1 BER-encoded OR-name", "dmp.or_name", FT_NONE,
4309 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4310 { &hf_addr_ext_asn1_per,
4311 { "ASN.1 PER-encoded OR-name", "dmp.asn1_per", FT_BYTES,
4312 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4313 { &hf_addr_ext_unknown,
4314 { "Unknown encoded address", "dmp.addr_unknown", FT_BYTES,
4315 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4320 { &hf_message_content,
4321 { "Message Content", "dmp.message", FT_NONE, BASE_NONE,
4322 NULL, 0x0, NULL, HFILL } },
4323 { &hf_report_content,
4324 { "Report Content", "dmp.report", FT_NONE, BASE_NONE,
4325 NULL, 0x0, NULL, HFILL } },
4326 { &hf_notif_content,
4327 { "Notification Content", "dmp.notification", FT_NONE, BASE_NONE,
4328 NULL, 0x0, NULL, HFILL } },
4330 { &hf_message_st_type,
4331 { "Message type", "dmp.msg_type", FT_UINT8, BASE_DEC,
4332 VALS (message_type_vals), 0xC0, NULL, HFILL } },
4333 { &hf_message_precedence,
4334 { "Precedence", "dmp.precedence", FT_UINT8, BASE_DEC,
4335 VALS (precedence), 0x1C, NULL, HFILL } },
4336 { &hf_message_importance,
4337 { "Importance", "dmp.importance", FT_UINT8, BASE_DEC,
4338 VALS (importance), 0x1C, NULL, HFILL } },
4339 { &hf_message_body_format,
4340 { "Body format", "dmp.body_format", FT_UINT8, BASE_DEC,
4341 VALS (body_format_vals), 0x03, NULL, HFILL } },
4343 /* Security Values */
4344 { &hf_message_sec_label,
4345 { "Security Label", "dmp.sec_label", FT_STRING, BASE_NONE,
4346 NULL, 0x0, NULL, HFILL } },
4347 { &hf_message_sec_class_val,
4348 { "Security Classification", "dmp.sec_class", FT_UINT8,
4349 BASE_DEC, NULL, 0xE0, NULL, HFILL} },
4350 { &hf_message_sec_pol,
4351 { "Security Policy", "dmp.sec_pol", FT_UINT8, BASE_DEC,
4352 VALS (sec_pol), 0x1C, NULL, HFILL } },
4353 { &hf_message_heading_flags,
4354 { "Heading Flags", "dmp.heading_flags", FT_NONE, BASE_NONE,
4355 NULL, 0x0, NULL, HFILL } },
4356 { &hf_message_auth_users,
4357 { "Authorizing users discarded", "dmp.auth_discarded",
4358 FT_BOOLEAN, 8, TFS (&tfs_yes_no), 0x02,
4360 { &hf_message_subject_disc,
4361 { "Subject discarded", "dmp.subject_discarded", FT_BOOLEAN, 8,
4362 TFS (&tfs_yes_no), 0x01, NULL, HFILL } },
4364 /* National Policy Identifier */
4365 { &hf_message_national_policy_id,
4366 { "National Policy Identifier", "dmp.nat_pol_id", FT_UINT8,
4367 BASE_DEC, VALS(nat_pol_id), 0x0, NULL,
4370 /* Mission Policy Identifier */
4371 { &hf_message_mission_policy_id,
4372 { "Mission Policy Identifier", "dmp.mission_pol_id", FT_UINT8,
4373 BASE_DEC, NULL, 0x0, NULL,
4376 /* Security Categories */
4377 { &hf_message_sec_cat_nat,
4378 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4379 NULL, 0x0, NULL, HFILL } },
4380 { &hf_message_sec_cat_val,
4381 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4382 NULL, 0x0, NULL, HFILL } },
4383 { &hf_message_sec_cat_cl,
4384 { "Clear", "dmp.sec_cat.cl", FT_BOOLEAN, 8,
4385 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4386 { &hf_message_sec_cat_cs,
4387 { "Crypto Security", "dmp.sec_cat.cs", FT_BOOLEAN, 8,
4388 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4389 { &hf_message_sec_cat_ex,
4390 { "Exclusive", "dmp.sec_cat.ex", FT_BOOLEAN, 8,
4391 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4392 { &hf_message_sec_cat_ne,
4393 { "National Eyes Only", "dmp.sec_cat.ne", FT_BOOLEAN, 8,
4394 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4395 { &hf_message_sec_cat_permissive,
4396 { "Releasable to", "dmp.sec_cat.permissive", FT_UINT8, BASE_HEX,
4397 VALS (nat_pol_id), 0xFC, NULL, HFILL } },
4398 { &hf_message_sec_cat_country_code,
4399 { "Country Code", "dmp.sec_cat.country", FT_UINT8, BASE_DEC,
4400 NULL, 0x00, NULL, HFILL } },
4401 { &hf_message_sec_cat_restrictive,
4402 { "Restrictive", "dmp.sec_cat.restrictive", FT_UINT8, BASE_HEX,
4403 NULL, 0xFC, NULL, HFILL } },
4404 { &hf_message_sec_cat_extended,
4405 { "Extended", "dmp.sec_cat.extended", FT_UINT8, BASE_HEX,
4406 VALS (ext_sec_cat), 0x03, "Extended Security Category", HFILL } },
4407 { &hf_message_sec_cat_bit0,
4408 { "Bit 0", "dmp.sec_cat.bit0", FT_BOOLEAN, 8,
4409 TFS (&tfs_set_notset), 0x01, NULL, HFILL } },
4410 { &hf_message_sec_cat_bit1,
4411 { "Bit 1", "dmp.sec_cat.bit1", FT_BOOLEAN, 8,
4412 TFS (&tfs_set_notset), 0x02, NULL, HFILL } },
4413 { &hf_message_sec_cat_bit2,
4414 { "Bit 2", "dmp.sec_cat.bit2", FT_BOOLEAN, 8,
4415 TFS (&tfs_set_notset), 0x04, NULL, HFILL } },
4416 { &hf_message_sec_cat_bit3,
4417 { "Bit 3", "dmp.sec_cat.bit3", FT_BOOLEAN, 8,
4418 TFS (&tfs_set_notset), 0x08, NULL, HFILL } },
4419 { &hf_message_sec_cat_bit4,
4420 { "Bit 4", "dmp.sec_cat.bit4", FT_BOOLEAN, 8,
4421 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4422 { &hf_message_sec_cat_bit5,
4423 { "Bit 5", "dmp.sec_cat.bit5", FT_BOOLEAN, 8,
4424 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4425 { &hf_message_sec_cat_bit6,
4426 { "Bit 6", "dmp.sec_cat.bit6", FT_BOOLEAN, 8,
4427 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4428 { &hf_message_sec_cat_bit7,
4429 { "Bit 7", "dmp.sec_cat.bit7", FT_BOOLEAN, 8,
4430 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4433 { &hf_message_exp_time,
4434 { "Expiry Time", "dmp.expiry_time", FT_UINT8, BASE_HEX,
4435 NULL, 0x0, NULL, HFILL } },
4436 { &hf_message_exp_time_val,
4437 { "Expiry Time Value", "dmp.expiry_time_val", FT_UINT8, BASE_HEX,
4438 NULL, 0xFF, NULL, HFILL } },
4442 { "DTG", "dmp.dtg", FT_UINT8, BASE_HEX,
4443 NULL, 0xFF, NULL, HFILL } },
4444 { &hf_message_dtg_sign,
4445 { "DTG in the", "dmp.dtg.sign", FT_BOOLEAN, 8, TFS (&dtg_sign),
4446 0x80, "Sign", HFILL } },
4447 { &hf_message_dtg_val,
4448 { "DTG Value", "dmp.dtg.val", FT_UINT8, BASE_HEX, NULL,
4449 0x7F, NULL, HFILL } },
4453 { "SIC", "dmp.sic", FT_STRING, BASE_NONE,
4454 NULL, 0x0, NULL, HFILL } },
4455 { &hf_message_sic_key,
4456 { "SICs", "dmp.sic_key", FT_NONE, BASE_NONE,
4457 NULL, 0x0, "SIC Content", HFILL } },
4458 { &hf_message_sic_key_values,
4459 { "Content Byte", "dmp.sic_key.values", FT_UINT8, BASE_HEX,
4460 NULL, 0x0, "SIC Content Byte", HFILL } },
4461 { &hf_message_sic_key_type,
4462 { "Type", "dmp.sic_key.type", FT_UINT8, BASE_HEX,
4463 VALS (sic_key_type), 0xF0, "SIC Content Type", HFILL } },
4464 { &hf_message_sic_key_chars,
4465 { "Valid Characters", "dmp.sic_key.chars", FT_BOOLEAN, 8,
4466 TFS (&sic_key_chars), 0x08, "SIC Valid Characters", HFILL } },
4467 { &hf_message_sic_key_num,
4468 { "Number of SICs", "dmp.sic_key.num", FT_UINT8, BASE_HEX,
4469 VALS (sic_key_num), 0x07, NULL, HFILL } },
4470 { &hf_message_sic_bitmap,
4471 { "Length Bitmap (0 = 3 bytes, 1 = 4-8 bytes)", "dmp.sic_bitmap",
4472 FT_UINT8, BASE_HEX, NULL, 0xFF, "SIC Length Bitmap", HFILL } },
4473 { &hf_message_sic_bits,
4474 { "Bit 7-4", "dmp.sic_bits", FT_UINT8, BASE_HEX,
4475 VALS(sic_bit_vals), 0xF0, "SIC Bit 7-4, Characters [A-Z0-9] only",
4477 { &hf_message_sic_bits_any,
4478 { "Bit 7-4", "dmp.sic_bits_any", FT_UINT8, BASE_HEX,
4479 VALS(sic_bit_any_vals), 0xF0, "SIC Bit 7-4, Any valid characters",
4482 /* Subject Message Id */
4483 { &hf_message_subj_id,
4484 { "Subject Message Identifier", "dmp.subj_id", FT_UINT16,
4485 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4487 /* Subject MTS Identifier */
4488 { &hf_message_subj_mts_id,
4489 { "Subject MTS Identifier", "dmp.subj_mts_id", FT_STRING, BASE_NONE,
4490 NULL, 0x0, NULL, HFILL } },
4492 /* Subject IPM Identifier */
4493 { &hf_message_subj_ipm_id,
4494 { "Subject IPM Identifier", "dmp.subj_ipm_id", FT_STRING, BASE_NONE,
4495 NULL, 0x0, NULL, HFILL } },
4501 { "Message Body", "dmp.body", FT_NONE, BASE_NONE, NULL,
4502 0x0, NULL, HFILL} },
4506 { "EIT", "dmp.body.eit", FT_UINT8, BASE_DEC,
4507 VALS(eit_vals), 0xE0, "Encoded Information Type", HFILL } },
4508 { &hf_message_compr,
4509 { "Compression", "dmp.body.compression", FT_UINT8, BASE_DEC,
4510 VALS(compression_vals), 0x18, NULL, HFILL } },
4513 { &hf_message_subject,
4514 { "Subject", "dmp.subject", FT_STRINGZ, BASE_NONE,
4515 NULL, 0x0, NULL, HFILL } },
4518 { &hf_message_body_data,
4519 { "User data", "dmp.body.data", FT_BYTES, BASE_NONE,
4520 NULL, 0x0, NULL, HFILL } },
4521 { &hf_message_body_compressed,
4522 { "Compressed User data", "dmp.body.compressed", FT_NONE, BASE_NONE,
4523 NULL, 0x0, NULL, HFILL } },
4524 { &hf_message_body_plain,
4525 { "Message Body", "dmp.body.plain", FT_STRING, BASE_NONE,
4526 NULL, 0x0, NULL, HFILL } },
4527 { &hf_message_body_structured,
4528 { "Structured Body", "dmp.body.structured", FT_BYTES, BASE_NONE,
4529 NULL, 0x0, NULL, HFILL } },
4534 { &hf_delivery_report,
4535 { "Delivery Report", "dmp.dr", FT_NONE, BASE_NONE, NULL,
4536 0x0, NULL, HFILL} },
4537 { &hf_non_delivery_report,
4538 { "Non-Delivery Report", "dmp.ndr", FT_NONE, BASE_NONE, NULL,
4539 0x0, NULL, HFILL} },
4542 { "Report Type", "dmp.report_type", FT_BOOLEAN, 8,
4543 TFS (&report_type), 0x80, NULL, HFILL } },
4544 { &hf_report_info_present_dr,
4545 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4546 TFS (&tfs_present_absent), 0x40, NULL, HFILL } },
4547 { &hf_report_addr_enc_dr,
4548 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4549 TFS (&addr_enc), 0x20, NULL, HFILL } },
4550 { &hf_report_del_time,
4551 { "Delivery Time", "dmp.delivery_time", FT_UINT8, BASE_HEX,
4552 NULL, 0x0, NULL, HFILL } },
4553 { &hf_report_del_time_val,
4554 { "Delivery Time Value", "dmp.delivery_time_val", FT_UINT8,
4555 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4556 { &hf_report_addr_enc_ndr,
4557 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4558 TFS (&addr_enc), 0x40, NULL, HFILL } },
4559 { &hf_report_reason,
4560 { "Reason (P1)", "dmp.report_reason", FT_UINT8, BASE_DEC,
4561 VALS (p1_NonDeliveryReasonCode_vals), 0x3F,
4562 "Reason", HFILL } },
4563 { &hf_report_info_present_ndr,
4564 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4565 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4567 { "Diagnostic (P1)", "dmp.report_diagnostic", FT_UINT8, BASE_DEC,
4568 VALS (p1_NonDeliveryDiagnosticCode_vals), 0x7F,
4569 "Diagnostic", HFILL } },
4570 { &hf_report_suppl_info_len,
4571 { "Supplementary Information", "dmp.suppl_info_len", FT_UINT8,
4572 BASE_DEC, NULL, 0x0, "Supplementary Information Length", HFILL } },
4573 { &hf_report_suppl_info,
4574 { "Supplementary Information", "dmp.suppl_info", FT_STRINGZ,
4575 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4580 { &hf_receipt_notif,
4581 { "Receipt Notification (RN)", "dmp.rn", FT_NONE, BASE_NONE,
4582 NULL, 0x0, NULL, HFILL} },
4583 { &hf_non_receipt_notif,
4584 { "Non-Receipt Notification (NRN)", "dmp.nrn", FT_NONE, BASE_NONE,
4585 NULL, 0x0, NULL, HFILL} },
4587 { "Other Notification (ON)", "dmp.on", FT_NONE, BASE_NONE,
4588 NULL, 0x0, NULL, HFILL} },
4591 { "Notification Type", "dmp.notif_type", FT_UINT8, BASE_DEC,
4592 VALS (notif_type), 0x03, NULL, HFILL } },
4593 { &hf_notif_rec_time,
4594 { "Receipt Time", "dmp.receipt_time", FT_UINT8, BASE_HEX,
4595 NULL, 0x0, NULL, HFILL } },
4596 { &hf_notif_rec_time_val,
4597 { "Receipt Time Value", "dmp.receipt_time_val", FT_UINT8,
4598 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4599 { &hf_notif_suppl_info_len,
4600 { "Supplementary Information", "dmp.suppl_info_len",
4601 FT_UINT8, BASE_DEC, NULL, 0x0, "Supplementary Information Length",
4603 { &hf_notif_suppl_info,
4604 { "Supplementary Information", "dmp.suppl_info",
4605 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL,
4607 { &hf_notif_non_rec_reason,
4608 { "Non-Receipt Reason", "dmp.notif_non_rec_reason",
4609 FT_UINT8, BASE_DEC, VALS (p22_NonReceiptReasonField_vals), 0x0,
4611 { &hf_notif_discard_reason,
4612 { "Discard Reason", "dmp.notif_discard_reason", FT_UINT8,
4613 BASE_DEC, VALS (p22_DiscardReasonField_vals), 0x0,
4615 { &hf_notif_on_type,
4616 { "ON Type", "dmp.notif_on_type", FT_UINT8, BASE_DEC,
4617 VALS (on_type), 0x0, NULL, HFILL } },
4619 { "ACP127 Recipient", "dmp.acp127recip_len", FT_UINT8,
4620 BASE_DEC, NULL, 0x0, "ACP 127 Recipient Length", HFILL } },
4621 { &hf_notif_acp127recip,
4622 { "ACP127 Recipient", "dmp.acp127recip", FT_STRINGZ,
4623 BASE_NONE, NULL, 0x0, "ACP 127 Recipient", HFILL } },
4629 { "Acknowledgement", "dmp.ack", FT_NONE, BASE_NONE,
4630 NULL, 0x0, NULL, HFILL } },
4632 { "Ack Reason", "dmp.ack_reason", FT_UINT8, BASE_DEC,
4633 VALS (ack_reason), 0x0, "Reason", HFILL } },
4634 { &hf_ack_diagnostic,
4635 { "Ack Diagnostic", "dmp.ack_diagnostic", FT_UINT8, BASE_DEC,
4636 NULL, 0x0, "Diagnostic", HFILL } },
4638 { "Recipient List", "dmp.ack_rec_list", FT_NONE, BASE_NONE,
4639 NULL, 0x0, NULL, HFILL } },
4645 { "Checksum", "dmp.checksum", FT_UINT16, BASE_HEX,
4646 NULL, 0x0, NULL, HFILL } },
4647 { &hf_checksum_status,
4648 { "Checksum Status", "dmp.checksum.status", FT_UINT8, BASE_NONE,
4649 VALS(proto_checksum_vals), 0x0, NULL, HFILL } },
4652 ** Ack matching / Resend
4654 { &hf_analysis_ack_time,
4655 { "Acknowledgement Time", "dmp.analysis.ack_time", FT_RELATIVE_TIME, BASE_NONE,
4656 NULL, 0x0, "The time between the Message and the Acknowledge", HFILL } },
4657 { &hf_analysis_rep_time,
4658 { "Report Reply Time", "dmp.analysis.report_time", FT_RELATIVE_TIME, BASE_NONE,
4659 NULL, 0x0, "The time between the Message and the Report", HFILL } },
4660 { &hf_analysis_not_time,
4661 { "Notification Reply Time", "dmp.analysis.notif_time", FT_RELATIVE_TIME, BASE_NONE,
4662 NULL, 0x0, "The time between the Message and the Notification", HFILL } },
4663 { &hf_analysis_total_time,
4664 { "Total Time", "dmp.analysis.total_time", FT_RELATIVE_TIME, BASE_NONE,
4665 NULL, 0x0, "The time between the first Message and the Acknowledge", HFILL } },
4666 { &hf_analysis_retrans_time,
4667 { "Retransmission Time", "dmp.analysis.retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4668 NULL, 0x0, "The time between the last Message and this Message", HFILL } },
4669 { &hf_analysis_total_retrans_time,
4670 { "Total Retransmission Time", "dmp.analysis.total_retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4671 NULL, 0x0, "The time between the first Message and this Message", HFILL } },
4672 { &hf_analysis_msg_num,
4673 { "Message in", "dmp.analysis.msg_in", FT_FRAMENUM, BASE_NONE,
4674 NULL, 0x0, "This packet has a Message in this frame", HFILL } },
4675 { &hf_analysis_acks_msg_num,
4676 { "This is an Ack to the Message in", "dmp.analysis.acks_msg_in", FT_FRAMENUM, BASE_NONE,
4677 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Message in this frame", HFILL } },
4678 { &hf_analysis_ack_num,
4679 { "Acknowledgement in", "dmp.analysis.ack_in", FT_FRAMENUM, BASE_NONE,
4680 NULL, 0x0, "This packet has an Acknowledgement in this frame", HFILL } },
4681 { &hf_analysis_acks_rep_num,
4682 { "This is an Ack to the Report in", "dmp.analysis.acks_report_in", FT_FRAMENUM, BASE_NONE,
4683 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Report in this frame", HFILL } },
4685 { &hf_analysis_rep_num,
4686 { "Report in", "dmp.analysis.report_in", FT_FRAMENUM, BASE_NONE,
4687 NULL, 0x0, "This packet has a Report in this frame", HFILL } },
4688 { &hf_analysis_not_num,
4689 { "Notification in", "dmp.analysis.notif_in", FT_FRAMENUM, BASE_NONE,
4690 NULL, 0x0, "This packet has a Notification in this frame", HFILL } },
4692 { &hf_analysis_acks_not_num,
4693 { "This is an Ack to the Notification in", "dmp.analysis.acks_notif_in", FT_FRAMENUM, BASE_NONE,
4694 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Notification in this frame", HFILL } },
4695 { &hf_analysis_ack_missing,
4696 { "Acknowledgement missing", "dmp.analysis.ack_missing", FT_NONE, BASE_NONE,
4697 NULL, 0x0, "The acknowledgement for this packet is missing", HFILL } },
4698 { &hf_analysis_retrans_no,
4699 { "Retransmission #", "dmp.analysis.retrans_no", FT_UINT32, BASE_DEC,
4700 NULL, 0x0, "Retransmission count", HFILL } },
4701 { &hf_analysis_ack_dup_no,
4702 { "Duplicate ACK #", "dmp.analysis.dup_ack_no", FT_UINT32, BASE_DEC,
4703 NULL, 0x0, "Duplicate Acknowledgement count", HFILL } },
4704 { &hf_analysis_msg_resend_from,
4705 { "Retransmission of Message sent in", "dmp.analysis.msg_first_sent_in",
4706 FT_FRAMENUM, BASE_NONE,
4707 NULL, 0x0, "This Message was first sent in this frame", HFILL } },
4708 { &hf_analysis_rep_resend_from,
4709 { "Retransmission of Report sent in", "dmp.analysis.report_first_sent_in",
4710 FT_FRAMENUM, BASE_NONE,
4711 NULL, 0x0, "This Report was first sent in this frame", HFILL } },
4712 { &hf_analysis_not_resend_from,
4713 { "Retransmission of Notification sent in", "dmp.analysis.notif_first_sent_in",
4714 FT_FRAMENUM, BASE_NONE,
4715 NULL, 0x0, "This Notification was first sent in this frame", HFILL } },
4716 { &hf_analysis_ack_resend_from,
4717 { "Retransmission of Acknowledgement sent in", "dmp.analysis.ack_first_sent_in",
4718 FT_FRAMENUM, BASE_NONE,
4719 NULL, 0x0, "This Acknowledgement was first sent in this frame", HFILL } },
4724 { &hf_reserved_0x01,
4725 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4726 NULL, 0x01, NULL, HFILL } },
4727 { &hf_reserved_0x02,
4728 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4729 NULL, 0x02, NULL, HFILL } },
4730 { &hf_reserved_0x04,
4731 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4732 NULL, 0x04, NULL, HFILL } },
4733 { &hf_reserved_0x07,
4734 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4735 NULL, 0x07, NULL, HFILL } },
4736 { &hf_reserved_0x08,
4737 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4738 NULL, 0x08, NULL, HFILL } },
4739 { &hf_reserved_0x0F,
4740 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4741 NULL, 0x0F, NULL, HFILL } },
4742 { &hf_reserved_0x1F,
4743 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4744 NULL, 0x1F, NULL, HFILL } },
4745 { &hf_reserved_0x20,
4746 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4747 NULL, 0x20, NULL, HFILL } },
4748 { &hf_reserved_0x40,
4749 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4750 NULL, 0x40, NULL, HFILL } },
4751 { &hf_reserved_0xC0,
4752 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4753 NULL, 0xC0, NULL, HFILL } },
4754 { &hf_reserved_0xE0,
4755 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4756 NULL, 0xE0, NULL, HFILL } },
4757 { &hf_reserved_0x8000,
4758 { "Reserved", "dmp.reserved", FT_UINT16, BASE_DEC,
4759 NULL, 0x8000, NULL, HFILL } },
4762 static gint *ett[] = {
4765 &ett_envelope_version,
4766 &ett_envelope_hop_count,
4767 &ett_envelope_rec_present,
4768 &ett_envelope_addr_enc,
4769 &ett_envelope_checksum,
4770 &ett_envelope_extensions,
4771 &ett_envelope_msg_id_type,
4772 &ett_envelope_msg_id,
4773 &ett_envelope_mts_id_length,
4774 &ett_envelope_ipm_id_length,
4775 &ett_envelope_cont_type,
4776 &ett_envelope_subm_time,
4777 &ett_envelope_time_diff,
4778 &ett_envelope_flags,
4779 &ett_envelope_recipients,
4780 &ett_envelope_ext_recipients,
4781 &ett_envelope_addresses,
4783 &ett_address_direct,
4784 &ett_address_rec_no,
4785 &ett_address_extended,
4786 &ett_address_ext_form,
4787 &ett_address_ext_rec_no,
4788 &ett_address_ext_action,
4789 &ett_address_ext_rep_req,
4790 &ett_address_ext_not_req,
4791 &ett_address_ext_type,
4792 &ett_address_ext_length,
4795 &ett_extension_header,
4798 &ett_message_st_type,
4799 &ett_message_reserved,
4800 &ett_message_precedence,
4801 &ett_message_importance,
4802 &ett_message_body_format,
4803 &ett_message_sec_class,
4804 &ett_message_sec_pol,
4805 &ett_message_sec_cat,
4806 &ett_message_heading_flags,
4807 &ett_message_exp_time,
4810 &ett_message_sic_key,
4811 &ett_message_sic_bitmap,
4812 &ett_message_sic_bits,
4815 &ett_message_body_reserved,
4819 &ett_report_info_present_dr,
4820 &ett_report_info_present_ndr,
4821 &ett_report_addr_enc_dr,
4822 &ett_report_addr_enc_ndr,
4823 &ett_report_reserved,
4824 &ett_report_del_time,
4826 &ett_report_suppl_info,
4830 &ett_notif_rec_time,
4831 &ett_notif_suppl_info,
4832 &ett_notif_acp127recip,
4838 static ei_register_info ei[] = {
4839 { &ei_reserved_value,
4840 { "dmp.reserved.expert", PI_UNDECODED, PI_WARN,
4841 "Reserved value", EXPFILL } },
4842 { &ei_message_sic_illegal,
4843 { "dmp.sic.illegal", PI_UNDECODED, PI_NOTE,
4844 "Illegal SIC", EXPFILL } },
4845 { &ei_analysis_ack_unexpected,
4846 { "dmp.analysis.ack_unexpected", PI_SEQUENCE, PI_NOTE,
4847 "Unexpected ACK", EXPFILL } },
4848 { &ei_analysis_ack_missing,
4849 { "dmp.analysis.ack_missing.expert", PI_SEQUENCE, PI_NOTE,
4850 "Acknowledgement missing", EXPFILL } },
4851 { &ei_analysis_msg_missing,
4852 { "dmp.analysis.msg_missing", PI_SEQUENCE, PI_NOTE,
4853 "Message missing", EXPFILL } },
4854 { &ei_analysis_retrans_no,
4855 { "dmp.analysis.retrans_no.expert", PI_SEQUENCE, PI_NOTE,
4856 "Retransmission #", EXPFILL } },
4857 { &ei_analysis_ack_dup_no,
4858 { "dmp.analysis.dup_ack_no.expert", PI_SEQUENCE, PI_NOTE,
4859 "Dup ACK #", EXPFILL } },
4860 { &ei_addr_dir_rec_no_generated,
4861 { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN,
4862 "Recipient number too big", EXPFILL } },
4863 { &ei_addr_ext_rec_no_generated,
4864 { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN,
4865 "Recipient number too big", EXPFILL } },
4867 { "dmp.ack_reason.expert", PI_RESPONSE_CODE, PI_NOTE,
4868 "ACK reason: %s", EXPFILL } },
4869 { &ei_envelope_version_value,
4870 { "dmp.version_value.unsupported", PI_UNDECODED, PI_ERROR,
4871 "Unsupported DMP Version", EXPFILL } },
4872 { &ei_envelope_msg_id,
4873 { "dmp.msg_id.short_id", PI_PROTOCOL, PI_NOTE,
4874 "Id < 4096 - should use ShortId", EXPFILL } },
4875 { &ei_7bit_string_unused_bits,
4876 { "dmp.7bit_string.unused_bits", PI_PROTOCOL, PI_WARN,
4877 "Unused bits in last byte shall be null", EXPFILL } },
4878 { &ei_message_compr,
4879 { "dmp.body.compression.unknown", PI_UNDECODED, PI_WARN,
4880 "Unknown compression algorithm", EXPFILL } },
4881 { &ei_message_body_uncompress,
4882 { "dmp.body.uncompress.fail", PI_UNDECODED, PI_WARN,
4883 "Error: Unable to uncompress content", EXPFILL } },
4885 { "dmp.checksum_bad.expert", PI_CHECKSUM, PI_WARN,
4886 "Bad checksum", EXPFILL } },
4889 static uat_field_t attributes_flds[] = {
4890 UAT_FLD_VS(dmp_security_class,nation, "Nation", nat_pol_id, 0),
4891 UAT_FLD_DEC(dmp_security_class,sec_class, "Classification", "Security Classification"),
4892 UAT_FLD_CSTRING(dmp_security_class,name, "Name", "Classification Name"),
4896 uat_t *attributes_uat = uat_new("DMP Security Classifications",
4897 sizeof(dmp_security_class_t),
4898 "dmp_security_classifications",
4900 &dmp_security_classes,
4901 &num_dmp_security_classes,
4902 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4903 "ChDMPSecurityClassifications",
4911 module_t *dmp_module;
4912 expert_module_t* expert_dmp;
4914 proto_dmp = proto_register_protocol (PNAME, PSNAME, PFNAME);
4916 dmp_handle = register_dissector(PFNAME, dissect_dmp, proto_dmp);
4918 proto_register_field_array (proto_dmp, hf, array_length (hf));
4919 proto_register_subtree_array (ett, array_length (ett));
4920 expert_dmp = expert_register_protocol(proto_dmp);
4921 expert_register_field_array(expert_dmp, ei, array_length(ei));
4922 register_init_routine (&dmp_init_routine);
4923 register_cleanup_routine (&dmp_cleanup_routine);
4925 /* Build national values */
4926 build_national_strings ();
4928 /* Register our configuration options */
4929 dmp_module = prefs_register_protocol (proto_dmp, NULL);
4931 prefs_register_obsolete_preference (dmp_module, "udp_port");
4932 prefs_register_obsolete_preference (dmp_module, "udp_port_second");
4934 prefs_register_enum_preference (dmp_module, "national_decode",
4935 "National decoding",
4936 "Select the type of decoding for nationally-defined values",
4937 &dmp_nat_decode, national_decoding,
4939 prefs_register_enum_preference (dmp_module, "local_nation",
4940 "Nation of local server",
4941 "Select the nation of sending server. This is used when presenting"
4942 " security classification values in messages with security"
4943 " policy set to National (nation of local server)",
4944 &dmp_local_nation, dmp_national_values,
4946 prefs_register_uat_preference (dmp_module, "classes_table",
4947 "National Security Classifications",
4948 "Translation table for national security classifications. This is used"
4949 " when presenting security classification values in messages with"
4950 " security policy set to National or Extended National",
4952 prefs_register_bool_preference (dmp_module, "seq_ack_analysis",
4954 "Calculate sequence/acknowledgement analysis",
4955 &use_seq_ack_analysis);
4956 prefs_register_bool_preference (dmp_module, "align_ids",
4957 "Align identifiers in info list",
4958 "Align identifiers in info list"
4959 " (does not align when retransmission or"
4960 " duplicate acknowledgement indication)",
4962 prefs_register_obsolete_preference(dmp_module, "subject_as_id");
4963 prefs_register_obsolete_preference(dmp_module, "struct_print");
4964 prefs_register_obsolete_preference(dmp_module, "struct_offset");
4965 prefs_register_obsolete_preference(dmp_module, "struct_length");
4968 void proto_reg_handoff_dmp (void)
4970 dissector_add_uint ("s5066sis.ctl.appid", S5066_CLIENT_S4406_ANNEX_E_TMI_4_DMP, dmp_handle);
4971 dissector_add_uint_range_with_preference("udp.port", DEFAULT_DMP_PORT_RANGE, dmp_handle);
4980 * indent-tabs-mode: nil
4983 * ex: set shiftwidth=2 tabstop=8 expandtab:
4984 * :indentSize=2:tabSize=8:noTabs=true: