MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-dmp.c
blob4b7dd7402721cdf21abc2b1e6f95455b37e6c465
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 * $Id$
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 * Ref: http://jcs.dtic.mil/j6/cceb/acps/acp123/
34 * TODO:
35 * - Dissect extended Restrictive security categories
36 * - Add Transmission/Retransmission statistics
39 #include "config.h"
41 #include <string.h>
42 #include <math.h>
44 #include <epan/packet.h>
45 #include <epan/address.h>
46 #include <epan/addr_resolv.h>
47 #include <epan/to_str.h>
48 #include <epan/prefs.h>
49 #include <epan/wmem/wmem.h>
50 #include <epan/expert.h>
51 #include <epan/crc16-tvb.h>
52 #include <epan/asn1.h>
53 #include <epan/strutil.h>
54 #include <epan/uat.h>
56 #include "packet-p1.h"
57 #include "packet-p22.h"
59 #define PNAME "Direct Message Profile"
60 #define PSNAME "DMP"
61 #define PFNAME "dmp"
63 /* Default UDP Port Number */
64 #define DEFAULT_DMP_PORT_RANGE "5031"
66 /* Protocol Identifier */
67 #define PROT_NAT 0x0D
68 #define PROT_DMP 0x1D
70 /* Versions supported */
71 #define DMP_VERSION_1 1
72 #define DMP_VERSION_2 2
74 /* Message Type (dmp.msg_type) */
75 #define STANAG 0x0
76 #define IPM 0x1
77 #define REPORT 0x2
78 #define NOTIF 0x3
79 #define ACK 0x4
81 /* Message Identifier Type (dmp.msg_id_type) */
82 #define ONLY_DMP_ID 0x0
83 #define X400_MSG_ID 0x1
84 #define NAT_MSG_ID 0x2
86 /* Report Type (dmp.report_type) */
87 #define DR 0x0
88 #define NDR 0x1
90 /* Notification Type (dmp.notif_type) */
91 #define RN 0x0
92 #define NRN 0x1
93 #define ON 0x2
95 /* Address Encoding (dmp.addr_enc) */
96 #define DIRECT_ADDR 0x0
97 #define EXTENDED_ADDR 0x1
99 /* Address type (internal values) */
100 #define ORIGINATOR 1
101 #define P1_ADDRESS 2
102 #define P2_ADDRESS 3
103 #define ORIG_P2_ADDRESS 4
105 /* Extended Address Form (dmp_addr_form) */
106 #define P1_DIRECT 0x0
107 #define P2_DIRECT 0x1
108 #define P1_EXTENDED 0x2
109 #define P2_EXTENDED 0x3
110 #define P1_P2_DIRECT 0x4
111 #define P1_DIRECT_P2_EXTENDED 0x5
112 #define P1_EXTENDED_P2_DIRECT 0x6
113 #define P1_P2_EXTENDED 0x7
115 /* Extended Address Type */
116 #define ASN1_BER 0x0
117 #define ASN1_PER 0x1
119 /* Security Policy (dmp_sec_pol) */
120 #define NATO 0x4
121 #define NATIONAL 0x5
122 #define EXTENDED_NATIONAL 0x6
123 #define EXTENDED_MISSION 0x7
125 #define SEC_CAT_EXT_NONE 0x0
126 #define SEC_CAT_EXT_PERMISSIVE 0x1
127 #define SEC_CAT_EXT_RESTRICTIVE 0x2
129 /* Body Format (dmp.body_format) */
130 #define FREE_TEXT 0x0
131 #define FREE_TEXT_SUBJECT 0x1
132 #define STRUCTURED 0x2
134 /* Encoded Information Types */
135 #define EIT_BILATERAL 0x3
137 /* Compression Algorithm */
138 #define ALGORITHM_NONE 0x0
139 #define ALGORITHM_ZLIB 0x1
141 /* Type of structured id to print */
142 #define STRUCT_ID_NONE 0
143 #define STRUCT_ID_UINT8 1
144 #define STRUCT_ID_UINT16 2
145 #define STRUCT_ID_UINT32 3
146 #define STRUCT_ID_UINT64 4
147 #define STRUCT_ID_STRING 5
148 #define STRUCT_ID_ZSTRING 6
150 #define NAT_DECODE_NONE 0
151 #define NAT_DECODE_DMP 1
152 #define NAT_DECODE_THALES 2
154 #define IPM_MODIFIER_X400 0
156 /* Internal values for not present and reserved time values */
157 #define DMP_TIME_NOT_PRESENT -1
158 #define DMP_TIME_RESERVED -2
160 #define ILLEGAL_FORMAT "<Illegal format>"
162 /* Maximum lengths */
163 #define MAX_SIC_LEN 30
165 void proto_reg_handoff_dmp (void);
167 static int proto_dmp = -1;
169 static int hf_dmp_id = -1;
170 static int hf_mts_id = -1;
171 static int hf_ipm_id = -1;
173 static int hf_envelope = -1;
174 static int hf_envelope_protocol_id = -1;
175 static int hf_envelope_version = -1;
176 static int hf_envelope_version_value = -1;
177 static int hf_envelope_hop_count = -1;
178 static int hf_envelope_hop_count_value = -1;
179 static int hf_envelope_rec_present = -1;
180 static int hf_envelope_addr_enc = -1;
181 static int hf_envelope_checksum = -1;
182 static int hf_envelope_extensions = -1;
183 static int hf_envelope_msg_id_type = -1;
184 static int hf_envelope_msg_id_length = -1;
185 static int hf_envelope_mts_id_length = -1;
186 static int hf_envelope_ipm_id_modifier = -1;
187 static int hf_envelope_ipm_id_length = -1;
188 static int hf_envelope_mts_id = -1;
189 static int hf_envelope_ipm_id = -1;
190 static int hf_envelope_type = -1;
191 static int hf_envelope_msg_id = -1;
192 static int hf_envelope_msg_id_12bit = -1;
193 static int hf_envelope_subm_time = -1;
194 static int hf_envelope_subm_time_value = -1;
195 static int hf_envelope_time_diff_present = -1;
196 static int hf_envelope_time_diff = -1;
197 static int hf_envelope_time_diff_value = -1;
198 static int hf_envelope_flags = -1;
199 static int hf_envelope_content_id_discarded = -1;
200 static int hf_envelope_recip_reassign_prohib = -1;
201 static int hf_envelope_dl_expansion_prohib = -1;
202 static int hf_envelope_recipients = -1;
203 static int hf_envelope_ext_recipients = -1;
205 static int hf_thales_ipm_id_modifier = -1;
207 static int hf_extensions = -1;
208 static int hf_extension = -1;
209 static int hf_extension_header = -1;
210 static int hf_extension_more = -1;
211 static int hf_extension_length = -1;
212 static int hf_extension_data = -1;
214 static int hf_message_content = -1;
215 static int hf_report_content = -1;
216 static int hf_notif_content = -1;
218 static int hf_addr_recipient = -1;
219 static int hf_addr_originator = -1;
220 static int hf_addr_reporting_name = -1;
221 static int hf_addr_dl_expanded = -1;
222 static int hf_addr_int_rec = -1;
223 static int hf_addr_dir_addr_ext = -1;
224 static int hf_addr_dir_rec_no = -1;
225 static int hf_addr_dir_rec_no1 = -1;
226 static int hf_addr_dir_rec_no2 = -1;
227 static int hf_addr_dir_rec_no3 = -1;
228 static int hf_addr_dir_rec_no_generated = -1;
229 static int hf_addr_dir_rep_req1 = -1;
230 static int hf_addr_dir_rep_req2 = -1;
231 static int hf_addr_dir_rep_req3 = -1;
232 static int hf_addr_dir_not_req1 = -1;
233 static int hf_addr_dir_not_req2 = -1;
234 static int hf_addr_dir_not_req3 = -1;
235 static int hf_addr_dir_action = -1;
236 static int hf_addr_dir_address = -1;
237 static int hf_addr_dir_address1 = -1;
238 static int hf_addr_dir_address2 = -1;
239 static int hf_addr_dir_address3 = -1;
240 static int hf_addr_dir_address_generated = -1;
242 static int hf_addr_ext_form = -1;
243 static int hf_addr_ext_form_orig_v1 = -1;
244 static int hf_addr_ext_form_orig = -1;
245 static int hf_addr_ext_action = -1;
246 static int hf_addr_ext_rep_req = -1;
247 static int hf_addr_ext_not_req = -1;
248 static int hf_addr_ext_rec_ext = -1;
249 static int hf_addr_ext_rec_no = -1;
250 static int hf_addr_ext_rec_no1 = -1;
251 static int hf_addr_ext_rec_no2 = -1;
252 static int hf_addr_ext_rec_no_generated = -1;
253 static int hf_addr_ext_address = -1;
254 static int hf_addr_ext_type = -1;
255 static int hf_addr_ext_type_ext = -1;
256 static int hf_addr_ext_length = -1;
257 static int hf_addr_ext_length1 = -1;
258 static int hf_addr_ext_length2 = -1;
259 static int hf_addr_ext_length_generated = -1;
260 static int hf_addr_ext_asn1_ber = -1;
261 static int hf_addr_ext_asn1_per = -1;
262 static int hf_addr_ext_unknown = -1;
264 static int hf_message_body = -1;
265 static int hf_message_st_type = -1;
266 static int hf_message_precedence = -1;
267 static int hf_message_importance = -1;
268 static int hf_message_body_format = -1;
269 static int hf_message_sec_class_val = -1;
270 static int hf_message_sec_pol = -1;
271 static int hf_message_heading_flags = -1;
272 static int hf_message_auth_users = -1;
273 static int hf_message_subject_disc = -1;
274 static int hf_message_national_policy_id = -1;
275 static int hf_message_mission_policy_id = -1;
276 static int hf_message_sec_label = -1;
277 static int hf_message_sec_cat_nat = -1;
278 static int hf_message_sec_cat_val = -1;
279 static int hf_message_sec_cat_cl = -1;
280 static int hf_message_sec_cat_cs = -1;
281 static int hf_message_sec_cat_ex = -1;
282 static int hf_message_sec_cat_ne = -1;
283 static int hf_message_sec_cat_permissive = -1;
284 static int hf_message_sec_cat_country_code = -1;
285 static int hf_message_sec_cat_restrictive = -1;
286 static int hf_message_sec_cat_extended = -1;
287 static int hf_message_sec_cat_bit0 = -1;
288 static int hf_message_sec_cat_bit1 = -1;
289 static int hf_message_sec_cat_bit2 = -1;
290 static int hf_message_sec_cat_bit3 = -1;
291 static int hf_message_sec_cat_bit4 = -1;
292 static int hf_message_sec_cat_bit5 = -1;
293 static int hf_message_sec_cat_bit6 = -1;
294 static int hf_message_sec_cat_bit7 = -1;
295 static int hf_message_exp_time = -1;
296 static int hf_message_exp_time_val = -1;
297 static int hf_message_dtg = -1;
298 static int hf_message_dtg_sign = -1;
299 static int hf_message_dtg_val = -1;
300 static int hf_message_sic = -1;
301 static int hf_message_sic_key = -1;
302 static int hf_message_sic_key_values = -1;
303 static int hf_message_sic_key_type = -1;
304 static int hf_message_sic_key_chars = -1;
305 static int hf_message_sic_key_num = -1;
306 static int hf_message_sic_bitmap = -1;
307 static int hf_message_sic_bits = -1;
308 static int hf_message_sic_bits_any = -1;
309 static int hf_message_subj_id = -1;
310 static int hf_message_subj_mts_id = -1;
311 static int hf_message_subj_ipm_id = -1;
313 static int hf_message_subject = -1;
314 static int hf_message_eit = -1;
315 static int hf_message_compr = -1;
316 static int hf_message_body_data = -1;
317 static int hf_message_body_plain = -1;
318 static int hf_message_bodyid_uint8 = -1;
319 static int hf_message_bodyid_uint16 = -1;
320 static int hf_message_bodyid_uint32 = -1;
321 static int hf_message_bodyid_uint64 = -1;
322 static int hf_message_bodyid_string = -1;
323 static int hf_message_bodyid_zstring = -1;
324 static int hf_message_body_structured = -1;
325 static int hf_message_body_uncompr = -1;
326 static int hf_message_body_uncompressed = -1;
328 static int hf_delivery_report = -1;
329 static int hf_non_delivery_report = -1;
330 static int hf_report_type = -1;
331 static int hf_report_info_present_dr = -1;
332 static int hf_report_addr_enc_dr = -1;
333 static int hf_report_del_time = -1;
334 static int hf_report_del_time_val = -1;
335 static int hf_report_addr_enc_ndr = -1;
336 static int hf_report_reason = -1;
337 static int hf_report_info_present_ndr = -1;
338 static int hf_report_diagn = -1;
339 static int hf_report_suppl_info_len = -1;
340 static int hf_report_suppl_info = -1;
342 static int hf_receipt_notif = -1;
343 static int hf_non_receipt_notif = -1;
344 static int hf_other_notif = -1;
345 static int hf_notif_type = -1;
346 static int hf_notif_rec_time = -1;
347 static int hf_notif_rec_time_val = -1;
348 static int hf_notif_suppl_info_len = -1;
349 static int hf_notif_suppl_info = -1;
350 static int hf_notif_non_rec_reason = -1;
351 static int hf_notif_discard_reason = -1;
352 static int hf_notif_on_type = -1;
353 static int hf_notif_acp127 = -1;
354 static int hf_notif_acp127recip = -1;
356 static int hf_ack = -1;
357 static int hf_ack_reason = -1;
358 static int hf_ack_diagnostic = -1;
359 static int hf_ack_recips = -1;
361 static int hf_checksum = -1;
362 static int hf_checksum_good = -1;
363 static int hf_checksum_bad = -1;
365 static int hf_analysis_ack_time = -1;
366 static int hf_analysis_total_time = -1;
367 static int hf_analysis_retrans_time = -1;
368 static int hf_analysis_total_retrans_time = -1;
369 static int hf_analysis_msg_num = -1;
370 static int hf_analysis_retrans_no = -1;
371 static int hf_analysis_ack_num = -1;
372 static int hf_analysis_ack_missing = -1;
373 static int hf_analysis_ack_dup_no = -1;
374 static int hf_analysis_rep_num = -1;
375 static int hf_analysis_rep_time = -1;
376 static int hf_analysis_not_num = -1;
377 static int hf_analysis_not_time = -1;
378 static int hf_analysis_msg_resend_from = -1;
379 static int hf_analysis_rep_resend_from = -1;
380 static int hf_analysis_not_resend_from = -1;
381 static int hf_analysis_ack_resend_from = -1;
383 static int hf_reserved_0x01 = -1;
384 static int hf_reserved_0x02 = -1;
385 static int hf_reserved_0x04 = -1;
386 static int hf_reserved_0x07 = -1;
387 static int hf_reserved_0x08 = -1;
388 static int hf_reserved_0x0F = -1;
389 static int hf_reserved_0x1F = -1;
390 static int hf_reserved_0x20 = -1;
391 static int hf_reserved_0x40 = -1;
392 static int hf_reserved_0xC0 = -1;
393 static int hf_reserved_0xE0 = -1;
394 static int hf_reserved_0x8000 = -1;
396 static gint ett_dmp = -1;
397 static gint ett_envelope = -1;
398 static gint ett_envelope_version = -1;
399 static gint ett_envelope_hop_count = -1;
400 static gint ett_envelope_rec_present = -1;
401 static gint ett_envelope_addr_enc = -1;
402 static gint ett_envelope_checksum = -1;
403 static gint ett_envelope_extensions = -1;
404 static gint ett_envelope_msg_id_type = -1;
405 static gint ett_envelope_msg_id = -1;
406 static gint ett_envelope_mts_id_length = -1;
407 static gint ett_envelope_ipm_id_length = -1;
408 static gint ett_envelope_cont_type = -1;
409 static gint ett_envelope_subm_time = -1;
410 static gint ett_envelope_time_diff = -1;
411 static gint ett_envelope_flags = -1;
412 static gint ett_envelope_recipients = -1;
413 static gint ett_envelope_ext_recipients = -1;
414 static gint ett_envelope_addresses = -1;
416 static gint ett_address = -1;
417 static gint ett_address_direct = -1;
418 static gint ett_address_rec_no = -1;
419 static gint ett_address_extended = -1;
420 static gint ett_address_ext_form = -1;
421 static gint ett_address_ext_rec_no = -1;
422 static gint ett_address_ext_action = -1;
423 static gint ett_address_ext_rep_req = -1;
424 static gint ett_address_ext_not_req = -1;
425 static gint ett_address_ext_type = -1;
426 static gint ett_address_ext_length = -1;
428 static gint ett_extensions = -1;
429 static gint ett_extension = -1;
430 static gint ett_extension_header = -1;
432 static gint ett_content = -1;
434 static gint ett_message = -1;
435 static gint ett_message_st_type = -1;
436 static gint ett_message_reserved = -1;
437 static gint ett_message_precedence = -1;
438 static gint ett_message_importance = -1;
439 static gint ett_message_body_format = -1;
440 static gint ett_message_sec_class = -1;
441 static gint ett_message_sec_pol = -1;
442 static gint ett_message_sec_cat = -1;
443 static gint ett_message_heading_flags = -1;
444 static gint ett_message_exp_time = -1;
445 static gint ett_message_dtg = -1;
446 static gint ett_message_sic = -1;
447 static gint ett_message_sic_key = -1;
448 static gint ett_message_sic_bitmap = -1;
449 static gint ett_message_sic_bits = -1;
450 static gint ett_message_eit = -1;
451 static gint ett_message_compr = -1;
452 static gint ett_message_body_reserved = -1;
453 static gint ett_message_body = -1;
454 static gint ett_message_body_uncompr = -1;
456 static gint ett_report = -1;
457 static gint ett_report_type = -1;
458 static gint ett_report_info_present_dr = -1;
459 static gint ett_report_info_present_ndr = -1;
460 static gint ett_report_addr_enc_dr = -1;
461 static gint ett_report_addr_enc_ndr = -1;
462 static gint ett_report_reserved = -1;
463 static gint ett_report_del_time = -1;
464 static gint ett_report_reason = -1;
465 static gint ett_report_suppl_info = -1;
466 static gint ett_report_diagn = -1;
468 static gint ett_notif = -1;
469 static gint ett_notif_type = -1;
470 static gint ett_notif_rec_time = -1;
471 static gint ett_notif_suppl_info = -1;
472 static gint ett_notif_acp127recip = -1;
474 static gint ett_ack = -1;
475 static gint ett_ack_recips = -1;
477 static gint ett_checksum = -1;
479 static gint ett_analysis = -1;
481 static expert_field ei_reserved_value = EI_INIT;
482 static expert_field ei_message_sic_illegal = EI_INIT;
483 static expert_field ei_envelope_version_value = EI_INIT;
484 static expert_field ei_message_compr = EI_INIT;
485 static expert_field ei_ack_reason = EI_INIT;
486 static expert_field ei_addr_dir_rec_no_generated = EI_INIT;
487 static expert_field ei_checksum_bad = EI_INIT;
488 static expert_field ei_message_body_uncompressed = EI_INIT;
489 static expert_field ei_addr_ext_rec_no_generated = EI_INIT;
490 static expert_field ei_envelope_msg_id = EI_INIT;
491 static expert_field ei_analysis_ack_missing = EI_INIT;
492 static expert_field ei_analysis_ack_dup_no = EI_INIT;
493 static expert_field ei_analysis_ack_unexpected = EI_INIT;
494 static expert_field ei_analysis_msg_missing = EI_INIT;
495 static expert_field ei_analysis_retrans_no = EI_INIT;
497 static dissector_handle_t dmp_handle;
499 typedef struct _dmp_id_key {
500 guint id;
501 address src;
502 address dst;
503 } dmp_id_key;
505 typedef struct _dmp_id_val {
506 gint msg_type; /* Message type */
507 guint prev_msg_id; /* Previous message package num */
508 guint msg_id; /* Message package num */
509 guint ack_id; /* Acknowledgement package num */
510 guint rep_id; /* Report package num */
511 guint not_id; /* Notification package num */
512 nstime_t msg_time; /* Message receive time */
513 nstime_t first_msg_time; /* First message receive time */
514 nstime_t prev_msg_time; /* Previous message receive time */
515 nstime_t rep_not_msg_time; /* Report or Notification time */
516 guint32 msg_resend_count; /* Message resend counter */
517 guint32 ack_resend_count; /* Acknowledgement resend counter */
518 } dmp_id_val;
520 static GHashTable *dmp_id_hash_table = NULL;
521 static GHashTable *dmp_long_id_hash_table = NULL;
523 /* Global values used in several functions */
524 static struct dmp_data {
525 gint version;
526 gint prot_id;
527 gint addr_enc;
528 gint checksum;
529 gint msg_type;
530 gint st_type;
531 gint prec;
532 gint body_format;
533 gint notif_type;
534 guchar *struct_id;
535 gint32 subm_time;
536 guint8 msg_id_type;
537 guint8 mts_id_length;
538 proto_item *mts_id_item;
539 guint8 ack_reason;
540 guint16 msg_id;
541 guint16 subj_id;
542 gboolean extensions;
543 gboolean dr;
544 gboolean ndr;
545 gboolean notif_req;
546 gboolean ack_rec_present;
547 dmp_id_val *id_val;
548 } dmp;
550 /* User definable values */
551 static range_t *global_dmp_port_range;
552 static gint dmp_nat_decode = NAT_DECODE_DMP;
553 static gint dmp_local_nation = 0;
554 static gboolean use_seq_ack_analysis = TRUE;
555 static gboolean dmp_align = FALSE;
556 static gboolean dmp_subject_as_id = FALSE;
557 static gint dmp_struct_format = STRUCT_ID_NONE;
558 static guint dmp_struct_offset = 0;
559 static guint dmp_struct_length = 1;
561 typedef struct _dmp_security_class_t {
562 guint nation;
563 guint sec_class;
564 char *name;
565 } dmp_security_class_t;
567 static dmp_security_class_t *dmp_security_classes;
568 static guint num_dmp_security_classes;
570 static const true_false_string addr_enc = {
571 "Use Extended Encoding", "Use Direct Encoding"
574 static const true_false_string dtg_sign = {
575 "Future", "Past"
578 static const true_false_string report_type = {
579 "Non-Delivery Report", "Delivery Report"
582 static const value_string version_vals[] = {
583 { 0x0, "1" },
584 { 0x1, "2" },
585 { 0x2, "Unknown" },
586 { 0x3, "Unknown" },
587 { 0x4, "Unknown" },
588 { 0x5, "Unknown" },
589 { 0x6, "Unknown" },
590 { 0x7, "Unknown" },
591 { 0, NULL } };
593 static const value_string type_vals[] = {
594 { 0x0, "Message" },
595 { 0x1, "Message (E-Mail)" },
596 { 0x2, "Report" },
597 { 0x3, "Notification" },
598 { 0x4, "Acknowledgement" },
599 { 0x5, "Unknown Content" },
600 { 0x6, "Unknown Content" },
601 { 0x7, "Unknown Content" },
602 { 0, NULL } };
604 static const value_string msg_id_type_vals[] = {
605 { 0x0, "DMP Identifiers only" },
606 { 0x1, "X.400 Message Identifiers" },
607 { 0x2, "Nationally-defined" },
608 { 0x3, "Reserved" },
609 { 0, NULL } };
611 static const value_string msg_id_length_vals[] = {
612 { 0x0, "Full (16 bits)" },
613 { 0x1, "Short (12 bits)" },
614 { 0, NULL } };
616 static const value_string report_vals[] = {
617 { 0x0, "No Report" },
618 { 0x1, "Non-Delivery Report" },
619 { 0x2, "Delivery Report" },
620 { 0x3, "Reserved" },
621 { 0, NULL } };
623 static const value_string report_vals_ext[] = {
624 { 0x0, "No Report" },
625 { 0x1, "Non-Delivery Report" },
626 { 0x2, "Delivery Report" },
627 { 0x3, "Recipient Number Extended" },
628 { 0, NULL } };
630 /* Note the space in front of these values */
631 static const value_string report_vals_short[] = {
632 { 0x1, " NDR" },
633 { 0x2, " DR" },
634 { 0, NULL } };
636 static const value_string notif_vals[] = {
637 { 0x0, "No Notification" },
638 { 0x1, "Non-Receipt Notification" },
639 { 0x2, "Receipt Notification" },
640 { 0x3, "Reserved" },
641 { 0, NULL } };
643 static const value_string notif_vals_ext[] = {
644 { 0x0, "No Notification" },
645 { 0x1, "Non-Receipt Notification" },
646 { 0x2, "Receipt Notification" },
647 { 0x3, "Direct Address Extended" },
648 { 0, NULL } };
650 /* Note the space in front of these values */
651 static const value_string notif_vals_short[] = {
652 { 0x1, " NRN" },
653 { 0x2, " RN" },
654 { 0, NULL } };
656 static const value_string notif_type [] = {
657 { 0x0, "Receipt Notification (RN)" },
658 { 0x1, "Non-Receipt Notification (NRN)" },
659 { 0x2, "Other Notification (ON)" },
660 { 0x3, "Unknown Notification" },
661 { 0, NULL } };
663 /* Note the space behind these values */
664 static const value_string addr_type_str [] = {
665 { ORIGINATOR, "" },
666 { P1_ADDRESS, "P1 " },
667 { P2_ADDRESS, "P22/P772 " },
668 { ORIG_P2_ADDRESS, "P22 " },
669 { 0, NULL } };
671 static const value_string addr_form [] = {
672 { 0x0, "P1 Direct" },
673 { 0x1, "P22/P772 Direct" },
674 { 0x2, "P1 Extended" },
675 { 0x3, "P22/P772 Extended" },
676 { 0x4, "P1 and P22/P772 Direct" },
677 { 0x5, "P1 Direct and P22/P772 Extended" },
678 { 0x6, "P1 Extended and P22/P772 Direct" },
679 { 0x7, "P1 and P22/P772 Extended" },
680 { 0, NULL } };
682 static const value_string addr_form_orig_v1 [] = {
683 { 0x0, "Direct" },
684 { 0x1, "Reserved" },
685 { 0x2, "Extended" },
686 { 0x3, "Reserved" },
687 { 0x4, "Reserved" },
688 { 0x5, "Reserved" },
689 { 0x6, "Reserved" },
690 { 0x7, "Reserved" },
691 { 0, NULL } };
693 static const value_string addr_form_orig [] = {
694 { 0x0, "Direct" },
695 { 0x1, "Reserved" },
696 { 0x2, "Extended" },
697 { 0x3, "Reserved" },
698 { 0x4, "Originator and P2 Direct" },
699 { 0x5, "Originator Direct and P2 Extended" },
700 { 0x6, "Originator Extended and P2 Direct" },
701 { 0x7, "Originator and P2 Extended" },
702 { 0, NULL } };
704 static const value_string ext_addr_type [] = {
705 { 0x0, "ASN.1 BER-encoded OR-name" },
706 { 0x1, "ASN.1 PER-encoded OR-name" },
707 { 0x2, "Reserved" },
708 { 0x3, "Reserved" },
709 { 0x4, "Reserved" },
710 { 0x5, "Reserved" },
711 { 0x6, "Reserved" },
712 { 0x7, "Address Length Extended" },
713 { 0, NULL } };
715 static const value_string ext_addr_type_ext [] = {
716 { 0x0, "ASN.1 BER-encoded OR-name" },
717 { 0x1, "ASN.1 PER-encoded OR-name" },
718 { 0x2, "Reserved" },
719 { 0x3, "Reserved" },
720 { 0x4, "Reserved" },
721 { 0x5, "Reserved" },
722 { 0x6, "Reserved" },
723 { 0x7, "Reserved" },
724 { 0, NULL } };
726 static const value_string ext_addr_type_short [] = {
727 { 0x0, "OR-name (BER)" },
728 { 0x1, "OR-name (PER)" },
729 { 0x2, "Reserved" },
730 { 0x3, "Reserved" },
731 { 0x4, "Reserved" },
732 { 0x5, "Reserved" },
733 { 0x6, "Reserved" },
734 { 0x7, "Reserved" },
735 { 0, NULL } };
737 static const value_string message_type_vals[] = {
738 { 0x0, "Operation" },
739 { 0x1, "Project" },
740 { 0x2, "Exercise" },
741 { 0x3, "Drill" },
742 { 0, NULL } };
744 static const value_string precedence[] = {
745 { 0x0, "Deferred" },
746 { 0x1, "Routine" },
747 { 0x2, "Priority" },
748 { 0x3, "Immediate" },
749 { 0x4, "Flash" },
750 { 0x5, "Override" },
751 { 0x6, "Priority, Info Precedence: Routine" },
752 { 0x7, "Immediate, Info Precedence: Routine" },
753 { 0, NULL } };
755 static const value_string importance[] = {
756 { 0x0, "Low" },
757 { 0x1, "Reserved" },
758 { 0x2, "Normal" },
759 { 0x3, "Reserved" },
760 { 0x4, "High" },
761 { 0x5, "Reserved" },
762 { 0x6, "Reserved" },
763 { 0x7, "Reserved" },
764 { 0, NULL } };
766 static const value_string sec_class[] = {
767 { 0x0, "Unmarked" },
768 { 0x1, "Unclassified" },
769 /* { 0x2, "Reserved" }, */
770 { 0x3, "Restricted" },
771 /* { 0x4, "Reserved" }, */
772 { 0x5, "Confidential" },
773 { 0x6, "Secret" },
774 { 0x7, "Top secret" },
775 { 0, NULL } };
777 static const value_string sec_pol[] = {
778 { 0x0, "Network defined" },
779 { 0x1, "Network defined" },
780 { 0x2, "Network defined" },
781 { 0x3, "Network defined" },
782 { 0x4, "NATO" },
783 { 0x5, "National (nation of local server)" },
784 { 0x6, "Extended, National" },
785 { 0x7, "Extended, Mission Defined" },
786 { 0, NULL } };
788 #define MAX_NATIONAL_VALUES 56
789 /* Will be built in build_national_strings() */
790 static value_string nat_pol_id[MAX_NATIONAL_VALUES+1];
792 /* For name we use the ISO 3166-1 Alfa-3 value for the country,
793 * for description we use the Country Name and
794 * for value we use the DMP value for National Policy Identifier.
796 static const enum_val_t dmp_national_values[MAX_NATIONAL_VALUES+1] = {
797 { "???", "None", 0x00 },
798 { "alb", "Albania", 0x1B },
799 { "arm", "Armenia", 0x20 },
800 { "aut", "Austria", 0x21 },
801 { "aze", "Azerbaijan", 0x22 },
802 { "blr", "Belarus", 0x23 },
803 { "bel", "Belgium", 0x01 },
804 { "bih", "Bosnia and Hercegowina", 0x24 },
805 { "bgr", "Bulgaria", 0x02 },
806 { "can", "Canada", 0x03 },
807 { "hrv", "Croatia", 0x1C },
808 { "cze", "Czech Republic", 0x04 },
809 { "dnk", "Denmark", 0x05 },
810 { "est", "Estonia", 0x06 },
811 { "eapc", "Euro-Atlantic Partnership Council (EAPC)", 0x3A },
812 { "eu", "European Union (EU)", 0x3B },
813 { "fin", "Finland", 0x25 },
814 { "mkd", "Former Yugoslav Republic of Macedonia", 0x26 },
815 { "fra", "France", 0x07 },
816 { "geo", "Georgia", 0x27 },
817 { "deu", "Germany", 0x08 },
818 { "grc", "Greece", 0x09 },
819 { "hun", "Hungary", 0x0A },
820 { "isl", "Iceland", 0x0B },
821 { "isaf", "International Security Assistance Force (ISAF)", 0x3C },
822 { "irl", "Ireland", 0x28 },
823 { "ita", "Italy", 0x0C },
824 { "kaz", "Kazakhstan", 0x29 },
825 { "kgz", "Kyrgyztan", 0x2A },
826 { "lva", "Latvia", 0x0D },
827 { "ltu", "Lithuania", 0x0E },
828 { "lux", "Luxembourg", 0x0F },
829 { "mlt", "Malta", 0x2B },
830 { "mda", "Moldova", 0x2C },
831 { "mne", "Montenegro", 0x2D },
832 { "nld", "Netherlands", 0x10 },
833 { "nor", "Norway", 0x11 },
834 { "pfp", "Partnership for Peace (PfP)", 0x3D },
835 { "pol", "Poland", 0x12 },
836 { "ptr", "Portugal", 0x13 },
837 { "rou", "Romania", 0x14 },
838 { "rus", "Russian Federation", 0x2E },
839 { "srb", "Serbia", 0x2F },
840 { "svk", "Slovakia", 0x15 },
841 { "svn", "Slovenia", 0x16 },
842 { "esp", "Spain", 0x17 },
843 { "swe", "Sweden", 0x30 },
844 { "che", "Switzerland", 0x31 },
845 { "tjk", "Tajikistan", 0x32 },
846 { "tur", "Turkey", 0x18 },
847 { "tkm", "Turkmenistan", 0x33 },
848 { "gbr", "United Kingdom", 0x19 },
849 { "usa", "United States", 0x1A },
850 { "ukr", "Ukraine", 0x34 },
851 { "uzb", "Uzbekistan", 0x35 },
852 { "weu", "Western European Union (WEU)", 0x3E },
853 { NULL, NULL, 0 }
856 static const value_string ext_sec_cat[] = {
857 { 0x0, "Not present" },
858 { 0x1, "Permissive category follows" },
859 { 0x2, "Restrictive category follows" },
860 { 0x3, "Reserved" },
861 { 0, NULL } };
863 static const value_string sic_key_type[] = {
864 { 0xc, "2 or more 3-character SICs" },
865 { 0xd, "1 or more 3-to-8 character SICs" },
866 { 0, NULL } };
868 static const true_false_string sic_key_chars = {
869 "Any", "[A-Z0-9] only"
872 static const value_string sic_key_num[] = {
873 { 0, "1" },
874 { 1, "2" },
875 { 2, "3" },
876 { 3, "4" },
877 { 4, "5" },
878 { 5, "6" },
879 { 6, "7" },
880 { 7, "8" },
881 { 0, NULL } };
884 static const value_string sic_bit_vals[] = {
885 { 0, "length:6, bytes:4" },
886 { 1, "length:6, bytes:4" },
887 { 2, "length:6, bytes:4" },
888 { 3, "length:6, bytes:4" },
889 { 4, "length:6, bytes:4" },
890 { 5, "length:6, bytes:4" },
891 { 6, "length:6, bytes:4" },
892 { 7, "length:6, bytes:4" },
893 { 8, "length:6, bytes:4" },
894 { 9, "reserved" },
895 { 10, "length:5, bytes:4" },
896 { 11, "length:8, bytes:6" },
897 { 12, "length:4, bytes:3" },
898 { 13, "length:4, bytes:3" },
899 { 14, "length:7, bytes:5" },
900 { 15, "length:7, bytes:5" },
901 { 0, NULL } };
903 static const value_string sic_bit_any_vals[] = {
904 { 0, "length:5, bytes:4" },
905 { 1, "length:5, bytes:4" },
906 { 2, "length:5, bytes:4" },
907 { 3, "length:5, bytes:4" },
908 { 4, "length:5, bytes:4" },
909 { 5, "length:5, bytes:4" },
910 { 6, "length:5, bytes:4" },
911 { 7, "length:5, bytes:4" },
912 { 8, "length:5, bytes:4" },
913 { 9, "length:8, bytes:7" },
914 { 10, "length:4, bytes:4" },
915 { 11, "length:7, bytes:6" },
916 { 12, "length:6, bytes:5" },
917 { 13, "length:6, bytes:5" },
918 { 14, "length:6, bytes:5" },
919 { 15, "length:6, bytes:5" },
920 { 0, NULL } };
922 static const value_string body_format_vals[] = {
923 { 0x0, "Free text" },
924 { 0x1, "Free text including subject" },
925 { 0x2, "Structured" },
926 { 0x3, "Reserved" },
927 { 0, NULL } };
929 static const value_string eit_vals[] = {
930 { 0x0, "Empty" },
931 { 0x1, "IA5-text" },
932 { 0x2, "General text" },
933 { 0x3, "Bilaterally defined (binary data)" },
934 { 0x4, "AdatP-3" },
935 { 0x5, "Reserved" },
936 { 0x6, "Reserved" },
937 { 0x7, "Reserved" },
938 { 0, NULL } };
940 static const value_string compression_vals[] = {
941 { 0x0, "No compression" },
942 { 0x1, "ZLib compressed" },
943 { 0x2, "Reserved" },
944 { 0x3, "Reserved" },
945 { 0, NULL } };
947 static const value_string ack_reason [] = {
948 { 0x00, "Successful, positive acknowledgement" },
949 { 0x01, "Unspecified error" },
950 { 0x02, "Checksum incorrect" },
951 { 0, NULL } };
953 static const value_string non_del_reason [] = {
954 { 0x3D, "Unknown reason" },
955 { 0x3E, "Reason code greater than 0x3c (60)" },
956 { 0x3F, "Reserved" },
957 { 0, NULL } };
959 static const value_string non_del_diagn [] = {
960 { 0x7C, "Diagnostic not specified" },
961 { 0x7D, "Unknown diagnostic" },
962 { 0x7E, "Diagnostic code greater than 0x7b (123)" },
963 { 0x7F, "Reserved" },
964 { 0, NULL } };
966 static const value_string discard_reason [] = {
967 { 0xFE, "Discard Reason absent" },
968 { 0xFF, "Reserved" },
969 { 0, NULL } };
971 static const value_string on_type [] = {
972 { 0x00, "acp127-nn" },
973 { 0x01, "acp127-pn" },
974 { 0x02, "acp127-tn" },
975 { 0, NULL } };
977 static const value_string ack_msg_type [] = {
978 { STANAG, " (message)" },
979 { IPM, " (e-mail)" },
980 { REPORT, " (report)" },
981 { NOTIF, " (notif)" },
982 { ACK, " (ack)" },
983 { 0, NULL } };
985 static const enum_val_t struct_id_options[] = {
986 { "none", "None", STRUCT_ID_NONE },
987 { "1byte", "1 Byte value", STRUCT_ID_UINT8 },
988 { "2byte", "2 Byte value", STRUCT_ID_UINT16 },
989 { "4byte", "4 Byte value", STRUCT_ID_UINT32 },
990 { "8byte", "8 Byte value", STRUCT_ID_UINT64 },
991 { "fstring", "Fixed text string", STRUCT_ID_STRING },
992 { "zstring", "Zero terminated text string", STRUCT_ID_ZSTRING },
993 { NULL, NULL, 0 }
996 static const enum_val_t national_decoding[] = {
997 { "none", "None (raw data)", NAT_DECODE_NONE },
998 { "dmp", "As for regular", NAT_DECODE_DMP },
999 { "thales", "Thales XOmail", NAT_DECODE_THALES },
1000 { NULL, NULL, 0 }
1003 static const value_string ipm_id_modifier[] = {
1004 { 0x0, "X.400 IPM Identifier" },
1005 { 0x1, "Nationally-defined" },
1006 { 0x2, "Nationally-defined" },
1007 { 0x3, "Nationally-defined" },
1008 { 0, NULL }
1011 static const value_string thales_ipm_id_modifier[] = {
1012 { 0x0, "X.400 IPM Identifier" },
1013 { 0x1, "3 or 5 digits" },
1014 { 0x2, "4 digits" },
1015 { 0x3, "5 digits" },
1016 { 0, NULL }
1019 UAT_VS_DEF(dmp_security_class, nation, dmp_security_class_t, guint, 0, "None")
1020 UAT_DEC_CB_DEF(dmp_security_class, sec_class, dmp_security_class_t)
1021 UAT_CSTRING_CB_DEF(dmp_security_class, name, dmp_security_class_t)
1023 static void *
1024 dmp_class_copy_cb(void *dest, const void *orig, size_t len _U_)
1026 dmp_security_class_t *u = (dmp_security_class_t *)dest;
1027 const dmp_security_class_t *o = (const dmp_security_class_t *)orig;
1029 u->nation = o->nation;
1030 u->sec_class = o->sec_class;
1031 u->name = g_strdup(o->name);
1033 return dest;
1036 static void
1037 dmp_class_free_cb(void *r)
1039 dmp_security_class_t *u = (dmp_security_class_t *)r;
1041 g_free(u->name);
1044 static gchar *dmp_national_sec_class (guint nation, guint dmp_sec_class)
1046 guint i;
1048 for (i = 0; i < num_dmp_security_classes; i++) {
1049 dmp_security_class_t *u = &(dmp_security_classes[i]);
1051 if (u->nation == nation && u->sec_class == dmp_sec_class) {
1052 return u->name;
1056 return NULL;
1059 static void build_national_strings (void)
1061 gint i = 0;
1064 ** We use values from dmp_national_values to build value_string for nat_pol_id.
1066 while (dmp_national_values[i].name && i < MAX_NATIONAL_VALUES) {
1067 nat_pol_id[i].value = dmp_national_values[i].value;
1068 nat_pol_id[i].strptr = dmp_national_values[i].description;
1069 i++;
1071 nat_pol_id[i].value = 0;
1072 nat_pol_id[i].strptr = NULL;
1075 static const gchar *get_nat_pol_id_short (gint nation)
1077 gint i = 0;
1078 while (dmp_national_values[i].name) {
1079 if (dmp_national_values[i].value == nation) {
1080 return dmp_national_values[i].name;
1082 i++;
1085 return "???";
1088 static const gchar *msg_type_to_str (void)
1090 const gchar *msg_type;
1091 gboolean have_msg = FALSE;
1093 switch (dmp.msg_type) {
1095 case STANAG:
1096 /* Include message type and precedence */
1097 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s (%s) [%s]",
1098 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1099 val_to_str_const (dmp.st_type, message_type_vals, "Unknown"),
1100 (dmp.prec == 0x6 || dmp.prec == 0x7) ?
1101 val_to_str_const (dmp.prec-4, precedence, "Unknown") :
1102 val_to_str_const (dmp.prec, precedence, "Unknown"));
1103 break;
1105 case IPM:
1106 /* Include importance */
1107 msg_type = wmem_strdup_printf (wmem_packet_scope(), "%s [%s]",
1108 val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
1109 val_to_str_const (dmp.prec, importance, "Unknown"));
1110 break;
1112 case REPORT:
1113 /* Include report types included */
1114 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Report (%s%s%s)",
1115 dmp.dr ? "DR" : "", (dmp.dr && dmp.ndr) ? " and " : "",
1116 dmp.ndr ? "NDR" : "");
1117 break;
1119 case NOTIF:
1120 msg_type = val_to_str_const (dmp.notif_type, notif_type, "Unknown");
1121 break;
1123 case ACK:
1124 /* If we have msg_time we have a matching packet */
1125 have_msg = (dmp.id_val &&
1126 (dmp.id_val->msg_time.secs>0 || dmp.id_val->msg_time.nsecs>0));
1127 msg_type = wmem_strdup_printf (wmem_packet_scope(), "Acknowledgement%s%s",
1128 have_msg ? val_to_str (dmp.id_val->msg_type, ack_msg_type,
1129 " (unknown:%d)") : "",
1130 dmp.ack_reason ? " [negative]" : "");
1131 break;
1133 default:
1134 msg_type = "Unknown";
1135 break;
1138 return msg_type;
1141 static const gchar *non_del_reason_str (guint32 value)
1143 if (value < 0x3D) {
1144 /* Standard values according to P1 */
1145 return val_to_str_const (value, p1_NonDeliveryReasonCode_vals, "Unknown");
1146 } else {
1147 return val_to_str_const (value, non_del_reason, "Unknown");
1151 static const gchar *non_del_diagn_str (guint32 value)
1153 if (value < 0x7C) {
1154 /* Standard values according to P1 */
1155 return val_to_str_const (value, p1_NonDeliveryDiagnosticCode_vals, "Unknown");
1156 } else {
1157 return val_to_str_const (value, non_del_diagn, "Unknown");
1161 static const gchar *nrn_reason_str (guint32 value)
1163 /* Standard values according to P22 */
1164 return val_to_str_const (value, p22_NonReceiptReasonField_vals, "Reserved");
1167 static const gchar *discard_reason_str (guint32 value)
1169 if (value < 0xFE) {
1170 /* Standard values according to P22 */
1171 return val_to_str_const (value, p22_DiscardReasonField_vals, "Reserved");
1172 } else {
1173 return val_to_str_const (value, discard_reason, "Unknown");
1177 /* Ref chapter 6.2.8.10 TimeDifference */
1178 static gint32 dmp_dec_time_diff (guint8 dmp_time_diff)
1180 gint32 time_diff = 0;
1182 if (dmp_time_diff <= 0x01) {
1183 /* Reserved - low value */
1184 time_diff = DMP_TIME_RESERVED;
1185 } else if (dmp_time_diff <= 0x1D) {
1186 /* Number of 2-second units (2-58 seconds) */
1187 time_diff = dmp_time_diff * 2;
1188 } else if (dmp_time_diff <= 0x91) {
1189 /* Number of 15-second units (1 min - 29 min 45 sec) */
1190 time_diff = (dmp_time_diff - 0x1D + 3) * 15;
1191 } else if (dmp_time_diff <= 0xDF) {
1192 /* Number of 5-minute units (30 min - 6 hours 55 min) */
1193 time_diff = (dmp_time_diff - 0x91 + 5) * 5*60;
1194 } else if (dmp_time_diff <= 0xF7) {
1195 /* Number of 30-minute units (7 hours - 18 hours 30 min) */
1196 time_diff = (dmp_time_diff - 0xDF + 7) * 30*60;
1197 } else {
1198 /* Reserved - high value */
1199 time_diff = DMP_TIME_RESERVED;
1202 return time_diff;
1206 * Ref chapter 6.3.7.2.10 ExpiryTime
1207 * and chapter 6.3.9.2.2 DeliveryTime
1209 static gint32 dmp_dec_exp_del_time (guint8 timev, gboolean expiry_time)
1211 gint32 time_value = 0;
1213 if (expiry_time && (timev == 0x00)) {
1214 /* No expiry time */
1215 time_value = DMP_TIME_NOT_PRESENT;
1216 } else if (timev <= 0x1D) {
1217 /* Number of 2-second units (2-58 seconds) */
1218 time_value = timev * 2;
1219 } else if (timev <= 0x91) {
1220 /* Number of 15-second units (1 min - 29 min 45 sec) */
1221 time_value = (timev - 0x1D + 3) * 15;
1222 } else if (timev <= 0xBB) {
1223 /* Number of 5-minute units (30 min - 3 hours 55 min) */
1224 time_value = (timev - 0x91 + 5) * 5*60;
1225 } else if (timev <= 0xE3) {
1226 /* Number of 30-minute units (4 hours - 23 hours 30 min) */
1227 time_value = (timev - 0xBB + 7) * 30*60;
1228 } else if (timev < 0xFF) {
1229 /* Number of 2-hour units (24 - 78 hours) */
1230 time_value = (timev - 0xE3 + 11) * 2*3600;
1231 } else {
1232 /* Reserved */
1233 time_value = DMP_TIME_RESERVED;
1236 return time_value;
1239 static gint32 dmp_dec_exp_time (guint8 expiry_time)
1241 return dmp_dec_exp_del_time (expiry_time, TRUE);
1244 static gint32 dmp_dec_del_time (guint8 delivery_time)
1246 return dmp_dec_exp_del_time (delivery_time, FALSE);
1249 /* Ref chapter 6.3.7.2.11 DTG */
1250 static gint32 dmp_dec_dtg (guint32 dtg)
1252 gint32 value;
1254 if (dtg == 0x00) {
1255 /* Not present */
1256 value = DMP_TIME_NOT_PRESENT;
1257 } else if (dtg <= 0x3C) {
1258 /* Number of minutes (0-59 min) */
1259 value = (dtg - 1) * 60;
1260 } else if (dtg <= 0x64) {
1261 /* Number of 15-minute units (1 hour - 10 hours 45 min) */
1262 value = (dtg - 0x3C + 3) * 15 * 60;
1263 } else if (dtg < 0x7F) {
1264 /* Number of hours (11-36 hours) */
1265 value = (dtg - 0x64 + 10) * 3600;
1266 } else {
1267 /* Reserved */
1268 value = DMP_TIME_RESERVED;
1271 return value;
1275 * Ref chapter 7.10.11.1 Submission time
1277 * start_time (current time)
1278 * delta1 = E (encoded submission time)
1279 * delta2 = C (encoded current time)
1280 * 0x01C2 = Pn + 15min (maximum point for S1)
1281 * 0x7E38 = Pn+1 - 15min (minimum point for S3)
1282 * 0x7FF8 = Pn+1 (length of P (period))
1284 static gint32 dmp_dec_subm_time (guint16 delta1, gint32 start_time)
1286 gint32 subm_time = start_time;
1287 guint16 delta2;
1289 delta2 = (guint16) ((subm_time / 2) % 0x7FF8);
1291 if ((delta1 < 0x01C2) && (delta2 >= delta1 + 0x7E38)) {
1292 subm_time += 2 * (0x7FF8 - delta2 + delta1);
1293 } else if ((delta1 >= 0x01C2) && (delta2 < delta1 - 0x01C2)) {
1294 subm_time -= 2 * (0x7FF8 - delta1 + delta2);
1295 } else {
1296 subm_time -= 2 * (delta2 - delta1);
1299 return subm_time;
1302 /* Ref chapter 6.3.7.2.12 SIC */
1303 static gboolean dmp_dec_xbyte_sic (guint64 bin, gchar *sic,
1304 guint8 no_char, gboolean any)
1306 gboolean failure = FALSE;
1307 gdouble multiplier;
1308 guint8 i;
1309 guint64 p, tmp;
1311 if (no_char >= MAX_SIC_LEN) {
1312 /* Illegal length */
1313 g_snprintf (sic, MAX_SIC_LEN, "Illegal length: %d", no_char);
1314 return TRUE;
1317 if (any) {
1318 multiplier = 74.0;
1319 } else {
1320 multiplier = 36.0;
1323 for (i = 0; i < no_char; i++) {
1324 p = (guint64) pow (multiplier, no_char - 1 - i);
1325 tmp = bin / p;
1326 bin -= tmp * p;
1327 sic[i] = (gchar) tmp;
1328 if (sic[i] <= 9) {
1329 sic[i] += '0';
1330 } else if (sic[i] <= 35) {
1331 sic[i] += ('A' - 10);
1332 } else if (!any) {
1333 sic[i] = '*';
1334 failure = TRUE;
1335 } else if (sic[i] <= 61) {
1336 sic[i] += ('a' - 36);
1337 } else if (sic[i] == 62) {
1338 sic[i] = '\'';
1339 } else if (sic[i] == 63) {
1340 sic[i] = '(';
1341 } else if (sic[i] == 64) {
1342 sic[i] = ')';
1343 } else if (sic[i] == 65) {
1344 sic[i] = '+';
1345 } else if (sic[i] == 66) {
1346 sic[i] = ',';
1347 } else if (sic[i] == 67) {
1348 sic[i] = '-';
1349 } else if (sic[i] == 68) {
1350 sic[i] = '.';
1351 } else if (sic[i] == 69) {
1352 sic[i] = '/';
1353 } else if (sic[i] == 70) {
1354 sic[i] = ':';
1355 } else if (sic[i] == 71) {
1356 sic[i] = '=';
1357 } else if (sic[i] == 72) {
1358 sic[i] = '?';
1359 } else if (sic[i] == 73) {
1360 sic[i] = ' ';
1361 } else {
1362 sic[i] = '*';
1363 failure = TRUE;
1366 sic[i] = '\0';
1368 return failure;
1371 static guint dmp_id_hash (gconstpointer k)
1373 dmp_id_key *dmpx=(dmp_id_key *)k;
1374 return dmpx->id;
1377 static gint dmp_id_hash_equal (gconstpointer k1, gconstpointer k2)
1379 dmp_id_key *dmp1=(dmp_id_key *)k1;
1380 dmp_id_key *dmp2=(dmp_id_key *)k2;
1381 if (dmp1->id != dmp2->id)
1382 return 0;
1384 return (ADDRESSES_EQUAL (&dmp1->src, &dmp2->src) &&
1385 ADDRESSES_EQUAL (&dmp1->dst, &dmp2->dst));
1388 static void register_dmp_id (packet_info *pinfo, guint8 reason)
1390 dmp_id_val *dmp_data = NULL, *pkg_data = NULL;
1391 dmp_id_key *dmp_key = NULL;
1392 nstime_t msg_time;
1393 guint msg_id = 0;
1395 if (pinfo->flags.in_error_pkt) {
1396 /* No analysis of error packets */
1397 return;
1400 nstime_set_zero(&msg_time);
1402 dmp_key = wmem_new (wmem_file_scope(), dmp_id_key);
1404 if (!pinfo->fd->flags.visited &&
1405 (dmp.msg_type == REPORT || dmp.msg_type == NOTIF))
1407 /* Try to match corresponding message */
1408 dmp_key->id = (guint) dmp.subj_id;
1409 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
1410 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
1412 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1414 if (dmp_data) {
1415 /* Found message */
1416 if (dmp_data->prev_msg_id > 0) {
1417 msg_id = dmp_data->prev_msg_id;
1418 } else {
1419 msg_id = dmp_data->msg_id;
1421 msg_time = dmp_data->msg_time;
1425 if (dmp.msg_type == ACK) {
1426 dmp_key->id = (guint) dmp.subj_id;
1427 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
1428 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
1429 } else {
1430 dmp_key->id = (guint) dmp.msg_id;
1431 SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->src));
1432 SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->dst));
1435 dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
1437 if (!pinfo->fd->flags.visited) {
1438 if (dmp_data) {
1439 if (dmp.msg_type == ACK) {
1440 /* Only save this data if positive ack */
1441 if (reason == 0) {
1442 if (dmp_data->ack_id == 0) {
1443 /* Only save reference to first ACK */
1444 dmp_data->ack_id = pinfo->fd->num;
1445 } else {
1446 /* Only count when resending */
1447 dmp_data->ack_resend_count++;
1450 } else {
1451 /* Message resent */
1452 dmp_data->msg_resend_count++;
1453 dmp_data->prev_msg_id = pinfo->fd->num;
1454 dmp_data->prev_msg_time = dmp_data->msg_time;
1455 dmp_data->msg_time = pinfo->fd->abs_ts;
1457 } else {
1458 /* New message */
1459 dmp_data = wmem_new0 (wmem_file_scope(), dmp_id_val);
1460 dmp_data->msg_type = dmp.msg_type;
1462 if (dmp.msg_type == ACK) {
1463 /* No matching message for this ack */
1464 dmp_data->ack_id = pinfo->fd->num;
1465 } else {
1466 dmp_data->first_msg_time = pinfo->fd->abs_ts;
1467 dmp_data->msg_time = pinfo->fd->abs_ts;
1469 if (dmp.msg_type == REPORT) {
1470 dmp_data->rep_id = pinfo->fd->num;
1471 dmp_data->msg_id = msg_id;
1472 dmp_data->rep_not_msg_time = msg_time;
1473 } else if (dmp.msg_type == NOTIF) {
1474 dmp_data->not_id = pinfo->fd->num;
1475 dmp_data->msg_id = msg_id;
1476 dmp_data->rep_not_msg_time = msg_time;
1477 } else {
1478 dmp_data->msg_id = pinfo->fd->num;
1481 g_hash_table_insert (dmp_id_hash_table, dmp_key, dmp_data);
1485 pkg_data = wmem_new (wmem_file_scope(), dmp_id_val);
1486 *pkg_data = *dmp_data;
1487 p_add_proto_data (pinfo->fd, proto_dmp, 0, pkg_data);
1488 } else {
1489 /* Fetch last values from data saved in packet */
1490 pkg_data = (dmp_id_val *)p_get_proto_data (pinfo->fd, proto_dmp, 0);
1492 if (dmp_data && pkg_data && dmp.msg_type != ACK && pkg_data->ack_id == 0) {
1493 pkg_data->ack_id = dmp_data->ack_id;
1497 DISSECTOR_ASSERT (pkg_data);
1498 dmp.id_val = pkg_data;
1501 static void dmp_add_seq_ack_analysis (tvbuff_t *tvb, packet_info *pinfo,
1502 proto_tree *dmp_tree, gint offset)
1504 proto_tree *analysis_tree = NULL;
1505 proto_item *en = NULL, *eh = NULL;
1506 nstime_t ns;
1508 if (dmp.msg_type > ACK || (dmp.msg_type < ACK && !dmp.checksum) ||
1509 dmp.id_val == NULL || pinfo->flags.in_error_pkt)
1511 /* No need for seq/ack analysis */
1512 return;
1515 en = proto_tree_add_text (dmp_tree, tvb, 0, 0, "SEQ/ACK analysis");
1516 PROTO_ITEM_SET_GENERATED (en);
1517 analysis_tree = proto_item_add_subtree (en, ett_analysis);
1519 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
1520 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) {
1521 if (dmp.id_val->ack_id) {
1522 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb,
1523 0, 0, dmp.id_val->ack_id);
1524 PROTO_ITEM_SET_GENERATED (en);
1525 if (!dmp.checksum) {
1526 proto_item_append_text (en, " (unexpected)");
1527 expert_add_info(pinfo, en, &ei_analysis_ack_unexpected);
1529 } else if (dmp.checksum && !dmp.id_val->msg_resend_count) {
1530 en = proto_tree_add_item (analysis_tree, hf_analysis_ack_missing, tvb, offset, 0, ENC_NA);
1531 if (pinfo->fd->flags.visited) {
1532 /* We do not know this on first visit and we do not want to
1533 add a entry in the "Expert Severity Info" for this note */
1534 expert_add_info(pinfo, en, &ei_analysis_ack_missing);
1535 PROTO_ITEM_SET_GENERATED (en);
1539 if (dmp.msg_type == REPORT) {
1540 if (dmp.id_val->msg_id) {
1541 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1542 tvb, 0, 0, dmp.id_val->msg_id);
1543 PROTO_ITEM_SET_GENERATED (en);
1545 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
1546 en = proto_tree_add_time (analysis_tree, hf_analysis_rep_time,
1547 tvb, 0, 0, &ns);
1548 PROTO_ITEM_SET_GENERATED (en);
1549 } else {
1550 proto_tree_add_expert(analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1552 } else if (dmp.msg_type == NOTIF) {
1553 if (dmp.id_val->msg_id) {
1554 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1555 tvb, 0, 0, dmp.id_val->msg_id);
1556 PROTO_ITEM_SET_GENERATED (en);
1558 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
1559 en = proto_tree_add_time (analysis_tree, hf_analysis_not_time,
1560 tvb, 0, 0, &ns);
1561 PROTO_ITEM_SET_GENERATED (en);
1562 } else {
1563 proto_tree_add_expert(analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1567 if (dmp.id_val->msg_resend_count) {
1568 en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no,
1569 tvb, 0, 0, dmp.id_val->msg_resend_count);
1570 PROTO_ITEM_SET_GENERATED (en);
1572 expert_add_info_format(pinfo, en, &ei_analysis_retrans_no, "Retransmission #%d", dmp.id_val->msg_resend_count);
1574 if (dmp.msg_type == REPORT) {
1575 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_resend_from,
1576 tvb, 0, 0, dmp.id_val->rep_id);
1577 } else if (dmp.msg_type == NOTIF) {
1578 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_resend_from,
1579 tvb, 0, 0, dmp.id_val->not_id);
1580 } else {
1581 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_resend_from,
1582 tvb, 0, 0, dmp.id_val->msg_id);
1584 PROTO_ITEM_SET_GENERATED (en);
1586 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->prev_msg_time);
1587 en = proto_tree_add_time (analysis_tree, hf_analysis_retrans_time,
1588 tvb, 0, 0, &ns);
1589 PROTO_ITEM_SET_GENERATED (en);
1591 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
1592 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_retrans_time,
1593 tvb, 0, 0, &ns);
1594 PROTO_ITEM_SET_GENERATED (eh);
1596 if (dmp.id_val->first_msg_time.secs == dmp.id_val->prev_msg_time.secs &&
1597 dmp.id_val->first_msg_time.nsecs == dmp.id_val->prev_msg_time.nsecs) {
1598 /* Time values does not differ, hide the total time */
1599 PROTO_ITEM_SET_HIDDEN (eh);
1602 } else if (dmp.msg_type == ACK) {
1603 if (dmp.id_val->msg_type != ACK) {
1604 if (dmp.id_val->msg_type == REPORT) {
1605 en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_num,
1606 tvb, 0, 0, dmp.id_val->rep_id);
1607 } else if (dmp.id_val->msg_type == NOTIF) {
1608 en = proto_tree_add_uint (analysis_tree, hf_analysis_not_num,
1609 tvb, 0, 0, dmp.id_val->not_id);
1610 } else {
1611 en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
1612 tvb, 0, 0, dmp.id_val->msg_id);
1614 PROTO_ITEM_SET_GENERATED (en);
1616 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->msg_time);
1617 en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time,
1618 tvb, 0, 0, &ns);
1619 PROTO_ITEM_SET_GENERATED (en);
1621 nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
1622 eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time,
1623 tvb, 0, 0, &ns);
1624 PROTO_ITEM_SET_GENERATED (eh);
1626 if (dmp.id_val->first_msg_time.secs == dmp.id_val->msg_time.secs &&
1627 dmp.id_val->first_msg_time.nsecs == dmp.id_val->msg_time.nsecs) {
1628 /* Time values does not differ, hide the total time */
1629 PROTO_ITEM_SET_HIDDEN (eh);
1630 } else {
1631 /* Different times, add a reference to the message we have ack'ed */
1632 proto_item_append_text (en, " (from frame %d)",
1633 dmp.id_val->prev_msg_id);
1635 } else {
1636 proto_tree_add_expert(analysis_tree, pinfo, &ei_analysis_msg_missing, tvb, 0, 0);
1639 if (dmp.id_val->ack_resend_count) {
1640 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no,
1641 tvb, 0, 0, dmp.id_val->ack_resend_count);
1642 PROTO_ITEM_SET_GENERATED (en);
1644 expert_add_info_format(pinfo, en, &ei_analysis_ack_dup_no, "Dup ACK #%d", dmp.id_val->ack_resend_count);
1646 en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from,
1647 tvb, 0, 0, dmp.id_val->ack_id);
1648 PROTO_ITEM_SET_GENERATED (en);
1653 static gchar *dissect_7bit_string (tvbuff_t *tvb, gint offset, gint length)
1655 guchar *encoded = tvb_get_string (wmem_packet_scope(), tvb, offset, length);
1656 guchar *decoded = (guchar *)wmem_alloc0 (wmem_packet_scope(), (size_t)(length * 1.2) + 1);
1657 guchar rest = 0, bits = 1;
1658 gint len = 0, i;
1660 for (i = 0; i < length; i++) {
1661 decoded[len++] = encoded[i] >> bits | rest;
1662 rest = (encoded[i] << (7 - bits) & 0x7F);
1663 if (bits == 7) {
1664 decoded[len++] = rest;
1665 bits = 1;
1666 rest = 0;
1667 } else {
1668 bits++;
1672 return (gchar *) decoded;
1675 static const gchar *dissect_thales_mts_id (tvbuff_t *tvb, gint offset, gint length)
1677 /* Thales XOmail uses this format: "MTA-NAME/000000000000" */
1678 if (length >= 7 && length <= 22) {
1679 return wmem_strdup_printf (wmem_packet_scope(), "%s/%08X%04X",
1680 dissect_7bit_string (tvb, offset, length - 6),
1681 tvb_get_ntohl (tvb, offset + length - 6),
1682 tvb_get_ntohs (tvb, offset + length - 2));
1685 return ILLEGAL_FORMAT;
1688 static const gchar *dissect_thales_ipm_id (tvbuff_t *tvb, gint offset, gint length, gint modifier)
1690 /* Thales XOmail uses this format: "<prefix>0000 YYMMDDhhmmssZ" */
1691 if (length >= 6 && length <= 20 && modifier >= 0 && modifier <= 2) {
1692 guint number = tvb_get_ntohs (tvb, offset + length - 6);
1693 guint8 number_len = modifier + 2;
1694 time_t timev = tvb_get_ntohl(tvb, offset + length - 4);
1695 struct tm *tmp = gmtime(&timev);
1697 if (modifier == 1 && number >= 1024) {
1698 /* The number is in the range 65536-99999 */
1699 number_len = 5;
1700 number += (65536 - 1024);
1703 return wmem_strdup_printf (wmem_packet_scope(), "%s%0*d %02d%02d%02d%02d%02d%02dZ",
1704 (length == 6) ? "" : dissect_7bit_string (tvb, offset, length - 6),
1705 number_len, number,
1706 tmp->tm_year % 100, tmp->tm_mon + 1, tmp->tm_mday,
1707 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1710 return ILLEGAL_FORMAT;
1713 /* Ref chapter 6.3.7.2.12 SIC */
1714 static gint dissect_dmp_sic (tvbuff_t *tvb, packet_info *pinfo,
1715 proto_tree *message_tree, gint offset)
1717 proto_tree *sic_tree = NULL, *bitmap_tree = NULL, *key_tree = NULL;
1718 proto_item *sf = NULL, *bf = NULL, *kf = NULL;
1719 guint64 value;
1720 guint8 key, bitmap, no, i, length = 0;
1721 gboolean any, no_sic = FALSE, failure = FALSE;
1722 gint bytes = 0, boffset = offset;
1723 gchar *sic = NULL;
1725 key = tvb_get_guint8 (tvb, offset);
1726 sic = (gchar *)wmem_alloc (wmem_packet_scope(), MAX_SIC_LEN);
1728 if (key <= 0xB6) {
1729 /* 2 bytes, single 3-character SIC, characters [A-Z0-9] only */
1731 value = tvb_get_ntohs (tvb, offset);
1732 failure = dmp_dec_xbyte_sic (value, sic, 3, FALSE);
1733 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1734 offset, 2, sic,
1735 "%s [A-Z0-9 only]%s", sic,
1736 failure ? " (invalid)": "");
1737 if (failure) {
1738 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1740 offset += 2;
1742 } else if (key <= 0xBD) {
1743 /* 3 bytes, single 3-character SIC, any valid character */
1745 value = tvb_get_ntohl (tvb, offset);
1746 value = (value >> 8) & 0x48FFFF;
1747 failure = dmp_dec_xbyte_sic (value, sic, 3, TRUE);
1748 sf = proto_tree_add_string_format_value(message_tree, hf_message_sic, tvb,
1749 offset, 3, sic,
1750 "%s [any character]%s", sic,
1751 failure ? " (invalid)": "");
1752 if (failure) {
1753 expert_add_info(pinfo, sf, &ei_message_sic_illegal);
1755 offset += 3;
1757 } else if (key <= 0xBF) {
1758 /* Reserved (not used) */
1759 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1760 no_sic = TRUE;
1762 } else if (key <= 0xCF) {
1763 /* 2 or more 3-character SICs */
1765 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1766 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1768 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1769 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1771 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1772 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1773 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1774 offset += 1;
1776 any = (key & 0x08);
1777 no = (key & 0x07) + 1;
1778 for (i = 0; i < no; i++) {
1779 if (any) {
1780 value = tvb_get_ntohl (tvb, offset);
1781 value = (value >> 8) & 0x48FFFF;
1782 bytes = 3;
1783 } else {
1784 value = tvb_get_ntohs (tvb, offset);
1785 bytes = 2;
1787 failure = dmp_dec_xbyte_sic (value, sic, 3, any);
1788 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1789 offset, bytes, sic,
1790 "SIC %d: %s%s", i + 1, sic,
1791 failure ? " (invalid)": "");
1792 if (failure) {
1793 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1795 offset += bytes;
1797 proto_item_append_text (sf, ": %d (3 %s character)", no,
1798 any ? "any" : "[A-Z0-9]");
1800 } else if (key <= 0xDF) {
1801 /* 1 or more 3 to 8 character SICs */
1803 sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
1804 sic_tree = proto_item_add_subtree (sf, ett_message_sic);
1806 kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
1807 key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
1809 proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1810 proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
1811 proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
1812 offset += 1;
1814 bitmap = tvb_get_guint8 (tvb, offset);
1815 bf = proto_tree_add_uint_format (sic_tree, hf_message_sic_bitmap, tvb,
1816 offset, 1, bitmap,
1817 "Length Bitmap: 0x%2.2x", bitmap);
1818 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bitmap);
1819 proto_tree_add_item (bitmap_tree, hf_message_sic_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
1821 any = (key & 0x08);
1822 no = (key & 0x07) + 1;
1823 offset += 1;
1825 for (i = 0; i < no; i++) {
1826 if (bitmap & (1 << (7 - i))) {
1827 /* 4 - 8 character */
1828 key = tvb_get_guint8 (tvb, offset);
1829 if (any) {
1830 /* Any valid characters */
1831 if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1832 length = 4;
1833 bytes = 4;
1834 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1835 } else if ((key & 0xC0) == 0xC0) { /* bit 7-4: 11xx */
1836 length = 6;
1837 bytes = 5;
1838 value = ((guint64)key & 0x3F)<<32|tvb_get_ntohl (tvb, offset + 1);
1839 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1840 length = 7;
1841 bytes = 6;
1842 value = ((guint64)(tvb_get_ntohs (tvb, offset) & 0x0FFF)) << 32 |
1843 tvb_get_ntohl (tvb, offset + 2);
1844 } else if ((key & 0xF0) == 0x90) { /* bit 7-4: 1001 */
1845 length = 8;
1846 bytes = 7;
1847 value = ((guint64)((tvb_get_ntohl (tvb, offset)>>8) & 0x0FFF))<<32 |
1848 tvb_get_ntohl (tvb, offset + 3);
1849 } else { /* bit 7-4: 0xxx or 1000 */
1850 length = 5;
1851 bytes = 4;
1852 value = tvb_get_ntohl (tvb, offset);
1854 } else {
1855 /* Characterts [A-Z0-9] only */
1856 if ((key & 0xE0) == 0xC0) { /* bit 7-4: 110x */
1857 length = 4;
1858 bytes = 3;
1859 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x1FFFFF;
1860 } else if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
1861 length = 5;
1862 bytes = 4;
1863 value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
1864 } else if ((key & 0xE0) == 0xE0) { /* bit 7-4: 111x */
1865 length = 7;
1866 bytes = 5;
1867 value = ((guint64)key & 0x1F)<<32 | tvb_get_ntohl (tvb, offset +1);
1868 } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
1869 length = 8;
1870 bytes = 6;
1871 value = ((guint64)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
1872 tvb_get_ntohl (tvb, offset + 2);
1873 } else { /* bit 7-4: 0xxx or 1000 */
1874 length = 6;
1875 bytes = 4;
1876 value = tvb_get_ntohl (tvb, offset);
1879 } else {
1880 /* 3 character */
1881 if (any) {
1882 value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x48FFFF;
1883 length = 3;
1884 bytes = 3;
1885 } else {
1886 value = tvb_get_ntohs (tvb, offset);
1887 length = 3;
1888 bytes = 2;
1891 failure = dmp_dec_xbyte_sic (value, sic, length, any);
1892 bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
1893 offset, bytes, sic,
1894 "SIC %d: %s (%d bytes: %" G_GINT64_MODIFIER "x)%s",
1895 i + 1, sic, bytes, value,
1896 failure ? " (invalid)": "");
1897 if (bitmap & (1 << (7 - i))) {
1898 /* Only if 4 - 8 character */
1899 bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bits);
1900 if (any) {
1901 proto_tree_add_item (bitmap_tree, hf_message_sic_bits_any, tvb, offset, 1, ENC_BIG_ENDIAN);
1902 } else {
1903 proto_tree_add_item (bitmap_tree, hf_message_sic_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
1906 if (failure) {
1907 expert_add_info(pinfo, bf, &ei_message_sic_illegal);
1909 offset += bytes;
1911 proto_item_append_text (sf, ": %d (3-to-8 %s character)", no,
1912 any ? "any" : "[A-Z0-9]");
1914 } else if (key == 0xFE) {
1915 /* No SIC */
1916 g_snprintf (sic, MAX_SIC_LEN, "Not present");
1917 no_sic = TRUE;
1919 } else {
1920 /* Resered (not used) */
1921 g_snprintf (sic, MAX_SIC_LEN, "Reserved");
1922 no_sic = TRUE;
1925 if (no_sic) {
1926 /* Not added any SIC, dump text value */
1927 sf = proto_tree_add_string (message_tree, hf_message_sic, tvb, offset, 1, sic);
1928 offset += 1;
1931 proto_item_set_len (sf, offset - boffset);
1933 return offset;
1936 /* Ref chapter 5.2.7.1 Direct Originator Encoding */
1937 static gint dissect_dmp_direct_addr (tvbuff_t *tvb, packet_info *pinfo,
1938 proto_tree *field_tree, proto_item *tf,
1939 gint offset, gint rec_no,
1940 gint rec_ofs, gint addr_type)
1942 proto_tree *addr_tree = NULL;
1943 proto_item *en = NULL;
1944 gint dir_addr;
1945 guint8 value;
1947 value = tvb_get_guint8 (tvb, offset);
1948 dir_addr = (value & 0x7F);
1949 if (value & 0x80) {
1950 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1, tvb,
1951 offset, 1, value,
1952 "%sDirect Address (bits 6-0): %d",
1953 val_to_str_const (addr_type, addr_type_str, ""),
1954 value & 0x7F);
1955 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1956 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1957 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
1958 offset += 1;
1960 /* Extended 1 */
1961 value = tvb_get_guint8 (tvb, offset);
1962 dir_addr |= ((value & 0x3F) << 7);
1963 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
1964 offset, 1, value,
1965 "%sDirect Address (bits 12-7): %d",
1966 val_to_str_const (addr_type, addr_type_str, ""),
1967 value & 0x3F);
1968 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1969 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
1970 en = proto_tree_add_item (addr_tree, hf_reserved_0x40, tvb, offset, 1, ENC_BIG_ENDIAN);
1971 if (value & 0x40) {
1972 expert_add_info(pinfo, en, &ei_reserved_value);
1974 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
1975 offset += 1;
1977 if (value & 0x80) {
1978 /* Extended 2 */
1979 value = tvb_get_guint8 (tvb, offset);
1980 dir_addr |= ((value & 0x3F) << 13);
1981 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
1982 offset, 1, value,
1983 "%sDirect Address (bits 18-13): %d",
1984 val_to_str_const (addr_type,addr_type_str,""),
1985 value & 0x3F);
1986 addr_tree = proto_item_add_subtree (en, ett_address_direct);
1987 en = proto_tree_add_item (addr_tree, hf_reserved_0xC0, tvb, offset, 1, ENC_BIG_ENDIAN);
1988 if (value & 0xC0) {
1989 expert_add_info(pinfo, en, &ei_reserved_value);
1991 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
1992 offset += 1;
1995 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
1996 tvb, offset, 0, dir_addr,
1997 "%sDirect Address: %d",
1998 val_to_str_const (addr_type, addr_type_str, ""),
1999 dir_addr);
2000 PROTO_ITEM_SET_GENERATED (en);
2001 } else {
2002 en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address, tvb,
2003 offset, 1, value,
2004 "%sDirect Address: %d",
2005 val_to_str_const (addr_type, addr_type_str, ""),
2006 value & 0x7F);
2007 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2008 proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2009 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2010 offset += 1;
2013 if (rec_no != -1) {
2014 proto_item_append_text (tf, " %d", rec_no);
2015 if (rec_ofs != -1) {
2016 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2019 proto_item_append_text (tf, ", %sDirect Address: %d",
2020 val_to_str_const (addr_type, addr_type_str, ""), dir_addr);
2022 return offset;
2025 /* Ref 5.3.14 Extended Address */
2026 static gint dissect_dmp_ext_addr (tvbuff_t *tvb, packet_info *pinfo,
2027 proto_tree *field_tree, proto_item *tf,
2028 gint offset, gint rec_no, gint rec_ofs,
2029 gint addr_type)
2031 proto_tree *addr_tree = NULL, *ext_tree = NULL;
2032 proto_item *en = NULL, *ef = NULL;
2033 gint type, length;
2034 guint8 value;
2035 gint boffset = offset;
2036 gboolean addr_length_extended = FALSE;
2037 asn1_ctx_t asn1_ctx;
2039 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
2041 value = tvb_get_guint8 (tvb, offset);
2042 type = (value & 0xE0) >> 5;
2043 length = (value & 0x1F);
2044 ef = proto_tree_add_none_format (field_tree, hf_addr_ext_address, tvb,
2045 offset, -1, "%sExtended Address",
2046 val_to_str_const (addr_type, addr_type_str, ""));
2047 ext_tree = proto_item_add_subtree (ef, ett_address_extended);
2049 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type, tvb,
2050 offset, 1, value, "Address Type: %s",
2051 val_to_str_const (type, ext_addr_type,
2052 "Reserved"));
2053 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2054 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2056 if (value & 0x80) {
2057 addr_length_extended = TRUE;
2058 en = proto_tree_add_uint(ext_tree, hf_addr_ext_length1, tvb,
2059 offset, 1, value);
2060 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2061 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2062 offset += 1;
2064 /* Extended */
2065 value = tvb_get_guint8 (tvb, offset);
2066 type = ((value & 0xE0) >> 5);
2067 length |= ((value & 0x1F) << 5);
2069 en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type_ext, tvb,
2070 offset, 1, value, "Address Type Ext: %s",
2071 val_to_str_const (type, ext_addr_type_ext,
2072 "Reserved"));
2073 addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
2074 proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2076 en = proto_tree_add_uint(ext_tree, hf_addr_ext_length2, tvb,
2077 offset, 1, value);
2078 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2079 proto_tree_add_item (addr_tree, hf_addr_ext_length2, tvb, offset, 1, ENC_BIG_ENDIAN);
2080 offset += 1;
2081 } else {
2082 en = proto_tree_add_uint(ext_tree, hf_addr_ext_length, tvb,
2083 offset, 1, value);
2084 addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
2085 proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
2086 offset += 1;
2089 if (type == ASN1_BER) {
2090 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, length, length);
2092 dissect_p1_ORName (FALSE, next_tvb, 0, &asn1_ctx, ext_tree,
2093 hf_addr_ext_asn1_ber);
2094 } else if (type == ASN1_PER) {
2095 proto_tree_add_item (ext_tree, hf_addr_ext_asn1_per, tvb, offset, length, ENC_NA);
2096 } else {
2097 proto_tree_add_item (ext_tree, hf_addr_ext_unknown, tvb, offset, length, ENC_NA);
2099 offset += length;
2101 if (addr_length_extended) {
2102 en = proto_tree_add_uint(ext_tree, hf_addr_ext_length_generated,
2103 tvb, offset, 0, length);
2104 PROTO_ITEM_SET_GENERATED (en);
2107 proto_item_append_text (ef, ", Type: %s, Length: %d",
2108 val_to_str_const (type, ext_addr_type, "Reserved"),
2109 length);
2111 if (rec_no != -1) {
2112 proto_item_append_text (tf, " %d", rec_no);
2113 if (rec_ofs != -1) {
2114 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2117 proto_item_append_text (tf, ", %sExtended Address Type: %s",
2118 val_to_str_const (addr_type, addr_type_str, ""),
2119 val_to_str_const (type, ext_addr_type_short, "Reserved"));
2121 proto_item_set_len (ef, offset - boffset);
2123 return offset;
2126 /* Ref chapter 5.2.8.1 Extended Originator Encoding */
2127 static gint dissect_dmp_originator (tvbuff_t *tvb, packet_info *pinfo,
2128 proto_tree *envelope_tree, gint offset)
2130 proto_tree *field_tree = NULL, *rec_tree = NULL;
2131 proto_item *en = NULL, *tf = NULL;
2132 guint8 value, dmp_addr_form;
2133 gint boffset = offset;
2134 gboolean p2_addr = FALSE;
2136 tf = proto_tree_add_item (envelope_tree, hf_addr_originator, tvb, offset, -1, ENC_NA);
2137 field_tree = proto_item_add_subtree (tf, ett_address);
2139 if (dmp.addr_enc == DIRECT_ADDR) {
2140 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf,
2141 offset, -1, -1, ORIGINATOR);
2142 } else {
2143 value = tvb_get_guint8 (tvb, offset);
2144 dmp_addr_form = (value & 0xE0) >> 5;
2146 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2147 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig_v1, tvb,
2148 offset, 1, value,
2149 "Address Form: %s",
2150 val_to_str_const (dmp_addr_form,
2151 addr_form_orig_v1, "Reserved"));
2152 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2153 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig_v1, tvb, offset, 1, ENC_BIG_ENDIAN);
2154 } else {
2155 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig, tvb,
2156 offset, 1, value,
2157 "Address Form: %s",
2158 val_to_str_const (dmp_addr_form,
2159 addr_form_orig, "Reserved"));
2160 rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
2161 proto_tree_add_item (rec_tree, hf_addr_ext_form_orig, tvb, offset, 1, ENC_BIG_ENDIAN);
2164 en = proto_tree_add_item (rec_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
2165 if (value & 0x1F) {
2166 expert_add_info(pinfo, en, &ei_reserved_value);
2168 offset += 1;
2170 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2171 switch (dmp_addr_form) {
2173 case P1_DIRECT:
2174 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2175 tf, offset, -1, -1,
2176 ORIGINATOR);
2177 break;
2179 case P1_EXTENDED:
2180 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2181 -1, ORIGINATOR);
2182 break;
2184 default:
2185 proto_item_append_text (tf, " (invalid address form)");
2186 break;
2189 } else {
2190 switch (dmp_addr_form) {
2192 case P1_DIRECT:
2193 case P1_P2_DIRECT:
2194 case P1_DIRECT_P2_EXTENDED:
2195 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2196 tf, offset, -1, -1,
2197 ORIGINATOR);
2198 break;
2200 case P1_EXTENDED:
2201 case P1_EXTENDED_P2_DIRECT:
2202 case P1_P2_EXTENDED:
2203 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2204 -1, ORIGINATOR);
2205 break;
2207 default:
2208 proto_item_append_text (tf, " (invalid address form)");
2209 break;
2213 switch (dmp_addr_form) {
2215 case P1_P2_DIRECT:
2216 case P1_EXTENDED_P2_DIRECT:
2217 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
2218 tf, offset, -1, -1,
2219 ORIG_P2_ADDRESS);
2220 p2_addr = TRUE;
2221 break;
2223 case P1_DIRECT_P2_EXTENDED:
2224 case P1_P2_EXTENDED:
2225 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
2226 -1, ORIG_P2_ADDRESS);
2227 p2_addr = TRUE;
2228 break;
2233 if (p2_addr) {
2234 if (dmp.msg_type == NOTIF) {
2235 en = proto_tree_add_boolean (field_tree, hf_addr_int_rec, tvb,
2236 offset, 0, TRUE);
2237 } else {
2238 en = proto_tree_add_boolean (field_tree, hf_addr_dl_expanded, tvb,
2239 offset, 0, TRUE);
2241 PROTO_ITEM_SET_GENERATED (en);
2244 proto_item_set_len (tf, offset - boffset);
2246 return offset;
2249 static void dmp_add_recipient_info (proto_item *tf, guint8 rep_req,
2250 guint8 not_req, gboolean action)
2252 if (rep_req || not_req) {
2253 proto_item_append_text (tf, ", Request:");
2255 if (rep_req) {
2256 proto_item_append_text (tf, "%s",
2257 val_to_str_const (rep_req, report_vals_short, ""));
2259 if (not_req) {
2260 dmp.notif_req = TRUE;
2261 proto_item_append_text (tf, "%s",
2262 val_to_str_const (not_req, notif_vals_short, ""));
2264 if (action) {
2265 if (dmp.msg_type == STANAG) {
2266 proto_item_append_text (tf, " (Action)");
2267 } else if (dmp.msg_type == IPM) {
2268 proto_item_append_text (tf, " (To)");
2270 } else {
2271 if (dmp.msg_type == STANAG) {
2272 proto_item_append_text (tf, " (Info)");
2273 } else if (dmp.msg_type == IPM) {
2274 proto_item_append_text (tf, " (Cc)");
2279 /* Ref chapter 5.2.7 Direct Recipient Encoding */
2280 static gint dissect_dmp_direct_encoding (tvbuff_t *tvb, packet_info *pinfo,
2281 proto_tree *field_tree, proto_item *tf,
2282 gint offset, guint *prev_rec_no)
2285 proto_tree *addr_tree = NULL, *rec_tree = NULL;
2286 proto_item *en = NULL;
2287 guint8 rep_req = 0, not_req = 0, value;
2288 gint rec_no, rec_ofs = -1, dir_addr;
2289 gboolean action = FALSE, dir_addr_extended = FALSE;
2291 value = tvb_get_guint8 (tvb, offset);
2292 rec_no = (value & 0xF0) >> 4;
2293 rep_req = (value & 0x0C) >> 2;
2294 not_req = (value & 0x03);
2296 if (rep_req == 0x03) {
2297 en = proto_tree_add_uint_format_value(field_tree, hf_addr_dir_rec_no1,
2298 tvb, offset, 1, value,
2299 "%d (offset from previous)",
2300 (value & 0xF0) >> 4);
2301 } else {
2302 en = proto_tree_add_uint_format_value(field_tree, hf_addr_dir_rec_no,
2303 tvb, offset, 1, value,
2304 "%d (offset from previous)",
2305 (value & 0xF0) >> 4);
2307 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2308 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2309 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2310 proto_tree_add_item (rec_tree, hf_addr_dir_not_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
2311 offset += 1;
2313 value = tvb_get_guint8 (tvb, offset);
2314 dir_addr = (value & 0x7F);
2315 action = (value & 0x80);
2316 if (not_req == 0x03) {
2317 en = proto_tree_add_uint(field_tree, hf_addr_dir_address1,
2318 tvb, offset, 1, value);
2319 } else {
2320 en = proto_tree_add_uint(field_tree, hf_addr_dir_address,
2321 tvb, offset, 1, value);
2323 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2324 proto_tree_add_item (addr_tree, hf_addr_dir_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2325 proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
2326 offset += 1;
2328 if (rep_req == 0x03) {
2329 /* Extended Recipient Number 1 */
2330 value = tvb_get_guint8 (tvb, offset);
2331 rec_no |= ((value & 0x3F) << 4);
2332 rec_ofs = rec_no;
2333 rep_req = (value & 0xC0) >> 6;
2335 en = proto_tree_add_uint_format_value(field_tree, hf_addr_dir_rec_no2,
2336 tvb, offset, 1, value,
2337 "%d (offset from previous)",
2338 value & 0x3F);
2339 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2340 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2341 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2342 offset += 1;
2344 if (rep_req == 0x03) {
2345 /* Extended Recipient Number 2 */
2346 value = tvb_get_guint8 (tvb, offset);
2347 rec_no |= ((value & 0x1F) << 10);
2348 rec_ofs = rec_no;
2349 rep_req = (value & 0xC0) >> 6;
2351 en = proto_tree_add_uint_format_value(field_tree, hf_addr_dir_rec_no3,
2352 tvb, offset, 1, value,
2353 "%d (offset from previous)",
2354 value & 0x1F);
2355 rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
2356 proto_tree_add_item (rec_tree, hf_addr_dir_rep_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2357 en = proto_tree_add_item (rec_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
2358 if (value & 0x20) {
2359 expert_add_info(pinfo, en, &ei_reserved_value);
2361 proto_tree_add_item (rec_tree, hf_addr_dir_rec_no3, tvb, offset, 1, ENC_BIG_ENDIAN);
2362 offset += 1;
2366 if (not_req == 0x03) {
2367 /* Extended Direct Address 1 */
2368 dir_addr_extended = TRUE;
2369 value = tvb_get_guint8 (tvb, offset);
2370 dir_addr |= ((value & 0x3F) << 7);
2371 not_req = (value & 0xC0) >> 6;
2373 en = proto_tree_add_uint(field_tree, hf_addr_dir_address2, tvb,
2374 offset, 1, value);
2375 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2376 proto_tree_add_item (addr_tree, hf_addr_dir_not_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
2377 proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
2378 offset += 1;
2380 if (not_req == 0x03) {
2381 /* Extended Direct Address 2 */
2382 value = tvb_get_guint8 (tvb, offset);
2383 dir_addr |= ((value & 0x3F) << 13);
2384 not_req = (value & 0xC0) >> 6;
2386 en = proto_tree_add_uint(field_tree, hf_addr_dir_address3, tvb,
2387 offset, 1, value);
2388 addr_tree = proto_item_add_subtree (en, ett_address_direct);
2389 proto_tree_add_item (addr_tree, hf_addr_dir_not_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
2390 proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
2391 offset += 1;
2395 rec_no += *prev_rec_no;
2396 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2397 rec_no++;
2399 *prev_rec_no = rec_no;
2401 en = proto_tree_add_uint(field_tree, hf_addr_dir_rec_no_generated,
2402 tvb, offset, 0, rec_no);
2403 if (rec_no > 32767) {
2404 proto_item_append_text (en, " (maximum 32767)");
2405 expert_add_info(pinfo, en, &ei_addr_dir_rec_no_generated);
2407 PROTO_ITEM_SET_GENERATED (en);
2409 if (dir_addr_extended) {
2410 en = proto_tree_add_uint(field_tree, hf_addr_dir_address_generated,
2411 tvb, offset, 0, dir_addr);
2412 PROTO_ITEM_SET_GENERATED (en);
2415 proto_item_append_text (tf, " %d", rec_no);
2416 if (rec_ofs != -1) {
2417 proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
2420 proto_item_append_text (tf, ", Direct Address: %d", dir_addr);
2421 dmp_add_recipient_info (tf, rep_req, not_req, action);
2423 return offset;
2426 /* Ref 5.2.8.2 Extended Recipient Encoding */
2427 static gint dissect_dmp_ext_encoding (tvbuff_t *tvb, packet_info *pinfo,
2428 proto_tree *field_tree,
2429 proto_item *tf, gint offset,
2430 guint *prev_rec_no)
2432 proto_tree *addr_tree = NULL;
2433 proto_item *en = NULL;
2434 guint8 rep_req = 0, not_req = 0;
2435 guint8 value, dmp_addr_form;
2436 gboolean action = FALSE;
2437 gint rec_no, rec_ofs = -1;
2439 value = tvb_get_guint8 (tvb, offset);
2440 dmp_addr_form = (value & 0xE0) >> 5;
2441 action = (value & 0x10);
2442 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form, tvb,
2443 offset, 1, value,
2444 "Address Form: %s",
2445 val_to_str_const (dmp_addr_form,
2446 addr_form, "Reserved"));
2447 addr_tree = proto_item_add_subtree (en, ett_address_ext_form);
2448 proto_tree_add_item (addr_tree, hf_addr_ext_form, tvb, offset, 1, ENC_BIG_ENDIAN);
2450 en = proto_tree_add_boolean_format (field_tree, hf_addr_ext_action, tvb,
2451 offset, 1, value, "Action: %s",
2452 action ? "Yes" : "No");
2453 addr_tree = proto_item_add_subtree (en, ett_address_ext_action);
2454 proto_tree_add_item (addr_tree, hf_addr_ext_action, tvb, offset, 1, ENC_BIG_ENDIAN);
2456 rep_req = (value & 0x0C) >> 2;
2457 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rep_req, tvb,
2458 offset, 1, value,
2459 "Report Request: %s",
2460 val_to_str_const ((value & 0x0C) >> 2,
2461 report_vals, "Reserved"));
2462 addr_tree = proto_item_add_subtree (en, ett_address_ext_rep_req);
2463 proto_tree_add_item (addr_tree, hf_addr_ext_rep_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2465 not_req = (value & 0x03);
2466 en = proto_tree_add_uint_format (field_tree, hf_addr_ext_not_req, tvb,
2467 offset, 1, value,
2468 "Notification Request: %s",
2469 val_to_str_const (value & 0x03,
2470 notif_vals, "Reserved"));
2471 addr_tree = proto_item_add_subtree (en, ett_address_ext_not_req);
2472 proto_tree_add_item (addr_tree, hf_addr_ext_not_req, tvb, offset, 1, ENC_BIG_ENDIAN);
2473 offset += 1;
2475 value = tvb_get_guint8 (tvb, offset);
2476 rec_no = (value & 0x7F);
2477 if (value & 0x80) {
2478 en = proto_tree_add_uint_format_value(field_tree, hf_addr_ext_rec_no1, tvb,
2479 offset, 1, value,
2480 "%d (offset from previous)",
2481 value & 0x7F);
2482 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2483 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2484 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2485 offset += 1;
2487 /* Extended */
2488 value = tvb_get_guint8 (tvb, offset);
2489 rec_no |= (value << 7);
2490 rec_ofs = rec_no;
2491 en = proto_tree_add_uint_format_value(field_tree, hf_addr_ext_rec_no2, tvb,
2492 offset, 1, value,
2493 "%d (offset from previous)", value);
2494 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2495 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
2496 offset += 1;
2498 } else {
2499 en = proto_tree_add_uint_format_value(field_tree, hf_addr_ext_rec_no, tvb,
2500 offset, 1, value,
2501 "%d (offset from previous)",
2502 value & 0x7F);
2503 addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
2504 proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
2505 proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
2506 offset += 1;
2510 rec_no += *prev_rec_no;
2511 if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
2512 rec_no++;
2514 *prev_rec_no = rec_no;
2516 en = proto_tree_add_uint(field_tree, hf_addr_ext_rec_no_generated,
2517 tvb, offset, 0, rec_no);
2518 if (rec_no > 32767) {
2519 proto_item_append_text (en, " (maximum 32767)");
2520 expert_add_info(pinfo, en, &ei_addr_ext_rec_no_generated);
2522 PROTO_ITEM_SET_GENERATED (en);
2524 switch (dmp_addr_form) {
2526 case P1_DIRECT:
2527 case P1_P2_DIRECT:
2528 case P1_DIRECT_P2_EXTENDED:
2529 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2530 rec_no, rec_ofs, P1_ADDRESS);
2531 break;
2533 case P1_EXTENDED:
2534 case P1_EXTENDED_P2_DIRECT:
2535 case P1_P2_EXTENDED:
2536 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2537 rec_no, rec_ofs, P1_ADDRESS);
2538 break;
2542 switch (dmp_addr_form) {
2544 case P2_DIRECT:
2545 case P1_P2_DIRECT:
2546 case P1_EXTENDED_P2_DIRECT:
2547 offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
2548 rec_no, rec_ofs, P2_ADDRESS);
2549 break;
2551 case P2_EXTENDED:
2552 case P1_DIRECT_P2_EXTENDED:
2553 case P1_P2_EXTENDED:
2554 offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
2555 rec_no, rec_ofs, P2_ADDRESS);
2556 break;
2560 dmp_add_recipient_info (tf, rep_req, not_req, action);
2562 return offset;
2565 /* Ref chapter 5.2 Address encoding */
2566 static gint dissect_dmp_address (tvbuff_t *tvb, packet_info *pinfo,
2567 proto_tree *envelope_tree,
2568 gint offset, guint *prev_rec_no,
2569 gboolean reporting_name)
2571 proto_tree *field_tree = NULL;
2572 proto_item *tf = NULL;
2573 gint boffset = offset;
2575 if (reporting_name) {
2576 tf = proto_tree_add_item (envelope_tree, hf_addr_reporting_name, tvb, offset, -1, ENC_NA);
2577 } else {
2578 tf = proto_tree_add_none_format (envelope_tree, hf_addr_recipient, tvb,
2579 offset, -1, "Recipient Number");
2581 field_tree = proto_item_add_subtree (tf, ett_address);
2583 if (dmp.addr_enc == DIRECT_ADDR) {
2584 offset = dissect_dmp_direct_encoding (tvb, pinfo, field_tree, tf,
2585 offset, prev_rec_no);
2586 } else {
2587 offset = dissect_dmp_ext_encoding (tvb, pinfo, field_tree, tf, offset,
2588 prev_rec_no);
2591 proto_item_set_len (tf, offset - boffset);
2593 return offset;
2596 /* Ref chapter 6.2.9 Acknowledgement */
2597 static gint dissect_dmp_ack (tvbuff_t *tvb, packet_info *pinfo,
2598 proto_tree *dmp_tree, gint offset)
2600 proto_tree *ack_tree = NULL, *recip_tree = NULL;
2601 proto_item *en = NULL, *rt = NULL;
2602 proto_item *hidden_item;
2603 guint prev_rec_no = 0;
2604 gint rec_len, rec_no = 0;
2605 gint boffset = offset;
2607 en = proto_tree_add_item (dmp_tree, hf_ack, tvb, offset, 4, ENC_NA);
2608 ack_tree = proto_item_add_subtree (en, ett_ack);
2610 dmp.ack_reason = tvb_get_guint8 (tvb, offset);
2611 proto_item_append_text (en, ", Reason: %s",
2612 val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2614 rt = proto_tree_add_item (ack_tree, hf_ack_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
2615 if (dmp.ack_reason != 0) {
2616 expert_add_info_format(pinfo, rt, &ei_ack_reason, "ACK reason: %s", val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
2618 offset += 1;
2620 proto_tree_add_item (ack_tree, hf_ack_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN);
2621 offset += 1;
2623 /* Subject Message Identifier */
2624 dmp.subj_id = tvb_get_ntohs (tvb, offset);
2625 proto_tree_add_item (ack_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2626 hidden_item = proto_tree_add_item (ack_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
2627 PROTO_ITEM_SET_HIDDEN (hidden_item);
2628 offset += 2;
2630 if (use_seq_ack_analysis) {
2631 register_dmp_id (pinfo, dmp.ack_reason);
2634 if (dmp.ack_rec_present) {
2635 /* Recipient List */
2636 rec_len = tvb_length (tvb);
2637 if (dmp.checksum) {
2638 rec_len -= 2;
2640 if (offset < rec_len) {
2641 rt = proto_tree_add_item (ack_tree, hf_ack_recips, tvb, offset, -1, ENC_NA);
2642 recip_tree = proto_item_add_subtree (rt, ett_ack_recips);
2643 while (offset < rec_len) {
2644 offset = dissect_dmp_address (tvb, pinfo, recip_tree, offset,
2645 &prev_rec_no, FALSE);
2646 rec_no++;
2648 proto_item_append_text (rt, ", No Recipients: %d", rec_no);
2649 proto_item_set_len (rt, offset - boffset - 4);
2650 proto_item_set_len (en, offset - boffset);
2654 return offset;
2657 static gint dissect_mts_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2658 gint offset, gboolean subject)
2660 proto_item *hidden_item;
2661 const gchar *mts_id;
2663 if (dmp.msg_id_type == X400_MSG_ID || dmp_nat_decode == NAT_DECODE_DMP) {
2664 mts_id = dissect_7bit_string (tvb, offset, dmp.mts_id_length);
2665 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2666 mts_id = dissect_thales_mts_id (tvb, offset, dmp.mts_id_length);
2667 } else {
2668 mts_id = tvb_bytes_to_str (tvb, offset, dmp.mts_id_length);
2670 proto_item_append_text (dmp.mts_id_item, " (%zu bytes decompressed)", strlen (mts_id));
2671 mts_id = format_text (mts_id, strlen (mts_id));
2672 if (subject) {
2673 proto_tree_add_string (tree, hf_message_subj_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2674 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2675 /* Read from hash, for analysis */
2676 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, mts_id));
2677 } else {
2678 proto_tree_add_string (tree, hf_envelope_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2679 hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
2680 /* Insert into hash, for analysis */
2681 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (mts_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2683 PROTO_ITEM_SET_HIDDEN (hidden_item);
2684 offset += dmp.mts_id_length;
2686 return offset;
2689 static gint dissect_ipm_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2690 gint offset, gboolean subject)
2692 proto_tree *field_tree;
2693 proto_item *tf, *hidden_item;
2694 const gchar *ipm_id;
2695 gint length, modifier, ipm_id_length;
2697 length = tvb_get_guint8 (tvb, offset);
2698 modifier = (length & 0xC0) >> 6;
2699 ipm_id_length = length & 0x3F;
2701 tf = proto_tree_add_uint(tree, hf_envelope_ipm_id_length,
2702 tvb, offset, 1, ipm_id_length);
2703 field_tree = proto_item_add_subtree (tf, ett_envelope_ipm_id_length);
2704 if ((dmp.msg_id_type == NAT_MSG_ID || modifier != IPM_MODIFIER_X400) && dmp_nat_decode == NAT_DECODE_THALES) {
2705 proto_tree_add_item (field_tree, hf_thales_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2706 } else {
2707 proto_tree_add_item (field_tree, hf_envelope_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
2709 proto_tree_add_item (field_tree, hf_envelope_ipm_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2710 offset += 1;
2712 if (modifier == IPM_MODIFIER_X400 || dmp_nat_decode == NAT_DECODE_DMP) {
2713 ipm_id = dissect_7bit_string (tvb, offset, ipm_id_length);
2714 } else if (dmp_nat_decode == NAT_DECODE_THALES) {
2715 ipm_id = dissect_thales_ipm_id (tvb, offset, ipm_id_length, modifier);
2716 } else {
2717 ipm_id = tvb_bytes_to_str (tvb, offset, ipm_id_length);
2719 proto_item_append_text (tf, " (%zu bytes decompressed)", strlen (ipm_id));
2720 ipm_id = format_text (ipm_id, strlen (ipm_id));
2721 if (subject) {
2722 proto_tree_add_string (tree, hf_message_subj_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2723 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2724 /* Read from hash, for analysis */
2725 dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, ipm_id));
2726 } else {
2727 proto_tree_add_string (tree, hf_envelope_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2728 hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
2729 /* Insert into hash, for analysis */
2730 g_hash_table_insert (dmp_long_id_hash_table, g_strdup (ipm_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
2732 PROTO_ITEM_SET_HIDDEN (hidden_item);
2733 offset += ipm_id_length;
2735 return offset;
2738 /* Ref chapter 6.2.7 Envelope structure */
2739 static gint dissect_dmp_envelope (tvbuff_t *tvb, packet_info *pinfo,
2740 proto_tree *dmp_tree, gint offset)
2742 proto_tree *envelope_tree = NULL;
2743 proto_tree *field_tree = NULL;
2744 proto_item *en = NULL, *tf = NULL, *vf = NULL;
2745 proto_item *hidden_item;
2746 guint8 envelope, time_diff;
2747 guint16 subm_time, no_rec, value16;
2748 gint32 secs = 0;
2749 gchar *env_flags = NULL;
2750 guint prev_rec_no = 0;
2751 gint boffset = offset, i;
2752 gboolean using_short_id = FALSE;
2754 en = proto_tree_add_item (dmp_tree, hf_envelope, tvb, offset, 10, ENC_NA);
2755 envelope_tree = proto_item_add_subtree (en, ett_envelope);
2757 envelope = tvb_get_guint8 (tvb, offset);
2758 dmp.prot_id = (envelope & 0xF8) >> 3;
2759 dmp.version = (envelope & 0x07) + 1;
2761 /* Protocol Version */
2762 tf = proto_tree_add_uint(envelope_tree, hf_envelope_version,
2763 tvb, offset, 1, dmp.version);
2765 field_tree = proto_item_add_subtree (tf, ett_envelope_version);
2766 vf = proto_tree_add_item (field_tree, hf_envelope_protocol_id, tvb, offset, 1, ENC_BIG_ENDIAN);
2767 if (dmp.prot_id == PROT_NAT) {
2768 proto_item_append_text (vf, " (national version of DMP)");
2769 proto_item_append_text (tf, " (national)");
2770 } else if (dmp.prot_id == PROT_DMP) {
2771 proto_item_append_text (vf, " (correct)");
2772 } else {
2773 proto_item_append_text (vf, " (incorrect, should be 0x1d)");
2775 vf = proto_tree_add_item (field_tree, hf_envelope_version_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2776 offset += 1;
2778 if (dmp.version > DMP_VERSION_2) {
2779 /* Unsupported DMP Version */
2780 proto_item_append_text (vf, " (unsupported)");
2781 proto_item_append_text (tf, " (unsupported)");
2782 expert_add_info_format(pinfo, vf, &ei_envelope_version_value, "Unsupported DMP Version: %d", dmp.version);
2783 return offset;
2786 envelope = tvb_get_guint8 (tvb, offset);
2787 dmp.addr_enc = ((envelope & 0x10) >> 4);
2788 dmp.checksum = ((envelope & 0x08) >> 3);
2789 dmp.msg_type = (envelope & 0x07);
2791 if (dmp.msg_type != ACK) {
2792 /* Hop count */
2793 tf = proto_tree_add_uint(envelope_tree, hf_envelope_hop_count,
2794 tvb, offset, 1, envelope);
2795 field_tree = proto_item_add_subtree (tf, ett_envelope_hop_count);
2796 proto_tree_add_item (field_tree, hf_envelope_hop_count_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2797 } else {
2798 if (dmp.version >= DMP_VERSION_2) {
2799 /* Extensions Present */
2800 dmp.extensions = (envelope & 0x80);
2801 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2802 tvb, offset, 1, envelope,
2803 "Extensions: %s",
2804 (envelope & 0x80) ? "Present" : "Absent");
2805 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2806 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2809 /* Recipient Present */
2810 dmp.ack_rec_present = (envelope & 0x20);
2811 tf = proto_tree_add_boolean_format (envelope_tree,hf_envelope_rec_present,
2812 tvb, offset, 1, envelope,
2813 "Recipient Present: %s",
2814 (envelope & 0x20) ? "Present" : "Absent");
2815 field_tree = proto_item_add_subtree (tf, ett_envelope_rec_present);
2816 proto_tree_add_item (field_tree, hf_envelope_rec_present, tvb, offset, 1, ENC_BIG_ENDIAN);
2819 /* Address Encoding */
2820 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_addr_enc,
2821 tvb, offset, 1, envelope,
2822 "Address Encoding: %s",
2823 (envelope & 0x10) ?
2824 addr_enc.true_string :
2825 addr_enc.false_string);
2826 field_tree = proto_item_add_subtree (tf, ett_envelope_addr_enc);
2827 proto_tree_add_item (field_tree, hf_envelope_addr_enc, tvb, offset, 1, ENC_BIG_ENDIAN);
2829 /* Checksum Present */
2830 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_checksum,
2831 tvb, offset, 1, envelope,
2832 "Checksum: %s",
2833 (envelope & 0x08) ? "Used" : "Not used");
2834 field_tree = proto_item_add_subtree (tf, ett_envelope_checksum);
2835 proto_tree_add_item (field_tree, hf_envelope_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
2837 /* Content Type */
2838 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_type,
2839 tvb, offset, 1, envelope,
2840 "Content Type: %s (%d)",
2841 val_to_str_const (envelope & 0x07,
2842 type_vals, "Unknown"),
2843 envelope & 0x07);
2844 field_tree = proto_item_add_subtree (tf, ett_envelope_cont_type);
2845 proto_tree_add_item (field_tree, hf_envelope_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2847 proto_item_append_text (en, ", Checksum %s", (envelope >> 3) & 0x01 ? "Used" : "Not used");
2848 offset += 1;
2850 if (dmp.msg_type >= ACK) {
2851 proto_item_set_len (en, offset - boffset);
2852 return offset;
2855 if (dmp.version >= DMP_VERSION_2) {
2856 envelope = tvb_get_guint8 (tvb, offset);
2857 /* Extensions Present */
2858 tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
2859 tvb, offset, 1, envelope,
2860 "Extensions: %s",
2861 (envelope & 0x80) ? "Present" : "Absent");
2862 field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
2863 proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
2864 dmp.extensions = (envelope & 0x80);
2866 /* Message Identifier Type */
2867 dmp.msg_id_type = (envelope & 0x60) >> 5;
2868 tf = proto_tree_add_item (envelope_tree, hf_envelope_msg_id_type,
2869 tvb, offset, 1, ENC_BIG_ENDIAN);
2870 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id_type);
2871 proto_tree_add_item (field_tree, hf_envelope_msg_id_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2873 if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
2874 /* MTS Identifier Length */
2875 dmp.mts_id_length = (envelope & 0x1F);
2876 dmp.mts_id_item = proto_tree_add_item(envelope_tree, hf_envelope_mts_id_length,
2877 tvb, offset, 1, ENC_BIG_ENDIAN);
2878 field_tree = proto_item_add_subtree (dmp.mts_id_item, ett_envelope_mts_id_length);
2879 proto_tree_add_item (field_tree, hf_envelope_mts_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2880 offset += 1;
2881 } else {
2882 proto_tree_add_item (field_tree, hf_envelope_msg_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
2883 if (envelope & 0x10) {
2884 /* Using Short Identifier (12 bits) */
2885 using_short_id = TRUE;
2886 } else {
2887 tf = proto_tree_add_item (field_tree, hf_reserved_0x0F, tvb, offset, 1, ENC_BIG_ENDIAN);
2888 if (envelope & 0x0F) {
2889 expert_add_info(pinfo, tf, &ei_reserved_value);
2891 offset += 1;
2896 /* Message Identifier */
2897 dmp.msg_id = tvb_get_ntohs (tvb, offset);
2898 if (using_short_id) {
2899 dmp.msg_id &= 0x0FFF;
2901 tf = proto_tree_add_uint (envelope_tree, hf_envelope_msg_id, tvb, offset, 2, dmp.msg_id);
2902 hidden_item = proto_tree_add_uint (envelope_tree, hf_dmp_id, tvb, offset, 2, dmp.msg_id);
2903 if (using_short_id) {
2904 field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id);
2905 proto_tree_add_item (field_tree, hf_envelope_msg_id_12bit, tvb, offset, 2, ENC_BIG_ENDIAN);
2906 } else if (dmp.version >= DMP_VERSION_2 && dmp.msg_id_type == ONLY_DMP_ID && dmp.msg_id < 4096) {
2907 expert_add_info(pinfo, tf, &ei_envelope_msg_id);
2909 PROTO_ITEM_SET_HIDDEN (hidden_item);
2910 offset += 2;
2912 if (dmp.version >= DMP_VERSION_2) {
2913 if ((dmp.msg_type != REPORT) && (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID)) {
2914 offset = dissect_mts_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
2918 /* Submission Time */
2919 subm_time = tvb_get_ntohs (tvb, offset);
2920 dmp.subm_time = dmp_dec_subm_time ((guint16)(subm_time & 0x7FFF),
2921 (gint32) pinfo->fd->abs_ts.secs);
2922 tf = proto_tree_add_uint_format_value(envelope_tree, hf_envelope_subm_time, tvb,
2923 offset, 2, subm_time,
2924 "%s",
2925 (subm_time & 0x7FFF) >= 0x7FF8 ?
2926 "Reserved" :
2927 abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
2928 field_tree = proto_item_add_subtree (tf, ett_envelope_subm_time);
2929 proto_tree_add_item (field_tree, hf_envelope_time_diff_present, tvb, offset, 2, ENC_BIG_ENDIAN);
2930 proto_tree_add_item (field_tree, hf_envelope_subm_time_value, tvb, offset, 2, ENC_BIG_ENDIAN);
2931 offset += 2;
2933 if (subm_time & 0x8000) {
2934 /* Timed Difference */
2935 time_diff = tvb_get_guint8 (tvb, offset);
2936 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_time_diff,
2937 tvb, offset, 1, time_diff,
2938 "Time Difference: ");
2939 field_tree = proto_item_add_subtree (tf, ett_envelope_time_diff);
2940 proto_tree_add_item (field_tree, hf_envelope_time_diff_value, tvb, offset, 1, ENC_BIG_ENDIAN);
2941 secs = dmp_dec_time_diff (time_diff);
2942 if (secs == DMP_TIME_RESERVED) {
2943 proto_item_append_text (tf, "Reserved (0x%2.2x)", time_diff);
2944 } else {
2945 proto_item_append_text (tf, "%s", time_secs_to_str (secs));
2947 offset += 1;
2950 /* Envelope Flags */
2951 envelope = tvb_get_guint8 (tvb, offset);
2952 tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_flags,
2953 tvb, offset, 1, envelope,
2954 "Envelope Flags");
2956 field_tree = proto_item_add_subtree (tf, ett_envelope_flags);
2957 proto_tree_add_item (field_tree, hf_envelope_content_id_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
2958 proto_tree_add_item (field_tree, hf_envelope_recip_reassign_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2959 proto_tree_add_item (field_tree, hf_envelope_dl_expansion_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
2961 if (envelope & 0xE0) {
2962 env_flags = wmem_strdup_printf (wmem_packet_scope(), "%s%s%s",
2963 (envelope & 0x80) ? ", ContId discarded" : "",
2964 (envelope & 0x40) ? ", Reass prohibited" : "",
2965 (envelope & 0x20) ? ", DLE prohibited" : "");
2966 proto_item_append_text (tf, ":%s", &env_flags[1]);
2967 } else {
2968 proto_item_append_text (tf, " (none)");
2971 /* Recipient Count */
2972 no_rec = (envelope & 0x1F);
2973 tf = proto_tree_add_uint(envelope_tree, hf_envelope_recipients,
2974 tvb, offset, 1, envelope);
2976 field_tree = proto_item_add_subtree (tf, ett_envelope_recipients);
2977 proto_tree_add_item (field_tree, hf_envelope_recipients, tvb, offset, 1, ENC_BIG_ENDIAN);
2978 offset += 1;
2980 if (no_rec == 0) {
2981 /* Extended Recipient Count */
2982 value16 = tvb_get_ntohs (tvb, offset);
2983 no_rec = value16 & 0x7FFF;
2984 tf = proto_tree_add_uint_format_value(envelope_tree,hf_envelope_ext_recipients,
2985 tvb, offset, 2, value16,
2986 "%d%s", no_rec,
2987 (no_rec < 32 ?
2988 " (incorrect, reserved value)" : ""));
2990 field_tree = proto_item_add_subtree (tf, ett_envelope_ext_recipients);
2991 en = proto_tree_add_item (field_tree, hf_reserved_0x8000, tvb, offset, 2, ENC_BIG_ENDIAN);
2992 if (value16 & 0x8000) {
2993 expert_add_info(pinfo, en, &ei_reserved_value);
2995 proto_tree_add_item (field_tree, hf_envelope_ext_recipients, tvb, offset, 2, ENC_BIG_ENDIAN);
2996 offset += 2;
2999 if (dmp.msg_type != REPORT) {
3000 /* Originator - Not present for reports */
3001 offset = dissect_dmp_originator (tvb, pinfo, envelope_tree, offset);
3004 for (i = 0; i < no_rec; i++) {
3005 /* Recipient(s) */
3006 offset = dissect_dmp_address (tvb, pinfo, envelope_tree, offset,
3007 &prev_rec_no, FALSE);
3010 if (dmp.version >= DMP_VERSION_2) {
3011 if ((dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) &&
3012 dmp.notif_req && (dmp.msg_type == STANAG || dmp.msg_type == IPM))
3014 offset = dissect_ipm_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
3018 proto_item_set_len (en, offset - boffset);
3020 return offset;
3023 static void dissect_dmp_structured_id (tvbuff_t *tvb, proto_tree *body_tree,
3024 gint offset)
3026 gint length;
3028 offset += dmp_struct_offset;
3029 switch (dmp_struct_format) {
3031 case STRUCT_ID_UINT8:
3032 dmp.struct_id = wmem_strdup_printf (wmem_packet_scope(), "%u", tvb_get_guint8 (tvb, offset));
3033 proto_tree_add_item (body_tree, hf_message_bodyid_uint8, tvb, offset, 1, ENC_BIG_ENDIAN);
3034 break;
3036 case STRUCT_ID_UINT16:
3037 dmp.struct_id = wmem_strdup_printf (wmem_packet_scope(), "%u", tvb_get_ntohs (tvb, offset));
3038 proto_tree_add_item (body_tree, hf_message_bodyid_uint16, tvb, offset, 2, ENC_BIG_ENDIAN);
3039 break;
3041 case STRUCT_ID_UINT32:
3042 dmp.struct_id = wmem_strdup_printf (wmem_packet_scope(), "%u", tvb_get_ntohl (tvb, offset));
3043 proto_tree_add_item (body_tree, hf_message_bodyid_uint32, tvb, offset, 4, ENC_BIG_ENDIAN);
3044 break;
3046 case STRUCT_ID_UINT64:
3047 dmp.struct_id = wmem_strdup_printf (wmem_packet_scope(), "%" G_GINT64_MODIFIER "u", tvb_get_ntoh64 (tvb, offset));
3048 proto_tree_add_item (body_tree, hf_message_bodyid_uint64, tvb, offset, 8, ENC_BIG_ENDIAN);
3049 break;
3051 case STRUCT_ID_STRING:
3052 dmp.struct_id = tvb_get_string (wmem_packet_scope(), tvb, offset, (gint) dmp_struct_length);
3053 proto_tree_add_item (body_tree, hf_message_bodyid_string, tvb, offset, dmp_struct_length, ENC_ASCII|ENC_NA);
3054 break;
3056 case STRUCT_ID_ZSTRING:
3057 dmp.struct_id = tvb_get_stringz (wmem_packet_scope(), tvb, offset, &length);
3058 proto_tree_add_item (body_tree, hf_message_bodyid_zstring, tvb, offset, length, ENC_ASCII|ENC_NA);
3059 break;
3065 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3066 * and chapter 6.3.8.1 IPM 88 message structure
3068 static gint dissect_dmp_message (tvbuff_t *tvb, packet_info *pinfo,
3069 proto_tree *dmp_tree, gint offset)
3071 tvbuff_t *next_tvb = NULL;
3072 proto_tree *message_tree = NULL;
3073 proto_tree *field_tree = NULL;
3074 proto_item *en = NULL, *tf = NULL, *tr = NULL;
3075 guint8 message, eit = 0, compr_alg = ALGORITHM_NONE;
3076 gint len, boffset = offset;
3078 en = proto_tree_add_item (dmp_tree, hf_message_body, tvb, offset, -1, ENC_NA);
3079 message_tree = proto_item_add_subtree (en, ett_message);
3081 if (dmp.body_format == FREE_TEXT_SUBJECT) {
3082 len = tvb_strsize (tvb, offset);
3083 if (dmp_subject_as_id) {
3084 dmp.struct_id = tvb_get_string (wmem_packet_scope(), tvb, offset, len);
3086 proto_tree_add_item (message_tree, hf_message_subject, tvb, offset, len, ENC_ASCII|ENC_NA);
3087 offset += len;
3090 if (dmp.body_format == FREE_TEXT || dmp.body_format == FREE_TEXT_SUBJECT) {
3091 message = tvb_get_guint8 (tvb, offset);
3092 eit = (message & 0xE0) >> 5;
3093 compr_alg = (message & 0x18) >> 3;
3094 /* Encoded Information Type */
3095 tf = proto_tree_add_item (message_tree, hf_message_eit,
3096 tvb, offset, 1, ENC_BIG_ENDIAN);
3097 field_tree = proto_item_add_subtree (tf, ett_message_eit);
3098 proto_tree_add_item (field_tree, hf_message_eit, tvb, offset, 1, ENC_BIG_ENDIAN);
3099 proto_item_append_text (en, ", Type: %s",
3100 val_to_str_const (eit, eit_vals, "Unknown"));
3102 /* Compression Algorithm */
3103 tf = proto_tree_add_item (message_tree, hf_message_compr,
3104 tvb, offset, 1,ENC_BIG_ENDIAN);
3105 field_tree = proto_item_add_subtree (tf, ett_message_compr);
3106 tr = proto_tree_add_item (field_tree, hf_message_compr, tvb, offset, 1, ENC_BIG_ENDIAN);
3107 if (compr_alg == ALGORITHM_ZLIB) {
3108 proto_item_append_text (en, " (compressed)");
3109 } else if (compr_alg != ALGORITHM_NONE) {
3110 expert_add_info(pinfo, tr, &ei_message_compr);
3113 if (message & 0x07) {
3114 /* Reserved */
3115 tf = proto_tree_add_item(message_tree, hf_reserved_0x07,
3116 tvb, offset, 1, ENC_BIG_ENDIAN);
3117 field_tree = proto_item_add_subtree (tf, ett_message_body_reserved);
3118 tf = proto_tree_add_item (field_tree, hf_reserved_0x07, tvb, offset, 1, ENC_BIG_ENDIAN);
3119 expert_add_info(pinfo, tf, &ei_reserved_value);
3121 offset += 1;
3124 len = tvb_length_remaining (tvb, offset);
3125 if (dmp.checksum) {
3126 len -= 2;
3129 tf = proto_tree_add_none_format (message_tree, hf_message_body_data, tvb,
3130 offset, len,
3131 "%sUser data, Length: %d",
3132 (compr_alg == ALGORITHM_ZLIB) ?
3133 "Compressed " : "", len);
3134 field_tree = proto_item_add_subtree (tf, ett_message_body);
3136 if (dmp.body_format == STRUCTURED) {
3137 /* Structured Message ID */
3138 dissect_dmp_structured_id (tvb, field_tree, offset);
3139 proto_tree_add_item (field_tree, hf_message_body_structured, tvb, offset, len, ENC_NA);
3140 } else if (len > 0 && (dmp.body_format == FREE_TEXT ||
3141 dmp.body_format == FREE_TEXT_SUBJECT)) {
3142 if (compr_alg == ALGORITHM_ZLIB) {
3143 if ((next_tvb = tvb_child_uncompress (tvb, tvb, offset, len)) != NULL) {
3144 gint zlen = tvb_length (next_tvb);
3145 add_new_data_source (pinfo, next_tvb, "Uncompressed User data");
3146 tf = proto_tree_add_none_format (message_tree,
3147 hf_message_body_uncompr,
3148 next_tvb, 0, zlen,
3149 "Uncompressed User data, "
3150 "Length: %d", zlen);
3151 field_tree = proto_item_add_subtree (tf, ett_message_body_uncompr);
3152 proto_tree_add_item (field_tree, hf_message_body_uncompressed, next_tvb, 0, -1, ENC_ASCII|ENC_NA);
3153 } else {
3154 proto_tree_add_expert(message_tree, pinfo, &ei_message_body_uncompressed, tvb, offset, -1);
3156 } else if (eit != EIT_BILATERAL) {
3157 proto_tree_add_item (field_tree, hf_message_body_plain, tvb, offset, len, ENC_ASCII|ENC_NA);
3160 offset += len;
3162 if (dmp.struct_id) {
3163 proto_item_append_text (en, ", Id: %s", format_text (dmp.struct_id, strlen (dmp.struct_id)));
3166 proto_item_set_len (en, offset - boffset);
3168 return offset;
3171 /* Ref chapter 6.3.9.1 Report structure */
3172 static gint dissect_dmp_report (tvbuff_t *tvb, packet_info *pinfo,
3173 proto_tree *dmp_tree, gint offset,
3174 guint *prev_rec_no, gint num)
3176 proto_tree *report_tree = NULL;
3177 proto_tree *field_tree = NULL;
3178 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3179 guint8 report;
3180 gboolean info_present;
3181 gint32 secs = 0;
3182 gint len, boffset = offset;
3183 gint rep_type = 0;
3185 report = tvb_get_guint8 (tvb, offset);
3186 rep_type = (report & 0x80) >> 7;
3187 if (rep_type) {
3188 en = proto_tree_add_item (dmp_tree, hf_non_delivery_report, tvb, offset, 4, ENC_NA);
3189 } else {
3190 en = proto_tree_add_item (dmp_tree, hf_delivery_report, tvb, offset, 4, ENC_NA);
3192 proto_item_append_text (en, " (#%d)", num);
3194 report_tree = proto_item_add_subtree (en, ett_report);
3196 /* Report Type */
3197 tf = proto_tree_add_boolean_format (report_tree, hf_report_type,
3198 tvb, offset, 1, report,
3199 "Report Type: %s", rep_type ?
3200 report_type.true_string :
3201 report_type.false_string);
3202 field_tree = proto_item_add_subtree (tf, ett_report_type);
3203 proto_tree_add_item (field_tree, hf_report_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3205 if (rep_type == DR) {
3206 dmp.dr = TRUE;
3207 /* Info Present */
3208 info_present = (report & 0x40);
3209 tf = proto_tree_add_boolean_format (report_tree,hf_report_info_present_dr,
3210 tvb, offset, 1, report,
3211 "Info Present: %s", (report & 0x40) ? "Present" : "Absent");
3212 field_tree = proto_item_add_subtree (tf, ett_report_info_present_dr);
3213 proto_tree_add_item (field_tree, hf_report_info_present_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3215 /* Address Encoding */
3216 dmp.addr_enc = ((report & 0x20) >> 5);
3217 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_dr,
3218 tvb, offset, 1, report,
3219 "Address Encoding: %s",
3220 (report & 0x20) ?
3221 addr_enc.true_string :
3222 addr_enc.false_string);
3223 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_dr);
3224 proto_tree_add_item (field_tree, hf_report_addr_enc_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
3226 if (report & 0x1F) {
3227 /* Reserved */
3228 tf = proto_tree_add_item(report_tree, hf_reserved_0x1F,
3229 tvb, offset, 1, ENC_BIG_ENDIAN);
3230 field_tree = proto_item_add_subtree (tf, ett_report_reserved);
3231 tf = proto_tree_add_item (field_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
3232 expert_add_info(pinfo, tf, &ei_reserved_value);
3235 offset += 1;
3237 /* Delivery Time */
3238 report = tvb_get_guint8 (tvb, offset);
3239 tf = proto_tree_add_uint_format (report_tree, hf_report_del_time,
3240 tvb, offset, 1, report,
3241 "Delivery Time: ");
3242 field_tree = proto_item_add_subtree (tf, ett_report_del_time);
3243 ei = proto_tree_add_item (field_tree, hf_report_del_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3244 secs = dmp_dec_del_time (report);
3245 if (secs == DMP_TIME_RESERVED) {
3246 proto_item_append_text (tf, "Reserved (0x%2.2x)", report);
3247 proto_item_append_text (ei, " (Reserved)");
3248 } else {
3249 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3250 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3251 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3253 } else {
3254 dmp.ndr = TRUE;
3255 /* Address Encoding */
3256 dmp.addr_enc = ((report & 0x40) >> 6);
3257 tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_ndr,
3258 tvb, offset, 1, report,
3259 "Address Encoding: %s",
3260 (report & 0x40) ?
3261 addr_enc.true_string :
3262 addr_enc.false_string);
3263 field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_ndr);
3264 proto_tree_add_item (field_tree, hf_report_addr_enc_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3266 /* Reason */
3267 tf = proto_tree_add_uint_format (report_tree, hf_report_reason,
3268 tvb, offset, 1, report,
3269 "Reason%s: %s (%d)",
3270 ((report & 0x3F) < 0x3D) ? " (P1)":"",
3271 non_del_reason_str (report & 0x3F),
3272 report & 0x3F);
3273 field_tree = proto_item_add_subtree (tf, ett_report_reason);
3274 proto_tree_add_item (field_tree, hf_report_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
3275 offset += 1;
3277 /* Info Present */
3278 report = tvb_get_guint8 (tvb, offset);
3279 info_present = (report & 0x80);
3280 tf = proto_tree_add_boolean_format (report_tree,
3281 hf_report_info_present_ndr,
3282 tvb, offset, 1, report,
3283 "Info Present: %s", (report & 0x80) ? "Present" : "Absent");
3284 field_tree = proto_item_add_subtree (tf, ett_report_info_present_ndr);
3285 proto_tree_add_item (field_tree, hf_report_info_present_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
3287 /* Diagnostic */
3288 tf = proto_tree_add_uint_format (report_tree, hf_report_diagn,
3289 tvb, offset, 1, report,
3290 "Diagnostic%s: %s (%d)",
3291 ((report & 0x7F) < 0x7C) ? " (P1)":"",
3292 non_del_diagn_str (report & 0x7F),
3293 report & 0x7F);
3294 field_tree = proto_item_add_subtree (tf, ett_report_diagn);
3295 proto_tree_add_item (field_tree, hf_report_diagn, tvb, offset, 1, ENC_BIG_ENDIAN);
3297 offset += 1;
3299 offset = dissect_dmp_address (tvb, pinfo, report_tree, offset,
3300 prev_rec_no, TRUE);
3302 if (info_present) {
3303 /* Supplementary Information */
3304 len = tvb_strsize (tvb, offset);
3305 tf = proto_tree_add_uint_format (report_tree, hf_report_suppl_info_len,
3306 tvb, offset, len, len,
3307 "Supplementary Information, Length: %d",
3308 len - 1);
3309 if (len > 1) {
3310 if ((offset - boffset + len) > 128) {
3311 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3312 128 - (offset - boffset));
3314 field_tree = proto_item_add_subtree (tf, ett_report_suppl_info);
3315 proto_tree_add_item (field_tree, hf_report_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3317 offset += len;
3320 proto_item_set_len (en, offset - boffset);
3322 return offset;
3325 /* Ref chapter 6.3.10.1 Notification structure */
3326 static gint dissect_dmp_notification (tvbuff_t *tvb, packet_info *pinfo _U_,
3327 proto_tree *dmp_tree, gint offset)
3329 proto_tree *notif_tree = NULL;
3330 proto_tree *field_tree = NULL;
3331 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3332 guint8 notif, rec_time, on_typex = 0xFF;
3333 gint len, boffset = offset;
3334 gint32 secs = 0;
3336 if (dmp.notif_type == RN) {
3337 en = proto_tree_add_item (dmp_tree, hf_receipt_notif, tvb, offset, 4, ENC_NA);
3338 } else if (dmp.notif_type == NRN) {
3339 en = proto_tree_add_item (dmp_tree, hf_non_receipt_notif, tvb, offset, 4, ENC_NA);
3340 } else if (dmp.notif_type == ON) {
3341 en = proto_tree_add_item (dmp_tree, hf_other_notif, tvb, offset, 4, ENC_NA);
3342 } else {
3343 return offset;
3345 notif_tree = proto_item_add_subtree (en, ett_notif);
3347 if (dmp.notif_type == RN || dmp.notif_type == ON) {
3348 /* Receipt Time */
3349 rec_time = tvb_get_guint8 (tvb, offset);
3350 tf = proto_tree_add_uint_format (notif_tree, hf_notif_rec_time,
3351 tvb, offset, 1, rec_time,
3352 "Receipt Time: ");
3353 field_tree = proto_item_add_subtree (tf, ett_notif_rec_time);
3354 ei = proto_tree_add_item (field_tree, hf_notif_rec_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3355 secs = dmp_dec_exp_time (rec_time);
3356 if (secs == DMP_TIME_NOT_PRESENT) {
3357 proto_item_append_text (tf, "Not present");
3358 proto_item_append_text (ei, " (not present)");
3359 } else if (secs == DMP_TIME_RESERVED) {
3360 proto_item_append_text (tf, "Reserved (0x%2.2x)", rec_time);
3361 proto_item_append_text (ei, " (Reserved)");
3362 } else {
3363 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3364 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3365 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3367 offset += 1;
3369 if (dmp.notif_type == ON) {
3370 /* ON Type */
3371 on_typex = tvb_get_guint8 (tvb, offset);
3372 proto_tree_add_item (notif_tree, hf_notif_on_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3373 offset += 1;
3376 /* Supplementary Information */
3377 len = tvb_strsize (tvb, offset);
3378 tf = proto_tree_add_uint_format (notif_tree, hf_notif_suppl_info_len,
3379 tvb, offset, len, len,
3380 "Supplementary Information, Length: %d",
3381 len - 1);
3382 if (len > 1) {
3383 if ((offset - boffset + len) > 128) {
3384 proto_item_append_text (tf, " (incorrect, should be less than %d)",
3385 128 - (offset - boffset));
3387 field_tree = proto_item_add_subtree (tf, ett_notif_suppl_info);
3388 proto_tree_add_item (field_tree, hf_notif_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
3390 offset += len;
3392 if ((dmp.notif_type == ON) && (on_typex < 0x03)) {
3393 /* ACP127 Receipient */
3394 len = tvb_strsize (tvb, offset);
3395 tf = proto_tree_add_uint_format (notif_tree, hf_notif_acp127,
3396 tvb, offset, len, len,
3397 "ACP127 Recipient, Length: %d",
3398 len - 1);
3399 if (len > 1) {
3400 if (len > 64) {
3401 proto_item_append_text (tf, " (incorrect, must be less than 64)");
3403 field_tree = proto_item_add_subtree (tf, ett_notif_acp127recip);
3404 proto_tree_add_item (field_tree, hf_notif_acp127recip, tvb, offset, len, ENC_ASCII|ENC_NA);
3406 offset += len;
3408 } else if (dmp.notif_type == NRN) {
3409 /* Non-Recipient Reason */
3410 notif = tvb_get_guint8 (tvb, offset);
3411 proto_tree_add_uint_format (notif_tree, hf_notif_non_rec_reason,
3412 tvb, offset, 1, notif,
3413 "Non-Receipt Reason%s: %s (%d)",
3414 (notif < 0x10) ? " (P22)" : "",
3415 nrn_reason_str (notif), notif);
3416 offset += 1;
3418 /* Discard Reason */
3419 notif = tvb_get_guint8 (tvb, offset);
3420 proto_tree_add_uint_format (notif_tree, hf_notif_discard_reason,
3421 tvb, offset, 1, notif,
3422 "Discard Reason%s: %s (%d)",
3423 (notif < 0x10) ? " (P22)" : "",
3424 discard_reason_str (notif), notif);
3425 offset += 1;
3428 proto_item_set_len (en, offset - boffset);
3430 return offset;
3433 /* Ref chapter 6.2.1.2.8 SecurityCategories */
3434 static gint dissect_dmp_security_category (tvbuff_t *tvb, packet_info *pinfo,
3435 proto_tree *tree,
3436 const gchar **label_string,
3437 gint offset, guint8 ext)
3439 proto_tree *field_tree = NULL;
3440 proto_item *tf = NULL, *tr = NULL;
3441 gchar *sec_cat = NULL;
3442 guint8 message;
3443 gboolean country_code = FALSE;
3445 message = tvb_get_guint8 (tvb, offset);
3446 tf = proto_tree_add_uint_format (tree, hf_message_sec_cat_nat, tvb,
3447 offset, 1, message, "Security Categories");
3448 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3450 switch (ext) {
3452 case SEC_CAT_EXT_NONE:
3453 proto_tree_add_item (field_tree, hf_message_sec_cat_cl, tvb, offset, 1, ENC_BIG_ENDIAN);
3454 proto_tree_add_item (field_tree, hf_message_sec_cat_cs, tvb, offset, 1, ENC_BIG_ENDIAN);
3455 proto_tree_add_item (field_tree, hf_message_sec_cat_ex, tvb, offset, 1, ENC_BIG_ENDIAN);
3456 proto_tree_add_item (field_tree, hf_message_sec_cat_ne, tvb, offset, 1, ENC_BIG_ENDIAN);
3458 tr = proto_tree_add_item (field_tree, hf_reserved_0x08, tvb, offset, 1, ENC_BIG_ENDIAN);
3459 if (message & 0x08) {
3460 expert_add_info(pinfo, tr, &ei_reserved_value);
3462 tr = proto_tree_add_item (field_tree, hf_reserved_0x04, tvb, offset, 1, ENC_BIG_ENDIAN);
3463 if (message & 0x04) {
3464 expert_add_info(pinfo, tr, &ei_reserved_value);
3467 if (message & 0xF0) {
3468 sec_cat = wmem_strdup_printf (wmem_packet_scope(), "%s%s%s%s",
3469 (message & 0x80) ? ",cl" : "",
3470 (message & 0x40) ? ",cs" : "",
3471 (message & 0x20) ? ",ex" : "",
3472 (message & 0x10) ? ",ne" : "");
3473 proto_item_append_text (tf, ": %s", &sec_cat[1]);
3474 *label_string = wmem_strconcat(wmem_packet_scope(), *label_string, sec_cat, NULL);
3476 break;
3478 case SEC_CAT_EXT_PERMISSIVE:
3479 if ((message >> 2) == 0x3F) {
3480 /* Fake entry because nat_pol_id defines 0x3F as reserved */
3481 proto_tree_add_uint_format (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1,
3482 message, "1111 11.. = Next byte has Country Code (0x3F)");
3483 country_code = TRUE;
3484 } else {
3485 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1, ENC_BIG_ENDIAN);
3486 proto_item_append_text (tf, ": rel-to-%s", get_nat_pol_id_short (message >> 2));
3487 *label_string = wmem_strdup_printf(wmem_packet_scope(), "%s,rel-to-%s", *label_string, get_nat_pol_id_short (message >> 2));
3488 if ((message >> 2) == 0) {
3489 expert_add_info(pinfo, tr, &ei_reserved_value);
3492 break;
3494 case SEC_CAT_EXT_RESTRICTIVE:
3495 proto_tree_add_item (field_tree, hf_message_sec_cat_restrictive, tvb, offset, 1, ENC_BIG_ENDIAN);
3496 proto_item_append_text (tf, " (restrictive: 0x%2.2x)", message >> 2);
3497 break;
3499 default:
3500 break;
3503 proto_item_append_text (tf, " (0x%2.2x)", message);
3505 if (dmp.version == 1) {
3506 tr = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3507 if (message & 0x02) {
3508 expert_add_info(pinfo, tr, &ei_reserved_value);
3510 tr = proto_tree_add_item (field_tree, hf_reserved_0x01, tvb, offset, 1, ENC_BIG_ENDIAN);
3511 if (message & 0x01) {
3512 expert_add_info(pinfo, tr, &ei_reserved_value);
3514 } else {
3515 tr = proto_tree_add_item (field_tree, hf_message_sec_cat_extended, tvb, offset, 1, ENC_BIG_ENDIAN);
3516 if ((message & 0x01) && (message & 0x02)) {
3517 expert_add_info(pinfo, tr, &ei_reserved_value);
3518 } else if (message & 0x01 || message & 0x02) {
3519 proto_item_append_text (tf, " (extended)");
3520 offset = dissect_dmp_security_category (tvb, pinfo, tree, label_string, offset+1, message & 0x03);
3523 if (country_code) {
3524 proto_tree_add_item (field_tree, hf_message_sec_cat_country_code, tvb, offset+1, 1, ENC_BIG_ENDIAN);
3525 proto_item_append_text (tf, " (rel-to country-code: %d)", tvb_get_guint8 (tvb, offset+1));
3526 proto_item_set_len (tf, 2);
3527 offset++;
3531 return offset;
3535 * Ref chapter 6.3.7.1 STANAG 4406 message structure
3536 * and chapter 6.3.8.1 IPM 88 message structure
3537 * and chapter 6.3.9.1 Report structure
3538 * and chapter 6.3.10.1 Notification structure
3540 static gint dissect_dmp_content (tvbuff_t *tvb, packet_info *pinfo,
3541 proto_tree *dmp_tree, gint offset)
3543 proto_tree *message_tree = NULL;
3544 proto_tree *field_tree = NULL;
3545 proto_item *en = NULL, *ei = NULL, *tf = NULL;
3546 proto_item *hidden_item;
3547 const char *label_string = wmem_strdup (wmem_packet_scope(), "");
3548 const gchar *class_name = NULL;
3549 guint8 message, dmp_sec_pol, dmp_sec_class, dmp_nation = 0, exp_time, dtg;
3550 gint32 secs = 0;
3551 guint prev_rec_no = 0;
3552 gint rep_len, rep_no = 1;
3553 gint loffset, boffset = offset;
3555 if (dmp.msg_type == REPORT) {
3556 en = proto_tree_add_item (dmp_tree, hf_report_content, tvb, offset, 7, ENC_NA);
3557 } else if (dmp.msg_type == NOTIF) {
3558 en = proto_tree_add_item (dmp_tree, hf_notif_content, tvb, offset, 7, ENC_NA);
3559 } else {
3560 en = proto_tree_add_item (dmp_tree, hf_message_content, tvb, offset, 7, ENC_NA);
3562 message_tree = proto_item_add_subtree (en, ett_content);
3564 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3565 message = tvb_get_guint8 (tvb, offset);
3566 dmp.body_format = (message & 0x03);
3568 if (dmp.msg_type == STANAG) {
3569 /* Message Type */
3570 dmp.st_type = (message & 0xC0) >> 6;
3571 tf = proto_tree_add_uint_format (message_tree, hf_message_st_type,
3572 tvb, offset, 1, message,
3573 "Message Type: %s (%d)",
3574 val_to_str_const (dmp.st_type,
3575 message_type_vals, ""),
3576 dmp.st_type);
3577 field_tree = proto_item_add_subtree (tf, ett_message_st_type);
3578 proto_tree_add_item (field_tree, hf_message_st_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3580 if ((message & 0x20) >> 5) {
3581 /* Reserved */
3582 tf = proto_tree_add_item(message_tree, hf_reserved_0x20,
3583 tvb, offset, 1, ENC_BIG_ENDIAN);
3584 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3585 tf = proto_tree_add_item (field_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
3586 expert_add_info(pinfo, tf, &ei_reserved_value);
3589 /* Precedence */
3590 dmp.prec = (message & 0x1C) >> 2;
3591 tf = proto_tree_add_item(message_tree, hf_message_precedence,
3592 tvb, offset, 1,ENC_BIG_ENDIAN);
3593 field_tree = proto_item_add_subtree (tf, ett_message_precedence);
3594 proto_tree_add_item (field_tree, hf_message_precedence, tvb, offset, 1, ENC_BIG_ENDIAN);
3596 } else {
3597 if ((message & 0xE0) >> 5) {
3598 /* Reserved */
3599 tf = proto_tree_add_item(message_tree, hf_reserved_0xE0,
3600 tvb, offset, 1, ENC_BIG_ENDIAN);
3601 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3602 tf = proto_tree_add_item (field_tree, hf_reserved_0xE0, tvb, offset, 1, ENC_BIG_ENDIAN);
3603 expert_add_info(pinfo, tf, &ei_reserved_value);
3606 /* Importance */
3607 dmp.prec = (message & 0x1C) >> 2;
3608 tf = proto_tree_add_item(message_tree, hf_message_importance,
3609 tvb, offset, 1, ENC_BIG_ENDIAN);
3610 field_tree = proto_item_add_subtree (tf, ett_message_importance);
3611 proto_tree_add_item (field_tree, hf_message_importance, tvb, offset, 1, ENC_BIG_ENDIAN);
3614 /* Body Format */
3615 tf = proto_tree_add_uint_format (message_tree, hf_message_body_format,
3616 tvb, offset, 1, message,
3617 "Body Format: %s (%d)",
3618 val_to_str_const (message & 0x03,
3619 body_format_vals, ""),
3620 message & 0x03);
3621 field_tree = proto_item_add_subtree (tf, ett_message_body_format);
3622 proto_tree_add_item (field_tree, hf_message_body_format, tvb, offset, 1, ENC_BIG_ENDIAN);
3623 offset += 1;
3626 message = tvb_get_guint8 (tvb, offset);
3627 /* Security Classification */
3628 dmp_sec_class = (message & 0xE0) >> 5;
3629 dmp_sec_pol = (message & 0x1C) >> 2;
3630 if (dmp_sec_pol == EXTENDED_NATIONAL) {
3631 dmp_nation = tvb_get_guint8 (tvb, offset + 1);
3634 loffset = offset; /* Offset to start of security label */
3635 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3636 class_name = dmp_national_sec_class (dmp_local_nation, dmp_sec_class);
3637 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3638 class_name = dmp_national_sec_class (dmp_nation, dmp_sec_class);
3640 if ((dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL) && !class_name) {
3641 class_name = val_to_str_const (dmp_sec_class, sec_class, "");
3643 if (class_name && class_name[0]) {
3644 tf = proto_tree_add_uint_format_value(message_tree, hf_message_sec_class_val,
3645 tvb, offset, 1, message,
3646 "%s (%d)",
3647 class_name, dmp_sec_class);
3648 } else {
3649 tf = proto_tree_add_uint_format_value(message_tree, hf_message_sec_class_val,
3650 tvb, offset, 1, message,
3651 "%d",
3652 dmp_sec_class);
3654 field_tree = proto_item_add_subtree (tf, ett_message_sec_class);
3655 tf = proto_tree_add_item (field_tree, hf_message_sec_class_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3656 if (class_name) {
3657 proto_item_append_text (tf, " (%s)", class_name);
3658 label_string = wmem_strconcat(wmem_packet_scope(), label_string, class_name, NULL);
3661 /* Security Policy */
3662 tf = proto_tree_add_uint_format (message_tree, hf_message_sec_pol,
3663 tvb, offset, 1, message,
3664 "Security Policy: %s (%d)",
3665 val_to_str (dmp_sec_pol, sec_pol, "%d"),
3666 dmp_sec_pol);
3667 field_tree = proto_item_add_subtree (tf, ett_message_sec_pol);
3668 proto_tree_add_item (field_tree, hf_message_sec_pol, tvb, offset, 1, ENC_BIG_ENDIAN);
3670 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3671 /* Heading Flags */
3672 tf = proto_tree_add_item (message_tree, hf_message_heading_flags, tvb, offset, 1, ENC_NA);
3673 field_tree = proto_item_add_subtree (tf, ett_message_heading_flags);
3674 proto_tree_add_item (field_tree, hf_message_auth_users, tvb, offset, 1, ENC_BIG_ENDIAN);
3675 proto_tree_add_item (field_tree, hf_message_subject_disc, tvb, offset, 1, ENC_BIG_ENDIAN);
3676 if (message & 0x03) {
3677 proto_item_append_text (tf, ": %s%s%s discarded",
3678 (message & 0x02) ? "Authorizing users" : "",
3679 (message & 0x03) == 0x03 ? " and " : "",
3680 (message & 0x01) ? "Subject" : "");
3681 } else {
3682 proto_item_append_text (tf, " (none)");
3684 } else if (dmp.msg_type == NOTIF) {
3685 /* Notification Type */
3686 dmp.notif_type = (message & 0x03);
3687 tf = proto_tree_add_uint_format (message_tree, hf_notif_type,
3688 tvb, offset, 1, message,
3689 "Notification Type: %s",
3690 val_to_str_const (dmp.notif_type, notif_type,
3691 "Reserved"));
3692 field_tree = proto_item_add_subtree (tf, ett_notif_type);
3693 proto_tree_add_item (field_tree, hf_notif_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3694 } else if (message & 0x02) {
3695 /* Reserved */
3696 tf = proto_tree_add_item(message_tree, hf_reserved_0x02,
3697 tvb, offset, 1, ENC_BIG_ENDIAN);
3698 field_tree = proto_item_add_subtree (tf, ett_message_reserved);
3699 tf = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
3700 expert_add_info(pinfo, tf, &ei_reserved_value);
3702 offset += 1;
3704 if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
3705 /* Show configured national policy */
3706 tf = proto_tree_add_uint (message_tree, hf_message_national_policy_id,
3707 tvb, offset, 0, dmp_local_nation);
3708 PROTO_ITEM_SET_GENERATED (tf);
3709 } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
3710 /* National Policy Identifier */
3711 proto_tree_add_item (message_tree, hf_message_national_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3712 offset += 1;
3713 } else if (dmp_sec_pol == EXTENDED_MISSION) {
3714 /* Mission Policy Identifier */
3715 message = tvb_get_guint8 (tvb, offset);
3716 if (message == 0xFF) {
3717 proto_tree_add_uint_format_value(message_tree, hf_message_mission_policy_id,
3718 tvb, offset, 1, message,
3719 "Reserved (0xFF)");
3720 } else {
3721 proto_tree_add_item (message_tree, hf_message_mission_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
3723 offset += 1;
3726 /* Security Categories */
3727 if (dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL || dmp_sec_pol == EXTENDED_NATIONAL) {
3728 offset = dissect_dmp_security_category (tvb, pinfo, message_tree, &label_string, offset, 0);
3729 proto_item_append_text (en, ", Security Label: %s", label_string);
3730 tf = proto_tree_add_string (message_tree, hf_message_sec_label, tvb, loffset,
3731 offset - loffset + 1, label_string);
3732 PROTO_ITEM_SET_GENERATED (tf);
3733 } else {
3734 tf = proto_tree_add_item (message_tree, hf_message_sec_cat_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3735 field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
3737 proto_tree_add_item (field_tree, hf_message_sec_cat_bit7, tvb, offset, 1, ENC_BIG_ENDIAN);
3738 proto_tree_add_item (field_tree, hf_message_sec_cat_bit6, tvb, offset, 1, ENC_BIG_ENDIAN);
3739 proto_tree_add_item (field_tree, hf_message_sec_cat_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
3740 proto_tree_add_item (field_tree, hf_message_sec_cat_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
3741 proto_tree_add_item (field_tree, hf_message_sec_cat_bit3, tvb, offset, 1, ENC_BIG_ENDIAN);
3742 proto_tree_add_item (field_tree, hf_message_sec_cat_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
3743 proto_tree_add_item (field_tree, hf_message_sec_cat_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3744 proto_tree_add_item (field_tree, hf_message_sec_cat_bit0, tvb, offset, 1, ENC_BIG_ENDIAN);
3746 offset += 1;
3748 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3749 /* Expiry Time */
3750 exp_time = tvb_get_guint8 (tvb, offset);
3751 tf = proto_tree_add_uint_format (message_tree, hf_message_exp_time,
3752 tvb, offset, 1, exp_time,
3753 "Expiry Time: ");
3754 field_tree = proto_item_add_subtree (tf, ett_message_exp_time);
3755 ei = proto_tree_add_item (field_tree, hf_message_exp_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3756 secs = dmp_dec_exp_time (exp_time);
3757 if (secs == DMP_TIME_NOT_PRESENT) {
3758 proto_item_append_text (tf, "Not present");
3759 proto_item_append_text (ei, " (not present)");
3760 } else if (secs == DMP_TIME_RESERVED) {
3761 proto_item_append_text (tf, "Reserved (0x%2.2x)", exp_time);
3762 proto_item_append_text (ei, " (Reserved)");
3763 } else {
3764 proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
3765 abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE));
3766 proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
3768 offset += 1;
3771 if (dmp.msg_type == STANAG) {
3772 dtg = tvb_get_guint8 (tvb, offset);
3773 tf = proto_tree_add_uint_format (message_tree, hf_message_dtg, tvb, offset, 1, dtg, "DTG: ");
3774 field_tree = proto_item_add_subtree (tf, ett_message_dtg);
3775 proto_tree_add_item (field_tree, hf_message_dtg_sign, tvb, offset, 1, ENC_BIG_ENDIAN);
3776 proto_tree_add_item (field_tree, hf_message_dtg_val, tvb, offset, 1, ENC_BIG_ENDIAN);
3777 secs = dmp_dec_dtg (dtg & 0x7F);
3778 if (secs == DMP_TIME_NOT_PRESENT) {
3779 proto_item_append_text (tf, "Not present");
3780 } else if (secs == DMP_TIME_RESERVED) {
3781 proto_item_append_text (tf, "Reserved (0x%2.2x)", dtg & 0x7F);
3782 } else if (secs == 0) {
3783 proto_item_append_text (tf, "0 minutes in the %s (%s)",
3784 (dtg & 0x80) ? dtg_sign.true_string :
3785 dtg_sign.false_string,
3786 abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
3787 } else {
3788 proto_item_append_text (tf, "%s in the %s (%s)", time_secs_to_str(secs),
3789 (dtg & 0x80) ? dtg_sign.true_string :
3790 dtg_sign.false_string, (dtg & 0x80) ?
3791 abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE) :
3792 abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
3794 offset += 1;
3797 if (dmp.msg_type == STANAG) {
3798 /* SIC */
3799 offset = dissect_dmp_sic (tvb, pinfo, message_tree, offset);
3800 } else if (dmp.msg_type == REPORT || dmp.msg_type == NOTIF) {
3801 if (dmp.version == DMP_VERSION_1 || dmp.msg_id_type == ONLY_DMP_ID) {
3802 /* Subject Message Identifier */
3803 dmp.subj_id = tvb_get_ntohs (tvb, offset);
3804 proto_tree_add_item (message_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3805 hidden_item = proto_tree_add_item (message_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
3806 PROTO_ITEM_SET_HIDDEN (hidden_item);
3807 offset += 2;
3808 } else if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
3809 if (dmp.msg_type == REPORT) {
3810 /* Subject MTS Identifier */
3811 offset = dissect_mts_identifier (tvb, pinfo, message_tree, offset, TRUE);
3812 } else {
3813 /* Subject IPM Identifier */
3814 offset = dissect_ipm_identifier (tvb, pinfo, message_tree, offset, TRUE);
3816 if (dmp.subj_id) {
3817 tf = proto_tree_add_uint (message_tree, hf_message_subj_id, tvb, offset, 0, dmp.subj_id);
3818 PROTO_ITEM_SET_GENERATED (tf);
3819 hidden_item = proto_tree_add_uint (message_tree, hf_dmp_id, tvb, offset, 0, dmp.subj_id);
3820 PROTO_ITEM_SET_GENERATED (hidden_item);
3821 PROTO_ITEM_SET_HIDDEN (hidden_item);
3826 if (use_seq_ack_analysis) {
3827 register_dmp_id (pinfo, 0);
3830 proto_item_set_len (en, offset - boffset);
3832 if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
3833 /* User Data */
3834 offset = dissect_dmp_message (tvb, pinfo, dmp_tree, offset);
3835 } else if (dmp.msg_type == REPORT) {
3836 /* One or more Delivery Report or Non-Delivery Report Data */
3837 rep_len = tvb_length (tvb);
3838 if (dmp.checksum) {
3839 rep_len -= 2;
3841 while (offset < rep_len) {
3842 offset = dissect_dmp_report (tvb, pinfo, dmp_tree, offset, &prev_rec_no, rep_no++);
3844 } else if (dmp.msg_type == NOTIF) {
3845 /* Notification Data */
3846 offset = dissect_dmp_notification (tvb, pinfo, dmp_tree, offset);
3849 return offset;
3852 static gint dissect_dmp_extensions (tvbuff_t *tvb, packet_info *pinfo _U_,
3853 proto_tree *dmp_tree, gint offset)
3855 proto_tree *exts_tree, *ext_tree, *hdr_tree;
3856 proto_item *exts_item, *en;
3857 guint8 ext_hdr, ext_length;
3858 gboolean more_extensions = TRUE;
3859 gint num_ext = 0, boffset = offset;
3861 exts_item = proto_tree_add_item (dmp_tree, hf_extensions, tvb, offset, -1, ENC_NA);
3862 exts_tree = proto_item_add_subtree (exts_item, ett_extensions);
3864 while (more_extensions) {
3865 /* Extensions Present */
3866 ext_hdr = tvb_get_guint8 (tvb, offset);
3867 more_extensions = (ext_hdr & 0x80);
3868 ext_length = (ext_hdr & 0x7F) + 1;
3870 en = proto_tree_add_none_format (exts_tree, hf_extension, tvb, offset, ext_length + 1,
3871 "Extension (#%d)", num_ext + 1);
3872 ext_tree = proto_item_add_subtree (en, ett_extension);
3874 en = proto_tree_add_none_format (ext_tree, hf_extension_header, tvb, offset, 1,
3875 "Extension Length: %u, More %s", ext_length,
3876 (ext_hdr & 0x80) ? "Present" : "Not present");
3877 hdr_tree = proto_item_add_subtree (en, ett_extension_header);
3878 proto_tree_add_item (hdr_tree, hf_extension_more, tvb, offset, 1, ENC_BIG_ENDIAN);
3879 proto_tree_add_item (hdr_tree, hf_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
3880 offset += 1;
3882 proto_tree_add_item (ext_tree, hf_extension_data, tvb, offset, ext_length, ENC_NA);
3883 offset += ext_length;
3884 num_ext++;
3887 proto_item_append_text (exts_item, " (%d item%s)", num_ext, plurality (num_ext, "", "s"));
3888 proto_item_set_len (exts_item, offset - boffset);
3890 return offset;
3893 static void dissect_dmp (tvbuff_t *tvb, packet_info *pinfo,
3894 proto_tree *tree)
3896 proto_tree *dmp_tree = NULL, *checksum_tree = NULL;
3897 proto_item *ti = NULL, *en = NULL;
3898 guint16 checksum1 = 0, checksum2 = 1;
3899 gint length, offset = 0;
3900 gboolean retrans_or_dup_ack = FALSE;
3902 col_set_str (pinfo->cinfo, COL_PROTOCOL, "DMP");
3903 col_clear (pinfo->cinfo, COL_INFO);
3905 /* Initialize global data structure */
3906 memset (&dmp, 0, sizeof (dmp));
3908 ti = proto_tree_add_item (tree, proto_dmp, tvb, offset, -1, ENC_NA);
3909 dmp_tree = proto_item_add_subtree (ti, ett_dmp);
3911 offset = dissect_dmp_envelope (tvb, pinfo, dmp_tree, offset);
3913 if (dmp.version > DMP_VERSION_2) {
3914 /* Unsupported DMP Version, no point to continue */
3915 col_add_fstr (pinfo->cinfo, COL_INFO, "Unsupported Version: %d", dmp.version);
3916 return;
3919 if (dmp.extensions) {
3920 offset = dissect_dmp_extensions (tvb, pinfo, dmp_tree, offset);
3923 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3924 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3926 offset = dissect_dmp_content (tvb, pinfo, dmp_tree, offset);
3927 } else if (dmp.msg_type == ACK) {
3928 offset = dissect_dmp_ack (tvb, pinfo, dmp_tree, offset);
3931 if (dmp.checksum) {
3932 length = tvb_length (tvb);
3933 checksum1 = crc16_x25_ccitt_tvb (tvb, length - 2);
3934 checksum2 = tvb_get_ntohs (tvb, offset);
3936 en = proto_tree_add_item (dmp_tree, hf_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
3937 checksum_tree = proto_item_add_subtree (en, ett_checksum);
3938 if (checksum1 == checksum2) {
3939 proto_item_append_text (en, " (correct)");
3940 en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
3941 offset, 2, TRUE);
3942 PROTO_ITEM_SET_GENERATED (en);
3943 en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
3944 offset, 2, FALSE);
3945 PROTO_ITEM_SET_GENERATED (en);
3946 } else {
3947 proto_item_append_text (en, " (incorrect, should be 0x%04x)",
3948 checksum1);
3949 expert_add_info(pinfo, en, &ei_checksum_bad);
3950 en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
3951 offset, 2, FALSE);
3952 PROTO_ITEM_SET_GENERATED (en);
3953 en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
3954 offset, 2, TRUE);
3955 PROTO_ITEM_SET_GENERATED (en);
3959 if (use_seq_ack_analysis) {
3960 dmp_add_seq_ack_analysis (tvb, pinfo, dmp_tree, offset);
3963 if (((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3964 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) &&
3965 dmp.id_val && dmp.id_val->msg_resend_count)
3967 guint retrans_num;
3968 if (dmp.msg_type == REPORT) {
3969 retrans_num = dmp.id_val->rep_id;
3970 } else if (dmp.msg_type == NOTIF) {
3971 retrans_num = dmp.id_val->not_id;
3972 } else {
3973 retrans_num = dmp.id_val->msg_id;
3975 col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ",
3976 retrans_num, dmp.id_val->msg_resend_count);
3977 retrans_or_dup_ack = TRUE;
3978 } else if (dmp.msg_type == ACK && dmp.id_val && dmp.id_val->ack_resend_count) {
3979 col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ",
3980 dmp.id_val->ack_id, dmp.id_val->ack_resend_count);
3981 retrans_or_dup_ack = TRUE;
3983 if (dmp_align && !retrans_or_dup_ack) {
3984 if (dmp.msg_type == ACK) {
3985 /* ACK does not have "Msg Id" */
3986 col_append_fstr (pinfo->cinfo, COL_INFO, "%-45.45s", msg_type_to_str ());
3987 } else {
3988 col_append_fstr (pinfo->cinfo, COL_INFO, "%-31.31s", msg_type_to_str ());
3990 } else {
3991 col_append_str (pinfo->cinfo, COL_INFO, msg_type_to_str ());
3993 if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
3994 (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
3996 if (dmp_align && !retrans_or_dup_ack) {
3997 col_append_fstr (pinfo->cinfo, COL_INFO, " Msg Id: %5d", dmp.msg_id);
3998 } else {
3999 col_append_fstr (pinfo->cinfo, COL_INFO, ", Msg Id: %d", dmp.msg_id);
4002 if ((dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF) ||
4003 (dmp.msg_type == ACK))
4005 if (dmp_align && !retrans_or_dup_ack) {
4006 col_append_fstr (pinfo->cinfo, COL_INFO, " Subj Id: %5d",
4007 dmp.subj_id);
4008 } else {
4009 col_append_fstr (pinfo->cinfo, COL_INFO, ", Subj Id: %d",
4010 dmp.subj_id);
4012 } else if (dmp.struct_id) {
4013 if (dmp_align && !retrans_or_dup_ack) {
4014 col_append_fstr (pinfo->cinfo, COL_INFO, " Body Id: %s",
4015 format_text (dmp.struct_id, strlen (dmp.struct_id)));
4016 } else {
4017 col_append_fstr (pinfo->cinfo, COL_INFO, ", Body Id: %s",
4018 format_text (dmp.struct_id, strlen (dmp.struct_id)));
4021 if (dmp.checksum && (checksum1 != checksum2)) {
4022 col_append_str (pinfo->cinfo, COL_INFO, ", Checksum incorrect");
4025 proto_item_append_text (ti, ", Version: %d%s, %s", dmp.version,
4026 (dmp.prot_id == PROT_NAT ? " (national)" : ""),
4027 msg_type_to_str());
4030 static void dmp_init_routine (void)
4032 if (dmp_id_hash_table) {
4033 g_hash_table_destroy (dmp_id_hash_table);
4035 if (dmp_long_id_hash_table) {
4036 g_hash_table_destroy (dmp_long_id_hash_table);
4039 dmp_id_hash_table = g_hash_table_new (dmp_id_hash, dmp_id_hash_equal);
4040 dmp_long_id_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
4043 void proto_register_dmp (void)
4045 static hf_register_info hf[] = {
4047 ** DMP Identifier
4049 { &hf_dmp_id,
4050 { "DMP Identifier", "dmp.id", FT_UINT16, BASE_DEC,
4051 NULL, 0x0, NULL, HFILL}},
4053 /* MTS Identifier */
4054 { &hf_mts_id,
4055 { "MTS Identifier", "dmp.mts", FT_STRING, BASE_NONE,
4056 NULL, 0x0, NULL, HFILL } },
4058 /* IPM Identifier */
4059 { &hf_ipm_id,
4060 { "IPM Identifier", "dmp.ipm", FT_STRING, BASE_NONE,
4061 NULL, 0x0, NULL, HFILL } },
4064 ** Envelope
4066 { &hf_envelope,
4067 { "Envelope", "dmp.envelope", FT_NONE, BASE_NONE,
4068 NULL, 0x0, NULL, HFILL}},
4070 /* Protocol data */
4071 { &hf_envelope_protocol_id,
4072 { "Protocol Identifier", "dmp.protocol_id", FT_UINT8,
4073 BASE_HEX, NULL, 0xF8, NULL, HFILL}},
4074 { &hf_envelope_version,
4075 { "Protocol Version", "dmp.version", FT_UINT8, BASE_DEC,
4076 VALS(version_vals), 0x07, NULL, HFILL } },
4077 { &hf_envelope_version_value,
4078 { "Protocol Version", "dmp.version_value", FT_UINT8, BASE_DEC,
4079 VALS(version_vals), 0x07, NULL, HFILL } },
4081 /* Envelope elements (byte 1) */
4082 { &hf_envelope_hop_count,
4083 { "Hop Count", "dmp.hop_count", FT_UINT8, BASE_DEC,
4084 NULL, 0xE0, NULL, HFILL } },
4085 { &hf_envelope_hop_count_value,
4086 { "Hop Count", "dmp.hop_count_value", FT_UINT8, BASE_DEC,
4087 NULL, 0xE0, NULL, HFILL } },
4088 { &hf_envelope_rec_present,
4089 { "Recipient Present", "dmp.rec_present", FT_BOOLEAN, 8,
4090 TFS (&tfs_present_absent), 0x20, NULL, HFILL } },
4091 { &hf_envelope_addr_enc,
4092 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4093 TFS (&addr_enc), 0x10, NULL, HFILL } },
4094 { &hf_envelope_checksum,
4095 { "Checksum", "dmp.checksum_used", FT_BOOLEAN, 8,
4096 TFS (&tfs_used_notused), 0x08, "Checksum Used", HFILL } },
4097 { &hf_envelope_type,
4098 { "Content Type", "dmp.content_type", FT_UINT8, BASE_DEC,
4099 VALS(type_vals), 0x07, NULL, HFILL } },
4101 /* Envelope elements (byte 2) */
4102 { &hf_envelope_extensions,
4103 { "Extensions", "dmp.extensions_used", FT_BOOLEAN, 8,
4104 TFS (&tfs_present_absent), 0x80, "Extensions Used", HFILL } },
4105 { &hf_envelope_msg_id_type,
4106 { "Message Identifier Type", "dmp.msg_id_type", FT_UINT8, BASE_DEC,
4107 VALS(msg_id_type_vals), 0x60, NULL, HFILL } },
4108 { &hf_envelope_msg_id_length,
4109 { "Message Identifier Length", "dmp.msg_id_short", FT_UINT8, BASE_DEC,
4110 VALS(msg_id_length_vals), 0x10, NULL, HFILL}},
4111 { &hf_envelope_mts_id_length,
4112 { "MTS Identifier Length", "dmp.mts_id_length", FT_UINT8, BASE_DEC,
4113 NULL, 0x1F, NULL, HFILL } },
4114 { &hf_envelope_ipm_id_modifier,
4115 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4116 VALS(ipm_id_modifier), 0xC0, NULL, HFILL } },
4117 { &hf_envelope_ipm_id_length,
4118 { "IPM Identifier Length", "dmp.ipm_id_length", FT_UINT8, BASE_DEC,
4119 NULL, 0x3F, NULL, HFILL } },
4121 { &hf_thales_ipm_id_modifier,
4122 { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
4123 VALS(thales_ipm_id_modifier), 0xC0, "Thales XOmail IPM Identifier Modifier", HFILL } },
4125 /* Message identifier */
4126 { &hf_envelope_msg_id,
4127 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4128 NULL, 0x0, NULL, HFILL}},
4129 { &hf_envelope_msg_id_12bit,
4130 { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
4131 NULL, 0x0FFF, NULL, HFILL}},
4133 /* MTS Identifier */
4134 { &hf_envelope_mts_id,
4135 { "MTS Identifier", "dmp.mts_id", FT_STRING, BASE_NONE,
4136 NULL, 0x0, NULL, HFILL } },
4138 /* IPM Identifier */
4139 { &hf_envelope_ipm_id,
4140 { "IPM Identifier", "dmp.ipm_id", FT_STRING, BASE_NONE,
4141 NULL, 0x0, NULL, HFILL } },
4143 /* Extensions */
4144 { &hf_extensions,
4145 { "Extensions", "dmp.extensions", FT_NONE, BASE_NONE,
4146 NULL, 0x0, NULL, HFILL}},
4147 { &hf_extension,
4148 { "Extension", "dmp.extension", FT_NONE, BASE_NONE,
4149 NULL, 0x0, NULL, HFILL } },
4150 { &hf_extension_header,
4151 { "Extension Header", "dmp.extension_header", FT_NONE, BASE_NONE,
4152 NULL, 0x0, NULL, HFILL}},
4153 { &hf_extension_more,
4154 { "More Extensions", "dmp.extension_more", FT_BOOLEAN, 8,
4155 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4156 { &hf_extension_length,
4157 { "Extension Length (minus one)", "dmp.extension_length", FT_UINT8, BASE_DEC,
4158 NULL, 0x7F, "Extension Length minus one", HFILL } },
4159 { &hf_extension_data,
4160 { "Extension Data", "dmp.extension_data", FT_BYTES, BASE_NONE,
4161 NULL, 0x0, NULL, HFILL } },
4163 /* Submission time */
4164 { &hf_envelope_subm_time,
4165 { "Submission Time", "dmp.subm_time", FT_UINT16, BASE_HEX,
4166 NULL, 0x0, NULL, HFILL } },
4167 { &hf_envelope_time_diff_present,
4168 { "Time Diff", "dmp.time_diff_present", FT_BOOLEAN, 16,
4169 TFS (&tfs_present_absent), 0x8000, "Time Diff Present", HFILL } },
4170 { &hf_envelope_subm_time_value,
4171 { "Submission Time Value", "dmp.subm_time_value", FT_UINT16,
4172 BASE_HEX, NULL, 0x7FFF, NULL, HFILL } },
4173 { &hf_envelope_time_diff,
4174 { "Time Difference", "dmp.time_diff", FT_UINT8, BASE_HEX,
4175 NULL, 0xFF, NULL, HFILL } },
4176 { &hf_envelope_time_diff_value,
4177 { "Time Difference Value", "dmp.time_diff_value", FT_UINT8,
4178 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4180 /* Envelope flags */
4181 { &hf_envelope_flags,
4182 { "Flags", "dmp.envelope_flags", FT_UINT8, BASE_DEC,
4183 NULL, 0x0, "Envelope Flags", HFILL}},
4184 { &hf_envelope_content_id_discarded,
4185 { "Content Identifier discarded", "dmp.cont_id_discarded",
4186 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
4187 NULL, HFILL } },
4188 { &hf_envelope_recip_reassign_prohib,
4189 { "Recipient reassign prohibited","dmp.recip_reassign_prohib",
4190 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
4191 NULL, HFILL }},
4192 { &hf_envelope_dl_expansion_prohib,
4193 { "DL expansion prohibited", "dmp.dl_expansion_prohib",
4194 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL,
4195 HFILL } },
4197 /* Recipient Count */
4198 { &hf_envelope_recipients,
4199 { "Recipient Count", "dmp.rec_count", FT_UINT8, BASE_DEC,
4200 NULL, 0x1F, NULL, HFILL}},
4201 { &hf_envelope_ext_recipients,
4202 { "Extended Recipient Count", "dmp.ext_rec_count", FT_UINT16,
4203 BASE_DEC, NULL, 0x7FFF, NULL, HFILL}},
4206 ** Address
4208 { &hf_addr_recipient,
4209 { "Recipient Number", "dmp.recipient", FT_NONE, BASE_NONE,
4210 NULL, 0x0, "Recipient", HFILL } },
4211 { &hf_addr_originator,
4212 { "Originator", "dmp.originator", FT_NONE, BASE_NONE,
4213 NULL, 0x0, NULL, HFILL } },
4214 { &hf_addr_reporting_name,
4215 { "Reporting Name Number", "dmp.reporting_name", FT_NONE,
4216 BASE_NONE, NULL, 0x0, "Reporting Name", HFILL } },
4217 { &hf_addr_dl_expanded,
4218 { "DL Expanded", "dmp.dl_expanded", FT_BOOLEAN, BASE_NONE,
4219 NULL, 0x0, "Message has been DL expanded", HFILL } },
4220 { &hf_addr_int_rec,
4221 { "Intended Recipient", "dmp.int_rec", FT_BOOLEAN, BASE_NONE,
4222 NULL, 0x0, "Message has an intended recipient", HFILL } },
4225 ** Address Direct
4227 { &hf_addr_dir_addr_ext,
4228 { "Address Extended", "dmp.addr_ext", FT_BOOLEAN, 8,
4229 NULL, 0x80, NULL, HFILL } },
4230 { &hf_addr_dir_rec_no,
4231 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4232 BASE_DEC, NULL, 0xF0, NULL, HFILL } },
4233 { &hf_addr_dir_rec_no_generated,
4234 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4235 BASE_DEC, NULL, 0x0, "Recipient Number Offset", HFILL } },
4236 { &hf_addr_dir_rec_no1,
4237 { "Recipient Number (bits 3-0)", "dmp.rec_no_offset1", FT_UINT8,
4238 BASE_DEC, NULL, 0xF0, "Recipient Number (bits 3-0) Offset", HFILL } },
4239 { &hf_addr_dir_rec_no2,
4240 { "Recipient Number (bits 9-4)", "dmp.rec_no_offset2", FT_UINT8,
4241 BASE_DEC, NULL, 0x3F, "Recipient Number (bits 9-4) Offset", HFILL } },
4242 { &hf_addr_dir_rec_no3,
4243 { "Recipient Number (bits 14-10)", "dmp.rec_no_offset3", FT_UINT8,
4244 BASE_DEC, NULL, 0x1F, "Recipient Number (bits 14-10) Offset",HFILL } },
4245 { &hf_addr_dir_rep_req1,
4246 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4247 VALS (report_vals_ext), 0x0C, NULL, HFILL } },
4248 { &hf_addr_dir_rep_req2,
4249 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4250 VALS (report_vals_ext), 0xC0, NULL, HFILL } },
4251 { &hf_addr_dir_rep_req3,
4252 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4253 VALS (report_vals), 0xC0, NULL, HFILL } },
4254 { &hf_addr_dir_not_req1,
4255 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4256 VALS (notif_vals_ext), 0x03, NULL, HFILL } },
4257 { &hf_addr_dir_not_req2,
4258 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4259 VALS (notif_vals_ext), 0xC0, NULL, HFILL } },
4260 { &hf_addr_dir_not_req3,
4261 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4262 VALS (notif_vals), 0xC0, NULL, HFILL } },
4263 { &hf_addr_dir_action,
4264 { "Action", "dmp.action", FT_BOOLEAN, 8,
4265 TFS (&tfs_yes_no), 0x80, NULL, HFILL } },
4266 { &hf_addr_dir_address,
4267 { "Direct Address", "dmp.direct_addr", FT_UINT8,
4268 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4269 { &hf_addr_dir_address_generated,
4270 { "Direct Address", "dmp.direct_addr", FT_UINT32,
4271 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4272 { &hf_addr_dir_address1,
4273 { "Direct Address (bits 6-0)", "dmp.direct_addr1", FT_UINT8,
4274 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4275 { &hf_addr_dir_address2,
4276 { "Direct Address (bits 12-7)", "dmp.direct_addr2", FT_UINT8,
4277 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4278 { &hf_addr_dir_address3,
4279 { "Direct Address (bits 18-13)", "dmp.direct_addr3", FT_UINT8,
4280 BASE_DEC, NULL, 0x3F, NULL, HFILL } },
4283 ** Address Extended
4285 { &hf_addr_ext_form,
4286 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4287 VALS (&addr_form), 0xE0, NULL, HFILL } },
4288 { &hf_addr_ext_form_orig_v1,
4289 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4290 VALS (&addr_form_orig_v1), 0xE0, NULL, HFILL } },
4291 { &hf_addr_ext_form_orig,
4292 { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
4293 VALS (&addr_form_orig), 0xE0, NULL, HFILL } },
4294 { &hf_addr_ext_action,
4295 { "Action", "dmp.action", FT_BOOLEAN, 8,
4296 TFS (&tfs_yes_no), 0x10, NULL, HFILL } },
4297 { &hf_addr_ext_rep_req,
4298 { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
4299 VALS (report_vals), 0x0C, NULL, HFILL } },
4300 { &hf_addr_ext_not_req,
4301 { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
4302 VALS (notif_vals), 0x03, NULL, HFILL } },
4303 { &hf_addr_ext_rec_ext,
4304 { "Recipient Number Extended", "dmp.rec_no_ext", FT_BOOLEAN, 8,
4305 NULL, 0x80, NULL, HFILL } },
4306 { &hf_addr_ext_rec_no,
4307 { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
4308 BASE_DEC, NULL, 0x7F, NULL, HFILL } },
4309 { &hf_addr_ext_rec_no_generated,
4310 { "Recipient Number", "dmp.rec_no", FT_UINT32,
4311 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4312 { &hf_addr_ext_rec_no1,
4313 { "Recipient Number (bits 6-0)", "dmp.rec_no_offset1", FT_UINT8,
4314 BASE_DEC, NULL, 0x7F, "Recipient Number (bits 6-0) Offset", HFILL } },
4315 { &hf_addr_ext_rec_no2,
4316 { "Recipient Number (bits 14-7)", "dmp.rec_no_offset2", FT_UINT8,
4317 BASE_DEC, NULL, 0xFF, "Recipient Number (bits 14-7) Offset", HFILL } },
4318 { &hf_addr_ext_address,
4319 { "Extended Address", "dmp.addr_form", FT_NONE, BASE_NONE,
4320 NULL, 0x0, NULL, HFILL } },
4321 { &hf_addr_ext_type,
4322 { "Address Type", "dmp.addr_type", FT_UINT8, BASE_DEC,
4323 VALS (&ext_addr_type), 0xE0, NULL, HFILL } },
4324 { &hf_addr_ext_type_ext,
4325 { "Address Type Extended", "dmp.addr_type_ext", FT_UINT8,
4326 BASE_DEC, VALS (&ext_addr_type_ext), 0xE0, NULL,
4327 HFILL } },
4328 { &hf_addr_ext_length,
4329 { "Address Length", "dmp.addr_length", FT_UINT8,
4330 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4331 { &hf_addr_ext_length_generated,
4332 { "Address Length", "dmp.addr_length", FT_UINT32,
4333 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4334 { &hf_addr_ext_length1,
4335 { "Address Length (bits 4-0)", "dmp.addr_length1", FT_UINT8,
4336 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4337 { &hf_addr_ext_length2,
4338 { "Address Length (bits 9-5)", "dmp.addr_length2", FT_UINT8,
4339 BASE_DEC, NULL, 0x1F, NULL, HFILL } },
4340 { &hf_addr_ext_asn1_ber,
4341 { "ASN.1 BER-encoded OR-name", "dmp.or_name", FT_NONE,
4342 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4343 { &hf_addr_ext_asn1_per,
4344 { "ASN.1 PER-encoded OR-name", "dmp.asn1_per", FT_BYTES,
4345 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4346 { &hf_addr_ext_unknown,
4347 { "Unknown encoded address", "dmp.addr_unknown", FT_BYTES,
4348 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4351 ** Message content
4353 { &hf_message_content,
4354 { "Message Content", "dmp.message", FT_NONE, BASE_NONE,
4355 NULL, 0x0, NULL, HFILL } },
4356 { &hf_report_content,
4357 { "Report Content", "dmp.report", FT_NONE, BASE_NONE,
4358 NULL, 0x0, NULL, HFILL } },
4359 { &hf_notif_content,
4360 { "Notification Content", "dmp.notification", FT_NONE, BASE_NONE,
4361 NULL, 0x0, NULL, HFILL } },
4363 { &hf_message_st_type,
4364 { "Message type", "dmp.msg_type", FT_UINT8, BASE_DEC,
4365 VALS (message_type_vals), 0xC0, NULL, HFILL } },
4366 { &hf_message_precedence,
4367 { "Precedence", "dmp.precedence", FT_UINT8, BASE_DEC,
4368 VALS (precedence), 0x1C, NULL, HFILL } },
4369 { &hf_message_importance,
4370 { "Importance", "dmp.importance", FT_UINT8, BASE_DEC,
4371 VALS (importance), 0x1C, NULL, HFILL } },
4372 { &hf_message_body_format,
4373 { "Body format", "dmp.body_format", FT_UINT8, BASE_DEC,
4374 VALS (body_format_vals), 0x03, NULL, HFILL } },
4376 /* Security Values */
4377 { &hf_message_sec_label,
4378 { "Security Label", "dmp.sec_label", FT_STRING, BASE_NONE,
4379 NULL, 0x0, NULL, HFILL } },
4380 { &hf_message_sec_class_val,
4381 { "Security Classification", "dmp.sec_class", FT_UINT8,
4382 BASE_DEC, NULL, 0xE0, NULL, HFILL}},
4383 { &hf_message_sec_pol,
4384 { "Security Policy", "dmp.sec_pol", FT_UINT8, BASE_DEC,
4385 VALS (sec_pol), 0x1C, NULL, HFILL } },
4386 { &hf_message_heading_flags,
4387 { "Heading Flags", "dmp.heading_flags", FT_NONE, BASE_NONE,
4388 NULL, 0x0, NULL, HFILL } },
4389 { &hf_message_auth_users,
4390 { "Authorizing users discarded", "dmp.auth_discarded",
4391 FT_BOOLEAN, 8, TFS (&tfs_yes_no), 0x02,
4392 NULL, HFILL }},
4393 { &hf_message_subject_disc,
4394 { "Subject discarded", "dmp.subject_discarded", FT_BOOLEAN, 8,
4395 TFS (&tfs_yes_no), 0x01, NULL, HFILL } },
4397 /* National Policy Identifier */
4398 { &hf_message_national_policy_id,
4399 { "National Policy Identifier", "dmp.nat_pol_id", FT_UINT8,
4400 BASE_DEC, VALS(nat_pol_id), 0x0, NULL,
4401 HFILL } },
4403 /* Mission Policy Identifier */
4404 { &hf_message_mission_policy_id,
4405 { "Mission Policy Identifier", "dmp.mission_pol_id", FT_UINT8,
4406 BASE_DEC, NULL, 0x0, NULL,
4407 HFILL } },
4409 /* Security Categories */
4410 { &hf_message_sec_cat_nat,
4411 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4412 NULL, 0x0, NULL, HFILL } },
4413 { &hf_message_sec_cat_val,
4414 { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
4415 NULL, 0x0, NULL, HFILL } },
4416 { &hf_message_sec_cat_cl,
4417 { "Clear", "dmp.sec_cat.cl", FT_BOOLEAN, 8,
4418 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4419 { &hf_message_sec_cat_cs,
4420 { "Crypto Security", "dmp.sec_cat.cs", FT_BOOLEAN, 8,
4421 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4422 { &hf_message_sec_cat_ex,
4423 { "Exclusive", "dmp.sec_cat.ex", FT_BOOLEAN, 8,
4424 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4425 { &hf_message_sec_cat_ne,
4426 { "National Eyes Only", "dmp.sec_cat.ne", FT_BOOLEAN, 8,
4427 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4428 { &hf_message_sec_cat_permissive,
4429 { "Releasable to", "dmp.sec_cat.permissive", FT_UINT8, BASE_HEX,
4430 VALS (nat_pol_id), 0xFC, NULL, HFILL } },
4431 { &hf_message_sec_cat_country_code,
4432 { "Country Code", "dmp.sec_cat.country", FT_UINT8, BASE_DEC,
4433 NULL, 0x00, NULL, HFILL } },
4434 { &hf_message_sec_cat_restrictive,
4435 { "Restrictive", "dmp.sec_cat.restrictive", FT_UINT8, BASE_HEX,
4436 NULL, 0xFC, NULL, HFILL } },
4437 { &hf_message_sec_cat_extended,
4438 { "Extended", "dmp.sec_cat.extended", FT_UINT8, BASE_HEX,
4439 VALS (ext_sec_cat), 0x03, "Extended Security Category", HFILL } },
4440 { &hf_message_sec_cat_bit0,
4441 { "Bit 0", "dmp.sec_cat.bit0", FT_BOOLEAN, 8,
4442 TFS (&tfs_set_notset), 0x01, NULL, HFILL } },
4443 { &hf_message_sec_cat_bit1,
4444 { "Bit 1", "dmp.sec_cat.bit1", FT_BOOLEAN, 8,
4445 TFS (&tfs_set_notset), 0x02, NULL, HFILL } },
4446 { &hf_message_sec_cat_bit2,
4447 { "Bit 2", "dmp.sec_cat.bit2", FT_BOOLEAN, 8,
4448 TFS (&tfs_set_notset), 0x04, NULL, HFILL } },
4449 { &hf_message_sec_cat_bit3,
4450 { "Bit 3", "dmp.sec_cat.bit3", FT_BOOLEAN, 8,
4451 TFS (&tfs_set_notset), 0x08, NULL, HFILL } },
4452 { &hf_message_sec_cat_bit4,
4453 { "Bit 4", "dmp.sec_cat.bit4", FT_BOOLEAN, 8,
4454 TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
4455 { &hf_message_sec_cat_bit5,
4456 { "Bit 5", "dmp.sec_cat.bit5", FT_BOOLEAN, 8,
4457 TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
4458 { &hf_message_sec_cat_bit6,
4459 { "Bit 6", "dmp.sec_cat.bit6", FT_BOOLEAN, 8,
4460 TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
4461 { &hf_message_sec_cat_bit7,
4462 { "Bit 7", "dmp.sec_cat.bit7", FT_BOOLEAN, 8,
4463 TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
4465 /* Expiry Time */
4466 { &hf_message_exp_time,
4467 { "Expiry Time", "dmp.expiry_time", FT_UINT8, BASE_HEX,
4468 NULL, 0x0, NULL, HFILL } },
4469 { &hf_message_exp_time_val,
4470 { "Expiry Time Value", "dmp.expiry_time_val", FT_UINT8, BASE_HEX,
4471 NULL, 0xFF, NULL, HFILL } },
4473 /* DTG */
4474 { &hf_message_dtg,
4475 { "DTG", "dmp.dtg", FT_UINT8, BASE_HEX,
4476 NULL, 0xFF, NULL, HFILL } },
4477 { &hf_message_dtg_sign,
4478 { "DTG in the", "dmp.dtg.sign", FT_BOOLEAN, 8, TFS (&dtg_sign),
4479 0x80, "Sign", HFILL } },
4480 { &hf_message_dtg_val,
4481 { "DTG Value", "dmp.dtg.val", FT_UINT8, BASE_HEX, NULL,
4482 0x7F, NULL, HFILL } },
4484 /* SIC */
4485 { &hf_message_sic,
4486 { "SIC", "dmp.sic", FT_STRING, BASE_NONE,
4487 NULL, 0x0, NULL, HFILL } },
4488 { &hf_message_sic_key,
4489 { "SICs", "dmp.sic_key", FT_NONE, BASE_NONE,
4490 NULL, 0x0, "SIC Content", HFILL } },
4491 { &hf_message_sic_key_values,
4492 { "Content Byte", "dmp.sic_key.values", FT_UINT8, BASE_HEX,
4493 NULL, 0x0, "SIC Content Byte", HFILL } },
4494 { &hf_message_sic_key_type,
4495 { "Type", "dmp.sic_key.type", FT_UINT8, BASE_HEX,
4496 VALS (sic_key_type), 0xF0, "SIC Content Type", HFILL } },
4497 { &hf_message_sic_key_chars,
4498 { "Valid Characters", "dmp.sic_key.chars", FT_BOOLEAN, 8,
4499 TFS (&sic_key_chars), 0x08, "SIC Valid Characters", HFILL } },
4500 { &hf_message_sic_key_num,
4501 { "Number of SICs", "dmp.sic_key.num", FT_UINT8, BASE_HEX,
4502 VALS (sic_key_num), 0x07, NULL, HFILL } },
4503 { &hf_message_sic_bitmap,
4504 { "Length Bitmap (0 = 3 bytes, 1 = 4-8 bytes)", "dmp.sic_bitmap",
4505 FT_UINT8, BASE_HEX, NULL, 0xFF, "SIC Length Bitmap", HFILL } },
4506 { &hf_message_sic_bits,
4507 { "Bit 7-4", "dmp.sic_bits", FT_UINT8, BASE_HEX,
4508 VALS(sic_bit_vals), 0xF0, "SIC Bit 7-4, Characters [A-Z0-9] only",
4509 HFILL } },
4510 { &hf_message_sic_bits_any,
4511 { "Bit 7-4", "dmp.sic_bits_any", FT_UINT8, BASE_HEX,
4512 VALS(sic_bit_any_vals), 0xF0, "SIC Bit 7-4, Any valid characters",
4513 HFILL } },
4515 /* Subject Message Id */
4516 { &hf_message_subj_id,
4517 { "Subject Message Identifier", "dmp.subj_id", FT_UINT16,
4518 BASE_DEC, NULL, 0x0, NULL, HFILL } },
4520 /* Subject MTS Identifier */
4521 { &hf_message_subj_mts_id,
4522 { "Subject MTS Identifier", "dmp.subj_mts_id", FT_STRING, BASE_NONE,
4523 NULL, 0x0, NULL, HFILL } },
4525 /* Subject IPM Identifier */
4526 { &hf_message_subj_ipm_id,
4527 { "Subject IPM Identifier", "dmp.subj_ipm_id", FT_STRING, BASE_NONE,
4528 NULL, 0x0, NULL, HFILL } },
4531 ** Message body
4533 { &hf_message_body,
4534 { "Message Body", "dmp.body", FT_NONE, BASE_NONE, NULL,
4535 0x0, NULL, HFILL}},
4537 /* Body Id */
4538 { &hf_message_eit,
4539 { "EIT", "dmp.body.eit", FT_UINT8, BASE_DEC,
4540 VALS(eit_vals), 0xE0, "Encoded Information Type", HFILL } },
4541 { &hf_message_compr,
4542 { "Compression", "dmp.body.compression", FT_UINT8, BASE_DEC,
4543 VALS(compression_vals), 0x18, NULL, HFILL } },
4545 /* Subject */
4546 { &hf_message_subject,
4547 { "Subject", "dmp.subject", FT_STRINGZ, BASE_NONE,
4548 NULL, 0x0, NULL, HFILL } },
4550 /* Message Body */
4551 { &hf_message_body_data,
4552 { "User data", "dmp.body.data", FT_NONE, BASE_NONE,
4553 NULL, 0x0, NULL, HFILL } },
4554 { &hf_message_body_plain,
4555 { "Message Body", "dmp.body.plain", FT_STRING, BASE_NONE,
4556 NULL, 0x0, NULL, HFILL } },
4557 { &hf_message_bodyid_uint8,
4558 { "Structured Id", "dmp.body.id", FT_UINT8, BASE_DEC,
4559 NULL, 0x0, "Structured Body Id (1 byte)", HFILL } },
4560 { &hf_message_bodyid_uint16,
4561 { "Structured Id", "dmp.body.id", FT_UINT16, BASE_DEC,
4562 NULL, 0x0, "Structured Body Id (2 bytes)", HFILL } },
4563 { &hf_message_bodyid_uint32,
4564 { "Structured Id", "dmp.body.id", FT_UINT32, BASE_DEC,
4565 NULL, 0x0, "Structured Body Id (4 bytes)", HFILL } },
4566 { &hf_message_bodyid_uint64,
4567 { "Structured Id", "dmp.body.id", FT_UINT64, BASE_DEC,
4568 NULL, 0x0, "Structured Body Id (8 bytes)", HFILL } },
4569 { &hf_message_bodyid_string,
4570 { "Structured Id", "dmp.body.id", FT_STRING, BASE_NONE,
4571 NULL, 0x0, "Structured Body Id (fixed text string)", HFILL } },
4572 { &hf_message_bodyid_zstring,
4573 { "Structured Id", "dmp.body.id", FT_STRINGZ, BASE_NONE,
4574 NULL, 0x0, "Structured Body Id (zero terminated text string)",
4575 HFILL } },
4576 { &hf_message_body_structured,
4577 { "Structured Body", "dmp.body.structured", FT_BYTES, BASE_NONE,
4578 NULL, 0x0, NULL, HFILL } },
4579 { &hf_message_body_uncompr,
4580 { "Uncompressed User data", "dmp.body.uncompressed", FT_NONE,
4581 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4582 { &hf_message_body_uncompressed,
4583 { "Uncompressed Message Body", "dmp.body.uncompressed",
4584 FT_STRING, BASE_NONE, NULL, 0x0, NULL,
4585 HFILL } },
4588 ** Report
4590 { &hf_delivery_report,
4591 { "Delivery Report", "dmp.dr", FT_NONE, BASE_NONE, NULL,
4592 0x0, NULL, HFILL}},
4593 { &hf_non_delivery_report,
4594 { "Non-Delivery Report", "dmp.ndr", FT_NONE, BASE_NONE, NULL,
4595 0x0, NULL, HFILL}},
4597 { &hf_report_type,
4598 { "Report Type", "dmp.report_type", FT_BOOLEAN, 8,
4599 TFS (&report_type), 0x80, NULL, HFILL } },
4600 { &hf_report_info_present_dr,
4601 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4602 TFS (&tfs_present_absent), 0x40, NULL, HFILL } },
4603 { &hf_report_addr_enc_dr,
4604 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4605 TFS (&addr_enc), 0x20, NULL, HFILL } },
4606 { &hf_report_del_time,
4607 { "Delivery Time", "dmp.delivery_time", FT_UINT8, BASE_HEX,
4608 NULL, 0x0, NULL, HFILL } },
4609 { &hf_report_del_time_val,
4610 { "Delivery Time Value", "dmp.delivery_time_val", FT_UINT8,
4611 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4612 { &hf_report_addr_enc_ndr,
4613 { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
4614 TFS (&addr_enc), 0x40, NULL, HFILL } },
4615 { &hf_report_reason,
4616 { "Reason (P1)", "dmp.report_reason", FT_UINT8, BASE_DEC,
4617 VALS (p1_NonDeliveryReasonCode_vals), 0x3F,
4618 "Reason", HFILL } },
4619 { &hf_report_info_present_ndr,
4620 { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
4621 TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
4622 { &hf_report_diagn,
4623 { "Diagnostic (P1)", "dmp.report_diagnostic", FT_UINT8, BASE_DEC,
4624 VALS (p1_NonDeliveryDiagnosticCode_vals), 0x7F,
4625 "Diagnostic", HFILL } },
4626 { &hf_report_suppl_info_len,
4627 { "Supplementary Information", "dmp.suppl_info_len", FT_UINT8,
4628 BASE_DEC, NULL, 0x0, "Supplementary Information Length", HFILL } },
4629 { &hf_report_suppl_info,
4630 { "Supplementary Information", "dmp.suppl_info", FT_STRINGZ,
4631 BASE_NONE, NULL, 0x0, NULL, HFILL } },
4634 ** Notification
4636 { &hf_receipt_notif,
4637 { "Receipt Notification (RN)", "dmp.rn", FT_NONE, BASE_NONE,
4638 NULL, 0x0, NULL, HFILL} },
4639 { &hf_non_receipt_notif,
4640 { "Non-Receipt Notification (NRN)", "dmp.nrn", FT_NONE, BASE_NONE,
4641 NULL, 0x0, NULL, HFILL} },
4642 { &hf_other_notif,
4643 { "Other Notification (ON)", "dmp.on", FT_NONE, BASE_NONE,
4644 NULL, 0x0, NULL, HFILL} },
4646 { &hf_notif_type,
4647 { "Notification Type", "dmp.notif_type", FT_UINT8, BASE_DEC,
4648 VALS (notif_type), 0x03, NULL, HFILL } },
4649 { &hf_notif_rec_time,
4650 { "Receipt Time", "dmp.receipt_time", FT_UINT8, BASE_HEX,
4651 NULL, 0x0, NULL, HFILL } },
4652 { &hf_notif_rec_time_val,
4653 { "Receipt Time Value", "dmp.receipt_time_val", FT_UINT8,
4654 BASE_HEX, NULL, 0xFF, NULL, HFILL } },
4655 { &hf_notif_suppl_info_len,
4656 { "Supplementary Information", "dmp.suppl_info_len",
4657 FT_UINT8, BASE_DEC, NULL, 0x0, "Supplementary Information Length",
4658 HFILL } },
4659 { &hf_notif_suppl_info,
4660 { "Supplementary Information", "dmp.suppl_info",
4661 FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL,
4662 HFILL } },
4663 { &hf_notif_non_rec_reason,
4664 { "Non-Receipt Reason", "dmp.notif_non_rec_reason",
4665 FT_UINT8, BASE_DEC, VALS (p22_NonReceiptReasonField_vals), 0x0,
4666 NULL, HFILL } },
4667 { &hf_notif_discard_reason,
4668 { "Discard Reason", "dmp.notif_discard_reason", FT_UINT8,
4669 BASE_DEC, VALS (p22_DiscardReasonField_vals), 0x0,
4670 NULL, HFILL } },
4671 { &hf_notif_on_type,
4672 { "ON Type", "dmp.notif_on_type", FT_UINT8, BASE_DEC,
4673 VALS (on_type), 0x0, NULL, HFILL } },
4674 { &hf_notif_acp127,
4675 { "ACP127 Recipient", "dmp.acp127recip_len", FT_UINT8,
4676 BASE_DEC, NULL, 0x0, "ACP 127 Recipient Length", HFILL } },
4677 { &hf_notif_acp127recip,
4678 { "ACP127 Recipient", "dmp.acp127recip", FT_STRINGZ,
4679 BASE_NONE, NULL, 0x0, "ACP 127 Recipient", HFILL } },
4682 ** Acknowledgement
4684 { &hf_ack,
4685 { "Acknowledgement", "dmp.ack", FT_NONE, BASE_NONE,
4686 NULL, 0x0, NULL, HFILL } },
4687 { &hf_ack_reason,
4688 { "Ack Reason", "dmp.ack_reason", FT_UINT8, BASE_DEC,
4689 VALS (&ack_reason), 0x0, "Reason", HFILL } },
4690 { &hf_ack_diagnostic,
4691 { "Ack Diagnostic", "dmp.ack_diagnostic", FT_UINT8, BASE_DEC,
4692 NULL, 0x0, "Diagnostic", HFILL } },
4693 { &hf_ack_recips,
4694 { "Recipient List", "dmp.ack_rec_list", FT_NONE, BASE_NONE,
4695 NULL, 0x0, NULL, HFILL } },
4698 ** Checksum
4700 { &hf_checksum,
4701 { "Checksum", "dmp.checksum", FT_UINT16, BASE_HEX,
4702 NULL, 0x0, NULL, HFILL } },
4703 { &hf_checksum_good,
4704 { "Good", "dmp.checksum_good", FT_BOOLEAN, BASE_NONE,
4705 NULL, 0x0, "True: checksum matches packet content; False: doesn't match content or not checked", HFILL } },
4706 { &hf_checksum_bad,
4707 { "Bad", "dmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
4708 NULL, 0x0, "True: checksum doesn't match packet content; False: matches content or not checked", HFILL } },
4711 ** Ack matching / Resend
4713 { &hf_analysis_ack_time,
4714 { "Acknowledgement Time", "dmp.analysis.ack_time", FT_RELATIVE_TIME, BASE_NONE,
4715 NULL, 0x0, "The time between the Message and the Acknowledge", HFILL } },
4716 { &hf_analysis_rep_time,
4717 { "Report Reply Time", "dmp.analysis.report_time", FT_RELATIVE_TIME, BASE_NONE,
4718 NULL, 0x0, "The time between the Message and the Report", HFILL } },
4719 { &hf_analysis_not_time,
4720 { "Notification Reply Time", "dmp.analysis.notif_time", FT_RELATIVE_TIME, BASE_NONE,
4721 NULL, 0x0, "The time between the Message and the Notification", HFILL } },
4722 { &hf_analysis_total_time,
4723 { "Total Time", "dmp.analysis.total_time", FT_RELATIVE_TIME, BASE_NONE,
4724 NULL, 0x0, "The time between the first Message and the Acknowledge", HFILL } },
4725 { &hf_analysis_retrans_time,
4726 { "Retransmission Time", "dmp.analysis.retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4727 NULL, 0x0, "The time between the last Message and this Message", HFILL } },
4728 { &hf_analysis_total_retrans_time,
4729 { "Total Retransmission Time", "dmp.analysis.total_retrans_time", FT_RELATIVE_TIME, BASE_NONE,
4730 NULL, 0x0, "The time between the first Message and this Message", HFILL } },
4731 { &hf_analysis_msg_num,
4732 { "Message in", "dmp.analysis.msg_in", FT_FRAMENUM, BASE_NONE,
4733 NULL, 0x0, "This packet has a Message in this frame", HFILL } },
4734 { &hf_analysis_ack_num,
4735 { "Acknowledgement in", "dmp.analysis.ack_in", FT_FRAMENUM, BASE_NONE,
4736 NULL, 0x0, "This packet has an Acknowledgement in this frame", HFILL } },
4737 { &hf_analysis_rep_num,
4738 { "Report in", "dmp.analysis.report_in", FT_FRAMENUM, BASE_NONE,
4739 NULL, 0x0, "This packet has a Report in this frame", HFILL } },
4740 { &hf_analysis_not_num,
4741 { "Notification in", "dmp.analysis.notif_in", FT_FRAMENUM, BASE_NONE,
4742 NULL, 0x0, "This packet has a Notification in this frame", HFILL } },
4743 { &hf_analysis_ack_missing,
4744 { "Acknowledgement missing", "dmp.analysis.ack_missing", FT_NONE, BASE_NONE,
4745 NULL, 0x0, "The acknowledgement for this packet is missing", HFILL } },
4746 { &hf_analysis_retrans_no,
4747 { "Retransmission #", "dmp.analysis.retrans_no", FT_UINT32, BASE_DEC,
4748 NULL, 0x0, "Retransmission count", HFILL } },
4749 { &hf_analysis_ack_dup_no,
4750 { "Duplicate ACK #", "dmp.analysis.dup_ack_no", FT_UINT32, BASE_DEC,
4751 NULL, 0x0, "Duplicate Acknowledgement count", HFILL } },
4752 { &hf_analysis_msg_resend_from,
4753 { "Retransmission of Message sent in", "dmp.analysis.msg_first_sent_in",
4754 FT_FRAMENUM, BASE_NONE,
4755 NULL, 0x0, "This Message was first sent in this frame", HFILL } },
4756 { &hf_analysis_rep_resend_from,
4757 { "Retransmission of Report sent in", "dmp.analysis.report_first_sent_in",
4758 FT_FRAMENUM, BASE_NONE,
4759 NULL, 0x0, "This Report was first sent in this frame", HFILL } },
4760 { &hf_analysis_not_resend_from,
4761 { "Retransmission of Notification sent in", "dmp.analysis.notif_first_sent_in",
4762 FT_FRAMENUM, BASE_NONE,
4763 NULL, 0x0, "This Notification was first sent in this frame", HFILL } },
4764 { &hf_analysis_ack_resend_from,
4765 { "Retransmission of Acknowledgement sent in", "dmp.analysis.ack_first_sent_in",
4766 FT_FRAMENUM, BASE_NONE,
4767 NULL, 0x0, "This Acknowledgement was first sent in this frame", HFILL } },
4770 ** Reserved values
4772 { &hf_reserved_0x01,
4773 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4774 NULL, 0x01, NULL, HFILL } },
4775 { &hf_reserved_0x02,
4776 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4777 NULL, 0x02, NULL, HFILL } },
4778 { &hf_reserved_0x04,
4779 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4780 NULL, 0x04, NULL, HFILL } },
4781 { &hf_reserved_0x07,
4782 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4783 NULL, 0x07, NULL, HFILL } },
4784 { &hf_reserved_0x08,
4785 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4786 NULL, 0x08, NULL, HFILL } },
4787 { &hf_reserved_0x0F,
4788 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4789 NULL, 0x0F, NULL, HFILL } },
4790 { &hf_reserved_0x1F,
4791 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4792 NULL, 0x1F, NULL, HFILL } },
4793 { &hf_reserved_0x20,
4794 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4795 NULL, 0x20, NULL, HFILL } },
4796 { &hf_reserved_0x40,
4797 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4798 NULL, 0x40, NULL, HFILL } },
4799 { &hf_reserved_0xC0,
4800 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4801 NULL, 0xC0, NULL, HFILL } },
4802 { &hf_reserved_0xE0,
4803 { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
4804 NULL, 0xE0, NULL, HFILL } },
4805 { &hf_reserved_0x8000,
4806 { "Reserved", "dmp.reserved", FT_UINT16, BASE_DEC,
4807 NULL, 0x8000, NULL, HFILL } },
4810 static gint *ett[] = {
4811 &ett_dmp,
4812 &ett_envelope,
4813 &ett_envelope_version,
4814 &ett_envelope_hop_count,
4815 &ett_envelope_rec_present,
4816 &ett_envelope_addr_enc,
4817 &ett_envelope_checksum,
4818 &ett_envelope_extensions,
4819 &ett_envelope_msg_id_type,
4820 &ett_envelope_msg_id,
4821 &ett_envelope_mts_id_length,
4822 &ett_envelope_ipm_id_length,
4823 &ett_envelope_cont_type,
4824 &ett_envelope_subm_time,
4825 &ett_envelope_time_diff,
4826 &ett_envelope_flags,
4827 &ett_envelope_recipients,
4828 &ett_envelope_ext_recipients,
4829 &ett_envelope_addresses,
4830 &ett_address,
4831 &ett_address_direct,
4832 &ett_address_rec_no,
4833 &ett_address_extended,
4834 &ett_address_ext_form,
4835 &ett_address_ext_rec_no,
4836 &ett_address_ext_action,
4837 &ett_address_ext_rep_req,
4838 &ett_address_ext_not_req,
4839 &ett_address_ext_type,
4840 &ett_address_ext_length,
4841 &ett_extensions,
4842 &ett_extension,
4843 &ett_extension_header,
4844 &ett_content,
4845 &ett_message,
4846 &ett_message_st_type,
4847 &ett_message_reserved,
4848 &ett_message_precedence,
4849 &ett_message_importance,
4850 &ett_message_body_format,
4851 &ett_message_sec_class,
4852 &ett_message_sec_pol,
4853 &ett_message_sec_cat,
4854 &ett_message_heading_flags,
4855 &ett_message_exp_time,
4856 &ett_message_dtg,
4857 &ett_message_sic,
4858 &ett_message_sic_key,
4859 &ett_message_sic_bitmap,
4860 &ett_message_sic_bits,
4861 &ett_message_eit,
4862 &ett_message_compr,
4863 &ett_message_body_reserved,
4864 &ett_message_body,
4865 &ett_message_body_uncompr,
4866 &ett_report,
4867 &ett_report_type,
4868 &ett_report_info_present_dr,
4869 &ett_report_info_present_ndr,
4870 &ett_report_addr_enc_dr,
4871 &ett_report_addr_enc_ndr,
4872 &ett_report_reserved,
4873 &ett_report_del_time,
4874 &ett_report_reason,
4875 &ett_report_suppl_info,
4876 &ett_report_diagn,
4877 &ett_notif,
4878 &ett_notif_type,
4879 &ett_notif_rec_time,
4880 &ett_notif_suppl_info,
4881 &ett_notif_acp127recip,
4882 &ett_ack,
4883 &ett_ack_recips,
4884 &ett_checksum,
4885 &ett_analysis
4888 static ei_register_info ei[] = {
4889 { &ei_reserved_value, { "dmp.reserved.expert", PI_UNDECODED, PI_WARN, "Reserved value", EXPFILL }},
4890 { &ei_message_sic_illegal, { "dmp.sic.illegal", PI_UNDECODED, PI_NOTE, "Illegal SIC", EXPFILL }},
4891 { &ei_analysis_ack_unexpected, { "dmp.analysis.ack_unexpected", PI_SEQUENCE, PI_NOTE, "Unexpected ACK", EXPFILL }},
4892 { &ei_analysis_ack_missing, { "dmp.analysis.ack_missing.expert", PI_SEQUENCE, PI_NOTE, "Acknowledgement missing", EXPFILL }},
4893 { &ei_analysis_msg_missing, { "dmp.analysis.msg_missing", PI_SEQUENCE, PI_NOTE, "Message missing", EXPFILL }},
4894 { &ei_analysis_retrans_no, { "dmp.analysis.retrans_no.expert", PI_SEQUENCE, PI_NOTE, "Retransmission #", EXPFILL }},
4895 { &ei_analysis_ack_dup_no, { "dmp.analysis.dup_ack_no.expert", PI_SEQUENCE, PI_NOTE, "Dup ACK #", EXPFILL }},
4896 { &ei_addr_dir_rec_no_generated, { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN, "Recipient number too big", EXPFILL }},
4897 { &ei_addr_ext_rec_no_generated, { "dmp.rec_no.expert", PI_MALFORMED, PI_WARN, "Recipient number too big", EXPFILL }},
4898 { &ei_ack_reason, { "dmp.ack_reason.expert", PI_RESPONSE_CODE, PI_NOTE, "ACK reason: %s", EXPFILL }},
4899 { &ei_envelope_version_value, { "dmp.version_value.unsupported", PI_UNDECODED, PI_ERROR, "Unsupported DMP Version", EXPFILL }},
4900 { &ei_envelope_msg_id, { "dmp.msg_id.short_id", PI_PROTOCOL, PI_NOTE, "Id < 4096 - should use ShortId", EXPFILL }},
4901 { &ei_message_compr, { "dmp.body.compression.unknown", PI_UNDECODED, PI_WARN, "Unknown compression algorithm", EXPFILL }},
4902 { &ei_message_body_uncompressed, { "dmp.body.uncompressed.fail", PI_UNDECODED, PI_WARN, "Error: Unable to uncompress content", EXPFILL }},
4903 { &ei_checksum_bad, { "dmp.checksum_bad.expert", PI_CHECKSUM, PI_WARN, "Bad checksum", EXPFILL }},
4906 static uat_field_t attributes_flds[] = {
4907 UAT_FLD_VS(dmp_security_class,nation, "Nation", nat_pol_id, 0),
4908 UAT_FLD_DEC(dmp_security_class,sec_class, "Classification", "Security Classification"),
4909 UAT_FLD_CSTRING(dmp_security_class,name, "Name", "Classification Name"),
4910 UAT_END_FIELDS
4913 uat_t *attributes_uat = uat_new("DMP Security Classifications",
4914 sizeof(dmp_security_class_t),
4915 "dmp_security_classifications",
4916 TRUE,
4917 (void**) &dmp_security_classes,
4918 &num_dmp_security_classes,
4919 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
4920 "ChDMPSecurityClassifications",
4921 dmp_class_copy_cb,
4922 NULL,
4923 dmp_class_free_cb,
4924 NULL,
4925 attributes_flds);
4927 module_t *dmp_module;
4928 expert_module_t* expert_dmp;
4930 proto_dmp = proto_register_protocol (PNAME, PSNAME, PFNAME);
4932 dmp_handle = register_dissector(PFNAME, dissect_dmp, proto_dmp);
4934 proto_register_field_array (proto_dmp, hf, array_length (hf));
4935 proto_register_subtree_array (ett, array_length (ett));
4936 expert_dmp = expert_register_protocol(proto_dmp);
4937 expert_register_field_array(expert_dmp, ei, array_length(ei));
4938 register_init_routine (&dmp_init_routine);
4940 /* Set default UDP ports */
4941 range_convert_str (&global_dmp_port_range, DEFAULT_DMP_PORT_RANGE,
4942 MAX_UDP_PORT);
4944 /* Build national values */
4945 build_national_strings ();
4947 /* Register our configuration options */
4948 dmp_module = prefs_register_protocol (proto_dmp, proto_reg_handoff_dmp);
4950 prefs_register_obsolete_preference (dmp_module, "udp_port");
4951 prefs_register_obsolete_preference (dmp_module, "udp_port_second");
4953 prefs_register_range_preference (dmp_module, "udp_ports",
4954 "DMP port numbers",
4955 "Port numbers used for DMP traffic",
4956 &global_dmp_port_range, MAX_UDP_PORT);
4957 prefs_register_enum_preference (dmp_module, "national_decode",
4958 "National decoding",
4959 "Select the type of decoding for nationally-defined values",
4960 &dmp_nat_decode, national_decoding,
4961 FALSE);
4962 prefs_register_enum_preference (dmp_module, "local_nation",
4963 "Nation of local server",
4964 "Select the nation of sending server. This is used when presenting"
4965 " security classification values in messages with security"
4966 " policy set to National (nation of local server)",
4967 &dmp_local_nation, dmp_national_values,
4968 FALSE);
4969 prefs_register_uat_preference (dmp_module, "classes_table",
4970 "National Security Classifications",
4971 "Translation table for national security classifications. This is used"
4972 " when presenting security classification values in messages with"
4973 " security policy set to National or Extended National",
4974 attributes_uat);
4975 prefs_register_bool_preference (dmp_module, "seq_ack_analysis",
4976 "SEQ/ACK Analysis",
4977 "Calculate sequence/acknowledgement analysis",
4978 &use_seq_ack_analysis);
4979 prefs_register_bool_preference (dmp_module, "align_ids",
4980 "Align identifiers in info list",
4981 "Align identifiers in info list"
4982 " (does not align when retransmission or"
4983 " duplicate acknowledgement indication)",
4984 &dmp_align);
4985 prefs_register_bool_preference (dmp_module, "subject_as_id",
4986 "Print subject as body id",
4987 "Print subject as body id in free text "
4988 "messages with subject",
4989 &dmp_subject_as_id);
4990 prefs_register_enum_preference (dmp_module, "struct_print",
4991 "Structured message id format",
4992 "Format of the structured message id",
4993 &dmp_struct_format, struct_id_options,
4994 FALSE);
4995 prefs_register_uint_preference (dmp_module, "struct_offset",
4996 "Offset to structured message id",
4997 "Used to set where the structured message "
4998 "id starts in the User Data",
4999 10, &dmp_struct_offset);
5001 prefs_register_uint_preference (dmp_module, "struct_length",
5002 "Fixed text string length",
5003 "Used to set length of fixed text string "
5004 "in the structured message id format "
5005 "(maximum 128 characters)",
5006 10, &dmp_struct_length);
5009 void proto_reg_handoff_dmp (void)
5011 static range_t *dmp_port_range;
5012 static gboolean dmp_prefs_initialized = FALSE;
5014 if (!dmp_prefs_initialized) {
5015 dmp_prefs_initialized = TRUE;
5016 } else {
5017 dissector_delete_uint_range ("udp.port", dmp_port_range, dmp_handle);
5018 g_free (dmp_port_range);
5021 /* Save port number for later deletion */
5022 dmp_port_range = range_copy (global_dmp_port_range);
5024 dissector_add_uint_range ("udp.port", dmp_port_range, dmp_handle);
5028 * Editor modelines
5030 * Local Variables:
5031 * c-basic-offset: 2
5032 * tab-width: 8
5033 * indent-tabs-mode: nil
5034 * End:
5036 * ex: set shiftwidth=2 tabstop=8 expandtab:
5037 * :indentSize=2:tabSize=8:noTabs=true: