PageRenderTime 70ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/epan/dissectors/packet-dmp.c

https://github.com/labx-technologies-llc/wireshark
C | 5101 lines | 4232 code | 540 blank | 329 comment | 754 complexity | 84d246a4d8276feb832171e8cb46bcc6 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /* packet-dmp.c
  2. *
  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.
  7. *
  8. * Copyright 2006, Stig Bjorlykke <stig@bjorlykke.org>, Thales Norway AS
  9. *
  10. * $Id$
  11. *
  12. * Wireshark - Network traffic analyzer
  13. * By Gerald Combs <gerald@wireshark.org>
  14. * Copyright 1998 Gerald Combs
  15. *
  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.
  20. *
  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.
  25. *
  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.
  29. *
  30. * Ref: http://jcs.dtic.mil/j6/cceb/acps/acp123/
  31. */
  32. /*
  33. * TODO:
  34. * - Dissect extended Restrictive security categories
  35. * - Add Transmission/Retransmission statistics
  36. */
  37. #include "config.h"
  38. #include <string.h>
  39. #include <math.h>
  40. #include <epan/packet.h>
  41. #include <epan/address.h>
  42. #include <epan/addr_resolv.h>
  43. #include <epan/to_str.h>
  44. #include <epan/prefs.h>
  45. #include <epan/emem.h>
  46. #include <epan/expert.h>
  47. #include <epan/crc16-tvb.h>
  48. #include <epan/asn1.h>
  49. #include <epan/strutil.h>
  50. #include <epan/uat.h>
  51. #include "packet-p1.h"
  52. #include "packet-p22.h"
  53. #define PNAME "Direct Message Profile"
  54. #define PSNAME "DMP"
  55. #define PFNAME "dmp"
  56. /* Default UDP Port Number */
  57. #define DEFAULT_DMP_PORT_RANGE "5031"
  58. /* Protocol Identifier */
  59. #define PROT_NAT 0x0D
  60. #define PROT_DMP 0x1D
  61. /* Versions supported */
  62. #define DMP_VERSION_1 1
  63. #define DMP_VERSION_2 2
  64. /* Message Type (dmp.msg_type) */
  65. #define STANAG 0x0
  66. #define IPM 0x1
  67. #define REPORT 0x2
  68. #define NOTIF 0x3
  69. #define ACK 0x4
  70. /* Message Identifier Type (dmp.msg_id_type) */
  71. #define ONLY_DMP_ID 0x0
  72. #define X400_MSG_ID 0x1
  73. #define NAT_MSG_ID 0x2
  74. /* Report Type (dmp.report_type) */
  75. #define DR 0x0
  76. #define NDR 0x1
  77. /* Notification Type (dmp.notif_type) */
  78. #define RN 0x0
  79. #define NRN 0x1
  80. #define ON 0x2
  81. /* Address Encoding (dmp.addr_enc) */
  82. #define DIRECT_ADDR 0x0
  83. #define EXTENDED_ADDR 0x1
  84. /* Address type (internal values) */
  85. #define ORIGINATOR 1
  86. #define P1_ADDRESS 2
  87. #define P2_ADDRESS 3
  88. #define ORIG_P2_ADDRESS 4
  89. /* Extended Address Form (dmp_addr_form) */
  90. #define P1_DIRECT 0x0
  91. #define P2_DIRECT 0x1
  92. #define P1_EXTENDED 0x2
  93. #define P2_EXTENDED 0x3
  94. #define P1_P2_DIRECT 0x4
  95. #define P1_DIRECT_P2_EXTENDED 0x5
  96. #define P1_EXTENDED_P2_DIRECT 0x6
  97. #define P1_P2_EXTENDED 0x7
  98. /* Extended Address Type */
  99. #define ASN1_BER 0x0
  100. #define ASN1_PER 0x1
  101. /* Security Policy (dmp_sec_pol) */
  102. #define NATO 0x4
  103. #define NATIONAL 0x5
  104. #define EXTENDED_NATIONAL 0x6
  105. #define EXTENDED_MISSION 0x7
  106. #define SEC_CAT_EXT_NONE 0x0
  107. #define SEC_CAT_EXT_PERMISSIVE 0x1
  108. #define SEC_CAT_EXT_RESTRICTIVE 0x2
  109. /* Body Format (dmp.body_format) */
  110. #define FREE_TEXT 0x0
  111. #define FREE_TEXT_SUBJECT 0x1
  112. #define STRUCTURED 0x2
  113. /* Encoded Information Types */
  114. #define EIT_BILATERAL 0x3
  115. /* Compression Algorithm */
  116. #define ALGORITHM_NONE 0x0
  117. #define ALGORITHM_ZLIB 0x1
  118. /* Type of structured id to print */
  119. #define STRUCT_ID_NONE 0
  120. #define STRUCT_ID_UINT8 1
  121. #define STRUCT_ID_UINT16 2
  122. #define STRUCT_ID_UINT32 3
  123. #define STRUCT_ID_UINT64 4
  124. #define STRUCT_ID_STRING 5
  125. #define STRUCT_ID_ZSTRING 6
  126. #define NAT_DECODE_NONE 0
  127. #define NAT_DECODE_DMP 1
  128. #define NAT_DECODE_THALES 2
  129. #define IPM_MODIFIER_X400 0
  130. /* Internal values for not present and reserved time values */
  131. #define DMP_TIME_NOT_PRESENT -1
  132. #define DMP_TIME_RESERVED -2
  133. #define ILLEGAL_FORMAT "<Illegal format>"
  134. /* Maximum lengths */
  135. #define MAX_SIC_LEN 30
  136. void proto_reg_handoff_dmp (void);
  137. static int proto_dmp = -1;
  138. static int hf_dmp_id = -1;
  139. static int hf_mts_id = -1;
  140. static int hf_ipm_id = -1;
  141. static int hf_envelope = -1;
  142. static int hf_envelope_protocol_id = -1;
  143. static int hf_envelope_version = -1;
  144. static int hf_envelope_version_value = -1;
  145. static int hf_envelope_hop_count = -1;
  146. static int hf_envelope_hop_count_value = -1;
  147. static int hf_envelope_rec_present = -1;
  148. static int hf_envelope_addr_enc = -1;
  149. static int hf_envelope_checksum = -1;
  150. static int hf_envelope_extensions = -1;
  151. static int hf_envelope_msg_id_type = -1;
  152. static int hf_envelope_msg_id_length = -1;
  153. static int hf_envelope_mts_id_length = -1;
  154. static int hf_envelope_ipm_id_modifier = -1;
  155. static int hf_envelope_ipm_id_length = -1;
  156. static int hf_envelope_mts_id = -1;
  157. static int hf_envelope_ipm_id = -1;
  158. static int hf_envelope_type = -1;
  159. static int hf_envelope_msg_id = -1;
  160. static int hf_envelope_msg_id_12bit = -1;
  161. static int hf_envelope_subm_time = -1;
  162. static int hf_envelope_subm_time_value = -1;
  163. static int hf_envelope_time_diff_present = -1;
  164. static int hf_envelope_time_diff = -1;
  165. static int hf_envelope_time_diff_value = -1;
  166. static int hf_envelope_flags = -1;
  167. static int hf_envelope_content_id_discarded = -1;
  168. static int hf_envelope_recip_reassign_prohib = -1;
  169. static int hf_envelope_dl_expansion_prohib = -1;
  170. static int hf_envelope_recipients = -1;
  171. static int hf_envelope_ext_recipients = -1;
  172. static int hf_thales_ipm_id_modifier = -1;
  173. static int hf_extensions = -1;
  174. static int hf_extension = -1;
  175. static int hf_extension_header = -1;
  176. static int hf_extension_more = -1;
  177. static int hf_extension_length = -1;
  178. static int hf_extension_data = -1;
  179. static int hf_message_content = -1;
  180. static int hf_report_content = -1;
  181. static int hf_notif_content = -1;
  182. static int hf_addr_recipient = -1;
  183. static int hf_addr_originator = -1;
  184. static int hf_addr_reporting_name = -1;
  185. static int hf_addr_dl_expanded = -1;
  186. static int hf_addr_int_rec = -1;
  187. static int hf_addr_dir_addr_ext = -1;
  188. static int hf_addr_dir_rec_no = -1;
  189. static int hf_addr_dir_rec_no1 = -1;
  190. static int hf_addr_dir_rec_no2 = -1;
  191. static int hf_addr_dir_rec_no3 = -1;
  192. static int hf_addr_dir_rec_no_generated = -1;
  193. static int hf_addr_dir_rep_req1 = -1;
  194. static int hf_addr_dir_rep_req2 = -1;
  195. static int hf_addr_dir_rep_req3 = -1;
  196. static int hf_addr_dir_not_req1 = -1;
  197. static int hf_addr_dir_not_req2 = -1;
  198. static int hf_addr_dir_not_req3 = -1;
  199. static int hf_addr_dir_action = -1;
  200. static int hf_addr_dir_address = -1;
  201. static int hf_addr_dir_address1 = -1;
  202. static int hf_addr_dir_address2 = -1;
  203. static int hf_addr_dir_address3 = -1;
  204. static int hf_addr_dir_address_generated = -1;
  205. static int hf_addr_ext_form = -1;
  206. static int hf_addr_ext_form_orig_v1 = -1;
  207. static int hf_addr_ext_form_orig = -1;
  208. static int hf_addr_ext_action = -1;
  209. static int hf_addr_ext_rep_req = -1;
  210. static int hf_addr_ext_not_req = -1;
  211. static int hf_addr_ext_rec_ext = -1;
  212. static int hf_addr_ext_rec_no = -1;
  213. static int hf_addr_ext_rec_no1 = -1;
  214. static int hf_addr_ext_rec_no2 = -1;
  215. static int hf_addr_ext_rec_no_generated = -1;
  216. static int hf_addr_ext_address = -1;
  217. static int hf_addr_ext_type = -1;
  218. static int hf_addr_ext_type_ext = -1;
  219. static int hf_addr_ext_length = -1;
  220. static int hf_addr_ext_length1 = -1;
  221. static int hf_addr_ext_length2 = -1;
  222. static int hf_addr_ext_length_generated = -1;
  223. static int hf_addr_ext_asn1_ber = -1;
  224. static int hf_addr_ext_asn1_per = -1;
  225. static int hf_addr_ext_unknown = -1;
  226. static int hf_message_body = -1;
  227. static int hf_message_st_type = -1;
  228. static int hf_message_precedence = -1;
  229. static int hf_message_importance = -1;
  230. static int hf_message_body_format = -1;
  231. static int hf_message_sec_class_val = -1;
  232. static int hf_message_sec_pol = -1;
  233. static int hf_message_heading_flags = -1;
  234. static int hf_message_auth_users = -1;
  235. static int hf_message_subject_disc = -1;
  236. static int hf_message_national_policy_id = -1;
  237. static int hf_message_mission_policy_id = -1;
  238. static int hf_message_sec_label = -1;
  239. static int hf_message_sec_cat_nat = -1;
  240. static int hf_message_sec_cat_val = -1;
  241. static int hf_message_sec_cat_cl = -1;
  242. static int hf_message_sec_cat_cs = -1;
  243. static int hf_message_sec_cat_ex = -1;
  244. static int hf_message_sec_cat_ne = -1;
  245. static int hf_message_sec_cat_permissive = -1;
  246. static int hf_message_sec_cat_country_code = -1;
  247. static int hf_message_sec_cat_restrictive = -1;
  248. static int hf_message_sec_cat_extended = -1;
  249. static int hf_message_sec_cat_bit0 = -1;
  250. static int hf_message_sec_cat_bit1 = -1;
  251. static int hf_message_sec_cat_bit2 = -1;
  252. static int hf_message_sec_cat_bit3 = -1;
  253. static int hf_message_sec_cat_bit4 = -1;
  254. static int hf_message_sec_cat_bit5 = -1;
  255. static int hf_message_sec_cat_bit6 = -1;
  256. static int hf_message_sec_cat_bit7 = -1;
  257. static int hf_message_exp_time = -1;
  258. static int hf_message_exp_time_val = -1;
  259. static int hf_message_dtg = -1;
  260. static int hf_message_dtg_sign = -1;
  261. static int hf_message_dtg_val = -1;
  262. static int hf_message_sic = -1;
  263. static int hf_message_sic_key = -1;
  264. static int hf_message_sic_key_values = -1;
  265. static int hf_message_sic_key_type = -1;
  266. static int hf_message_sic_key_chars = -1;
  267. static int hf_message_sic_key_num = -1;
  268. static int hf_message_sic_bitmap = -1;
  269. static int hf_message_sic_bits = -1;
  270. static int hf_message_sic_bits_any = -1;
  271. static int hf_message_subj_id = -1;
  272. static int hf_message_subj_mts_id = -1;
  273. static int hf_message_subj_ipm_id = -1;
  274. static int hf_message_subject = -1;
  275. static int hf_message_eit = -1;
  276. static int hf_message_compr = -1;
  277. static int hf_message_body_data = -1;
  278. static int hf_message_body_plain = -1;
  279. static int hf_message_bodyid_uint8 = -1;
  280. static int hf_message_bodyid_uint16 = -1;
  281. static int hf_message_bodyid_uint32 = -1;
  282. static int hf_message_bodyid_uint64 = -1;
  283. static int hf_message_bodyid_string = -1;
  284. static int hf_message_bodyid_zstring = -1;
  285. static int hf_message_body_structured = -1;
  286. static int hf_message_body_uncompr = -1;
  287. static int hf_message_body_uncompressed = -1;
  288. static int hf_delivery_report = -1;
  289. static int hf_non_delivery_report = -1;
  290. static int hf_report_type = -1;
  291. static int hf_report_info_present_dr = -1;
  292. static int hf_report_addr_enc_dr = -1;
  293. static int hf_report_del_time = -1;
  294. static int hf_report_del_time_val = -1;
  295. static int hf_report_addr_enc_ndr = -1;
  296. static int hf_report_reason = -1;
  297. static int hf_report_info_present_ndr = -1;
  298. static int hf_report_diagn = -1;
  299. static int hf_report_suppl_info_len = -1;
  300. static int hf_report_suppl_info = -1;
  301. static int hf_receipt_notif = -1;
  302. static int hf_non_receipt_notif = -1;
  303. static int hf_other_notif = -1;
  304. static int hf_notif_type = -1;
  305. static int hf_notif_rec_time = -1;
  306. static int hf_notif_rec_time_val = -1;
  307. static int hf_notif_suppl_info_len = -1;
  308. static int hf_notif_suppl_info = -1;
  309. static int hf_notif_non_rec_reason = -1;
  310. static int hf_notif_discard_reason = -1;
  311. static int hf_notif_on_type = -1;
  312. static int hf_notif_acp127 = -1;
  313. static int hf_notif_acp127recip = -1;
  314. static int hf_ack = -1;
  315. static int hf_ack_reason = -1;
  316. static int hf_ack_diagnostic = -1;
  317. static int hf_ack_recips = -1;
  318. static int hf_checksum = -1;
  319. static int hf_checksum_good = -1;
  320. static int hf_checksum_bad = -1;
  321. static int hf_analysis_ack_time = -1;
  322. static int hf_analysis_total_time = -1;
  323. static int hf_analysis_retrans_time = -1;
  324. static int hf_analysis_total_retrans_time = -1;
  325. static int hf_analysis_msg_num = -1;
  326. static int hf_analysis_msg_missing = -1;
  327. static int hf_analysis_retrans_no = -1;
  328. static int hf_analysis_ack_num = -1;
  329. static int hf_analysis_ack_missing = -1;
  330. static int hf_analysis_ack_dup_no = -1;
  331. static int hf_analysis_rep_num = -1;
  332. static int hf_analysis_rep_time = -1;
  333. static int hf_analysis_not_num = -1;
  334. static int hf_analysis_not_time = -1;
  335. static int hf_analysis_msg_resend_from = -1;
  336. static int hf_analysis_rep_resend_from = -1;
  337. static int hf_analysis_not_resend_from = -1;
  338. static int hf_analysis_ack_resend_from = -1;
  339. static int hf_reserved_0x01 = -1;
  340. static int hf_reserved_0x02 = -1;
  341. static int hf_reserved_0x04 = -1;
  342. static int hf_reserved_0x07 = -1;
  343. static int hf_reserved_0x08 = -1;
  344. static int hf_reserved_0x0F = -1;
  345. static int hf_reserved_0x1F = -1;
  346. static int hf_reserved_0x20 = -1;
  347. static int hf_reserved_0x40 = -1;
  348. static int hf_reserved_0xC0 = -1;
  349. static int hf_reserved_0xE0 = -1;
  350. static int hf_reserved_0x8000 = -1;
  351. static gint ett_dmp = -1;
  352. static gint ett_envelope = -1;
  353. static gint ett_envelope_version = -1;
  354. static gint ett_envelope_hop_count = -1;
  355. static gint ett_envelope_rec_present = -1;
  356. static gint ett_envelope_addr_enc = -1;
  357. static gint ett_envelope_checksum = -1;
  358. static gint ett_envelope_extensions = -1;
  359. static gint ett_envelope_msg_id_type = -1;
  360. static gint ett_envelope_msg_id = -1;
  361. static gint ett_envelope_mts_id_length = -1;
  362. static gint ett_envelope_ipm_id_length = -1;
  363. static gint ett_envelope_cont_type = -1;
  364. static gint ett_envelope_subm_time = -1;
  365. static gint ett_envelope_time_diff = -1;
  366. static gint ett_envelope_flags = -1;
  367. static gint ett_envelope_recipients = -1;
  368. static gint ett_envelope_ext_recipients = -1;
  369. static gint ett_envelope_addresses = -1;
  370. static gint ett_address = -1;
  371. static gint ett_address_direct = -1;
  372. static gint ett_address_rec_no = -1;
  373. static gint ett_address_extended = -1;
  374. static gint ett_address_ext_form = -1;
  375. static gint ett_address_ext_rec_no = -1;
  376. static gint ett_address_ext_action = -1;
  377. static gint ett_address_ext_rep_req = -1;
  378. static gint ett_address_ext_not_req = -1;
  379. static gint ett_address_ext_type = -1;
  380. static gint ett_address_ext_length = -1;
  381. static gint ett_extensions = -1;
  382. static gint ett_extension = -1;
  383. static gint ett_extension_header = -1;
  384. static gint ett_content = -1;
  385. static gint ett_message = -1;
  386. static gint ett_message_st_type = -1;
  387. static gint ett_message_reserved = -1;
  388. static gint ett_message_precedence = -1;
  389. static gint ett_message_importance = -1;
  390. static gint ett_message_body_format = -1;
  391. static gint ett_message_sec_class = -1;
  392. static gint ett_message_sec_pol = -1;
  393. static gint ett_message_sec_cat = -1;
  394. static gint ett_message_heading_flags = -1;
  395. static gint ett_message_exp_time = -1;
  396. static gint ett_message_dtg = -1;
  397. static gint ett_message_sic = -1;
  398. static gint ett_message_sic_key = -1;
  399. static gint ett_message_sic_bitmap = -1;
  400. static gint ett_message_sic_bits = -1;
  401. static gint ett_message_eit = -1;
  402. static gint ett_message_compr = -1;
  403. static gint ett_message_body_reserved = -1;
  404. static gint ett_message_body = -1;
  405. static gint ett_message_body_uncompr = -1;
  406. static gint ett_report = -1;
  407. static gint ett_report_type = -1;
  408. static gint ett_report_info_present_dr = -1;
  409. static gint ett_report_info_present_ndr = -1;
  410. static gint ett_report_addr_enc_dr = -1;
  411. static gint ett_report_addr_enc_ndr = -1;
  412. static gint ett_report_reserved = -1;
  413. static gint ett_report_del_time = -1;
  414. static gint ett_report_reason = -1;
  415. static gint ett_report_suppl_info = -1;
  416. static gint ett_report_diagn = -1;
  417. static gint ett_notif = -1;
  418. static gint ett_notif_type = -1;
  419. static gint ett_notif_rec_time = -1;
  420. static gint ett_notif_suppl_info = -1;
  421. static gint ett_notif_acp127recip = -1;
  422. static gint ett_ack = -1;
  423. static gint ett_ack_recips = -1;
  424. static gint ett_checksum = -1;
  425. static gint ett_analysis = -1;
  426. static expert_field ei_reserved_value = EI_INIT;
  427. static expert_field ei_message_sic_illegal = EI_INIT;
  428. static dissector_handle_t dmp_handle;
  429. typedef struct _dmp_id_key {
  430. guint id;
  431. address src;
  432. address dst;
  433. } dmp_id_key;
  434. typedef struct _dmp_id_val {
  435. gint msg_type; /* Message type */
  436. guint prev_msg_id; /* Previous message package num */
  437. guint msg_id; /* Message package num */
  438. guint ack_id; /* Acknowledgement package num */
  439. guint rep_id; /* Report package num */
  440. guint not_id; /* Notification package num */
  441. nstime_t msg_time; /* Message receive time */
  442. nstime_t first_msg_time; /* First message receive time */
  443. nstime_t prev_msg_time; /* Previous message receive time */
  444. nstime_t rep_not_msg_time; /* Report or Notification time */
  445. guint32 msg_resend_count; /* Message resend counter */
  446. guint32 ack_resend_count; /* Acknowledgement resend counter */
  447. } dmp_id_val;
  448. static GHashTable *dmp_id_hash_table = NULL;
  449. static GHashTable *dmp_long_id_hash_table = NULL;
  450. /* Global values used in several functions */
  451. static struct dmp_data {
  452. gint version;
  453. gint prot_id;
  454. gint addr_enc;
  455. gint checksum;
  456. gint msg_type;
  457. gint st_type;
  458. gint prec;
  459. gint body_format;
  460. gint notif_type;
  461. guchar *struct_id;
  462. gint32 subm_time;
  463. guint8 msg_id_type;
  464. guint8 mts_id_length;
  465. proto_item *mts_id_item;
  466. guint8 ack_reason;
  467. guint16 msg_id;
  468. guint16 subj_id;
  469. gboolean extensions;
  470. gboolean dr;
  471. gboolean ndr;
  472. gboolean notif_req;
  473. gboolean ack_rec_present;
  474. dmp_id_val *id_val;
  475. } dmp;
  476. /* User definable values */
  477. static range_t *global_dmp_port_range;
  478. static gint dmp_nat_decode = NAT_DECODE_DMP;
  479. static gint dmp_local_nation = 0;
  480. static gboolean use_seq_ack_analysis = TRUE;
  481. static gboolean dmp_align = FALSE;
  482. static gboolean dmp_subject_as_id = FALSE;
  483. static gint dmp_struct_format = STRUCT_ID_NONE;
  484. static guint dmp_struct_offset = 0;
  485. static guint dmp_struct_length = 1;
  486. typedef struct _dmp_security_class_t {
  487. guint nation;
  488. guint sec_class;
  489. char *name;
  490. } dmp_security_class_t;
  491. static dmp_security_class_t *dmp_security_classes;
  492. static guint num_dmp_security_classes;
  493. static const true_false_string addr_enc = {
  494. "Use Extended Encoding", "Use Direct Encoding"
  495. };
  496. static const true_false_string dtg_sign = {
  497. "Future", "Past"
  498. };
  499. static const true_false_string report_type = {
  500. "Non-Delivery Report", "Delivery Report"
  501. };
  502. static const value_string version_vals[] = {
  503. { 0x0, "1" },
  504. { 0x1, "2" },
  505. { 0x2, "Unknown" },
  506. { 0x3, "Unknown" },
  507. { 0x4, "Unknown" },
  508. { 0x5, "Unknown" },
  509. { 0x6, "Unknown" },
  510. { 0x7, "Unknown" },
  511. { 0, NULL } };
  512. static const value_string type_vals[] = {
  513. { 0x0, "Message" },
  514. { 0x1, "Message (E-Mail)" },
  515. { 0x2, "Report" },
  516. { 0x3, "Notification" },
  517. { 0x4, "Acknowledgement" },
  518. { 0x5, "Unknown Content" },
  519. { 0x6, "Unknown Content" },
  520. { 0x7, "Unknown Content" },
  521. { 0, NULL } };
  522. static const value_string msg_id_type_vals[] = {
  523. { 0x0, "DMP Identifiers only" },
  524. { 0x1, "X.400 Message Identifiers" },
  525. { 0x2, "Nationally-defined" },
  526. { 0x3, "Reserved" },
  527. { 0, NULL } };
  528. static const value_string msg_id_length_vals[] = {
  529. { 0x0, "Full (16 bits)" },
  530. { 0x1, "Short (12 bits)" },
  531. { 0, NULL } };
  532. static const value_string report_vals[] = {
  533. { 0x0, "No Report" },
  534. { 0x1, "Non-Delivery Report" },
  535. { 0x2, "Delivery Report" },
  536. { 0x3, "Reserved" },
  537. { 0, NULL } };
  538. static const value_string report_vals_ext[] = {
  539. { 0x0, "No Report" },
  540. { 0x1, "Non-Delivery Report" },
  541. { 0x2, "Delivery Report" },
  542. { 0x3, "Recipient Number Extended" },
  543. { 0, NULL } };
  544. /* Note the space in front of these values */
  545. static const value_string report_vals_short[] = {
  546. { 0x1, " NDR" },
  547. { 0x2, " DR" },
  548. { 0, NULL } };
  549. static const value_string notif_vals[] = {
  550. { 0x0, "No Notification" },
  551. { 0x1, "Non-Receipt Notification" },
  552. { 0x2, "Receipt Notification" },
  553. { 0x3, "Reserved" },
  554. { 0, NULL } };
  555. static const value_string notif_vals_ext[] = {
  556. { 0x0, "No Notification" },
  557. { 0x1, "Non-Receipt Notification" },
  558. { 0x2, "Receipt Notification" },
  559. { 0x3, "Direct Address Extended" },
  560. { 0, NULL } };
  561. /* Note the space in front of these values */
  562. static const value_string notif_vals_short[] = {
  563. { 0x1, " NRN" },
  564. { 0x2, " RN" },
  565. { 0, NULL } };
  566. static const value_string notif_type [] = {
  567. { 0x0, "Receipt Notification (RN)" },
  568. { 0x1, "Non-Receipt Notification (NRN)" },
  569. { 0x2, "Other Notification (ON)" },
  570. { 0x3, "Unknown Notification" },
  571. { 0, NULL } };
  572. /* Note the space behind these values */
  573. static const value_string addr_type_str [] = {
  574. { ORIGINATOR, "" },
  575. { P1_ADDRESS, "P1 " },
  576. { P2_ADDRESS, "P22/P772 " },
  577. { ORIG_P2_ADDRESS, "P22 " },
  578. { 0, NULL } };
  579. static const value_string addr_form [] = {
  580. { 0x0, "P1 Direct" },
  581. { 0x1, "P22/P772 Direct" },
  582. { 0x2, "P1 Extended" },
  583. { 0x3, "P22/P772 Extended" },
  584. { 0x4, "P1 and P22/P772 Direct" },
  585. { 0x5, "P1 Direct and P22/P772 Extended" },
  586. { 0x6, "P1 Extended and P22/P772 Direct" },
  587. { 0x7, "P1 and P22/P772 Extended" },
  588. { 0, NULL } };
  589. static const value_string addr_form_orig_v1 [] = {
  590. { 0x0, "Direct" },
  591. { 0x1, "Reserved" },
  592. { 0x2, "Extended" },
  593. { 0x3, "Reserved" },
  594. { 0x4, "Reserved" },
  595. { 0x5, "Reserved" },
  596. { 0x6, "Reserved" },
  597. { 0x7, "Reserved" },
  598. { 0, NULL } };
  599. static const value_string addr_form_orig [] = {
  600. { 0x0, "Direct" },
  601. { 0x1, "Reserved" },
  602. { 0x2, "Extended" },
  603. { 0x3, "Reserved" },
  604. { 0x4, "Originator and P2 Direct" },
  605. { 0x5, "Originator Direct and P2 Extended" },
  606. { 0x6, "Originator Extended and P2 Direct" },
  607. { 0x7, "Originator and P2 Extended" },
  608. { 0, NULL } };
  609. static const value_string ext_addr_type [] = {
  610. { 0x0, "ASN.1 BER-encoded OR-name" },
  611. { 0x1, "ASN.1 PER-encoded OR-name" },
  612. { 0x2, "Reserved" },
  613. { 0x3, "Reserved" },
  614. { 0x4, "Reserved" },
  615. { 0x5, "Reserved" },
  616. { 0x6, "Reserved" },
  617. { 0x7, "Address Length Extended" },
  618. { 0, NULL } };
  619. static const value_string ext_addr_type_ext [] = {
  620. { 0x0, "ASN.1 BER-encoded OR-name" },
  621. { 0x1, "ASN.1 PER-encoded OR-name" },
  622. { 0x2, "Reserved" },
  623. { 0x3, "Reserved" },
  624. { 0x4, "Reserved" },
  625. { 0x5, "Reserved" },
  626. { 0x6, "Reserved" },
  627. { 0x7, "Reserved" },
  628. { 0, NULL } };
  629. static const value_string ext_addr_type_short [] = {
  630. { 0x0, "OR-name (BER)" },
  631. { 0x1, "OR-name (PER)" },
  632. { 0x2, "Reserved" },
  633. { 0x3, "Reserved" },
  634. { 0x4, "Reserved" },
  635. { 0x5, "Reserved" },
  636. { 0x6, "Reserved" },
  637. { 0x7, "Reserved" },
  638. { 0, NULL } };
  639. static const value_string message_type_vals[] = {
  640. { 0x0, "Operation" },
  641. { 0x1, "Project" },
  642. { 0x2, "Exercise" },
  643. { 0x3, "Drill" },
  644. { 0, NULL } };
  645. static const value_string precedence[] = {
  646. { 0x0, "Deferred" },
  647. { 0x1, "Routine" },
  648. { 0x2, "Priority" },
  649. { 0x3, "Immediate" },
  650. { 0x4, "Flash" },
  651. { 0x5, "Override" },
  652. { 0x6, "Priority, Info Precedence: Routine" },
  653. { 0x7, "Immediate, Info Precedence: Routine" },
  654. { 0, NULL } };
  655. static const value_string importance[] = {
  656. { 0x0, "Low" },
  657. { 0x1, "Reserved" },
  658. { 0x2, "Normal" },
  659. { 0x3, "Reserved" },
  660. { 0x4, "High" },
  661. { 0x5, "Reserved" },
  662. { 0x6, "Reserved" },
  663. { 0x7, "Reserved" },
  664. { 0, NULL } };
  665. static const value_string sec_class[] = {
  666. { 0x0, "Unmarked" },
  667. { 0x1, "Unclassified" },
  668. /* { 0x2, "Reserved" }, */
  669. { 0x3, "Restricted" },
  670. /* { 0x4, "Reserved" }, */
  671. { 0x5, "Confidential" },
  672. { 0x6, "Secret" },
  673. { 0x7, "Top secret" },
  674. { 0, NULL } };
  675. static const value_string sec_pol[] = {
  676. { 0x0, "Network defined" },
  677. { 0x1, "Network defined" },
  678. { 0x2, "Network defined" },
  679. { 0x3, "Network defined" },
  680. { 0x4, "NATO" },
  681. { 0x5, "National (nation of local server)" },
  682. { 0x6, "Extended, National" },
  683. { 0x7, "Extended, Mission Defined" },
  684. { 0, NULL } };
  685. #define MAX_NATIONAL_VALUES 56
  686. /* Will be built in build_national_strings() */
  687. static value_string nat_pol_id[MAX_NATIONAL_VALUES+1];
  688. /* For name we use the ISO 3166-1 Alfa-3 value for the country,
  689. * for description we use the Country Name and
  690. * for value we use the DMP value for National Policy Identifier.
  691. */
  692. static const enum_val_t dmp_national_values[MAX_NATIONAL_VALUES+1] = {
  693. { "???", "None", 0x00 },
  694. { "alb", "Albania", 0x1B },
  695. { "arm", "Armenia", 0x20 },
  696. { "aut", "Austria", 0x21 },
  697. { "aze", "Azerbaijan", 0x22 },
  698. { "blr", "Belarus", 0x23 },
  699. { "bel", "Belgium", 0x01 },
  700. { "bih", "Bosnia and Hercegowina", 0x24 },
  701. { "bgr", "Bulgaria", 0x02 },
  702. { "can", "Canada", 0x03 },
  703. { "hrv", "Croatia", 0x1C },
  704. { "cze", "Czech Republic", 0x04 },
  705. { "dnk", "Denmark", 0x05 },
  706. { "est", "Estonia", 0x06 },
  707. { "eapc", "Euro-Atlantic Partnership Council (EAPC)", 0x3A },
  708. { "eu", "European Union (EU)", 0x3B },
  709. { "fin", "Finland", 0x25 },
  710. { "mkd", "Former Yugoslav Republic of Macedonia", 0x26 },
  711. { "fra", "France", 0x07 },
  712. { "geo", "Georgia", 0x27 },
  713. { "deu", "Germany", 0x08 },
  714. { "grc", "Greece", 0x09 },
  715. { "hun", "Hungary", 0x0A },
  716. { "isl", "Iceland", 0x0B },
  717. { "isaf", "International Security Assistance Force (ISAF)", 0x3C },
  718. { "irl", "Ireland", 0x28 },
  719. { "ita", "Italy", 0x0C },
  720. { "kaz", "Kazakhstan", 0x29 },
  721. { "kgz", "Kyrgyztan", 0x2A },
  722. { "lva", "Latvia", 0x0D },
  723. { "ltu", "Lithuania", 0x0E },
  724. { "lux", "Luxembourg", 0x0F },
  725. { "mlt", "Malta", 0x2B },
  726. { "mda", "Moldova", 0x2C },
  727. { "mne", "Montenegro", 0x2D },
  728. { "nld", "Netherlands", 0x10 },
  729. { "nor", "Norway", 0x11 },
  730. { "pfp", "Partnership for Peace (PfP)", 0x3D },
  731. { "pol", "Poland", 0x12 },
  732. { "ptr", "Portugal", 0x13 },
  733. { "rou", "Romania", 0x14 },
  734. { "rus", "Russian Federation", 0x2E },
  735. { "srb", "Serbia", 0x2F },
  736. { "svk", "Slovakia", 0x15 },
  737. { "svn", "Slovenia", 0x16 },
  738. { "esp", "Spain", 0x17 },
  739. { "swe", "Sweden", 0x30 },
  740. { "che", "Switzerland", 0x31 },
  741. { "tjk", "Tajikistan", 0x32 },
  742. { "tur", "Turkey", 0x18 },
  743. { "tkm", "Turkmenistan", 0x33 },
  744. { "gbr", "United Kingdom", 0x19 },
  745. { "usa", "United States", 0x1A },
  746. { "ukr", "Ukraine", 0x34 },
  747. { "uzb", "Uzbekistan", 0x35 },
  748. { "weu", "Western European Union (WEU)", 0x3E },
  749. { NULL, NULL, 0 }
  750. };
  751. static const value_string ext_sec_cat[] = {
  752. { 0x0, "Not present" },
  753. { 0x1, "Permissive category follows" },
  754. { 0x2, "Restrictive category follows" },
  755. { 0x3, "Reserved" },
  756. { 0, NULL } };
  757. static const value_string sic_key_type[] = {
  758. { 0xc, "2 or more 3-character SICs" },
  759. { 0xd, "1 or more 3-to-8 character SICs" },
  760. { 0, NULL } };
  761. static const true_false_string sic_key_chars = {
  762. "Any", "[A-Z0-9] only"
  763. };
  764. static const value_string sic_key_num[] = {
  765. { 0, "1" },
  766. { 1, "2" },
  767. { 2, "3" },
  768. { 3, "4" },
  769. { 4, "5" },
  770. { 5, "6" },
  771. { 6, "7" },
  772. { 7, "8" },
  773. { 0, NULL } };
  774. static const value_string sic_bit_vals[] = {
  775. { 0, "length:6, bytes:4" },
  776. { 1, "length:6, bytes:4" },
  777. { 2, "length:6, bytes:4" },
  778. { 3, "length:6, bytes:4" },
  779. { 4, "length:6, bytes:4" },
  780. { 5, "length:6, bytes:4" },
  781. { 6, "length:6, bytes:4" },
  782. { 7, "length:6, bytes:4" },
  783. { 8, "length:6, bytes:4" },
  784. { 9, "reserved" },
  785. { 10, "length:5, bytes:4" },
  786. { 11, "length:8, bytes:6" },
  787. { 12, "length:4, bytes:3" },
  788. { 13, "length:4, bytes:3" },
  789. { 14, "length:7, bytes:5" },
  790. { 15, "length:7, bytes:5" },
  791. { 0, NULL } };
  792. static const value_string sic_bit_any_vals[] = {
  793. { 0, "length:5, bytes:4" },
  794. { 1, "length:5, bytes:4" },
  795. { 2, "length:5, bytes:4" },
  796. { 3, "length:5, bytes:4" },
  797. { 4, "length:5, bytes:4" },
  798. { 5, "length:5, bytes:4" },
  799. { 6, "length:5, bytes:4" },
  800. { 7, "length:5, bytes:4" },
  801. { 8, "length:5, bytes:4" },
  802. { 9, "length:8, bytes:7" },
  803. { 10, "length:4, bytes:4" },
  804. { 11, "length:7, bytes:6" },
  805. { 12, "length:6, bytes:5" },
  806. { 13, "length:6, bytes:5" },
  807. { 14, "length:6, bytes:5" },
  808. { 15, "length:6, bytes:5" },
  809. { 0, NULL } };
  810. static const value_string body_format_vals[] = {
  811. { 0x0, "Free text" },
  812. { 0x1, "Free text including subject" },
  813. { 0x2, "Structured" },
  814. { 0x3, "Reserved" },
  815. { 0, NULL } };
  816. static const value_string eit_vals[] = {
  817. { 0x0, "Empty" },
  818. { 0x1, "IA5-text" },
  819. { 0x2, "General text" },
  820. { 0x3, "Bilaterally defined (binary data)" },
  821. { 0x4, "AdatP-3" },
  822. { 0x5, "Reserved" },
  823. { 0x6, "Reserved" },
  824. { 0x7, "Reserved" },
  825. { 0, NULL } };
  826. static const value_string compression_vals[] = {
  827. { 0x0, "No compression" },
  828. { 0x1, "ZLib compressed" },
  829. { 0x2, "Reserved" },
  830. { 0x3, "Reserved" },
  831. { 0, NULL } };
  832. static const value_string ack_reason [] = {
  833. { 0x00, "Successful, positive acknowledgement" },
  834. { 0x01, "Unspecified error" },
  835. { 0x02, "Checksum incorrect" },
  836. { 0, NULL } };
  837. static const value_string non_del_reason [] = {
  838. { 0x3D, "Unknown reason" },
  839. { 0x3E, "Reason code greater than 0x3c (60)" },
  840. { 0x3F, "Reserved" },
  841. { 0, NULL } };
  842. static const value_string non_del_diagn [] = {
  843. { 0x7C, "Diagnostic not specified" },
  844. { 0x7D, "Unknown diagnostic" },
  845. { 0x7E, "Diagnostic code greater than 0x7b (123)" },
  846. { 0x7F, "Reserved" },
  847. { 0, NULL } };
  848. static const value_string discard_reason [] = {
  849. { 0xFE, "Discard Reason absent" },
  850. { 0xFF, "Reserved" },
  851. { 0, NULL } };
  852. static const value_string on_type [] = {
  853. { 0x00, "acp127-nn" },
  854. { 0x01, "acp127-pn" },
  855. { 0x02, "acp127-tn" },
  856. { 0, NULL } };
  857. static const value_string ack_msg_type [] = {
  858. { STANAG, " (message)" },
  859. { IPM, " (e-mail)" },
  860. { REPORT, " (report)" },
  861. { NOTIF, " (notif)" },
  862. { ACK, " (ack)" },
  863. { 0, NULL } };
  864. static const enum_val_t struct_id_options[] = {
  865. { "none", "None", STRUCT_ID_NONE },
  866. { "1byte", "1 Byte value", STRUCT_ID_UINT8 },
  867. { "2byte", "2 Byte value", STRUCT_ID_UINT16 },
  868. { "4byte", "4 Byte value", STRUCT_ID_UINT32 },
  869. { "8byte", "8 Byte value", STRUCT_ID_UINT64 },
  870. { "fstring", "Fixed text string", STRUCT_ID_STRING },
  871. { "zstring", "Zero terminated text string", STRUCT_ID_ZSTRING },
  872. { NULL, NULL, 0 }
  873. };
  874. static const enum_val_t national_decoding[] = {
  875. { "none", "None (raw data)", NAT_DECODE_NONE },
  876. { "dmp", "As for regular", NAT_DECODE_DMP },
  877. { "thales", "Thales XOmail", NAT_DECODE_THALES },
  878. { NULL, NULL, 0 }
  879. };
  880. static const value_string ipm_id_modifier[] = {
  881. { 0x0, "X.400 IPM Identifier" },
  882. { 0x1, "Nationally-defined" },
  883. { 0x2, "Nationally-defined" },
  884. { 0x3, "Nationally-defined" },
  885. { 0, NULL }
  886. };
  887. static const value_string thales_ipm_id_modifier[] = {
  888. { 0x0, "X.400 IPM Identifier" },
  889. { 0x1, "3 or 5 digits" },
  890. { 0x2, "4 digits" },
  891. { 0x3, "5 digits" },
  892. { 0, NULL }
  893. };
  894. UAT_VS_DEF(dmp_security_class, nation, dmp_security_class_t, guint, 0, "None")
  895. UAT_DEC_CB_DEF(dmp_security_class, sec_class, dmp_security_class_t)
  896. UAT_CSTRING_CB_DEF(dmp_security_class, name, dmp_security_class_t)
  897. static void *
  898. dmp_class_copy_cb(void *dest, const void *orig, size_t len _U_)
  899. {
  900. dmp_security_class_t *u = (dmp_security_class_t *)dest;
  901. const dmp_security_class_t *o = (const dmp_security_class_t *)orig;
  902. u->nation = o->nation;
  903. u->sec_class = o->sec_class;
  904. u->name = g_strdup(o->name);
  905. return dest;
  906. }
  907. static void
  908. dmp_class_free_cb(void *r)
  909. {
  910. dmp_security_class_t *u = (dmp_security_class_t *)r;
  911. g_free(u->name);
  912. }
  913. static gchar *dmp_national_sec_class (guint nation, guint dmp_sec_class)
  914. {
  915. guint i;
  916. for (i = 0; i < num_dmp_security_classes; i++) {
  917. dmp_security_class_t *u = &(dmp_security_classes[i]);
  918. if (u->nation == nation && u->sec_class == dmp_sec_class) {
  919. return u->name;
  920. }
  921. }
  922. return NULL;
  923. }
  924. static void build_national_strings (void)
  925. {
  926. gint i = 0;
  927. /*
  928. ** We use values from dmp_national_values to build value_string for nat_pol_id.
  929. */
  930. while (dmp_national_values[i].name && i < MAX_NATIONAL_VALUES) {
  931. nat_pol_id[i].value = dmp_national_values[i].value;
  932. nat_pol_id[i].strptr = dmp_national_values[i].description;
  933. i++;
  934. }
  935. nat_pol_id[i].value = 0;
  936. nat_pol_id[i].strptr = NULL;
  937. }
  938. static const gchar *get_nat_pol_id_short (gint nation)
  939. {
  940. gint i = 0;
  941. while (dmp_national_values[i].name) {
  942. if (dmp_national_values[i].value == nation) {
  943. return dmp_national_values[i].name;
  944. }
  945. i++;
  946. }
  947. return "???";
  948. }
  949. static const gchar *msg_type_to_str (void)
  950. {
  951. const gchar *msg_type;
  952. gboolean have_msg = FALSE;
  953. switch (dmp.msg_type) {
  954. case STANAG:
  955. /* Include message type and precedence */
  956. msg_type = ep_strdup_printf ("%s (%s) [%s]",
  957. val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
  958. val_to_str_const (dmp.st_type, message_type_vals, "Unknown"),
  959. (dmp.prec == 0x6 || dmp.prec == 0x7) ?
  960. val_to_str_const (dmp.prec-4, precedence, "Unknown") :
  961. val_to_str_const (dmp.prec, precedence, "Unknown"));
  962. break;
  963. case IPM:
  964. /* Include importance */
  965. msg_type = ep_strdup_printf ("%s [%s]",
  966. val_to_str_const (dmp.msg_type, type_vals, "Unknown"),
  967. val_to_str_const (dmp.prec, importance, "Unknown"));
  968. break;
  969. case REPORT:
  970. /* Include report types included */
  971. msg_type = ep_strdup_printf ("Report (%s%s%s)",
  972. dmp.dr ? "DR" : "", (dmp.dr && dmp.ndr) ? " and " : "",
  973. dmp.ndr ? "NDR" : "");
  974. break;
  975. case NOTIF:
  976. msg_type = val_to_str_const (dmp.notif_type, notif_type, "Unknown");
  977. break;
  978. case ACK:
  979. /* If we have msg_time we have a matching packet */
  980. have_msg = (dmp.id_val &&
  981. (dmp.id_val->msg_time.secs>0 || dmp.id_val->msg_time.nsecs>0));
  982. msg_type = ep_strdup_printf ( "Acknowledgement%s%s",
  983. have_msg ? val_to_str (dmp.id_val->msg_type, ack_msg_type,
  984. " (unknown:%d)") : "",
  985. dmp.ack_reason ? " [negative]" : "");
  986. break;
  987. default:
  988. msg_type = "Unknown";
  989. break;
  990. }
  991. return msg_type;
  992. }
  993. static const gchar *non_del_reason_str (guint32 value)
  994. {
  995. if (value < 0x3D) {
  996. /* Standard values according to P1 */
  997. return val_to_str_const (value, p1_NonDeliveryReasonCode_vals, "Unknown");
  998. } else {
  999. return val_to_str_const (value, non_del_reason, "Unknown");
  1000. }
  1001. }
  1002. static const gchar *non_del_diagn_str (guint32 value)
  1003. {
  1004. if (value < 0x7C) {
  1005. /* Standard values according to P1 */
  1006. return val_to_str_const (value, p1_NonDeliveryDiagnosticCode_vals, "Unknown");
  1007. } else {
  1008. return val_to_str_const (value, non_del_diagn, "Unknown");
  1009. }
  1010. }
  1011. static const gchar *nrn_reason_str (guint32 value)
  1012. {
  1013. /* Standard values according to P22 */
  1014. return val_to_str_const (value, p22_NonReceiptReasonField_vals, "Reserved");
  1015. }
  1016. static const gchar *discard_reason_str (guint32 value)
  1017. {
  1018. if (value < 0xFE) {
  1019. /* Standard values according to P22 */
  1020. return val_to_str_const (value, p22_DiscardReasonField_vals, "Reserved");
  1021. } else {
  1022. return val_to_str_const (value, discard_reason, "Unknown");
  1023. }
  1024. }
  1025. /* Ref chapter 6.2.8.10 TimeDifference */
  1026. static gint32 dmp_dec_time_diff (guint8 dmp_time_diff)
  1027. {
  1028. gint32 time_diff = 0;
  1029. if (dmp_time_diff <= 0x01) {
  1030. /* Reserved - low value */
  1031. time_diff = DMP_TIME_RESERVED;
  1032. } else if (dmp_time_diff <= 0x1D) {
  1033. /* Number of 2-second units (2-58 seconds) */
  1034. time_diff = dmp_time_diff * 2;
  1035. } else if (dmp_time_diff <= 0x91) {
  1036. /* Number of 15-second units (1 min - 29 min 45 sec) */
  1037. time_diff = (dmp_time_diff - 0x1D + 3) * 15;
  1038. } else if (dmp_time_diff <= 0xDF) {
  1039. /* Number of 5-minute units (30 min - 6 hours 55 min) */
  1040. time_diff = (dmp_time_diff - 0x91 + 5) * 5*60;
  1041. } else if (dmp_time_diff <= 0xF7) {
  1042. /* Number of 30-minute units (7 hours - 18 hours 30 min) */
  1043. time_diff = (dmp_time_diff - 0xDF + 7) * 30*60;
  1044. } else {
  1045. /* Reserved - high value */
  1046. time_diff = DMP_TIME_RESERVED;
  1047. }
  1048. return time_diff;
  1049. }
  1050. /*
  1051. * Ref chapter 6.3.7.2.10 ExpiryTime
  1052. * and chapter 6.3.9.2.2 DeliveryTime
  1053. */
  1054. static gint32 dmp_dec_exp_del_time (guint8 timev, gboolean expiry_time)
  1055. {
  1056. gint32 time_value = 0;
  1057. if (expiry_time && (timev == 0x00)) {
  1058. /* No expiry time */
  1059. time_value = DMP_TIME_NOT_PRESENT;
  1060. } else if (timev <= 0x1D) {
  1061. /* Number of 2-second units (2-58 seconds) */
  1062. time_value = timev * 2;
  1063. } else if (timev <= 0x91) {
  1064. /* Number of 15-second units (1 min - 29 min 45 sec) */
  1065. time_value = (timev - 0x1D + 3) * 15;
  1066. } else if (timev <= 0xBB) {
  1067. /* Number of 5-minute units (30 min - 3 hours 55 min) */
  1068. time_value = (timev - 0x91 + 5) * 5*60;
  1069. } else if (timev <= 0xE3) {
  1070. /* Number of 30-minute units (4 hours - 23 hours 30 min) */
  1071. time_value = (timev - 0xBB + 7) * 30*60;
  1072. } else if (timev < 0xFF) {
  1073. /* Number of 2-hour units (24 - 78 hours) */
  1074. time_value = (timev - 0xE3 + 11) * 2*3600;
  1075. } else {
  1076. /* Reserved */
  1077. time_value = DMP_TIME_RESERVED;
  1078. }
  1079. return time_value;
  1080. }
  1081. static gint32 dmp_dec_exp_time (guint8 expiry_time)
  1082. {
  1083. return dmp_dec_exp_del_time (expiry_time, TRUE);
  1084. }
  1085. static gint32 dmp_dec_del_time (guint8 delivery_time)
  1086. {
  1087. return dmp_dec_exp_del_time (delivery_time, FALSE);
  1088. }
  1089. /* Ref chapter 6.3.7.2.11 DTG */
  1090. static gint32 dmp_dec_dtg (guint32 dtg)
  1091. {
  1092. gint32 value;
  1093. if (dtg == 0x00) {
  1094. /* Not present */
  1095. value = DMP_TIME_NOT_PRESENT;
  1096. } else if (dtg <= 0x3C) {
  1097. /* Number of minutes (0-59 min) */
  1098. value = (dtg - 1) * 60;
  1099. } else if (dtg <= 0x64) {
  1100. /* Number of 15-minute units (1 hour - 10 hours 45 min) */
  1101. value = (dtg - 0x3C + 3) * 15 * 60;
  1102. } else if (dtg < 0x7F) {
  1103. /* Number of hours (11-36 hours) */
  1104. value = (dtg - 0x64 + 10) * 3600;
  1105. } else {
  1106. /* Reserved */
  1107. value = DMP_TIME_RESERVED;
  1108. }
  1109. return value;
  1110. }
  1111. /*
  1112. * Ref chapter 7.10.11.1 Submission time
  1113. *
  1114. * start_time (current time)
  1115. * delta1 = E (encoded submission time)
  1116. * delta2 = C (encoded current time)
  1117. * 0x01C2 = Pn + 15min (maximum point for S1)
  1118. * 0x7E38 = Pn+1 - 15min (minimum point for S3)
  1119. * 0x7FF8 = Pn+1 (length of P (period))
  1120. */
  1121. static gint32 dmp_dec_subm_time (guint16 delta1, gint32 start_time)
  1122. {
  1123. gint32 subm_time = start_time;
  1124. guint16 delta2;
  1125. delta2 = (guint16) ((subm_time / 2) % 0x7FF8);
  1126. if ((delta1 < 0x01C2) && (delta2 >= delta1 + 0x7E38)) {
  1127. subm_time += 2 * (0x7FF8 - delta2 + delta1);
  1128. } else if ((delta1 >= 0x01C2) && (delta2 < delta1 - 0x01C2)) {
  1129. subm_time -= 2 * (0x7FF8 - delta1 + delta2);
  1130. } else {
  1131. subm_time -= 2 * (delta2 - delta1);
  1132. }
  1133. return subm_time;
  1134. }
  1135. /* Ref chapter 6.3.7.2.12 SIC */
  1136. static gboolean dmp_dec_xbyte_sic (guint64 bin, gchar *sic,
  1137. guint8 no_char, gboolean any)
  1138. {
  1139. gboolean failure = FALSE;
  1140. gdouble multiplier;
  1141. guint8 i;
  1142. guint64 p, tmp;
  1143. if (no_char >= MAX_SIC_LEN) {
  1144. /* Illegal length */
  1145. g_snprintf (sic, MAX_SIC_LEN, "Illegal length: %d", no_char);
  1146. return TRUE;
  1147. }
  1148. if (any) {
  1149. multiplier = 74.0;
  1150. } else {
  1151. multiplier = 36.0;
  1152. }
  1153. for (i = 0; i < no_char; i++) {
  1154. p = (guint64) pow (multiplier, no_char - 1 - i);
  1155. tmp = bin / p;
  1156. bin -= tmp * p;
  1157. sic[i] = (gchar) tmp;
  1158. if (sic[i] <= 9) {
  1159. sic[i] += '0';
  1160. } else if (sic[i] <= 35) {
  1161. sic[i] += ('A' - 10);
  1162. } else if (!any) {
  1163. sic[i] = '*';
  1164. failure = TRUE;
  1165. } else if (sic[i] <= 61) {
  1166. sic[i] += ('a' - 36);
  1167. } else if (sic[i] == 62) {
  1168. sic[i] = '\'';
  1169. } else if (sic[i] == 63) {
  1170. sic[i] = '(';
  1171. } else if (sic[i] == 64) {
  1172. sic[i] = ')';
  1173. } else if (sic[i] == 65) {
  1174. sic[i] = '+';
  1175. } else if (sic[i] == 66) {
  1176. sic[i] = ',';
  1177. } else if (sic[i] == 67) {
  1178. sic[i] = '-';
  1179. } else if (sic[i] == 68) {
  1180. sic[i] = '.';
  1181. } else if (sic[i] == 69) {
  1182. sic[i] = '/';
  1183. } else if (sic[i] == 70) {
  1184. sic[i] = ':';
  1185. } else if (sic[i] == 71) {
  1186. sic[i] = '=';
  1187. } else if (sic[i] == 72) {
  1188. sic[i] = '?';
  1189. } else if (sic[i] == 73) {
  1190. sic[i] = ' ';
  1191. } else {
  1192. sic[i] = '*';
  1193. failure = TRUE;
  1194. }
  1195. }
  1196. sic[i] = '\0';
  1197. return failure;
  1198. }
  1199. static guint dmp_id_hash (gconstpointer k)
  1200. {
  1201. dmp_id_key *dmpx=(dmp_id_key *)k;
  1202. return dmpx->id;
  1203. }
  1204. static gint dmp_id_hash_equal (gconstpointer k1, gconstpointer k2)
  1205. {
  1206. dmp_id_key *dmp1=(dmp_id_key *)k1;
  1207. dmp_id_key *dmp2=(dmp_id_key *)k2;
  1208. if (dmp1->id != dmp2->id)
  1209. return 0;
  1210. return (ADDRESSES_EQUAL (&dmp1->src, &dmp2->src) &&
  1211. ADDRESSES_EQUAL (&dmp1->dst, &dmp2->dst));
  1212. }
  1213. static void register_dmp_id (packet_info *pinfo, guint8 reason)
  1214. {
  1215. dmp_id_val *dmp_data = NULL, *pkg_data = NULL;
  1216. dmp_id_key *dmp_key = NULL;
  1217. nstime_t msg_time;
  1218. guint msg_id = 0;
  1219. if (pinfo->flags.in_error_pkt) {
  1220. /* No analysis of error packets */
  1221. return;
  1222. }
  1223. nstime_set_zero(&msg_time);
  1224. dmp_key = se_new (dmp_id_key);
  1225. if (!pinfo->fd->flags.visited &&
  1226. (dmp.msg_type == REPORT || dmp.msg_type == NOTIF))
  1227. {
  1228. /* Try to match corresponding message */
  1229. dmp_key->id = (guint) dmp.subj_id;
  1230. SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
  1231. SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
  1232. dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
  1233. if (dmp_data) {
  1234. /* Found message */
  1235. if (dmp_data->prev_msg_id > 0) {
  1236. msg_id = dmp_data->prev_msg_id;
  1237. } else {
  1238. msg_id = dmp_data->msg_id;
  1239. }
  1240. msg_time = dmp_data->msg_time;
  1241. }
  1242. }
  1243. if (dmp.msg_type == ACK) {
  1244. dmp_key->id = (guint) dmp.subj_id;
  1245. SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->dst));
  1246. SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->src));
  1247. } else {
  1248. dmp_key->id = (guint) dmp.msg_id;
  1249. SE_COPY_ADDRESS(&dmp_key->src, &(pinfo->src));
  1250. SE_COPY_ADDRESS(&dmp_key->dst, &(pinfo->dst));
  1251. }
  1252. dmp_data = (dmp_id_val *) g_hash_table_lookup (dmp_id_hash_table, dmp_key);
  1253. if (!pinfo->fd->flags.visited) {
  1254. if (dmp_data) {
  1255. if (dmp.msg_type == ACK) {
  1256. /* Only save this data if positive ack */
  1257. if (reason == 0) {
  1258. if (dmp_data->ack_id == 0) {
  1259. /* Only save reference to first ACK */
  1260. dmp_data->ack_id = pinfo->fd->num;
  1261. } else {
  1262. /* Only count when resending */
  1263. dmp_data->ack_resend_count++;
  1264. }
  1265. }
  1266. } else {
  1267. /* Message resent */
  1268. dmp_data->msg_resend_count++;
  1269. dmp_data->prev_msg_id = pinfo->fd->num;
  1270. dmp_data->prev_msg_time = dmp_data->msg_time;
  1271. dmp_data->msg_time = pinfo->fd->abs_ts;
  1272. }
  1273. } else {
  1274. /* New message */
  1275. dmp_data = se_new0 (dmp_id_val);
  1276. dmp_data->msg_type = dmp.msg_type;
  1277. if (dmp.msg_type == ACK) {
  1278. /* No matching message for this ack */
  1279. dmp_data->ack_id = pinfo->fd->num;
  1280. } else {
  1281. dmp_data->first_msg_time = pinfo->fd->abs_ts;
  1282. dmp_data->msg_time = pinfo->fd->abs_ts;
  1283. if (dmp.msg_type == REPORT) {
  1284. dmp_data->rep_id = pinfo->fd->num;
  1285. dmp_data->msg_id = msg_id;
  1286. dmp_data->rep_not_msg_time = msg_time;
  1287. } else if (dmp.msg_type == NOTIF) {
  1288. dmp_data->not_id = pinfo->fd->num;
  1289. dmp_data->msg_id = msg_id;
  1290. dmp_data->rep_not_msg_time = msg_time;
  1291. } else {
  1292. dmp_data->msg_id = pinfo->fd->num;
  1293. }
  1294. g_hash_table_insert (dmp_id_hash_table, dmp_key, dmp_data);
  1295. }
  1296. }
  1297. pkg_data = se_new (dmp_id_val);
  1298. *pkg_data = *dmp_data;
  1299. p_add_proto_data (pinfo->fd, proto_dmp, 0, pkg_data);
  1300. } else {
  1301. /* Fetch last values from data saved in packet */
  1302. pkg_data = (dmp_id_val *)p_get_proto_data (pinfo->fd, proto_dmp, 0);
  1303. if (dmp_data && pkg_data && dmp.msg_type != ACK && pkg_data->ack_id == 0) {
  1304. pkg_data->ack_id = dmp_data->ack_id;
  1305. }
  1306. }
  1307. DISSECTOR_ASSERT (pkg_data);
  1308. dmp.id_val = pkg_data;
  1309. }
  1310. static void dmp_add_seq_ack_analysis (tvbuff_t *tvb, packet_info *pinfo,
  1311. proto_tree *dmp_tree, gint offset)
  1312. {
  1313. proto_tree *analysis_tree = NULL;
  1314. proto_item *en = NULL, *eh = NULL;
  1315. nstime_t ns;
  1316. if (dmp.msg_type > ACK || (dmp.msg_type < ACK && !dmp.checksum) ||
  1317. dmp.id_val == NULL || pinfo->flags.in_error_pkt)
  1318. {
  1319. /* No need for seq/ack analysis */
  1320. return;
  1321. }
  1322. en = proto_tree_add_text (dmp_tree, tvb, 0, 0, "SEQ/ACK analysis");
  1323. PROTO_ITEM_SET_GENERATED (en);
  1324. analysis_tree = proto_item_add_subtree (en, ett_analysis);
  1325. if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
  1326. (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) {
  1327. if (dmp.id_val->ack_id) {
  1328. en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_num, tvb,
  1329. 0, 0, dmp.id_val->ack_id);
  1330. PROTO_ITEM_SET_GENERATED (en);
  1331. if (!dmp.checksum) {
  1332. proto_item_append_text (en, " (unexpected)");
  1333. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1334. "Unexpected ACK");
  1335. }
  1336. } else if (dmp.checksum && !dmp.id_val->msg_resend_count) {
  1337. en = proto_tree_add_item (analysis_tree, hf_analysis_ack_missing, tvb, offset, 0, ENC_NA);
  1338. if (pinfo->fd->flags.visited) {
  1339. /* We do not know this on first visit and we do not want to
  1340. add a entry in the "Expert Severity Info" for this note */
  1341. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1342. "Acknowledgement missing");
  1343. PROTO_ITEM_SET_GENERATED (en);
  1344. }
  1345. }
  1346. if (dmp.msg_type == REPORT) {
  1347. if (dmp.id_val->msg_id) {
  1348. en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
  1349. tvb, 0, 0, dmp.id_val->msg_id);
  1350. PROTO_ITEM_SET_GENERATED (en);
  1351. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
  1352. en = proto_tree_add_time (analysis_tree, hf_analysis_rep_time,
  1353. tvb, 0, 0, &ns);
  1354. PROTO_ITEM_SET_GENERATED (en);
  1355. } else {
  1356. en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
  1357. PROTO_ITEM_SET_GENERATED (en);
  1358. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1359. "Message missing");
  1360. }
  1361. } else if (dmp.msg_type == NOTIF) {
  1362. if (dmp.id_val->msg_id) {
  1363. en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
  1364. tvb, 0, 0, dmp.id_val->msg_id);
  1365. PROTO_ITEM_SET_GENERATED (en);
  1366. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->rep_not_msg_time);
  1367. en = proto_tree_add_time (analysis_tree, hf_analysis_not_time,
  1368. tvb, 0, 0, &ns);
  1369. PROTO_ITEM_SET_GENERATED (en);
  1370. } else {
  1371. en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
  1372. PROTO_ITEM_SET_GENERATED (en);
  1373. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1374. "Message missing");
  1375. }
  1376. }
  1377. if (dmp.id_val->msg_resend_count) {
  1378. en = proto_tree_add_uint (analysis_tree, hf_analysis_retrans_no,
  1379. tvb, 0, 0, dmp.id_val->msg_resend_count);
  1380. PROTO_ITEM_SET_GENERATED (en);
  1381. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1382. "Retransmission #%d",
  1383. dmp.id_val->msg_resend_count);
  1384. if (dmp.msg_type == REPORT) {
  1385. en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_resend_from,
  1386. tvb, 0, 0, dmp.id_val->rep_id);
  1387. } else if (dmp.msg_type == NOTIF) {
  1388. en = proto_tree_add_uint (analysis_tree, hf_analysis_not_resend_from,
  1389. tvb, 0, 0, dmp.id_val->not_id);
  1390. } else {
  1391. en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_resend_from,
  1392. tvb, 0, 0, dmp.id_val->msg_id);
  1393. }
  1394. PROTO_ITEM_SET_GENERATED (en);
  1395. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->prev_msg_time);
  1396. en = proto_tree_add_time (analysis_tree, hf_analysis_retrans_time,
  1397. tvb, 0, 0, &ns);
  1398. PROTO_ITEM_SET_GENERATED (en);
  1399. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
  1400. eh = proto_tree_add_time (analysis_tree, hf_analysis_total_retrans_time,
  1401. tvb, 0, 0, &ns);
  1402. PROTO_ITEM_SET_GENERATED (eh);
  1403. if (dmp.id_val->first_msg_time.secs == dmp.id_val->prev_msg_time.secs &&
  1404. dmp.id_val->first_msg_time.nsecs == dmp.id_val->prev_msg_time.nsecs) {
  1405. /* Time values does not differ, hide the total time */
  1406. PROTO_ITEM_SET_HIDDEN (eh);
  1407. }
  1408. }
  1409. } else if (dmp.msg_type == ACK) {
  1410. if (dmp.id_val->msg_type != ACK) {
  1411. if (dmp.id_val->msg_type == REPORT) {
  1412. en = proto_tree_add_uint (analysis_tree, hf_analysis_rep_num,
  1413. tvb, 0, 0, dmp.id_val->rep_id);
  1414. } else if (dmp.id_val->msg_type == NOTIF) {
  1415. en = proto_tree_add_uint (analysis_tree, hf_analysis_not_num,
  1416. tvb, 0, 0, dmp.id_val->not_id);
  1417. } else {
  1418. en = proto_tree_add_uint (analysis_tree, hf_analysis_msg_num,
  1419. tvb, 0, 0, dmp.id_val->msg_id);
  1420. }
  1421. PROTO_ITEM_SET_GENERATED (en);
  1422. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->msg_time);
  1423. en = proto_tree_add_time (analysis_tree, hf_analysis_ack_time,
  1424. tvb, 0, 0, &ns);
  1425. PROTO_ITEM_SET_GENERATED (en);
  1426. nstime_delta (&ns, &pinfo->fd->abs_ts, &dmp.id_val->first_msg_time);
  1427. eh = proto_tree_add_time (analysis_tree, hf_analysis_total_time,
  1428. tvb, 0, 0, &ns);
  1429. PROTO_ITEM_SET_GENERATED (eh);
  1430. if (dmp.id_val->first_msg_time.secs == dmp.id_val->msg_time.secs &&
  1431. dmp.id_val->first_msg_time.nsecs == dmp.id_val->msg_time.nsecs) {
  1432. /* Time values does not differ, hide the total time */
  1433. PROTO_ITEM_SET_HIDDEN (eh);
  1434. } else {
  1435. /* Different times, add a reference to the message we have ack'ed */
  1436. proto_item_append_text (en, " (from frame %d)",
  1437. dmp.id_val->prev_msg_id);
  1438. }
  1439. } else {
  1440. en = proto_tree_add_item (analysis_tree, hf_analysis_msg_missing, tvb, 0, 0, ENC_NA);
  1441. PROTO_ITEM_SET_GENERATED (en);
  1442. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1443. "Message missing");
  1444. }
  1445. if (dmp.id_val->ack_resend_count) {
  1446. en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_dup_no,
  1447. tvb, 0, 0, dmp.id_val->ack_resend_count);
  1448. PROTO_ITEM_SET_GENERATED (en);
  1449. expert_add_info_format (pinfo, en, PI_SEQUENCE, PI_NOTE,
  1450. "Dup ACK #%d", dmp.id_val->ack_resend_count);
  1451. en = proto_tree_add_uint (analysis_tree, hf_analysis_ack_resend_from,
  1452. tvb, 0, 0, dmp.id_val->ack_id);
  1453. PROTO_ITEM_SET_GENERATED (en);
  1454. }
  1455. }
  1456. }
  1457. static gchar *dissect_7bit_string (tvbuff_t *tvb, gint offset, gint length)
  1458. {
  1459. guchar *encoded = tvb_get_ephemeral_string (tvb, offset, length);
  1460. guchar *decoded = (guchar *)ep_alloc0 ((size_t)(length * 1.2) + 1);
  1461. guchar rest = 0, bits = 1;
  1462. gint len = 0, i;
  1463. for (i = 0; i < length; i++) {
  1464. decoded[len++] = encoded[i] >> bits | rest;
  1465. rest = (encoded[i] << (7 - bits) & 0x7F);
  1466. if (bits == 7) {
  1467. decoded[len++] = rest;
  1468. bits = 1;
  1469. rest = 0;
  1470. } else {
  1471. bits++;
  1472. }
  1473. }
  1474. return (gchar *) decoded;
  1475. }
  1476. static const gchar *dissect_thales_mts_id (tvbuff_t *tvb, gint offset, gint length)
  1477. {
  1478. /* Thales XOmail uses this format: "MTA-NAME/000000000000" */
  1479. if (length >= 7 && length <= 22) {
  1480. return ep_strdup_printf ("%s/%08X%04X",
  1481. dissect_7bit_string (tvb, offset, length - 6),
  1482. tvb_get_ntohl (tvb, offset + length - 6),
  1483. tvb_get_ntohs (tvb, offset + length - 2));
  1484. }
  1485. return ILLEGAL_FORMAT;
  1486. }
  1487. static const gchar *dissect_thales_ipm_id (tvbuff_t *tvb, gint offset, gint length, gint modifier)
  1488. {
  1489. /* Thales XOmail uses this format: "<prefix>0000 YYMMDDhhmmssZ" */
  1490. if (length >= 6 && length <= 20 && modifier >= 0 && modifier <= 2) {
  1491. guint number = tvb_get_ntohs (tvb, offset + length - 6);
  1492. guint8 number_len = modifier + 2;
  1493. time_t timev = tvb_get_ntohl(tvb, offset + length - 4);
  1494. struct tm *tmp = gmtime(&timev);
  1495. if (modifier == 1 && number >= 1024) {
  1496. /* The number is in the range 65536-99999 */
  1497. number_len = 5;
  1498. number += (65536 - 1024);
  1499. }
  1500. return ep_strdup_printf ("%s%0*d %02d%02d%02d%02d%02d%02dZ",
  1501. (length == 6) ? "" : dissect_7bit_string (tvb, offset, length - 6),
  1502. number_len, number,
  1503. tmp->tm_year % 100, tmp->tm_mon + 1, tmp->tm_mday,
  1504. tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
  1505. }
  1506. return ILLEGAL_FORMAT;
  1507. }
  1508. /* Ref chapter 6.3.7.2.12 SIC */
  1509. static gint dissect_dmp_sic (tvbuff_t *tvb, packet_info *pinfo,
  1510. proto_tree *message_tree, gint offset)
  1511. {
  1512. proto_tree *sic_tree = NULL, *bitmap_tree = NULL, *key_tree = NULL;
  1513. proto_item *sf = NULL, *bf = NULL, *kf = NULL;
  1514. guint64 value;
  1515. guint8 key, bitmap, no, i, length = 0;
  1516. gboolean any, no_sic = FALSE, failure = FALSE;
  1517. gint bytes = 0, boffset = offset;
  1518. gchar *sic = NULL;
  1519. key = tvb_get_guint8 (tvb, offset);
  1520. sic = (gchar *)ep_alloc (MAX_SIC_LEN);
  1521. if (key <= 0xB6) {
  1522. /* 2 bytes, single 3-character SIC, characters [A-Z0-9] only */
  1523. value = tvb_get_ntohs (tvb, offset);
  1524. failure = dmp_dec_xbyte_sic (value, sic, 3, FALSE);
  1525. sf = proto_tree_add_string_format (message_tree, hf_message_sic, tvb,
  1526. offset, 2, sic,
  1527. "SIC: %s [A-Z0-9 only]%s", sic,
  1528. failure ? " (invalid)": "");
  1529. if (failure) {
  1530. expert_add_info(pinfo, sf, &ei_message_sic_illegal);
  1531. }
  1532. offset += 2;
  1533. } else if (key <= 0xBD) {
  1534. /* 3 bytes, single 3-character SIC, any valid character */
  1535. value = tvb_get_ntohl (tvb, offset);
  1536. value = (value >> 8) & 0x48FFFF;
  1537. failure = dmp_dec_xbyte_sic (value, sic, 3, TRUE);
  1538. sf = proto_tree_add_string_format (message_tree, hf_message_sic, tvb,
  1539. offset, 3, sic,
  1540. "SIC: %s [any character]%s", sic,
  1541. failure ? " (invalid)": "");
  1542. if (failure) {
  1543. expert_add_info(pinfo, sf, &ei_message_sic_illegal);
  1544. }
  1545. offset += 3;
  1546. } else if (key <= 0xBF) {
  1547. /* Reserved (not used) */
  1548. g_snprintf (sic, MAX_SIC_LEN, "Reserved");
  1549. no_sic = TRUE;
  1550. } else if (key <= 0xCF) {
  1551. /* 2 or more 3-character SICs */
  1552. sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
  1553. sic_tree = proto_item_add_subtree (sf, ett_message_sic);
  1554. kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
  1555. key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
  1556. proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  1557. proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
  1558. proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
  1559. offset += 1;
  1560. any = (key & 0x08);
  1561. no = (key & 0x07) + 1;
  1562. for (i = 0; i < no; i++) {
  1563. if (any) {
  1564. value = tvb_get_ntohl (tvb, offset);
  1565. value = (value >> 8) & 0x48FFFF;
  1566. bytes = 3;
  1567. } else {
  1568. value = tvb_get_ntohs (tvb, offset);
  1569. bytes = 2;
  1570. }
  1571. failure = dmp_dec_xbyte_sic (value, sic, 3, any);
  1572. bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
  1573. offset, bytes, sic,
  1574. "SIC %d: %s%s", i + 1, sic,
  1575. failure ? " (invalid)": "");
  1576. if (failure) {
  1577. expert_add_info(pinfo, bf, &ei_message_sic_illegal);
  1578. }
  1579. offset += bytes;
  1580. }
  1581. proto_item_append_text (sf, ": %d (3 %s character)", no,
  1582. any ? "any" : "[A-Z0-9]");
  1583. } else if (key <= 0xDF) {
  1584. /* 1 or more 3 to 8 character SICs */
  1585. sf = proto_tree_add_item (message_tree, hf_message_sic_key, tvb, offset, 1, ENC_NA);
  1586. sic_tree = proto_item_add_subtree (sf, ett_message_sic);
  1587. kf = proto_tree_add_item (sic_tree, hf_message_sic_key_values, tvb, offset, 1, ENC_BIG_ENDIAN);
  1588. key_tree = proto_item_add_subtree (kf, ett_message_sic_key);
  1589. proto_tree_add_item (key_tree, hf_message_sic_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  1590. proto_tree_add_item (key_tree, hf_message_sic_key_chars, tvb, offset, 1, ENC_BIG_ENDIAN);
  1591. proto_tree_add_item (key_tree, hf_message_sic_key_num, tvb, offset, 1, ENC_BIG_ENDIAN);
  1592. offset += 1;
  1593. bitmap = tvb_get_guint8 (tvb, offset);
  1594. bf = proto_tree_add_uint_format (sic_tree, hf_message_sic_bitmap, tvb,
  1595. offset, 1, bitmap,
  1596. "Length Bitmap: 0x%2.2x", bitmap);
  1597. bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bitmap);
  1598. proto_tree_add_item (bitmap_tree, hf_message_sic_bitmap, tvb, offset, 1, ENC_BIG_ENDIAN);
  1599. any = (key & 0x08);
  1600. no = (key & 0x07) + 1;
  1601. offset += 1;
  1602. for (i = 0; i < no; i++) {
  1603. if (bitmap & (1 << (7 - i))) {
  1604. /* 4 - 8 character */
  1605. key = tvb_get_guint8 (tvb, offset);
  1606. if (any) {
  1607. /* Any valid characters */
  1608. if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
  1609. length = 4;
  1610. bytes = 4;
  1611. value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
  1612. } else if ((key & 0xC0) == 0xC0) { /* bit 7-4: 11xx */
  1613. length = 6;
  1614. bytes = 5;
  1615. value = ((guint64)key & 0x3F)<<32|tvb_get_ntohl (tvb, offset + 1);
  1616. } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
  1617. length = 7;
  1618. bytes = 6;
  1619. value = ((guint64)(tvb_get_ntohs (tvb, offset) & 0x0FFF)) << 32 |
  1620. tvb_get_ntohl (tvb, offset + 2);
  1621. } else if ((key & 0xF0) == 0x90) { /* bit 7-4: 1001 */
  1622. length = 8;
  1623. bytes = 7;
  1624. value = ((guint64)((tvb_get_ntohl (tvb, offset)>>8) & 0x0FFF))<<32 |
  1625. tvb_get_ntohl (tvb, offset + 3);
  1626. } else { /* bit 7-4: 0xxx or 1000 */
  1627. length = 5;
  1628. bytes = 4;
  1629. value = tvb_get_ntohl (tvb, offset);
  1630. }
  1631. } else {
  1632. /* Characterts [A-Z0-9] only */
  1633. if ((key & 0xE0) == 0xC0) { /* bit 7-4: 110x */
  1634. length = 4;
  1635. bytes = 3;
  1636. value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x1FFFFF;
  1637. } else if ((key & 0xF0) == 0xA0) { /* bit 7-4: 1010 */
  1638. length = 5;
  1639. bytes = 4;
  1640. value = tvb_get_ntohl (tvb, offset) & 0x0FFFFFFF;
  1641. } else if ((key & 0xE0) == 0xE0) { /* bit 7-4: 111x */
  1642. length = 7;
  1643. bytes = 5;
  1644. value = ((guint64)key & 0x1F)<<32 | tvb_get_ntohl (tvb, offset +1);
  1645. } else if ((key & 0xF0) == 0xB0) { /* bit 7-4: 1011 */
  1646. length = 8;
  1647. bytes = 6;
  1648. value = ((guint64)tvb_get_ntohs (tvb, offset) & 0x0FFF) << 32 |
  1649. tvb_get_ntohl (tvb, offset + 2);
  1650. } else { /* bit 7-4: 0xxx or 1000 */
  1651. length = 6;
  1652. bytes = 4;
  1653. value = tvb_get_ntohl (tvb, offset);
  1654. }
  1655. }
  1656. } else {
  1657. /* 3 character */
  1658. if (any) {
  1659. value = (tvb_get_ntohl (tvb, offset) >> 8) & 0x48FFFF;
  1660. length = 3;
  1661. bytes = 3;
  1662. } else {
  1663. value = tvb_get_ntohs (tvb, offset);
  1664. length = 3;
  1665. bytes = 2;
  1666. }
  1667. }
  1668. failure = dmp_dec_xbyte_sic (value, sic, length, any);
  1669. bf = proto_tree_add_string_format (sic_tree, hf_message_sic, tvb,
  1670. offset, bytes, sic,
  1671. "SIC %d: %s (%d bytes: %" G_GINT64_MODIFIER "x)%s",
  1672. i + 1, sic, bytes, value,
  1673. failure ? " (invalid)": "");
  1674. if (bitmap & (1 << (7 - i))) {
  1675. /* Only if 4 - 8 character */
  1676. bitmap_tree = proto_item_add_subtree (bf, ett_message_sic_bits);
  1677. if (any) {
  1678. proto_tree_add_item (bitmap_tree, hf_message_sic_bits_any, tvb, offset, 1, ENC_BIG_ENDIAN);
  1679. } else {
  1680. proto_tree_add_item (bitmap_tree, hf_message_sic_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
  1681. }
  1682. }
  1683. if (failure) {
  1684. expert_add_info(pinfo, bf, &ei_message_sic_illegal);
  1685. }
  1686. offset += bytes;
  1687. }
  1688. proto_item_append_text (sf, ": %d (3-to-8 %s character)", no,
  1689. any ? "any" : "[A-Z0-9]");
  1690. } else if (key == 0xFE) {
  1691. /* No SIC */
  1692. g_snprintf (sic, MAX_SIC_LEN, "Not present");
  1693. no_sic = TRUE;
  1694. } else {
  1695. /* Resered (not used) */
  1696. g_snprintf (sic, MAX_SIC_LEN, "Reserved");
  1697. no_sic = TRUE;
  1698. }
  1699. if (no_sic) {
  1700. /* Not added any SIC, dump text value */
  1701. sf = proto_tree_add_string (message_tree, hf_message_sic, tvb, offset, 1, sic);
  1702. offset += 1;
  1703. }
  1704. proto_item_set_len (sf, offset - boffset);
  1705. return offset;
  1706. }
  1707. /* Ref chapter 5.2.7.1 Direct Originator Encoding */
  1708. static gint dissect_dmp_direct_addr (tvbuff_t *tvb, packet_info *pinfo,
  1709. proto_tree *field_tree, proto_item *tf,
  1710. gint offset, gint rec_no,
  1711. gint rec_ofs, gint addr_type)
  1712. {
  1713. proto_tree *addr_tree = NULL;
  1714. proto_item *en = NULL;
  1715. gint dir_addr;
  1716. guint8 value;
  1717. value = tvb_get_guint8 (tvb, offset);
  1718. dir_addr = (value & 0x7F);
  1719. if (value & 0x80) {
  1720. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1, tvb,
  1721. offset, 1, value,
  1722. "%sDirect Address (bits 6-0): %d",
  1723. val_to_str_const (addr_type, addr_type_str, ""),
  1724. value & 0x7F);
  1725. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  1726. proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
  1727. proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
  1728. offset += 1;
  1729. /* Extended 1 */
  1730. value = tvb_get_guint8 (tvb, offset);
  1731. dir_addr |= ((value & 0x3F) << 7);
  1732. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
  1733. offset, 1, value,
  1734. "%sDirect Address (bits 12-7): %d",
  1735. val_to_str_const (addr_type, addr_type_str, ""),
  1736. value & 0x3F);
  1737. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  1738. proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
  1739. en = proto_tree_add_item (addr_tree, hf_reserved_0x40, tvb, offset, 1, ENC_BIG_ENDIAN);
  1740. if (value & 0x40) {
  1741. expert_add_info(pinfo, en, &ei_reserved_value);
  1742. }
  1743. proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
  1744. offset += 1;
  1745. if (value & 0x80) {
  1746. /* Extended 2 */
  1747. value = tvb_get_guint8 (tvb, offset);
  1748. dir_addr |= ((value & 0x3F) << 13);
  1749. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
  1750. offset, 1, value,
  1751. "%sDirect Address (bits 18-13): %d",
  1752. val_to_str_const (addr_type,addr_type_str,""),
  1753. value & 0x3F);
  1754. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  1755. en = proto_tree_add_item (addr_tree, hf_reserved_0xC0, tvb, offset, 1, ENC_BIG_ENDIAN);
  1756. if (value & 0xC0) {
  1757. expert_add_info(pinfo, en, &ei_reserved_value);
  1758. }
  1759. proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
  1760. offset += 1;
  1761. }
  1762. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
  1763. tvb, offset, 0, dir_addr,
  1764. "%sDirect Address: %d",
  1765. val_to_str_const (addr_type, addr_type_str, ""),
  1766. dir_addr);
  1767. PROTO_ITEM_SET_GENERATED (en);
  1768. } else {
  1769. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address, tvb,
  1770. offset, 1, value,
  1771. "%sDirect Address: %d",
  1772. val_to_str_const (addr_type, addr_type_str, ""),
  1773. value & 0x7F);
  1774. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  1775. proto_tree_add_item (addr_tree, hf_addr_dir_addr_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
  1776. proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
  1777. offset += 1;
  1778. }
  1779. if (rec_no != -1) {
  1780. proto_item_append_text (tf, " %d", rec_no);
  1781. if (rec_ofs != -1) {
  1782. proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
  1783. }
  1784. }
  1785. proto_item_append_text (tf, ", %sDirect Address: %d",
  1786. val_to_str_const (addr_type, addr_type_str, ""), dir_addr);
  1787. return offset;
  1788. }
  1789. /* Ref 5.3.14 Extended Address */
  1790. static gint dissect_dmp_ext_addr (tvbuff_t *tvb, packet_info *pinfo,
  1791. proto_tree *field_tree, proto_item *tf,
  1792. gint offset, gint rec_no, gint rec_ofs,
  1793. gint addr_type)
  1794. {
  1795. proto_tree *addr_tree = NULL, *ext_tree = NULL;
  1796. proto_item *en = NULL, *ef = NULL;
  1797. gint type, length;
  1798. guint8 value;
  1799. gint boffset = offset;
  1800. gboolean addr_length_extended = FALSE;
  1801. asn1_ctx_t asn1_ctx;
  1802. asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
  1803. value = tvb_get_guint8 (tvb, offset);
  1804. type = (value & 0xE0) >> 5;
  1805. length = (value & 0x1F);
  1806. ef = proto_tree_add_none_format (field_tree, hf_addr_ext_address, tvb,
  1807. offset, -1, "%sExtended Address",
  1808. val_to_str_const (addr_type, addr_type_str, ""));
  1809. ext_tree = proto_item_add_subtree (ef, ett_address_extended);
  1810. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type, tvb,
  1811. offset, 1, value, "Address Type: %s",
  1812. val_to_str_const (type, ext_addr_type,
  1813. "Reserved"));
  1814. addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
  1815. proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  1816. if (value & 0x80) {
  1817. addr_length_extended = TRUE;
  1818. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length1, tvb,
  1819. offset, 1, value,
  1820. "Address Length (bits 4-0): %d", length);
  1821. addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
  1822. proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
  1823. offset += 1;
  1824. /* Extended */
  1825. value = tvb_get_guint8 (tvb, offset);
  1826. type = ((value & 0xE0) >> 5);
  1827. length |= ((value & 0x1F) << 5);
  1828. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_type_ext, tvb,
  1829. offset, 1, value, "Address Type Ext: %s",
  1830. val_to_str_const (type, ext_addr_type_ext,
  1831. "Reserved"));
  1832. addr_tree = proto_item_add_subtree (en, ett_address_ext_type);
  1833. proto_tree_add_item (addr_tree, hf_addr_ext_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  1834. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length2, tvb,
  1835. offset, 1, value,
  1836. "Address Length (bits 9-5): %d",
  1837. value & 0x1F);
  1838. addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
  1839. proto_tree_add_item (addr_tree, hf_addr_ext_length2, tvb, offset, 1, ENC_BIG_ENDIAN);
  1840. offset += 1;
  1841. } else {
  1842. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length, tvb,
  1843. offset, 1, value, "Address Length: %d",
  1844. length);
  1845. addr_tree = proto_item_add_subtree (en, ett_address_ext_length);
  1846. proto_tree_add_item (addr_tree, hf_addr_ext_length1, tvb, offset, 1, ENC_BIG_ENDIAN);
  1847. offset += 1;
  1848. }
  1849. if (type == ASN1_BER) {
  1850. tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, length, length);
  1851. dissect_p1_ORName (FALSE, next_tvb, 0, &asn1_ctx, ext_tree,
  1852. hf_addr_ext_asn1_ber);
  1853. } else if (type == ASN1_PER) {
  1854. proto_tree_add_item (ext_tree, hf_addr_ext_asn1_per, tvb, offset, length, ENC_NA);
  1855. } else {
  1856. proto_tree_add_item (ext_tree, hf_addr_ext_unknown, tvb, offset, length, ENC_NA);
  1857. }
  1858. offset += length;
  1859. if (addr_length_extended) {
  1860. en = proto_tree_add_uint_format (ext_tree, hf_addr_ext_length_generated,
  1861. tvb, offset, 0, length,
  1862. "Address Length: %d", length);
  1863. PROTO_ITEM_SET_GENERATED (en);
  1864. }
  1865. proto_item_append_text (ef, ", Type: %s, Length: %d",
  1866. val_to_str_const (type, ext_addr_type, "Reserved"),
  1867. length);
  1868. if (rec_no != -1) {
  1869. proto_item_append_text (tf, " %d", rec_no);
  1870. if (rec_ofs != -1) {
  1871. proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
  1872. }
  1873. }
  1874. proto_item_append_text (tf, ", %sExtended Address Type: %s",
  1875. val_to_str_const (addr_type, addr_type_str, ""),
  1876. val_to_str_const (type, ext_addr_type_short, "Reserved"));
  1877. proto_item_set_len (ef, offset - boffset);
  1878. return offset;
  1879. }
  1880. /* Ref chapter 5.2.8.1 Extended Originator Encoding */
  1881. static gint dissect_dmp_originator (tvbuff_t *tvb, packet_info *pinfo,
  1882. proto_tree *envelope_tree, gint offset)
  1883. {
  1884. proto_tree *field_tree = NULL, *rec_tree = NULL;
  1885. proto_item *en = NULL, *tf = NULL;
  1886. guint8 value, dmp_addr_form;
  1887. gint boffset = offset;
  1888. gboolean p2_addr = FALSE;
  1889. tf = proto_tree_add_item (envelope_tree, hf_addr_originator, tvb, offset, -1, ENC_NA);
  1890. field_tree = proto_item_add_subtree (tf, ett_address);
  1891. if (dmp.addr_enc == DIRECT_ADDR) {
  1892. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf,
  1893. offset, -1, -1, ORIGINATOR);
  1894. } else {
  1895. value = tvb_get_guint8 (tvb, offset);
  1896. dmp_addr_form = (value & 0xE0) >> 5;
  1897. if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
  1898. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig_v1, tvb,
  1899. offset, 1, value,
  1900. "Address Form: %s",
  1901. val_to_str_const (dmp_addr_form,
  1902. addr_form_orig_v1, "Reserved"));
  1903. rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
  1904. proto_tree_add_item (rec_tree, hf_addr_ext_form_orig_v1, tvb, offset, 1, ENC_BIG_ENDIAN);
  1905. } else {
  1906. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form_orig, tvb,
  1907. offset, 1, value,
  1908. "Address Form: %s",
  1909. val_to_str_const (dmp_addr_form,
  1910. addr_form_orig, "Reserved"));
  1911. rec_tree = proto_item_add_subtree (en, ett_address_ext_form);
  1912. proto_tree_add_item (rec_tree, hf_addr_ext_form_orig, tvb, offset, 1, ENC_BIG_ENDIAN);
  1913. }
  1914. en = proto_tree_add_item (rec_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
  1915. if (value & 0x1F) {
  1916. expert_add_info(pinfo, en, &ei_reserved_value);
  1917. }
  1918. offset += 1;
  1919. if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
  1920. switch (dmp_addr_form) {
  1921. case P1_DIRECT:
  1922. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
  1923. tf, offset, -1, -1,
  1924. ORIGINATOR);
  1925. break;
  1926. case P1_EXTENDED:
  1927. offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
  1928. -1, ORIGINATOR);
  1929. break;
  1930. default:
  1931. proto_item_append_text (tf, " (invalid address form)");
  1932. break;
  1933. }
  1934. } else {
  1935. switch (dmp_addr_form) {
  1936. case P1_DIRECT:
  1937. case P1_P2_DIRECT:
  1938. case P1_DIRECT_P2_EXTENDED:
  1939. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
  1940. tf, offset, -1, -1,
  1941. ORIGINATOR);
  1942. break;
  1943. case P1_EXTENDED:
  1944. case P1_EXTENDED_P2_DIRECT:
  1945. case P1_P2_EXTENDED:
  1946. offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
  1947. -1, ORIGINATOR);
  1948. break;
  1949. default:
  1950. proto_item_append_text (tf, " (invalid address form)");
  1951. break;
  1952. }
  1953. switch (dmp_addr_form) {
  1954. case P1_P2_DIRECT:
  1955. case P1_EXTENDED_P2_DIRECT:
  1956. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree,
  1957. tf, offset, -1, -1,
  1958. ORIG_P2_ADDRESS);
  1959. p2_addr = TRUE;
  1960. break;
  1961. case P1_DIRECT_P2_EXTENDED:
  1962. case P1_P2_EXTENDED:
  1963. offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset, -1,
  1964. -1, ORIG_P2_ADDRESS);
  1965. p2_addr = TRUE;
  1966. break;
  1967. }
  1968. }
  1969. if (p2_addr) {
  1970. if (dmp.msg_type == NOTIF) {
  1971. en = proto_tree_add_boolean (field_tree, hf_addr_int_rec, tvb,
  1972. offset, 0, TRUE);
  1973. } else {
  1974. en = proto_tree_add_boolean (field_tree, hf_addr_dl_expanded, tvb,
  1975. offset, 0, TRUE);
  1976. }
  1977. PROTO_ITEM_SET_GENERATED (en);
  1978. }
  1979. }
  1980. proto_item_set_len (tf, offset - boffset);
  1981. return offset;
  1982. }
  1983. static void dmp_add_recipient_info (proto_item *tf, guint8 rep_req,
  1984. guint8 not_req, gboolean action)
  1985. {
  1986. if (rep_req || not_req) {
  1987. proto_item_append_text (tf, ", Request:");
  1988. }
  1989. if (rep_req) {
  1990. proto_item_append_text (tf, "%s",
  1991. val_to_str_const (rep_req, report_vals_short, ""));
  1992. }
  1993. if (not_req) {
  1994. dmp.notif_req = TRUE;
  1995. proto_item_append_text (tf, "%s",
  1996. val_to_str_const (not_req, notif_vals_short, ""));
  1997. }
  1998. if (action) {
  1999. if (dmp.msg_type == STANAG) {
  2000. proto_item_append_text (tf, " (Action)");
  2001. } else if (dmp.msg_type == IPM) {
  2002. proto_item_append_text (tf, " (To)");
  2003. }
  2004. } else {
  2005. if (dmp.msg_type == STANAG) {
  2006. proto_item_append_text (tf, " (Info)");
  2007. } else if (dmp.msg_type == IPM) {
  2008. proto_item_append_text (tf, " (Cc)");
  2009. }
  2010. }
  2011. }
  2012. /* Ref chapter 5.2.7 Direct Recipient Encoding */
  2013. static gint dissect_dmp_direct_encoding (tvbuff_t *tvb, packet_info *pinfo,
  2014. proto_tree *field_tree, proto_item *tf,
  2015. gint offset, guint *prev_rec_no)
  2016. {
  2017. proto_tree *addr_tree = NULL, *rec_tree = NULL;
  2018. proto_item *en = NULL;
  2019. guint8 rep_req = 0, not_req = 0, value;
  2020. gint rec_no, rec_ofs = -1, dir_addr;
  2021. gboolean action = FALSE, dir_addr_extended = FALSE;
  2022. value = tvb_get_guint8 (tvb, offset);
  2023. rec_no = (value & 0xF0) >> 4;
  2024. rep_req = (value & 0x0C) >> 2;
  2025. not_req = (value & 0x03);
  2026. if (rep_req == 0x03) {
  2027. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no1,
  2028. tvb, offset, 1, value,
  2029. "Recipient Number (bits 3-0): %d"
  2030. " (offset from previous)",
  2031. (value & 0xF0) >> 4);
  2032. } else {
  2033. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no,
  2034. tvb, offset, 1, value,
  2035. "Recipient Number Offset: %d"
  2036. " (offset from previous)",
  2037. (value & 0xF0) >> 4);
  2038. }
  2039. rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
  2040. proto_tree_add_item (rec_tree, hf_addr_dir_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2041. proto_tree_add_item (rec_tree, hf_addr_dir_rep_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2042. proto_tree_add_item (rec_tree, hf_addr_dir_not_req1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2043. offset += 1;
  2044. value = tvb_get_guint8 (tvb, offset);
  2045. dir_addr = (value & 0x7F);
  2046. action = (value & 0x80);
  2047. if (not_req == 0x03) {
  2048. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address1,
  2049. tvb, offset, 1, value,
  2050. "Direct Address (bits 6-0): %d",
  2051. value & 0x7F);
  2052. } else {
  2053. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address,
  2054. tvb, offset, 1, value,
  2055. "Direct Address: %d",
  2056. value & 0x7F);
  2057. }
  2058. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  2059. proto_tree_add_item (addr_tree, hf_addr_dir_action, tvb, offset, 1, ENC_BIG_ENDIAN);
  2060. proto_tree_add_item (addr_tree, hf_addr_dir_address1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2061. offset += 1;
  2062. if (rep_req == 0x03) {
  2063. /* Extended Recipient Number 1 */
  2064. value = tvb_get_guint8 (tvb, offset);
  2065. rec_no |= ((value & 0x3F) << 4);
  2066. rec_ofs = rec_no;
  2067. rep_req = (value & 0xC0) >> 6;
  2068. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no2,
  2069. tvb, offset, 1, value,
  2070. "Recipient Number (bits 9-4): %d"
  2071. " (offset from previous)",
  2072. value & 0x3F);
  2073. rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
  2074. proto_tree_add_item (rec_tree, hf_addr_dir_rep_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
  2075. proto_tree_add_item (rec_tree, hf_addr_dir_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
  2076. offset += 1;
  2077. if (rep_req == 0x03) {
  2078. /* Extended Recipient Number 2 */
  2079. value = tvb_get_guint8 (tvb, offset);
  2080. rec_no |= ((value & 0x1F) << 10);
  2081. rec_ofs = rec_no;
  2082. rep_req = (value & 0xC0) >> 6;
  2083. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no3,
  2084. tvb, offset, 1, value,
  2085. "Recipient Number (bits 14-10): %d"
  2086. " (offset from previous)",
  2087. value & 0x1F);
  2088. rec_tree = proto_item_add_subtree (en, ett_address_rec_no);
  2089. proto_tree_add_item (rec_tree, hf_addr_dir_rep_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
  2090. en = proto_tree_add_item (rec_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
  2091. if (value & 0x20) {
  2092. expert_add_info(pinfo, en, &ei_reserved_value);
  2093. }
  2094. proto_tree_add_item (rec_tree, hf_addr_dir_rec_no3, tvb, offset, 1, ENC_BIG_ENDIAN);
  2095. offset += 1;
  2096. }
  2097. }
  2098. if (not_req == 0x03) {
  2099. /* Extended Direct Address 1 */
  2100. dir_addr_extended = TRUE;
  2101. value = tvb_get_guint8 (tvb, offset);
  2102. dir_addr |= ((value & 0x3F) << 7);
  2103. not_req = (value & 0xC0) >> 6;
  2104. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address2, tvb,
  2105. offset, 1, value,
  2106. "Direct Address (bits 12-7): %d",
  2107. value & 0x3F);
  2108. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  2109. proto_tree_add_item (addr_tree, hf_addr_dir_not_req2, tvb, offset, 1, ENC_BIG_ENDIAN);
  2110. proto_tree_add_item (addr_tree, hf_addr_dir_address2, tvb, offset, 1, ENC_BIG_ENDIAN);
  2111. offset += 1;
  2112. if (not_req == 0x03) {
  2113. /* Extended Direct Address 2 */
  2114. value = tvb_get_guint8 (tvb, offset);
  2115. dir_addr |= ((value & 0x3F) << 13);
  2116. not_req = (value & 0xC0) >> 6;
  2117. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address3, tvb,
  2118. offset, 1, value,
  2119. "Direct Address (bits 18-13): %d",
  2120. value & 0x3F);
  2121. addr_tree = proto_item_add_subtree (en, ett_address_direct);
  2122. proto_tree_add_item (addr_tree, hf_addr_dir_not_req3, tvb, offset, 1, ENC_BIG_ENDIAN);
  2123. proto_tree_add_item (addr_tree, hf_addr_dir_address3, tvb, offset, 1, ENC_BIG_ENDIAN);
  2124. offset += 1;
  2125. }
  2126. }
  2127. rec_no += *prev_rec_no;
  2128. if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
  2129. rec_no++;
  2130. }
  2131. *prev_rec_no = rec_no;
  2132. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_rec_no_generated,
  2133. tvb, offset, 0, rec_no,
  2134. "Recipient Number: %d", rec_no);
  2135. if (rec_no > 32767) {
  2136. proto_item_append_text (en, " (maximum 32767)");
  2137. expert_add_info_format (pinfo, en, PI_MALFORMED, PI_WARN,
  2138. "Recipient number too big");
  2139. }
  2140. PROTO_ITEM_SET_GENERATED (en);
  2141. if (dir_addr_extended) {
  2142. en = proto_tree_add_uint_format (field_tree, hf_addr_dir_address_generated,
  2143. tvb, offset, 0, dir_addr,
  2144. "Direct Address: %d", dir_addr);
  2145. PROTO_ITEM_SET_GENERATED (en);
  2146. }
  2147. proto_item_append_text (tf, " %d", rec_no);
  2148. if (rec_ofs != -1) {
  2149. proto_item_append_text (tf, " (offset from previous: %d)", rec_ofs);
  2150. }
  2151. proto_item_append_text (tf, ", Direct Address: %d", dir_addr);
  2152. dmp_add_recipient_info (tf, rep_req, not_req, action);
  2153. return offset;
  2154. }
  2155. /* Ref 5.2.8.2 Extended Recipient Encoding */
  2156. static gint dissect_dmp_ext_encoding (tvbuff_t *tvb, packet_info *pinfo,
  2157. proto_tree *field_tree,
  2158. proto_item *tf, gint offset,
  2159. guint *prev_rec_no)
  2160. {
  2161. proto_tree *addr_tree = NULL;
  2162. proto_item *en = NULL;
  2163. guint8 rep_req = 0, not_req = 0;
  2164. guint8 value, dmp_addr_form;
  2165. gboolean action = FALSE;
  2166. gint rec_no, rec_ofs = -1;
  2167. value = tvb_get_guint8 (tvb, offset);
  2168. dmp_addr_form = (value & 0xE0) >> 5;
  2169. action = (value & 0x10);
  2170. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_form, tvb,
  2171. offset, 1, value,
  2172. "Address Form: %s",
  2173. val_to_str_const (dmp_addr_form,
  2174. addr_form, "Reserved"));
  2175. addr_tree = proto_item_add_subtree (en, ett_address_ext_form);
  2176. proto_tree_add_item (addr_tree, hf_addr_ext_form, tvb, offset, 1, ENC_BIG_ENDIAN);
  2177. en = proto_tree_add_boolean_format (field_tree, hf_addr_ext_action, tvb,
  2178. offset, 1, value, "Action: %s",
  2179. action ? "Yes" : "No");
  2180. addr_tree = proto_item_add_subtree (en, ett_address_ext_action);
  2181. proto_tree_add_item (addr_tree, hf_addr_ext_action, tvb, offset, 1, ENC_BIG_ENDIAN);
  2182. rep_req = (value & 0x0C) >> 2;
  2183. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rep_req, tvb,
  2184. offset, 1, value,
  2185. "Report Request: %s",
  2186. val_to_str_const ((value & 0x0C) >> 2,
  2187. report_vals, "Reserved"));
  2188. addr_tree = proto_item_add_subtree (en, ett_address_ext_rep_req);
  2189. proto_tree_add_item (addr_tree, hf_addr_ext_rep_req, tvb, offset, 1, ENC_BIG_ENDIAN);
  2190. not_req = (value & 0x03);
  2191. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_not_req, tvb,
  2192. offset, 1, value,
  2193. "Notification Request: %s",
  2194. val_to_str_const (value & 0x03,
  2195. notif_vals, "Reserved"));
  2196. addr_tree = proto_item_add_subtree (en, ett_address_ext_not_req);
  2197. proto_tree_add_item (addr_tree, hf_addr_ext_not_req, tvb, offset, 1, ENC_BIG_ENDIAN);
  2198. offset += 1;
  2199. value = tvb_get_guint8 (tvb, offset);
  2200. rec_no = (value & 0x7F);
  2201. if (value & 0x80) {
  2202. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no1, tvb,
  2203. offset, 1, value,
  2204. "Recipient Number (bits 6-0): %d"
  2205. " (offset from previous)",
  2206. value & 0x7F);
  2207. addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
  2208. proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
  2209. proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2210. offset += 1;
  2211. /* Extended */
  2212. value = tvb_get_guint8 (tvb, offset);
  2213. rec_no |= (value << 7);
  2214. rec_ofs = rec_no;
  2215. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no2, tvb,
  2216. offset, 1, value,
  2217. "Recipient Number (bits 14-7): %d"
  2218. " (offset from previous)", value);
  2219. addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
  2220. proto_tree_add_item (addr_tree, hf_addr_ext_rec_no2, tvb, offset, 1, ENC_BIG_ENDIAN);
  2221. offset += 1;
  2222. } else {
  2223. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no, tvb,
  2224. offset, 1, value,
  2225. "Recipient Number Offset: %d"
  2226. " (offset from previous)",
  2227. value & 0x7F);
  2228. addr_tree = proto_item_add_subtree (en, ett_address_ext_rec_no);
  2229. proto_tree_add_item (addr_tree, hf_addr_ext_rec_ext, tvb, offset, 1, ENC_BIG_ENDIAN);
  2230. proto_tree_add_item (addr_tree, hf_addr_ext_rec_no1, tvb, offset, 1, ENC_BIG_ENDIAN);
  2231. offset += 1;
  2232. }
  2233. rec_no += *prev_rec_no;
  2234. if (dmp.version == DMP_VERSION_1 && !(dmp.prot_id == PROT_NAT && dmp_nat_decode == NAT_DECODE_THALES)) {
  2235. rec_no++;
  2236. }
  2237. *prev_rec_no = rec_no;
  2238. en = proto_tree_add_uint_format (field_tree, hf_addr_ext_rec_no_generated,
  2239. tvb, offset, 0, rec_no,
  2240. "Recipient Number: %d", rec_no);
  2241. if (rec_no > 32767) {
  2242. proto_item_append_text (en, " (maximum 32767)");
  2243. expert_add_info_format (pinfo, en, PI_MALFORMED, PI_WARN,
  2244. "Recipient number too big");
  2245. }
  2246. PROTO_ITEM_SET_GENERATED (en);
  2247. switch (dmp_addr_form) {
  2248. case P1_DIRECT:
  2249. case P1_P2_DIRECT:
  2250. case P1_DIRECT_P2_EXTENDED:
  2251. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
  2252. rec_no, rec_ofs, P1_ADDRESS);
  2253. break;
  2254. case P1_EXTENDED:
  2255. case P1_EXTENDED_P2_DIRECT:
  2256. case P1_P2_EXTENDED:
  2257. offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
  2258. rec_no, rec_ofs, P1_ADDRESS);
  2259. break;
  2260. }
  2261. switch (dmp_addr_form) {
  2262. case P2_DIRECT:
  2263. case P1_P2_DIRECT:
  2264. case P1_EXTENDED_P2_DIRECT:
  2265. offset = dissect_dmp_direct_addr (tvb, pinfo, field_tree, tf, offset,
  2266. rec_no, rec_ofs, P2_ADDRESS);
  2267. break;
  2268. case P2_EXTENDED:
  2269. case P1_DIRECT_P2_EXTENDED:
  2270. case P1_P2_EXTENDED:
  2271. offset = dissect_dmp_ext_addr (tvb, pinfo, field_tree, tf, offset,
  2272. rec_no, rec_ofs, P2_ADDRESS);
  2273. break;
  2274. }
  2275. dmp_add_recipient_info (tf, rep_req, not_req, action);
  2276. return offset;
  2277. }
  2278. /* Ref chapter 5.2 Address encoding */
  2279. static gint dissect_dmp_address (tvbuff_t *tvb, packet_info *pinfo,
  2280. proto_tree *envelope_tree,
  2281. gint offset, guint *prev_rec_no,
  2282. gboolean reporting_name)
  2283. {
  2284. proto_tree *field_tree = NULL;
  2285. proto_item *tf = NULL;
  2286. gint boffset = offset;
  2287. if (reporting_name) {
  2288. tf = proto_tree_add_item (envelope_tree, hf_addr_reporting_name, tvb, offset, -1, ENC_NA);
  2289. } else {
  2290. tf = proto_tree_add_none_format (envelope_tree, hf_addr_recipient, tvb,
  2291. offset, -1, "Recipient Number");
  2292. }
  2293. field_tree = proto_item_add_subtree (tf, ett_address);
  2294. if (dmp.addr_enc == DIRECT_ADDR) {
  2295. offset = dissect_dmp_direct_encoding (tvb, pinfo, field_tree, tf,
  2296. offset, prev_rec_no);
  2297. } else {
  2298. offset = dissect_dmp_ext_encoding (tvb, pinfo, field_tree, tf, offset,
  2299. prev_rec_no);
  2300. }
  2301. proto_item_set_len (tf, offset - boffset);
  2302. return offset;
  2303. }
  2304. /* Ref chapter 6.2.9 Acknowledgement */
  2305. static gint dissect_dmp_ack (tvbuff_t *tvb, packet_info *pinfo,
  2306. proto_tree *dmp_tree, gint offset)
  2307. {
  2308. proto_tree *ack_tree = NULL, *recip_tree = NULL;
  2309. proto_item *en = NULL, *rt = NULL;
  2310. proto_item *hidden_item;
  2311. guint prev_rec_no = 0;
  2312. gint rec_len, rec_no = 0;
  2313. gint boffset = offset;
  2314. en = proto_tree_add_item (dmp_tree, hf_ack, tvb, offset, 4, ENC_NA);
  2315. ack_tree = proto_item_add_subtree (en, ett_ack);
  2316. dmp.ack_reason = tvb_get_guint8 (tvb, offset);
  2317. proto_item_append_text (en, ", Reason: %s",
  2318. val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
  2319. rt = proto_tree_add_item (ack_tree, hf_ack_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
  2320. if (dmp.ack_reason != 0) {
  2321. expert_add_info_format (pinfo, rt, PI_RESPONSE_CODE, PI_NOTE, "ACK reason: %s",
  2322. val_to_str_const (dmp.ack_reason, ack_reason, "Reserved"));
  2323. }
  2324. offset += 1;
  2325. proto_tree_add_item (ack_tree, hf_ack_diagnostic, tvb, offset, 1, ENC_BIG_ENDIAN);
  2326. offset += 1;
  2327. /* Subject Message Identifier */
  2328. dmp.subj_id = tvb_get_ntohs (tvb, offset);
  2329. proto_tree_add_item (ack_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
  2330. hidden_item = proto_tree_add_item (ack_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
  2331. PROTO_ITEM_SET_HIDDEN (hidden_item);
  2332. offset += 2;
  2333. if (use_seq_ack_analysis) {
  2334. register_dmp_id (pinfo, dmp.ack_reason);
  2335. }
  2336. if (dmp.ack_rec_present) {
  2337. /* Recipient List */
  2338. rec_len = tvb_length (tvb);
  2339. if (dmp.checksum) {
  2340. rec_len -= 2;
  2341. }
  2342. if (offset < rec_len) {
  2343. rt = proto_tree_add_item (ack_tree, hf_ack_recips, tvb, offset, -1, ENC_NA);
  2344. recip_tree = proto_item_add_subtree (rt, ett_ack_recips);
  2345. while (offset < rec_len) {
  2346. offset = dissect_dmp_address (tvb, pinfo, recip_tree, offset,
  2347. &prev_rec_no, FALSE);
  2348. rec_no++;
  2349. }
  2350. proto_item_append_text (rt, ", No Recipients: %d", rec_no);
  2351. proto_item_set_len (rt, offset - boffset - 4);
  2352. proto_item_set_len (en, offset - boffset);
  2353. }
  2354. }
  2355. return offset;
  2356. }
  2357. static gint dissect_mts_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
  2358. gint offset, gboolean subject)
  2359. {
  2360. proto_item *hidden_item;
  2361. const gchar *mts_id;
  2362. if (dmp.msg_id_type == X400_MSG_ID || dmp_nat_decode == NAT_DECODE_DMP) {
  2363. mts_id = dissect_7bit_string (tvb, offset, dmp.mts_id_length);
  2364. } else if (dmp_nat_decode == NAT_DECODE_THALES) {
  2365. mts_id = dissect_thales_mts_id (tvb, offset, dmp.mts_id_length);
  2366. } else {
  2367. mts_id = tvb_bytes_to_str (tvb, offset, dmp.mts_id_length);
  2368. }
  2369. proto_item_append_text (dmp.mts_id_item, " (%zu bytes decompressed)", strlen (mts_id));
  2370. mts_id = format_text (mts_id, strlen (mts_id));
  2371. if (subject) {
  2372. proto_tree_add_string (tree, hf_message_subj_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
  2373. hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
  2374. /* Read from hash, for analysis */
  2375. dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, mts_id));
  2376. } else {
  2377. proto_tree_add_string (tree, hf_envelope_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
  2378. hidden_item = proto_tree_add_string (tree, hf_mts_id, tvb, offset, dmp.mts_id_length, mts_id);
  2379. /* Insert into hash, for analysis */
  2380. g_hash_table_insert (dmp_long_id_hash_table, g_strdup (mts_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
  2381. }
  2382. PROTO_ITEM_SET_HIDDEN (hidden_item);
  2383. offset += dmp.mts_id_length;
  2384. return offset;
  2385. }
  2386. static gint dissect_ipm_identifier (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
  2387. gint offset, gboolean subject)
  2388. {
  2389. proto_tree *field_tree;
  2390. proto_item *tf, *hidden_item;
  2391. const gchar *ipm_id;
  2392. gint length, modifier, ipm_id_length;
  2393. length = tvb_get_guint8 (tvb, offset);
  2394. modifier = (length & 0xC0) >> 6;
  2395. ipm_id_length = length & 0x3F;
  2396. tf = proto_tree_add_uint_format (tree, hf_envelope_ipm_id_length,
  2397. tvb, offset, 1, ipm_id_length,
  2398. "IPM Identifier Length: %u",
  2399. ipm_id_length);
  2400. field_tree = proto_item_add_subtree (tf, ett_envelope_ipm_id_length);
  2401. if ((dmp.msg_id_type == NAT_MSG_ID || modifier != IPM_MODIFIER_X400) && dmp_nat_decode == NAT_DECODE_THALES) {
  2402. proto_tree_add_item (field_tree, hf_thales_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
  2403. } else {
  2404. proto_tree_add_item (field_tree, hf_envelope_ipm_id_modifier, tvb, offset, 1, ENC_BIG_ENDIAN);
  2405. }
  2406. proto_tree_add_item (field_tree, hf_envelope_ipm_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
  2407. offset += 1;
  2408. if (modifier == IPM_MODIFIER_X400 || dmp_nat_decode == NAT_DECODE_DMP) {
  2409. ipm_id = dissect_7bit_string (tvb, offset, ipm_id_length);
  2410. } else if (dmp_nat_decode == NAT_DECODE_THALES) {
  2411. ipm_id = dissect_thales_ipm_id (tvb, offset, ipm_id_length, modifier);
  2412. } else {
  2413. ipm_id = tvb_bytes_to_str (tvb, offset, ipm_id_length);
  2414. }
  2415. proto_item_append_text (tf, " (%zu bytes decompressed)", strlen (ipm_id));
  2416. ipm_id = format_text (ipm_id, strlen (ipm_id));
  2417. if (subject) {
  2418. proto_tree_add_string (tree, hf_message_subj_ipm_id, tvb, offset, ipm_id_length, ipm_id);
  2419. hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
  2420. /* Read from hash, for analysis */
  2421. dmp.subj_id = GPOINTER_TO_UINT (g_hash_table_lookup (dmp_long_id_hash_table, ipm_id));
  2422. } else {
  2423. proto_tree_add_string (tree, hf_envelope_ipm_id, tvb, offset, ipm_id_length, ipm_id);
  2424. hidden_item = proto_tree_add_string (tree, hf_ipm_id, tvb, offset, ipm_id_length, ipm_id);
  2425. /* Insert into hash, for analysis */
  2426. g_hash_table_insert (dmp_long_id_hash_table, g_strdup (ipm_id), GUINT_TO_POINTER ((guint)dmp.msg_id));
  2427. }
  2428. PROTO_ITEM_SET_HIDDEN (hidden_item);
  2429. offset += ipm_id_length;
  2430. return offset;
  2431. }
  2432. /* Ref chapter 6.2.7 Envelope structure */
  2433. static gint dissect_dmp_envelope (tvbuff_t *tvb, packet_info *pinfo,
  2434. proto_tree *dmp_tree, gint offset)
  2435. {
  2436. proto_tree *envelope_tree = NULL;
  2437. proto_tree *field_tree = NULL;
  2438. proto_item *en = NULL, *tf = NULL, *vf = NULL;
  2439. proto_item *hidden_item;
  2440. guint8 envelope, time_diff;
  2441. guint16 subm_time, no_rec, value16;
  2442. gint32 secs = 0;
  2443. gchar *env_flags = NULL;
  2444. guint prev_rec_no = 0;
  2445. gint boffset = offset, i;
  2446. gboolean using_short_id = FALSE;
  2447. en = proto_tree_add_item (dmp_tree, hf_envelope, tvb, offset, 10, ENC_NA);
  2448. envelope_tree = proto_item_add_subtree (en, ett_envelope);
  2449. envelope = tvb_get_guint8 (tvb, offset);
  2450. dmp.prot_id = (envelope & 0xF8) >> 3;
  2451. dmp.version = (envelope & 0x07) + 1;
  2452. /* Protocol Version */
  2453. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_version,
  2454. tvb, offset, 1, dmp.version,
  2455. "Protocol Version: %d", dmp.version);
  2456. field_tree = proto_item_add_subtree (tf, ett_envelope_version);
  2457. vf = proto_tree_add_item (field_tree, hf_envelope_protocol_id, tvb, offset, 1, ENC_BIG_ENDIAN);
  2458. if (dmp.prot_id == PROT_NAT) {
  2459. proto_item_append_text (vf, " (national version of DMP)");
  2460. proto_item_append_text (tf, " (national)");
  2461. } else if (dmp.prot_id == PROT_DMP) {
  2462. proto_item_append_text (vf, " (correct)");
  2463. } else {
  2464. proto_item_append_text (vf, " (incorrect, should be 0x1d)");
  2465. }
  2466. vf = proto_tree_add_item (field_tree, hf_envelope_version_value, tvb, offset, 1, ENC_BIG_ENDIAN);
  2467. offset += 1;
  2468. if (dmp.version > DMP_VERSION_2) {
  2469. /* Unsupported DMP Version */
  2470. proto_item_append_text (vf, " (unsupported)");
  2471. proto_item_append_text (tf, " (unsupported)");
  2472. expert_add_info_format (pinfo, vf, PI_UNDECODED, PI_ERROR,
  2473. "Unsupported DMP Version: %d", dmp.version);
  2474. return offset;
  2475. }
  2476. envelope = tvb_get_guint8 (tvb, offset);
  2477. dmp.addr_enc = ((envelope & 0x10) >> 4);
  2478. dmp.checksum = ((envelope & 0x08) >> 3);
  2479. dmp.msg_type = (envelope & 0x07);
  2480. if (dmp.msg_type != ACK) {
  2481. /* Hop count */
  2482. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_hop_count,
  2483. tvb, offset, 1, envelope,
  2484. "Hop Count: %d", (envelope & 0xE0) >> 5);
  2485. field_tree = proto_item_add_subtree (tf, ett_envelope_hop_count);
  2486. proto_tree_add_item (field_tree, hf_envelope_hop_count_value, tvb, offset, 1, ENC_BIG_ENDIAN);
  2487. } else {
  2488. if (dmp.version >= DMP_VERSION_2) {
  2489. /* Extensions Present */
  2490. dmp.extensions = (envelope & 0x80);
  2491. tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
  2492. tvb, offset, 1, envelope,
  2493. "Extensions: %s",
  2494. (envelope & 0x80) ? "Present" : "Absent");
  2495. field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
  2496. proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
  2497. }
  2498. /* Recipient Present */
  2499. dmp.ack_rec_present = (envelope & 0x20);
  2500. tf = proto_tree_add_boolean_format (envelope_tree,hf_envelope_rec_present,
  2501. tvb, offset, 1, envelope,
  2502. "Recipient Present: %s",
  2503. (envelope & 0x20) ? "Present" : "Absent");
  2504. field_tree = proto_item_add_subtree (tf, ett_envelope_rec_present);
  2505. proto_tree_add_item (field_tree, hf_envelope_rec_present, tvb, offset, 1, ENC_BIG_ENDIAN);
  2506. }
  2507. /* Address Encoding */
  2508. tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_addr_enc,
  2509. tvb, offset, 1, envelope,
  2510. "Address Encoding: %s",
  2511. (envelope & 0x10) ?
  2512. addr_enc.true_string :
  2513. addr_enc.false_string);
  2514. field_tree = proto_item_add_subtree (tf, ett_envelope_addr_enc);
  2515. proto_tree_add_item (field_tree, hf_envelope_addr_enc, tvb, offset, 1, ENC_BIG_ENDIAN);
  2516. /* Checksum Present */
  2517. tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_checksum,
  2518. tvb, offset, 1, envelope,
  2519. "Checksum: %s",
  2520. (envelope & 0x08) ? "Used" : "Not used");
  2521. field_tree = proto_item_add_subtree (tf, ett_envelope_checksum);
  2522. proto_tree_add_item (field_tree, hf_envelope_checksum, tvb, offset, 1, ENC_BIG_ENDIAN);
  2523. /* Content Type */
  2524. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_type,
  2525. tvb, offset, 1, envelope,
  2526. "Content Type: %s (%d)",
  2527. val_to_str_const (envelope & 0x07,
  2528. type_vals, "Unknown"),
  2529. envelope & 0x07);
  2530. field_tree = proto_item_add_subtree (tf, ett_envelope_cont_type);
  2531. proto_tree_add_item (field_tree, hf_envelope_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  2532. proto_item_append_text (en, ", Checksum %s", (envelope >> 3) & 0x01 ? "Used" : "Not used");
  2533. offset += 1;
  2534. if (dmp.msg_type >= ACK) {
  2535. proto_item_set_len (en, offset - boffset);
  2536. return offset;
  2537. }
  2538. if (dmp.version >= DMP_VERSION_2) {
  2539. envelope = tvb_get_guint8 (tvb, offset);
  2540. /* Extensions Present */
  2541. tf = proto_tree_add_boolean_format (envelope_tree, hf_envelope_extensions,
  2542. tvb, offset, 1, envelope,
  2543. "Extensions: %s",
  2544. (envelope & 0x80) ? "Present" : "Absent");
  2545. field_tree = proto_item_add_subtree (tf, ett_envelope_extensions);
  2546. proto_tree_add_item (field_tree, hf_envelope_extensions, tvb, offset, 1, ENC_BIG_ENDIAN);
  2547. dmp.extensions = (envelope & 0x80);
  2548. /* Message Identifier Type */
  2549. dmp.msg_id_type = (envelope & 0x60) >> 5;
  2550. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_msg_id_type,
  2551. tvb, offset, 1, envelope,
  2552. "Message Identifier Type: %s (%d)",
  2553. val_to_str_const (dmp.msg_id_type, msg_id_type_vals, "Unknown"),
  2554. dmp.msg_id_type);
  2555. field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id_type);
  2556. proto_tree_add_item (field_tree, hf_envelope_msg_id_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  2557. if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
  2558. /* MTS Identifier Length */
  2559. dmp.mts_id_length = (envelope & 0x1F);
  2560. dmp.mts_id_item = proto_tree_add_uint_format (envelope_tree, hf_envelope_mts_id_length,
  2561. tvb, offset, 1, envelope,
  2562. "MTS Identifier Length: %u",
  2563. dmp.mts_id_length);
  2564. field_tree = proto_item_add_subtree (dmp.mts_id_item, ett_envelope_mts_id_length);
  2565. proto_tree_add_item (field_tree, hf_envelope_mts_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
  2566. offset += 1;
  2567. } else {
  2568. proto_tree_add_item (field_tree, hf_envelope_msg_id_length, tvb, offset, 1, ENC_BIG_ENDIAN);
  2569. if (envelope & 0x10) {
  2570. /* Using Short Identifier (12 bits) */
  2571. using_short_id = TRUE;
  2572. } else {
  2573. tf = proto_tree_add_item (field_tree, hf_reserved_0x0F, tvb, offset, 1, ENC_BIG_ENDIAN);
  2574. if (envelope & 0x0F) {
  2575. expert_add_info(pinfo, tf, &ei_reserved_value);
  2576. }
  2577. offset += 1;
  2578. }
  2579. }
  2580. }
  2581. /* Message Identifier */
  2582. dmp.msg_id = tvb_get_ntohs (tvb, offset);
  2583. if (using_short_id) {
  2584. dmp.msg_id &= 0x0FFF;
  2585. }
  2586. tf = proto_tree_add_uint (envelope_tree, hf_envelope_msg_id, tvb, offset, 2, dmp.msg_id);
  2587. hidden_item = proto_tree_add_uint (envelope_tree, hf_dmp_id, tvb, offset, 2, dmp.msg_id);
  2588. if (using_short_id) {
  2589. field_tree = proto_item_add_subtree (tf, ett_envelope_msg_id);
  2590. proto_tree_add_item (field_tree, hf_envelope_msg_id_12bit, tvb, offset, 2, ENC_BIG_ENDIAN);
  2591. } else if (dmp.version >= DMP_VERSION_2 && dmp.msg_id_type == ONLY_DMP_ID && dmp.msg_id < 4096) {
  2592. expert_add_info_format (pinfo, tf, PI_PROTOCOL, PI_NOTE, "Id < 4096 - should use ShortId");
  2593. }
  2594. PROTO_ITEM_SET_HIDDEN (hidden_item);
  2595. offset += 2;
  2596. if (dmp.version >= DMP_VERSION_2) {
  2597. if ((dmp.msg_type != REPORT) && (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID)) {
  2598. offset = dissect_mts_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
  2599. }
  2600. }
  2601. /* Submission Time */
  2602. subm_time = tvb_get_ntohs (tvb, offset);
  2603. dmp.subm_time = dmp_dec_subm_time ((guint16)(subm_time & 0x7FFF),
  2604. (gint32) pinfo->fd->abs_ts.secs);
  2605. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_subm_time, tvb,
  2606. offset, 2, subm_time,
  2607. "Submission time: %s",
  2608. (subm_time & 0x7FFF) >= 0x7FF8 ?
  2609. "Reserved" :
  2610. abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
  2611. field_tree = proto_item_add_subtree (tf, ett_envelope_subm_time);
  2612. proto_tree_add_item (field_tree, hf_envelope_time_diff_present, tvb, offset, 2, ENC_BIG_ENDIAN);
  2613. proto_tree_add_item (field_tree, hf_envelope_subm_time_value, tvb, offset, 2, ENC_BIG_ENDIAN);
  2614. offset += 2;
  2615. if (subm_time & 0x8000) {
  2616. /* Timed Difference */
  2617. time_diff = tvb_get_guint8 (tvb, offset);
  2618. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_time_diff,
  2619. tvb, offset, 1, time_diff,
  2620. "Time Difference: ");
  2621. field_tree = proto_item_add_subtree (tf, ett_envelope_time_diff);
  2622. proto_tree_add_item (field_tree, hf_envelope_time_diff_value, tvb, offset, 1, ENC_BIG_ENDIAN);
  2623. secs = dmp_dec_time_diff (time_diff);
  2624. if (secs == DMP_TIME_RESERVED) {
  2625. proto_item_append_text (tf, "Reserved (0x%2.2x)", time_diff);
  2626. } else {
  2627. proto_item_append_text (tf, "%s", time_secs_to_str (secs));
  2628. }
  2629. offset += 1;
  2630. }
  2631. /* Envelope Flags */
  2632. envelope = tvb_get_guint8 (tvb, offset);
  2633. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_flags,
  2634. tvb, offset, 1, envelope,
  2635. "Envelope Flags");
  2636. field_tree = proto_item_add_subtree (tf, ett_envelope_flags);
  2637. proto_tree_add_item (field_tree, hf_envelope_content_id_discarded, tvb, offset, 1, ENC_BIG_ENDIAN);
  2638. proto_tree_add_item (field_tree, hf_envelope_recip_reassign_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
  2639. proto_tree_add_item (field_tree, hf_envelope_dl_expansion_prohib, tvb, offset, 1, ENC_BIG_ENDIAN);
  2640. if (envelope & 0xE0) {
  2641. env_flags = ep_strdup_printf ("%s%s%s",
  2642. (envelope & 0x80) ? ", ContId discarded" : "",
  2643. (envelope & 0x40) ? ", Reass prohibited" : "",
  2644. (envelope & 0x20) ? ", DLE prohibited" : "");
  2645. proto_item_append_text (tf, ":%s", &env_flags[1]);
  2646. } else {
  2647. proto_item_append_text (tf, " (none)");
  2648. }
  2649. /* Recipient Count */
  2650. no_rec = (envelope & 0x1F);
  2651. tf = proto_tree_add_uint_format (envelope_tree, hf_envelope_recipients,
  2652. tvb, offset, 1, envelope,
  2653. "Recipient Count: %d", no_rec);
  2654. field_tree = proto_item_add_subtree (tf, ett_envelope_recipients);
  2655. proto_tree_add_item (field_tree, hf_envelope_recipients, tvb, offset, 1, ENC_BIG_ENDIAN);
  2656. offset += 1;
  2657. if (no_rec == 0) {
  2658. /* Extended Recipient Count */
  2659. value16 = tvb_get_ntohs (tvb, offset);
  2660. no_rec = value16 & 0x7FFF;
  2661. tf = proto_tree_add_uint_format (envelope_tree,hf_envelope_ext_recipients,
  2662. tvb, offset, 2, value16,
  2663. "Extended Recipient Count: %d%s", no_rec,
  2664. (no_rec < 32 ?
  2665. " (incorrect, reserved value)" : ""));
  2666. field_tree = proto_item_add_subtree (tf, ett_envelope_ext_recipients);
  2667. en = proto_tree_add_item (field_tree, hf_reserved_0x8000, tvb, offset, 2, ENC_BIG_ENDIAN);
  2668. if (value16 & 0x8000) {
  2669. expert_add_info(pinfo, en, &ei_reserved_value);
  2670. }
  2671. proto_tree_add_item (field_tree, hf_envelope_ext_recipients, tvb, offset, 2, ENC_BIG_ENDIAN);
  2672. offset += 2;
  2673. }
  2674. if (dmp.msg_type != REPORT) {
  2675. /* Originator - Not present for reports */
  2676. offset = dissect_dmp_originator (tvb, pinfo, envelope_tree, offset);
  2677. }
  2678. for (i = 0; i < no_rec; i++) {
  2679. /* Recipient(s) */
  2680. offset = dissect_dmp_address (tvb, pinfo, envelope_tree, offset,
  2681. &prev_rec_no, FALSE);
  2682. }
  2683. if (dmp.version >= DMP_VERSION_2) {
  2684. if ((dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) &&
  2685. dmp.notif_req && (dmp.msg_type == STANAG || dmp.msg_type == IPM))
  2686. {
  2687. offset = dissect_ipm_identifier (tvb, pinfo, envelope_tree, offset, FALSE);
  2688. }
  2689. }
  2690. proto_item_set_len (en, offset - boffset);
  2691. return offset;
  2692. }
  2693. static void dissect_dmp_structured_id (tvbuff_t *tvb, proto_tree *body_tree,
  2694. gint offset)
  2695. {
  2696. gint length;
  2697. offset += dmp_struct_offset;
  2698. switch (dmp_struct_format) {
  2699. case STRUCT_ID_UINT8:
  2700. dmp.struct_id = ep_strdup_printf ("%u", tvb_get_guint8 (tvb, offset));
  2701. proto_tree_add_item (body_tree, hf_message_bodyid_uint8, tvb, offset, 1, ENC_BIG_ENDIAN);
  2702. break;
  2703. case STRUCT_ID_UINT16:
  2704. dmp.struct_id = ep_strdup_printf ("%u", tvb_get_ntohs (tvb, offset));
  2705. proto_tree_add_item (body_tree, hf_message_bodyid_uint16, tvb, offset, 2, ENC_BIG_ENDIAN);
  2706. break;
  2707. case STRUCT_ID_UINT32:
  2708. dmp.struct_id = ep_strdup_printf ("%u", tvb_get_ntohl (tvb, offset));
  2709. proto_tree_add_item (body_tree, hf_message_bodyid_uint32, tvb, offset, 4, ENC_BIG_ENDIAN);
  2710. break;
  2711. case STRUCT_ID_UINT64:
  2712. dmp.struct_id = ep_strdup_printf ("%" G_GINT64_MODIFIER "u", tvb_get_ntoh64 (tvb, offset));
  2713. proto_tree_add_item (body_tree, hf_message_bodyid_uint64, tvb, offset, 8, ENC_BIG_ENDIAN);
  2714. break;
  2715. case STRUCT_ID_STRING:
  2716. dmp.struct_id = tvb_get_ephemeral_string (tvb, offset, (gint) dmp_struct_length);
  2717. proto_tree_add_item (body_tree, hf_message_bodyid_string, tvb, offset, dmp_struct_length, ENC_ASCII|ENC_NA);
  2718. break;
  2719. case STRUCT_ID_ZSTRING:
  2720. dmp.struct_id = tvb_get_ephemeral_stringz (tvb, offset, &length);
  2721. proto_tree_add_item (body_tree, hf_message_bodyid_zstring, tvb, offset, length, ENC_ASCII|ENC_NA);
  2722. break;
  2723. }
  2724. }
  2725. /*
  2726. * Ref chapter 6.3.7.1 STANAG 4406 message structure
  2727. * and chapter 6.3.8.1 IPM 88 message structure
  2728. */
  2729. static gint dissect_dmp_message (tvbuff_t *tvb, packet_info *pinfo,
  2730. proto_tree *dmp_tree, gint offset)
  2731. {
  2732. tvbuff_t *next_tvb = NULL;
  2733. proto_tree *message_tree = NULL;
  2734. proto_tree *field_tree = NULL;
  2735. proto_item *en = NULL, *tf = NULL, *tr = NULL;
  2736. guint8 message, eit = 0, compr_alg = ALGORITHM_NONE;
  2737. gint len, boffset = offset;
  2738. en = proto_tree_add_item (dmp_tree, hf_message_body, tvb, offset, -1, ENC_NA);
  2739. message_tree = proto_item_add_subtree (en, ett_message);
  2740. if (dmp.body_format == FREE_TEXT_SUBJECT) {
  2741. len = tvb_strsize (tvb, offset);
  2742. if (dmp_subject_as_id) {
  2743. dmp.struct_id = tvb_get_ephemeral_string (tvb, offset, len);
  2744. }
  2745. proto_tree_add_item (message_tree, hf_message_subject, tvb, offset, len, ENC_ASCII|ENC_NA);
  2746. offset += len;
  2747. }
  2748. if (dmp.body_format == FREE_TEXT || dmp.body_format == FREE_TEXT_SUBJECT) {
  2749. message = tvb_get_guint8 (tvb, offset);
  2750. eit = (message & 0xE0) >> 5;
  2751. compr_alg = (message & 0x18) >> 3;
  2752. /* Encoded Information Type */
  2753. tf = proto_tree_add_uint_format (message_tree, hf_message_eit,
  2754. tvb, offset, 1, message, "EIT: %s (%d)",
  2755. val_to_str_const (eit, eit_vals, "Unknown"),
  2756. eit);
  2757. field_tree = proto_item_add_subtree (tf, ett_message_eit);
  2758. proto_tree_add_item (field_tree, hf_message_eit, tvb, offset, 1, ENC_BIG_ENDIAN);
  2759. proto_item_append_text (en, ", Type: %s",
  2760. val_to_str_const (eit, eit_vals, "Unknown"));
  2761. /* Compression Algorithm */
  2762. tf = proto_tree_add_uint_format (message_tree, hf_message_compr,
  2763. tvb, offset, 1, message,
  2764. "Compression Algorithm: %s (%d)",
  2765. val_to_str_const (compr_alg, compression_vals, "Unknown"),
  2766. compr_alg);
  2767. field_tree = proto_item_add_subtree (tf, ett_message_compr);
  2768. tr = proto_tree_add_item (field_tree, hf_message_compr, tvb, offset, 1, ENC_BIG_ENDIAN);
  2769. if (compr_alg == ALGORITHM_ZLIB) {
  2770. proto_item_append_text (en, " (compressed)");
  2771. } else if (compr_alg != ALGORITHM_NONE) {
  2772. expert_add_info_format (pinfo, tr, PI_UNDECODED, PI_WARN,
  2773. "Unknown compression algorithm");
  2774. }
  2775. if (message & 0x07) {
  2776. /* Reserved */
  2777. tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x07,
  2778. tvb, offset, 1, message,
  2779. "Reserved: %d", message & 0x07);
  2780. field_tree = proto_item_add_subtree (tf, ett_message_body_reserved);
  2781. tf = proto_tree_add_item (field_tree, hf_reserved_0x07, tvb, offset, 1, ENC_BIG_ENDIAN);
  2782. expert_add_info(pinfo, tf, &ei_reserved_value);
  2783. }
  2784. offset += 1;
  2785. }
  2786. len = tvb_length_remaining (tvb, offset);
  2787. if (dmp.checksum) {
  2788. len -= 2;
  2789. }
  2790. tf = proto_tree_add_none_format (message_tree, hf_message_body_data, tvb,
  2791. offset, len,
  2792. "%sUser data, Length: %d",
  2793. (compr_alg == ALGORITHM_ZLIB) ?
  2794. "Compressed " : "", len);
  2795. field_tree = proto_item_add_subtree (tf, ett_message_body);
  2796. if (dmp.body_format == STRUCTURED) {
  2797. /* Structured Message ID */
  2798. dissect_dmp_structured_id (tvb, field_tree, offset);
  2799. proto_tree_add_item (field_tree, hf_message_body_structured, tvb, offset, len, ENC_NA);
  2800. } else if (len > 0 && (dmp.body_format == FREE_TEXT ||
  2801. dmp.body_format == FREE_TEXT_SUBJECT)) {
  2802. if (compr_alg == ALGORITHM_ZLIB) {
  2803. if ((next_tvb = tvb_child_uncompress (tvb, tvb, offset, len)) != NULL) {
  2804. gint zlen = tvb_length (next_tvb);
  2805. add_new_data_source (pinfo, next_tvb, "Uncompressed User data");
  2806. tf = proto_tree_add_none_format (message_tree,
  2807. hf_message_body_uncompr,
  2808. next_tvb, 0, zlen,
  2809. "Uncompressed User data, "
  2810. "Length: %d", zlen);
  2811. field_tree = proto_item_add_subtree (tf, ett_message_body_uncompr);
  2812. proto_tree_add_item (field_tree, hf_message_body_uncompressed, next_tvb, 0, -1, ENC_ASCII|ENC_NA);
  2813. } else {
  2814. tf = proto_tree_add_text (message_tree, tvb, offset, -1,
  2815. "Error: Unable to uncompress content");
  2816. expert_add_info_format (pinfo, tf, PI_UNDECODED, PI_WARN,
  2817. "Unable to uncompress content");
  2818. }
  2819. } else if (eit != EIT_BILATERAL) {
  2820. proto_tree_add_item (field_tree, hf_message_body_plain, tvb, offset, len, ENC_ASCII|ENC_NA);
  2821. }
  2822. }
  2823. offset += len;
  2824. if (dmp.struct_id) {
  2825. proto_item_append_text (en, ", Id: %s", format_text (dmp.struct_id, strlen (dmp.struct_id)));
  2826. }
  2827. proto_item_set_len (en, offset - boffset);
  2828. return offset;
  2829. }
  2830. /* Ref chapter 6.3.9.1 Report structure */
  2831. static gint dissect_dmp_report (tvbuff_t *tvb, packet_info *pinfo,
  2832. proto_tree *dmp_tree, gint offset,
  2833. guint *prev_rec_no, gint num)
  2834. {
  2835. proto_tree *report_tree = NULL;
  2836. proto_tree *field_tree = NULL;
  2837. proto_item *en = NULL, *ei = NULL, *tf = NULL;
  2838. guint8 report;
  2839. gboolean info_present;
  2840. gint32 secs = 0;
  2841. gint len, boffset = offset;
  2842. gint rep_type = 0;
  2843. report = tvb_get_guint8 (tvb, offset);
  2844. rep_type = (report & 0x80) >> 7;
  2845. if (rep_type) {
  2846. en = proto_tree_add_item (dmp_tree, hf_non_delivery_report, tvb, offset, 4, ENC_NA);
  2847. } else {
  2848. en = proto_tree_add_item (dmp_tree, hf_delivery_report, tvb, offset, 4, ENC_NA);
  2849. }
  2850. proto_item_append_text (en, " (#%d)", num);
  2851. report_tree = proto_item_add_subtree (en, ett_report);
  2852. /* Report Type */
  2853. tf = proto_tree_add_boolean_format (report_tree, hf_report_type,
  2854. tvb, offset, 1, report,
  2855. "Report Type: %s", rep_type ?
  2856. report_type.true_string :
  2857. report_type.false_string);
  2858. field_tree = proto_item_add_subtree (tf, ett_report_type);
  2859. proto_tree_add_item (field_tree, hf_report_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  2860. if (rep_type == DR) {
  2861. dmp.dr = TRUE;
  2862. /* Info Present */
  2863. info_present = (report & 0x40);
  2864. tf = proto_tree_add_boolean_format (report_tree,hf_report_info_present_dr,
  2865. tvb, offset, 1, report,
  2866. "Info Present: %s", (report & 0x40) ? "Present" : "Absent");
  2867. field_tree = proto_item_add_subtree (tf, ett_report_info_present_dr);
  2868. proto_tree_add_item (field_tree, hf_report_info_present_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
  2869. /* Address Encoding */
  2870. dmp.addr_enc = ((report & 0x20) >> 5);
  2871. tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_dr,
  2872. tvb, offset, 1, report,
  2873. "Address Encoding: %s",
  2874. (report & 0x20) ?
  2875. addr_enc.true_string :
  2876. addr_enc.false_string);
  2877. field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_dr);
  2878. proto_tree_add_item (field_tree, hf_report_addr_enc_dr, tvb, offset, 1, ENC_BIG_ENDIAN);
  2879. if (report & 0x1F) {
  2880. /* Reserved */
  2881. tf = proto_tree_add_uint_format (report_tree, hf_reserved_0x1F,
  2882. tvb, offset, 1, report,
  2883. "Reserved: %d", report & 0x1F);
  2884. field_tree = proto_item_add_subtree (tf, ett_report_reserved);
  2885. tf = proto_tree_add_item (field_tree, hf_reserved_0x1F, tvb, offset, 1, ENC_BIG_ENDIAN);
  2886. expert_add_info(pinfo, tf, &ei_reserved_value);
  2887. }
  2888. offset += 1;
  2889. /* Delivery Time */
  2890. report = tvb_get_guint8 (tvb, offset);
  2891. tf = proto_tree_add_uint_format (report_tree, hf_report_del_time,
  2892. tvb, offset, 1, report,
  2893. "Delivery Time: ");
  2894. field_tree = proto_item_add_subtree (tf, ett_report_del_time);
  2895. ei = proto_tree_add_item (field_tree, hf_report_del_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  2896. secs = dmp_dec_del_time (report);
  2897. if (secs == DMP_TIME_RESERVED) {
  2898. proto_item_append_text (tf, "Reserved (0x%2.2x)", report);
  2899. proto_item_append_text (ei, " (Reserved)");
  2900. } else {
  2901. proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
  2902. abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
  2903. proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
  2904. }
  2905. } else {
  2906. dmp.ndr = TRUE;
  2907. /* Address Encoding */
  2908. dmp.addr_enc = ((report & 0x40) >> 6);
  2909. tf = proto_tree_add_boolean_format (report_tree, hf_report_addr_enc_ndr,
  2910. tvb, offset, 1, report,
  2911. "Address Encoding: %s",
  2912. (report & 0x40) ?
  2913. addr_enc.true_string :
  2914. addr_enc.false_string);
  2915. field_tree = proto_item_add_subtree (tf, ett_report_addr_enc_ndr);
  2916. proto_tree_add_item (field_tree, hf_report_addr_enc_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
  2917. /* Reason */
  2918. tf = proto_tree_add_uint_format (report_tree, hf_report_reason,
  2919. tvb, offset, 1, report,
  2920. "Reason%s: %s (%d)",
  2921. ((report & 0x3F) < 0x3D) ? " (P1)":"",
  2922. non_del_reason_str (report & 0x3F),
  2923. report & 0x3F);
  2924. field_tree = proto_item_add_subtree (tf, ett_report_reason);
  2925. proto_tree_add_item (field_tree, hf_report_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
  2926. offset += 1;
  2927. /* Info Present */
  2928. report = tvb_get_guint8 (tvb, offset);
  2929. info_present = (report & 0x80);
  2930. tf = proto_tree_add_boolean_format (report_tree,
  2931. hf_report_info_present_ndr,
  2932. tvb, offset, 1, report,
  2933. "Info Present: %s", (report & 0x80) ? "Present" : "Absent");
  2934. field_tree = proto_item_add_subtree (tf, ett_report_info_present_ndr);
  2935. proto_tree_add_item (field_tree, hf_report_info_present_ndr, tvb, offset, 1, ENC_BIG_ENDIAN);
  2936. /* Diagnostic */
  2937. tf = proto_tree_add_uint_format (report_tree, hf_report_diagn,
  2938. tvb, offset, 1, report,
  2939. "Diagnostic%s: %s (%d)",
  2940. ((report & 0x7F) < 0x7C) ? " (P1)":"",
  2941. non_del_diagn_str (report & 0x7F),
  2942. report & 0x7F);
  2943. field_tree = proto_item_add_subtree (tf, ett_report_diagn);
  2944. proto_tree_add_item (field_tree, hf_report_diagn, tvb, offset, 1, ENC_BIG_ENDIAN);
  2945. }
  2946. offset += 1;
  2947. offset = dissect_dmp_address (tvb, pinfo, report_tree, offset,
  2948. prev_rec_no, TRUE);
  2949. if (info_present) {
  2950. /* Supplementary Information */
  2951. len = tvb_strsize (tvb, offset);
  2952. tf = proto_tree_add_uint_format (report_tree, hf_report_suppl_info_len,
  2953. tvb, offset, len, len,
  2954. "Supplementary Information, Length: %d",
  2955. len - 1);
  2956. if (len > 1) {
  2957. if ((offset - boffset + len) > 128) {
  2958. proto_item_append_text (tf, " (incorrect, should be less than %d)",
  2959. 128 - (offset - boffset));
  2960. }
  2961. field_tree = proto_item_add_subtree (tf, ett_report_suppl_info);
  2962. proto_tree_add_item (field_tree, hf_report_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
  2963. }
  2964. offset += len;
  2965. }
  2966. proto_item_set_len (en, offset - boffset);
  2967. return offset;
  2968. }
  2969. /* Ref chapter 6.3.10.1 Notification structure */
  2970. static gint dissect_dmp_notification (tvbuff_t *tvb, packet_info *pinfo _U_,
  2971. proto_tree *dmp_tree, gint offset)
  2972. {
  2973. proto_tree *notif_tree = NULL;
  2974. proto_tree *field_tree = NULL;
  2975. proto_item *en = NULL, *ei = NULL, *tf = NULL;
  2976. guint8 notif, rec_time, on_typex = 0xFF;
  2977. gint len, boffset = offset;
  2978. gint32 secs = 0;
  2979. if (dmp.notif_type == RN) {
  2980. en = proto_tree_add_item (dmp_tree, hf_receipt_notif, tvb, offset, 4, ENC_NA);
  2981. } else if (dmp.notif_type == NRN) {
  2982. en = proto_tree_add_item (dmp_tree, hf_non_receipt_notif, tvb, offset, 4, ENC_NA);
  2983. } else if (dmp.notif_type == ON) {
  2984. en = proto_tree_add_item (dmp_tree, hf_other_notif, tvb, offset, 4, ENC_NA);
  2985. } else {
  2986. return offset;
  2987. }
  2988. notif_tree = proto_item_add_subtree (en, ett_notif);
  2989. if (dmp.notif_type == RN || dmp.notif_type == ON) {
  2990. /* Receipt Time */
  2991. rec_time = tvb_get_guint8 (tvb, offset);
  2992. tf = proto_tree_add_uint_format (notif_tree, hf_notif_rec_time,
  2993. tvb, offset, 1, rec_time,
  2994. "Receipt Time: ");
  2995. field_tree = proto_item_add_subtree (tf, ett_notif_rec_time);
  2996. ei = proto_tree_add_item (field_tree, hf_notif_rec_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  2997. secs = dmp_dec_exp_time (rec_time);
  2998. if (secs == DMP_TIME_NOT_PRESENT) {
  2999. proto_item_append_text (tf, "Not present");
  3000. proto_item_append_text (ei, " (not present)");
  3001. } else if (secs == DMP_TIME_RESERVED) {
  3002. proto_item_append_text (tf, "Reserved (0x%2.2x)", rec_time);
  3003. proto_item_append_text (ei, " (Reserved)");
  3004. } else {
  3005. proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
  3006. abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
  3007. proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
  3008. }
  3009. offset += 1;
  3010. if (dmp.notif_type == ON) {
  3011. /* ON Type */
  3012. on_typex = tvb_get_guint8 (tvb, offset);
  3013. proto_tree_add_item (notif_tree, hf_notif_on_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  3014. offset += 1;
  3015. }
  3016. /* Supplementary Information */
  3017. len = tvb_strsize (tvb, offset);
  3018. tf = proto_tree_add_uint_format (notif_tree, hf_notif_suppl_info_len,
  3019. tvb, offset, len, len,
  3020. "Supplementary Information, Length: %d",
  3021. len - 1);
  3022. if (len > 1) {
  3023. if ((offset - boffset + len) > 128) {
  3024. proto_item_append_text (tf, " (incorrect, should be less than %d)",
  3025. 128 - (offset - boffset));
  3026. }
  3027. field_tree = proto_item_add_subtree (tf, ett_notif_suppl_info);
  3028. proto_tree_add_item (field_tree, hf_notif_suppl_info, tvb, offset, len, ENC_ASCII|ENC_NA);
  3029. }
  3030. offset += len;
  3031. if ((dmp.notif_type == ON) && (on_typex < 0x03)) {
  3032. /* ACP127 Receipient */
  3033. len = tvb_strsize (tvb, offset);
  3034. tf = proto_tree_add_uint_format (notif_tree, hf_notif_acp127,
  3035. tvb, offset, len, len,
  3036. "ACP127 Recipient, Length: %d",
  3037. len - 1);
  3038. if (len > 1) {
  3039. if (len > 64) {
  3040. proto_item_append_text (tf, " (incorrect, must be less than 64)");
  3041. }
  3042. field_tree = proto_item_add_subtree (tf, ett_notif_acp127recip);
  3043. proto_tree_add_item (field_tree, hf_notif_acp127recip, tvb, offset, len, ENC_ASCII|ENC_NA);
  3044. }
  3045. offset += len;
  3046. }
  3047. } else if (dmp.notif_type == NRN) {
  3048. /* Non-Recipient Reason */
  3049. notif = tvb_get_guint8 (tvb, offset);
  3050. proto_tree_add_uint_format (notif_tree, hf_notif_non_rec_reason,
  3051. tvb, offset, 1, notif,
  3052. "Non-Receipt Reason%s: %s (%d)",
  3053. (notif < 0x10) ? " (P22)" : "",
  3054. nrn_reason_str (notif), notif);
  3055. offset += 1;
  3056. /* Discard Reason */
  3057. notif = tvb_get_guint8 (tvb, offset);
  3058. proto_tree_add_uint_format (notif_tree, hf_notif_discard_reason,
  3059. tvb, offset, 1, notif,
  3060. "Discard Reason%s: %s (%d)",
  3061. (notif < 0x10) ? " (P22)" : "",
  3062. discard_reason_str (notif), notif);
  3063. offset += 1;
  3064. }
  3065. proto_item_set_len (en, offset - boffset);
  3066. return offset;
  3067. }
  3068. /* Ref chapter 6.2.1.2.8 SecurityCategories */
  3069. static gint dissect_dmp_security_category (tvbuff_t *tvb, packet_info *pinfo,
  3070. proto_tree *tree,
  3071. const gchar **label_string,
  3072. gint offset, guint8 ext)
  3073. {
  3074. proto_tree *field_tree = NULL;
  3075. proto_item *tf = NULL, *tr = NULL;
  3076. gchar *sec_cat = NULL;
  3077. guint8 message;
  3078. gboolean country_code = FALSE;
  3079. message = tvb_get_guint8 (tvb, offset);
  3080. tf = proto_tree_add_uint_format (tree, hf_message_sec_cat_nat, tvb,
  3081. offset, 1, message, "Security Categories");
  3082. field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
  3083. switch (ext) {
  3084. case SEC_CAT_EXT_NONE:
  3085. proto_tree_add_item (field_tree, hf_message_sec_cat_cl, tvb, offset, 1, ENC_BIG_ENDIAN);
  3086. proto_tree_add_item (field_tree, hf_message_sec_cat_cs, tvb, offset, 1, ENC_BIG_ENDIAN);
  3087. proto_tree_add_item (field_tree, hf_message_sec_cat_ex, tvb, offset, 1, ENC_BIG_ENDIAN);
  3088. proto_tree_add_item (field_tree, hf_message_sec_cat_ne, tvb, offset, 1, ENC_BIG_ENDIAN);
  3089. tr = proto_tree_add_item (field_tree, hf_reserved_0x08, tvb, offset, 1, ENC_BIG_ENDIAN);
  3090. if (message & 0x08) {
  3091. expert_add_info(pinfo, tr, &ei_reserved_value);
  3092. }
  3093. tr = proto_tree_add_item (field_tree, hf_reserved_0x04, tvb, offset, 1, ENC_BIG_ENDIAN);
  3094. if (message & 0x04) {
  3095. expert_add_info(pinfo, tr, &ei_reserved_value);
  3096. }
  3097. if (message & 0xF0) {
  3098. sec_cat = ep_strdup_printf ("%s%s%s%s",
  3099. (message & 0x80) ? ",cl" : "",
  3100. (message & 0x40) ? ",cs" : "",
  3101. (message & 0x20) ? ",ex" : "",
  3102. (message & 0x10) ? ",ne" : "");
  3103. proto_item_append_text (tf, ": %s", &sec_cat[1]);
  3104. *label_string = ep_strconcat(*label_string, sec_cat, NULL);
  3105. }
  3106. break;
  3107. case SEC_CAT_EXT_PERMISSIVE:
  3108. if ((message >> 2) == 0x3F) {
  3109. /* Fake entry because nat_pol_id defines 0x3F as reserved */
  3110. proto_tree_add_uint_format (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1,
  3111. message, "1111 11.. = Next byte has Country Code (0x3F)");
  3112. country_code = TRUE;
  3113. } else {
  3114. tr = proto_tree_add_item (field_tree, hf_message_sec_cat_permissive, tvb, offset, 1, ENC_BIG_ENDIAN);
  3115. proto_item_append_text (tf, ": rel-to-%s", get_nat_pol_id_short (message >> 2));
  3116. *label_string = ep_strdup_printf("%s,rel-to-%s", *label_string, get_nat_pol_id_short (message >> 2));
  3117. if ((message >> 2) == 0) {
  3118. expert_add_info(pinfo, tr, &ei_reserved_value);
  3119. }
  3120. }
  3121. break;
  3122. case SEC_CAT_EXT_RESTRICTIVE:
  3123. proto_tree_add_item (field_tree, hf_message_sec_cat_restrictive, tvb, offset, 1, ENC_BIG_ENDIAN);
  3124. proto_item_append_text (tf, " (restrictive: 0x%2.2x)", message >> 2);
  3125. break;
  3126. default:
  3127. break;
  3128. }
  3129. proto_item_append_text (tf, " (0x%2.2x)", message);
  3130. if (dmp.version == 1) {
  3131. tr = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
  3132. if (message & 0x02) {
  3133. expert_add_info(pinfo, tr, &ei_reserved_value);
  3134. }
  3135. tr = proto_tree_add_item (field_tree, hf_reserved_0x01, tvb, offset, 1, ENC_BIG_ENDIAN);
  3136. if (message & 0x01) {
  3137. expert_add_info(pinfo, tr, &ei_reserved_value);
  3138. }
  3139. } else {
  3140. tr = proto_tree_add_item (field_tree, hf_message_sec_cat_extended, tvb, offset, 1, ENC_BIG_ENDIAN);
  3141. if ((message & 0x01) && (message & 0x02)) {
  3142. expert_add_info(pinfo, tr, &ei_reserved_value);
  3143. } else if (message & 0x01 || message & 0x02) {
  3144. proto_item_append_text (tf, " (extended)");
  3145. offset = dissect_dmp_security_category (tvb, pinfo, tree, label_string, offset+1, message & 0x03);
  3146. }
  3147. if (country_code) {
  3148. proto_tree_add_item (field_tree, hf_message_sec_cat_country_code, tvb, offset+1, 1, ENC_BIG_ENDIAN);
  3149. proto_item_append_text (tf, " (rel-to country-code: %d)", tvb_get_guint8 (tvb, offset+1));
  3150. proto_item_set_len (tf, 2);
  3151. offset++;
  3152. }
  3153. }
  3154. return offset;
  3155. }
  3156. /*
  3157. * Ref chapter 6.3.7.1 STANAG 4406 message structure
  3158. * and chapter 6.3.8.1 IPM 88 message structure
  3159. * and chapter 6.3.9.1 Report structure
  3160. * and chapter 6.3.10.1 Notification structure
  3161. */
  3162. static gint dissect_dmp_content (tvbuff_t *tvb, packet_info *pinfo,
  3163. proto_tree *dmp_tree, gint offset)
  3164. {
  3165. proto_tree *message_tree = NULL;
  3166. proto_tree *field_tree = NULL;
  3167. proto_item *en = NULL, *ei = NULL, *tf = NULL;
  3168. proto_item *hidden_item;
  3169. const char *label_string = ep_strdup ("");
  3170. const gchar *class_name = NULL;
  3171. guint8 message, dmp_sec_pol, dmp_sec_class, dmp_nation = 0, exp_time, dtg;
  3172. gint32 secs = 0;
  3173. guint prev_rec_no = 0;
  3174. gint rep_len, rep_no = 1;
  3175. gint loffset, boffset = offset;
  3176. if (dmp.msg_type == REPORT) {
  3177. en = proto_tree_add_item (dmp_tree, hf_report_content, tvb, offset, 7, ENC_NA);
  3178. } else if (dmp.msg_type == NOTIF) {
  3179. en = proto_tree_add_item (dmp_tree, hf_notif_content, tvb, offset, 7, ENC_NA);
  3180. } else {
  3181. en = proto_tree_add_item (dmp_tree, hf_message_content, tvb, offset, 7, ENC_NA);
  3182. }
  3183. message_tree = proto_item_add_subtree (en, ett_content);
  3184. if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
  3185. message = tvb_get_guint8 (tvb, offset);
  3186. dmp.body_format = (message & 0x03);
  3187. if (dmp.msg_type == STANAG) {
  3188. /* Message Type */
  3189. dmp.st_type = (message & 0xC0) >> 6;
  3190. tf = proto_tree_add_uint_format (message_tree, hf_message_st_type,
  3191. tvb, offset, 1, message,
  3192. "Message Type: %s (%d)",
  3193. val_to_str_const (dmp.st_type,
  3194. message_type_vals, ""),
  3195. dmp.st_type);
  3196. field_tree = proto_item_add_subtree (tf, ett_message_st_type);
  3197. proto_tree_add_item (field_tree, hf_message_st_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  3198. if ((message & 0x20) >> 5) {
  3199. /* Reserved */
  3200. tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x20,
  3201. tvb, offset, 1, message,
  3202. "Reserved: %d", (message & 0x20)>>5);
  3203. field_tree = proto_item_add_subtree (tf, ett_message_reserved);
  3204. tf = proto_tree_add_item (field_tree, hf_reserved_0x20, tvb, offset, 1, ENC_BIG_ENDIAN);
  3205. expert_add_info(pinfo, tf, &ei_reserved_value);
  3206. }
  3207. /* Precedence */
  3208. dmp.prec = (message & 0x1C) >> 2;
  3209. tf = proto_tree_add_uint_format (message_tree, hf_message_precedence,
  3210. tvb, offset, 1, message,
  3211. "Precedence: %s (%d)",
  3212. val_to_str_const (dmp.prec, precedence, ""),
  3213. dmp.prec);
  3214. field_tree = proto_item_add_subtree (tf, ett_message_precedence);
  3215. proto_tree_add_item (field_tree, hf_message_precedence, tvb, offset, 1, ENC_BIG_ENDIAN);
  3216. } else {
  3217. if ((message & 0xE0) >> 5) {
  3218. /* Reserved */
  3219. tf = proto_tree_add_uint_format (message_tree, hf_reserved_0xE0,
  3220. tvb, offset, 1, message,
  3221. "Reserved: %d", (message & 0xE0)>>5);
  3222. field_tree = proto_item_add_subtree (tf, ett_message_reserved);
  3223. tf = proto_tree_add_item (field_tree, hf_reserved_0xE0, tvb, offset, 1, ENC_BIG_ENDIAN);
  3224. expert_add_info(pinfo, tf, &ei_reserved_value);
  3225. }
  3226. /* Importance */
  3227. dmp.prec = (message & 0x1C) >> 2;
  3228. tf = proto_tree_add_uint_format (message_tree, hf_message_importance,
  3229. tvb, offset, 1, message,
  3230. "Importance: %s (%d)",
  3231. val_to_str_const (dmp.prec, importance, ""),
  3232. dmp.prec);
  3233. field_tree = proto_item_add_subtree (tf, ett_message_importance);
  3234. proto_tree_add_item (field_tree, hf_message_importance, tvb, offset, 1, ENC_BIG_ENDIAN);
  3235. }
  3236. /* Body Format */
  3237. tf = proto_tree_add_uint_format (message_tree, hf_message_body_format,
  3238. tvb, offset, 1, message,
  3239. "Body Format: %s (%d)",
  3240. val_to_str_const (message & 0x03,
  3241. body_format_vals, ""),
  3242. message & 0x03);
  3243. field_tree = proto_item_add_subtree (tf, ett_message_body_format);
  3244. proto_tree_add_item (field_tree, hf_message_body_format, tvb, offset, 1, ENC_BIG_ENDIAN);
  3245. offset += 1;
  3246. }
  3247. message = tvb_get_guint8 (tvb, offset);
  3248. /* Security Classification */
  3249. dmp_sec_class = (message & 0xE0) >> 5;
  3250. dmp_sec_pol = (message & 0x1C) >> 2;
  3251. if (dmp_sec_pol == EXTENDED_NATIONAL) {
  3252. dmp_nation = tvb_get_guint8 (tvb, offset + 1);
  3253. }
  3254. loffset = offset; /* Offset to start of security label */
  3255. if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
  3256. class_name = dmp_national_sec_class (dmp_local_nation, dmp_sec_class);
  3257. } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
  3258. class_name = dmp_national_sec_class (dmp_nation, dmp_sec_class);
  3259. }
  3260. if ((dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL) && !class_name) {
  3261. class_name = val_to_str_const (dmp_sec_class, sec_class, "");
  3262. }
  3263. if (class_name && class_name[0]) {
  3264. tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
  3265. tvb, offset, 1, message,
  3266. "Security Classification: %s (%d)",
  3267. class_name, dmp_sec_class);
  3268. } else {
  3269. tf = proto_tree_add_uint_format (message_tree, hf_message_sec_class_val,
  3270. tvb, offset, 1, message,
  3271. "Security Classification: %d",
  3272. dmp_sec_class);
  3273. }
  3274. field_tree = proto_item_add_subtree (tf, ett_message_sec_class);
  3275. tf = proto_tree_add_item (field_tree, hf_message_sec_class_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  3276. if (class_name) {
  3277. proto_item_append_text (tf, " (%s)", class_name);
  3278. label_string = ep_strconcat(label_string, class_name, NULL);
  3279. }
  3280. /* Security Policy */
  3281. tf = proto_tree_add_uint_format (message_tree, hf_message_sec_pol,
  3282. tvb, offset, 1, message,
  3283. "Security Policy: %s (%d)",
  3284. val_to_str (dmp_sec_pol, sec_pol, "%d"),
  3285. dmp_sec_pol);
  3286. field_tree = proto_item_add_subtree (tf, ett_message_sec_pol);
  3287. proto_tree_add_item (field_tree, hf_message_sec_pol, tvb, offset, 1, ENC_BIG_ENDIAN);
  3288. if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
  3289. /* Heading Flags */
  3290. tf = proto_tree_add_item (message_tree, hf_message_heading_flags, tvb, offset, 1, ENC_NA);
  3291. field_tree = proto_item_add_subtree (tf, ett_message_heading_flags);
  3292. proto_tree_add_item (field_tree, hf_message_auth_users, tvb, offset, 1, ENC_BIG_ENDIAN);
  3293. proto_tree_add_item (field_tree, hf_message_subject_disc, tvb, offset, 1, ENC_BIG_ENDIAN);
  3294. if (message & 0x03) {
  3295. proto_item_append_text (tf, ": %s%s%s discarded",
  3296. (message & 0x02) ? "Authorizing users" : "",
  3297. (message & 0x03) == 0x03 ? " and " : "",
  3298. (message & 0x01) ? "Subject" : "");
  3299. } else {
  3300. proto_item_append_text (tf, " (none)");
  3301. }
  3302. } else if (dmp.msg_type == NOTIF) {
  3303. /* Notification Type */
  3304. dmp.notif_type = (message & 0x03);
  3305. tf = proto_tree_add_uint_format (message_tree, hf_notif_type,
  3306. tvb, offset, 1, message,
  3307. "Notification Type: %s",
  3308. val_to_str_const (dmp.notif_type, notif_type,
  3309. "Reserved"));
  3310. field_tree = proto_item_add_subtree (tf, ett_notif_type);
  3311. proto_tree_add_item (field_tree, hf_notif_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  3312. } else if (message & 0x02) {
  3313. /* Reserved */
  3314. tf = proto_tree_add_uint_format (message_tree, hf_reserved_0x02,
  3315. tvb, offset, 1, message,
  3316. "Reserved: %d", message & 0x02);
  3317. field_tree = proto_item_add_subtree (tf, ett_message_reserved);
  3318. tf = proto_tree_add_item (field_tree, hf_reserved_0x02, tvb, offset, 1, ENC_BIG_ENDIAN);
  3319. expert_add_info(pinfo, tf, &ei_reserved_value);
  3320. }
  3321. offset += 1;
  3322. if (dmp_sec_pol == NATIONAL && dmp_local_nation != 0) {
  3323. /* Show configured national policy */
  3324. tf = proto_tree_add_uint (message_tree, hf_message_national_policy_id,
  3325. tvb, offset, 0, dmp_local_nation);
  3326. PROTO_ITEM_SET_GENERATED (tf);
  3327. } else if (dmp_sec_pol == EXTENDED_NATIONAL) {
  3328. /* National Policy Identifier */
  3329. proto_tree_add_item (message_tree, hf_message_national_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
  3330. offset += 1;
  3331. } else if (dmp_sec_pol == EXTENDED_MISSION) {
  3332. /* Mission Policy Identifier */
  3333. message = tvb_get_guint8 (tvb, offset);
  3334. if (message == 0xFF) {
  3335. proto_tree_add_uint_format (message_tree, hf_message_mission_policy_id,
  3336. tvb, offset, 1, message,
  3337. "Mission Policy Identifier: Reserved (0xFF)");
  3338. } else {
  3339. proto_tree_add_item (message_tree, hf_message_mission_policy_id, tvb, offset, 1, ENC_BIG_ENDIAN);
  3340. }
  3341. offset += 1;
  3342. }
  3343. /* Security Categories */
  3344. if (dmp_sec_pol == NATO || dmp_sec_pol == NATIONAL || dmp_sec_pol == EXTENDED_NATIONAL) {
  3345. offset = dissect_dmp_security_category (tvb, pinfo, message_tree, &label_string, offset, 0);
  3346. proto_item_append_text (en, ", Security Label: %s", label_string);
  3347. tf = proto_tree_add_string (message_tree, hf_message_sec_label, tvb, loffset,
  3348. offset - loffset + 1, label_string);
  3349. PROTO_ITEM_SET_GENERATED (tf);
  3350. } else {
  3351. tf = proto_tree_add_item (message_tree, hf_message_sec_cat_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  3352. field_tree = proto_item_add_subtree (tf, ett_message_sec_cat);
  3353. proto_tree_add_item (field_tree, hf_message_sec_cat_bit7, tvb, offset, 1, ENC_BIG_ENDIAN);
  3354. proto_tree_add_item (field_tree, hf_message_sec_cat_bit6, tvb, offset, 1, ENC_BIG_ENDIAN);
  3355. proto_tree_add_item (field_tree, hf_message_sec_cat_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
  3356. proto_tree_add_item (field_tree, hf_message_sec_cat_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
  3357. proto_tree_add_item (field_tree, hf_message_sec_cat_bit3, tvb, offset, 1, ENC_BIG_ENDIAN);
  3358. proto_tree_add_item (field_tree, hf_message_sec_cat_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
  3359. proto_tree_add_item (field_tree, hf_message_sec_cat_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
  3360. proto_tree_add_item (field_tree, hf_message_sec_cat_bit0, tvb, offset, 1, ENC_BIG_ENDIAN);
  3361. }
  3362. offset += 1;
  3363. if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
  3364. /* Expiry Time */
  3365. exp_time = tvb_get_guint8 (tvb, offset);
  3366. tf = proto_tree_add_uint_format (message_tree, hf_message_exp_time,
  3367. tvb, offset, 1, exp_time,
  3368. "Expiry Time: ");
  3369. field_tree = proto_item_add_subtree (tf, ett_message_exp_time);
  3370. ei = proto_tree_add_item (field_tree, hf_message_exp_time_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  3371. secs = dmp_dec_exp_time (exp_time);
  3372. if (secs == DMP_TIME_NOT_PRESENT) {
  3373. proto_item_append_text (tf, "Not present");
  3374. proto_item_append_text (ei, " (not present)");
  3375. } else if (secs == DMP_TIME_RESERVED) {
  3376. proto_item_append_text (tf, "Reserved (0x%2.2x)", exp_time);
  3377. proto_item_append_text (ei, " (Reserved)");
  3378. } else {
  3379. proto_item_append_text (tf, "%s (%s)", time_secs_to_str (secs),
  3380. abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE));
  3381. proto_item_append_text (ei, " (%s from submission time)", time_secs_to_str (secs));
  3382. }
  3383. offset += 1;
  3384. }
  3385. if (dmp.msg_type == STANAG) {
  3386. dtg = tvb_get_guint8 (tvb, offset);
  3387. tf = proto_tree_add_uint_format (message_tree, hf_message_dtg, tvb, offset, 1, dtg, "DTG: ");
  3388. field_tree = proto_item_add_subtree (tf, ett_message_dtg);
  3389. proto_tree_add_item (field_tree, hf_message_dtg_sign, tvb, offset, 1, ENC_BIG_ENDIAN);
  3390. proto_tree_add_item (field_tree, hf_message_dtg_val, tvb, offset, 1, ENC_BIG_ENDIAN);
  3391. secs = dmp_dec_dtg (dtg & 0x7F);
  3392. if (secs == DMP_TIME_NOT_PRESENT) {
  3393. proto_item_append_text (tf, "Not present");
  3394. } else if (secs == DMP_TIME_RESERVED) {
  3395. proto_item_append_text (tf, "Reserved (0x%2.2x)", dtg & 0x7F);
  3396. } else if (secs == 0) {
  3397. proto_item_append_text (tf, "0 minutes in the %s (%s)",
  3398. (dtg & 0x80) ? dtg_sign.true_string :
  3399. dtg_sign.false_string,
  3400. abs_time_secs_to_str (dmp.subm_time, ABSOLUTE_TIME_LOCAL, TRUE));
  3401. } else {
  3402. proto_item_append_text (tf, "%s in the %s (%s)", time_secs_to_str(secs),
  3403. (dtg & 0x80) ? dtg_sign.true_string :
  3404. dtg_sign.false_string, (dtg & 0x80) ?
  3405. abs_time_secs_to_str (dmp.subm_time + secs, ABSOLUTE_TIME_LOCAL, TRUE) :
  3406. abs_time_secs_to_str (dmp.subm_time - secs, ABSOLUTE_TIME_LOCAL, TRUE));
  3407. }
  3408. offset += 1;
  3409. }
  3410. if (dmp.msg_type == STANAG) {
  3411. /* SIC */
  3412. offset = dissect_dmp_sic (tvb, pinfo, message_tree, offset);
  3413. } else if (dmp.msg_type == REPORT || dmp.msg_type == NOTIF) {
  3414. if (dmp.version == DMP_VERSION_1 || dmp.msg_id_type == ONLY_DMP_ID) {
  3415. /* Subject Message Identifier */
  3416. dmp.subj_id = tvb_get_ntohs (tvb, offset);
  3417. proto_tree_add_item (message_tree, hf_message_subj_id, tvb, offset, 2, ENC_BIG_ENDIAN);
  3418. hidden_item = proto_tree_add_item (message_tree, hf_dmp_id, tvb, offset, 2, ENC_BIG_ENDIAN);
  3419. PROTO_ITEM_SET_HIDDEN (hidden_item);
  3420. offset += 2;
  3421. } else if (dmp.msg_id_type == X400_MSG_ID || dmp.msg_id_type == NAT_MSG_ID) {
  3422. if (dmp.msg_type == REPORT) {
  3423. /* Subject MTS Identifier */
  3424. offset = dissect_mts_identifier (tvb, pinfo, message_tree, offset, TRUE);
  3425. } else {
  3426. /* Subject IPM Identifier */
  3427. offset = dissect_ipm_identifier (tvb, pinfo, message_tree, offset, TRUE);
  3428. }
  3429. if (dmp.subj_id) {
  3430. tf = proto_tree_add_uint (message_tree, hf_message_subj_id, tvb, offset, 0, dmp.subj_id);
  3431. PROTO_ITEM_SET_GENERATED (tf);
  3432. hidden_item = proto_tree_add_uint (message_tree, hf_dmp_id, tvb, offset, 0, dmp.subj_id);
  3433. PROTO_ITEM_SET_GENERATED (hidden_item);
  3434. PROTO_ITEM_SET_HIDDEN (hidden_item);
  3435. }
  3436. }
  3437. }
  3438. if (use_seq_ack_analysis) {
  3439. register_dmp_id (pinfo, 0);
  3440. }
  3441. proto_item_set_len (en, offset - boffset);
  3442. if (dmp.msg_type == STANAG || dmp.msg_type == IPM) {
  3443. /* User Data */
  3444. offset = dissect_dmp_message (tvb, pinfo, dmp_tree, offset);
  3445. } else if (dmp.msg_type == REPORT) {
  3446. /* One or more Delivery Report or Non-Delivery Report Data */
  3447. rep_len = tvb_length (tvb);
  3448. if (dmp.checksum) {
  3449. rep_len -= 2;
  3450. }
  3451. while (offset < rep_len) {
  3452. offset = dissect_dmp_report (tvb, pinfo, dmp_tree, offset, &prev_rec_no, rep_no++);
  3453. }
  3454. } else if (dmp.msg_type == NOTIF) {
  3455. /* Notification Data */
  3456. offset = dissect_dmp_notification (tvb, pinfo, dmp_tree, offset);
  3457. }
  3458. return offset;
  3459. }
  3460. static gint dissect_dmp_extensions (tvbuff_t *tvb, packet_info *pinfo _U_,
  3461. proto_tree *dmp_tree, gint offset)
  3462. {
  3463. proto_tree *exts_tree, *ext_tree, *hdr_tree;
  3464. proto_item *exts_item, *en;
  3465. guint8 ext_hdr, ext_length;
  3466. gboolean more_extensions = TRUE;
  3467. gint num_ext = 0, boffset = offset;
  3468. exts_item = proto_tree_add_item (dmp_tree, hf_extensions, tvb, offset, -1, ENC_NA);
  3469. exts_tree = proto_item_add_subtree (exts_item, ett_extensions);
  3470. while (more_extensions) {
  3471. /* Extensions Present */
  3472. ext_hdr = tvb_get_guint8 (tvb, offset);
  3473. more_extensions = (ext_hdr & 0x80);
  3474. ext_length = (ext_hdr & 0x7F) + 1;
  3475. en = proto_tree_add_none_format (exts_tree, hf_extension, tvb, offset, ext_length + 1,
  3476. "Extension (#%d)", num_ext + 1);
  3477. ext_tree = proto_item_add_subtree (en, ett_extension);
  3478. en = proto_tree_add_none_format (ext_tree, hf_extension_header, tvb, offset, 1,
  3479. "Extension Length: %u, More %s", ext_length,
  3480. (ext_hdr & 0x80) ? "Present" : "Not present");
  3481. hdr_tree = proto_item_add_subtree (en, ett_extension_header);
  3482. proto_tree_add_item (hdr_tree, hf_extension_more, tvb, offset, 1, ENC_BIG_ENDIAN);
  3483. proto_tree_add_item (hdr_tree, hf_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
  3484. offset += 1;
  3485. proto_tree_add_item (ext_tree, hf_extension_data, tvb, offset, ext_length, ENC_NA);
  3486. offset += ext_length;
  3487. num_ext++;
  3488. }
  3489. proto_item_append_text (exts_item, " (%d item%s)", num_ext, plurality (num_ext, "", "s"));
  3490. proto_item_set_len (exts_item, offset - boffset);
  3491. return offset;
  3492. }
  3493. static void dissect_dmp (tvbuff_t *tvb, packet_info *pinfo,
  3494. proto_tree *tree)
  3495. {
  3496. proto_tree *dmp_tree = NULL, *checksum_tree = NULL;
  3497. proto_item *ti = NULL, *en = NULL;
  3498. guint16 checksum1 = 0, checksum2 = 1;
  3499. gint length, offset = 0;
  3500. gboolean retrans_or_dup_ack = FALSE;
  3501. col_set_str (pinfo->cinfo, COL_PROTOCOL, "DMP");
  3502. col_clear (pinfo->cinfo, COL_INFO);
  3503. /* Initialize global data structure */
  3504. memset (&dmp, 0, sizeof (dmp));
  3505. ti = proto_tree_add_item (tree, proto_dmp, tvb, offset, -1, ENC_NA);
  3506. dmp_tree = proto_item_add_subtree (ti, ett_dmp);
  3507. offset = dissect_dmp_envelope (tvb, pinfo, dmp_tree, offset);
  3508. if (dmp.version > DMP_VERSION_2) {
  3509. /* Unsupported DMP Version, no point to continue */
  3510. col_add_fstr (pinfo->cinfo, COL_INFO, "Unsupported Version: %d", dmp.version);
  3511. return;
  3512. }
  3513. if (dmp.extensions) {
  3514. offset = dissect_dmp_extensions (tvb, pinfo, dmp_tree, offset);
  3515. }
  3516. if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
  3517. (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
  3518. {
  3519. offset = dissect_dmp_content (tvb, pinfo, dmp_tree, offset);
  3520. } else if (dmp.msg_type == ACK) {
  3521. offset = dissect_dmp_ack (tvb, pinfo, dmp_tree, offset);
  3522. }
  3523. if (dmp.checksum) {
  3524. length = tvb_length (tvb);
  3525. checksum1 = crc16_x25_ccitt_tvb (tvb, length - 2);
  3526. checksum2 = tvb_get_ntohs (tvb, offset);
  3527. en = proto_tree_add_item (dmp_tree, hf_checksum, tvb, offset, 2, ENC_BIG_ENDIAN);
  3528. checksum_tree = proto_item_add_subtree (en, ett_checksum);
  3529. if (checksum1 == checksum2) {
  3530. proto_item_append_text (en, " (correct)");
  3531. en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
  3532. offset, 2, TRUE);
  3533. PROTO_ITEM_SET_GENERATED (en);
  3534. en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
  3535. offset, 2, FALSE);
  3536. PROTO_ITEM_SET_GENERATED (en);
  3537. } else {
  3538. proto_item_append_text (en, " (incorrect, should be 0x%04x)",
  3539. checksum1);
  3540. expert_add_info_format (pinfo, en, PI_CHECKSUM, PI_WARN, "Bad checksum");
  3541. en = proto_tree_add_boolean (checksum_tree, hf_checksum_good, tvb,
  3542. offset, 2, FALSE);
  3543. PROTO_ITEM_SET_GENERATED (en);
  3544. en = proto_tree_add_boolean (checksum_tree, hf_checksum_bad, tvb,
  3545. offset, 2, TRUE);
  3546. PROTO_ITEM_SET_GENERATED (en);
  3547. }
  3548. }
  3549. if (use_seq_ack_analysis) {
  3550. dmp_add_seq_ack_analysis (tvb, pinfo, dmp_tree, offset);
  3551. }
  3552. if (((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
  3553. (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF)) &&
  3554. dmp.id_val && dmp.id_val->msg_resend_count)
  3555. {
  3556. guint retrans_num;
  3557. if (dmp.msg_type == REPORT) {
  3558. retrans_num = dmp.id_val->rep_id;
  3559. } else if (dmp.msg_type == NOTIF) {
  3560. retrans_num = dmp.id_val->not_id;
  3561. } else {
  3562. retrans_num = dmp.id_val->msg_id;
  3563. }
  3564. col_append_fstr (pinfo->cinfo, COL_INFO, "[Retrans %d#%d] ",
  3565. retrans_num, dmp.id_val->msg_resend_count);
  3566. retrans_or_dup_ack = TRUE;
  3567. } else if (dmp.msg_type == ACK && dmp.id_val && dmp.id_val->ack_resend_count) {
  3568. col_append_fstr (pinfo->cinfo, COL_INFO, "[Dup ACK %d#%d] ",
  3569. dmp.id_val->ack_id, dmp.id_val->ack_resend_count);
  3570. retrans_or_dup_ack = TRUE;
  3571. }
  3572. if (dmp_align && !retrans_or_dup_ack) {
  3573. if (dmp.msg_type == ACK) {
  3574. /* ACK does not have "Msg Id" */
  3575. col_append_fstr (pinfo->cinfo, COL_INFO, "%-45.45s", msg_type_to_str ());
  3576. } else {
  3577. col_append_fstr (pinfo->cinfo, COL_INFO, "%-31.31s", msg_type_to_str ());
  3578. }
  3579. } else {
  3580. col_append_str (pinfo->cinfo, COL_INFO, msg_type_to_str ());
  3581. }
  3582. if ((dmp.msg_type == STANAG) || (dmp.msg_type == IPM) ||
  3583. (dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF))
  3584. {
  3585. if (dmp_align && !retrans_or_dup_ack) {
  3586. col_append_fstr (pinfo->cinfo, COL_INFO, " Msg Id: %5d", dmp.msg_id);
  3587. } else {
  3588. col_append_fstr (pinfo->cinfo, COL_INFO, ", Msg Id: %d", dmp.msg_id);
  3589. }
  3590. }
  3591. if ((dmp.msg_type == REPORT) || (dmp.msg_type == NOTIF) ||
  3592. (dmp.msg_type == ACK))
  3593. {
  3594. if (dmp_align && !retrans_or_dup_ack) {
  3595. col_append_fstr (pinfo->cinfo, COL_INFO, " Subj Id: %5d",
  3596. dmp.subj_id);
  3597. } else {
  3598. col_append_fstr (pinfo->cinfo, COL_INFO, ", Subj Id: %d",
  3599. dmp.subj_id);
  3600. }
  3601. } else if (dmp.struct_id) {
  3602. if (dmp_align && !retrans_or_dup_ack) {
  3603. col_append_fstr (pinfo->cinfo, COL_INFO, " Body Id: %s",
  3604. format_text (dmp.struct_id, strlen (dmp.struct_id)));
  3605. } else {
  3606. col_append_fstr (pinfo->cinfo, COL_INFO, ", Body Id: %s",
  3607. format_text (dmp.struct_id, strlen (dmp.struct_id)));
  3608. }
  3609. }
  3610. if (dmp.checksum && (checksum1 != checksum2)) {
  3611. col_append_str (pinfo->cinfo, COL_INFO, ", Checksum incorrect");
  3612. }
  3613. proto_item_append_text (ti, ", Version: %d%s, %s", dmp.version,
  3614. (dmp.prot_id == PROT_NAT ? " (national)" : ""),
  3615. msg_type_to_str());
  3616. }
  3617. static void dmp_init_routine (void)
  3618. {
  3619. if (dmp_id_hash_table) {
  3620. g_hash_table_destroy (dmp_id_hash_table);
  3621. }
  3622. if (dmp_long_id_hash_table) {
  3623. g_hash_table_destroy (dmp_long_id_hash_table);
  3624. }
  3625. dmp_id_hash_table = g_hash_table_new (dmp_id_hash, dmp_id_hash_equal);
  3626. dmp_long_id_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
  3627. }
  3628. void proto_register_dmp (void)
  3629. {
  3630. static hf_register_info hf[] = {
  3631. /*
  3632. ** DMP Identifier
  3633. */
  3634. { &hf_dmp_id,
  3635. { "DMP Identifier", "dmp.id", FT_UINT16, BASE_DEC,
  3636. NULL, 0x0, NULL, HFILL}},
  3637. /* MTS Identifier */
  3638. { &hf_mts_id,
  3639. { "MTS Identifier", "dmp.mts", FT_STRING, BASE_NONE,
  3640. NULL, 0x0, NULL, HFILL } },
  3641. /* IPM Identifier */
  3642. { &hf_ipm_id,
  3643. { "IPM Identifier", "dmp.ipm", FT_STRING, BASE_NONE,
  3644. NULL, 0x0, NULL, HFILL } },
  3645. /*
  3646. ** Envelope
  3647. */
  3648. { &hf_envelope,
  3649. { "Envelope", "dmp.envelope", FT_NONE, BASE_NONE,
  3650. NULL, 0x0, NULL, HFILL}},
  3651. /* Protocol data */
  3652. { &hf_envelope_protocol_id,
  3653. { "Protocol Identifier", "dmp.protocol_id", FT_UINT8,
  3654. BASE_HEX, NULL, 0xF8, NULL, HFILL}},
  3655. { &hf_envelope_version,
  3656. { "Protocol Version", "dmp.version", FT_UINT8, BASE_DEC,
  3657. VALS(version_vals), 0x07, NULL, HFILL } },
  3658. { &hf_envelope_version_value,
  3659. { "Protocol Version", "dmp.version_value", FT_UINT8, BASE_DEC,
  3660. VALS(version_vals), 0x07, NULL, HFILL } },
  3661. /* Envelope elements (byte 1) */
  3662. { &hf_envelope_hop_count,
  3663. { "Hop Count", "dmp.hop_count", FT_UINT8, BASE_DEC,
  3664. NULL, 0xE0, NULL, HFILL } },
  3665. { &hf_envelope_hop_count_value,
  3666. { "Hop Count", "dmp.hop_count_value", FT_UINT8, BASE_DEC,
  3667. NULL, 0xE0, NULL, HFILL } },
  3668. { &hf_envelope_rec_present,
  3669. { "Recipient Present", "dmp.rec_present", FT_BOOLEAN, 8,
  3670. TFS (&tfs_present_absent), 0x20, NULL, HFILL } },
  3671. { &hf_envelope_addr_enc,
  3672. { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
  3673. TFS (&addr_enc), 0x10, NULL, HFILL } },
  3674. { &hf_envelope_checksum,
  3675. { "Checksum", "dmp.checksum_used", FT_BOOLEAN, 8,
  3676. TFS (&tfs_used_notused), 0x08, "Checksum Used", HFILL } },
  3677. { &hf_envelope_type,
  3678. { "Content Type", "dmp.content_type", FT_UINT8, BASE_DEC,
  3679. VALS(type_vals), 0x07, NULL, HFILL } },
  3680. /* Envelope elements (byte 2) */
  3681. { &hf_envelope_extensions,
  3682. { "Extensions", "dmp.extensions_used", FT_BOOLEAN, 8,
  3683. TFS (&tfs_present_absent), 0x80, "Extensions Used", HFILL } },
  3684. { &hf_envelope_msg_id_type,
  3685. { "Message Identifier Type", "dmp.msg_id_type", FT_UINT8, BASE_DEC,
  3686. VALS(msg_id_type_vals), 0x60, NULL, HFILL } },
  3687. { &hf_envelope_msg_id_length,
  3688. { "Message Identifier Length", "dmp.msg_id_short", FT_UINT8, BASE_DEC,
  3689. VALS(msg_id_length_vals), 0x10, NULL, HFILL}},
  3690. { &hf_envelope_mts_id_length,
  3691. { "MTS Identifier Length", "dmp.mts_id_length", FT_UINT8, BASE_DEC,
  3692. NULL, 0x1F, NULL, HFILL } },
  3693. { &hf_envelope_ipm_id_modifier,
  3694. { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
  3695. VALS(ipm_id_modifier), 0xC0, NULL, HFILL } },
  3696. { &hf_envelope_ipm_id_length,
  3697. { "IPM Identifier Length", "dmp.ipm_id_length", FT_UINT8, BASE_DEC,
  3698. NULL, 0x3F, NULL, HFILL } },
  3699. { &hf_thales_ipm_id_modifier,
  3700. { "IPM Identifier Modifier", "dmp.ipm_id_modifier", FT_UINT8, BASE_DEC,
  3701. VALS(thales_ipm_id_modifier), 0xC0, "Thales XOmail IPM Identifier Modifier", HFILL } },
  3702. /* Message identifier */
  3703. { &hf_envelope_msg_id,
  3704. { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
  3705. NULL, 0x0, NULL, HFILL}},
  3706. { &hf_envelope_msg_id_12bit,
  3707. { "Message Identifier", "dmp.msg_id", FT_UINT16, BASE_DEC,
  3708. NULL, 0x0FFF, NULL, HFILL}},
  3709. /* MTS Identifier */
  3710. { &hf_envelope_mts_id,
  3711. { "MTS Identifier", "dmp.mts_id", FT_STRING, BASE_NONE,
  3712. NULL, 0x0, NULL, HFILL } },
  3713. /* IPM Identifier */
  3714. { &hf_envelope_ipm_id,
  3715. { "IPM Identifier", "dmp.ipm_id", FT_STRING, BASE_NONE,
  3716. NULL, 0x0, NULL, HFILL } },
  3717. /* Extensions */
  3718. { &hf_extensions,
  3719. { "Extensions", "dmp.extensions", FT_NONE, BASE_NONE,
  3720. NULL, 0x0, NULL, HFILL}},
  3721. { &hf_extension,
  3722. { "Extension", "dmp.extension", FT_NONE, BASE_NONE,
  3723. NULL, 0x0, NULL, HFILL } },
  3724. { &hf_extension_header,
  3725. { "Extension Header", "dmp.extension_header", FT_NONE, BASE_NONE,
  3726. NULL, 0x0, NULL, HFILL}},
  3727. { &hf_extension_more,
  3728. { "More Extensions", "dmp.extension_more", FT_BOOLEAN, 8,
  3729. TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
  3730. { &hf_extension_length,
  3731. { "Extension Length (minus one)", "dmp.extension_length", FT_UINT8, BASE_DEC,
  3732. NULL, 0x7F, "Extension Length minus one", HFILL } },
  3733. { &hf_extension_data,
  3734. { "Extension Data", "dmp.extension_data", FT_BYTES, BASE_NONE,
  3735. NULL, 0x0, NULL, HFILL } },
  3736. /* Submission time */
  3737. { &hf_envelope_subm_time,
  3738. { "Submission Time", "dmp.subm_time", FT_UINT16, BASE_HEX,
  3739. NULL, 0x0, NULL, HFILL } },
  3740. { &hf_envelope_time_diff_present,
  3741. { "Time Diff", "dmp.time_diff_present", FT_BOOLEAN, 16,
  3742. TFS (&tfs_present_absent), 0x8000, "Time Diff Present", HFILL } },
  3743. { &hf_envelope_subm_time_value,
  3744. { "Submission Time Value", "dmp.subm_time_value", FT_UINT16,
  3745. BASE_HEX, NULL, 0x7FFF, NULL, HFILL } },
  3746. { &hf_envelope_time_diff,
  3747. { "Time Difference", "dmp.time_diff", FT_UINT8, BASE_HEX,
  3748. NULL, 0xFF, NULL, HFILL } },
  3749. { &hf_envelope_time_diff_value,
  3750. { "Time Difference Value", "dmp.time_diff_value", FT_UINT8,
  3751. BASE_HEX, NULL, 0xFF, NULL, HFILL } },
  3752. /* Envelope flags */
  3753. { &hf_envelope_flags,
  3754. { "Flags", "dmp.envelope_flags", FT_UINT8, BASE_DEC,
  3755. NULL, 0x0, "Envelope Flags", HFILL}},
  3756. { &hf_envelope_content_id_discarded,
  3757. { "Content Identifier discarded", "dmp.cont_id_discarded",
  3758. FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
  3759. NULL, HFILL } },
  3760. { &hf_envelope_recip_reassign_prohib,
  3761. { "Recipient reassign prohibited","dmp.recip_reassign_prohib",
  3762. FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
  3763. NULL, HFILL }},
  3764. { &hf_envelope_dl_expansion_prohib,
  3765. { "DL expansion prohibited", "dmp.dl_expansion_prohib",
  3766. FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, NULL,
  3767. HFILL } },
  3768. /* Recipient Count */
  3769. { &hf_envelope_recipients,
  3770. { "Recipient Count", "dmp.rec_count", FT_UINT8, BASE_DEC,
  3771. NULL, 0x1F, NULL, HFILL}},
  3772. { &hf_envelope_ext_recipients,
  3773. { "Extended Recipient Count", "dmp.ext_rec_count", FT_UINT16,
  3774. BASE_DEC, NULL, 0x7FFF, NULL, HFILL}},
  3775. /*
  3776. ** Address
  3777. */
  3778. { &hf_addr_recipient,
  3779. { "Recipient Number", "dmp.recipient", FT_NONE, BASE_NONE,
  3780. NULL, 0x0, "Recipient", HFILL } },
  3781. { &hf_addr_originator,
  3782. { "Originator", "dmp.originator", FT_NONE, BASE_NONE,
  3783. NULL, 0x0, NULL, HFILL } },
  3784. { &hf_addr_reporting_name,
  3785. { "Reporting Name Number", "dmp.reporting_name", FT_NONE,
  3786. BASE_NONE, NULL, 0x0, "Reporting Name", HFILL } },
  3787. { &hf_addr_dl_expanded,
  3788. { "DL Expanded", "dmp.dl_expanded", FT_BOOLEAN, BASE_NONE,
  3789. NULL, 0x0, "Message has been DL expanded", HFILL } },
  3790. { &hf_addr_int_rec,
  3791. { "Intended Recipient", "dmp.int_rec", FT_BOOLEAN, BASE_NONE,
  3792. NULL, 0x0, "Message has an intended recipient", HFILL } },
  3793. /*
  3794. ** Address Direct
  3795. */
  3796. { &hf_addr_dir_addr_ext,
  3797. { "Address Extended", "dmp.addr_ext", FT_BOOLEAN, 8,
  3798. NULL, 0x80, NULL, HFILL } },
  3799. { &hf_addr_dir_rec_no,
  3800. { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
  3801. BASE_DEC, NULL, 0xF0, NULL, HFILL } },
  3802. { &hf_addr_dir_rec_no_generated,
  3803. { "Recipient Number", "dmp.rec_no", FT_UINT32,
  3804. BASE_DEC, NULL, 0x0, "Recipient Number Offset", HFILL } },
  3805. { &hf_addr_dir_rec_no1,
  3806. { "Recipient Number (bits 3-0)", "dmp.rec_no_offset1", FT_UINT8,
  3807. BASE_DEC, NULL, 0xF0, "Recipient Number (bits 3-0) Offset", HFILL } },
  3808. { &hf_addr_dir_rec_no2,
  3809. { "Recipient Number (bits 9-4)", "dmp.rec_no_offset2", FT_UINT8,
  3810. BASE_DEC, NULL, 0x3F, "Recipient Number (bits 9-4) Offset", HFILL } },
  3811. { &hf_addr_dir_rec_no3,
  3812. { "Recipient Number (bits 14-10)", "dmp.rec_no_offset3", FT_UINT8,
  3813. BASE_DEC, NULL, 0x1F, "Recipient Number (bits 14-10) Offset",HFILL } },
  3814. { &hf_addr_dir_rep_req1,
  3815. { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
  3816. VALS (report_vals_ext), 0x0C, NULL, HFILL } },
  3817. { &hf_addr_dir_rep_req2,
  3818. { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
  3819. VALS (report_vals_ext), 0xC0, NULL, HFILL } },
  3820. { &hf_addr_dir_rep_req3,
  3821. { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
  3822. VALS (report_vals), 0xC0, NULL, HFILL } },
  3823. { &hf_addr_dir_not_req1,
  3824. { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
  3825. VALS (notif_vals_ext), 0x03, NULL, HFILL } },
  3826. { &hf_addr_dir_not_req2,
  3827. { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
  3828. VALS (notif_vals_ext), 0xC0, NULL, HFILL } },
  3829. { &hf_addr_dir_not_req3,
  3830. { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
  3831. VALS (notif_vals), 0xC0, NULL, HFILL } },
  3832. { &hf_addr_dir_action,
  3833. { "Action", "dmp.action", FT_BOOLEAN, 8,
  3834. TFS (&tfs_yes_no), 0x80, NULL, HFILL } },
  3835. { &hf_addr_dir_address,
  3836. { "Direct Address", "dmp.direct_addr", FT_UINT8,
  3837. BASE_DEC, NULL, 0x7F, NULL, HFILL } },
  3838. { &hf_addr_dir_address_generated,
  3839. { "Direct Address", "dmp.direct_addr", FT_UINT32,
  3840. BASE_DEC, NULL, 0x0, NULL, HFILL } },
  3841. { &hf_addr_dir_address1,
  3842. { "Direct Address (bits 6-0)", "dmp.direct_addr1", FT_UINT8,
  3843. BASE_DEC, NULL, 0x7F, NULL, HFILL } },
  3844. { &hf_addr_dir_address2,
  3845. { "Direct Address (bits 12-7)", "dmp.direct_addr2", FT_UINT8,
  3846. BASE_DEC, NULL, 0x3F, NULL, HFILL } },
  3847. { &hf_addr_dir_address3,
  3848. { "Direct Address (bits 18-13)", "dmp.direct_addr3", FT_UINT8,
  3849. BASE_DEC, NULL, 0x3F, NULL, HFILL } },
  3850. /*
  3851. ** Address Extended
  3852. */
  3853. { &hf_addr_ext_form,
  3854. { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
  3855. VALS (&addr_form), 0xE0, NULL, HFILL } },
  3856. { &hf_addr_ext_form_orig_v1,
  3857. { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
  3858. VALS (&addr_form_orig_v1), 0xE0, NULL, HFILL } },
  3859. { &hf_addr_ext_form_orig,
  3860. { "Address Form", "dmp.addr_form", FT_UINT8, BASE_DEC,
  3861. VALS (&addr_form_orig), 0xE0, NULL, HFILL } },
  3862. { &hf_addr_ext_action,
  3863. { "Action", "dmp.action", FT_BOOLEAN, 8,
  3864. TFS (&tfs_yes_no), 0x10, NULL, HFILL } },
  3865. { &hf_addr_ext_rep_req,
  3866. { "Report Request", "dmp.rep_rec", FT_UINT8, BASE_HEX,
  3867. VALS (report_vals), 0x0C, NULL, HFILL } },
  3868. { &hf_addr_ext_not_req,
  3869. { "Notification Request", "dmp.not_req", FT_UINT8, BASE_HEX,
  3870. VALS (notif_vals), 0x03, NULL, HFILL } },
  3871. { &hf_addr_ext_rec_ext,
  3872. { "Recipient Number Extended", "dmp.rec_no_ext", FT_BOOLEAN, 8,
  3873. NULL, 0x80, NULL, HFILL } },
  3874. { &hf_addr_ext_rec_no,
  3875. { "Recipient Number Offset", "dmp.rec_no_offset", FT_UINT8,
  3876. BASE_DEC, NULL, 0x7F, NULL, HFILL } },
  3877. { &hf_addr_ext_rec_no_generated,
  3878. { "Recipient Number", "dmp.rec_no", FT_UINT32,
  3879. BASE_DEC, NULL, 0x0, NULL, HFILL } },
  3880. { &hf_addr_ext_rec_no1,
  3881. { "Recipient Number (bits 6-0)", "dmp.rec_no_offset1", FT_UINT8,
  3882. BASE_DEC, NULL, 0x7F, "Recipient Number (bits 6-0) Offset", HFILL } },
  3883. { &hf_addr_ext_rec_no2,
  3884. { "Recipient Number (bits 14-7)", "dmp.rec_no_offset2", FT_UINT8,
  3885. BASE_DEC, NULL, 0xFF, "Recipient Number (bits 14-7) Offset", HFILL } },
  3886. { &hf_addr_ext_address,
  3887. { "Extended Address", "dmp.addr_form", FT_NONE, BASE_NONE,
  3888. NULL, 0x0, NULL, HFILL } },
  3889. { &hf_addr_ext_type,
  3890. { "Address Type", "dmp.addr_type", FT_UINT8, BASE_DEC,
  3891. VALS (&ext_addr_type), 0xE0, NULL, HFILL } },
  3892. { &hf_addr_ext_type_ext,
  3893. { "Address Type Extended", "dmp.addr_type_ext", FT_UINT8,
  3894. BASE_DEC, VALS (&ext_addr_type_ext), 0xE0, NULL,
  3895. HFILL } },
  3896. { &hf_addr_ext_length,
  3897. { "Address Length", "dmp.addr_length", FT_UINT8,
  3898. BASE_DEC, NULL, 0x1F, NULL, HFILL } },
  3899. { &hf_addr_ext_length_generated,
  3900. { "Address Length", "dmp.addr_length", FT_UINT32,
  3901. BASE_DEC, NULL, 0x0, NULL, HFILL } },
  3902. { &hf_addr_ext_length1,
  3903. { "Address Length (bits 4-0)", "dmp.addr_length1", FT_UINT8,
  3904. BASE_DEC, NULL, 0x1F, NULL, HFILL } },
  3905. { &hf_addr_ext_length2,
  3906. { "Address Length (bits 9-5)", "dmp.addr_length2", FT_UINT8,
  3907. BASE_DEC, NULL, 0x1F, NULL, HFILL } },
  3908. { &hf_addr_ext_asn1_ber,
  3909. { "ASN.1 BER-encoded OR-name", "dmp.or_name", FT_NONE,
  3910. BASE_NONE, NULL, 0x0, NULL, HFILL } },
  3911. { &hf_addr_ext_asn1_per,
  3912. { "ASN.1 PER-encoded OR-name", "dmp.asn1_per", FT_BYTES,
  3913. BASE_NONE, NULL, 0x0, NULL, HFILL } },
  3914. { &hf_addr_ext_unknown,
  3915. { "Unknown encoded address", "dmp.addr_unknown", FT_BYTES,
  3916. BASE_NONE, NULL, 0x0, NULL, HFILL } },
  3917. /*
  3918. ** Message content
  3919. */
  3920. { &hf_message_content,
  3921. { "Message Content", "dmp.message", FT_NONE, BASE_NONE,
  3922. NULL, 0x0, NULL, HFILL } },
  3923. { &hf_report_content,
  3924. { "Report Content", "dmp.report", FT_NONE, BASE_NONE,
  3925. NULL, 0x0, NULL, HFILL } },
  3926. { &hf_notif_content,
  3927. { "Notification Content", "dmp.notification", FT_NONE, BASE_NONE,
  3928. NULL, 0x0, NULL, HFILL } },
  3929. { &hf_message_st_type,
  3930. { "Message type", "dmp.msg_type", FT_UINT8, BASE_DEC,
  3931. VALS (message_type_vals), 0xC0, NULL, HFILL } },
  3932. { &hf_message_precedence,
  3933. { "Precedence", "dmp.precedence", FT_UINT8, BASE_DEC,
  3934. VALS (precedence), 0x1C, NULL, HFILL } },
  3935. { &hf_message_importance,
  3936. { "Importance", "dmp.importance", FT_UINT8, BASE_DEC,
  3937. VALS (importance), 0x1C, NULL, HFILL } },
  3938. { &hf_message_body_format,
  3939. { "Body format", "dmp.body_format", FT_UINT8, BASE_DEC,
  3940. VALS (body_format_vals), 0x03, NULL, HFILL } },
  3941. /* Security Values */
  3942. { &hf_message_sec_label,
  3943. { "Security Label", "dmp.sec_label", FT_STRING, BASE_NONE,
  3944. NULL, 0x0, NULL, HFILL } },
  3945. { &hf_message_sec_class_val,
  3946. { "Security Classification", "dmp.sec_class", FT_UINT8,
  3947. BASE_DEC, NULL, 0xE0, NULL, HFILL}},
  3948. { &hf_message_sec_pol,
  3949. { "Security Policy", "dmp.sec_pol", FT_UINT8, BASE_DEC,
  3950. VALS (sec_pol), 0x1C, NULL, HFILL } },
  3951. { &hf_message_heading_flags,
  3952. { "Heading Flags", "dmp.heading_flags", FT_NONE, BASE_NONE,
  3953. NULL, 0x0, NULL, HFILL } },
  3954. { &hf_message_auth_users,
  3955. { "Authorizing users discarded", "dmp.auth_discarded",
  3956. FT_BOOLEAN, 8, TFS (&tfs_yes_no), 0x02,
  3957. NULL, HFILL }},
  3958. { &hf_message_subject_disc,
  3959. { "Subject discarded", "dmp.subject_discarded", FT_BOOLEAN, 8,
  3960. TFS (&tfs_yes_no), 0x01, NULL, HFILL } },
  3961. /* National Policy Identifier */
  3962. { &hf_message_national_policy_id,
  3963. { "National Policy Identifier", "dmp.nat_pol_id", FT_UINT8,
  3964. BASE_DEC, VALS(nat_pol_id), 0x0, NULL,
  3965. HFILL } },
  3966. /* Mission Policy Identifier */
  3967. { &hf_message_mission_policy_id,
  3968. { "Mission Policy Identifier", "dmp.mission_pol_id", FT_UINT8,
  3969. BASE_DEC, NULL, 0x0, NULL,
  3970. HFILL } },
  3971. /* Security Categories */
  3972. { &hf_message_sec_cat_nat,
  3973. { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
  3974. NULL, 0x0, NULL, HFILL } },
  3975. { &hf_message_sec_cat_val,
  3976. { "Security Categories", "dmp.sec_cat", FT_UINT8, BASE_HEX,
  3977. NULL, 0x0, NULL, HFILL } },
  3978. { &hf_message_sec_cat_cl,
  3979. { "Clear", "dmp.sec_cat.cl", FT_BOOLEAN, 8,
  3980. TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
  3981. { &hf_message_sec_cat_cs,
  3982. { "Crypto Security", "dmp.sec_cat.cs", FT_BOOLEAN, 8,
  3983. TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
  3984. { &hf_message_sec_cat_ex,
  3985. { "Exclusive", "dmp.sec_cat.ex", FT_BOOLEAN, 8,
  3986. TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
  3987. { &hf_message_sec_cat_ne,
  3988. { "National Eyes Only", "dmp.sec_cat.ne", FT_BOOLEAN, 8,
  3989. TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
  3990. { &hf_message_sec_cat_permissive,
  3991. { "Releasable to", "dmp.sec_cat.permissive", FT_UINT8, BASE_HEX,
  3992. VALS (nat_pol_id), 0xFC, NULL, HFILL } },
  3993. { &hf_message_sec_cat_country_code,
  3994. { "Country Code", "dmp.sec_cat.country", FT_UINT8, BASE_DEC,
  3995. NULL, 0x00, NULL, HFILL } },
  3996. { &hf_message_sec_cat_restrictive,
  3997. { "Restrictive", "dmp.sec_cat.restrictive", FT_UINT8, BASE_HEX,
  3998. NULL, 0xFC, NULL, HFILL } },
  3999. { &hf_message_sec_cat_extended,
  4000. { "Extended", "dmp.sec_cat.extended", FT_UINT8, BASE_HEX,
  4001. VALS (ext_sec_cat), 0x03, "Extended Security Category", HFILL } },
  4002. { &hf_message_sec_cat_bit0,
  4003. { "Bit 0", "dmp.sec_cat.bit0", FT_BOOLEAN, 8,
  4004. TFS (&tfs_set_notset), 0x01, NULL, HFILL } },
  4005. { &hf_message_sec_cat_bit1,
  4006. { "Bit 1", "dmp.sec_cat.bit1", FT_BOOLEAN, 8,
  4007. TFS (&tfs_set_notset), 0x02, NULL, HFILL } },
  4008. { &hf_message_sec_cat_bit2,
  4009. { "Bit 2", "dmp.sec_cat.bit2", FT_BOOLEAN, 8,
  4010. TFS (&tfs_set_notset), 0x04, NULL, HFILL } },
  4011. { &hf_message_sec_cat_bit3,
  4012. { "Bit 3", "dmp.sec_cat.bit3", FT_BOOLEAN, 8,
  4013. TFS (&tfs_set_notset), 0x08, NULL, HFILL } },
  4014. { &hf_message_sec_cat_bit4,
  4015. { "Bit 4", "dmp.sec_cat.bit4", FT_BOOLEAN, 8,
  4016. TFS (&tfs_set_notset), 0x10, NULL, HFILL } },
  4017. { &hf_message_sec_cat_bit5,
  4018. { "Bit 5", "dmp.sec_cat.bit5", FT_BOOLEAN, 8,
  4019. TFS (&tfs_set_notset), 0x20, NULL, HFILL } },
  4020. { &hf_message_sec_cat_bit6,
  4021. { "Bit 6", "dmp.sec_cat.bit6", FT_BOOLEAN, 8,
  4022. TFS (&tfs_set_notset), 0x40, NULL, HFILL } },
  4023. { &hf_message_sec_cat_bit7,
  4024. { "Bit 7", "dmp.sec_cat.bit7", FT_BOOLEAN, 8,
  4025. TFS (&tfs_set_notset), 0x80, NULL, HFILL } },
  4026. /* Expiry Time */
  4027. { &hf_message_exp_time,
  4028. { "Expiry Time", "dmp.expiry_time", FT_UINT8, BASE_HEX,
  4029. NULL, 0x0, NULL, HFILL } },
  4030. { &hf_message_exp_time_val,
  4031. { "Expiry Time Value", "dmp.expiry_time_val", FT_UINT8, BASE_HEX,
  4032. NULL, 0xFF, NULL, HFILL } },
  4033. /* DTG */
  4034. { &hf_message_dtg,
  4035. { "DTG", "dmp.dtg", FT_UINT8, BASE_HEX,
  4036. NULL, 0xFF, NULL, HFILL } },
  4037. { &hf_message_dtg_sign,
  4038. { "DTG in the", "dmp.dtg.sign", FT_BOOLEAN, 8, TFS (&dtg_sign),
  4039. 0x80, "Sign", HFILL } },
  4040. { &hf_message_dtg_val,
  4041. { "DTG Value", "dmp.dtg.val", FT_UINT8, BASE_HEX, NULL,
  4042. 0x7F, NULL, HFILL } },
  4043. /* SIC */
  4044. { &hf_message_sic,
  4045. { "SIC", "dmp.sic", FT_STRING, BASE_NONE,
  4046. NULL, 0x0, NULL, HFILL } },
  4047. { &hf_message_sic_key,
  4048. { "SICs", "dmp.sic_key", FT_NONE, BASE_NONE,
  4049. NULL, 0x0, "SIC Content", HFILL } },
  4050. { &hf_message_sic_key_values,
  4051. { "Content Byte", "dmp.sic_key.values", FT_UINT8, BASE_HEX,
  4052. NULL, 0x0, "SIC Content Byte", HFILL } },
  4053. { &hf_message_sic_key_type,
  4054. { "Type", "dmp.sic_key.type", FT_UINT8, BASE_HEX,
  4055. VALS (sic_key_type), 0xF0, "SIC Content Type", HFILL } },
  4056. { &hf_message_sic_key_chars,
  4057. { "Valid Characters", "dmp.sic_key.chars", FT_BOOLEAN, 8,
  4058. TFS (&sic_key_chars), 0x08, "SIC Valid Characters", HFILL } },
  4059. { &hf_message_sic_key_num,
  4060. { "Number of SICs", "dmp.sic_key.num", FT_UINT8, BASE_HEX,
  4061. VALS (sic_key_num), 0x07, NULL, HFILL } },
  4062. { &hf_message_sic_bitmap,
  4063. { "Length Bitmap (0 = 3 bytes, 1 = 4-8 bytes)", "dmp.sic_bitmap",
  4064. FT_UINT8, BASE_HEX, NULL, 0xFF, "SIC Length Bitmap", HFILL } },
  4065. { &hf_message_sic_bits,
  4066. { "Bit 7-4", "dmp.sic_bits", FT_UINT8, BASE_HEX,
  4067. VALS(sic_bit_vals), 0xF0, "SIC Bit 7-4, Characters [A-Z0-9] only",
  4068. HFILL } },
  4069. { &hf_message_sic_bits_any,
  4070. { "Bit 7-4", "dmp.sic_bits_any", FT_UINT8, BASE_HEX,
  4071. VALS(sic_bit_any_vals), 0xF0, "SIC Bit 7-4, Any valid characters",
  4072. HFILL } },
  4073. /* Subject Message Id */
  4074. { &hf_message_subj_id,
  4075. { "Subject Message Identifier", "dmp.subj_id", FT_UINT16,
  4076. BASE_DEC, NULL, 0x0, NULL, HFILL } },
  4077. /* Subject MTS Identifier */
  4078. { &hf_message_subj_mts_id,
  4079. { "Subject MTS Identifier", "dmp.subj_mts_id", FT_STRING, BASE_NONE,
  4080. NULL, 0x0, NULL, HFILL } },
  4081. /* Subject IPM Identifier */
  4082. { &hf_message_subj_ipm_id,
  4083. { "Subject IPM Identifier", "dmp.subj_ipm_id", FT_STRING, BASE_NONE,
  4084. NULL, 0x0, NULL, HFILL } },
  4085. /*
  4086. ** Message body
  4087. */
  4088. { &hf_message_body,
  4089. { "Message Body", "dmp.body", FT_NONE, BASE_NONE, NULL,
  4090. 0x0, NULL, HFILL}},
  4091. /* Body Id */
  4092. { &hf_message_eit,
  4093. { "EIT", "dmp.body.eit", FT_UINT8, BASE_DEC,
  4094. VALS(eit_vals), 0xE0, "Encoded Information Type", HFILL } },
  4095. { &hf_message_compr,
  4096. { "Compression", "dmp.body.compression", FT_UINT8, BASE_DEC,
  4097. VALS(compression_vals), 0x18, NULL, HFILL } },
  4098. /* Subject */
  4099. { &hf_message_subject,
  4100. { "Subject", "dmp.subject", FT_STRINGZ, BASE_NONE,
  4101. NULL, 0x0, NULL, HFILL } },
  4102. /* Message Body */
  4103. { &hf_message_body_data,
  4104. { "User data", "dmp.body.data", FT_NONE, BASE_NONE,
  4105. NULL, 0x0, NULL, HFILL } },
  4106. { &hf_message_body_plain,
  4107. { "Message Body", "dmp.body.plain", FT_STRING, BASE_NONE,
  4108. NULL, 0x0, NULL, HFILL } },
  4109. { &hf_message_bodyid_uint8,
  4110. { "Structured Id", "dmp.body.id", FT_UINT8, BASE_DEC,
  4111. NULL, 0x0, "Structured Body Id (1 byte)", HFILL } },
  4112. { &hf_message_bodyid_uint16,
  4113. { "Structured Id", "dmp.body.id", FT_UINT16, BASE_DEC,
  4114. NULL, 0x0, "Structured Body Id (2 bytes)", HFILL } },
  4115. { &hf_message_bodyid_uint32,
  4116. { "Structured Id", "dmp.body.id", FT_UINT32, BASE_DEC,
  4117. NULL, 0x0, "Structured Body Id (4 bytes)", HFILL } },
  4118. { &hf_message_bodyid_uint64,
  4119. { "Structured Id", "dmp.body.id", FT_UINT64, BASE_DEC,
  4120. NULL, 0x0, "Structured Body Id (8 bytes)", HFILL } },
  4121. { &hf_message_bodyid_string,
  4122. { "Structured Id", "dmp.body.id", FT_STRING, BASE_NONE,
  4123. NULL, 0x0, "Structured Body Id (fixed text string)", HFILL } },
  4124. { &hf_message_bodyid_zstring,
  4125. { "Structured Id", "dmp.body.id", FT_STRINGZ, BASE_NONE,
  4126. NULL, 0x0, "Structured Body Id (zero terminated text string)",
  4127. HFILL } },
  4128. { &hf_message_body_structured,
  4129. { "Structured Body", "dmp.body.structured", FT_BYTES, BASE_NONE,
  4130. NULL, 0x0, NULL, HFILL } },
  4131. { &hf_message_body_uncompr,
  4132. { "Uncompressed User data", "dmp.body.uncompressed", FT_NONE,
  4133. BASE_NONE, NULL, 0x0, NULL, HFILL } },
  4134. { &hf_message_body_uncompressed,
  4135. { "Uncompressed Message Body", "dmp.body.uncompressed",
  4136. FT_STRING, BASE_NONE, NULL, 0x0, NULL,
  4137. HFILL } },
  4138. /*
  4139. ** Report
  4140. */
  4141. { &hf_delivery_report,
  4142. { "Delivery Report", "dmp.dr", FT_NONE, BASE_NONE, NULL,
  4143. 0x0, NULL, HFILL}},
  4144. { &hf_non_delivery_report,
  4145. { "Non-Delivery Report", "dmp.ndr", FT_NONE, BASE_NONE, NULL,
  4146. 0x0, NULL, HFILL}},
  4147. { &hf_report_type,
  4148. { "Report Type", "dmp.report_type", FT_BOOLEAN, 8,
  4149. TFS (&report_type), 0x80, NULL, HFILL } },
  4150. { &hf_report_info_present_dr,
  4151. { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
  4152. TFS (&tfs_present_absent), 0x40, NULL, HFILL } },
  4153. { &hf_report_addr_enc_dr,
  4154. { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
  4155. TFS (&addr_enc), 0x20, NULL, HFILL } },
  4156. { &hf_report_del_time,
  4157. { "Delivery Time", "dmp.delivery_time", FT_UINT8, BASE_HEX,
  4158. NULL, 0x0, NULL, HFILL } },
  4159. { &hf_report_del_time_val,
  4160. { "Delivery Time Value", "dmp.delivery_time_val", FT_UINT8,
  4161. BASE_HEX, NULL, 0xFF, NULL, HFILL } },
  4162. { &hf_report_addr_enc_ndr,
  4163. { "Address Encoding", "dmp.addr_encoding", FT_BOOLEAN, 8,
  4164. TFS (&addr_enc), 0x40, NULL, HFILL } },
  4165. { &hf_report_reason,
  4166. { "Reason (P1)", "dmp.report_reason", FT_UINT8, BASE_DEC,
  4167. VALS (p1_NonDeliveryReasonCode_vals), 0x3F,
  4168. "Reason", HFILL } },
  4169. { &hf_report_info_present_ndr,
  4170. { "Info Present", "dmp.info_present", FT_BOOLEAN, 8,
  4171. TFS (&tfs_present_absent), 0x80, NULL, HFILL } },
  4172. { &hf_report_diagn,
  4173. { "Diagnostic (P1)", "dmp.report_diagnostic", FT_UINT8, BASE_DEC,
  4174. VALS (p1_NonDeliveryDiagnosticCode_vals), 0x7F,
  4175. "Diagnostic", HFILL } },
  4176. { &hf_report_suppl_info_len,
  4177. { "Supplementary Information", "dmp.suppl_info_len", FT_UINT8,
  4178. BASE_DEC, NULL, 0x0, "Supplementary Information Length", HFILL } },
  4179. { &hf_report_suppl_info,
  4180. { "Supplementary Information", "dmp.suppl_info", FT_STRINGZ,
  4181. BASE_NONE, NULL, 0x0, NULL, HFILL } },
  4182. /*
  4183. ** Notification
  4184. */
  4185. { &hf_receipt_notif,
  4186. { "Receipt Notification (RN)", "dmp.rn", FT_NONE, BASE_NONE,
  4187. NULL, 0x0, NULL, HFILL} },
  4188. { &hf_non_receipt_notif,
  4189. { "Non-Receipt Notification (NRN)", "dmp.nrn", FT_NONE, BASE_NONE,
  4190. NULL, 0x0, NULL, HFILL} },
  4191. { &hf_other_notif,
  4192. { "Other Notification (ON)", "dmp.on", FT_NONE, BASE_NONE,
  4193. NULL, 0x0, NULL, HFILL} },
  4194. { &hf_notif_type,
  4195. { "Notification Type", "dmp.notif_type", FT_UINT8, BASE_DEC,
  4196. VALS (notif_type), 0x03, NULL, HFILL } },
  4197. { &hf_notif_rec_time,
  4198. { "Receipt Time", "dmp.receipt_time", FT_UINT8, BASE_HEX,
  4199. NULL, 0x0, NULL, HFILL } },
  4200. { &hf_notif_rec_time_val,
  4201. { "Receipt Time Value", "dmp.receipt_time_val", FT_UINT8,
  4202. BASE_HEX, NULL, 0xFF, NULL, HFILL } },
  4203. { &hf_notif_suppl_info_len,
  4204. { "Supplementary Information", "dmp.suppl_info_len",
  4205. FT_UINT8, BASE_DEC, NULL, 0x0, "Supplementary Information Length",
  4206. HFILL } },
  4207. { &hf_notif_suppl_info,
  4208. { "Supplementary Information", "dmp.suppl_info",
  4209. FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL,
  4210. HFILL } },
  4211. { &hf_notif_non_rec_reason,
  4212. { "Non-Receipt Reason", "dmp.notif_non_rec_reason",
  4213. FT_UINT8, BASE_DEC, VALS (p22_NonReceiptReasonField_vals), 0x0,
  4214. NULL, HFILL } },
  4215. { &hf_notif_discard_reason,
  4216. { "Discard Reason", "dmp.notif_discard_reason", FT_UINT8,
  4217. BASE_DEC, VALS (p22_DiscardReasonField_vals), 0x0,
  4218. NULL, HFILL } },
  4219. { &hf_notif_on_type,
  4220. { "ON Type", "dmp.notif_on_type", FT_UINT8, BASE_DEC,
  4221. VALS (on_type), 0x0, NULL, HFILL } },
  4222. { &hf_notif_acp127,
  4223. { "ACP127 Recipient", "dmp.acp127recip_len", FT_UINT8,
  4224. BASE_DEC, NULL, 0x0, "ACP 127 Recipient Length", HFILL } },
  4225. { &hf_notif_acp127recip,
  4226. { "ACP127 Recipient", "dmp.acp127recip", FT_STRINGZ,
  4227. BASE_NONE, NULL, 0x0, "ACP 127 Recipient", HFILL } },
  4228. /*
  4229. ** Acknowledgement
  4230. */
  4231. { &hf_ack,
  4232. { "Acknowledgement", "dmp.ack", FT_NONE, BASE_NONE,
  4233. NULL, 0x0, NULL, HFILL } },
  4234. { &hf_ack_reason,
  4235. { "Ack Reason", "dmp.ack_reason", FT_UINT8, BASE_DEC,
  4236. VALS (&ack_reason), 0x0, "Reason", HFILL } },
  4237. { &hf_ack_diagnostic,
  4238. { "Ack Diagnostic", "dmp.ack_diagnostic", FT_UINT8, BASE_DEC,
  4239. NULL, 0x0, "Diagnostic", HFILL } },
  4240. { &hf_ack_recips,
  4241. { "Recipient List", "dmp.ack_rec_list", FT_NONE, BASE_NONE,
  4242. NULL, 0x0, NULL, HFILL } },
  4243. /*
  4244. ** Checksum
  4245. */
  4246. { &hf_checksum,
  4247. { "Checksum", "dmp.checksum", FT_UINT16, BASE_HEX,
  4248. NULL, 0x0, NULL, HFILL } },
  4249. { &hf_checksum_good,
  4250. { "Good", "dmp.checksum_good", FT_BOOLEAN, BASE_NONE,
  4251. NULL, 0x0, "True: checksum matches packet content; False: doesn't match content or not checked", HFILL } },
  4252. { &hf_checksum_bad,
  4253. { "Bad", "dmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
  4254. NULL, 0x0, "True: checksum doesn't match packet content; False: matches content or not checked", HFILL } },
  4255. /*
  4256. ** Ack matching / Resend
  4257. */
  4258. { &hf_analysis_ack_time,
  4259. { "Acknowledgement Time", "dmp.analysis.ack_time", FT_RELATIVE_TIME, BASE_NONE,
  4260. NULL, 0x0, "The time between the Message and the Acknowledge", HFILL } },
  4261. { &hf_analysis_rep_time,
  4262. { "Report Reply Time", "dmp.analysis.report_time", FT_RELATIVE_TIME, BASE_NONE,
  4263. NULL, 0x0, "The time between the Message and the Report", HFILL } },
  4264. { &hf_analysis_not_time,
  4265. { "Notification Reply Time", "dmp.analysis.notif_time", FT_RELATIVE_TIME, BASE_NONE,
  4266. NULL, 0x0, "The time between the Message and the Notification", HFILL } },
  4267. { &hf_analysis_total_time,
  4268. { "Total Time", "dmp.analysis.total_time", FT_RELATIVE_TIME, BASE_NONE,
  4269. NULL, 0x0, "The time between the first Message and the Acknowledge", HFILL } },
  4270. { &hf_analysis_retrans_time,
  4271. { "Retransmission Time", "dmp.analysis.retrans_time", FT_RELATIVE_TIME, BASE_NONE,
  4272. NULL, 0x0, "The time between the last Message and this Message", HFILL } },
  4273. { &hf_analysis_total_retrans_time,
  4274. { "Total Retransmission Time", "dmp.analysis.total_retrans_time", FT_RELATIVE_TIME, BASE_NONE,
  4275. NULL, 0x0, "The time between the first Message and this Message", HFILL } },
  4276. { &hf_analysis_msg_num,
  4277. { "Message in", "dmp.analysis.msg_in", FT_FRAMENUM, BASE_NONE,
  4278. NULL, 0x0, "This packet has a Message in this frame", HFILL } },
  4279. { &hf_analysis_ack_num,
  4280. { "Acknowledgement in", "dmp.analysis.ack_in", FT_FRAMENUM, BASE_NONE,
  4281. NULL, 0x0, "This packet has an Acknowledgement in this frame", HFILL } },
  4282. { &hf_analysis_rep_num,
  4283. { "Report in", "dmp.analysis.report_in", FT_FRAMENUM, BASE_NONE,
  4284. NULL, 0x0, "This packet has a Report in this frame", HFILL } },
  4285. { &hf_analysis_not_num,
  4286. { "Notification in", "dmp.analysis.notif_in", FT_FRAMENUM, BASE_NONE,
  4287. NULL, 0x0, "This packet has a Notification in this frame", HFILL } },
  4288. { &hf_analysis_msg_missing,
  4289. { "Message missing", "dmp.analysis.msg_missing", FT_NONE, BASE_NONE,
  4290. NULL, 0x0, "The Message for this packet is missing", HFILL } },
  4291. { &hf_analysis_ack_missing,
  4292. { "Acknowledgement missing", "dmp.analysis.ack_missing", FT_NONE, BASE_NONE,
  4293. NULL, 0x0, "The acknowledgement for this packet is missing", HFILL } },
  4294. { &hf_analysis_retrans_no,
  4295. { "Retransmission #", "dmp.analysis.retrans_no", FT_UINT32, BASE_DEC,
  4296. NULL, 0x0, "Retransmission count", HFILL } },
  4297. { &hf_analysis_ack_dup_no,
  4298. { "Duplicate ACK #", "dmp.analysis.dup_ack_no", FT_UINT32, BASE_DEC,
  4299. NULL, 0x0, "Duplicate Acknowledgement count", HFILL } },
  4300. { &hf_analysis_msg_resend_from,
  4301. { "Retransmission of Message sent in", "dmp.analysis.msg_first_sent_in",
  4302. FT_FRAMENUM, BASE_NONE,
  4303. NULL, 0x0, "This Message was first sent in this frame", HFILL } },
  4304. { &hf_analysis_rep_resend_from,
  4305. { "Retransmission of Report sent in", "dmp.analysis.report_first_sent_in",
  4306. FT_FRAMENUM, BASE_NONE,
  4307. NULL, 0x0, "This Report was first sent in this frame", HFILL } },
  4308. { &hf_analysis_not_resend_from,
  4309. { "Retransmission of Notification sent in", "dmp.analysis.notif_first_sent_in",
  4310. FT_FRAMENUM, BASE_NONE,
  4311. NULL, 0x0, "This Notification was first sent in this frame", HFILL } },
  4312. { &hf_analysis_ack_resend_from,
  4313. { "Retransmission of Acknowledgement sent in", "dmp.analysis.ack_first_sent_in",
  4314. FT_FRAMENUM, BASE_NONE,
  4315. NULL, 0x0, "This Acknowledgement was first sent in this frame", HFILL } },
  4316. /*
  4317. ** Reserved values
  4318. */
  4319. { &hf_reserved_0x01,
  4320. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4321. NULL, 0x01, NULL, HFILL } },
  4322. { &hf_reserved_0x02,
  4323. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4324. NULL, 0x02, NULL, HFILL } },
  4325. { &hf_reserved_0x04,
  4326. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4327. NULL, 0x04, NULL, HFILL } },
  4328. { &hf_reserved_0x07,
  4329. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4330. NULL, 0x07, NULL, HFILL } },
  4331. { &hf_reserved_0x08,
  4332. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4333. NULL, 0x08, NULL, HFILL } },
  4334. { &hf_reserved_0x0F,
  4335. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4336. NULL, 0x0F, NULL, HFILL } },
  4337. { &hf_reserved_0x1F,
  4338. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4339. NULL, 0x1F, NULL, HFILL } },
  4340. { &hf_reserved_0x20,
  4341. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4342. NULL, 0x20, NULL, HFILL } },
  4343. { &hf_reserved_0x40,
  4344. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4345. NULL, 0x40, NULL, HFILL } },
  4346. { &hf_reserved_0xC0,
  4347. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4348. NULL, 0xC0, NULL, HFILL } },
  4349. { &hf_reserved_0xE0,
  4350. { "Reserved", "dmp.reserved", FT_UINT8, BASE_DEC,
  4351. NULL, 0xE0, NULL, HFILL } },
  4352. { &hf_reserved_0x8000,
  4353. { "Reserved", "dmp.reserved", FT_UINT16, BASE_DEC,
  4354. NULL, 0x8000, NULL, HFILL } },
  4355. };
  4356. static gint *ett[] = {
  4357. &ett_dmp,
  4358. &ett_envelope,
  4359. &ett_envelope_version,
  4360. &ett_envelope_hop_count,
  4361. &ett_envelope_rec_present,
  4362. &ett_envelope_addr_enc,
  4363. &ett_envelope_checksum,
  4364. &ett_envelope_extensions,
  4365. &ett_envelope_msg_id_type,
  4366. &ett_envelope_msg_id,
  4367. &ett_envelope_mts_id_length,
  4368. &ett_envelope_ipm_id_length,
  4369. &ett_envelope_cont_type,
  4370. &ett_envelope_subm_time,
  4371. &ett_envelope_time_diff,
  4372. &ett_envelope_flags,
  4373. &ett_envelope_recipients,
  4374. &ett_envelope_ext_recipients,
  4375. &ett_envelope_addresses,
  4376. &ett_address,
  4377. &ett_address_direct,
  4378. &ett_address_rec_no,
  4379. &ett_address_extended,
  4380. &ett_address_ext_form,
  4381. &ett_address_ext_rec_no,
  4382. &ett_address_ext_action,
  4383. &ett_address_ext_rep_req,
  4384. &ett_address_ext_not_req,
  4385. &ett_address_ext_type,
  4386. &ett_address_ext_length,
  4387. &ett_extensions,
  4388. &ett_extension,
  4389. &ett_extension_header,
  4390. &ett_content,
  4391. &ett_message,
  4392. &ett_message_st_type,
  4393. &ett_message_reserved,
  4394. &ett_message_precedence,
  4395. &ett_message_importance,
  4396. &ett_message_body_format,
  4397. &ett_message_sec_class,
  4398. &ett_message_sec_pol,
  4399. &ett_message_sec_cat,
  4400. &ett_message_heading_flags,
  4401. &ett_message_exp_time,
  4402. &ett_message_dtg,
  4403. &ett_message_sic,
  4404. &ett_message_sic_key,
  4405. &ett_message_sic_bitmap,
  4406. &ett_message_sic_bits,
  4407. &ett_message_eit,
  4408. &ett_message_compr,
  4409. &ett_message_body_reserved,
  4410. &ett_message_body,
  4411. &ett_message_body_uncompr,
  4412. &ett_report,
  4413. &ett_report_type,
  4414. &ett_report_info_present_dr,
  4415. &ett_report_info_present_ndr,
  4416. &ett_report_addr_enc_dr,
  4417. &ett_report_addr_enc_ndr,
  4418. &ett_report_reserved,
  4419. &ett_report_del_time,
  4420. &ett_report_reason,
  4421. &ett_report_suppl_info,
  4422. &ett_report_diagn,
  4423. &ett_notif,
  4424. &ett_notif_type,
  4425. &ett_notif_rec_time,
  4426. &ett_notif_suppl_info,
  4427. &ett_notif_acp127recip,
  4428. &ett_ack,
  4429. &ett_ack_recips,
  4430. &ett_checksum,
  4431. &ett_analysis
  4432. };
  4433. static ei_register_info ei[] = {
  4434. { &ei_reserved_value, { "dmp.reserved.expert", PI_UNDECODED, PI_WARN, "Reserved value", EXPFILL }},
  4435. { &ei_message_sic_illegal, { "dmp.sic.illegal", PI_UNDECODED, PI_NOTE, "Illegal SIC", EXPFILL }},
  4436. };
  4437. static uat_field_t attributes_flds[] = {
  4438. UAT_FLD_VS(dmp_security_class,nation, "Nation", nat_pol_id, 0),
  4439. UAT_FLD_DEC(dmp_security_class,sec_class, "Classification", "Security Classification"),
  4440. UAT_FLD_CSTRING(dmp_security_class,name, "Name", "Classification Name"),
  4441. UAT_END_FIELDS
  4442. };
  4443. uat_t *attributes_uat = uat_new("DMP Security Classifications",
  4444. sizeof(dmp_security_class_t),
  4445. "dmp_security_classifications",
  4446. TRUE,
  4447. (void**) &dmp_security_classes,
  4448. &num_dmp_security_classes,
  4449. UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
  4450. "ChDMPSecurityClassifications",
  4451. dmp_class_copy_cb,
  4452. NULL,
  4453. dmp_class_free_cb,
  4454. NULL,
  4455. attributes_flds);
  4456. module_t *dmp_module;
  4457. expert_module_t* expert_dmp;
  4458. proto_dmp = proto_register_protocol (PNAME, PSNAME, PFNAME);
  4459. dmp_handle = register_dissector(PFNAME, dissect_dmp, proto_dmp);
  4460. proto_register_field_array (proto_dmp, hf, array_length (hf));
  4461. proto_register_subtree_array (ett, array_length (ett));
  4462. expert_dmp = expert_register_protocol(proto_dmp);
  4463. expert_register_field_array(expert_dmp, ei, array_length(ei));
  4464. register_init_routine (&dmp_init_routine);
  4465. /* Set default UDP ports */
  4466. range_convert_str (&global_dmp_port_range, DEFAULT_DMP_PORT_RANGE,
  4467. MAX_UDP_PORT);
  4468. /* Build national values */
  4469. build_national_strings ();
  4470. /* Register our configuration options */
  4471. dmp_module = prefs_register_protocol (proto_dmp, proto_reg_handoff_dmp);
  4472. prefs_register_obsolete_preference (dmp_module, "udp_port");
  4473. prefs_register_obsolete_preference (dmp_module, "udp_port_second");
  4474. prefs_register_range_preference (dmp_module, "udp_ports",
  4475. "DMP port numbers",
  4476. "Port numbers used for DMP traffic",
  4477. &global_dmp_port_range, MAX_UDP_PORT);
  4478. prefs_register_enum_preference (dmp_module, "national_decode",
  4479. "National decoding",
  4480. "Select the type of decoding for nationally-defined values",
  4481. &dmp_nat_decode, national_decoding,
  4482. FALSE);
  4483. prefs_register_enum_preference (dmp_module, "local_nation",
  4484. "Nation of local server",
  4485. "Select the nation of sending server. This is used when presenting"
  4486. " security classification values in messages with security"
  4487. " policy set to National (nation of local server)",
  4488. &dmp_local_nation, dmp_national_values,
  4489. FALSE);
  4490. prefs_register_uat_preference (dmp_module, "classes_table",
  4491. "National Security Classifications",
  4492. "Translation table for national security classifications. This is used"
  4493. " when presenting security classification values in messages with"
  4494. " security policy set to National or Extended National",
  4495. attributes_uat);
  4496. prefs_register_bool_preference (dmp_module, "seq_ack_analysis",
  4497. "SEQ/ACK Analysis",
  4498. "Calculate sequence/acknowledgement analysis",
  4499. &use_seq_ack_analysis);
  4500. prefs_register_bool_preference (dmp_module, "align_ids",
  4501. "Align identifiers in info list",
  4502. "Align identifiers in info list"
  4503. " (does not align when retransmission or"
  4504. " duplicate acknowledgement indication)",
  4505. &dmp_align);
  4506. prefs_register_bool_preference (dmp_module, "subject_as_id",
  4507. "Print subject as body id",
  4508. "Print subject as body id in free text "
  4509. "messages with subject",
  4510. &dmp_subject_as_id);
  4511. prefs_register_enum_preference (dmp_module, "struct_print",
  4512. "Structured message id format",
  4513. "Format of the structured message id",
  4514. &dmp_struct_format, struct_id_options,
  4515. FALSE);
  4516. prefs_register_uint_preference (dmp_module, "struct_offset",
  4517. "Offset to structured message id",
  4518. "Used to set where the structured message "
  4519. "id starts in the User Data",
  4520. 10, &dmp_struct_offset);
  4521. prefs_register_uint_preference (dmp_module, "struct_length",
  4522. "Fixed text string length",
  4523. "Used to set length of fixed text string "
  4524. "in the structured message id format "
  4525. "(maximum 128 characters)",
  4526. 10, &dmp_struct_length);
  4527. }
  4528. static void range_delete_callback (guint32 port)
  4529. {
  4530. dissector_delete_uint ("udp.port", port, dmp_handle);
  4531. }
  4532. static void range_add_callback (guint32 port)
  4533. {
  4534. dissector_add_uint ("udp.port", port, dmp_handle);
  4535. }
  4536. void proto_reg_handoff_dmp (void)
  4537. {
  4538. static range_t *dmp_port_range;
  4539. static gboolean dmp_prefs_initialized = FALSE;
  4540. if (!dmp_prefs_initialized) {
  4541. dmp_prefs_initialized = TRUE;
  4542. } else {
  4543. range_foreach (dmp_port_range, range_delete_callback);
  4544. g_free (dmp_port_range);
  4545. }
  4546. /* Save port number for later deletion */
  4547. dmp_port_range = range_copy (global_dmp_port_range);
  4548. range_foreach (dmp_port_range, range_add_callback);
  4549. }
  4550. /*
  4551. * Editor modelines
  4552. *
  4553. * Local Variables:
  4554. * c-basic-offset: 2
  4555. * tab-width: 8
  4556. * indent-tabs-mode: nil
  4557. * End:
  4558. *
  4559. * ex: set shiftwidth=2 tabstop=8 expandtab:
  4560. * :indentSize=2:tabSize=8:noTabs=true:
  4561. */