Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-dmp.c
blob192be75a35bd8ea2a679a80cde361b2e3f54f065
1 /* packet-dmp.c
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 * SPDX-License-Identifier: GPL-2.0-or-later
16 * Ref: http://jcs.dtic.mil/j6/cceb/acps/acp123/
17 * https://web.archive.org/web/20100326015412/http://jcs.dtic.mil/j6/cceb/acps/acp123/ACP123A.pdf
21 * TODO:
22 * - Dissect extended Restrictive security categories
23 * - Add Transmission/Retransmission statistics
26 #include "config.h"
28 #include <math.h>
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
34 #include <epan/crc16-tvb.h>
35 #include <epan/asn1.h>
36 #include <epan/uat.h>
37 #include <epan/proto_data.h>
38 #include <epan/tfs.h>
39 #include <epan/exceptions.h>
41 #include <wsutil/str_util.h>
42 #include <wsutil/array.h>
44 #include "packet-p1.h"
45 #include "packet-p22.h"
46 #include "packet-s5066sis.h"
48 void proto_register_dmp(void);
49 void proto_reg_handoff_dmp(void);
51 #define PNAME "Direct Message Profile"
52 #define PSNAME "DMP"
53 #define PFNAME "dmp"
55 /* Default UDP Port Number */
56 #define DEFAULT_DMP_PORT_RANGE "5031"
58 /* Protocol Identifier */
59 #define PROT_NAT 0x0D
60 #define PROT_DMP 0x1D
62 /* Versions supported */
63 #define DMP_VERSION_1 1
64 #define DMP_VERSION_2 2
66 /* Message Type (dmp.msg_type) */
67 #define STANAG 0x0
68 #define IPM 0x1
69 #define REPORT 0x2
70 #define NOTIF 0x3
71 #define ACK 0x4
73 /* Message Identifier Type (dmp.msg_id_type) */
74 #define ONLY_DMP_ID 0x0
75 #define X400_MSG_ID 0x1
76 #define NAT_MSG_ID 0x2
78 /* Report Type (dmp.report_type) */
79 #define DR 0x0
80 #define NDR 0x1
82 /* Notification Type (dmp.notif_type) */
83 #define RN 0x0
84 #define NRN 0x1
85 #define ON 0x2
87 /* Address Encoding (dmp.addr_enc) */
88 #define DIRECT_ADDR 0x0
89 #define EXTENDED_ADDR 0x1
91 /* Address type (internal values) */
92 #define ORIGINATOR 1
93 #define P1_ADDRESS 2
94 #define P2_ADDRESS 3
95 #define ORIG_P2_ADDRESS 4
97 /* Extended Address Form (dmp_addr_form) */
98 #define P1_DIRECT 0x0
99 #define P2_DIRECT 0x1
100 #define P1_EXTENDED 0x2
101 #define P2_EXTENDED 0x3
102 #define P1_P2_DIRECT 0x4
103 #define P1_DIRECT_P2_EXTENDED 0x5
104 #define P1_EXTENDED_P2_DIRECT 0x6
105 #define P1_P2_EXTENDED 0x7
107 /* Extended Address Type */
108 #define ASN1_BER 0x0
109 #define ASN1_PER 0x1
111 /* Security Policy (dmp_sec_pol) */
112 #define NATO 0x4
113 #define NATIONAL 0x5
114 #define EXTENDED_NATIONAL 0x6
115 #define EXTENDED_MISSION 0x7
117 #define SEC_CAT_EXT_NONE 0x0
118 #define SEC_CAT_EXT_PERMISSIVE 0x1
119 #define SEC_CAT_EXT_RESTRICTIVE 0x2
121 /* Body Format (dmp.body_format) */
122 #define FREE_TEXT 0x0
123 #define FREE_TEXT_SUBJECT 0x1
124 #define STRUCTURED 0x2
126 /* Encoded Information Types */
127 #define EIT_BILATERAL 0x3
129 /* Compression Algorithm */
130 #define ALGORITHM_NONE 0x0
131 #define ALGORITHM_ZLIB 0x1
133 /* National Decoding */
134 #define NAT_DECODE_NONE 0
135 #define NAT_DECODE_DMP 1
136 #define NAT_DECODE_THALES 2
138 #define IPM_MODIFIER_X400 0
140 /* Internal values for not present and reserved time values */
141 #define DMP_TIME_NOT_PRESENT -1
142 #define DMP_TIME_RESERVED -2
144 #define ILLEGAL_FORMAT "<Illegal format>"
145 #define TIME_NOT_REPRESENTABLE "<Time not representable>"
147 /* Maximum lengths */
148 #define MAX_SIC_LEN 30
150 static int proto_dmp;
152 static int hf_dmp_id;
153 static int hf_mts_id;
154 static int hf_ipm_id;
156 static int hf_envelope;
157 static int hf_envelope_protocol_id;
158 static int hf_envelope_version;
159 static int hf_envelope_version_value;
160 static int hf_envelope_hop_count;
161 static int hf_envelope_hop_count_value;
162 static int hf_envelope_rec_present;
163 static int hf_envelope_addr_enc;
164 static int hf_envelope_checksum;
165 static int hf_envelope_extensions;
166 static int hf_envelope_msg_id_type;
167 static int hf_envelope_msg_id_length;
168 static int hf_envelope_mts_id_length;
169 static int hf_envelope_ipm_id_modifier;
170 static int hf_envelope_ipm_id_length;
171 static int hf_envelope_mts_id;
172 static int hf_envelope_ipm_id;
173 static int hf_envelope_type;
174 static int hf_envelope_msg_id;
175 static int hf_envelope_msg_id_12bit;
176 static int hf_envelope_subm_time;
177 static int hf_envelope_subm_time_value;
178 static int hf_envelope_time_diff_present;
179 static int hf_envelope_time_diff;
180 static int hf_envelope_time_diff_value;
181 static int hf_envelope_flags;
182 static int hf_envelope_content_id_discarded;
183 static int hf_envelope_recip_reassign_prohib;
184 static int hf_envelope_dl_expansion_prohib;
185 static int hf_envelope_recipients;
186 static int hf_envelope_ext_recipients;
188 static int hf_thales_ipm_id_modifier;
190 static int hf_extensions;
191 static int hf_extension;
192 static int hf_extension_header;
193 static int hf_extension_more;
194 static int hf_extension_length;
195 static int hf_extension_data;
197 static int hf_message_content;
198 static int hf_report_content;
199 static int hf_notif_content;
201 static int hf_addr_recipient;
202 static int hf_addr_originator;
203 static int hf_addr_reporting_name;
204 static int hf_addr_dl_expanded;
205 static int hf_addr_int_rec;
206 static int hf_addr_dir_addr_ext;
207 static int hf_addr_dir_rec_no;
208 static int hf_addr_dir_rec_no1;
209 static int hf_addr_dir_rec_no2;
210 static int hf_addr_dir_rec_no3;
211 static int hf_addr_dir_rec_no_generated;
212 static int hf_addr_dir_rep_req1;
213 static int hf_addr_dir_rep_req2;
214 static int hf_addr_dir_rep_req3;
215 static int hf_addr_dir_not_req1;
216 static int hf_addr_dir_not_req2;
217 static int hf_addr_dir_not_req3;
218 static int hf_addr_dir_action;
219 static int hf_addr_dir_address;
220 static int hf_addr_dir_address1;
221 static int hf_addr_dir_address2;
222 static int hf_addr_dir_address3;
223 static int hf_addr_dir_address_generated;
225 static int hf_addr_ext_form;
226 static int hf_addr_ext_form_orig_v1;
227 static int hf_addr_ext_form_orig;
228 static int hf_addr_ext_action;
229 static int hf_addr_ext_rep_req;
230 static int hf_addr_ext_not_req;
231 static int hf_addr_ext_rec_ext;
232 static int hf_addr_ext_rec_no;
233 static int hf_addr_ext_rec_no1;
234 static int hf_addr_ext_rec_no2;
235 static int hf_addr_ext_rec_no_generated;
236 static int hf_addr_ext_address;
237 static int hf_addr_ext_type;
238 static int hf_addr_ext_type_ext;
239 static int hf_addr_ext_length;
240 static int hf_addr_ext_length1;
241 static int hf_addr_ext_length2;
242 static int hf_addr_ext_length_generated;
243 static int hf_addr_ext_asn1_ber;
244 static int hf_addr_ext_asn1_per;
245 static int hf_addr_ext_unknown;
247 static int hf_message_body;
248 static int hf_message_st_type;
249 static int hf_message_precedence;
250 static int hf_message_importance;
251 static int hf_message_body_format;
252 static int hf_message_sec_class_val;
253 static int hf_message_sec_pol;
254 static int hf_message_heading_flags;
255 static int hf_message_auth_users;
256 static int hf_message_subject_disc;
257 static int hf_message_national_policy_id;
258 static int hf_message_mission_policy_id;
259 static int hf_message_sec_label;
260 static int hf_message_sec_cat_nat;
261 static int hf_message_sec_cat_val;
262 static int hf_message_sec_cat_cl;
263 static int hf_message_sec_cat_cs;
264 static int hf_message_sec_cat_ex;
265 static int hf_message_sec_cat_ne;
266 static int hf_message_sec_cat_permissive;
267 static int hf_message_sec_cat_country_code;
268 static int hf_message_sec_cat_restrictive;
269 static int hf_message_sec_cat_extended;
270 static int hf_message_sec_cat_bit0;
271 static int hf_message_sec_cat_bit1;
272 static int hf_message_sec_cat_bit2;
273 static int hf_message_sec_cat_bit3;
274 static int hf_message_sec_cat_bit4;
275 static int hf_message_sec_cat_bit5;
276 static int hf_message_sec_cat_bit6;
277 static int hf_message_sec_cat_bit7;
278 static int hf_message_exp_time;
279 static int hf_message_exp_time_val;
280 static int hf_message_dtg;
281 static int hf_message_dtg_sign;
282 static int hf_message_dtg_val;
283 static int hf_message_sic;
284 static int hf_message_sic_key;
285 static int hf_message_sic_key_values;
286 static int hf_message_sic_key_type;
287 static int hf_message_sic_key_chars;
288 static int hf_message_sic_key_num;
289 static int hf_message_sic_bitmap;
290 static int hf_message_sic_bits;
291 static int hf_message_sic_bits_any;
292 static int hf_message_subj_id;
293 static int hf_message_subj_mts_id;
294 static int hf_message_subj_ipm_id;
296 static int hf_message_subject;
297 static int hf_message_eit;
298 static int hf_message_compr;
299 static int hf_message_body_data;
300 static int hf_message_body_compressed;
301 static int hf_message_body_plain;
302 static int hf_message_body_structured;
304 static int hf_delivery_report;
305 static int hf_non_delivery_report;
306 static int hf_report_type;
307 static int hf_report_info_present_dr;
308 static int hf_report_addr_enc_dr;
309 static int hf_report_del_time;
310 static int hf_report_del_time_val;
311 static int hf_report_addr_enc_ndr;
312 static int hf_report_reason;
313 static int hf_report_info_present_ndr;
314 static int hf_report_diagn;
315 static int hf_report_suppl_info_len;
316 static int hf_report_suppl_info;
318 static int hf_receipt_notif;
319 static int hf_non_receipt_notif;
320 static int hf_other_notif;
321 static int hf_notif_type;
322 static int hf_notif_rec_time;
323 static int hf_notif_rec_time_val;
324 static int hf_notif_suppl_info_len;
325 static int hf_notif_suppl_info;
326 static int hf_notif_non_rec_reason;
327 static int hf_notif_discard_reason;
328 static int hf_notif_on_type;
329 static int hf_notif_acp127;
330 static int hf_notif_acp127recip;
332 static int hf_ack;
333 static int hf_ack_reason;
334 static int hf_ack_diagnostic;
335 static int hf_ack_recips;
337 static int hf_checksum;
338 static int hf_checksum_status;
340 static int hf_analysis_ack_time;
341 static int hf_analysis_total_time;
342 static int hf_analysis_retrans_time;
343 static int hf_analysis_total_retrans_time;
344 static int hf_analysis_msg_num;
345 static int hf_analysis_acks_msg_num;
346 static int hf_analysis_retrans_no;
347 static int hf_analysis_ack_num;
348 static int hf_analysis_ack_missing;
349 static int hf_analysis_ack_dup_no;
350 /* static int hf_analysis_rep_num; */
351 static int hf_analysis_acks_rep_num;
352 static int hf_analysis_rep_time;
353 /* static int hf_analysis_not_num; */
354 static int hf_analysis_acks_not_num;
355 static int hf_analysis_not_time;
356 static int hf_analysis_msg_resend_from;
357 static int hf_analysis_rep_resend_from;
358 static int hf_analysis_not_resend_from;
359 static int hf_analysis_ack_resend_from;
361 static int hf_reserved_0x01;
362 static int hf_reserved_0x02;
363 static int hf_reserved_0x04;
364 static int hf_reserved_0x07;
365 static int hf_reserved_0x08;
366 static int hf_reserved_0x0F;
367 static int hf_reserved_0x1F;
368 static int hf_reserved_0x20;
369 static int hf_reserved_0x40;
370 static int hf_reserved_0xC0;
371 static int hf_reserved_0xE0;
372 static int hf_reserved_0x8000;
374 static int ett_dmp;
375 static int ett_envelope;
376 static int ett_envelope_version;
377 static int ett_envelope_hop_count;
378 static int ett_envelope_rec_present;
379 static int ett_envelope_addr_enc;
380 static int ett_envelope_checksum;
381 static int ett_envelope_extensions;
382 static int ett_envelope_msg_id_type;
383 static int ett_envelope_msg_id;
384 static int ett_envelope_mts_id_length;
385 static int ett_envelope_ipm_id_length;
386 static int ett_envelope_cont_type;
387 static int ett_envelope_subm_time;
388 static int ett_envelope_time_diff;
389 static int ett_envelope_flags;
390 static int ett_envelope_recipients;
391 static int ett_envelope_ext_recipients;
392 static int ett_envelope_addresses;
394 static int ett_address;
395 static int ett_address_direct;
396 static int ett_address_rec_no;
397 static int ett_address_extended;
398 static int ett_address_ext_form;
399 static int ett_address_ext_rec_no;
400 static int ett_address_ext_action;
401 static int ett_address_ext_rep_req;
402 static int ett_address_ext_not_req;
403 static int ett_address_ext_type;
404 static int ett_address_ext_length;
406 static int ett_extensions;
407 static int ett_extension;
408 static int ett_extension_header;
410 static int ett_content;
412 static int ett_message;
413 static int ett_message_st_type;
414 static int ett_message_reserved;
415 static int ett_message_precedence;
416 static int ett_message_importance;
417 static int ett_message_body_format;
418 static int ett_message_sec_class;
419 static int ett_message_sec_pol;
420 static int ett_message_sec_cat;
421 static int ett_message_heading_flags;
422 static int ett_message_exp_time;
423 static int ett_message_dtg;
424 static int ett_message_sic;
425 static int ett_message_sic_key;
426 static int ett_message_sic_bitmap;
427 static int ett_message_sic_bits;
428 static int ett_message_eit;
429 static int ett_message_compr;
430 static int ett_message_body_reserved;
431 static int ett_message_body;
433 static int ett_report;
434 static int ett_report_type;
435 static int ett_report_info_present_dr;
436 static int ett_report_info_present_ndr;
437 static int ett_report_addr_enc_dr;
438 static int ett_report_addr_enc_ndr;
439 static int ett_report_reserved;
440 static int ett_report_del_time;
441 static int ett_report_reason;
442 static int ett_report_suppl_info;
443 static int ett_report_diagn;
445 static int ett_notif;
446 static int ett_notif_type;
447 static int ett_notif_rec_time;
448 static int ett_notif_suppl_info;
449 static int ett_notif_acp127recip;
451 static int ett_ack;
452 static int ett_ack_recips;
454 static int ett_analysis;
456 static expert_field ei_reserved_value;
457 static expert_field ei_message_sic_illegal;
458 static expert_field ei_envelope_version_value;
459 static expert_field ei_message_compr;
460 static expert_field ei_ack_reason;
461 static expert_field ei_addr_dir_rec_no_generated;
462 static expert_field ei_checksum_bad;
463 static expert_field ei_message_body_uncompress;
464 static expert_field ei_addr_ext_rec_no_generated;
465 static expert_field ei_envelope_msg_id;
466 static expert_field ei_7bit_string_unused_bits;
467 static expert_field ei_analysis_ack_missing;
468 static expert_field ei_analysis_ack_dup_no;
469 static expert_field ei_analysis_ack_unexpected;
470 static expert_field ei_analysis_msg_missing;
471 static expert_field ei_analysis_retrans_no;
472 static expert_field ei_too_many_sec_cat;
474 static dissector_handle_t dmp_handle;
476 typedef struct _dmp_id_key {
477 unsigned id;
478 address src;
479 address dst;
480 } dmp_id_key;
482 typedef struct _dmp_id_val {
483 int msg_type; /* Message type */
484 unsigned prev_msg_id; /* Previous message package num */
485 unsigned msg_id; /* Message package num */
486 unsigned ack_id; /* Acknowledgement package num */
487 unsigned rep_id; /* Report package num */
488 unsigned not_id; /* Notification package num */
489 nstime_t msg_time; /* Message receive time */
490 nstime_t first_msg_time; /* First message receive time */
491 nstime_t prev_msg_time; /* Previous message receive time */
492 nstime_t rep_not_msg_time; /* Report or Notification time */
493 uint32_t msg_resend_count; /* Message resend counter */
494 uint32_t ack_resend_count; /* Acknowledgement resend counter */
495 } dmp_id_val;
497 static wmem_map_t *dmp_id_hash_table;
498 static wmem_map_t *dmp_long_id_hash_table;
500 /* Global values used in several functions */
501 static struct dmp_data {
502 int version;
503 int prot_id;
504 int addr_enc;
505 int checksum;
506 int msg_type;
507 int st_type;
508 int prec;
509 int body_format;
510 int notif_type;
511 int32_t subm_time;
512 uint8_t msg_id_type;
513 uint8_t mts_id_length;
514 proto_item *mts_id_item;
515 uint8_t ack_reason;
516 uint16_t msg_id;
517 uint16_t subj_id;
518 bool extensions;
519 bool dr;
520 bool ndr;
521 bool notif_req;
522 bool ack_rec_present;
523 dmp_id_val *id_val;
524 } dmp;
526 /* User definable values */
527 static int dmp_nat_decode = NAT_DECODE_DMP;
528 static int dmp_local_nation;
529 static bool use_seq_ack_analysis = true;
530 static bool dmp_align;
532 typedef struct _dmp_security_class_t {
533 unsigned nation;
534 unsigned sec_class;
535 char *name;
536 } dmp_security_class_t;
538 static dmp_security_class_t *dmp_security_classes;
539 static unsigned num_dmp_security_classes;
541 static const true_false_string addr_enc = {
542 "Use Extended Encoding", "Use Direct Encoding"
545 static const true_false_string dtg_sign = {
546 "Future", "Past"
549 static const true_false_string report_type = {
550 "Non-Delivery Report", "Delivery Report"
553 static const value_string version_vals[] = {
554 { 0x0, "1" },
555 { 0x1, "2" },
556 { 0x2, "Unknown" },
557 { 0x3, "Unknown" },
558 { 0x4, "Unknown" },
559 { 0x5, "Unknown" },
560 { 0x6, "Unknown" },
561 { 0x7, "Unknown" },
562 { 0, NULL } };
564 static const value_string type_vals[] = {
565 { 0x0, "Message" },
566 { 0x1, "Message (E-Mail)" },
567 { 0x2, "Report" },
568 { 0x3, "Notification" },
569 { 0x4, "Acknowledgement" },
570 { 0x5, "Unknown Content" },
571 { 0x6, "Unknown Content" },
572 { 0x7, "Unknown Content" },
573 { 0, NULL } };
575 static const value_string msg_id_type_vals[] = {
576 { 0x0, "DMP Identifiers only" },
577 { 0x1, "X.400 Message Identifiers" },
578 { 0x2, "Nationally-defined" },
579 { 0x3, "Reserved" },
580 { 0, NULL } };
582 static const value_string msg_id_length_vals[] = {
583 { 0x0, "Full (16 bits)" },
584 { 0x1, "Short (12 bits)" },
585 { 0, NULL } };
587 static const value_string report_vals[] = {
588 { 0x0, "No Report" },
589 { 0x1, "Non-Delivery Report" },
590 { 0x2, "Delivery Report" },
591 { 0x3, "Reserved" },
592 { 0, NULL } };
594 static const value_string report_vals_ext[] = {
595 { 0x0, "No Report" },
596 { 0x1, "Non-Delivery Report" },
597 { 0x2, "Delivery Report" },
598 { 0x3, "Recipient Number Extended" },
599 { 0, NULL } };
601 /* Note the space in front of these values */
602 static const value_string report_vals_short[] = {
603 { 0x1, " NDR" },
604 { 0x2, " DR" },
605 { 0, NULL } };
607 static const value_string notif_vals[] = {
608 { 0x0, "No Notification" },
609 { 0x1, "Non-Receipt Notification" },
610 { 0x2, "Receipt Notification" },
611 { 0x3, "Reserved" },
612 { 0, NULL } };
614 static const value_string notif_vals_ext[] = {
615 { 0x0, "No Notification" },
616 { 0x1, "Non-Receipt Notification" },
617 { 0x2, "Receipt Notification" },
618 { 0x3, "Direct Address Extended" },
619 { 0, NULL } };
621 /* Note the space in front of these values */
622 static const value_string notif_vals_short[] = {
623 { 0x1, " NRN" },
624 { 0x2, " RN" },
625 { 0, NULL } };
627 static const value_string notif_type [] = {
628 { 0x0, "Receipt Notification (RN)" },
629 { 0x1, "Non-Receipt Notification (NRN)" },
630 { 0x2, "Other Notification (ON)" },
631 { 0x3, "Unknown Notification" },
632 { 0, NULL } };
634 /* Note the space behind these values */
635 static const value_string addr_type_str [] = {
636 { ORIGINATOR, "" },
637 { P1_ADDRESS, "P1 " },
638 { P2_ADDRESS, "P22/P772 " },
639 { ORIG_P2_ADDRESS, "P22 " },
640 { 0, NULL } };
642 static const value_string addr_form [] = {
643 { 0x0, "P1 Direct" },
644 { 0x1, "P22/P772 Direct" },
645 { 0x2, "P1 Extended" },
646 { 0x3, "P22/P772 Extended" },
647 { 0x4, "P1 and P22/P772 Direct" },
648 { 0x5, "P1 Direct and P22/P772 Extended" },
649 { 0x6, "P1 Extended and P22/P772 Direct" },
650 { 0x7, "P1 and P22/P772 Extended" },
651 { 0, NULL } };
653 static const value_string addr_form_orig_v1 [] = {
654 { 0x0, "Direct" },
655 { 0x1, "Reserved" },
656 { 0x2, "Extended" },
657 { 0x3, "Reserved" },
658 { 0x4, "Reserved" },
659 { 0x5, "Reserved" },
660 { 0x6, "Reserved" },
661 { 0x7, "Reserved" },
662 { 0, NULL } };
664 static const value_string addr_form_orig [] = {
665 { 0x0, "Direct" },
666 { 0x1, "Reserved" },
667 { 0x2, "Extended" },
668 { 0x3, "Reserved" },
669 { 0x4, "Originator and P2 Direct" },
670 { 0x5, "Originator Direct and P2 Extended" },
671 { 0x6, "Originator Extended and P2 Direct" },
672 { 0x7, "Originator and P2 Extended" },
673 { 0, NULL } };
675 static const value_string ext_addr_type [] = {
676 { 0x0, "ASN.1 BER-encoded OR-name" },
677 { 0x1, "ASN.1 PER-encoded OR-name" },
678 { 0x2, "Reserved" },
679 { 0x3, "Reserved" },
680 { 0x4, "Reserved" },
681 { 0x5, "Reserved" },
682 { 0x6, "Reserved" },
683 { 0x7, "Address Length Extended" },
684 { 0, NULL } };
686 static const value_string ext_addr_type_ext [] = {
687 { 0x0, "ASN.1 BER-encoded OR-name" },
688 { 0x1, "ASN.1 PER-encoded OR-name" },
689 { 0x2, "Reserved" },
690 { 0x3, "Reserved" },
691 { 0x4, "Reserved" },
692 { 0x5, "Reserved" },
693 { 0x6, "Reserved" },
694 { 0x7, "Reserved" },
695 { 0, NULL } };
697 static const value_string ext_addr_type_short [] = {
698 { 0x0, "OR-name (BER)" },
699 { 0x1, "OR-name (PER)" },
700 { 0x2, "Reserved" },
701 { 0x3, "Reserved" },
702 { 0x4, "Reserved" },
703 { 0x5, "Reserved" },
704 { 0x6, "Reserved" },
705 { 0x7, "Reserved" },
706 { 0, NULL } };
708 static const value_string message_type_vals[] = {
709 { 0x0, "Operation" },
710 { 0x1, "Project" },
711 { 0x2, "Exercise" },
712 { 0x3, "Drill" },
713 { 0, NULL } };
715 static const value_string precedence[] = {
716 { 0x0, "Deferred" },
717 { 0x1, "Routine" },
718 { 0x2, "Priority" },
719 { 0x3, "Immediate" },
720 { 0x4, "Flash" },
721 { 0x5, "Override" },
722 { 0x6, "Priority, Info Precedence: Routine" },
723 { 0x7, "Immediate, Info Precedence: Routine" },
724 { 0, NULL } };
726 static const value_string importance[] = {
727 { 0x0, "Low" },
728 { 0x1, "Reserved" },
729 { 0x2, "Normal" },
730 { 0x3, "Reserved" },
731 { 0x4, "High" },
732 { 0x5, "Reserved" },
733 { 0x6, "Reserved" },
734 { 0x7, "Reserved" },
735 { 0, NULL } };
737 static const value_string sec_class[] = {
738 { 0x0, "Unmarked" },
739 { 0x1, "Unclassified" },
740 /* { 0x2, "Reserved" }, */
741 { 0x3, "Restricted" },
742 /* { 0x4, "Reserved" }, */
743 { 0x5, "Confidential" },
744 { 0x6, "Secret" },
745 { 0x7, "Top secret" },
746 { 0, NULL } };
748 static const value_string sec_pol[] = {
749 { 0x0, "Network defined" },
750 { 0x1, "Network defined" },
751 { 0x2, "Network defined" },
752 { 0x3, "Network defined" },
753 { 0x4, "NATO" },
754 { 0x5, "National (nation of local server)" },
755 { 0x6, "Extended, National" },
756 { 0x7, "Extended, Mission Defined" },
757 { 0, NULL } };
759 /* For name we use the ISO 3166-1 Alfa-3 value for the country,
760 * for description we use the Country Name and
761 * for value we use the DMP value for National Policy Identifier.
763 static const enum_val_t dmp_national_values[] = {
764 { "xxx", "None", 0x00 },
765 { "alb", "Albania", 0x1B },
766 { "arm", "Armenia", 0x20 },
767 { "aut", "Austria", 0x21 },
768 { "aze", "Azerbaijan", 0x22 },
769 { "blr", "Belarus", 0x23 },
770 { "bel", "Belgium", 0x01 },
771 { "bih", "Bosnia and Hercegowina", 0x24 },
772 { "bgr", "Bulgaria", 0x02 },
773 { "can", "Canada", 0x03 },
774 { "hrv", "Croatia", 0x1C },
775 { "cze", "Czech Republic", 0x04 },
776 { "dnk", "Denmark", 0x05 },
777 { "est", "Estonia", 0x06 },
778 { "eapc", "Euro-Atlantic Partnership Council (EAPC)", 0x3A },
779 { "eu", "European Union (EU)", 0x3B },
780 { "fin", "Finland", 0x25 },
781 { "mkd", "Former Yugoslav Republic of Macedonia", 0x26 },
782 { "fra", "France", 0x07 },
783 { "geo", "Georgia", 0x27 },
784 { "deu", "Germany", 0x08 },
785 { "grc", "Greece", 0x09 },
786 { "hun", "Hungary", 0x0A },
787 { "isl", "Iceland", 0x0B },
788 { "isaf", "International Security Assistance Force (ISAF)", 0x3C },
789 { "irl", "Ireland", 0x28 },
790 { "ita", "Italy", 0x0C },
791 { "kaz", "Kazakhstan", 0x29 },
792 { "kgz", "Kyrgyztan", 0x2A },
793 { "lva", "Latvia", 0x0D },
794 { "ltu", "Lithuania", 0x0E },
795 { "lux", "Luxembourg", 0x0F },
796 { "mlt", "Malta", 0x2B },
797 { "mda", "Moldova", 0x2C },
798 { "mne", "Montenegro", 0x2D },
799 { "nld", "Netherlands", 0x10 },
800 { "nor", "Norway", 0x11 },
801 { "pfp", "Partnership for Peace (PfP)", 0x3D },
802 { "pol", "Poland", 0x12 },
803 { "ptr", "Portugal", 0x13 },
804 { "rou", "Romania", 0x14 },
805 { "rus", "Russian Federation", 0x2E },
806 { "srb", "Serbia", 0x2F },
807 { "svk", "Slovakia", 0x15 },
808 { "svn", "Slovenia", 0x16 },
809 { "esp", "Spain", 0x17 },
810 { "swe", "Sweden", 0x30 },
811 { "che", "Switzerland", 0x31 },
812 { "tjk", "Tajikistan", 0x32 },
813 { "tur", "Turkey", 0x18 },
814 { "tkm", "Turkmenistan", 0x33 },
815 { "gbr", "United Kingdom", 0x19 },
816 { "usa", "United States", 0x1A },
817 { "ukr", "Ukraine", 0x34 },
818 { "uzb", "Uzbekistan", 0x35 },
819 { "weu", "Western European Union (WEU)", 0x3E },
820 { NULL, NULL, 0 }
823 #define MAX_NATIONAL_VALUES array_length(dmp_national_values)
824 /* Will be built in build_national_strings() */
825 static value_string nat_pol_id[MAX_NATIONAL_VALUES];
827 static const value_string ext_sec_cat[] = {
828 { 0x0, "Not present" },
829 { 0x1, "Permissive category follows" },
830 { 0x2, "Restrictive category follows" },
831 { 0x3, "Reserved" },
832 { 0, NULL } };
834 static const value_string sic_key_type[] = {
835 { 0xc, "2 or more 3-character SICs" },
836 { 0xd, "1 or more 3-to-8 character SICs" },
837 { 0, NULL } };
839 static const true_false_string sic_key_chars = {
840 "Any", "[A-Z0-9] only"
843 static const value_string sic_key_num[] = {
844 { 0, "1" },
845 { 1, "2" },
846 { 2, "3" },
847 { 3, "4" },
848 { 4, "5" },
849 { 5, "6" },
850 { 6, "7" },
851 { 7, "8" },
852 { 0, NULL } };
855 static const value_string sic_bit_vals[] = {
856 { 0, "length:6, bytes:4" },
857 { 1, "length:6, bytes:4" },
858 { 2, "length:6, bytes:4" },
859 { 3, "length:6, bytes:4" },
860 { 4, "length:6, bytes:4" },
861 { 5, "length:6, bytes:4" },
862 { 6, "length:6, bytes:4" },
863 { 7, "length:6, bytes:4" },
864 { 8, "length:6, bytes:4" },
865 { 9, "reserved" },
866 { 10, "length:5, bytes:4" },
867 { 11, "length:8, bytes:6" },
868 { 12, "length:4, bytes:3" },
869 { 13, "length:4, bytes:3" },
870 { 14, "length:7, bytes:5" },
871 { 15, "length:7, bytes:5" },
872 { 0, NULL } };
874 static const value_string sic_bit_any_vals[] = {
875 { 0, "length:5, bytes:4" },
876 { 1, "length:5, bytes:4" },
877 { 2, "length:5, bytes:4" },
878 { 3, "length:5, bytes:4" },
879 { 4, "length:5, bytes:4" },
880 { 5, "length:5, bytes:4" },
881 { 6, "length:5, bytes:4" },
882 { 7, "length:5, bytes:4" },
883 { 8, "length:5, bytes:4" },
884 { 9, "length:8, bytes:7" },
885 { 10, "length:4, bytes:4" },
886 { 11, "length:7, bytes:6" },
887 { 12, "length:6, bytes:5" },
888 { 13, "length:6, bytes:5" },
889 { 14, "length:6, bytes:5" },
890 { 15, "length:6, bytes:5" },
891 { 0, NULL } };
893 static const value_string body_format_vals[] = {
894 { 0x0, "Free text" },
895 { 0x1, "Free text including subject" },
896 { 0x2, "Structured" },
897 { 0x3, "Reserved" },
898 { 0, NULL } };
900 static const value_string eit_vals[] = {
901 { 0x0, "Empty" },
902 { 0x1, "IA5-text" },
903 { 0x2, "General text" },
904 { 0x3, "Bilaterally defined (binary data)" },
905 { 0x4, "AdatP-3" },
906 { 0x5, "Reserved" },
907 { 0x6, "Reserved" },
908 { 0x7, "Reserved" },
909 { 0, NULL } };
911 static const value_string compression_vals[] = {
912 { 0x0, "No compression" },
913 { 0x1, "ZLib compressed" },
914 { 0x2, "Reserved" },
915 { 0x3, "Reserved" },
916 { 0, NULL } };
918 static const value_string ack_reason [] = {
919 { 0x00, "Successful, positive acknowledgement" },
920 { 0x01, "Unspecified error" },
921 { 0x02, "Checksum incorrect" },
922 { 0, NULL } };
924 static const value_string non_del_reason [] = {
925 { 0x3D, "Unknown reason" },
926 { 0x3E, "Reason code greater than 0x3c (60)" },
927 { 0x3F, "Reserved" },
928 { 0, NULL } };
930 static const value_string non_del_diagn [] = {
931 { 0x7C, "Diagnostic not specified" },
932 { 0x7D, "Unknown diagnostic" },
933 { 0x7E, "Diagnostic code greater than 0x7b (123)" },
934 { 0x7F, "Reserved" },
935 { 0, NULL } };
937 static const value_string discard_reason [] = {
938 { 0xFE, "Discard Reason absent" },
939 { 0xFF, "Reserved" },
940 { 0, NULL } };
942 static const value_string on_type [] = {
943 { 0x00, "acp127-nn" },
944 { 0x01, "acp127-pn" },
945 { 0x02, "acp127-tn" },
946 { 0, NULL } };
948 static const value_string ack_msg_type [] = {
949 { STANAG, " (message)" },
950 { IPM, " (e-mail)" },
951 { REPORT, " (report)" },
952 { NOTIF, " (notif)" },
953 { ACK, " (ack)" },
954 { 0, NULL } };
956 static const enum_val_t national_decoding[] = {
957 { "none", "None (raw data)", NAT_DECODE_NONE },
958 { "dmp", "As for regular", NAT_DECODE_DMP },
959 { "thales", "Thales XOmail", NAT_DECODE_THALES },
960 { NULL, NULL, 0 }
963 static const value_string ipm_id_modifier[] = {
964 { 0x0, "X.400 IPM Identifier" },
965 { 0x1, "Nationally-defined" },
966 { 0x2, "Nationally-defined" },
967 { 0x3, "Nationally-defined" },
968 { 0, NULL }
971 static const value_string thales_ipm_id_modifier[] = {
972 { 0x0, "X.400 IPM Identifier" },
973 { 0x1, "3 or 5 digits" },
974 { 0x2, "4 digits" },
975 { 0x3, "5 digits" },
976 { 0, NULL }
979 UAT_VS_DEF(dmp_security_class, nation, dmp_security_class_t, unsigned, 0, "None")
980 UAT_DEC_CB_DEF(dmp_security_class, sec_class, dmp_security_class_t)
981 UAT_CSTRING_CB_DEF(dmp_security_class, name, dmp_security_class_t)
983 static void *
984 dmp_class_copy_cb(void *dest, const void *orig, size_t len _U_)
986 dmp_security_class_t *u = (dmp_security_class_t *)dest;
987 const dmp_security_class_t *o = (const dmp_security_class_t *)orig;
989 u->nation = o->nation;
990 u->sec_class = o->sec_class;
991 u->name = g_strdup(o->name);
993 return dest;
996 static void
997 dmp_class_free_cb(void *r)
999 dmp_security_class_t *u = (dmp_security_class_t *)r;
1001 g_free(u->name);
1004 static char *dmp_national_sec_class (unsigned nation, unsigned dmp_sec_class)
1006 unsigned i;
1008 for (i = 0; i < num_dmp_security_classes; i++) {
1009 dmp_security_class_t *u = &(dmp_security_classes[i]);
1011 if (u->nation == nation && u->sec_class == dmp_sec_class) {
1012 return u->name;
1016 return NULL;
1019 static void build_national_strings (void)
1021 unsigned i = 0;
1024 ** We use values from dmp_national_values to build value_string for nat_pol_id.
1026 for (i = 0; i < MAX_NATIONAL_VALUES; i++) {
1027 nat_pol_id[i].value = dmp_national_values[i].value;
1028 nat_pol_id[i].strptr = dmp_national_values[i].description;
1032 static const char *get_nat_pol_id_short (int nation)
1034 int i = 0;
1035 while (dmp_national_values[i].name) {
1036 if (dmp_national_values[i].value == nation) {
1037 return dmp_national_values[i].name;
1039 i++;
1042 return "???";
1045 static const char *msg_type_to_str (void)
1047 const char *msg_type;
1048 bool have_msg = false;
1050 switch (dmp.msg_type) {
1052 case STANAG:
1053 /* Include message type and precedence */
1054 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s (%s) [%s]",
1055 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1056 val_to_str_const (dmp.st_type, message_type_vals, "Unknown"),
1057 (dmp.prec == 0x6 || dmp.prec == 0x7) ?
1058 val_to_str_const (dmp.prec-4, precedence, "Unknown") :
1059 val_to_str_const (dmp.prec, precedence, "Unknown"));
1060 break;
1062 case IPM:
1063 /* Include importance */
1064 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s [%s]",
1065 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1066 val_to_str_const (dmp.prec, importance, "Unknown"));
1067 break;
1069 case REPORT:
1070 /* Include report types included */
1071 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Report (%s%s%s)",
1072 dmp.dr ? "DR" : "", (dmp.dr && dmp.ndr) ? " and " : "",
1073 dmp.ndr ? "NDR" : "");
1074 break;
1076 case NOTIF:
1077 msg_type = val_to_str_const (dmp.notif_type, notif_type, "Unknown");
1078 break;
1080 case ACK:
1081 /* If we have msg_time we have a matching packet */
1082 have_msg = (dmp.id_val &&
1083 (dmp.id_val->msg_time.secs>0 || dmp.id_val->msg_time.nsecs>0));
1084 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Acknowledgement%s%s",
1085 have_msg ? val_to_str (dmp.id_val->msg_type, ack_msg_type,
1086 " (unknown:%d)") : "",
1087 dmp.ack_reason ? " [negative]" : "");
1088 break;
1090 default:
1091 msg_type = "Unknown";
1092 break;
1095 return msg_type;
1098 static const char *non_del_reason_str (uint32_t value)
1100 if (value < 0x3D) {
1101 /* Standard values according to P1 */
1102 return val_to_str_const (value, p1_NonDeliveryReasonCode_vals, "Unknown");
1103 } else {
1104 return val_to_str_const (value, non_del_reason, "Unknown");
1108 static const char *non_del_diagn_str (uint32_t value)
1110 if (value < 0x7C) {
1111 /* Standard values according to P1 */
1112 return val_to_str_const (value, p1_NonDeliveryDiagnosticCode_vals, "Unknown");
1113 } else {
1114 return val_to_str_const (value, non_del_diagn, "Unknown");
1118 static const char *nrn_reason_str (uint32_t value)
1120 /* Standard values according to P22 */
1121 return val_to_str_const (value, p22_NonReceiptReasonField_vals, "Reserved");
1124 static const char *discard_reason_str (uint32_t value)
1126 if (value < 0xFE) {
1127 /* Standard values according to P22 */
1128 return val_to_str_const (value, p22_DiscardReasonField_vals, "Reserved");
1129 } else {
1130 return val_to_str_const (value, discard_reason, "Unknown");
1134 /* Ref chapter 6.2.8.10 TimeDifference */
1135 static int32_t dmp_dec_time_diff (uint8_t dmp_time_diff)
1137 int32_t time_diff = 0;
1139 if (dmp_time_diff <= 0x01) {
1140 /* Reserved - low value */
1141 time_diff = DMP_TIME_RESERVED;
1142 } else if (dmp_time_diff <= 0x1D) {
1143 /* Number of 2-second units (2-58 seconds) */
1144 time_diff = dmp_time_diff * 2;
1145 } else if (dmp_time_diff <= 0x91) {
1146 /* Number of 15-second units (1 min - 29 min 45 sec) */
1147 time_diff = (dmp_time_diff - 0x1D + 3) * 15;
1148 } else if (dmp_time_diff <= 0xDF) {
1149 /* Number of 5-minute units (30 min - 6 hours 55 min) */
1150 time_diff = (dmp_time_diff - 0x91 + 5) * 5*60;
1151 } else if (dmp_time_diff <= 0xF7) {
1152 /* Number of 30-minute units (7 hours - 18 hours 30 min) */
1153 time_diff = (dmp_time_diff - 0xDF + 7) * 30*60;
1154 } else {
1155 /* Reserved - high value */
1156 time_diff = DMP_TIME_RESERVED;
1159 return time_diff;
1163 * Ref chapter 6.3.7.2.10 ExpiryTime
1164 * and chapter 6.3.9.2.2 DeliveryTime
1166 static int32_t dmp_dec_exp_del_time (uint8_t timev, bool expiry_time)
1168 int32_t time_value = 0;
1170 if (expiry_time && (timev == 0x00)) {
1171 /* No expiry time */
1172 time_value = DMP_TIME_NOT_PRESENT;
1173 } else if (timev <= 0x1D) {
1174 /* Number of 2-second units (2-58 seconds) */
1175 time_value = timev * 2;
1176 } else if (timev <= 0x91) {
1177 /* Number of 15-second units (1 min - 29 min 45 sec) */
1178 time_value = (timev - 0x1D + 3) * 15;
1179 } else if (timev <= 0xBB) {
1180 /* Number of 5-minute units (30 min - 3 hours 55 min) */
1181 time_value = (timev - 0x91 + 5) * 5*60;
1182 } else if (timev <= 0xE3) {
1183 /* Number of 30-minute units (4 hours - 23 hours 30 min) */
1184 time_value = (timev - 0xBB + 7) * 30*60;
1185 } else if (timev < 0xFF) {
1186 /* Number of 2-hour units (24 - 78 hours) */
1187 time_value = (timev - 0xE3 + 11) * 2*3600;
1188 } else {
1189 /* Reserved */
1190 time_value = DMP_TIME_RESERVED;
1193 return time_value;
1196 static int32_t dmp_dec_exp_time (uint8_t expiry_time)
1198 return dmp_dec_exp_del_time (expiry_time, true);
1201 static int32_t dmp_dec_del_time (uint8_t delivery_time)
1203 return dmp_dec_exp_del_time (delivery_time, false);
1206 /* Ref chapter 6.3.7.2.11 DTG */
1207 static int32_t dmp_dec_dtg (uint32_t dtg)
1209 int32_t value;
1211 if (dtg == 0x00) {
1212 /* Not present */
1213 value = DMP_TIME_NOT_PRESENT;
1214 } else if (dtg <= 0x3C) {
1215 /* Number of minutes (0-59 min) */
1216 value = (dtg - 1) * 60;
1217 } else if (dtg <= 0x64) {
1218 /* Number of 15-minute units (1 hour - 10 hours 45 min) */
1219 value = (dtg - 0x3C + 3) * 15 * 60;
1220 } else if (dtg < 0x7F) {
1221 /* Number of hours (11-36 hours) */
1222 value = (dtg - 0x64 + 10) * 3600;
1223 } else {
1224 /* Reserved */
1225 value = DMP_TIME_RESERVED;
1228 return value;
1232 * Ref chapter 7.10.11.1 Submission time
1234 * start_time (current time)
1235 * delta1 = E (encoded submission time)
1236 * delta2 = C (encoded current time)
1237 * 0x01C2 = Pn + 15min (maximum point for S1)
1238 * 0x7E38 = Pn+1 - 15min (minimum point for S3)
1239 * 0x7FF8 = Pn+1 (length of P (period))
1241 static int32_t dmp_dec_subm_time (uint16_t delta1, int32_t start_time)
1243 int32_t subm_time = start_time;
1244 uint16_t delta2;
1246 delta2 = (uint16_t) ((subm_time / 2) % 0x7FF8);
1248 if ((delta1 < 0x01C2) && (delta2 >= delta1 + 0x7E38)) {
1249 subm_time += 2 * (0x7FF8 - delta2 + delta1);
1250 } else if ((delta1 >= 0x01C2) && (delta2 < delta1 - 0x01C2)) {
1251 subm_time -= 2 * (0x7FF8 - delta1 + delta2);
1252 } else {
1253 subm_time -= 2 * (delta2 - delta1);
1256 return subm_time;
1259 /* Ref chapter 6.3.7.2.12 SIC */
1260 static bool dmp_dec_xbyte_sic (uint64_t bin, char *sic,
1261 uint8_t no_char, bool any)
1263 bool failure = false;
1264 double multiplier;
1265 uint8_t i;
1266 uint64_t p, tmp;
1268 if (no_char >= MAX_SIC_LEN) {
1269 /* Illegal length */
1270 snprintf (sic, MAX_SIC_LEN, "Illegal length: %d", no_char);
1271 return true;
1274 if (any) {
1275 multiplier = 74.0;
1276 } else {
1277 multiplier = 36.0;
1280 for (i = 0; i < no_char; i++) {
1281 p = (uint64_t) pow (multiplier, no_char - 1 - i);
1282 tmp = bin / p;
1283 bin -= tmp * p;
1284 sic[i] = (char) tmp;
1285 if (sic[i] <= 9) {
1286 sic[i] += '0';
1287 } else if (sic[i] <= 35) {
1288 sic[i] += ('A' - 10);
1289 } else if (!any) {
1290 sic[i] = '*';
1291 failure = true;
1292 } else if (sic[i] <= 61) {
1293 sic[i] += ('a' - 36);
1294 } else if (sic[i] == 62) {
1295 sic[i] = '\'';
1296 } else if (sic[i] == 63) {
1297 sic[i] = '(';
1298 } else if (sic[i] == 64) {
1299 sic[i] = ')';
1300 } else if (sic[i] == 65) {
1301 sic[i] = '+';
1302 } else if (sic[i] == 66) {
1303 sic[i] = ',';
1304 } else if (sic[i] == 67) {
1305 sic[i] = '-';
1306 } else if (sic[i] == 68) {
1307 sic[i] = '.';
1308 } else if (sic[i] == 69) {
1309 sic[i] = '/';
1310 } else if (sic[i] == 70) {
1311 sic[i] = ':';
1312 } else if (sic[i] == 71) {
1313 sic[i] = '=';
1314 } else if (sic[i] == 72) {
1315 sic[i] = '?';
1316 } else if (sic[i] == 73) {
1317 sic[i] = ' ';
1318 } else {
1319 sic[i] = '*';
1320 failure = true;
1322 if (!g_ascii_isprint(sic[i])) {
1323 sic[i] = '*';
1324 failure = true;
1327 sic[i] = '\0';
1329 return failure;
1332 static unsigned dmp_id_hash (const void *k)
1334 const dmp_id_key *dmpx=(const dmp_id_key *)k;
1335 return dmpx->id;
1338 static int dmp_id_hash_equal (const void *k1, const void *k2)
1340 const dmp_id_key *dmp1=(const dmp_id_key *)k1;
1341 const dmp_id_key *dmp2=(const dmp_id_key *)k2;
1342 if (dmp1->id != dmp2->id)
1343 return 0;
1345 return (addresses_equal (&dmp1->src, &dmp2->src) &&
1346 addresses_equal (&dmp1->dst, &dmp2->dst));
1349 static void register_dmp_id (packet_info *pinfo, uint8_t reason)
1351 dmp_id_val *dmp_data = NULL, *pkg_data = NULL;
1352 dmp_id_key *dmp_key = NULL;
1353 nstime_t msg_time;
1354 unsigned msg_id = 0;
1356 if (pinfo->flags.in_error_pkt) {
1357 /* No analysis of error packets */
1358 return;
1361 nstime_set_zero(&msg_time);
1363 dmp_key = wmem_new (wmem_file_scope(), dmp_id_key);
1365 if (!pinfo->fd->visited &&
1366 (dmp.msg_type == REPORT || dmp.msg_type == NOTIF))
1368 /* Try to match corresponding message */
1369 dmp_key->id = (unsigned) dmp.subj_id;
1370 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->dst));
1371 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->src));
1373 dmp_data = (dmp_id_val *) wmem_map_lookup (dmp_id_hash_table, dmp_key);
1375 if (dmp_data) {
1376 /* Found message */
1377 if (dmp_data->prev_msg_id > 0) {
1378 msg_id = dmp_data->prev_msg_id;
1379 } else {
1380 msg_id = dmp_data->msg_id;
1382 msg_time = dmp_data->msg_time;
1386 if (dmp.msg_type == ACK) {
1387 dmp_key->id = (unsigned) dmp.subj_id;
1388 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->dst));
1389 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->src));
1390 } else {
1391 dmp_key->id = (unsigned) dmp.msg_id;
1392 copy_address_wmem(wmem_file_scope(), &dmp_key->src, &(pinfo->src));
1393 copy_address_wmem(wmem_file_scope(), &dmp_key->dst, &(pinfo->dst));
1396 dmp_data = (dmp_id_val *) wmem_map_lookup (dmp_id_hash_table, dmp_key);
1398 if (!pinfo->fd->visited) {
1399 if (dmp_data) {
1400 if (dmp.msg_type == ACK) {
1401 /* Only save this data if positive ack */
1402 if (reason == 0) {
1403 if (dmp_data->ack_id == 0) {
1404 /* Only save reference to first ACK */
1405 dmp_data->ack_id = pinfo->num;
1406 } else {
1407 /* Only count when resending */
1408 dmp_data->ack_resend_count++;
1411 } else {
1412 /* Message resent */
1413 dmp_data->msg_resend_count++;
1414 dmp_data->prev_msg_id = pinfo->num;
1415 dmp_data->prev_msg_time = dmp_data->msg_time;
1416 dmp_data->msg_time = pinfo->abs_ts;
1418 } else {
1419 /* New message */
1420 dmp_data = wmem_new0 (wmem_file_scope(), dmp_id_val);
1421 dmp_data->msg_type = dmp.msg_type;
1423 if (dmp.msg_type == ACK) {
1424 /* No matching message for this ack */
1425 dmp_data->ack_id = pinfo->num;
1426 } else {
1427 dmp_data->first_msg_time = pinfo->abs_ts;
1428 dmp_data->msg_time = pinfo->abs_ts;
1430 if (dmp.msg_type == REPORT) {
1431 dmp_data->rep_id = pinfo->num;
1432 dmp_data->msg_id = msg_id;
1433 dmp_data->rep_not_msg_time = msg_time;
1434 } else if (dmp.msg_type == NOTIF) {
1435 dmp_data->not_id = pinfo->num;
1436 dmp_data->msg_id = msg_id;
1437 dmp_data->rep_not_msg_time = msg_time;
1438 } else {
1439 dmp_data->msg_id = pinfo->num;
1442 wmem_map_insert (dmp_id_hash_table, dmp_key, dmp_data);
1446 pkg_data = wmem_new (wmem_file_scope(), dmp_id_val);
1447 *pkg_data = *dmp_data;
1448 p_add_proto_data(wmem_file_scope(), pinfo, proto_dmp, 0, pkg_data);
1449 } else {
1450 /* Fetch last values from data saved in packet */
1451 pkg_data = (dmp_id_val *)p_get_proto_data(wmem_file_scope(), pinfo, proto_dmp, 0);
1453 if (dmp_data && pkg_data && dmp.msg_type != ACK && pkg_data->ack_id == 0) {
1454 pkg_data->ack_id = dmp_data->ack_id;
1458 DISSECTOR_ASSERT (pkg_data);
1459 dmp.id_val = pkg_data;
1462 static void dmp_add_seq_ack_analysis (tvbuff_t *tvb, packet_info *pinfo,
1463 proto_tree *dmp_tree, int offset)
1465 proto_tree *analysis_tree = NULL;
1466 proto_item *en = NULL, *eh = NULL;
1467 nstime_t ns;
1469 if (dmp.msg_type > ACK || (dmp.msg_type < ACK && !dmp.checksum) ||
1470 dmp.id_val == NULL || pinfo->flags.in_error_pkt)
1472 /* No need for seq/ack analysis */
1473 return;
1476 analysis_tree = proto_tree_add_subtree(dmp_tree, tvb, 0, 0, ett_analysis, &en, "SEQ/ACK analysis");
1477 proto_item_set_generated (en);
1479 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
1480 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) {
1481 if (dmp.id_val->ack_id) {
1482 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb,
1483 0, 0, dmp.id_val->ack_id);
1484 proto_item_set_generated (en);
1485 if (!dmp.checksum) {
1486 proto_item_append_text (en, " (unexpected)");
1487 expert_add_info(pinfo, en, &ei_analysis_ack_unexpected);
1489 } else if (dmp.checksum && !dmp.id_val->msg_resend_count) {
1490 en = proto_tree_add_item (analysis_tree, hf_analysis_ack_missing, tvb, offset, 0, ENC_NA);
1491 if (pinfo->fd->visited) {
1492 /* We do not know this on first visit and we do not want to
1493 add a entry in the "Expert Severity Info" for this note */
1494 expert_add_info(pinfo, en, &ei_analysis_ack_missing);
1495 proto_item_set_generated (en);
1499 if (dmp.msg_type == REPORT) {
1500 if (dmp.id_val->msg_id) {
1501 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1502 tvb, 0, 0, dmp.id_val->msg_id);
1503 proto_item_set_generated (en);
1505 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->rep_not_msg_time);
1506 en = proto_tree_add_time (analysis_tree, hf_analysis_rep_time,
1507 tvb, 0, 0, &ns);
1508 proto_item_set_generated (en);
1509 } else {
1510 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1512 } else if (dmp.msg_type == NOTIF) {
1513 if (dmp.id_val->msg_id) {
1514 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1515 tvb, 0, 0, dmp.id_val->msg_id);
1516 proto_item_set_generated (en);
1518 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->rep_not_msg_time);
1519 en = proto_tree_add_time (analysis_tree, hf_analysis_not_time,
1520 tvb, 0, 0, &ns);
1521 proto_item_set_generated (en);
1522 } else {
1523 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1527 if (dmp.id_val->msg_resend_count) {
1528 en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no,
1529 tvb, 0, 0, dmp.id_val->msg_resend_count);
1530 proto_item_set_generated (en);
1532 expert_add_info_format(pinfo, en, &ei_analysis_retrans_no, "Retransmission #%d", dmp.id_val->msg_resend_count);
1534 if (dmp.msg_type == REPORT) {
1535 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_resend_from,
1536 tvb, 0, 0, dmp.id_val->rep_id);
1537 } else if (dmp.msg_type == NOTIF) {
1538 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_resend_from,
1539 tvb, 0, 0, dmp.id_val->not_id);
1540 } else {
1541 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_resend_from,
1542 tvb, 0, 0, dmp.id_val->msg_id);
1544 proto_item_set_generated (en);
1546 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->prev_msg_time);
1547 en = proto_tree_add_time (analysis_tree, hf_analysis_retrans_time,
1548 tvb, 0, 0, &ns);
1549 proto_item_set_generated (en);
1551 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->first_msg_time);
1552 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_retrans_time,
1553 tvb, 0, 0, &ns);
1554 proto_item_set_generated (eh);
1556 if (dmp.id_val->first_msg_time.secs == dmp.id_val->prev_msg_time.secs &&
1557 dmp.id_val->first_msg_time.nsecs == dmp.id_val->prev_msg_time.nsecs) {
1558 /* Time values does not differ, hide the total time */
1559 proto_item_set_hidden (eh);
1562 } else if (dmp.msg_type == ACK) {
1563 if (dmp.id_val->msg_type != ACK) {
1564 if (dmp.id_val->msg_type == REPORT) {
1565 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_rep_num,
1566 tvb, 0, 0, dmp.id_val->rep_id);
1567 } else if (dmp.id_val->msg_type == NOTIF) {
1568 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_not_num,
1569 tvb, 0, 0, dmp.id_val->not_id);
1570 } else {
1571 en = proto_tree_add_uint (analysis_tree, hf_analysis_acks_msg_num,
1572 tvb, 0, 0, dmp.id_val->msg_id);
1574 proto_item_set_generated (en);
1576 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->msg_time);
1577 en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time,
1578 tvb, 0, 0, &ns);
1579 proto_item_set_generated (en);
1581 nstime_delta (&ns, &pinfo->abs_ts, &dmp.id_val->first_msg_time);
1582 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time,
1583 tvb, 0, 0, &ns);
1584 proto_item_set_generated (eh);
1586 if (dmp.id_val->first_msg_time.secs == dmp.id_val->msg_time.secs &&
1587 dmp.id_val->first_msg_time.nsecs == dmp.id_val->msg_time.nsecs) {
1588 /* Time values does not differ, hide the total time */
1589 proto_item_set_hidden (eh);
1590 } else {
1591 /* Different times, add a reference to the message we have ack'ed */
1592 proto_item_append_text (en, " (from frame %d)",
1593 dmp.id_val->prev_msg_id);
1595 } else {
1596 proto_tree_add_expert (analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1599 if (dmp.id_val->ack_resend_count) {
1600 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no,
1601 tvb, 0, 0, dmp.id_val->ack_resend_count);
1602 proto_item_set_generated (en);
1604 expert_add_info_format(pinfo, en, &ei_analysis_ack_dup_no, "Dup ACK #%d", dmp.id_val->ack_resend_count);
1606 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from,
1607 tvb, 0, 0, dmp.id_val->ack_id);
1608 proto_item_set_generated (en);
1613 static const char *dissect_7bit_string (tvbuff_t *tvb, int offset, int length, unsigned char *byte_rest)
1615 unsigned char *encoded, *decoded;
1616 unsigned char rest = 0, bits = 1;
1617 int len = 0, i;
1619 if (length <= 0) {
1620 if (byte_rest) {
1621 *byte_rest = '\0';
1623 return "";
1626 encoded = (unsigned char *)tvb_memdup (wmem_packet_scope(), tvb, offset, length);
1627 decoded = (unsigned char *)wmem_alloc0 (wmem_packet_scope(), (size_t)(length * 1.2) + 1);
1628 for (i = 0; i < length; i++) {
1629 decoded[len++] = encoded[i] >> bits | rest;
1630 rest = (encoded[i] << (7 - bits) & 0x7F);
1631 if (bits == 7) {
1632 decoded[len++] = rest;
1633 bits = 1;
1634 rest = 0;
1635 } else {
1636 bits++;
1640 if (byte_rest) {
1641 *byte_rest = rest;
1644 return decoded;
1647 static const char *dissect_thales_mts_id (tvbuff_t *tvb, int offset, int length, unsigned char *byte_rest)
1649 /* Thales XOmail uses this format: "MTA-NAME/000000000000" */
1650 if (length >= 7 && length <= 22) {
1651 return wmem_strdup_printf (wmem_packet_scope(), "%s/%08X%04X",
1652 dissect_7bit_string (tvb, offset, length - 6, byte_rest),
1653 tvb_get_ntohl (tvb, offset + length - 6),
1654 tvb_get_ntohs (tvb, offset + length - 2));
1657 return ILLEGAL_FORMAT;
1660 static const char *dissect_thales_ipm_id (tvbuff_t *tvb, int offset, int length, int modifier, unsigned char *byte_rest)
1662 /* Thales XOmail uses this format: "<prefix>0000 YYMMDDhhmmssZ" */
1663 if (length >= 6 && length <= 20 && modifier >= 0 && modifier <= 2) {
1664 unsigned number = tvb_get_ntohs (tvb, offset + length - 6);
1665 uint8_t number_len = modifier + 2;
1666 time_t timev = tvb_get_ntohl(tvb, offset + length - 4);
1667 struct tm *tmp = gmtime(&timev);
1669 if (tmp == NULL)
1670 return TIME_NOT_REPRESENTABLE;
1672 if (modifier == 1 && number >= 1024) {
1673 /* The number is in the range 65536-99999 */
1674 number_len = 5;
1675 number += (65536 - 1024);
1678 return wmem_strdup_printf (wmem_packet_scope(), "%s%0*d %02d%02d%02d%02d%02d%02dZ",
1679 (length == 6) ? "" : dissect_7bit_string (tvb, offset, length - 6, byte_rest),
1680 number_len, number,
1681 tmp->tm_year % 100, tmp->tm_mon + 1, tmp->tm_mday,
1682 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1685 return ILLEGAL_FORMAT;
1688 /* Ref chapter 6.3.7.2.12 SIC */
1689 static int dissect_dmp_sic (tvbuff_t *tvb, packet_info *pinfo,
1690 proto_tree *message_tree, int offset)
1692 proto_tree *sic_tree = NULL, *bitmap_tree = NULL, *key_tree = NULL;
1693 proto_item *sf = NULL, *bf = NULL, *kf = NULL;
1694 uint64_t value;
1695 uint8_t key, bitmap, no, i, length = 0;
1696 bool any, no_sic = false, failure = false;
1697 int bytes = 0, boffset = offset;
1698 char *sic = NULL;
1700 key = tvb_get_uint8 (tvb, offset);
1701 sic = (char *)wmem_alloc (pinfo->pool, MAX_SIC_LEN);
1703 if (key <= 0xB6) {
1704 /* 2 bytes, single 3-character SIC, characters [A-Z0-9] only */
1706 value = tvb_get_ntohs (tvb, offset);
1707 failure = dmp_dec_xbyte_sic (value, sic, 3, false);
1708 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1709 offset, 2, sic,
1710 "%s [A-Z0-9 only]%s", sic,
1711 failure ? " (invalid)": "");
1712 if (failure) {
1713 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1715 offset += 2;
1717 } else if (key <= 0xBD) {
1718 /* 3 bytes, single 3-character SIC, any valid character */
1720 value = tvb_get_ntohl (tvb, offset);
1721 value = (value >> 8) & 0x48FFFF;
1722 failure = dmp_dec_xbyte_sic (value, sic, 3, true);
1723 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1724 offset, 3, sic,
1725 "%s [any character]%s", sic,
1726 failure ? " (invalid)": "");
1727 if (failure) {
1728 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1730 offset += 3;
1732 } else if (key <= 0xBF) {
1733 /* Reserved (not used) */
1734 snprintf (sic, MAX_SIC_LEN, "Reserved");
1735 no_sic = true;
1737 } else if (key <= 0xCF) {
1738 /* 2 or more 3-character SICs */
1740 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1741 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1743 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1744 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1746 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1747 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1748 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1749 offset += 1;
1751 any = (key & 0x08);
1752 no = (key & 0x07) + 1;
1753 for (i = 0; i < no; i++) {
1754 if (any) {
1755 value = tvb_get_ntohl (tvb, offset);
1756 value = (value >> 8) & 0x48FFFF;
1757 bytes = 3;
1758 } else {
1759 value = tvb_get_ntohs (tvb, offset);
1760 bytes = 2;
1762 failure = dmp_dec_xbyte_sic (value, sic, 3, any);
1763 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1764 offset, bytes, sic,
1765 "SIC %d: %s%s", i + 1, sic,
1766 failure ? " (invalid)": "");
1767 if (failure) {
1768 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1770 offset += bytes;
1772 proto_item_append_text (sf, ": %d (3 %s character)", no,
1773 any ? "any" : "[A-Z0-9]");
1775 } else if (key <= 0xDF) {
1776 /* 1 or more 3 to 8 character SICs */
1778 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1779 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1781 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1782 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1784 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1785 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1786 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1787 offset += 1;
1789 bitmap = tvb_get_uint8 (tvb, offset);
1790 bf = proto_tree_add_uint_format (sic_tree, hf_message_sic_bitmap, tvb,
1791 offset, 1, bitmap,
1792 "Length Bitmap: 0x%2.2x", bitmap);
1793 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bitmap);
1794 proto_tree_add_item (bitmap_tree, hf_message_sic_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
1796 any = (key & 0x08);
1797 no = (key & 0x07) + 1;
1798 offset += 1;
1800 for (i = 0; i < no; i++) {
1801 if (bitmap & (1 << (7 - i))) {
1802 /* 4 - 8 character */
1803 key = tvb_get_uint8 (tvb, offset);
1804 if (any) {
1805 /* Any valid characters */
1806 if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1807 length = 4;
1808 bytes = 4;
1809 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1810 } else if ((key & 0xC0) == 0xC0) { /* bit 7-4: 11xx */
1811 length = 6;
1812 bytes = 5;
1813 value = ((uint64_t)key & 0x3F)<<32|tvb_get_ntohl (tvb, offset + 1);
1814 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1815 length = 7;
1816 bytes = 6;
1817 value = ((uint64_t)(tvb_get_ntohs (tvb, offset) & 0x0FFF)) << 32 |
1818 tvb_get_ntohl (tvb, offset + 2);
1819 } else if ((key & 0xF0) == 0x90) { /* bit 7-4: 1001 */
1820 length = 8;
1821 bytes = 7;
1822 value = ((uint64_t)((tvb_get_ntohl (tvb, offset)>>8) & 0x0FFF))<<32 |
1823 tvb_get_ntohl (tvb, offset + 3);
1824 } else { /* bit 7-4: 0xxx or 1000 */
1825 length = 5;
1826 bytes = 4;
1827 value = tvb_get_ntohl (tvb, offset);
1829 } else {
1830 /* Characters [A-Z0-9] only */
1831 if ((key & 0xE0) == 0xC0) { /* bit 7-4: 110x */
1832 length = 4;
1833 bytes = 3;
1834 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x1FFFFF;
1835 } else if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1836 length = 5;
1837 bytes = 4;
1838 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1839 } else if ((key & 0xE0) == 0xE0) { /* bit 7-4: 111x */
1840 length = 7;
1841 bytes = 5;
1842 value = ((uint64_t)key & 0x1F)<<32 | tvb_get_ntohl (tvb, offset +1);
1843 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1844 length = 8;
1845 bytes = 6;
1846 value = ((uint64_t)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
1847 tvb_get_ntohl (tvb, offset + 2);
1848 } else { /* bit 7-4: 0xxx or 1000 */
1849 length = 6;
1850 bytes = 4;
1851 value = tvb_get_ntohl (tvb, offset);
1854 } else {
1855 /* 3 character */
1856 if (any) {
1857 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x48FFFF;
1858 length = 3;
1859 bytes = 3;
1860 } else {
1861 value = tvb_get_ntohs (tvb, offset);
1862 length = 3;
1863 bytes = 2;
1866 failure = dmp_dec_xbyte_sic (value, sic, length, any);
1867 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1868 offset, bytes, sic,
1869 "SIC %d: %s (%d bytes: %" PRIx64 ")%s",
1870 i + 1, sic, bytes, value,
1871 failure ? " (invalid)": "");
1872 if (bitmap & (1 << (7 - i))) {
1873 /* Only if 4 - 8 character */
1874 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bits);
1875 if (any) {
1876 proto_tree_add_item (bitmap_tree, hf_message_sic_bits_any, tvb, offset, 1, ENC_BIG_ENDIAN);
1877 } else {
1878 proto_tree_add_item (bitmap_tree, hf_message_sic_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
1881 if (failure) {
1882 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1884 offset += bytes;
1886 proto_item_append_text (sf, ": %d (3-to-8 %s character)", no,
1887 any ? "any" : "[A-Z0-9]");
1889 } else if (key == 0xFE) {
1890 /* No SIC */
1891 snprintf (sic, MAX_SIC_LEN, "Not present");
1892 no_sic = true;
1894 } else {
1895 /* Resered (not used) */
1896 snprintf (sic, MAX_SIC_LEN, "Reserved");
1897 no_sic = true;
1900 if (no_sic) {
1901 /* Not added any SIC, dump text value */
1902 sf = proto_tree_add_string (message_tree, hf_message_sic, tvb, offset, 1, sic);
1903 offset += 1;
1906 proto_item_set_len (sf, offset - boffset);
1908 return offset;
1911 /* Ref chapter 5.2.7.1 Direct Originator Encoding */
1912 static int dissect_dmp_direct_addr (tvbuff_t *tvb, packet_info *pinfo,
1913 proto_tree *field_tree, proto_item *tf,
1914 int offset, int rec_no,
1915 int rec_ofs, int addr_type)
1917 proto_tree *addr_tree = NULL;
1918 proto_item *en = NULL;
1919 int dir_addr;
1920 uint8_t value;
1922 value = tvb_get_uint8 (tvb, offset);
1923 dir_addr = (value & 0x7F);
1924 if (value & 0x80) {
1925 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1, tvb,
1926 offset, 1, value,
1927 "%sDirect Address (bits 6-0): %d",
1928 val_to_str_const (addr_type, addr_type_str, ""),
1929 value & 0x7F);
1930 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1931 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1932 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1933 offset += 1;
1935 /* Extended 1 */
1936 value = tvb_get_uint8 (tvb, offset);
1937 dir_addr |= ((value & 0x3F) << 7);
1938 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
1939 offset, 1, value,
1940 "%sDirect Address (bits 12-7): %d",
1941 val_to_str_const (addr_type, addr_type_str, ""),
1942 value & 0x3F);
1943 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1944 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1945 en = proto_tree_add_item (addr_tree, hf_reserved_0x40, tvb, offset, 1, ENC_BIG_ENDIAN);
1946 if (value & 0x40) {
1947 expert_add_info(pinfo, en, &ei_reserved_value);
1949 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
1950 offset += 1;
1952 if (value & 0x80) {
1953 /* Extended 2 */
1954 value = tvb_get_uint8 (tvb, offset);
1955 dir_addr |= ((value & 0x3F) << 13);
1956 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
1957 offset, 1, value,
1958 "%sDirect Address (bits 18-13): %d",
1959 val_to_str_const (addr_type,addr_type_str,""),
1960 value & 0x3F);
1961 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1962 en = proto_tree_add_item (addr_tree, hf_reserved_0xC0, tvb, offset, 1, ENC_BIG_ENDIAN);
1963 if (value & 0xC0) {
1964 expert_add_info(pinfo, en, &ei_reserved_value);
1966 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
1967 offset += 1;
1970 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
1971 tvb, offset, 0, dir_addr,
1972 "%sDirect Address: %d",
1973 val_to_str_const (addr_type, addr_type_str, ""),
1974 dir_addr);
1975 proto_item_set_generated (en);
1976 } else {
1977 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address, tvb,
1978 offset, 1, value,
1979 "%sDirect Address: %d",
1980 val_to_str_const (addr_type, addr_type_str, ""),
1981 value & 0x7F);
1982 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1983 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1984 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1985 offset += 1;
1988 if (rec_no != -1) {
1989 proto_item_append_text (tf, " %d", rec_no);
1990 if (rec_ofs != -1) {
1991 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
1994 proto_item_append_text (tf, ", %sDirect Address: %d",
1995 val_to_str_const (addr_type, addr_type_str, ""), dir_addr);
1997 return offset;
2000 /* Ref 5.3.14 Extended Address */
2001 static int dissect_dmp_ext_addr (tvbuff_t *tvb, packet_info *pinfo,
2002 proto_tree *field_tree, proto_item *tf,
2003 int offset, int rec_no, int rec_ofs,
2004 int addr_type)
2006 proto_tree *addr_tree = NULL, *ext_tree = NULL;
2007 proto_item *en = NULL, *ef = NULL;
2008 int type, length;
2009 uint8_t value;
2010 int boffset = offset;
2011 bool addr_length_extended = false;
2012 asn1_ctx_t asn1_ctx;
2014 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
2016 value = tvb_get_uint8 (tvb, offset);
2017 type = (value & 0xE0) >> 5;
2018 length = (value & 0x1F);
2019 ef = proto_tree_add_none_format (field_tree, hf_addr_ext_address, tvb,
2020 offset, -1, "%sExtended Address",
2021 val_to_str_const (addr_type, addr_type_str, ""));
2022 ext_tree = proto_item_add_subtree (ef, ett_address_extended);
2024 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type, tvb,
2025 offset, 1, value, "Address Type: %s",
2026 val_to_str_const (type, ext_addr_type,
2027 "Reserved"));
2028 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2029 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2031 if (value & 0x80) {
2032 addr_length_extended = true;
2033 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length1, tvb,
2034 offset, 1, value,
2035 "Address Length (bits 4-0): %d", length);
2036 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2037 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2038 offset += 1;
2040 /* Extended */
2041 value = tvb_get_uint8 (tvb, offset);
2042 type = ((value & 0xE0) >> 5);
2043 length |= ((value & 0x1F) << 5);
2045 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type_ext, tvb,
2046 offset, 1, value, "Address Type Ext: %s",
2047 val_to_str_const (type, ext_addr_type_ext,
2048 "Reserved"));
2049 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2050 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2052 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length2, tvb,
2053 offset, 1, value,
2054 "Address Length (bits 9-5): %d",
2055 value & 0x1F);
2056 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2057 proto_tree_add_item (addr_tree, hf_addr_ext_length2, tvb, offset, 1, ENC_BIG_ENDIAN);
2058 offset += 1;
2059 } else {
2060 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length, tvb,
2061 offset, 1, value, "Address Length: %d",
2062 length);
2063 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2064 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2065 offset += 1;
2068 if (type == ASN1_BER) {
2069 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, length);
2071 dissect_p1_ORName (false, next_tvb, 0, &asn1_ctx, ext_tree,
2072 hf_addr_ext_asn1_ber);
2073 } else if (type == ASN1_PER) {
2074 proto_tree_add_item (ext_tree, hf_addr_ext_asn1_per, tvb, offset, length, ENC_NA);
2075 } else {
2076 proto_tree_add_item (ext_tree, hf_addr_ext_unknown, tvb, offset, length, ENC_NA);
2078 offset += length;
2080 if (addr_length_extended) {
2081 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length_generated,
2082 tvb, offset, 0, length,
2083 "Address Length: %d", length);
2084 proto_item_set_generated (en);
2087 proto_item_append_text (ef, ", Type: %s, Length: %d",
2088 val_to_str_const (type, ext_addr_type, "Reserved"),
2089 length);
2091 if (rec_no != -1) {
2092 proto_item_append_text (tf, " %d", rec_no);
2093 if (rec_ofs != -1) {
2094 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2097 proto_item_append_text (tf, ", %sExtended Address Type: %s",
2098 val_to_str_const (addr_type, addr_type_str, ""),
2099 val_to_str_const (type, ext_addr_type_short, "Reserved"));
2101 proto_item_set_len (ef, offset - boffset);
2103 return offset;
2106 /* Ref chapter 5.2.8.1 Extended Originator Encoding */
2107 static int dissect_dmp_originator (tvbuff_t *tvb, packet_info *pinfo,
2108 proto_tree *envelope_tree, int offset)
2110 proto_tree *field_tree = NULL, *rec_tree = NULL;
2111 proto_item *en = NULL, *tf = NULL;
2112 uint8_t value, dmp_addr_form;
2113 int boffset = offset;
2114 bool p2_addr = false;
2116 tf = proto_tree_add_item (envelope_tree, hf_addr_originator, tvb, offset, -1, ENC_NA);
2117 field_tree = proto_item_add_subtree (tf, ett_address);
2119 if (dmp.addr_enc == DIRECT_ADDR) {
2120 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf,
2121 offset, -1, -1, ORIGINATOR);
2122 } else {
2123 value = tvb_get_uint8 (tvb, offset);
2124 dmp_addr_form = (value & 0xE0) >> 5;
2126 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2127 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig_v1, tvb,
2128 offset, 1, value,
2129 "Address Form: %s",
2130 val_to_str_const (dmp_addr_form,
2131 addr_form_orig_v1, "Reserved"));
2132 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2133 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig_v1, tvb, offset, 1, ENC_BIG_ENDIAN);
2134 } else {
2135 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig, tvb,
2136 offset, 1, value,
2137 "Address Form: %s",
2138 val_to_str_const (dmp_addr_form,
2139 addr_form_orig, "Reserved"));
2140 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2141 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig, tvb, offset, 1, ENC_BIG_ENDIAN);
2144 en = proto_tree_add_item (rec_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
2145 if (value & 0x1F) {
2146 expert_add_info(pinfo, en, &ei_reserved_value);
2148 offset += 1;
2150 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2151 switch (dmp_addr_form) {
2153 case P1_DIRECT:
2154 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2155 tf, offset, -1, -1,
2156 ORIGINATOR);
2157 break;
2159 case P1_EXTENDED:
2160 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2161 -1, ORIGINATOR);
2162 break;
2164 default:
2165 proto_item_append_text (tf, " (invalid address form)");
2166 break;
2169 } else {
2170 switch (dmp_addr_form) {
2172 case P1_DIRECT:
2173 case P1_P2_DIRECT:
2174 case P1_DIRECT_P2_EXTENDED:
2175 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2176 tf, offset, -1, -1,
2177 ORIGINATOR);
2178 break;
2180 case P1_EXTENDED:
2181 case P1_EXTENDED_P2_DIRECT:
2182 case P1_P2_EXTENDED:
2183 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2184 -1, ORIGINATOR);
2185 break;
2187 default:
2188 proto_item_append_text (tf, " (invalid address form)");
2189 break;
2193 switch (dmp_addr_form) {
2195 case P1_P2_DIRECT:
2196 case P1_EXTENDED_P2_DIRECT:
2197 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2198 tf, offset, -1, -1,
2199 ORIG_P2_ADDRESS);
2200 p2_addr = true;
2201 break;
2203 case P1_DIRECT_P2_EXTENDED:
2204 case P1_P2_EXTENDED:
2205 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2206 -1, ORIG_P2_ADDRESS);
2207 p2_addr = true;
2208 break;
2213 if (p2_addr) {
2214 if (dmp.msg_type == NOTIF) {
2215 en = proto_tree_add_boolean (field_tree, hf_addr_int_rec, tvb,
2216 offset, 0, true);
2217 } else {
2218 en = proto_tree_add_boolean (field_tree, hf_addr_dl_expanded, tvb,
2219 offset, 0, true);
2221 proto_item_set_generated (en);
2224 proto_item_set_len (tf, offset - boffset);
2226 return offset;
2229 static void dmp_add_recipient_info (proto_item *tf, uint8_t rep_req,
2230 uint8_t not_req, bool action)
2232 if (rep_req || not_req) {
2233 proto_item_append_text (tf, ", Request:");
2235 if (rep_req) {
2236 proto_item_append_text (tf, "%s",
2237 val_to_str_const (rep_req, report_vals_short, ""));
2239 if (not_req) {
2240 dmp.notif_req = true;
2241 proto_item_append_text (tf, "%s",
2242 val_to_str_const (not_req, notif_vals_short, ""));
2244 if (action) {
2245 if (dmp.msg_type == STANAG) {
2246 proto_item_append_text (tf, " (Action)");
2247 } else if (dmp.msg_type == IPM) {
2248 proto_item_append_text (tf, " (To)");
2250 } else {
2251 if (dmp.msg_type == STANAG) {
2252 proto_item_append_text (tf, " (Info)");
2253 } else if (dmp.msg_type == IPM) {
2254 proto_item_append_text (tf, " (Cc)");
2259 /* Ref chapter 5.2.7 Direct Recipient Encoding */
2260 static int dissect_dmp_direct_encoding (tvbuff_t *tvb, packet_info *pinfo,
2261 proto_tree *field_tree, proto_item *tf,
2262 int offset, unsigned *prev_rec_no)
2265 proto_tree *addr_tree = NULL, *rec_tree = NULL;
2266 proto_item *en = NULL;
2267 uint8_t rep_req = 0, not_req = 0, value;
2268 int rec_no, rec_ofs = -1, dir_addr;
2269 bool action = false, dir_addr_extended = false;
2271 value = tvb_get_uint8 (tvb, offset);
2272 rec_no = (value & 0xF0) >> 4;
2273 rep_req = (value & 0x0C) >> 2;
2274 not_req = (value & 0x03);
2276 if (rep_req == 0x03) {
2277 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no1,
2278 tvb, offset, 1, value,
2279 "Recipient Number (bits 3-0): %d"
2280 " (offset from previous)",
2281 (value & 0xF0) >> 4);
2282 } else {
2283 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no,
2284 tvb, offset, 1, value,
2285 "Recipient Number Offset: %d"
2286 " (offset from previous)",
2287 (value & 0xF0) >> 4);
2289 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2290 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2291 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2292 proto_tree_add_item (rec_tree, hf_addr_dir_not_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2293 offset += 1;
2295 value = tvb_get_uint8 (tvb, offset);
2296 dir_addr = (value & 0x7F);
2297 action = (value & 0x80);
2298 if (not_req == 0x03) {
2299 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1,
2300 tvb, offset, 1, value,
2301 "Direct Address (bits 6-0): %d",
2302 value & 0x7F);
2303 } else {
2304 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address,
2305 tvb, offset, 1, value,
2306 "Direct Address: %d",
2307 value & 0x7F);
2309 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2310 proto_tree_add_item (addr_tree, hf_addr_dir_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2311 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2312 offset += 1;
2314 if (rep_req == 0x03) {
2315 /* Extended Recipient Number 1 */
2316 value = tvb_get_uint8 (tvb, offset);
2317 rec_no |= ((value & 0x3F) << 4);
2318 rec_ofs = rec_no;
2319 rep_req = (value & 0xC0) >> 6;
2321 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no2,
2322 tvb, offset, 1, value,
2323 "Recipient Number (bits 9-4): %d"
2324 " (offset from previous)",
2325 value & 0x3F);
2326 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2327 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2328 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2329 offset += 1;
2331 if (rep_req == 0x03) {
2332 /* Extended Recipient Number 2 */
2333 value = tvb_get_uint8 (tvb, offset);
2334 rec_no |= ((value & 0x1F) << 10);
2335 rec_ofs = rec_no;
2336 rep_req = (value & 0xC0) >> 6;
2338 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no3,
2339 tvb, offset, 1, value,
2340 "Recipient Number (bits 14-10): %d"
2341 " (offset from previous)",
2342 value & 0x1F);
2343 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2344 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2345 en = proto_tree_add_item (rec_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
2346 if (value & 0x20) {
2347 expert_add_info(pinfo, en, &ei_reserved_value);
2349 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no3, tvb, offset, 1, ENC_BIG_ENDIAN);
2350 offset += 1;
2354 if (not_req == 0x03) {
2355 /* Extended Direct Address 1 */
2356 dir_addr_extended = true;
2357 value = tvb_get_uint8 (tvb, offset);
2358 dir_addr |= ((value & 0x3F) << 7);
2359 not_req = (value & 0xC0) >> 6;
2361 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
2362 offset, 1, value,
2363 "Direct Address (bits 12-7): %d",
2364 value & 0x3F);
2365 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2366 proto_tree_add_item (addr_tree, hf_addr_dir_not_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2367 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
2368 offset += 1;
2370 if (not_req == 0x03) {
2371 /* Extended Direct Address 2 */
2372 value = tvb_get_uint8 (tvb, offset);
2373 dir_addr |= ((value & 0x3F) << 13);
2374 not_req = (value & 0xC0) >> 6;
2376 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
2377 offset, 1, value,
2378 "Direct Address (bits 18-13): %d",
2379 value & 0x3F);
2380 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2381 proto_tree_add_item (addr_tree, hf_addr_dir_not_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2382 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
2383 offset += 1;
2387 rec_no += *prev_rec_no;
2388 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2389 rec_no++;
2391 *prev_rec_no = rec_no;
2393 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no_generated,
2394 tvb, offset, 0, rec_no,
2395 "Recipient Number: %d", rec_no);
2396 if (rec_no > 32767) {
2397 proto_item_append_text (en, " (maximum 32767)");
2398 expert_add_info(pinfo, en, &ei_addr_dir_rec_no_generated);
2400 proto_item_set_generated (en);
2402 if (dir_addr_extended) {
2403 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
2404 tvb, offset, 0, dir_addr,
2405 "Direct Address: %d", dir_addr);
2406 proto_item_set_generated (en);
2409 proto_item_append_text (tf, " %d", rec_no);
2410 if (rec_ofs != -1) {
2411 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2414 proto_item_append_text (tf, ", Direct Address: %d", dir_addr);
2415 dmp_add_recipient_info (tf, rep_req, not_req, action);
2417 return offset;
2420 /* Ref 5.2.8.2 Extended Recipient Encoding */
2421 static int dissect_dmp_ext_encoding (tvbuff_t *tvb, packet_info *pinfo,
2422 proto_tree *field_tree,
2423 proto_item *tf, int offset,
2424 unsigned *prev_rec_no)
2426 proto_tree *addr_tree = NULL;
2427 proto_item *en = NULL;
2428 uint8_t rep_req = 0, not_req = 0;
2429 uint8_t value, dmp_addr_form;
2430 bool action = false;
2431 int rec_no, rec_ofs = -1;
2433 value = tvb_get_uint8 (tvb, offset);
2434 dmp_addr_form = (value & 0xE0) >> 5;
2435 action = (value & 0x10);
2436 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form, tvb,
2437 offset, 1, value,
2438 "Address Form: %s",
2439 val_to_str_const (dmp_addr_form,
2440 addr_form, "Reserved"));
2441 addr_tree = proto_item_add_subtree (en, ett_address_ext_form);
2442 proto_tree_add_item (addr_tree, hf_addr_ext_form, tvb, offset, 1, ENC_BIG_ENDIAN);
2444 en = proto_tree_add_boolean_format (field_tree, hf_addr_ext_action, tvb,
2445 offset, 1, value, "Action: %s",
2446 action ? "Yes" : "No");
2447 addr_tree = proto_item_add_subtree (en, ett_address_ext_action);
2448 proto_tree_add_item (addr_tree, hf_addr_ext_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2450 rep_req = (value & 0x0C) >> 2;
2451 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rep_req, tvb,
2452 offset, 1, value,
2453 "Report Request: %s",
2454 val_to_str_const ((value & 0x0C) >> 2,
2455 report_vals, "Reserved"));
2456 addr_tree = proto_item_add_subtree (en, ett_address_ext_rep_req);
2457 proto_tree_add_item (addr_tree, hf_addr_ext_rep_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2459 not_req = (value & 0x03);
2460 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_not_req, tvb,
2461 offset, 1, value,
2462 "Notification Request: %s",
2463 val_to_str_const (value & 0x03,
2464 notif_vals, "Reserved"));
2465 addr_tree = proto_item_add_subtree (en, ett_address_ext_not_req);
2466 proto_tree_add_item (addr_tree, hf_addr_ext_not_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2467 offset += 1;
2469 value = tvb_get_uint8 (tvb, offset);
2470 rec_no = (value & 0x7F);
2471 if (value & 0x80) {
2472 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no1, tvb,
2473 offset, 1, value,
2474 "Recipient Number (bits 6-0): %d"
2475 " (offset from previous)",
2476 value & 0x7F);
2477 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2478 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2479 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2480 offset += 1;
2482 /* Extended */
2483 value = tvb_get_uint8 (tvb, offset);
2484 rec_no |= (value << 7);
2485 rec_ofs = rec_no;
2486 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no2, tvb,
2487 offset, 1, value,
2488 "Recipient Number (bits 14-7): %d"
2489 " (offset from previous)", value);
2490 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2491 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2492 offset += 1;
2494 } else {
2495 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no, tvb,
2496 offset, 1, value,
2497 "Recipient Number Offset: %d"
2498 " (offset from previous)",
2499 value & 0x7F);
2500 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2501 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2502 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2503 offset += 1;
2507 rec_no += *prev_rec_no;
2508 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2509 rec_no++;
2511 *prev_rec_no = rec_no;
2513 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no_generated,
2514 tvb, offset, 0, rec_no,
2515 "Recipient Number: %d", rec_no);
2516 if (rec_no > 32767) {
2517 proto_item_append_text (en, " (maximum 32767)");
2518 expert_add_info(pinfo, en, &ei_addr_ext_rec_no_generated);
2520 proto_item_set_generated (en);
2522 switch (dmp_addr_form) {
2524 case P1_DIRECT:
2525 case P1_P2_DIRECT:
2526 case P1_DIRECT_P2_EXTENDED:
2527 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2528 rec_no, rec_ofs, P1_ADDRESS);
2529 break;
2531 case P1_EXTENDED:
2532 case P1_EXTENDED_P2_DIRECT:
2533 case P1_P2_EXTENDED:
2534 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2535 rec_no, rec_ofs, P1_ADDRESS);
2536 break;
2540 switch (dmp_addr_form) {
2542 case P2_DIRECT:
2543 case P1_P2_DIRECT:
2544 case P1_EXTENDED_P2_DIRECT:
2545 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2546 rec_no, rec_ofs, P2_ADDRESS);
2547 break;
2549 case P2_EXTENDED:
2550 case P1_DIRECT_P2_EXTENDED:
2551 case P1_P2_EXTENDED:
2552 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2553 rec_no, rec_ofs, P2_ADDRESS);
2554 break;
2558 dmp_add_recipient_info (tf, rep_req, not_req, action);
2560 return offset;
2563 /* Ref chapter 5.2 Address encoding */
2564 static int dissect_dmp_address (tvbuff_t *tvb, packet_info *pinfo,
2565 proto_tree *envelope_tree,
2566 int offset, unsigned *prev_rec_no,
2567 bool reporting_name)
2569 proto_tree *field_tree = NULL;
2570 proto_item *tf = NULL;
2571 int boffset = offset;
2573 if (reporting_name) {
2574 tf = proto_tree_add_item (envelope_tree, hf_addr_reporting_name, tvb, offset, -1, ENC_NA);
2575 } else {
2576 tf = proto_tree_add_none_format (envelope_tree, hf_addr_recipient, tvb,
2577 offset, -1, "Recipient Number");
2579 field_tree = proto_item_add_subtree (tf, ett_address);
2581 if (dmp.addr_enc == DIRECT_ADDR) {
2582 offset = dissect_dmp_direct_encoding (tvb, pinfo, field_tree, tf,
2583 offset, prev_rec_no);
2584 } else {
2585 offset = dissect_dmp_ext_encoding (tvb, pinfo, field_tree, tf, offset,
2586 prev_rec_no);
2589 proto_item_set_len (tf, offset - boffset);
2591 return offset;
2594 /* Ref chapter 6.2.9 Acknowledgement */
2595 static int dissect_dmp_ack (tvbuff_t *tvb, packet_info *pinfo,
2596 proto_tree *dmp_tree, int offset)
2598 proto_tree *ack_tree = NULL, *recip_tree = NULL;
2599 proto_item *en = NULL, *rt = NULL;
2600 proto_item *hidden_item;
2601 unsigned prev_rec_no = 0;
2602 int rec_len, rec_no = 0;
2603 int boffset = offset;
2605 en = proto_tree_add_item (dmp_tree, hf_ack, tvb, offset, 4, ENC_NA);
2606 ack_tree = proto_item_add_subtree (en, ett_ack);
2608 dmp.ack_reason = tvb_get_uint8 (tvb, offset);
2609 proto_item_append_text (en, ", Reason: %s",
2610 val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2612 rt = proto_tree_add_item (ack_tree, hf_ack_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
2613 if (dmp.ack_reason != 0) {
2614 expert_add_info_format(pinfo, rt, &ei_ack_reason, "ACK reason: %s", val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2616 offset += 1;
2618 proto_tree_add_item (ack_tree, hf_ack_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN);
2619 offset += 1;
2621 /* Subject Message Identifier */
2622 dmp.subj_id = tvb_get_ntohs (tvb, offset);
2623 proto_tree_add_item (ack_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2624 hidden_item = proto_tree_add_item (ack_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2625 proto_item_set_hidden (hidden_item);
2626 offset += 2;
2628 if (use_seq_ack_analysis) {
2629 register_dmp_id (pinfo, dmp.ack_reason);
2632 if (dmp.ack_rec_present) {
2633 /* Recipient List */
2634 rec_len = tvb_reported_length (tvb);
2635 if (dmp.checksum) {
2636 rec_len -= 2;
2638 if (offset < rec_len) {
2639 rt = proto_tree_add_item (ack_tree, hf_ack_recips, tvb, offset, -1, ENC_NA);
2640 recip_tree = proto_item_add_subtree (rt, ett_ack_recips);
2641 while (offset < rec_len) {
2642 offset = dissect_dmp_address (tvb, pinfo, recip_tree, offset,
2643 &prev_rec_no, false);
2644 rec_no++;
2646 proto_item_append_text (rt, ", No Recipients: %d", rec_no);
2647 proto_item_set_len (rt, offset - boffset - 4);
2648 proto_item_set_len (en, offset - boffset);
2652 return offset;
2655 static int dissect_mts_identifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2656 int offset, bool subject)
2658 proto_item *ti, *hidden_item;
2659 const char *mts_id;
2660 unsigned char byte_rest = 0;
2662 if (dmp.msg_id_type == X400_MSG_ID || dmp_nat_decode == NAT_DECODE_DMP) {
2663 mts_id = dissect_7bit_string (tvb, offset, dmp.mts_id_length, &byte_rest);
2664 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2665 mts_id = dissect_thales_mts_id (tvb, offset, dmp.mts_id_length, &byte_rest);
2666 } else {
2667 mts_id = tvb_bytes_to_str(pinfo->pool, tvb, offset, dmp.mts_id_length);
2669 proto_item_append_text (dmp.mts_id_item, " (%zu bytes decompressed)", strlen(mts_id));
2670 mts_id = format_text(pinfo->pool, mts_id, strlen(mts_id));
2671 if (subject) {
2672 ti = proto_tree_add_string (tree, hf_message_subj_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2673 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2674 /* Read from hash, for analysis */
2675 dmp.subj_id = GPOINTER_TO_UINT (wmem_map_lookup (dmp_long_id_hash_table, mts_id));
2676 } else {
2677 ti = proto_tree_add_string (tree, hf_envelope_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2678 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2679 /* Insert into hash, for analysis */
2680 wmem_map_insert (dmp_long_id_hash_table, wmem_strdup (wmem_file_scope(), mts_id), GUINT_TO_POINTER ((unsigned)dmp.msg_id));
2682 proto_item_set_hidden (hidden_item);
2683 offset += dmp.mts_id_length;
2685 if (byte_rest) {
2686 expert_add_info (pinfo, ti, &ei_7bit_string_unused_bits);
2689 return offset;
2692 static int dissect_ipm_identifier (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2693 int offset, bool subject)
2695 proto_tree *field_tree;
2696 proto_item *ti, *tf, *hidden_item;
2697 const char *ipm_id;
2698 int length, modifier, ipm_id_length;
2699 unsigned char byte_rest = 0;
2701 length = tvb_get_uint8 (tvb, offset);
2702 modifier = (length & 0xC0) >> 6;
2703 ipm_id_length = length & 0x3F;
2705 tf = proto_tree_add_uint_format (tree, hf_envelope_ipm_id_length,
2706 tvb, offset, 1, ipm_id_length,
2707 "IPM Identifier Length: %u",
2708 ipm_id_length);
2709 field_tree = proto_item_add_subtree (tf, ett_envelope_ipm_id_length);
2710 if ((dmp.msg_id_type == NAT_MSG_ID || modifier != IPM_MODIFIER_X400) && dmp_nat_decode == NAT_DECODE_THALES) {
2711 proto_tree_add_item (field_tree, hf_thales_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2712 } else {
2713 proto_tree_add_item (field_tree, hf_envelope_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2715 proto_tree_add_item (field_tree, hf_envelope_ipm_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2716 offset += 1;
2718 if (modifier == IPM_MODIFIER_X400 || dmp_nat_decode == NAT_DECODE_DMP) {
2719 ipm_id = dissect_7bit_string (tvb, offset, ipm_id_length, &byte_rest);
2720 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2721 ipm_id = dissect_thales_ipm_id (tvb, offset, ipm_id_length, modifier, &byte_rest);
2722 } else {
2723 ipm_id = tvb_bytes_to_str(pinfo->pool, tvb, offset, ipm_id_length);
2725 proto_item_append_text (tf, " (%zu bytes decompressed)", strlen(ipm_id));
2726 ipm_id = format_text(pinfo->pool, ipm_id, strlen(ipm_id));
2727 if (subject) {
2728 ti = proto_tree_add_string (tree, hf_message_subj_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2729 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2730 /* Read from hash, for analysis */
2731 dmp.subj_id = GPOINTER_TO_UINT (wmem_map_lookup (dmp_long_id_hash_table, ipm_id));
2732 } else {
2733 ti = proto_tree_add_string (tree, hf_envelope_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2734 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2735 /* Insert into hash, for analysis */
2736 wmem_map_insert (dmp_long_id_hash_table, wmem_strdup (wmem_file_scope(), ipm_id), GUINT_TO_POINTER ((unsigned)dmp.msg_id));
2738 proto_item_set_hidden (hidden_item);
2739 offset += ipm_id_length;
2741 if (byte_rest) {
2742 expert_add_info (pinfo, ti, &ei_7bit_string_unused_bits);
2745 return offset;
2748 /* Ref chapter 6.2.7 Envelope structure */
2749 static int dissect_dmp_envelope (tvbuff_t *tvb, packet_info *pinfo,
2750 proto_tree *dmp_tree, int offset)
2752 proto_tree *envelope_tree = NULL;
2753 proto_tree *field_tree = NULL;
2754 proto_item *en = NULL, *tf = NULL, *vf = NULL;
2755 proto_item *hidden_item;
2756 uint8_t envelope, time_diff;
2757 uint16_t subm_time, no_rec, value16;
2758 int32_t secs = 0;
2759 char *env_flags = NULL;
2760 unsigned prev_rec_no = 0;
2761 int boffset = offset, i;
2762 bool using_short_id = false;
2764 en = proto_tree_add_item (dmp_tree, hf_envelope, tvb, offset, 10, ENC_NA);
2765 envelope_tree = proto_item_add_subtree (en, ett_envelope);
2767 envelope = tvb_get_uint8 (tvb, offset);
2768 dmp.prot_id = (envelope & 0xF8) >> 3;
2769 dmp.version = (envelope & 0x07) + 1;
2771 /* Protocol Version */
2772 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_version,
2773 tvb, offset, 1, dmp.version,
2774 "Protocol Version: %d", dmp.version);
2776 field_tree = proto_item_add_subtree (tf, ett_envelope_version);
2777 vf = proto_tree_add_item (field_tree, hf_envelope_protocol_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2778 if (dmp.prot_id == PROT_NAT) {
2779 proto_item_append_text (vf, " (national version of DMP)");
2780 proto_item_append_text (tf, " (national)");
2781 } else if (dmp.prot_id == PROT_DMP) {
2782 proto_item_append_text (vf, " (correct)");
2783 } else {
2784 proto_item_append_text (vf, " (incorrect, should be 0x1d)");
2786 vf = proto_tree_add_item (field_tree, hf_envelope_version_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2787 offset += 1;
2789 if (dmp.version > DMP_VERSION_2) {
2790 /* Unsupported DMP Version */
2791 proto_item_append_text (vf, " (unsupported)");
2792 proto_item_append_text (tf, " (unsupported)");
2793 expert_add_info_format(pinfo, vf, &ei_envelope_version_value, "Unsupported DMP Version: %d", dmp.version);
2794 return offset;
2797 envelope = tvb_get_uint8 (tvb, offset);
2798 dmp.addr_enc = ((envelope & 0x10) >> 4);
2799 dmp.checksum = ((envelope & 0x08) >> 3);
2800 dmp.msg_type = (envelope & 0x07);
2802 if (dmp.msg_type != ACK) {
2803 /* Hop count */
2804 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_hop_count,
2805 tvb, offset, 1, envelope,
2806 "Hop Count: %d", (envelope & 0xE0) >> 5);
2807 field_tree = proto_item_add_subtree (tf, ett_envelope_hop_count);
2808 proto_tree_add_item (field_tree, hf_envelope_hop_count_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2809 } else {
2810 if (dmp.version >= DMP_VERSION_2) {
2811 /* Extensions Present */
2812 dmp.extensions = (envelope & 0x80);
2813 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2814 tvb, offset, 1, envelope,
2815 "Extensions: %s",
2816 tfs_get_string(envelope & 0x80, &tfs_present_absent));
2817 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2818 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2821 /* Recipient Present */
2822 dmp.ack_rec_present = (envelope & 0x20);
2823 tf = proto_tree_add_boolean_format (envelope_tree,hf_envelope_rec_present,
2824 tvb, offset, 1, envelope,
2825 "Recipient Present: %s",
2826 tfs_get_string(envelope & 0x20, &tfs_present_absent));
2827 field_tree = proto_item_add_subtree (tf, ett_envelope_rec_present);
2828 proto_tree_add_item (field_tree, hf_envelope_rec_present, tvb, offset, 1, ENC_BIG_ENDIAN);
2831 /* Address Encoding */
2832 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_addr_enc,
2833 tvb, offset, 1, envelope,
2834 "Address Encoding: %s",
2835 tfs_get_string(envelope & 0x10, &addr_enc));
2836 field_tree = proto_item_add_subtree (tf, ett_envelope_addr_enc);
2837 proto_tree_add_item (field_tree, hf_envelope_addr_enc, tvb, offset, 1, ENC_BIG_ENDIAN);
2839 /* Checksum Present */
2840 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_checksum,
2841 tvb, offset, 1, envelope,
2842 "Checksum: %s",
2843 (envelope & 0x08) ? "Used" : "Not used");
2844 field_tree = proto_item_add_subtree (tf, ett_envelope_checksum);
2845 proto_tree_add_item (field_tree, hf_envelope_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
2847 /* Content Type */
2848 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_type,
2849 tvb, offset, 1, envelope,
2850 "Content Type: %s (%d)",
2851 val_to_str_const (envelope & 0x07,
2852 type_vals, "Unknown"),
2853 envelope & 0x07);
2854 field_tree = proto_item_add_subtree (tf, ett_envelope_cont_type);
2855 proto_tree_add_item (field_tree, hf_envelope_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2857 proto_item_append_text (en, ", Checksum %s", (envelope >> 3) & 0x01 ? "Used" : "Not used");
2858 offset += 1;
2860 if (dmp.msg_type >= ACK) {
2861 proto_item_set_len (en, offset - boffset);
2862 return offset;
2865 if (dmp.version >= DMP_VERSION_2) {
2866 envelope = tvb_get_uint8 (tvb, offset);
2867 /* Extensions Present */
2868 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2869 tvb, offset, 1, envelope,
2870 "Extensions: %s",
2871 (envelope & 0x80) ? "Present" : "Absent");
2872 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2873 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2874 dmp.extensions = (envelope & 0x80);
2876 /* Message Identifier Type */
2877 dmp.msg_id_type = (envelope & 0x60) >> 5;
2878 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_msg_id_type,
2879 tvb, offset, 1, envelope,
2880 "Message Identifier Type: %s (%d)",
2881 val_to_str_const (dmp.msg_id_type, msg_id_type_vals, "Unknown"),
2882 dmp.msg_id_type);
2883 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id_type);
2884 proto_tree_add_item (field_tree, hf_envelope_msg_id_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2886 if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
2887 /* MTS Identifier Length */
2888 dmp.mts_id_length = (envelope & 0x1F);
2889 dmp.mts_id_item = proto_tree_add_uint_format (envelope_tree, hf_envelope_mts_id_length,
2890 tvb, offset, 1, envelope,
2891 "MTS Identifier Length: %u",
2892 dmp.mts_id_length);
2893 field_tree = proto_item_add_subtree (dmp.mts_id_item, ett_envelope_mts_id_length);
2894 proto_tree_add_item (field_tree, hf_envelope_mts_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2895 offset += 1;
2896 } else {
2897 proto_tree_add_item (field_tree, hf_envelope_msg_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2898 if (envelope & 0x10) {
2899 /* Using Short Identifier (12 bits) */
2900 using_short_id = true;
2901 } else {
2902 tf = proto_tree_add_item (field_tree, hf_reserved_0x0F, tvb, offset, 1, ENC_BIG_ENDIAN);
2903 if (envelope & 0x0F) {
2904 expert_add_info(pinfo, tf, &ei_reserved_value);
2906 offset += 1;
2911 /* Message Identifier */
2912 dmp.msg_id = tvb_get_ntohs (tvb, offset);
2913 if (using_short_id) {
2914 dmp.msg_id &= 0x0FFF;
2916 tf = proto_tree_add_uint (envelope_tree, hf_envelope_msg_id, tvb, offset, 2, dmp.msg_id);
2917 hidden_item = proto_tree_add_uint (envelope_tree, hf_dmp_id, tvb, offset, 2, dmp.msg_id);
2918 if (using_short_id) {
2919 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id);
2920 proto_tree_add_item (field_tree, hf_envelope_msg_id_12bit, tvb, offset, 2, ENC_BIG_ENDIAN);
2921 } else if (dmp.version >= DMP_VERSION_2 && dmp.msg_id_type == ONLY_DMP_ID && dmp.msg_id < 4096) {
2922 expert_add_info(pinfo, tf, &ei_envelope_msg_id);
2924 proto_item_set_hidden (hidden_item);
2925 offset += 2;
2927 if (dmp.version >= DMP_VERSION_2) {
2928 if ((dmp.msg_type != REPORT) && (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID)) {
2929 offset = dissect_mts_identifier (tvb, pinfo, envelope_tree, offset, false);
2933 /* Submission Time */
2934 subm_time = tvb_get_ntohs (tvb, offset);
2935 dmp.subm_time = dmp_dec_subm_time ((uint16_t)(subm_time & 0x7FFF),
2936 (int32_t) pinfo->abs_ts.secs);
2937 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_subm_time, tvb,
2938 offset, 2, subm_time,
2939 "Submission time: %s",
2940 (subm_time & 0x7FFF) >= 0x7FF8 ?
2941 "Reserved" :
2942 abs_time_secs_to_str (pinfo->pool, dmp.subm_time, ABSOLUTE_TIME_LOCAL, true));
2943 field_tree = proto_item_add_subtree (tf, ett_envelope_subm_time);
2944 proto_tree_add_item (field_tree, hf_envelope_time_diff_present, tvb, offset, 2, ENC_BIG_ENDIAN);
2945 proto_tree_add_item (field_tree, hf_envelope_subm_time_value, tvb, offset, 2, ENC_BIG_ENDIAN);
2946 offset += 2;
2948 if (subm_time & 0x8000) {
2949 /* Timed Difference */
2950 time_diff = tvb_get_uint8 (tvb, offset);
2951 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_time_diff,
2952 tvb, offset, 1, time_diff,
2953 "Time Difference: ");
2954 field_tree = proto_item_add_subtree (tf, ett_envelope_time_diff);
2955 proto_tree_add_item (field_tree, hf_envelope_time_diff_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2956 secs = dmp_dec_time_diff (time_diff);
2957 if (secs == DMP_TIME_RESERVED) {
2958 proto_item_append_text (tf, "Reserved (0x%2.2x)", time_diff);
2959 } else {
2960 proto_item_append_text (tf, "%s", signed_time_secs_to_str(pinfo->pool, secs));
2962 offset += 1;
2965 /* Envelope Flags */
2966 envelope = tvb_get_uint8 (tvb, offset);
2967 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_flags,
2968 tvb, offset, 1, envelope,
2969 "Envelope Flags");
2971 field_tree = proto_item_add_subtree (tf, ett_envelope_flags);
2972 proto_tree_add_item (field_tree, hf_envelope_content_id_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
2973 proto_tree_add_item (field_tree, hf_envelope_recip_reassign_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2974 proto_tree_add_item (field_tree, hf_envelope_dl_expansion_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2976 if (envelope & 0xE0) {
2977 env_flags = wmem_strdup_printf (pinfo->pool, "%s%s%s",
2978 (envelope & 0x80) ? ", ContId discarded" : "",
2979 (envelope & 0x40) ? ", Reass prohibited" : "",
2980 (envelope & 0x20) ? ", DLE prohibited" : "");
2981 proto_item_append_text (tf, ":%s", &env_flags[1]);
2982 } else {
2983 proto_item_append_text (tf, " (none)");
2986 /* Recipient Count */
2987 no_rec = (envelope & 0x1F);
2988 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_recipients,
2989 tvb, offset, 1, envelope,
2990 "Recipient Count: %d", no_rec);
2992 field_tree = proto_item_add_subtree (tf, ett_envelope_recipients);
2993 proto_tree_add_item (field_tree, hf_envelope_recipients, tvb, offset, 1, ENC_BIG_ENDIAN);
2994 offset += 1;
2996 if (no_rec == 0) {
2997 /* Extended Recipient Count */
2998 value16 = tvb_get_ntohs (tvb, offset);
2999 no_rec = value16 & 0x7FFF;
3000 tf = proto_tree_add_uint_format (envelope_tree,hf_envelope_ext_recipients,
3001 tvb, offset, 2, value16,
3002 "Extended Recipient Count: %d%s", no_rec,
3003 (no_rec < 32 ?
3004 " (incorrect, reserved value)" : ""));
3006 field_tree = proto_item_add_subtree (tf, ett_envelope_ext_recipients);
3007 en = proto_tree_add_item (field_tree, hf_reserved_0x8000, tvb, offset, 2, ENC_BIG_ENDIAN);
3008 if (value16 & 0x8000) {
3009 expert_add_info(pinfo, en, &ei_reserved_value);
3011 proto_tree_add_item (field_tree, hf_envelope_ext_recipients, tvb, offset, 2, ENC_BIG_ENDIAN);
3012 offset += 2;
3015 if (dmp.msg_type != REPORT) {
3016 /* Originator - Not present for reports */
3017 offset = dissect_dmp_originator (tvb, pinfo, envelope_tree, offset);
3020 for (i = 0; i < no_rec; i++) {
3021 /* Recipient(s) */
3022 offset = dissect_dmp_address (tvb, pinfo, envelope_tree, offset,
3023 &prev_rec_no, false);
3026 if (dmp.version >= DMP_VERSION_2) {
3027 if ((dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) &&
3028 dmp.notif_req && (dmp.msg_type == STANAG || dmp.msg_type == IPM))
3030 offset = dissect_ipm_identifier (tvb, pinfo, envelope_tree, offset, false);
3034 proto_item_set_len (en, offset - boffset);
3036 return offset;
3040 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3041 * and chapter 6.3.8.1 IPM 88 message structure
3043 static int dissect_dmp_message (tvbuff_t *tvb, packet_info *pinfo,
3044 proto_tree *dmp_tree, int offset)
3046 tvbuff_t *body_tvb = NULL;
3047 proto_tree *message_tree = NULL;
3048 proto_tree *field_tree = NULL;
3049 proto_item *en = NULL, *tf = NULL, *tr = NULL;
3050 uint8_t message, eit = 0, compr_alg = ALGORITHM_NONE;
3051 int len, boffset = offset, body_offset = 0, body_len = 0;
3053 en = proto_tree_add_item (dmp_tree, hf_message_body, tvb, offset, -1, ENC_NA);
3054 message_tree = proto_item_add_subtree (en, ett_message);
3056 if (dmp.body_format == FREE_TEXT_SUBJECT) {
3057 len = tvb_strsize (tvb, offset);
3058 proto_tree_add_item (message_tree, hf_message_subject, tvb, offset, len, ENC_ASCII);
3059 offset += len;
3062 if (dmp.body_format == FREE_TEXT || dmp.body_format == FREE_TEXT_SUBJECT) {
3063 message = tvb_get_uint8 (tvb, offset);
3064 eit = (message & 0xE0) >> 5;
3065 compr_alg = (message & 0x18) >> 3;
3066 /* Encoded Information Type */
3067 tf = proto_tree_add_uint_format (message_tree, hf_message_eit,
3068 tvb, offset, 1, message, "EIT: %s (%d)",
3069 val_to_str_const (eit, eit_vals, "Unknown"),
3070 eit);
3071 field_tree = proto_item_add_subtree (tf, ett_message_eit);
3072 proto_tree_add_item (field_tree, hf_message_eit, tvb, offset, 1, ENC_BIG_ENDIAN);
3073 proto_item_append_text (en, ", Type: %s",
3074 val_to_str_const (eit, eit_vals, "Unknown"));
3076 /* Compression Algorithm */
3077 tf = proto_tree_add_uint_format (message_tree, hf_message_compr,
3078 tvb, offset, 1, message,
3079 "Compression Algorithm: %s (%d)",
3080 val_to_str_const (compr_alg, compression_vals, "Unknown"),
3081 compr_alg);
3082 field_tree = proto_item_add_subtree (tf, ett_message_compr);
3083 tr = proto_tree_add_item (field_tree, hf_message_compr, tvb, offset, 1, ENC_BIG_ENDIAN);
3084 if (compr_alg == ALGORITHM_ZLIB) {
3085 proto_item_append_text (en, " (compressed)");
3086 } else if (compr_alg != ALGORITHM_NONE) {
3087 expert_add_info(pinfo, tr, &ei_message_compr);
3090 if (message & 0x07) {
3091 /* Reserved */
3092 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x07,
3093 tvb, offset, 1, message,
3094 "Reserved: %d", message & 0x07);
3095 field_tree = proto_item_add_subtree (tf, ett_message_body_reserved);
3096 tf = proto_tree_add_item (field_tree, hf_reserved_0x07, tvb, offset, 1, ENC_BIG_ENDIAN);
3097 expert_add_info(pinfo, tf, &ei_reserved_value);
3099 offset += 1;
3102 len = tvb_reported_length_remaining (tvb, offset);
3103 if (dmp.checksum) {
3104 len -= 2;
3105 if (len < 0) {
3106 THROW_MESSAGE(ReportedBoundsError, "Packet length too short");
3110 if (compr_alg == ALGORITHM_ZLIB) {
3111 tf = proto_tree_add_item (message_tree, hf_message_body_compressed,
3112 tvb, offset, len, ENC_NA);
3113 proto_item_append_text (tf, ", Length: %d", len);
3114 } else {
3115 tf = proto_tree_add_item (message_tree, hf_message_body_data,
3116 tvb, offset, len, ENC_NA);
3117 proto_item_set_text (tf, "User data, Length: %d", len);
3120 if (dmp.body_format == STRUCTURED) {
3121 /* Structured Message ID */
3122 field_tree = proto_item_add_subtree (tf, ett_message_body);
3123 proto_tree_add_item (field_tree, hf_message_body_structured, tvb, offset, len, ENC_NA);
3124 } else if (len > 0 && (dmp.body_format == FREE_TEXT ||
3125 dmp.body_format == FREE_TEXT_SUBJECT)) {
3126 if (compr_alg == ALGORITHM_ZLIB) {
3127 if ((body_tvb = tvb_child_uncompress_zlib(tvb, tvb, offset, len)) != NULL) {
3128 body_len = tvb_captured_length (body_tvb);
3129 add_new_data_source (pinfo, body_tvb, "Uncompressed User data");
3130 tf = proto_tree_add_item (message_tree, hf_message_body_data,
3131 body_tvb, 0, body_len, ENC_NA);
3132 proto_item_set_text (tf, "User data, Length: %d", body_len);
3133 proto_item_set_generated (tf);
3134 } else {
3135 proto_tree_add_expert (message_tree, pinfo, &ei_message_body_uncompress, tvb, offset, len);
3137 } else {
3138 body_tvb = tvb;
3139 body_offset = offset;
3140 body_len = len;
3143 if (eit != EIT_BILATERAL && body_len > 0) {
3144 field_tree = proto_item_add_subtree (tf, ett_message_body);
3145 proto_tree_add_item (field_tree, hf_message_body_plain, body_tvb,
3146 body_offset, body_len, ENC_ASCII);
3149 offset += len;
3151 proto_item_set_len (en, offset - boffset);
3153 return offset;
3156 /* Ref chapter 6.3.9.1 Report structure */
3157 static int dissect_dmp_report (tvbuff_t *tvb, packet_info *pinfo,
3158 proto_tree *dmp_tree, int offset,
3159 unsigned *prev_rec_no, int num)
3161 proto_tree *report_tree = NULL;
3162 proto_tree *field_tree = NULL;
3163 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3164 uint8_t report;
3165 bool info_present;
3166 int32_t secs = 0;
3167 int len, boffset = offset;
3168 int rep_type = 0;
3170 report = tvb_get_uint8 (tvb, offset);
3171 rep_type = (report & 0x80) >> 7;
3172 if (rep_type) {
3173 en = proto_tree_add_item (dmp_tree, hf_non_delivery_report, tvb, offset, 4, ENC_NA);
3174 } else {
3175 en = proto_tree_add_item (dmp_tree, hf_delivery_report, tvb, offset, 4, ENC_NA);
3177 proto_item_append_text (en, " (#%d)", num);
3179 report_tree = proto_item_add_subtree (en, ett_report);
3181 /* Report Type */
3182 tf = proto_tree_add_boolean_format (report_tree, hf_report_type,
3183 tvb, offset, 1, report,
3184 "Report Type: %s",
3185 tfs_get_string(rep_type, &report_type));
3186 field_tree = proto_item_add_subtree (tf, ett_report_type);
3187 proto_tree_add_item (field_tree, hf_report_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3189 if (rep_type == DR) {
3190 dmp.dr = true;
3191 /* Info Present */
3192 info_present = (report & 0x40);
3193 tf = proto_tree_add_boolean_format (report_tree,hf_report_info_present_dr,
3194 tvb, offset, 1, report,
3195 "Info Present: %s",
3196 tfs_get_string(report & 0x40, &tfs_present_absent));
3197 field_tree = proto_item_add_subtree (tf, ett_report_info_present_dr);
3198 proto_tree_add_item (field_tree, hf_report_info_present_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3200 /* Address Encoding */
3201 dmp.addr_enc = ((report & 0x20) >> 5);
3202 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_dr,
3203 tvb, offset, 1, report,
3204 "Address Encoding: %s",
3205 tfs_get_string(report & 0x20, &addr_enc));
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) {
3210 /* Reserved */
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);
3219 offset += 1;
3221 /* Delivery Time */
3222 report = tvb_get_uint8 (tvb, offset);
3223 tf = proto_tree_add_uint_format (report_tree, hf_report_del_time,
3224 tvb, offset, 1, report,
3225 "Delivery Time: ");
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)");
3232 } else {
3233 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(pinfo->pool, secs),
3234 abs_time_secs_to_str (pinfo->pool, dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, true));
3235 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(pinfo->pool, secs));
3237 } else {
3238 dmp.ndr = true;
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",
3244 tfs_get_string(report & 0x40, &addr_enc));
3245 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_ndr);
3246 proto_tree_add_item (field_tree, hf_report_addr_enc_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3248 /* Reason */
3249 tf = proto_tree_add_uint_format (report_tree, hf_report_reason,
3250 tvb, offset, 1, report,
3251 "Reason%s: %s (%d)",
3252 ((report & 0x3F) < 0x3D) ? " (P1)":"",
3253 non_del_reason_str (report & 0x3F),
3254 report & 0x3F);
3255 field_tree = proto_item_add_subtree (tf, ett_report_reason);
3256 proto_tree_add_item (field_tree, hf_report_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
3257 offset += 1;
3259 /* Info Present */
3260 report = tvb_get_uint8 (tvb, offset);
3261 info_present = (report & 0x80);
3262 tf = proto_tree_add_boolean_format (report_tree,
3263 hf_report_info_present_ndr,
3264 tvb, offset, 1, report,
3265 "Info Present: %s", (report & 0x80) ? "Present" : "Absent");
3266 field_tree = proto_item_add_subtree (tf, ett_report_info_present_ndr);
3267 proto_tree_add_item (field_tree, hf_report_info_present_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3269 /* Diagnostic */
3270 tf = proto_tree_add_uint_format (report_tree, hf_report_diagn,
3271 tvb, offset, 1, report,
3272 "Diagnostic%s: %s (%d)",
3273 ((report & 0x7F) < 0x7C) ? " (P1)":"",
3274 non_del_diagn_str (report & 0x7F),
3275 report & 0x7F);
3276 field_tree = proto_item_add_subtree (tf, ett_report_diagn);
3277 proto_tree_add_item (field_tree, hf_report_diagn, tvb, offset, 1, ENC_BIG_ENDIAN);
3279 offset += 1;
3281 offset = dissect_dmp_address (tvb, pinfo, report_tree, offset,
3282 prev_rec_no, true);
3284 if (info_present) {
3285 /* Supplementary Information */
3286 len = tvb_strsize (tvb, offset);
3287 tf = proto_tree_add_uint_format (report_tree, hf_report_suppl_info_len,
3288 tvb, offset, len, len,
3289 "Supplementary Information, Length: %d",
3290 len - 1);
3291 if (len > 1) {
3292 if ((offset - boffset + len) > 128) {
3293 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3294 128 - (offset - boffset));
3296 field_tree = proto_item_add_subtree (tf, ett_report_suppl_info);
3297 proto_tree_add_item (field_tree, hf_report_suppl_info, tvb, offset, len, ENC_ASCII);
3299 offset += len;
3302 proto_item_set_len (en, offset - boffset);
3304 return offset;
3307 /* Ref chapter 6.3.10.1 Notification structure */
3308 static int dissect_dmp_notification (tvbuff_t *tvb, packet_info *pinfo,
3309 proto_tree *dmp_tree, int offset)
3311 proto_tree *notif_tree = NULL;
3312 proto_tree *field_tree = NULL;
3313 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3314 uint8_t notif, rec_time, on_typex = 0xFF;
3315 int len, boffset = offset;
3316 int32_t secs = 0;
3318 if (dmp.notif_type == RN) {
3319 en = proto_tree_add_item (dmp_tree, hf_receipt_notif, tvb, offset, 4, ENC_NA);
3320 } else if (dmp.notif_type == NRN) {
3321 en = proto_tree_add_item (dmp_tree, hf_non_receipt_notif, tvb, offset, 4, ENC_NA);
3322 } else if (dmp.notif_type == ON) {
3323 en = proto_tree_add_item (dmp_tree, hf_other_notif, tvb, offset, 4, ENC_NA);
3324 } else {
3325 return offset;
3327 notif_tree = proto_item_add_subtree (en, ett_notif);
3329 if (dmp.notif_type == RN || dmp.notif_type == ON) {
3330 /* Receipt Time */
3331 rec_time = tvb_get_uint8 (tvb, offset);
3332 tf = proto_tree_add_uint_format (notif_tree, hf_notif_rec_time,
3333 tvb, offset, 1, rec_time,
3334 "Receipt Time: ");
3335 field_tree = proto_item_add_subtree (tf, ett_notif_rec_time);
3336 ei = proto_tree_add_item (field_tree, hf_notif_rec_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3337 secs = dmp_dec_exp_time (rec_time);
3338 if (secs == DMP_TIME_NOT_PRESENT) {
3339 proto_item_append_text (tf, "Not present");
3340 proto_item_append_text (ei, " (not present)");
3341 } else if (secs == DMP_TIME_RESERVED) {
3342 proto_item_append_text (tf, "Reserved (0x%2.2x)", rec_time);
3343 proto_item_append_text (ei, " (Reserved)");
3344 } else {
3345 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(pinfo->pool, secs),
3346 abs_time_secs_to_str (pinfo->pool, dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, true));
3347 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(pinfo->pool, secs));
3349 offset += 1;
3351 if (dmp.notif_type == ON) {
3352 /* ON Type */
3353 on_typex = tvb_get_uint8 (tvb, offset);
3354 proto_tree_add_item (notif_tree, hf_notif_on_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3355 offset += 1;
3358 /* Supplementary Information */
3359 len = tvb_strsize (tvb, offset);
3360 tf = proto_tree_add_uint_format (notif_tree, hf_notif_suppl_info_len,
3361 tvb, offset, len, len,
3362 "Supplementary Information, Length: %d",
3363 len - 1);
3364 if (len > 1) {
3365 if ((offset - boffset + len) > 128) {
3366 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3367 128 - (offset - boffset));
3369 field_tree = proto_item_add_subtree (tf, ett_notif_suppl_info);
3370 proto_tree_add_item (field_tree, hf_notif_suppl_info, tvb, offset, len, ENC_ASCII);
3372 offset += len;
3374 if ((dmp.notif_type == ON) && (on_typex < 0x03)) {
3375 /* ACP127 Recipient */
3376 len = tvb_strsize (tvb, offset);
3377 tf = proto_tree_add_uint_format (notif_tree, hf_notif_acp127,
3378 tvb, offset, len, len,
3379 "ACP127 Recipient, Length: %d",
3380 len - 1);
3381 if (len > 1) {
3382 if (len > 64) {
3383 proto_item_append_text (tf, " (incorrect, must be less than 64)");
3385 field_tree = proto_item_add_subtree (tf, ett_notif_acp127recip);
3386 proto_tree_add_item (field_tree, hf_notif_acp127recip, tvb, offset, len, ENC_ASCII);
3388 offset += len;
3390 } else if (dmp.notif_type == NRN) {
3391 /* Non-Recipient Reason */
3392 notif = tvb_get_uint8 (tvb, offset);
3393 proto_tree_add_uint_format (notif_tree, hf_notif_non_rec_reason,
3394 tvb, offset, 1, notif,
3395 "Non-Receipt Reason%s: %s (%d)",
3396 (notif < 0x10) ? " (P22)" : "",
3397 nrn_reason_str (notif), notif);
3398 offset += 1;
3400 /* Discard Reason */
3401 notif = tvb_get_uint8 (tvb, offset);
3402 proto_tree_add_uint_format (notif_tree, hf_notif_discard_reason,
3403 tvb, offset, 1, notif,
3404 "Discard Reason%s: %s (%d)",
3405 (notif < 0x10) ? " (P22)" : "",
3406 discard_reason_str (notif), notif);
3407 offset += 1;
3410 proto_item_set_len (en, offset - boffset);
3412 return offset;
3415 /* Ref chapter 6.2.1.2.8 SecurityCategories */
3416 static int dissect_dmp_security_category (tvbuff_t *tvb, packet_info *pinfo,
3417 proto_tree *tree,
3418 const char **label_string,
3419 int offset, uint8_t *ext)
3421 proto_tree *field_tree = NULL;
3422 proto_item *tf = NULL, *tr = NULL;
3423 char *sec_cat = NULL;
3424 uint8_t message;
3425 bool country_code = false;
3427 message = tvb_get_uint8 (tvb, offset);
3428 tf = proto_tree_add_uint_format (tree, hf_message_sec_cat_nat, tvb,
3429 offset, 1, message, "Security Categories");
3430 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3432 switch (*ext) {
3434 case SEC_CAT_EXT_NONE:
3435 proto_tree_add_item (field_tree, hf_message_sec_cat_cl, tvb, offset, 1, ENC_BIG_ENDIAN);
3436 proto_tree_add_item (field_tree, hf_message_sec_cat_cs, tvb, offset, 1, ENC_BIG_ENDIAN);
3437 proto_tree_add_item (field_tree, hf_message_sec_cat_ex, tvb, offset, 1, ENC_BIG_ENDIAN);
3438 proto_tree_add_item (field_tree, hf_message_sec_cat_ne, tvb, offset, 1, ENC_BIG_ENDIAN);
3440 tr = proto_tree_add_item (field_tree, hf_reserved_0x08, tvb, offset, 1, ENC_BIG_ENDIAN);
3441 if (message & 0x08) {
3442 expert_add_info(pinfo, tr, &ei_reserved_value);
3444 tr = proto_tree_add_item (field_tree, hf_reserved_0x04, tvb, offset, 1, ENC_BIG_ENDIAN);
3445 if (message & 0x04) {
3446 expert_add_info(pinfo, tr, &ei_reserved_value);
3449 if (message & 0xF0) {
3450 sec_cat = wmem_strdup_printf (pinfo->pool, "%s%s%s%s",
3451 (message & 0x80) ? ",cl" : "",
3452 (message & 0x40) ? ",cs" : "",
3453 (message & 0x20) ? ",ex" : "",
3454 (message & 0x10) ? ",ne" : "");
3455 proto_item_append_text (tf, ": %s", &sec_cat[1]);
3456 *label_string = wmem_strconcat(pinfo->pool, *label_string, sec_cat, NULL);
3458 break;
3460 case SEC_CAT_EXT_PERMISSIVE:
3461 if ((message >> 2) == 0x3F) {
3462 /* Fake entry because nat_pol_id defines 0x3F as reserved */
3463 proto_tree_add_uint_format (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1,
3464 message, "1111 11.. = Next byte has Country Code (0x3F)");
3465 country_code = true;
3466 } else {
3467 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1, ENC_BIG_ENDIAN);
3468 proto_item_append_text (tf, ": rel-to-%s", get_nat_pol_id_short (message >> 2));
3469 *label_string = wmem_strdup_printf(pinfo->pool, "%s,rel-to-%s", *label_string, get_nat_pol_id_short (message >> 2));
3470 if ((message >> 2) == 0) {
3471 expert_add_info(pinfo, tr, &ei_reserved_value);
3474 break;
3476 case SEC_CAT_EXT_RESTRICTIVE:
3477 proto_tree_add_item (field_tree, hf_message_sec_cat_restrictive, tvb, offset, 1, ENC_BIG_ENDIAN);
3478 proto_item_append_text (tf, " (restrictive: 0x%2.2x)", message >> 2);
3479 break;
3481 default:
3482 break;
3485 proto_item_append_text (tf, " (0x%2.2x)", message);
3486 *ext = 0; /* Reset extended bits */
3488 if (dmp.version == 1) {
3489 tr = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3490 if (message & 0x02) {
3491 expert_add_info(pinfo, tr, &ei_reserved_value);
3493 tr = proto_tree_add_item (field_tree, hf_reserved_0x01, tvb, offset, 1, ENC_BIG_ENDIAN);
3494 if (message & 0x01) {
3495 expert_add_info(pinfo, tr, &ei_reserved_value);
3497 offset += 1;
3498 } else {
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 *ext = message & 0x03;
3506 offset += 1;
3508 if (country_code) {
3509 proto_tree_add_item (field_tree, hf_message_sec_cat_country_code, tvb, offset, 1, ENC_BIG_ENDIAN);
3510 proto_item_append_text (tf, " (rel-to country-code: %d)", tvb_get_uint8 (tvb, offset));
3511 proto_item_set_len (tf, 2);
3512 offset += 1;
3516 return offset;
3520 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3521 * and chapter 6.3.8.1 IPM 88 message structure
3522 * and chapter 6.3.9.1 Report structure
3523 * and chapter 6.3.10.1 Notification structure
3525 static int dissect_dmp_content (tvbuff_t *tvb, packet_info *pinfo,
3526 proto_tree *dmp_tree, int offset)
3528 proto_tree *message_tree = NULL;
3529 proto_tree *field_tree = NULL;
3530 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3531 proto_item *hidden_item;
3532 const char *label_string = wmem_strdup (pinfo->pool, "");
3533 const char *class_name = NULL;
3534 uint8_t message, dmp_sec_pol, dmp_sec_class, dmp_nation = 0, exp_time, dtg;
3535 int32_t secs = 0;
3536 unsigned prev_rec_no = 0;
3537 int rep_len, rep_no = 1;
3538 int loffset, boffset = offset;
3540 if (dmp.msg_type == REPORT) {
3541 en = proto_tree_add_item (dmp_tree, hf_report_content, tvb, offset, 7, ENC_NA);
3542 } else if (dmp.msg_type == NOTIF) {
3543 en = proto_tree_add_item (dmp_tree, hf_notif_content, tvb, offset, 7, ENC_NA);
3544 } else {
3545 en = proto_tree_add_item (dmp_tree, hf_message_content, tvb, offset, 7, ENC_NA);
3547 message_tree = proto_item_add_subtree (en, ett_content);
3549 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3550 message = tvb_get_uint8 (tvb, offset);
3551 dmp.body_format = (message & 0x03);
3553 if (dmp.msg_type == STANAG) {
3554 /* Message Type */
3555 dmp.st_type = (message & 0xC0) >> 6;
3556 tf = proto_tree_add_uint_format (message_tree, hf_message_st_type,
3557 tvb, offset, 1, message,
3558 "Message Type: %s (%d)",
3559 val_to_str_const (dmp.st_type,
3560 message_type_vals, ""),
3561 dmp.st_type);
3562 field_tree = proto_item_add_subtree (tf, ett_message_st_type);
3563 proto_tree_add_item (field_tree, hf_message_st_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3565 if ((message & 0x20) >> 5) {
3566 /* Reserved */
3567 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x20,
3568 tvb, offset, 1, message,
3569 "Reserved: %d", (message & 0x20)>>5);
3570 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3571 tf = proto_tree_add_item (field_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
3572 expert_add_info(pinfo, tf, &ei_reserved_value);
3575 /* Precedence */
3576 dmp.prec = (message & 0x1C) >> 2;
3577 tf = proto_tree_add_uint_format (message_tree, hf_message_precedence,
3578 tvb, offset, 1, message,
3579 "Precedence: %s (%d)",
3580 val_to_str_const (dmp.prec, precedence, ""),
3581 dmp.prec);
3582 field_tree = proto_item_add_subtree (tf, ett_message_precedence);
3583 proto_tree_add_item (field_tree, hf_message_precedence, tvb, offset, 1, ENC_BIG_ENDIAN);
3585 } else {
3586 if ((message & 0xE0) >> 5) {
3587 /* Reserved */
3588 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0xE0,
3589 tvb, offset, 1, message,
3590 "Reserved: %d", (message & 0xE0)>>5);
3591 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3592 tf = proto_tree_add_item (field_tree, hf_reserved_0xE0, tvb, offset, 1, ENC_BIG_ENDIAN);
3593 expert_add_info(pinfo, tf, &ei_reserved_value);
3596 /* Importance */
3597 dmp.prec = (message & 0x1C) >> 2;
3598 tf = proto_tree_add_uint_format (message_tree, hf_message_importance,
3599 tvb, offset, 1, message,
3600 "Importance: %s (%d)",
3601 val_to_str_const (dmp.prec, importance, ""),
3602 dmp.prec);
3603 field_tree = proto_item_add_subtree (tf, ett_message_importance);
3604 proto_tree_add_item (field_tree, hf_message_importance, tvb, offset, 1, ENC_BIG_ENDIAN);
3607 /* Body Format */
3608 tf = proto_tree_add_uint_format (message_tree, hf_message_body_format,
3609 tvb, offset, 1, message,
3610 "Body Format: %s (%d)",
3611 val_to_str_const (message & 0x03,
3612 body_format_vals, ""),
3613 message & 0x03);
3614 field_tree = proto_item_add_subtree (tf, ett_message_body_format);
3615 proto_tree_add_item (field_tree, hf_message_body_format, tvb, offset, 1, ENC_BIG_ENDIAN);
3616 offset += 1;
3619 message = tvb_get_uint8 (tvb, offset);
3620 /* Security Classification */
3621 dmp_sec_class = (message & 0xE0) >> 5;
3622 dmp_sec_pol = (message & 0x1C) >> 2;
3623 if (dmp_sec_pol == EXTENDED_NATIONAL) {
3624 dmp_nation = tvb_get_uint8 (tvb, offset + 1);
3627 loffset = offset; /* Offset to start of security label */
3628 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3629 class_name = dmp_national_sec_class (dmp_local_nation, dmp_sec_class);
3630 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3631 class_name = dmp_national_sec_class (dmp_nation, dmp_sec_class);
3633 if ((dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL) && !class_name) {
3634 class_name = val_to_str_const (dmp_sec_class, sec_class, "");
3636 if (class_name && class_name[0]) {
3637 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3638 tvb, offset, 1, message,
3639 "Security Classification: %s (%d)",
3640 class_name, dmp_sec_class);
3641 } else {
3642 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
3643 tvb, offset, 1, message,
3644 "Security Classification: %d",
3645 dmp_sec_class);
3647 field_tree = proto_item_add_subtree (tf, ett_message_sec_class);
3648 tf = proto_tree_add_item (field_tree, hf_message_sec_class_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3649 if (class_name) {
3650 proto_item_append_text (tf, " (%s)", class_name);
3651 label_string = wmem_strconcat(pinfo->pool, label_string, class_name, NULL);
3654 /* Security Policy */
3655 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_pol,
3656 tvb, offset, 1, message,
3657 "Security Policy: %s (%d)",
3658 val_to_str (dmp_sec_pol, sec_pol, "%d"),
3659 dmp_sec_pol);
3660 field_tree = proto_item_add_subtree (tf, ett_message_sec_pol);
3661 proto_tree_add_item (field_tree, hf_message_sec_pol, tvb, offset, 1, ENC_BIG_ENDIAN);
3663 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3664 /* Heading Flags */
3665 tf = proto_tree_add_item (message_tree, hf_message_heading_flags, tvb, offset, 1, ENC_NA);
3666 field_tree = proto_item_add_subtree (tf, ett_message_heading_flags);
3667 proto_tree_add_item (field_tree, hf_message_auth_users, tvb, offset, 1, ENC_BIG_ENDIAN);
3668 proto_tree_add_item (field_tree, hf_message_subject_disc, tvb, offset, 1, ENC_BIG_ENDIAN);
3669 if (message & 0x03) {
3670 proto_item_append_text (tf, ": %s%s%s discarded",
3671 (message & 0x02) ? "Authorizing users" : "",
3672 (message & 0x03) == 0x03 ? " and " : "",
3673 (message & 0x01) ? "Subject" : "");
3674 } else {
3675 proto_item_append_text (tf, " (none)");
3677 } else if (dmp.msg_type == NOTIF) {
3678 /* Notification Type */
3679 dmp.notif_type = (message & 0x03);
3680 tf = proto_tree_add_uint_format (message_tree, hf_notif_type,
3681 tvb, offset, 1, message,
3682 "Notification Type: %s",
3683 val_to_str_const (dmp.notif_type, notif_type,
3684 "Reserved"));
3685 field_tree = proto_item_add_subtree (tf, ett_notif_type);
3686 proto_tree_add_item (field_tree, hf_notif_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3687 } else if (message & 0x02) {
3688 /* Reserved */
3689 tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x02,
3690 tvb, offset, 1, message,
3691 "Reserved: %d", message & 0x02);
3692 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3693 tf = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3694 expert_add_info(pinfo, tf, &ei_reserved_value);
3696 offset += 1;
3698 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3699 /* Show configured national policy */
3700 tf = proto_tree_add_uint (message_tree, hf_message_national_policy_id,
3701 tvb, offset, 0, dmp_local_nation);
3702 proto_item_set_generated (tf);
3703 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3704 /* National Policy Identifier */
3705 proto_tree_add_item (message_tree, hf_message_national_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3706 offset += 1;
3707 } else if (dmp_sec_pol == EXTENDED_MISSION) {
3708 /* Mission Policy Identifier */
3709 message = tvb_get_uint8 (tvb, offset);
3710 if (message == 0xFF) {
3711 proto_tree_add_uint_format_value (message_tree, hf_message_mission_policy_id,
3712 tvb, offset, 1, message,
3713 "Reserved (0xFF)");
3714 } else {
3715 proto_tree_add_item (message_tree, hf_message_mission_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3717 offset += 1;
3720 /* Security Categories */
3721 if (dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL || dmp_sec_pol == EXTENDED_NATIONAL) {
3722 uint8_t ext = 0;
3723 unsigned sec_cat_count = 0;
3724 do {
3725 offset = dissect_dmp_security_category (tvb, pinfo, message_tree, &label_string, offset, &ext);
3726 sec_cat_count++;
3727 } while (ext != 0 && sec_cat_count < UINT8_MAX);
3728 if (sec_cat_count == UINT8_MAX) {
3729 /* This is a arbitrary limit to avoid a long dissector loop. */
3730 expert_add_info(pinfo, en, &ei_too_many_sec_cat);
3732 proto_item_append_text (en, ", Security Label: %s", label_string);
3733 tf = proto_tree_add_string (message_tree, hf_message_sec_label, tvb, loffset,
3734 offset - loffset, label_string);
3735 proto_item_set_generated (tf);
3736 } else {
3737 tf = proto_tree_add_item (message_tree, hf_message_sec_cat_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3738 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3740 proto_tree_add_item (field_tree, hf_message_sec_cat_bit7, tvb, offset, 1, ENC_BIG_ENDIAN);
3741 proto_tree_add_item (field_tree, hf_message_sec_cat_bit6, tvb, offset, 1, ENC_BIG_ENDIAN);
3742 proto_tree_add_item (field_tree, hf_message_sec_cat_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
3743 proto_tree_add_item (field_tree, hf_message_sec_cat_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
3744 proto_tree_add_item (field_tree, hf_message_sec_cat_bit3, tvb, offset, 1, ENC_BIG_ENDIAN);
3745 proto_tree_add_item (field_tree, hf_message_sec_cat_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
3746 proto_tree_add_item (field_tree, hf_message_sec_cat_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3747 proto_tree_add_item (field_tree, hf_message_sec_cat_bit0, tvb, offset, 1, ENC_BIG_ENDIAN);
3748 offset += 1;
3751 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3752 /* Expiry Time */
3753 exp_time = tvb_get_uint8 (tvb, offset);
3754 tf = proto_tree_add_uint_format (message_tree, hf_message_exp_time,
3755 tvb, offset, 1, exp_time,
3756 "Expiry Time: ");
3757 field_tree = proto_item_add_subtree (tf, ett_message_exp_time);
3758 ei = proto_tree_add_item (field_tree, hf_message_exp_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3759 secs = dmp_dec_exp_time (exp_time);
3760 if (secs == DMP_TIME_NOT_PRESENT) {
3761 proto_item_append_text (tf, "Not present");
3762 proto_item_append_text (ei, " (not present)");
3763 } else if (secs == DMP_TIME_RESERVED) {
3764 proto_item_append_text (tf, "Reserved (0x%2.2x)", exp_time);
3765 proto_item_append_text (ei, " (Reserved)");
3766 } else {
3767 proto_item_append_text (tf, "%s (%s)", signed_time_secs_to_str(pinfo->pool, secs),
3768 abs_time_secs_to_str (pinfo->pool, dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, true));
3769 proto_item_append_text (ei, " (%s from submission time)", signed_time_secs_to_str(pinfo->pool, secs));
3771 offset += 1;
3774 if (dmp.msg_type == STANAG) {
3775 dtg = tvb_get_uint8 (tvb, offset);
3776 tf = proto_tree_add_uint_format (message_tree, hf_message_dtg, tvb, offset, 1, dtg, "DTG: ");
3777 field_tree = proto_item_add_subtree (tf, ett_message_dtg);
3778 proto_tree_add_item (field_tree, hf_message_dtg_sign, tvb, offset, 1, ENC_BIG_ENDIAN);
3779 proto_tree_add_item (field_tree, hf_message_dtg_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3780 secs = dmp_dec_dtg (dtg & 0x7F);
3781 if (secs == DMP_TIME_NOT_PRESENT) {
3782 proto_item_append_text (tf, "Not present");
3783 } else if (secs == DMP_TIME_RESERVED) {
3784 proto_item_append_text (tf, "Reserved (0x%2.2x)", dtg & 0x7F);
3785 } else if (secs == 0) {
3786 proto_item_append_text (tf, "0 minutes in the %s (%s)",
3787 tfs_get_string(dtg & 0x80, &dtg_sign),
3788 abs_time_secs_to_str (pinfo->pool, dmp.subm_time, ABSOLUTE_TIME_LOCAL, true));
3789 } else {
3790 proto_item_append_text (tf, "%s in the %s (%s)", signed_time_secs_to_str(pinfo->pool, secs),
3791 tfs_get_string(dtg & 0x80, &dtg_sign), (dtg & 0x80) ?
3792 abs_time_secs_to_str (pinfo->pool, dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, true) :
3793 abs_time_secs_to_str (pinfo->pool, dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, true));
3795 offset += 1;
3798 if (dmp.msg_type == STANAG) {
3799 /* SIC */
3800 offset = dissect_dmp_sic (tvb, pinfo, message_tree, offset);
3801 } else if (dmp.msg_type == REPORT || dmp.msg_type == NOTIF) {
3802 if (dmp.version == DMP_VERSION_1 || dmp.msg_id_type == ONLY_DMP_ID) {
3803 /* Subject Message Identifier */
3804 dmp.subj_id = tvb_get_ntohs (tvb, offset);
3805 proto_tree_add_item (message_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3806 hidden_item = proto_tree_add_item (message_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3807 proto_item_set_hidden (hidden_item);
3808 offset += 2;
3809 } else if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
3810 if (dmp.msg_type == REPORT) {
3811 /* Subject MTS Identifier */
3812 offset = dissect_mts_identifier (tvb, pinfo, message_tree, offset, true);
3813 } else {
3814 /* Subject IPM Identifier */
3815 offset = dissect_ipm_identifier (tvb, pinfo, message_tree, offset, true);
3817 if (dmp.subj_id) {
3818 tf = proto_tree_add_uint (message_tree, hf_message_subj_id, tvb, offset, 0, dmp.subj_id);
3819 proto_item_set_generated (tf);
3820 hidden_item = proto_tree_add_uint (message_tree, hf_dmp_id, tvb, offset, 0, dmp.subj_id);
3821 proto_item_set_generated (hidden_item);
3822 proto_item_set_hidden (hidden_item);
3827 if (use_seq_ack_analysis) {
3828 register_dmp_id (pinfo, 0);
3831 proto_item_set_len (en, offset - boffset);
3833 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3834 /* User Data */
3835 offset = dissect_dmp_message (tvb, pinfo, dmp_tree, offset);
3836 } else if (dmp.msg_type == REPORT) {
3837 /* One or more Delivery Report or Non-Delivery Report Data */
3838 rep_len = tvb_reported_length (tvb);
3839 if (dmp.checksum) {
3840 rep_len -= 2;
3842 while (offset < rep_len) {
3843 offset = dissect_dmp_report (tvb, pinfo, dmp_tree, offset, &prev_rec_no, rep_no++);
3845 } else if (dmp.msg_type == NOTIF) {
3846 /* Notification Data */
3847 offset = dissect_dmp_notification (tvb, pinfo, dmp_tree, offset);
3850 return offset;
3853 static int dissect_dmp_extensions (tvbuff_t *tvb, packet_info *pinfo _U_,
3854 proto_tree *dmp_tree, int offset)
3856 proto_tree *exts_tree, *ext_tree, *hdr_tree;
3857 proto_item *exts_item, *en;
3858 uint8_t ext_hdr, ext_length;
3859 bool more_extensions = true;
3860 int num_ext = 0, boffset = offset;
3862 exts_item = proto_tree_add_item (dmp_tree, hf_extensions, tvb, offset, -1, ENC_NA);
3863 exts_tree = proto_item_add_subtree (exts_item, ett_extensions);
3865 while (more_extensions) {
3866 /* Extensions Present */
3867 ext_hdr = tvb_get_uint8 (tvb, offset);
3868 more_extensions = (ext_hdr & 0x80);
3869 ext_length = (ext_hdr & 0x7F) + 1;
3871 en = proto_tree_add_none_format (exts_tree, hf_extension, tvb, offset, ext_length + 1,
3872 "Extension (#%d)", num_ext + 1);
3873 ext_tree = proto_item_add_subtree (en, ett_extension);
3875 en = proto_tree_add_none_format (ext_tree, hf_extension_header, tvb, offset, 1,
3876 "Extension Length: %u, More %s", ext_length,
3877 (ext_hdr & 0x80) ? "Present" : "Not present");
3878 hdr_tree = proto_item_add_subtree (en, ett_extension_header);
3879 proto_tree_add_item (hdr_tree, hf_extension_more, tvb, offset, 1, ENC_BIG_ENDIAN);
3880 proto_tree_add_item (hdr_tree, hf_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3881 offset += 1;
3883 proto_tree_add_item (ext_tree, hf_extension_data, tvb, offset, ext_length, ENC_NA);
3884 offset += ext_length;
3885 num_ext++;
3888 proto_item_append_text (exts_item, " (%d item%s)", num_ext, plurality (num_ext, "", "s"));
3889 proto_item_set_len (exts_item, offset - boffset);
3891 return offset;
3894 static int dissect_dmp (tvbuff_t *tvb, packet_info *pinfo,
3895 proto_tree *tree, void *data _U_)
3897 proto_tree *dmp_tree;
3898 proto_item *ti;
3899 uint16_t checksum1 = 0, checksum2 = 1;
3900 int length, offset = 0;
3901 bool retrans_or_dup_ack = false;
3903 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DMP");
3904 col_clear (pinfo->cinfo, COL_INFO);
3906 /* Initialize global data structure */
3907 memset (&dmp, 0, sizeof (dmp));
3909 ti = proto_tree_add_item (tree, proto_dmp, tvb, offset, -1, ENC_NA);
3910 dmp_tree = proto_item_add_subtree (ti, ett_dmp);
3912 offset = dissect_dmp_envelope (tvb, pinfo, dmp_tree, offset);
3914 if (dmp.version > DMP_VERSION_2) {
3915 /* Unsupported DMP Version, no point to continue */
3916 col_add_fstr (pinfo->cinfo, COL_INFO, "Unsupported Version: %d", dmp.version);
3917 return 0;
3920 if (dmp.extensions) {
3921 offset = dissect_dmp_extensions (tvb, pinfo, dmp_tree, offset);
3924 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3925 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3927 offset = dissect_dmp_content (tvb, pinfo, dmp_tree, offset);
3928 } else if (dmp.msg_type == ACK) {
3929 offset = dissect_dmp_ack (tvb, pinfo, dmp_tree, offset);
3932 if (dmp.checksum) {
3933 length = tvb_captured_length (tvb);
3934 checksum1 = crc16_x25_ccitt_tvb (tvb, length - 2);
3935 checksum2 = tvb_get_ntohs (tvb, offset);
3937 proto_tree_add_checksum(dmp_tree, tvb, offset, hf_checksum, hf_checksum_status, &ei_checksum_bad, pinfo, checksum1, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
3938 offset += 2;
3941 if (use_seq_ack_analysis) {
3942 dmp_add_seq_ack_analysis (tvb, pinfo, dmp_tree, offset);
3945 if (((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3946 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) &&
3947 dmp.id_val && dmp.id_val->msg_resend_count)
3949 unsigned retrans_num;
3950 if (dmp.msg_type == REPORT) {
3951 retrans_num = dmp.id_val->rep_id;
3952 } else if (dmp.msg_type == NOTIF) {
3953 retrans_num = dmp.id_val->not_id;
3954 } else {
3955 retrans_num = dmp.id_val->msg_id;
3957 col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ",
3958 retrans_num, dmp.id_val->msg_resend_count);
3959 retrans_or_dup_ack = true;
3960 } else if (dmp.msg_type == ACK && dmp.id_val && dmp.id_val->ack_resend_count) {
3961 col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ",
3962 dmp.id_val->ack_id, dmp.id_val->ack_resend_count);
3963 retrans_or_dup_ack = true;
3965 if (dmp_align && !retrans_or_dup_ack) {
3966 if (dmp.msg_type == ACK) {
3967 /* ACK does not have "Msg Id" */
3968 col_append_fstr (pinfo->cinfo, COL_INFO, "%-45.45s", msg_type_to_str ());
3969 } else {
3970 col_append_fstr (pinfo->cinfo, COL_INFO, "%-31.31s", msg_type_to_str ());
3972 } else {
3973 col_append_str (pinfo->cinfo, COL_INFO, msg_type_to_str ());
3975 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3976 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3978 if (dmp_align && !retrans_or_dup_ack) {
3979 col_append_fstr (pinfo->cinfo, COL_INFO, " Msg Id: %5d", dmp.msg_id);
3980 } else {
3981 col_append_fstr (pinfo->cinfo, COL_INFO, ", Msg Id: %d", dmp.msg_id);
3984 if ((dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF) ||
3985 (dmp.msg_type == ACK))
3987 if (dmp_align && !retrans_or_dup_ack) {
3988 col_append_fstr (pinfo->cinfo, COL_INFO, " Subj Id: %5d",
3989 dmp.subj_id);
3990 } else {
3991 col_append_fstr (pinfo->cinfo, COL_INFO, ", Subj Id: %d",
3992 dmp.subj_id);
3995 if (dmp.checksum && (checksum1 != checksum2)) {
3996 col_append_str (pinfo->cinfo, COL_INFO, ", Checksum incorrect");
3999 proto_item_append_text (ti, ", Version: %d%s, %s", dmp.version,
4000 (dmp.prot_id == PROT_NAT ? " (national)" : ""),
4001 msg_type_to_str());
4003 return offset;
4006 void proto_register_dmp (void)
4008 static hf_register_info hf[] = {
4010 ** DMP Identifier
4012 { &hf_dmp_id,
4013 { "DMP Identifier", "dmp.id", FT_UINT16, BASE_DEC,
4014 NULL, 0x0, NULL, HFILL} },
4016 /* MTS Identifier */
4017 { &hf_mts_id,
4018 { "MTS Identifier", "dmp.mts", FT_STRING, BASE_NONE,
4019 NULL, 0x0, NULL, HFILL } },
4021 /* IPM Identifier */
4022 { &hf_ipm_id,
4023 { "IPM Identifier", "dmp.ipm", FT_STRING, BASE_NONE,
4024 NULL, 0x0, NULL, HFILL } },
4027 ** Envelope
4029 { &hf_envelope,
4030 { "Envelope", "dmp.envelope", FT_NONE, BASE_NONE,
4031 NULL, 0x0, NULL, HFILL} },
4033 /* Protocol data */
4034 { &hf_envelope_protocol_id,
4035 { "Protocol Identifier", "dmp.protocol_id", FT_UINT8,
4036 BASE_HEX, NULL, 0xF8, NULL, HFILL} },
4037 { &hf_envelope_version,
4038 { "Protocol Version", "dmp.version", FT_UINT8, BASE_DEC,
4039 VALS(version_vals), 0x07, NULL, HFILL } },
4040 { &hf_envelope_version_value,
4041 { "Protocol Version", "dmp.version_value", FT_UINT8, BASE_DEC,
4042 VALS(version_vals), 0x07, NULL, HFILL } },
4044 /* Envelope elements (byte 1) */
4045 { &hf_envelope_hop_count,
4046 { "Hop Count", "dmp.hop_count", FT_UINT8, BASE_DEC,
4047 NULL, 0xE0, NULL, HFILL } },
4048 { &hf_envelope_hop_count_value,
4049 { "Hop Count", "dmp.hop_count_value", FT_UINT8, BASE_DEC,
4050 NULL, 0xE0, NULL, HFILL } },
4051 { &hf_envelope_rec_present,
4052 { "Recipient Present", "dmp.rec_present", FT_BOOLEAN, 8,
4053 TFS (&tfs_present_absent), 0x20, NULL, HFILL } },
4054 { &hf_envelope_addr_enc,
4055 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4056 TFS (&addr_enc), 0x10, NULL, HFILL } },
4057 { &hf_envelope_checksum,
4058 { "Checksum", "dmp.checksum_used", FT_BOOLEAN, 8,
4059 TFS (&tfs_used_notused), 0x08, "Checksum Used", HFILL } },
4060 { &hf_envelope_type,
4061 { "Content Type", "dmp.content_type", FT_UINT8, BASE_DEC,
4062 VALS(type_vals), 0x07, NULL, HFILL } },
4064 /* Envelope elements (byte 2) */
4065 { &hf_envelope_extensions,
4066 { "Extensions", "dmp.extensions_used", FT_BOOLEAN, 8,
4067 TFS (&tfs_present_absent), 0x80, "Extensions Used", HFILL } },
4068 { &hf_envelope_msg_id_type,
4069 { "Message Identifier Type", "dmp.msg_id_type", FT_UINT8, BASE_DEC,
4070 VALS(msg_id_type_vals), 0x60, NULL, HFILL } },
4071 { &hf_envelope_msg_id_length,
4072 { "Message Identifier Length", "dmp.msg_id_short", FT_UINT8, BASE_DEC,
4073 VALS(msg_id_length_vals), 0x10, NULL, HFILL} },
4074 { &hf_envelope_mts_id_length,
4075 { "MTS Identifier Length", "dmp.mts_id_length", FT_UINT8, BASE_DEC,
4076 NULL, 0x1F, NULL, HFILL } },
4077 { &hf_envelope_ipm_id_modifier,
4078 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4079 VALS(ipm_id_modifier), 0xC0, NULL, HFILL } },
4080 { &hf_envelope_ipm_id_length,
4081 { "IPM Identifier Length", "dmp.ipm_id_length", FT_UINT8, BASE_DEC,
4082 NULL, 0x3F, NULL, HFILL } },
4084 { &hf_thales_ipm_id_modifier,
4085 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4086 VALS(thales_ipm_id_modifier), 0xC0, "Thales XOmail IPM Identifier Modifier", HFILL } },
4088 /* Message identifier */
4089 { &hf_envelope_msg_id,
4090 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4091 NULL, 0x0, NULL, HFILL} },
4092 { &hf_envelope_msg_id_12bit,
4093 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4094 NULL, 0x0FFF, NULL, HFILL} },
4096 /* MTS Identifier */
4097 { &hf_envelope_mts_id,
4098 { "MTS Identifier", "dmp.mts_id", FT_STRING, BASE_NONE,
4099 NULL, 0x0, NULL, HFILL } },
4101 /* IPM Identifier */
4102 { &hf_envelope_ipm_id,
4103 { "IPM Identifier", "dmp.ipm_id", FT_STRING, BASE_NONE,
4104 NULL, 0x0, NULL, HFILL } },
4106 /* Extensions */
4107 { &hf_extensions,
4108 { "Extensions", "dmp.extensions", FT_NONE, BASE_NONE,
4109 NULL, 0x0, NULL, HFILL} },
4110 { &hf_extension,
4111 { "Extension", "dmp.extension", FT_NONE, BASE_NONE,
4112 NULL, 0x0, NULL, HFILL } },
4113 { &hf_extension_header,
4114 { "Extension Header", "dmp.extension_header", FT_NONE, BASE_NONE,
4115 NULL, 0x0, NULL, HFILL} },
4116 { &hf_extension_more,
4117 { "More Extensions", "dmp.extension_more", FT_BOOLEAN, 8,
4118 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4119 { &hf_extension_length,
4120 { "Extension Length (minus one)", "dmp.extension_length", FT_UINT8, BASE_DEC,
4121 NULL, 0x7F, "Extension Length minus one", HFILL } },
4122 { &hf_extension_data,
4123 { "Extension Data", "dmp.extension_data", FT_BYTES, BASE_NONE,
4124 NULL, 0x0, NULL, HFILL } },
4126 /* Submission time */
4127 { &hf_envelope_subm_time,
4128 { "Submission Time", "dmp.subm_time", FT_UINT16, BASE_HEX,
4129 NULL, 0x0, NULL, HFILL } },
4130 { &hf_envelope_time_diff_present,
4131 { "Time Diff", "dmp.time_diff_present", FT_BOOLEAN, 16,
4132 TFS (&tfs_present_absent), 0x8000, "Time Diff Present", HFILL } },
4133 { &hf_envelope_subm_time_value,
4134 { "Submission Time Value", "dmp.subm_time_value", FT_UINT16,
4135 BASE_HEX, NULL, 0x7FFF, NULL, HFILL } },
4136 { &hf_envelope_time_diff,
4137 { "Time Difference", "dmp.time_diff", FT_UINT8, BASE_HEX,
4138 NULL, 0x0, NULL, HFILL } },
4139 { &hf_envelope_time_diff_value,
4140 { "Time Difference Value", "dmp.time_diff_value", FT_UINT8,
4141 BASE_HEX, NULL, 0x0, NULL, HFILL } },
4143 /* Envelope flags */
4144 { &hf_envelope_flags,
4145 { "Flags", "dmp.envelope_flags", FT_UINT8, BASE_DEC,
4146 NULL, 0x0, "Envelope Flags", HFILL} },
4147 { &hf_envelope_content_id_discarded,
4148 { "Content Identifier discarded", "dmp.cont_id_discarded",
4149 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
4150 NULL, HFILL } },
4151 { &hf_envelope_recip_reassign_prohib,
4152 { "Recipient reassign prohibited","dmp.recip_reassign_prohib",
4153 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
4154 NULL, HFILL } },
4155 { &hf_envelope_dl_expansion_prohib,
4156 { "DL expansion prohibited", "dmp.dl_expansion_prohib",
4157 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL,
4158 HFILL } },
4160 /* Recipient Count */
4161 { &hf_envelope_recipients,
4162 { "Recipient Count", "dmp.rec_count", FT_UINT8, BASE_DEC,
4163 NULL, 0x1F, NULL, HFILL} },
4164 { &hf_envelope_ext_recipients,
4165 { "Extended Recipient Count", "dmp.ext_rec_count", FT_UINT16,
4166 BASE_DEC, NULL, 0x7FFF, NULL, HFILL} },
4169 ** Address
4171 { &hf_addr_recipient,
4172 { "Recipient Number", "dmp.recipient", FT_NONE, BASE_NONE,
4173 NULL, 0x0, NULL, HFILL } },
4174 { &hf_addr_originator,
4175 { "Originator", "dmp.originator", FT_NONE, BASE_NONE,
4176 NULL, 0x0, NULL, HFILL } },
4177 { &hf_addr_reporting_name,
4178 { "Reporting Name Number", "dmp.reporting_name", FT_NONE,
4179 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4180 { &hf_addr_dl_expanded,
4181 { "DL Expanded", "dmp.dl_expanded", FT_BOOLEAN, BASE_NONE,
4182 NULL, 0x0, "Message has been DL expanded", HFILL } },
4183 { &hf_addr_int_rec,
4184 { "Intended Recipient", "dmp.int_rec", FT_BOOLEAN, BASE_NONE,
4185 NULL, 0x0, "Message has an intended recipient", HFILL } },
4188 ** Address Direct
4190 { &hf_addr_dir_addr_ext,
4191 { "Address Extended", "dmp.addr_ext", FT_BOOLEAN, 8,
4192 NULL, 0x80, NULL, HFILL } },
4193 { &hf_addr_dir_rec_no,
4194 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4195 BASE_DEC, NULL, 0xF0, NULL, HFILL } },
4196 { &hf_addr_dir_rec_no_generated,
4197 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4198 BASE_DEC, NULL, 0x0, "Recipient Number Offset", HFILL } },
4199 { &hf_addr_dir_rec_no1,
4200 { "Recipient Number (bits 3-0)", "dmp.rec_no_offset1", FT_UINT8,
4201 BASE_DEC, NULL, 0xF0, "Recipient Number (bits 3-0) Offset", HFILL } },
4202 { &hf_addr_dir_rec_no2,
4203 { "Recipient Number (bits 9-4)", "dmp.rec_no_offset2", FT_UINT8,
4204 BASE_DEC, NULL, 0x3F, "Recipient Number (bits 9-4) Offset", HFILL } },
4205 { &hf_addr_dir_rec_no3,
4206 { "Recipient Number (bits 14-10)", "dmp.rec_no_offset3", FT_UINT8,
4207 BASE_DEC, NULL, 0x1F, "Recipient Number (bits 14-10) Offset",HFILL } },
4208 { &hf_addr_dir_rep_req1,
4209 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4210 VALS (report_vals_ext), 0x0C, NULL, HFILL } },
4211 { &hf_addr_dir_rep_req2,
4212 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4213 VALS (report_vals_ext), 0xC0, NULL, HFILL } },
4214 { &hf_addr_dir_rep_req3,
4215 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4216 VALS (report_vals), 0xC0, NULL, HFILL } },
4217 { &hf_addr_dir_not_req1,
4218 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4219 VALS (notif_vals_ext), 0x03, NULL, HFILL } },
4220 { &hf_addr_dir_not_req2,
4221 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4222 VALS (notif_vals_ext), 0xC0, NULL, HFILL } },
4223 { &hf_addr_dir_not_req3,
4224 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4225 VALS (notif_vals), 0xC0, NULL, HFILL } },
4226 { &hf_addr_dir_action,
4227 { "Action", "dmp.action", FT_BOOLEAN, 8,
4228 TFS (&tfs_yes_no), 0x80, NULL, HFILL } },
4229 { &hf_addr_dir_address,
4230 { "Direct Address", "dmp.direct_addr", FT_UINT8,
4231 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4232 { &hf_addr_dir_address_generated,
4233 { "Direct Address", "dmp.direct_addr", FT_UINT32,
4234 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4235 { &hf_addr_dir_address1,
4236 { "Direct Address (bits 6-0)", "dmp.direct_addr1", FT_UINT8,
4237 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4238 { &hf_addr_dir_address2,
4239 { "Direct Address (bits 12-7)", "dmp.direct_addr2", FT_UINT8,
4240 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4241 { &hf_addr_dir_address3,
4242 { "Direct Address (bits 18-13)", "dmp.direct_addr3", FT_UINT8,
4243 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4246 ** Address Extended
4248 { &hf_addr_ext_form,
4249 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4250 VALS (addr_form), 0xE0, NULL, HFILL } },
4251 { &hf_addr_ext_form_orig_v1,
4252 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4253 VALS (addr_form_orig_v1), 0xE0, NULL, HFILL } },
4254 { &hf_addr_ext_form_orig,
4255 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4256 VALS (addr_form_orig), 0xE0, NULL, HFILL } },
4257 { &hf_addr_ext_action,
4258 { "Action", "dmp.action", FT_BOOLEAN, 8,
4259 TFS (&tfs_yes_no), 0x10, NULL, HFILL } },
4260 { &hf_addr_ext_rep_req,
4261 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4262 VALS (report_vals), 0x0C, NULL, HFILL } },
4263 { &hf_addr_ext_not_req,
4264 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4265 VALS (notif_vals), 0x03, NULL, HFILL } },
4266 { &hf_addr_ext_rec_ext,
4267 { "Recipient Number Extended", "dmp.rec_no_ext", FT_BOOLEAN, 8,
4268 NULL, 0x80, NULL, HFILL } },
4269 { &hf_addr_ext_rec_no,
4270 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4271 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4272 { &hf_addr_ext_rec_no_generated,
4273 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4274 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4275 { &hf_addr_ext_rec_no1,
4276 { "Recipient Number (bits 6-0)", "dmp.rec_no_offset1", FT_UINT8,
4277 BASE_DEC, NULL, 0x7F, "Recipient Number (bits 6-0) Offset", HFILL } },
4278 { &hf_addr_ext_rec_no2,
4279 { "Recipient Number (bits 14-7)", "dmp.rec_no_offset2", FT_UINT8,
4280 BASE_DEC, NULL, 0x0, "Recipient Number (bits 14-7) Offset", HFILL } },
4281 { &hf_addr_ext_address,
4282 { "Extended Address", "dmp.addr_form_ext", FT_NONE, BASE_NONE,
4283 NULL, 0x0, NULL, HFILL } },
4284 { &hf_addr_ext_type,
4285 { "Address Type", "dmp.addr_type", FT_UINT8, BASE_DEC,
4286 VALS (ext_addr_type), 0xE0, NULL, HFILL } },
4287 { &hf_addr_ext_type_ext,
4288 { "Address Type Extended", "dmp.addr_type_ext", FT_UINT8,
4289 BASE_DEC, VALS (ext_addr_type_ext), 0xE0, NULL,
4290 HFILL } },
4291 { &hf_addr_ext_length,
4292 { "Address Length", "dmp.addr_length", FT_UINT8,
4293 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4294 { &hf_addr_ext_length_generated,
4295 { "Address Length", "dmp.addr_length", FT_UINT32,
4296 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4297 { &hf_addr_ext_length1,
4298 { "Address Length (bits 4-0)", "dmp.addr_length1", FT_UINT8,
4299 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4300 { &hf_addr_ext_length2,
4301 { "Address Length (bits 9-5)", "dmp.addr_length2", FT_UINT8,
4302 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4303 { &hf_addr_ext_asn1_ber,
4304 { "ASN.1 BER-encoded OR-name", "dmp.or_name", FT_NONE,
4305 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4306 { &hf_addr_ext_asn1_per,
4307 { "ASN.1 PER-encoded OR-name", "dmp.asn1_per", FT_BYTES,
4308 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4309 { &hf_addr_ext_unknown,
4310 { "Unknown encoded address", "dmp.addr_unknown", FT_BYTES,
4311 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4314 ** Message content
4316 { &hf_message_content,
4317 { "Message Content", "dmp.message", FT_NONE, BASE_NONE,
4318 NULL, 0x0, NULL, HFILL } },
4319 { &hf_report_content,
4320 { "Report Content", "dmp.report", FT_NONE, BASE_NONE,
4321 NULL, 0x0, NULL, HFILL } },
4322 { &hf_notif_content,
4323 { "Notification Content", "dmp.notification", FT_NONE, BASE_NONE,
4324 NULL, 0x0, NULL, HFILL } },
4326 { &hf_message_st_type,
4327 { "Message type", "dmp.msg_type", FT_UINT8, BASE_DEC,
4328 VALS (message_type_vals), 0xC0, NULL, HFILL } },
4329 { &hf_message_precedence,
4330 { "Precedence", "dmp.precedence", FT_UINT8, BASE_DEC,
4331 VALS (precedence), 0x1C, NULL, HFILL } },
4332 { &hf_message_importance,
4333 { "Importance", "dmp.importance", FT_UINT8, BASE_DEC,
4334 VALS (importance), 0x1C, NULL, HFILL } },
4335 { &hf_message_body_format,
4336 { "Body format", "dmp.body_format", FT_UINT8, BASE_DEC,
4337 VALS (body_format_vals), 0x03, NULL, HFILL } },
4339 /* Security Values */
4340 { &hf_message_sec_label,
4341 { "Security Label", "dmp.sec_label", FT_STRING, BASE_NONE,
4342 NULL, 0x0, NULL, HFILL } },
4343 { &hf_message_sec_class_val,
4344 { "Security Classification", "dmp.sec_class", FT_UINT8,
4345 BASE_DEC, NULL, 0xE0, NULL, HFILL} },
4346 { &hf_message_sec_pol,
4347 { "Security Policy", "dmp.sec_pol", FT_UINT8, BASE_DEC,
4348 VALS (sec_pol), 0x1C, NULL, HFILL } },
4349 { &hf_message_heading_flags,
4350 { "Heading Flags", "dmp.heading_flags", FT_NONE, BASE_NONE,
4351 NULL, 0x0, NULL, HFILL } },
4352 { &hf_message_auth_users,
4353 { "Authorizing users discarded", "dmp.auth_discarded",
4354 FT_BOOLEAN, 8, TFS (&tfs_yes_no), 0x02,
4355 NULL, HFILL } },
4356 { &hf_message_subject_disc,
4357 { "Subject discarded", "dmp.subject_discarded", FT_BOOLEAN, 8,
4358 TFS (&tfs_yes_no), 0x01, NULL, HFILL } },
4360 /* National Policy Identifier */
4361 { &hf_message_national_policy_id,
4362 { "National Policy Identifier", "dmp.nat_pol_id", FT_UINT8,
4363 BASE_DEC, VALS(nat_pol_id), 0x0, NULL,
4364 HFILL } },
4366 /* Mission Policy Identifier */
4367 { &hf_message_mission_policy_id,
4368 { "Mission Policy Identifier", "dmp.mission_pol_id", FT_UINT8,
4369 BASE_DEC, NULL, 0x0, NULL,
4370 HFILL } },
4372 /* Security Categories */
4373 { &hf_message_sec_cat_nat,
4374 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4375 NULL, 0x0, NULL, HFILL } },
4376 { &hf_message_sec_cat_val,
4377 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4378 NULL, 0x0, NULL, HFILL } },
4379 { &hf_message_sec_cat_cl,
4380 { "Clear", "dmp.sec_cat.cl", FT_BOOLEAN, 8,
4381 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4382 { &hf_message_sec_cat_cs,
4383 { "Crypto Security", "dmp.sec_cat.cs", FT_BOOLEAN, 8,
4384 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4385 { &hf_message_sec_cat_ex,
4386 { "Exclusive", "dmp.sec_cat.ex", FT_BOOLEAN, 8,
4387 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4388 { &hf_message_sec_cat_ne,
4389 { "National Eyes Only", "dmp.sec_cat.ne", FT_BOOLEAN, 8,
4390 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4391 { &hf_message_sec_cat_permissive,
4392 { "Releasable to", "dmp.sec_cat.permissive", FT_UINT8, BASE_HEX,
4393 VALS (nat_pol_id), 0xFC, NULL, HFILL } },
4394 { &hf_message_sec_cat_country_code,
4395 { "Country Code", "dmp.sec_cat.country", FT_UINT8, BASE_DEC,
4396 NULL, 0x00, NULL, HFILL } },
4397 { &hf_message_sec_cat_restrictive,
4398 { "Restrictive", "dmp.sec_cat.restrictive", FT_UINT8, BASE_HEX,
4399 NULL, 0xFC, NULL, HFILL } },
4400 { &hf_message_sec_cat_extended,
4401 { "Extended", "dmp.sec_cat.extended", FT_UINT8, BASE_HEX,
4402 VALS (ext_sec_cat), 0x03, "Extended Security Category", HFILL } },
4403 { &hf_message_sec_cat_bit0,
4404 { "Bit 0", "dmp.sec_cat.bit0", FT_BOOLEAN, 8,
4405 TFS (&tfs_set_notset), 0x01, NULL, HFILL } },
4406 { &hf_message_sec_cat_bit1,
4407 { "Bit 1", "dmp.sec_cat.bit1", FT_BOOLEAN, 8,
4408 TFS (&tfs_set_notset), 0x02, NULL, HFILL } },
4409 { &hf_message_sec_cat_bit2,
4410 { "Bit 2", "dmp.sec_cat.bit2", FT_BOOLEAN, 8,
4411 TFS (&tfs_set_notset), 0x04, NULL, HFILL } },
4412 { &hf_message_sec_cat_bit3,
4413 { "Bit 3", "dmp.sec_cat.bit3", FT_BOOLEAN, 8,
4414 TFS (&tfs_set_notset), 0x08, NULL, HFILL } },
4415 { &hf_message_sec_cat_bit4,
4416 { "Bit 4", "dmp.sec_cat.bit4", FT_BOOLEAN, 8,
4417 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4418 { &hf_message_sec_cat_bit5,
4419 { "Bit 5", "dmp.sec_cat.bit5", FT_BOOLEAN, 8,
4420 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4421 { &hf_message_sec_cat_bit6,
4422 { "Bit 6", "dmp.sec_cat.bit6", FT_BOOLEAN, 8,
4423 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4424 { &hf_message_sec_cat_bit7,
4425 { "Bit 7", "dmp.sec_cat.bit7", FT_BOOLEAN, 8,
4426 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4428 /* Expiry Time */
4429 { &hf_message_exp_time,
4430 { "Expiry Time", "dmp.expiry_time", FT_UINT8, BASE_HEX,
4431 NULL, 0x0, NULL, HFILL } },
4432 { &hf_message_exp_time_val,
4433 { "Expiry Time Value", "dmp.expiry_time_val", FT_UINT8, BASE_HEX,
4434 NULL, 0x0, NULL, HFILL } },
4436 /* DTG */
4437 { &hf_message_dtg,
4438 { "DTG", "dmp.dtg", FT_UINT8, BASE_HEX,
4439 NULL, 0x0, NULL, HFILL } },
4440 { &hf_message_dtg_sign,
4441 { "DTG in the", "dmp.dtg.sign", FT_BOOLEAN, 8, TFS (&dtg_sign),
4442 0x80, "Sign", HFILL } },
4443 { &hf_message_dtg_val,
4444 { "DTG Value", "dmp.dtg.val", FT_UINT8, BASE_HEX, NULL,
4445 0x7F, NULL, HFILL } },
4447 /* SIC */
4448 { &hf_message_sic,
4449 { "SIC", "dmp.sic", FT_STRING, BASE_NONE,
4450 NULL, 0x0, NULL, HFILL } },
4451 { &hf_message_sic_key,
4452 { "SICs", "dmp.sic_key", FT_NONE, BASE_NONE,
4453 NULL, 0x0, "SIC Content", HFILL } },
4454 { &hf_message_sic_key_values,
4455 { "Content Byte", "dmp.sic_key.values", FT_UINT8, BASE_HEX,
4456 NULL, 0x0, "SIC Content Byte", HFILL } },
4457 { &hf_message_sic_key_type,
4458 { "Type", "dmp.sic_key.type", FT_UINT8, BASE_HEX,
4459 VALS (sic_key_type), 0xF0, "SIC Content Type", HFILL } },
4460 { &hf_message_sic_key_chars,
4461 { "Valid Characters", "dmp.sic_key.chars", FT_BOOLEAN, 8,
4462 TFS (&sic_key_chars), 0x08, "SIC Valid Characters", HFILL } },
4463 { &hf_message_sic_key_num,
4464 { "Number of SICs", "dmp.sic_key.num", FT_UINT8, BASE_HEX,
4465 VALS (sic_key_num), 0x07, NULL, HFILL } },
4466 { &hf_message_sic_bitmap,
4467 { "Length Bitmap (0 = 3 bytes, 1 = 4-8 bytes)", "dmp.sic_bitmap",
4468 FT_UINT8, BASE_HEX, NULL, 0xFF, "SIC Length Bitmap", HFILL } },
4469 { &hf_message_sic_bits,
4470 { "Bit 7-4", "dmp.sic_bits", FT_UINT8, BASE_HEX,
4471 VALS(sic_bit_vals), 0xF0, "SIC Bit 7-4, Characters [A-Z0-9] only",
4472 HFILL } },
4473 { &hf_message_sic_bits_any,
4474 { "Bit 7-4", "dmp.sic_bits_any", FT_UINT8, BASE_HEX,
4475 VALS(sic_bit_any_vals), 0xF0, "SIC Bit 7-4, Any valid characters",
4476 HFILL } },
4478 /* Subject Message Id */
4479 { &hf_message_subj_id,
4480 { "Subject Message Identifier", "dmp.subj_id", FT_UINT16,
4481 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4483 /* Subject MTS Identifier */
4484 { &hf_message_subj_mts_id,
4485 { "Subject MTS Identifier", "dmp.subj_mts_id", FT_STRING, BASE_NONE,
4486 NULL, 0x0, NULL, HFILL } },
4488 /* Subject IPM Identifier */
4489 { &hf_message_subj_ipm_id,
4490 { "Subject IPM Identifier", "dmp.subj_ipm_id", FT_STRING, BASE_NONE,
4491 NULL, 0x0, NULL, HFILL } },
4494 ** Message body
4496 { &hf_message_body,
4497 { "Message Body", "dmp.body", FT_NONE, BASE_NONE, NULL,
4498 0x0, NULL, HFILL} },
4500 /* Body Id */
4501 { &hf_message_eit,
4502 { "EIT", "dmp.body.eit", FT_UINT8, BASE_DEC,
4503 VALS(eit_vals), 0xE0, "Encoded Information Type", HFILL } },
4504 { &hf_message_compr,
4505 { "Compression", "dmp.body.compression", FT_UINT8, BASE_DEC,
4506 VALS(compression_vals), 0x18, NULL, HFILL } },
4508 /* Subject */
4509 { &hf_message_subject,
4510 { "Subject", "dmp.subject", FT_STRINGZ, BASE_NONE,
4511 NULL, 0x0, NULL, HFILL } },
4513 /* Message Body */
4514 { &hf_message_body_data,
4515 { "User data", "dmp.body.data", FT_BYTES, BASE_NONE,
4516 NULL, 0x0, NULL, HFILL } },
4517 { &hf_message_body_compressed,
4518 { "Compressed User data", "dmp.body.compressed", FT_NONE, BASE_NONE,
4519 NULL, 0x0, NULL, HFILL } },
4520 { &hf_message_body_plain,
4521 { "Message Body", "dmp.body.plain", FT_STRING, BASE_NONE,
4522 NULL, 0x0, NULL, HFILL } },
4523 { &hf_message_body_structured,
4524 { "Structured Body", "dmp.body.structured", FT_BYTES, BASE_NONE,
4525 NULL, 0x0, NULL, HFILL } },
4528 ** Report
4530 { &hf_delivery_report,
4531 { "Delivery Report", "dmp.dr", FT_NONE, BASE_NONE, NULL,
4532 0x0, NULL, HFILL} },
4533 { &hf_non_delivery_report,
4534 { "Non-Delivery Report", "dmp.ndr", FT_NONE, BASE_NONE, NULL,
4535 0x0, NULL, HFILL} },
4537 { &hf_report_type,
4538 { "Report Type", "dmp.report_type", FT_BOOLEAN, 8,
4539 TFS (&report_type), 0x80, NULL, HFILL } },
4540 { &hf_report_info_present_dr,
4541 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4542 TFS (&tfs_present_absent), 0x40, NULL, HFILL } },
4543 { &hf_report_addr_enc_dr,
4544 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4545 TFS (&addr_enc), 0x20, NULL, HFILL } },
4546 { &hf_report_del_time,
4547 { "Delivery Time", "dmp.delivery_time", FT_UINT8, BASE_HEX,
4548 NULL, 0x0, NULL, HFILL } },
4549 { &hf_report_del_time_val,
4550 { "Delivery Time Value", "dmp.delivery_time_val", FT_UINT8,
4551 BASE_HEX, NULL, 0x0, NULL, HFILL } },
4552 { &hf_report_addr_enc_ndr,
4553 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4554 TFS (&addr_enc), 0x40, NULL, HFILL } },
4555 { &hf_report_reason,
4556 { "Reason (P1)", "dmp.report_reason", FT_UINT8, BASE_DEC,
4557 VALS (p1_NonDeliveryReasonCode_vals), 0x3F,
4558 NULL, HFILL } },
4559 { &hf_report_info_present_ndr,
4560 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4561 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4562 { &hf_report_diagn,
4563 { "Diagnostic (P1)", "dmp.report_diagnostic", FT_UINT8, BASE_DEC,
4564 VALS (p1_NonDeliveryDiagnosticCode_vals), 0x7F,
4565 NULL, HFILL } },
4566 { &hf_report_suppl_info_len,
4567 { "Supplementary Information", "dmp.suppl_info_len", FT_UINT8,
4568 BASE_DEC, NULL, 0x0, "Supplementary Information Length", HFILL } },
4569 { &hf_report_suppl_info,
4570 { "Supplementary Information", "dmp.suppl_info", FT_STRINGZ,
4571 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4574 ** Notification
4576 { &hf_receipt_notif,
4577 { "Receipt Notification (RN)", "dmp.rn", FT_NONE, BASE_NONE,
4578 NULL, 0x0, NULL, HFILL} },
4579 { &hf_non_receipt_notif,
4580 { "Non-Receipt Notification (NRN)", "dmp.nrn", FT_NONE, BASE_NONE,
4581 NULL, 0x0, NULL, HFILL} },
4582 { &hf_other_notif,
4583 { "Other Notification (ON)", "dmp.on", FT_NONE, BASE_NONE,
4584 NULL, 0x0, NULL, HFILL} },
4586 { &hf_notif_type,
4587 { "Notification Type", "dmp.notif_type", FT_UINT8, BASE_DEC,
4588 VALS (notif_type), 0x03, NULL, HFILL } },
4589 { &hf_notif_rec_time,
4590 { "Receipt Time", "dmp.receipt_time", FT_UINT8, BASE_HEX,
4591 NULL, 0x0, NULL, HFILL } },
4592 { &hf_notif_rec_time_val,
4593 { "Receipt Time Value", "dmp.receipt_time_val", FT_UINT8,
4594 BASE_HEX, NULL, 0x0, NULL, HFILL } },
4595 { &hf_notif_suppl_info_len,
4596 { "Supplementary Information", "dmp.suppl_info_len",
4597 FT_UINT8, BASE_DEC, NULL, 0x0, "Supplementary Information Length",
4598 HFILL } },
4599 { &hf_notif_suppl_info,
4600 { "Supplementary Information", "dmp.suppl_info",
4601 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL,
4602 HFILL } },
4603 { &hf_notif_non_rec_reason,
4604 { "Non-Receipt Reason", "dmp.notif_non_rec_reason",
4605 FT_UINT8, BASE_DEC, VALS (p22_NonReceiptReasonField_vals), 0x0,
4606 NULL, HFILL } },
4607 { &hf_notif_discard_reason,
4608 { "Discard Reason", "dmp.notif_discard_reason", FT_UINT8,
4609 BASE_DEC, VALS (p22_DiscardReasonField_vals), 0x0,
4610 NULL, HFILL } },
4611 { &hf_notif_on_type,
4612 { "ON Type", "dmp.notif_on_type", FT_UINT8, BASE_DEC,
4613 VALS (on_type), 0x0, NULL, HFILL } },
4614 { &hf_notif_acp127,
4615 { "ACP127 Recipient", "dmp.acp127recip_len", FT_UINT8,
4616 BASE_DEC, NULL, 0x0, "ACP 127 Recipient Length", HFILL } },
4617 { &hf_notif_acp127recip,
4618 { "ACP127 Recipient", "dmp.acp127recip", FT_STRINGZ,
4619 BASE_NONE, NULL, 0x0, "ACP 127 Recipient", HFILL } },
4622 ** Acknowledgement
4624 { &hf_ack,
4625 { "Acknowledgement", "dmp.ack", FT_NONE, BASE_NONE,
4626 NULL, 0x0, NULL, HFILL } },
4627 { &hf_ack_reason,
4628 { "Ack Reason", "dmp.ack_reason", FT_UINT8, BASE_DEC,
4629 VALS (ack_reason), 0x0, NULL, HFILL } },
4630 { &hf_ack_diagnostic,
4631 { "Ack Diagnostic", "dmp.ack_diagnostic", FT_UINT8, BASE_DEC,
4632 NULL, 0x0, NULL, HFILL } },
4633 { &hf_ack_recips,
4634 { "Recipient List", "dmp.ack_rec_list", FT_NONE, BASE_NONE,
4635 NULL, 0x0, NULL, HFILL } },
4638 ** Checksum
4640 { &hf_checksum,
4641 { "Checksum", "dmp.checksum", FT_UINT16, BASE_HEX,
4642 NULL, 0x0, NULL, HFILL } },
4643 { &hf_checksum_status,
4644 { "Checksum Status", "dmp.checksum.status", FT_UINT8, BASE_NONE,
4645 VALS(proto_checksum_vals), 0x0, NULL, HFILL } },
4648 ** Ack matching / Resend
4650 { &hf_analysis_ack_time,
4651 { "Acknowledgement Time", "dmp.analysis.ack_time", FT_RELATIVE_TIME, BASE_NONE,
4652 NULL, 0x0, "The time between the Message and the Acknowledge", HFILL } },
4653 { &hf_analysis_rep_time,
4654 { "Report Reply Time", "dmp.analysis.report_time", FT_RELATIVE_TIME, BASE_NONE,
4655 NULL, 0x0, "The time between the Message and the Report", HFILL } },
4656 { &hf_analysis_not_time,
4657 { "Notification Reply Time", "dmp.analysis.notif_time", FT_RELATIVE_TIME, BASE_NONE,
4658 NULL, 0x0, "The time between the Message and the Notification", HFILL } },
4659 { &hf_analysis_total_time,
4660 { "Total Time", "dmp.analysis.total_time", FT_RELATIVE_TIME, BASE_NONE,
4661 NULL, 0x0, "The time between the first Message and the Acknowledge", HFILL } },
4662 { &hf_analysis_retrans_time,
4663 { "Retransmission Time", "dmp.analysis.retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4664 NULL, 0x0, "The time between the last Message and this Message", HFILL } },
4665 { &hf_analysis_total_retrans_time,
4666 { "Total Retransmission Time", "dmp.analysis.total_retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4667 NULL, 0x0, "The time between the first Message and this Message", HFILL } },
4668 { &hf_analysis_msg_num,
4669 { "Message in", "dmp.analysis.msg_in", FT_FRAMENUM, BASE_NONE,
4670 NULL, 0x0, "This packet has a Message in this frame", HFILL } },
4671 { &hf_analysis_acks_msg_num,
4672 { "This is an Ack to the Message in", "dmp.analysis.acks_msg_in", FT_FRAMENUM, BASE_NONE,
4673 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Message in this frame", HFILL } },
4674 { &hf_analysis_ack_num,
4675 { "Acknowledgement in", "dmp.analysis.ack_in", FT_FRAMENUM, BASE_NONE,
4676 NULL, 0x0, "This packet has an Acknowledgement in this frame", HFILL } },
4677 { &hf_analysis_acks_rep_num,
4678 { "This is an Ack to the Report in", "dmp.analysis.acks_report_in", FT_FRAMENUM, BASE_NONE,
4679 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Report in this frame", HFILL } },
4680 #if 0
4681 { &hf_analysis_rep_num,
4682 { "Report in", "dmp.analysis.report_in", FT_FRAMENUM, BASE_NONE,
4683 NULL, 0x0, "This packet has a Report in this frame", HFILL } },
4684 { &hf_analysis_not_num,
4685 { "Notification in", "dmp.analysis.notif_in", FT_FRAMENUM, BASE_NONE,
4686 NULL, 0x0, "This packet has a Notification in this frame", HFILL } },
4687 #endif
4688 { &hf_analysis_acks_not_num,
4689 { "This is an Ack to the Notification in", "dmp.analysis.acks_notif_in", FT_FRAMENUM, BASE_NONE,
4690 FRAMENUM_TYPE(FT_FRAMENUM_ACK), 0x0, "This packet ACKs a Notification in this frame", HFILL } },
4691 { &hf_analysis_ack_missing,
4692 { "Acknowledgement missing", "dmp.analysis.ack_missing", FT_NONE, BASE_NONE,
4693 NULL, 0x0, "The acknowledgement for this packet is missing", HFILL } },
4694 { &hf_analysis_retrans_no,
4695 { "Retransmission #", "dmp.analysis.retrans_no", FT_UINT32, BASE_DEC,
4696 NULL, 0x0, "Retransmission count", HFILL } },
4697 { &hf_analysis_ack_dup_no,
4698 { "Duplicate ACK #", "dmp.analysis.dup_ack_no", FT_UINT32, BASE_DEC,
4699 NULL, 0x0, "Duplicate Acknowledgement count", HFILL } },
4700 { &hf_analysis_msg_resend_from,
4701 { "Retransmission of Message sent in", "dmp.analysis.msg_first_sent_in",
4702 FT_FRAMENUM, BASE_NONE,
4703 NULL, 0x0, "This Message was first sent in this frame", HFILL } },
4704 { &hf_analysis_rep_resend_from,
4705 { "Retransmission of Report sent in", "dmp.analysis.report_first_sent_in",
4706 FT_FRAMENUM, BASE_NONE,
4707 NULL, 0x0, "This Report was first sent in this frame", HFILL } },
4708 { &hf_analysis_not_resend_from,
4709 { "Retransmission of Notification sent in", "dmp.analysis.notif_first_sent_in",
4710 FT_FRAMENUM, BASE_NONE,
4711 NULL, 0x0, "This Notification was first sent in this frame", HFILL } },
4712 { &hf_analysis_ack_resend_from,
4713 { "Retransmission of Acknowledgement sent in", "dmp.analysis.ack_first_sent_in",
4714 FT_FRAMENUM, BASE_NONE,
4715 NULL, 0x0, "This Acknowledgement was first sent in this frame", HFILL } },
4718 ** Reserved values
4720 { &hf_reserved_0x01,
4721 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4722 NULL, 0x01, NULL, HFILL } },
4723 { &hf_reserved_0x02,
4724 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4725 NULL, 0x02, NULL, HFILL } },
4726 { &hf_reserved_0x04,
4727 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4728 NULL, 0x04, NULL, HFILL } },
4729 { &hf_reserved_0x07,
4730 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4731 NULL, 0x07, NULL, HFILL } },
4732 { &hf_reserved_0x08,
4733 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4734 NULL, 0x08, NULL, HFILL } },
4735 { &hf_reserved_0x0F,
4736 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4737 NULL, 0x0F, NULL, HFILL } },
4738 { &hf_reserved_0x1F,
4739 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4740 NULL, 0x1F, NULL, HFILL } },
4741 { &hf_reserved_0x20,
4742 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4743 NULL, 0x20, NULL, HFILL } },
4744 { &hf_reserved_0x40,
4745 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4746 NULL, 0x40, NULL, HFILL } },
4747 { &hf_reserved_0xC0,
4748 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4749 NULL, 0xC0, NULL, HFILL } },
4750 { &hf_reserved_0xE0,
4751 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4752 NULL, 0xE0, NULL, HFILL } },
4753 { &hf_reserved_0x8000,
4754 { "Reserved", "dmp.reserved", FT_UINT16, BASE_DEC,
4755 NULL, 0x8000, NULL, HFILL } },
4758 static int *ett[] = {
4759 &ett_dmp,
4760 &ett_envelope,
4761 &ett_envelope_version,
4762 &ett_envelope_hop_count,
4763 &ett_envelope_rec_present,
4764 &ett_envelope_addr_enc,
4765 &ett_envelope_checksum,
4766 &ett_envelope_extensions,
4767 &ett_envelope_msg_id_type,
4768 &ett_envelope_msg_id,
4769 &ett_envelope_mts_id_length,
4770 &ett_envelope_ipm_id_length,
4771 &ett_envelope_cont_type,
4772 &ett_envelope_subm_time,
4773 &ett_envelope_time_diff,
4774 &ett_envelope_flags,
4775 &ett_envelope_recipients,
4776 &ett_envelope_ext_recipients,
4777 &ett_envelope_addresses,
4778 &ett_address,
4779 &ett_address_direct,
4780 &ett_address_rec_no,
4781 &ett_address_extended,
4782 &ett_address_ext_form,
4783 &ett_address_ext_rec_no,
4784 &ett_address_ext_action,
4785 &ett_address_ext_rep_req,
4786 &ett_address_ext_not_req,
4787 &ett_address_ext_type,
4788 &ett_address_ext_length,
4789 &ett_extensions,
4790 &ett_extension,
4791 &ett_extension_header,
4792 &ett_content,
4793 &ett_message,
4794 &ett_message_st_type,
4795 &ett_message_reserved,
4796 &ett_message_precedence,
4797 &ett_message_importance,
4798 &ett_message_body_format,
4799 &ett_message_sec_class,
4800 &ett_message_sec_pol,
4801 &ett_message_sec_cat,
4802 &ett_message_heading_flags,
4803 &ett_message_exp_time,
4804 &ett_message_dtg,
4805 &ett_message_sic,
4806 &ett_message_sic_key,
4807 &ett_message_sic_bitmap,
4808 &ett_message_sic_bits,
4809 &ett_message_eit,
4810 &ett_message_compr,
4811 &ett_message_body_reserved,
4812 &ett_message_body,
4813 &ett_report,
4814 &ett_report_type,
4815 &ett_report_info_present_dr,
4816 &ett_report_info_present_ndr,
4817 &ett_report_addr_enc_dr,
4818 &ett_report_addr_enc_ndr,
4819 &ett_report_reserved,
4820 &ett_report_del_time,
4821 &ett_report_reason,
4822 &ett_report_suppl_info,
4823 &ett_report_diagn,
4824 &ett_notif,
4825 &ett_notif_type,
4826 &ett_notif_rec_time,
4827 &ett_notif_suppl_info,
4828 &ett_notif_acp127recip,
4829 &ett_ack,
4830 &ett_ack_recips,
4831 &ett_analysis
4834 static ei_register_info ei[] = {
4835 { &ei_reserved_value,
4836 { "dmp.reserved.expert", PI_UNDECODED, PI_WARN,
4837 "Reserved value", EXPFILL } },
4838 { &ei_message_sic_illegal,
4839 { "dmp.sic.illegal", PI_UNDECODED, PI_NOTE,
4840 "Illegal SIC", EXPFILL } },
4841 { &ei_analysis_ack_unexpected,
4842 { "dmp.analysis.ack_unexpected", PI_SEQUENCE, PI_NOTE,
4843 "Unexpected ACK", EXPFILL } },
4844 { &ei_analysis_ack_missing,
4845 { "dmp.analysis.ack_missing.expert", PI_SEQUENCE, PI_NOTE,
4846 "Acknowledgement missing", EXPFILL } },
4847 { &ei_analysis_msg_missing,
4848 { "dmp.analysis.msg_missing", PI_SEQUENCE, PI_NOTE,
4849 "Message missing", EXPFILL } },
4850 { &ei_analysis_retrans_no,
4851 { "dmp.analysis.retrans_no.expert", PI_SEQUENCE, PI_NOTE,
4852 "Retransmission #", EXPFILL } },
4853 { &ei_analysis_ack_dup_no,
4854 { "dmp.analysis.dup_ack_no.expert", PI_SEQUENCE, PI_NOTE,
4855 "Dup ACK #", EXPFILL } },
4856 { &ei_addr_dir_rec_no_generated,
4857 { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN,
4858 "Recipient number too big", EXPFILL } },
4859 { &ei_addr_ext_rec_no_generated,
4860 { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN,
4861 "Recipient number too big", EXPFILL } },
4862 { &ei_ack_reason,
4863 { "dmp.ack_reason.expert", PI_RESPONSE_CODE, PI_NOTE,
4864 "ACK reason", EXPFILL } },
4865 { &ei_envelope_version_value,
4866 { "dmp.version_value.unsupported", PI_UNDECODED, PI_ERROR,
4867 "Unsupported DMP Version", EXPFILL } },
4868 { &ei_envelope_msg_id,
4869 { "dmp.msg_id.short_id", PI_PROTOCOL, PI_NOTE,
4870 "Id < 4096 - should use ShortId", EXPFILL } },
4871 { &ei_7bit_string_unused_bits,
4872 { "dmp.7bit_string.unused_bits", PI_PROTOCOL, PI_WARN,
4873 "Unused bits in last byte shall be null", EXPFILL } },
4874 { &ei_message_compr,
4875 { "dmp.body.compression.unknown", PI_UNDECODED, PI_WARN,
4876 "Unknown compression algorithm", EXPFILL } },
4877 { &ei_message_body_uncompress,
4878 { "dmp.body.uncompress.fail", PI_UNDECODED, PI_WARN,
4879 "Error: Unable to uncompress content", EXPFILL } },
4880 { &ei_checksum_bad,
4881 { "dmp.checksum_bad.expert", PI_CHECKSUM, PI_WARN,
4882 "Bad checksum", EXPFILL } },
4883 { &ei_too_many_sec_cat,
4884 { "dmp.too_many_security_categories", PI_PROTOCOL, PI_ERROR,
4885 "Too many security categories", EXPFILL } },
4888 static uat_field_t attributes_flds[] = {
4889 UAT_FLD_VS(dmp_security_class,nation, "Nation", nat_pol_id, 0),
4890 UAT_FLD_DEC(dmp_security_class,sec_class, "Classification", "Security Classification"),
4891 UAT_FLD_CSTRING(dmp_security_class,name, "Name", "Classification Name"),
4892 UAT_END_FIELDS
4895 uat_t *attributes_uat = uat_new("DMP Security Classifications",
4896 sizeof(dmp_security_class_t),
4897 "dmp_security_classifications",
4898 true,
4899 &dmp_security_classes,
4900 &num_dmp_security_classes,
4901 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4902 "ChDMPSecurityClassifications",
4903 dmp_class_copy_cb,
4904 NULL,
4905 dmp_class_free_cb,
4906 NULL,
4907 NULL,
4908 attributes_flds);
4910 module_t *dmp_module;
4911 expert_module_t* expert_dmp;
4913 proto_dmp = proto_register_protocol (PNAME, PSNAME, PFNAME);
4915 dmp_handle = register_dissector(PFNAME, dissect_dmp, proto_dmp);
4917 proto_register_field_array (proto_dmp, hf, array_length (hf));
4918 proto_register_subtree_array (ett, array_length (ett));
4919 expert_dmp = expert_register_protocol(proto_dmp);
4920 expert_register_field_array(expert_dmp, ei, array_length(ei));
4922 dmp_id_hash_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), dmp_id_hash, dmp_id_hash_equal);
4923 dmp_long_id_hash_table = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
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,
4938 false);
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,
4945 false);
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",
4951 attributes_uat);
4952 prefs_register_bool_preference (dmp_module, "seq_ack_analysis",
4953 "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)",
4961 &dmp_align);
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);
4975 * Editor modelines
4977 * Local Variables:
4978 * c-basic-offset: 2
4979 * tab-width: 8
4980 * indent-tabs-mode: nil
4981 * End:
4983 * ex: set shiftwidth=2 tabstop=8 expandtab:
4984 * :indentSize=2:tabSize=8:noTabs=true: