PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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

Large files files are truncated, but you can click here to view the full file

  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_ty

Large files files are truncated, but you can click here to view the full file