summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-do-irp.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-do-irp.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-do-irp.c')
-rw-r--r--epan/dissectors/packet-do-irp.c2168
1 files changed, 2168 insertions, 0 deletions
diff --git a/epan/dissectors/packet-do-irp.c b/epan/dissectors/packet-do-irp.c
new file mode 100644
index 00000000..c5e6e570
--- /dev/null
+++ b/epan/dissectors/packet-do-irp.c
@@ -0,0 +1,2168 @@
+/* packet-do-irp.c
+ * Dissector for Digital Object Identifier Resolution Protocol (DO-IRP)
+ *
+ * Copyright (c) 2023 by Martin Mayer <martin.mayer@m2-it-solutions.de>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * This dissector is based on:
+ *
+ * - Title: Digital Object Identifier Resolution Protocol Specification
+ * Version: 3.0 (June 30, 2022)
+ * Author: DONA Foundation (https://www.dona.net)
+ */
+
+#include "config.h"
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include "packet-tcp.h"
+
+/* N.B. IANA has these ports registered for hdl-srv (name from original RFC) */
+#define DO_IRP_UDP_PORT 2641
+#define DO_IRP_TCP_PORT 2641
+
+#define DO_IRP_ENVELOPE_LEN 20
+#define DO_IRP_MAX_UDP_SIZE 512
+
+void proto_register_do_irp(void);
+void proto_reg_handoff_do_irp(void);
+
+static dissector_handle_t do_irp_handle_udp;
+static dissector_handle_t do_irp_handle_tcp;
+
+static int proto_do_irp = -1;
+expert_module_t* expert_do_irp;
+
+/* Fields Generic */
+static int hf_do_irp_string_len = -1;
+static int hf_do_irp_string_value = -1;
+static int hf_do_irp_data_len = -1;
+static int hf_do_irp_data_value = -1;
+
+/* Fields Message Envelope */
+static int hf_do_irp_envelope = -1;
+static int hf_do_irp_version_major = -1;
+static int hf_do_irp_version_minor = -1;
+static int hf_do_irp_flags = -1;
+static int hf_do_irp_flag_cp = -1;
+static int hf_do_irp_flag_ec = -1;
+static int hf_do_irp_flag_tc = -1;
+static int hf_do_irp_version_major_sugg = -1;
+static int hf_do_irp_version_minor_sugg = -1;
+static int hf_do_irp_sessid = -1;
+static int hf_do_irp_reqid = -1;
+static int hf_do_irp_seq = -1;
+static int hf_do_irp_msglen = -1;
+
+/* Fields Message Header */
+static int hf_do_irp_header = -1;
+static int hf_do_irp_opcode = -1;
+static int hf_do_irp_responsecode = -1;
+static int hf_do_irp_opflags = -1;
+static int hf_do_irp_opflags_at = -1;
+static int hf_do_irp_opflags_ct = -1;
+static int hf_do_irp_opflags_enc = -1;
+static int hf_do_irp_opflags_rec = -1;
+static int hf_do_irp_opflags_ca = -1;
+static int hf_do_irp_opflags_cn = -1;
+static int hf_do_irp_opflags_kc = -1;
+static int hf_do_irp_opflags_po = -1;
+static int hf_do_irp_opflags_rd = -1;
+static int hf_do_irp_opflags_owe = -1;
+static int hf_do_irp_opflags_mns = -1;
+static int hf_do_irp_opflags_dnr = -1;
+static int hf_do_irp_sisn = -1;
+static int hf_do_irp_rcount = -1;
+static int hf_do_irp_expiration = -1;
+static int hf_do_irp_bodylen = -1;
+
+/* Fields Message Body */
+static int hf_do_irp_body = -1;
+static int hf_do_irp_digest_algo = -1;
+static int hf_do_irp_digest = -1;
+static int hf_do_irp_error_msg = -1;
+static int hf_do_irp_error_idxcount = -1;
+static int hf_do_irp_error_idx = -1;
+static int hf_do_irp_ident = -1;
+static int hf_do_irp_idxcount = -1;
+static int hf_do_irp_idx = -1;
+static int hf_do_irp_typecount = -1;
+static int hf_do_irp_type = -1;
+static int hf_do_irp_identcount = -1;
+static int hf_do_irp_identrecord = -1;
+static int hf_do_irp_identrecord_idx = -1;
+static int hf_do_irp_identrecord_type = -1;
+static int hf_do_irp_identrecord_value = -1;
+static int hf_do_irp_identrecord_value_string = -1;
+static int hf_do_irp_identrecord_value_len = -1;
+static int hf_do_irp_identrecord_perm = -1;
+static int hf_do_irp_identrecord_perm_pw = -1;
+static int hf_do_irp_identrecord_perm_pr = -1;
+static int hf_do_irp_identrecord_perm_aw = -1;
+static int hf_do_irp_identrecord_perm_ar = -1;
+static int hf_do_irp_identrecord_ttl_type = -1;
+static int hf_do_irp_identrecord_ttl = -1;
+static int hf_do_irp_identrecord_ttl_absolute = -1;
+static int hf_do_irp_identrecord_ts = -1;
+static int hf_do_irp_identrecord_ts_utc = -1;
+static int hf_do_irp_identrecord_refcount = -1;
+static int hf_do_irp_identrecord_ref = -1;
+static int hf_do_irp_hsadmin_perm = -1;
+static int hf_do_irp_hsadmin_perm_ai = -1;
+static int hf_do_irp_hsadmin_perm_di = -1;
+static int hf_do_irp_hsadmin_perm_adp = -1;
+static int hf_do_irp_hsadmin_perm_me = -1;
+static int hf_do_irp_hsadmin_perm_de = -1;
+static int hf_do_irp_hsadmin_perm_ae = -1;
+static int hf_do_irp_hsadmin_perm_ma = -1;
+static int hf_do_irp_hsadmin_perm_ra = -1;
+static int hf_do_irp_hsadmin_perm_aa = -1;
+static int hf_do_irp_hsadmin_perm_ar = -1;
+static int hf_do_irp_hsadmin_perm_li = -1;
+static int hf_do_irp_hsadmin_perm_ldp = -1;
+static int hf_do_irp_hsadmin_idx = -1;
+static int hf_do_irp_hsadmin_ident = -1;
+static int hf_do_irp_body_hssite_version = -1;
+static int hf_do_irp_hssite_protoversion_major = -1;
+static int hf_do_irp_hssite_protoversion_minor = -1;
+static int hf_do_irp_hssite_serial = -1;
+static int hf_do_irp_hssite_primask = -1;
+static int hf_do_irp_hssite_primask_pri = -1;
+static int hf_do_irp_hssite_primask_multi = -1;
+static int hf_do_irp_hssite_hashoption = -1;
+static int hf_do_irp_hssite_hashfilter = -1;
+static int hf_do_irp_hssite_attr_count = -1;
+static int hf_do_irp_hssite_attr = -1;
+static int hf_do_irp_hssite_attr_key = -1;
+static int hf_do_irp_hssite_attr_value = -1;
+static int hf_do_irp_hssite_srvcount = -1;
+static int hf_do_irp_hssite_srv = -1;
+static int hf_do_irp_hssite_srv_id = -1;
+static int hf_do_irp_hssite_srv_addr = -1;
+static int hf_do_irp_pkrec = -1;
+static int hf_do_irp_pkrec_len = -1;
+static int hf_do_irp_pkrec_type = -1;
+static int hf_do_irp_pkrec_dsa_q = -1;
+static int hf_do_irp_pkrec_dsa_p = -1;
+static int hf_do_irp_pkrec_dsa_g = -1;
+static int hf_do_irp_pkrec_dsa_y = -1;
+static int hf_do_irp_pkrec_rsa_exp = -1;
+static int hf_do_irp_pkrec_rsa_mod = -1;
+static int hf_do_irp_pkrec_dh_p = -1;
+static int hf_do_irp_pkrec_dh_g = -1;
+static int hf_do_irp_pkrec_dh_y = -1;
+static int hf_do_irp_hssite_srv_if = -1;
+static int hf_do_irp_hssite_srv_ifcount = -1;
+static int hf_do_irp_hssite_srv_if_type = -1;
+static int hf_do_irp_hssite_srv_if_type_admin = -1;
+static int hf_do_irp_hssite_srv_if_type_res = -1;
+static int hf_do_irp_hssite_srv_if_proto = -1;
+static int hf_do_irp_hssite_srv_if_port = -1;
+static int hf_do_irp_hsserv_ident = -1;
+static int hf_do_irp_hsvlist_count = -1;
+static int hf_do_irp_hsvlist_ref = -1;
+static int hf_do_irp_hsalias = -1;
+static int hf_do_irp_hsnamespace = -1;
+static int hf_do_irp_hscert_jwt = -1;
+static int hf_do_irp_hssignature_jwt = -1;
+static int hf_do_irp_refident = -1;
+static int hf_do_irp_nonce = -1;
+static int hf_do_irp_authtype = -1;
+static int hf_do_irp_keyident = -1;
+static int hf_do_irp_keyidx = -1;
+static int hf_do_irp_challresp = -1;
+static int hf_do_irp_veri_result = -1;
+static int hf_do_irp_ignoredident = -1;
+static int hf_do_irp_keyexmode = -1;
+static int hf_do_irp_timeout = -1;
+
+/* Fields Message Credential */
+static int hf_do_irp_credential = -1;
+static int hf_do_irp_credential_len = -1;
+static int hf_do_irp_credential_sesscounter = -1;
+static int hf_do_irp_credential_type = -1;
+static int hf_do_irp_credential_signedinfo = -1;
+static int hf_do_irp_credential_signedinfo_len = -1;
+static int hf_do_irp_credential_signedinfo_algo = -1;
+static int hf_do_irp_credential_signedinfo_sig = -1;
+
+/* Conversation */
+static int hf_do_irp_response_in = -1;
+static int hf_do_irp_response_to = -1;
+
+/* Fragment handling */
+static int hf_msg_fragments = -1;
+static int hf_msg_fragment = -1;
+static int hf_msg_fragment_overlap = -1;
+static int hf_msg_fragment_overlap_conflicts = -1;
+static int hf_msg_fragment_multiple_tails = -1;
+static int hf_msg_fragment_too_long_fragment = -1;
+static int hf_msg_fragment_error = -1;
+static int hf_msg_fragment_count = -1;
+static int hf_msg_reassembled_in = -1;
+static int hf_msg_reassembled_len = -1;
+static int hf_msg_reassembled_data = -1;
+
+/* Expert fields */
+static expert_field ei_do_irp_digest_unknown = EI_INIT;
+static expert_field ei_do_irp_frag_wo_tc = EI_INIT;
+
+/* Trees */
+static gint ett_do_irp = -1;
+static gint ett_do_irp_string = -1;
+static gint ett_do_irp_envelope = -1;
+static gint ett_do_irp_envelope_flags = -1;
+static gint ett_do_irp_header = -1;
+static gint ett_do_irp_header_flags = -1;
+static gint ett_do_irp_body = -1;
+static gint ett_do_irp_credential = -1;
+static gint ett_do_irp_credential_signedinfo = -1;
+static gint ett_do_irp_identifier_record = -1;
+static gint ett_do_irp_element_permission_flags = -1;
+static gint ett_do_irp_element_hsadmin_permission_flags = -1;
+static gint ett_do_irp_element_hsadmin_primary_flags = -1;
+static gint ett_do_irp_hsadmin = -1;
+static gint ett_do_irp_hssite = -1;
+static gint ett_do_irp_hssite_attribute = -1;
+static gint ett_do_irp_hssite_server = -1;
+static gint ett_do_irp_hssite_server_if = -1;
+static gint ett_do_irp_hssite_server_if_flags = -1;
+static gint ett_do_irp_pk = -1;
+static gint ett_msg_fragment = -1;
+static gint ett_msg_fragments = -1;
+
+static const fragment_items msg_frag_items = {
+ &ett_msg_fragment,
+ &ett_msg_fragments,
+ &hf_msg_fragments,
+ &hf_msg_fragment,
+ &hf_msg_fragment_overlap,
+ &hf_msg_fragment_overlap_conflicts,
+ &hf_msg_fragment_multiple_tails,
+ &hf_msg_fragment_too_long_fragment,
+ &hf_msg_fragment_error,
+ &hf_msg_fragment_count,
+ &hf_msg_reassembled_in,
+ &hf_msg_reassembled_len,
+ &hf_msg_reassembled_data,
+ "Message fragments"
+};
+
+/* Request Hashmap Key */
+struct do_irp_request_hash_key {
+ guint32 conv_index;
+ guint32 reqid;
+};
+/* Request Hashmap Val */
+struct do_irp_request_hash_val {
+ guint32 pnum;
+ guint32 pnum_resp;
+ guint32 opcode;
+};
+static wmem_map_t *do_irp_request_hash_map = NULL;
+
+#define DO_IRP_OC_RESERVED 0
+#define DO_IRP_OC_RESOLUTION 1
+#define DO_IRP_OC_GET_SITEINFO 2
+#define DO_IRP_OC_CREATE_ID 100
+#define DO_IRP_OC_DELETE_ID 101
+#define DO_IRP_OC_ADD_ELEMENT 102
+#define DO_IRP_OC_REMOVE_ELEMENT 103
+#define DO_IRP_OC_MODIFY_ELEMENT 104
+#define DO_IRP_OC_LIST_IDS 105
+#define DO_IRP_OC_LIST_DERIVED_PREFIXES 106
+#define DO_IRP_OC_CHALLENGE_RESPONSE 200
+#define DO_IRP_OC_VERIFY_RESPONSE 201
+#define DO_IRP_OC_HOME_PREFIX 300
+#define DO_IRP_OC_UNHOME_PREFIX 301
+#define DO_IRP_OC_LIST_HOMED_PREFIXES 302
+#define DO_IRP_OC_SESSION_SETUP 400
+#define DO_IRP_OC_SESSION_TERMINATE 401
+
+
+static const value_string opcode_vals[] = {
+ { DO_IRP_OC_RESERVED, "RESERVED" },
+ { DO_IRP_OC_RESOLUTION, "RESOLUTION" },
+ { DO_IRP_OC_GET_SITEINFO, "GET_SITEINFO" },
+ { DO_IRP_OC_CREATE_ID, "CREATE_ID" },
+ { DO_IRP_OC_DELETE_ID, "DELETE_ID" },
+ { DO_IRP_OC_ADD_ELEMENT, "ADD_ELEMENT" },
+ { DO_IRP_OC_REMOVE_ELEMENT, "REMOVE_ELEMENT" },
+ { DO_IRP_OC_MODIFY_ELEMENT, "MODIFY_ELEMENT" },
+ { DO_IRP_OC_LIST_IDS, "LIST_IDS" },
+ { DO_IRP_OC_LIST_DERIVED_PREFIXES, "LIST_DERIVED_PREFIXES" },
+ { DO_IRP_OC_CHALLENGE_RESPONSE, "CHALLENGE_RESPONSE" },
+ { DO_IRP_OC_VERIFY_RESPONSE, "VERIFY_RESPONSE" },
+ { DO_IRP_OC_HOME_PREFIX, "HOME_PREFIX" },
+ { DO_IRP_OC_UNHOME_PREFIX, "UNHOME_PREFIX" },
+ { DO_IRP_OC_LIST_HOMED_PREFIXES, "LIST_HOMED_PREFIXES" },
+ { DO_IRP_OC_SESSION_SETUP, "SESSION_SETUP" },
+ { DO_IRP_OC_SESSION_TERMINATE, "SESSION_TERMINATE" },
+ { 0, NULL },
+};
+
+#define DO_IRP_RC_RESERVED 0
+#define DO_IRP_RC_SUCCESS 1
+#define DO_IRP_RC_ERROR 2
+#define DO_IRP_RC_SERVER_BUSY 3
+#define DO_IRP_RC_PROTOCOL_ERROR 4
+#define DO_IRP_RC_OPERATION_DENIED 5
+#define DO_IRP_RC_RECUR_LIMIT_EXCEEDED 6
+#define DO_IRP_RC_SERVER_BACKUP 7
+#define DO_IRP_RC_ID_NOT_FOUND 100
+#define DO_IRP_RC_ID_ALREADY_EXIST 101
+#define DO_IRP_RC_INVALID_ID 102
+#define DO_IRP_RC_ELEMENT_NOT_FOUND 200
+#define DO_IRP_RC_ELEMENT_ALREADY_EXIST 201
+#define DO_IRP_RC_ELEMENT_INVALID 202
+#define DO_IRP_RC_EXPIRED_SITE_INFO 300
+#define DO_IRP_RC_SERVER_NOT_RESP 301
+#define DO_IRP_RC_SERVICE_REFERRAL 302
+#define DO_IRP_RC_PREFIX_REFERRAL 303
+#define DO_IRP_RC_INVALID_ADMIN 400
+#define DO_IRP_RC_ACCESS_DENIED 401
+#define DO_IRP_RC_AUTHEN_NEEDED 402
+#define DO_IRP_RC_AUTHEN_FAILED 403
+#define DO_IRP_RC_INVALID_CREDENTIAL 404
+#define DO_IRP_RC_AUTHEN_TIMEOUT 405
+#define DO_IRP_RC_UNABLE_TO_AUTHEN 406
+#define DO_IRP_RC_SESSION_TIMEOUT 500
+#define DO_IRP_RC_SESSION_FAILED 501
+#define DO_IRP_RC_SESSION_KEY_INVALID 502
+#define DO_IRP_RC_SESSION_MSG_REJECTED 505
+
+
+static const value_string responsecode_vals[] = {
+ { DO_IRP_RC_RESERVED, "RESERVED" },
+ { DO_IRP_RC_SUCCESS, "SUCCESS" },
+ { DO_IRP_RC_ERROR, "ERROR" },
+ { DO_IRP_RC_SERVER_BUSY, "SERVER_BUSY" },
+ { DO_IRP_RC_PROTOCOL_ERROR, "PROTOCOL_ERROR" },
+ { DO_IRP_RC_OPERATION_DENIED, "OPERATION_DENIED" },
+ { DO_IRP_RC_RECUR_LIMIT_EXCEEDED, "RECUR_LIMIT_EXCEEDED" },
+ { DO_IRP_RC_SERVER_BACKUP, "SERVER_BACKUP" },
+ { DO_IRP_RC_ID_NOT_FOUND, "ID_NOT_FOUND" },
+ { DO_IRP_RC_ID_ALREADY_EXIST, "ID_ALREADY_EXIST" },
+ { DO_IRP_RC_INVALID_ID, "INVALID_ID" },
+ { DO_IRP_RC_ELEMENT_NOT_FOUND, "ELEMENT_NOT_FOUND" },
+ { DO_IRP_RC_ELEMENT_ALREADY_EXIST, "ELEMENT_ALREADY_EXIST" },
+ { DO_IRP_RC_ELEMENT_INVALID, "ELEMENT_INVALID" },
+ { DO_IRP_RC_EXPIRED_SITE_INFO, "EXPIRED_SITE_INFO" },
+ { DO_IRP_RC_SERVER_NOT_RESP, "SERVER_NOT_RESP" },
+ { DO_IRP_RC_SERVICE_REFERRAL, "SERVICE_REFERRAL" },
+ { DO_IRP_RC_PREFIX_REFERRAL, "PREFIX_REFERRAL" },
+ { DO_IRP_RC_INVALID_ADMIN, "INVALID_ADMIN" },
+ { DO_IRP_RC_ACCESS_DENIED, "ACCESS_DENIED" },
+ { DO_IRP_RC_AUTHEN_NEEDED, "AUTHEN_NEEDED" },
+ { DO_IRP_RC_AUTHEN_FAILED, "AUTHEN_FAILED" },
+ { DO_IRP_RC_INVALID_CREDENTIAL, "INVALID_CREDENTIAL" },
+ { DO_IRP_RC_AUTHEN_TIMEOUT, "AUTHEN_TIMEOUT" },
+ { DO_IRP_RC_UNABLE_TO_AUTHEN, "UNABLE_TO_AUTHEN" },
+ { DO_IRP_RC_SESSION_TIMEOUT, "SESSION_TIMEOUT" },
+ { DO_IRP_RC_SESSION_FAILED, "SESSION_FAILED" },
+ { DO_IRP_RC_SESSION_KEY_INVALID, "SESSION_KEY_INVALID" },
+ { DO_IRP_RC_SESSION_MSG_REJECTED, "SESSION_MSG_REJECTED" },
+ { 0, NULL },
+};
+
+#define DO_IRP_DIGEST_ALGO_MD5 1
+#define DO_IRP_DIGEST_ALGO_SHA1 2
+#define DO_IRP_DIGEST_ALGO_SHA256 3
+
+static const value_string digest_algo_vals[] = {
+ { DO_IRP_DIGEST_ALGO_MD5, "MD5" },
+ { DO_IRP_DIGEST_ALGO_SHA1, "SHA-1" },
+ { DO_IRP_DIGEST_ALGO_SHA256, "SHA-256" },
+ { 0, NULL },
+};
+
+#define DO_IRP_TTL_RELATIVE 0
+#define DO_IRP_TTL_ABSOLUTE 1
+
+static const value_string ttl_vals[] = {
+ { DO_IRP_TTL_RELATIVE, "relative" },
+ { DO_IRP_TTL_ABSOLUTE, "absolute" },
+ { 0, NULL },
+};
+
+static const value_string hashoption_vals[] = {
+ { 0x0, "HASH_BY_PREFIX" },
+ { 0x1, "HASH_BY_SUFFIX" },
+ { 0x2, "HASH_BY_IDENTIFIER" },
+ { 0, NULL },
+};
+
+static const value_string transportproto_vals[] = {
+ { 0x0, "UDP" },
+ { 0x1, "TCP" },
+ { 0x2, "HTTP" },
+ { 0x3, "HTTPS" },
+ { 0, NULL },
+};
+
+static const value_string verification_resp_vals[] = {
+ { 0x0, "Fail" },
+ { 0x1, "Match" },
+ { 0, NULL },
+};
+
+static const value_string key_exchange_vals[] = {
+ { 0x4, "Diffie-Hellman" },
+ { 0, NULL },
+};
+
+static reassembly_table do_irp_reassemble_table;
+
+/* wmem hash/equal funcs */
+static guint
+do_irp_handle_hash (gconstpointer v)
+{
+ const struct do_irp_request_hash_key *key = (const struct do_irp_request_hash_key *)v;
+ guint val;
+
+ val = key->conv_index + key->reqid;
+
+ return val;
+}
+
+static gint
+do_irp_handle_equal(gconstpointer v, gconstpointer w)
+{
+ const struct do_irp_request_hash_key *v1 = (const struct do_irp_request_hash_key *)v;
+ const struct do_irp_request_hash_key *v2 = (const struct do_irp_request_hash_key *)w;
+
+ if (
+ v1->conv_index == v2->conv_index &&
+ v1->reqid == v2->reqid
+ )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Decodes a string to the given hf and adds it to a tree
+ * All "strings" are defined as 4 octets representing the length of of the actual string,
+ * followed by the octets representing the actual string.
+ *
+ * Passed hf must be of any FT_STRING type
+ *
+ * Returns length of the dissected string
+ * length, value_of_string and string_tree can be used by the calling function.
+ */
+static gint
+decode_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, int hf, const char **value_of_string)
+{
+ guint32 len = tvb_get_gint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_item *ti;
+
+ const char *text = tvb_get_string_enc(pinfo->pool, tvb, offset+4, len, ENC_UTF_8);
+
+ if(len) {
+ ti = proto_tree_add_string_format_value(tree, hf, tvb, offset, len + 4, text, "%s, Len: %u", text, len);
+ } else {
+ ti = proto_tree_add_string_format_value(tree, hf, tvb, offset, len + 4, text, "empty, Len: %u", len);
+ }
+
+ proto_tree *string_tree = proto_item_add_subtree(ti, ett_do_irp_string);
+
+ proto_tree_add_item(string_tree, hf_do_irp_string_len, tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(string_tree, hf_do_irp_string_value, tvb, offset + 4, len, ENC_UTF_8);
+
+ if(value_of_string != NULL) {
+ *value_of_string = text;
+ }
+
+ return len + 4;
+}
+
+/*
+ * Decodes generic byte-values to the given hf and adds it to a tree
+ *
+ * Returns length of the dissected value
+ */
+static gint
+decode_generic_data(tvbuff_t *tvb, proto_tree *tree, gint offset, int hf)
+{
+ guint32 len = tvb_get_gint32(tvb, offset, ENC_BIG_ENDIAN);
+
+ proto_item *ti = proto_tree_add_item(tree, hf, tvb, offset, len + 4, ENC_NA);
+ proto_tree *string_tree = proto_item_add_subtree(ti, ett_do_irp_string);
+
+ proto_tree_add_item(string_tree, hf_do_irp_data_len, tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(string_tree, hf_do_irp_data_value, tvb, offset + 4, len, ENC_NA);
+
+ return len + 4;
+}
+
+/*
+ * Decodes public key data (e.g. in HS_SITE, HS_PUBKEY)
+ *
+ * Returns length of the dissected data
+ */
+static gint
+decode_pk_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ gint len = 0;
+
+ guint32 pk_len = tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN);
+
+ proto_item *ti = proto_tree_add_item(tree, hf_do_irp_pkrec, tvb, offset, pk_len + 4, ENC_NA);
+ proto_tree *pk_tree = proto_item_add_subtree(ti, ett_do_irp_pk);
+
+ proto_tree_add_item(pk_tree, hf_do_irp_pkrec_len, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ const char *pk_type;
+ gint pk_type_len = decode_string(tvb, pinfo, pk_tree, offset + len, hf_do_irp_pkrec_type, &pk_type);
+ len += pk_type_len;
+
+ len += 2; /* Reserved */
+
+ proto_item_append_text(pk_tree, " (%s)", pk_type);
+
+ if(!strcmp("DSA_PUB_KEY", pk_type)) {
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dsa_q);
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dsa_p);
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dsa_g);
+ decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dsa_y);
+ }
+ else if(!strcmp("RSA_PUB_KEY", pk_type)) {
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_rsa_exp);
+ decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_rsa_mod);
+ /* len += 4; */ /* unused, 4 empty bytes */
+ }
+ else if(!strcmp("DH_PUB_KEY", pk_type)) {
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dh_y);
+ len += decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dh_p);
+ decode_generic_data(tvb, pk_tree, offset + len, hf_do_irp_pkrec_dh_g);
+ }
+ /* else: undefined, not dissectable */
+
+ return pk_len + 4;
+}
+
+/*
+ * Decodes a HS_ADMIN element
+ *
+ * Returns length of the dissected data
+ */
+static gint
+decode_hsadmin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ gint len = 0;
+
+ proto_tree *ti_hsadmin = proto_tree_add_item(tree, hf_do_irp_identrecord_value, tvb, offset + len, -1, ENC_NA);
+ proto_tree *do_irp_hsadmin_tree = proto_item_add_subtree(ti_hsadmin, ett_do_irp_hsadmin);
+
+ proto_tree_add_item(do_irp_hsadmin_tree, hf_do_irp_identrecord_value_len, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ static int* const hsadmin_permission_bits[] = {
+ &hf_do_irp_hsadmin_perm_ldp,
+ &hf_do_irp_hsadmin_perm_li,
+ &hf_do_irp_hsadmin_perm_ar,
+ &hf_do_irp_hsadmin_perm_aa,
+ &hf_do_irp_hsadmin_perm_ra,
+ &hf_do_irp_hsadmin_perm_ma,
+ &hf_do_irp_hsadmin_perm_ae,
+ &hf_do_irp_hsadmin_perm_de,
+ &hf_do_irp_hsadmin_perm_me,
+ &hf_do_irp_hsadmin_perm_adp,
+ &hf_do_irp_hsadmin_perm_di,
+ &hf_do_irp_hsadmin_perm_ai,
+ NULL
+ };
+
+ proto_tree_add_bitmask(do_irp_hsadmin_tree, tvb, offset + len, hf_do_irp_hsadmin_perm, ett_do_irp_element_hsadmin_permission_flags, hsadmin_permission_bits, ENC_BIG_ENDIAN);
+ len += 2;
+
+ const char *admin_identifier;
+ len += decode_string(tvb, pinfo, do_irp_hsadmin_tree, offset + len, hf_do_irp_hsadmin_ident, &admin_identifier);
+
+ proto_tree_add_item(do_irp_hsadmin_tree, hf_do_irp_hsadmin_idx, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ proto_item_append_text(ti_hsadmin, " %s, Index: %u", admin_identifier, tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN));
+ len += 4;
+
+ proto_item_set_len(ti_hsadmin, len);
+ return len;
+}
+
+/*
+ * Decodes a HS_SITE element
+ *
+ * Returns length of the dissected data
+ */
+static gint
+decode_hssite(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ gint len = 0;
+
+ proto_tree *ti_hssite = proto_tree_add_item(tree, hf_do_irp_identrecord_value, tvb, offset + len, -1, ENC_NA);
+ proto_tree *do_irp_hssite_tree = proto_item_add_subtree(ti_hssite, ett_do_irp_hssite);
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_identrecord_value_len, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_body_hssite_version, tvb, offset + len, 2, ENC_BIG_ENDIAN);
+ len += 2;
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_protoversion_major, tvb, offset + len, 1, ENC_BIG_ENDIAN);
+ len += 1;
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_protoversion_minor, tvb, offset + len, 1, ENC_BIG_ENDIAN);
+ len += 1;
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_serial, tvb, offset + len, 2, ENC_BIG_ENDIAN);
+ len += 2;
+
+ static int* const hssite_primary_bits[] = {
+ &hf_do_irp_hssite_primask_pri,
+ &hf_do_irp_hssite_primask_multi,
+ NULL
+ };
+
+ proto_tree_add_bitmask(do_irp_hssite_tree, tvb, offset + len, hf_do_irp_hssite_primask, ett_do_irp_element_hsadmin_primary_flags, hssite_primary_bits, ENC_BIG_ENDIAN);
+ len += 1;
+
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_hashoption, tvb, offset + len, 1, ENC_BIG_ENDIAN);
+ len += 1;
+
+ len += decode_string(tvb, pinfo, do_irp_hssite_tree, offset + len, hf_do_irp_hssite_hashfilter, NULL);
+
+ guint32 attr = tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_attr_count, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ for(guint32 i = 0; i < attr; i++) {
+ proto_tree *ti_hssite_attr = proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_attr, tvb, offset + len, -1, ENC_NA);
+ proto_tree *do_irp_hssite_attr_tree = proto_item_add_subtree(ti_hssite_attr, ett_do_irp_hssite_attribute);
+ gint attr_len = 0;
+
+ const char *attr_name;
+
+ attr_len += decode_string(tvb, pinfo, do_irp_hssite_attr_tree, offset + len + attr_len, hf_do_irp_hssite_attr_key, &attr_name);
+ attr_len += decode_string(tvb, pinfo, do_irp_hssite_attr_tree, offset + len + attr_len, hf_do_irp_hssite_attr_value, NULL);
+ len += attr_len;
+ proto_item_append_text(do_irp_hssite_attr_tree, " (%s)", attr_name);
+ proto_item_set_len(ti_hssite_attr, attr_len);
+ }
+
+ guint32 serv = tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_srvcount, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ for(guint32 i = 0; i < serv; i++) {
+
+ proto_tree *ti_hssite_serv = proto_tree_add_item(do_irp_hssite_tree, hf_do_irp_hssite_srv, tvb, offset + len, -1, ENC_NA);
+ proto_tree *do_irp_hssite_serv_tree = proto_item_add_subtree(ti_hssite_serv, ett_do_irp_hssite_server);
+ gint serv_len = 0;
+
+ proto_tree_add_item(do_irp_hssite_serv_tree, hf_do_irp_hssite_srv_id, tvb, offset + len + serv_len, 4, ENC_BIG_ENDIAN);
+ proto_item_append_text(do_irp_hssite_serv_tree, " (ID: %u)", tvb_get_guint32(tvb, offset + len + serv_len, ENC_BIG_ENDIAN));
+ serv_len += 4;
+
+ proto_tree_add_item(do_irp_hssite_serv_tree, hf_do_irp_hssite_srv_addr, tvb, offset + len + serv_len, 16, ENC_NA);
+ serv_len += 16;
+
+ serv_len += decode_pk_data(tvb, pinfo, do_irp_hssite_serv_tree, offset + len + serv_len);
+
+ guint32 servif = tvb_get_guint32(tvb, offset + len + serv_len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_hssite_serv_tree, hf_do_irp_hssite_srv_ifcount, tvb, offset + len + serv_len, 4, ENC_BIG_ENDIAN);
+ serv_len += 4;
+
+ for(guint32 j = 0; j < servif; j++) {
+
+ proto_tree *ti_hssite_serv_if = proto_tree_add_item(do_irp_hssite_serv_tree, hf_do_irp_hssite_srv_if, tvb, offset + len + serv_len, 6, ENC_NA);
+ proto_tree *do_irp_hssite_serv_if_tree = proto_item_add_subtree(ti_hssite_serv_if, ett_do_irp_hssite_server_if);
+
+ static int* const hsadmin_srv_if_type_bits[] = {
+ &hf_do_irp_hssite_srv_if_type_res,
+ &hf_do_irp_hssite_srv_if_type_admin,
+ NULL
+ };
+
+ proto_tree_add_bitmask(do_irp_hssite_serv_if_tree, tvb, offset + len + serv_len, hf_do_irp_hssite_srv_if_type, ett_do_irp_hssite_server_if_flags, hsadmin_srv_if_type_bits, ENC_BIG_ENDIAN);
+ serv_len += 1;
+
+ guint8 serv_if_proto = tvb_get_guint8(tvb, offset + len + serv_len);
+ proto_tree_add_item(do_irp_hssite_serv_if_tree, hf_do_irp_hssite_srv_if_proto, tvb, offset + len + serv_len, 1, ENC_BIG_ENDIAN);
+ serv_len += 1;
+
+ guint32 serv_if_port = tvb_get_guint32(tvb, offset + len + serv_len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_hssite_serv_if_tree, hf_do_irp_hssite_srv_if_port, tvb, offset + len + serv_len, 4, ENC_BIG_ENDIAN);
+ serv_len += 4;
+
+ proto_item_append_text(do_irp_hssite_serv_if_tree, " (%s:%u)",
+ val_to_str_const(serv_if_proto, transportproto_vals, "Unknown"),
+ serv_if_port
+ );
+ }
+
+ proto_item_set_len(ti_hssite_serv, serv_len);
+ len += serv_len;
+ }
+
+ proto_item_set_len(ti_hssite, len);
+ return len;
+}
+
+/*
+ * Decodes an identifier record
+ *
+ * Returns length of the dissected record
+ */
+static gint
+decode_identifier_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset)
+{
+ gint len = 0;
+
+ const char *type_string;
+
+ proto_item *ti = proto_tree_add_item(tree, hf_do_irp_identrecord, tvb, offset, -1, ENC_NA);
+ proto_tree *do_irp_record_tree = proto_item_add_subtree(ti, ett_do_irp_identifier_record);
+
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_idx, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_ts, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ proto_item *ts = proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_ts_utc, tvb, offset + len, 4, ENC_TIME_SECS);
+ proto_item_set_generated(ts);
+ len += 4;
+
+ guint8 ttl_type = tvb_get_guint8(tvb, offset + len);
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_ttl_type, tvb, offset + len, 1, ENC_BIG_ENDIAN);
+ len += 1;
+
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_ttl, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ if(ttl_type == DO_IRP_TTL_ABSOLUTE) {
+ proto_item *ttl = proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_ttl_absolute, tvb, offset + len, 4, ENC_TIME_SECS);
+ proto_item_set_generated(ttl);
+ }
+ len += 4;
+
+ static int* const permission_bits[] = {
+ &hf_do_irp_identrecord_perm_ar,
+ &hf_do_irp_identrecord_perm_aw,
+ &hf_do_irp_identrecord_perm_pr,
+ &hf_do_irp_identrecord_perm_pw,
+ NULL
+ };
+
+ proto_tree_add_bitmask(do_irp_record_tree, tvb, offset + len, hf_do_irp_identrecord_perm, ett_do_irp_element_permission_flags, permission_bits, ENC_BIG_ENDIAN);
+ len += 1;
+
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_identrecord_type, &type_string);
+ proto_item_append_text(do_irp_record_tree, " (%s)", type_string);
+
+ if(!strcmp("HS_ADMIN", type_string)) {
+ len += decode_hsadmin(tvb, pinfo, do_irp_record_tree, offset + len);
+ }
+ else if(!strcmp("HS_SITE", type_string) || !strcmp("HS_SITE.PREFIX", type_string)) {
+ len += decode_hssite(tvb, pinfo, do_irp_record_tree, offset + len);
+ }
+ else if(!strcmp("HS_SERV", type_string) || !strcmp("HS_SERV.PREFIX", type_string)) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hsserv_ident, NULL);
+ }
+ else if(!strcmp("HS_PUBKEY", type_string)) {
+ len += decode_pk_data(tvb, pinfo, do_irp_record_tree, offset + len);
+ }
+ else if(!strcmp("HS_VLIST", type_string)) {
+ guint32 refs = tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_hsvlist_count, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ for(guint32 i = 0; i < refs; i++) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hsvlist_ref, NULL);
+ }
+ }
+ else if(!strcmp("HS_NAMESPACE", type_string)) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hsnamespace, NULL);
+ }
+ else if(!strcmp("HS_ALIAS", type_string)) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hsalias, NULL);
+ }
+ else if(!strcmp("HS_CERT", type_string)) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hscert_jwt, NULL);
+ }
+ else if(!strcmp("HS_SIGNATURE", type_string)) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_hssignature_jwt, NULL);
+ }
+ else if(
+ !strcmp("DESC", type_string) ||
+ !strcmp("EMAIL", type_string) ||
+ !strcmp("URL", type_string)
+ ) {
+ /* generic string */
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_identrecord_value_string, NULL);
+ }
+ else {
+ /* generic data */
+ len += decode_generic_data(tvb, do_irp_record_tree, offset + len, hf_do_irp_identrecord_value);
+ }
+
+ guint32 references = tvb_get_guint32(tvb, offset + len, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_record_tree, hf_do_irp_identrecord_refcount, tvb, offset + len, 4, ENC_BIG_ENDIAN);
+ len += 4;
+
+ for(guint32 i = 0; i < references; i++) {
+ len += decode_string(tvb, pinfo, do_irp_record_tree, offset + len, hf_do_irp_identrecord_ref, NULL);
+ }
+
+ proto_item_set_len(ti, len);
+
+ return len;
+}
+
+/*
+ * Decodes message envelope
+ *
+ * Returns length of the dissected record
+ * It also sets reqid (Request ID) and encrypted (the encrypted bit)
+ */
+static int
+decode_envelope(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 *reqid, gboolean *encrypted)
+{
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DO-IRP");
+ col_clear(pinfo->cinfo,COL_INFO);
+
+ gint offset = 0;
+
+ /* Message Envelope */
+ proto_item *ti_envelope = proto_tree_add_item(tree, hf_do_irp_envelope, tvb, offset, 20, ENC_NA);
+ proto_tree *do_irp_envelope_tree = proto_item_add_subtree(ti_envelope, ett_do_irp_envelope);
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_version_major, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_version_minor, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ static int* const envelope_flag_bits[] = {
+ &hf_do_irp_flag_cp,
+ &hf_do_irp_flag_ec,
+ &hf_do_irp_flag_tc,
+ NULL
+ };
+
+ *encrypted = (gboolean)tvb_get_bits8(tvb, offset*8 + 1, 1);
+ proto_tree_add_bitmask(do_irp_envelope_tree, tvb, offset, hf_do_irp_flags, ett_do_irp_envelope_flags, envelope_flag_bits, ENC_BIG_ENDIAN);
+ proto_tree_add_bits_item(do_irp_envelope_tree, hf_do_irp_version_major_sugg, tvb, offset*8+3, 5, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_version_minor_sugg, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_sessid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ *reqid = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_reqid, tvb, offset, 4, ENC_BIG_ENDIAN);
+ col_append_fstr(pinfo->cinfo, COL_INFO, "ReqID=%u", tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN));
+ offset += 4;
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_seq, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(do_irp_envelope_tree, hf_do_irp_msglen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
+/*
+ * Decodes message header, body and credential record
+ *
+ * Returns length of the dissected record
+ */
+static int
+decode_header_body_credential(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 reqid)
+{
+ conversation_t *conversation;
+ struct do_irp_request_hash_key request_key, *new_request_key;
+ struct do_irp_request_hash_val *request_val = NULL;
+ proto_item *r_pkt;
+
+ /* Message Header */
+ proto_item *ti_header = proto_tree_add_item(tree, hf_do_irp_header, tvb, 0, 24, ENC_NA);
+ proto_tree *do_irp_header_tree = proto_item_add_subtree(ti_header, ett_do_irp_header);
+
+ gint offset = 0;
+
+ guint32 opcode = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_opcode, tvb, offset, 4, ENC_BIG_ENDIAN);
+ const char *opcode_text = val_to_str_const(tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN), opcode_vals, "Unknown OpCode");
+ offset += 4;
+
+ guint32 respcode = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_responsecode, tvb, offset, 4, ENC_BIG_ENDIAN);
+ const char *respcode_text = val_to_str_const(tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN), responsecode_vals, "Unknown RespCode");
+ offset += 4;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s, %s]", opcode_text, respcode_text);
+
+ static int* const header_flag_bits[] = {
+ &hf_do_irp_opflags_at,
+ &hf_do_irp_opflags_ct,
+ &hf_do_irp_opflags_enc,
+ &hf_do_irp_opflags_rec,
+ &hf_do_irp_opflags_ca,
+ &hf_do_irp_opflags_cn,
+ &hf_do_irp_opflags_kc,
+ &hf_do_irp_opflags_po,
+ &hf_do_irp_opflags_rd,
+ &hf_do_irp_opflags_owe,
+ &hf_do_irp_opflags_mns,
+ &hf_do_irp_opflags_dnr,
+ NULL
+ };
+
+ proto_tree_add_bitmask(do_irp_header_tree, tvb, offset, hf_do_irp_opflags, ett_do_irp_header_flags, header_flag_bits, ENC_BIG_ENDIAN);
+ guint32 header_opflags = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_sisn, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_rcount, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 2; /* One byte empty */
+
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_expiration, tvb, offset, 4, ENC_TIME_SECS);
+ offset += 4;
+
+ proto_tree_add_item(do_irp_header_tree, hf_do_irp_bodylen, tvb, offset, 4, ENC_BIG_ENDIAN);
+ guint32 body_len = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ /* Message Body */
+ if(tvb_captured_length_remaining(tvb, offset) > 0 && body_len > 0) {
+
+ proto_item *ti_body = proto_tree_add_item(tree, hf_do_irp_body, tvb, offset, body_len, ENC_NA);
+ proto_tree *do_irp_body_tree = proto_item_add_subtree(ti_body, ett_do_irp_body);
+
+ gint body_start_offset = offset;
+
+ /* If RD bit is set, body must start with message digest (response only) */
+ if(header_opflags & 0x800000 && respcode > DO_IRP_RC_RESERVED) {
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_digest_algo, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ switch (tvb_get_guint8(tvb, offset-1)) {
+
+ case DO_IRP_DIGEST_ALGO_MD5:
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_digest, tvb, offset, 16, ENC_NA);
+ offset += 16;
+ break;
+
+ case DO_IRP_DIGEST_ALGO_SHA1:
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_digest, tvb, offset, 20, ENC_NA);
+ offset += 20;
+ break;
+
+ case DO_IRP_DIGEST_ALGO_SHA256:
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_digest, tvb, offset, 32, ENC_NA);
+ offset += 32;
+ break;
+
+ default:
+ expert_add_info(pinfo, do_irp_body_tree, &ei_do_irp_digest_unknown);
+ /* We are now unable to dissect further because the fields now have variable length */
+ call_data_dissector(
+ tvb_new_subset_length(tvb, offset, -1), pinfo, do_irp_body_tree);
+ return tvb_captured_length(tvb);
+
+ }
+ }
+
+ if(opcode == DO_IRP_OC_RESOLUTION && respcode == DO_IRP_RC_RESERVED) { /* Query */
+
+ const char *identifier_text;
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, &identifier_text);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", identifier_text);
+
+ guint32 index_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_idxcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < index_entries; i++) {
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_idx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+
+ guint32 type_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_typecount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < type_entries; i++) {
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_type, NULL);
+ }
+
+ }
+ else if(
+ (opcode == DO_IRP_OC_RESOLUTION && respcode == DO_IRP_RC_SUCCESS) || /* Successful query response */
+ (opcode == DO_IRP_OC_ADD_ELEMENT && respcode == DO_IRP_RC_RESERVED) || /* Add elements request */
+ (opcode == DO_IRP_OC_MODIFY_ELEMENT && respcode == DO_IRP_RC_RESERVED) || /* Modify elements request */
+ (opcode == DO_IRP_OC_CREATE_ID && respcode == DO_IRP_RC_RESERVED) /* Create identifier request */
+ ) {
+
+ const char *identifier_text;
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, &identifier_text);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", identifier_text);
+
+ guint32 element_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_identcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < element_entries; i++) {
+ offset += decode_identifier_record(tvb, pinfo, do_irp_body_tree, offset);
+
+ }
+
+ }
+ if(opcode == DO_IRP_OC_REMOVE_ELEMENT && respcode == DO_IRP_RC_RESERVED) { /* Remove elements request */
+
+ const char *identifier_text;
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, &identifier_text);
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", identifier_text);
+
+ guint32 index_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_idxcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < index_entries; i++) {
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_idx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+
+ }
+ else if( /* Referral response */
+ (opcode == DO_IRP_OC_RESOLUTION && respcode == DO_IRP_RC_SERVICE_REFERRAL) ||
+ (opcode == DO_IRP_OC_RESOLUTION && respcode == DO_IRP_RC_PREFIX_REFERRAL)
+ ) {
+
+ const char *refident;
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_refident, &refident);
+
+ /* The following identifier records only exist if ReferralIdentifier is not provided, otherwise it must be empty */
+ if(strlen(refident) == 0) {
+
+ guint32 element_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_identcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < element_entries; i++) {
+ offset += decode_identifier_record(tvb, pinfo, do_irp_body_tree, offset);
+
+ }
+ }
+
+ }
+ else if(opcode == DO_IRP_OC_VERIFY_RESPONSE && respcode == DO_IRP_RC_SUCCESS) { /* Challenge response verification response */
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_veri_result, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ }
+ else if(opcode == DO_IRP_OC_VERIFY_RESPONSE && respcode == DO_IRP_RC_RESERVED) { /* Challenge response verification */
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_keyident, NULL);
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_keyidx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ offset += decode_generic_data(tvb, do_irp_body_tree, offset, hf_do_irp_nonce);
+
+ offset += decode_generic_data(tvb, do_irp_body_tree, offset, hf_do_irp_digest);
+
+ offset += decode_generic_data(tvb, do_irp_body_tree, offset, hf_do_irp_challresp);
+
+ }
+ else if(opcode == DO_IRP_OC_CHALLENGE_RESPONSE && respcode == DO_IRP_RC_RESERVED) { /* Challenge response (client -> server) */
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_authtype, NULL);
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_keyident, NULL);
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_keyidx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ offset += decode_generic_data(tvb, do_irp_body_tree, offset, hf_do_irp_challresp);
+
+ }
+ else if(respcode == DO_IRP_RC_AUTHEN_NEEDED) { /* Challenge (server -> client) */
+
+ offset += decode_generic_data(tvb, do_irp_body_tree, offset, hf_do_irp_nonce);
+
+ }
+ else if(
+ (opcode == DO_IRP_OC_GET_SITEINFO && respcode == DO_IRP_RC_RESERVED) || /* GetSiteInfo request */
+ (opcode == DO_IRP_OC_LIST_HOMED_PREFIXES && respcode == DO_IRP_RC_RESERVED) /* List homed prefixes request */
+ ) {
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ignoredident, NULL);
+
+ }
+ else if(opcode == DO_IRP_OC_GET_SITEINFO && respcode == DO_IRP_RC_SUCCESS) { /* GetSiteInfo response */
+
+ offset += decode_hssite(tvb, pinfo, do_irp_body_tree, offset);
+
+ }
+ else if(
+ (opcode == DO_IRP_OC_CREATE_ID && respcode == DO_IRP_RC_SUCCESS) || /* Create identifier response */
+ (opcode == DO_IRP_OC_DELETE_ID && respcode == DO_IRP_RC_RESERVED) || /* Delete identifier request */
+ (opcode == DO_IRP_OC_LIST_IDS && respcode == DO_IRP_RC_RESERVED) || /* List IDs request */
+ (opcode == DO_IRP_OC_LIST_DERIVED_PREFIXES && respcode == DO_IRP_RC_RESERVED) || /* List der. prefixes request */
+ (opcode == DO_IRP_OC_HOME_PREFIX && respcode == DO_IRP_RC_RESERVED) || /* Home prefix request */
+ (opcode == DO_IRP_OC_UNHOME_PREFIX && respcode == DO_IRP_RC_RESERVED) /* Unhome prefix request */
+ ) {
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, NULL);
+
+ }
+ else if(
+ (opcode == DO_IRP_OC_LIST_IDS && respcode == DO_IRP_RC_SUCCESS) || /* List IDs response */
+ (opcode == DO_IRP_OC_LIST_DERIVED_PREFIXES && respcode == DO_IRP_RC_SUCCESS) || /* List der. prefixes response */
+ (opcode == DO_IRP_OC_LIST_HOMED_PREFIXES && respcode == DO_IRP_RC_SUCCESS) /* List homed prefixes response */
+ ) {
+
+ guint32 element_entries = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_identcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < element_entries; i++) {
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, NULL);
+ }
+
+ }
+ else if(opcode == DO_IRP_OC_SESSION_SETUP && respcode == DO_IRP_RC_RESERVED) { /* Session setup request */
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_keyexmode, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_ident, NULL);
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_idx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ offset += decode_pk_data(tvb, pinfo, do_irp_body_tree, offset);
+
+ }
+ else if(opcode == DO_IRP_OC_SESSION_SETUP && respcode == DO_IRP_RC_SUCCESS) { /* Session setup response */
+
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_keyexmode, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ offset += decode_pk_data(tvb, pinfo, do_irp_body_tree, offset);
+
+ }
+ /* All error resposes */
+ else if(
+ (respcode >= DO_IRP_RC_ERROR && respcode <= DO_IRP_RC_SERVER_NOT_RESP) ||
+ (respcode >= DO_IRP_RC_INVALID_ADMIN && respcode <= DO_IRP_RC_ACCESS_DENIED) ||
+ (respcode >= DO_IRP_RC_AUTHEN_FAILED && respcode <= DO_IRP_RC_SESSION_MSG_REJECTED)
+ ) {
+
+ if(tvb_ensure_captured_length_remaining(tvb, offset) >= 4 ) {
+ offset += decode_string(tvb, pinfo, do_irp_body_tree, offset, hf_do_irp_error_msg, NULL);
+ }
+
+ /* If body length has not been reached, there must be error indices*/
+ if((guint32)(offset - body_start_offset) < body_len) {
+
+ guint32 err_indices = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_error_idxcount, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ for(guint32 i = 0; i < err_indices; i++) {
+ proto_tree_add_item(do_irp_body_tree, hf_do_irp_error_idx, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+ }
+ }
+ else {
+ /* unsupported codes */
+ gint unhandled_bytes = body_len - (offset - body_start_offset);
+ call_data_dissector(
+ tvb_new_subset_length(tvb, offset, unhandled_bytes),
+ pinfo, do_irp_body_tree
+ );
+ offset += unhandled_bytes;
+ }
+ }
+
+ /* Message Credential */
+ if(tvb_captured_length_remaining(tvb, offset) >= 4) {
+
+ guint32 cred_len = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+
+ proto_item *ti_cred = proto_tree_add_item(tree, hf_do_irp_credential, tvb, offset, cred_len + 4, ENC_NA);
+ proto_tree *do_irp_cred_tree = proto_item_add_subtree(ti_cred, ett_do_irp_credential);
+
+ proto_tree_add_item(do_irp_cred_tree, hf_do_irp_credential_len, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ if(cred_len > 0) { /* If credential length is 0, is ends here */
+
+ offset += 8; /* Reserved */
+
+ proto_tree_add_item(do_irp_cred_tree, hf_do_irp_credential_sesscounter, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ offset += decode_string(tvb, pinfo, do_irp_cred_tree, offset, hf_do_irp_credential_type, NULL);
+
+ guint32 sig_len = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN);
+
+ if(sig_len) {
+
+ proto_item *ti_signedinfo = proto_tree_add_item(do_irp_cred_tree, hf_do_irp_credential_signedinfo, tvb, offset, sig_len + 4, ENC_NA);
+ proto_tree *do_irp_signedinfo_tree = proto_item_add_subtree(ti_signedinfo, ett_do_irp_credential_signedinfo);
+
+ proto_tree_add_item(do_irp_signedinfo_tree, hf_do_irp_credential_signedinfo_len, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ const char *algo;
+ offset += decode_string(tvb, pinfo, do_irp_signedinfo_tree, offset, hf_do_irp_credential_signedinfo_algo, &algo);
+ proto_item_append_text(do_irp_signedinfo_tree, " (%s)", algo);
+
+ offset += decode_generic_data(tvb, do_irp_signedinfo_tree, offset, hf_do_irp_credential_signedinfo_sig);
+ }
+ }
+ }
+
+ /* Conversation Handling */
+ conversation = find_or_create_conversation(pinfo);
+ request_key.conv_index = conversation->conv_index;
+ request_key.reqid = reqid;
+
+ request_val = (struct do_irp_request_hash_val *) wmem_map_lookup(do_irp_request_hash_map, &request_key);
+
+ /* If this packet is a request WITHOUT a registered request */
+ if(respcode == DO_IRP_RC_RESERVED && !request_val) {
+
+ new_request_key = wmem_new(wmem_file_scope(), struct do_irp_request_hash_key);
+ *new_request_key = request_key;
+
+ request_val = wmem_new(wmem_file_scope(), struct do_irp_request_hash_val);
+ request_val->pnum = pinfo->num;
+ request_val->pnum_resp = 0;
+ request_val->opcode = opcode;
+
+ wmem_map_insert(do_irp_request_hash_map, new_request_key, request_val);
+
+ }
+ /* If this packet is a request WITH a registered request */
+ else if(respcode == DO_IRP_RC_RESERVED && request_val) {
+
+ if(request_val->pnum_resp > 0) {
+ r_pkt = proto_tree_add_uint(tree , hf_do_irp_response_in, tvb, 0, 0, request_val->pnum_resp);
+ proto_item_set_generated(r_pkt);
+ }
+
+ }
+ /* If this packet is a response to a registered request */
+ else if(respcode != DO_IRP_RC_RESERVED && request_val) {
+
+ request_val->pnum_resp = pinfo->num;
+
+ r_pkt = proto_tree_add_uint(tree , hf_do_irp_response_to, tvb, 0, 0, request_val->pnum);
+ proto_item_set_generated(r_pkt);
+ }
+
+ return offset;
+}
+
+static gboolean
+test_do_irp(tvbuff_t *tvb)
+{
+ /* Minimum length (envelope must be present) */
+ if(tvb_captured_length(tvb) < DO_IRP_ENVELOPE_LEN)
+ return FALSE;
+
+ /* Supported versions (2, 3) */
+ guint8 majorversion = tvb_get_guint8(tvb, 0);
+ if(majorversion < 2 || majorversion > 3)
+ return FALSE;
+
+ /* Message Length must not be 0 */
+ if(tvb_get_guint32(tvb, 16, ENC_BIG_ENDIAN) == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static guint
+get_do_irp_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
+{
+ return (tvb_get_guint32(tvb, offset + 16, ENC_BIG_ENDIAN) + DO_IRP_ENVELOPE_LEN);
+}
+
+static int
+dissect_do_irp_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+
+ /* Do some basic tests */
+ if(!test_do_irp(tvb))
+ return 0;
+
+ proto_item *ti = proto_tree_add_item(tree, proto_do_irp, tvb, 0, -1, ENC_NA);
+ proto_tree *do_irp_tree = proto_item_add_subtree(ti, ett_do_irp);
+
+ guint32 reqid;
+ gboolean encrypted;
+ tvbuff_t *new_tvb = NULL;
+ gint offset = 0;
+
+ /*
+ * RFC 3652 defines `<MessageFlag>` in 2.2.1.2 as two octets containing three flags.
+ * | MessageFlag (3 bits) | Reserved (13 bits) |
+ *
+ * DO-IRP v3.0 divided this field into three fields in 6.2.1 ff. while maintaining backward compatibility.
+ * | Flag (3 bits) | SuggMajor (5 bits) | SuggMinor (8 bits) |
+ *
+ * Both documents state that in case of fragmentation, each fragment must contain an envelope with the truncated bit (TC) set.
+ * In the wild the TC-flag is often ignored or not set. Therefore, reassembly is not (only) based on the TC-bit here,
+ * to be able to generate expert info when protocol specs are violated.
+ */
+
+ guint32 msg_len = tvb_get_guint32(tvb, 16, ENC_BIG_ENDIAN); /* Length of over-all message, excluding enevlope */
+ guint8 env_flags = tvb_get_guint8(tvb, 2);
+
+ /* Envelope is always present */
+ offset += decode_envelope(tvb, pinfo, do_irp_tree, &reqid, &encrypted);
+
+ if (
+ msg_len > (DO_IRP_MAX_UDP_SIZE - DO_IRP_ENVELOPE_LEN) || /* Message does not fit into one packet */
+ env_flags & 0x20 /* TC-bit set */
+ ) {
+ /* fragmented */
+
+ fragment_head *frag_msg = NULL;
+ gboolean first_frag = FALSE;
+
+ guint16 msg_reqid = tvb_get_guint32(tvb, 8, ENC_BIG_ENDIAN);
+ guint16 msg_seqid = tvb_get_guint32(tvb, 12, ENC_BIG_ENDIAN);
+
+ if( !(env_flags & 0x20) ) {
+ expert_add_info(pinfo, do_irp_tree, &ei_do_irp_frag_wo_tc);
+ }
+
+ /* Check if it's the first fragment, to set expected packets after first fragment_add */
+ if(fragment_get_tot_len(&do_irp_reassemble_table, pinfo, msg_reqid, NULL) == 0) {
+ first_frag = TRUE;
+ }
+
+ pinfo->fragmented = TRUE;
+ frag_msg = fragment_add_seq_check(&do_irp_reassemble_table, tvb, offset, pinfo,
+ msg_reqid, NULL,
+ msg_seqid,
+ tvb_captured_length_remaining(tvb, offset),
+ TRUE /* Expected packet count set */
+ );
+
+ if(first_frag) {
+
+ uint32_t expected_packets = msg_len / (DO_IRP_MAX_UDP_SIZE - DO_IRP_ENVELOPE_LEN);
+ if ((msg_len % (DO_IRP_MAX_UDP_SIZE - DO_IRP_ENVELOPE_LEN)) != 0) expected_packets++;
+
+ fragment_set_tot_len(&do_irp_reassemble_table, pinfo, msg_reqid, NULL, expected_packets-1); /* Set expected packet count (0-index) */
+ }
+
+ new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message", frag_msg, &msg_frag_items, NULL, do_irp_tree);
+
+
+ if (new_tvb) { /* Packet reassembled */
+
+ if(!encrypted) {
+ offset += decode_header_body_credential(new_tvb, pinfo, do_irp_tree, reqid);
+ } else {
+ /* Encrypted message can't be decoded */
+ col_append_str(pinfo->cinfo, COL_INFO, " (encrypted)");
+ call_data_dissector(new_tvb, pinfo, do_irp_tree);
+ offset = tvb_captured_length(tvb);
+ }
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Frag=%u, Reassembled)", msg_seqid+1);
+
+ } else { /* Packet fragment */
+
+ call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, do_irp_tree);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " (Frag=%u)", msg_seqid+1);
+ offset = tvb_captured_length(tvb);
+ }
+
+ }
+ else {
+
+ /* No fragmentation */
+ new_tvb = tvb_new_subset_remaining(tvb, offset);
+
+ if(!encrypted) {
+ offset += decode_header_body_credential(new_tvb, pinfo, do_irp_tree, reqid);
+ } else {
+ /* Encrypted message can't be decoded */
+ col_append_str(pinfo->cinfo, COL_INFO, " (encrypted)");
+ call_data_dissector(new_tvb, pinfo, do_irp_tree);
+ offset = tvb_captured_length(tvb);
+ }
+
+ }
+
+ return offset;
+}
+
+static int
+dissect_do_irp_tcp_full_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ proto_item *ti = proto_tree_add_item(tree, proto_do_irp, tvb, 0, -1, ENC_NA);
+ proto_tree *do_irp_tree = proto_item_add_subtree(ti, ett_do_irp);
+
+ guint32 reqid;
+ gboolean enc;
+ gint offset = 0;
+
+ offset += decode_envelope(tvb, pinfo, do_irp_tree, &reqid, &enc);
+ offset += decode_header_body_credential(tvb_new_subset_remaining(tvb, offset), pinfo, do_irp_tree, reqid);
+
+ return offset;
+}
+
+static int
+dissect_do_irp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ /* Do some basic tests */
+ if(!test_do_irp(tvb))
+ return 0;
+
+ tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DO_IRP_ENVELOPE_LEN, get_do_irp_message_len, dissect_do_irp_tcp_full_message, data);
+ return tvb_reported_length(tvb);
+}
+
+void
+proto_register_do_irp(void)
+{
+ static hf_register_info hf[] = {
+
+ /* Fragment handling */
+ {&hf_msg_fragments,
+ { "Message fragments", "do-irp.fragments",
+ FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment,
+ { "Message fragment", "do-irp.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_overlap,
+ { "Message fragment overlap", "do-irp.fragment.overlap",
+ FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_overlap_conflicts,
+ { "Message fragment overlapping with conflicting data", "do-irp.fragment.overlap.conflicts",
+ FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_multiple_tails,
+ { "Message has multiple tail fragments", "do-irp.fragment.multiple_tails",
+ FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_too_long_fragment,
+ { "Message fragment too long", "do-irp.fragment.too_long_fragment",
+ FT_BOOLEAN, 0, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_error,
+ { "Message defragmentation error", "do-irp.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_fragment_count,
+ { "Message fragment count", "do-irp.fragment.count",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_reassembled_in,
+ { "Reassembled in", "do-irp.reassembled.in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_reassembled_len,
+ { "Reassembled length", "do-irp.reassembled.len",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
+ {&hf_msg_reassembled_data,
+ { "Reassembled data", "do-irp.reassembled.data",
+ FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+
+ /* Generic */
+ { &hf_do_irp_string_len,
+ { "Length", "do-irp.string.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_string_value,
+ { "Value", "do-irp.string.value",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_data_len,
+ { "Length", "do-irp.data.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_data_value,
+ { "Value", "do-irp.data.value",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* Message Envelope */
+ { &hf_do_irp_envelope,
+ { "Message Envelope", "do-irp.envelope",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_version_major,
+ { "Version (Major)", "do-irp.version.major",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_version_minor,
+ { "Version (Minor)", "do-irp.version.minor",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_flags,
+ { "Flags", "do-irp.flags",
+ FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL }
+ },
+ { &hf_do_irp_flag_cp,
+ { "Compressed", "do-irp.flags.cp",
+ FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
+ },
+ { &hf_do_irp_flag_ec,
+ { "Encrypted", "do-irp.flags.ec",
+ FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
+ },
+ { &hf_do_irp_flag_tc,
+ { "Truncated", "do-irp.flags.tc",
+ FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }
+ },
+ { &hf_do_irp_version_major_sugg,
+ { "Version (Major, suggested)", "do-irp.version.major_sugg",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_version_minor_sugg,
+ { "Version (Minor, suggested)", "do-irp.version.minor_sugg",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_sessid,
+ { "Session ID", "do-irp.sessid",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_reqid,
+ { "Request ID", "do-irp.reqid",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_seq,
+ { "Sequence No.", "do-irp.seq",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_msglen,
+ { "Message Length", "do-irp.msglen",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* Message Header */
+ { &hf_do_irp_header,
+ { "Message Header", "do-irp.header",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_opcode,
+ { "Operation Code", "do-irp.opcode",
+ FT_UINT32, BASE_DEC, VALS(opcode_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_responsecode,
+ { "Response Code", "do-irp.responsecode",
+ FT_UINT32, BASE_DEC, VALS(responsecode_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags,
+ { "Flags", "do-irp.opflags",
+ FT_UINT32, BASE_HEX, NULL, 0xFFF00000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_at,
+ { "Authoritative", "do-irp.opflags.at",
+ FT_BOOLEAN, 32, NULL, 0x80000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_ct,
+ { "Certified", "do-irp.opflags.ct",
+ FT_BOOLEAN, 32, NULL, 0x40000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_enc,
+ { "Encryption", "do-irp.opflags.enc",
+ FT_BOOLEAN, 32, NULL, 0x20000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_rec,
+ { "Recursive", "do-irp.opflags.rec",
+ FT_BOOLEAN, 32, NULL, 0x10000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_ca,
+ { "Cache Authentication", "do-irp.opflags.ca",
+ FT_BOOLEAN, 32, NULL, 0x08000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_cn,
+ { "Continuous", "do-irp.opflags.cn",
+ FT_BOOLEAN, 32, NULL, 0x04000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_kc,
+ { "Keep Connection", "do-irp.opflags.kc",
+ FT_BOOLEAN, 32, NULL, 0x02000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_po,
+ { "Public Only", "do-irp.opflags.po",
+ FT_BOOLEAN, 32, NULL, 0x01000000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_rd,
+ { "Request-Digest", "do-irp.opflags.rd",
+ FT_BOOLEAN, 32, NULL, 0x00800000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_owe,
+ { "Overwrite when exists", "do-irp.opflags.owe",
+ FT_BOOLEAN, 32, NULL, 0x00400000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_mns,
+ { "Mint new suffix", "do-irp.opflags.mns",
+ FT_BOOLEAN, 32, NULL, 0x00200000, NULL, HFILL }
+ },
+ { &hf_do_irp_opflags_dnr,
+ { "Do not refer", "do-irp.opflags.dnr",
+ FT_BOOLEAN, 32, NULL, 0x00100000, NULL, HFILL }
+ },
+ { &hf_do_irp_sisn,
+ { "Site Info Serial No.", "do-irp.sisn",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_rcount,
+ { "Recursion Count", "do-irp.recursioncount",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_expiration,
+ { "Expiration Time", "do-irp.exp",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_bodylen,
+ { "Body Length", "do-irp.bodylen",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* Message Body */
+ { &hf_do_irp_body,
+ { "Message Body", "do-irp.body",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_digest_algo,
+ { "Message Digest Algorithm", "do-irp.digest_algo",
+ FT_UINT8, BASE_DEC, VALS(digest_algo_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_digest,
+ { "Message Digest", "do-irp.digest",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_error_msg,
+ { "Error Message", "do-irp.error.msg",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_error_idxcount,
+ { "Error Indices", "do-irp.error.idxcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_error_idx,
+ { "Error Index", "do-irp.error.idx",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_ident,
+ { "Identifier", "do-irp.ident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_idxcount,
+ { "Index Count", "do-irp.idxcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_idx,
+ { "Index", "do-irp.idx",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_typecount,
+ { "Type Count", "do-irp.typecount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_type,
+ { "Type Entry", "do-irp.type",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identcount,
+ { "Identifier Records", "do-irp.identcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord,
+ { "Identifier Record", "do-irp.identrecord",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_idx,
+ { "Index", "do-irp.identrecord.idx",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_type,
+ { "Type", "do-irp.identrecord.type",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_value,
+ { "Value", "do-irp.identrecord.value",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_value_string,
+ { "Value", "do-irp.identrecord.value.string",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_value_len,
+ { "Length", "do-irp.identrecord.value.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_perm,
+ { "Permission", "do-irp.identrecord.perm",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_perm_ar,
+ { "ADMIN_READ", "do-irp.identrecord.perm.ar",
+ FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_perm_aw,
+ { "ADMIN_WRITE", "do-irp.identrecord.perm.aw",
+ FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_perm_pr,
+ { "PUBLIC_READ", "do-irp.identrecord.perm.pr",
+ FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_perm_pw,
+ { "PUBLIC_WRITE", "do-irp.identrecord.perm.pw",
+ FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ts,
+ { "Timestamp", "do-irp.identrecord.ts",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ts_utc,
+ { "Timestamp (UTC)", "do-irp.identrecord.ts_utc",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ttl_type,
+ { "TTL Type", "do-irp.identrecord.ttl_type",
+ FT_UINT8, BASE_DEC, VALS(ttl_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ttl,
+ { "TTL", "do-irp.identrecord.ttl",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ttl_absolute,
+ { "TTL (until)", "do-irp.identrecord.ttl_absolute",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_refcount,
+ { "Reference Count", "do-irp.identrecord.refcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_identrecord_ref,
+ { "Reference", "do-irp.identrecord.ref",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm,
+ { "Permission", "do-irp.hsadmin.perm",
+ FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ai,
+ { "Add Identifier", "do-irp.hsadmin.perm.ai",
+ FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_di,
+ { "Delete Identifier", "do-irp.hsadmin.perm.di",
+ FT_BOOLEAN, 16, NULL, 0x0002, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_adp,
+ { "Add Derived Prefix", "do-irp.hsadmin.perm.adp",
+ FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_me,
+ { "Modify Element", "do-irp.hsadmin.perm.me",
+ FT_BOOLEAN, 16, NULL, 0x0010, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_de,
+ { "Delete Element", "do-irp.hsadmin.perm.de",
+ FT_BOOLEAN, 16, NULL, 0x0020, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ae,
+ { "Add Element", "do-irp.hsadminp.perm.ae",
+ FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ma,
+ { "Modify Admin", "do-irp.hsadmin.perm.ma",
+ FT_BOOLEAN, 16, NULL, 0x0080, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ra,
+ { "Remove Admin", "do-irp.hsadmin.perm.ra",
+ FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_aa,
+ { "Add Admin", "do-irp.hsadmin.perm.aa",
+ FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ar,
+ { "Authorized Read", "do-irp.hsadmin.perm.ar",
+ FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_li,
+ { "List Identifiers", "do-irp.hsadmin.perm.li",
+ FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_perm_ldp,
+ { "List Derived Prefixes", "do-irp.hsadmin.perm.ldp",
+ FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_idx,
+ { "Index", "do-irp.hsadmin.idx",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsadmin_ident,
+ { "Identifier", "do-irp.hsadmin.ident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_body_hssite_version,
+ { "Version", "do-irp.hssite.version",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_protoversion_major,
+ { "Protocol Version (Major)", "do-irp.hssite.protoversion.major",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_protoversion_minor,
+ { "Protocol Version (Minor)", "do-irp.hssite.protoversion.minor",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_serial,
+ { "Serial", "do-irp.hssite.serial",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_primask,
+ { "Primary Mask", "do-irp.hssite.primask",
+ FT_UINT8, BASE_HEX, NULL, 0xFF, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_primask_pri,
+ { "Primary Site", "do-irp.hssite.primask.pri",
+ FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_primask_multi,
+ { "Multi Primary", "do-irp.hssite.primask.multi",
+ FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_hashoption,
+ { "Hash Option", "do-irp.hssite.hashoption",
+ FT_UINT8, BASE_HEX, VALS(hashoption_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_hashfilter,
+ { "Hash Filter", "do-irp.hssite.hashfilter",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_attr_count,
+ { "Attributes", "do-irp.hssite.attr.num",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_attr,
+ { "Attribute", "do-irp.hssite.attr",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_attr_key,
+ { "Key", "do-irp.hssite.attr.key",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_attr_value,
+ { "Value", "do-irp.hssite.attr.value",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srvcount,
+ { "Server Count", "do-irp.hssite.srvcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv,
+ { "Server", "do-irp.hssite.srv",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_id,
+ { "ID", "do-irp.hssite.srv.id",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_addr,
+ { "Address", "do-irp.hssite.srv.addr",
+ FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_ifcount,
+ { "Interface Count", "do-irp.hssite.srv.ifcount",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if,
+ { "Interface", "do-irp.hssite.srv.if",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if_type,
+ { "Type", "do-irp.hssite.srv.if.type",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if_type_admin,
+ { "Administration", "do-irp.hssite.srv.if.type.admin",
+ FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if_type_res,
+ { "Resolution", "do-irp.hssite.srv.if.type.res",
+ FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if_proto,
+ { "Protocol", "do-irp.hssite.srv.if.proto",
+ FT_UINT8, BASE_HEX, VALS(transportproto_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssite_srv_if_port,
+ { "Port", "do-irp.hssite.srv.if.port",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec,
+ { "Public Key Data", "do-irp.pk",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_len,
+ { "Public Key Length", "do-irp.pk.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_type,
+ { "Public Key Type", "do-irp.pk.type",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dsa_q,
+ { "DSA (q)", "do-irp.pk.dsa.q",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dsa_p,
+ { "DSA (p)", "do-irp.pk.dsa.p",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dsa_g,
+ { "DSA (g)", "do-irp.pk.dsa.g",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dsa_y,
+ { "DSA (y)", "do-irp.pk.dsa.y",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dh_p,
+ { "DH (p)", "do-irp.pk.dh.p",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dh_g,
+ { "DH (g)", "do-irp.pk.dh.g",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_dh_y,
+ { "DH (y)", "do-irp.pk.dh.y",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_rsa_exp,
+ { "RSA (Exponent)", "do-irp.pk.rsa.exp",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_pkrec_rsa_mod,
+ { "RSA (Modulo)", "do-irp.pk.rsa.mod",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsserv_ident,
+ { "Identifier", "do-irp.hsserv.ident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsvlist_count,
+ { "Reference Count", "do-irp.vlist.count",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsvlist_ref,
+ { "Reference", "do-irp.vlist.ref",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsalias,
+ { "Alias", "do-irp.hsalias",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hsnamespace,
+ { "Namespace", "do-irp.hsnamespace",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hscert_jwt,
+ { "JWT", "do-irp.hscert.jwt",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_hssignature_jwt,
+ { "JWT", "do-irp.hssignature.jwt",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_refident,
+ { "Referral Identifier", "do-irp.refident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_nonce,
+ { "Nonce", "do-irp.nonce",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_authtype,
+ { "Authentication Type", "do-irp.authtype",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_keyident,
+ { "Key Identifier", "do-irp.keyident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_keyidx,
+ { "Key Index", "do-irp.keyidx",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_challresp,
+ { "Challenge Response", "do-irp.challresp",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_veri_result,
+ { "Verification Result", "do-irp.veri_result",
+ FT_UINT8, BASE_DEC, VALS(verification_resp_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_ignoredident,
+ { "Ignored Identifier", "do-irp.ignoredident",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_keyexmode,
+ { "Key Exchange Mode", "do-irp.keyexmode",
+ FT_UINT16, BASE_DEC, VALS(key_exchange_vals), 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_timeout,
+ { "Timeout", "do-irp.timeout",
+ FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_seconds, 0x0, NULL, HFILL }
+ },
+
+ /* Message Credential */
+ { &hf_do_irp_credential,
+ { "Message Credential", "do-irp.credential",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_len,
+ { "Length", "do-irp.credential.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_sesscounter,
+ { "Session Counter", "do-irp.credential.sesscounter",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_type,
+ { "Type", "do-irp.credential.type",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_signedinfo,
+ { "SignedInfo", "do-irp.credential.signedinfo",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_signedinfo_len,
+ { "Length", "do-irp.credential.signedinfo.len",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_signedinfo_algo,
+ { "Algorithm", "do-irp.credential.signedinfo.algo",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_credential_signedinfo_sig,
+ { "Signature", "do-irp.credential.signedinfo.sig",
+ FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* Conversation */
+ { &hf_do_irp_response_in,
+ { "Response in", "do-irp.response_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_do_irp_response_to,
+ { "Request in", "do-irp.response_to",
+ FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL }
+ }
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_do_irp_digest_unknown,
+ { "do-irp.header.digest.unknown", PI_MALFORMED, PI_WARN,
+ "Invalid digest algorithm", EXPFILL }
+ },
+ { &ei_do_irp_frag_wo_tc,
+ { "do-irp.envelope.tc_missing", PI_MALFORMED, PI_ERROR,
+ "Fragmentation without TC bit set", EXPFILL }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_msg_fragment,
+ &ett_msg_fragments,
+ &ett_do_irp,
+ &ett_do_irp_string,
+ &ett_do_irp_envelope,
+ &ett_do_irp_envelope_flags,
+ &ett_do_irp_header,
+ &ett_do_irp_header_flags,
+ &ett_do_irp_body,
+ &ett_do_irp_credential,
+ &ett_do_irp_credential_signedinfo,
+ &ett_do_irp_identifier_record,
+ &ett_do_irp_element_permission_flags,
+ &ett_do_irp_element_hsadmin_permission_flags,
+ &ett_do_irp_element_hsadmin_primary_flags,
+ &ett_do_irp_hsadmin,
+ &ett_do_irp_hssite,
+ &ett_do_irp_hssite_attribute,
+ &ett_do_irp_hssite_server,
+ &ett_do_irp_hssite_server_if,
+ &ett_do_irp_hssite_server_if_flags,
+ &ett_do_irp_pk
+ };
+
+ do_irp_request_hash_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), do_irp_handle_hash, do_irp_handle_equal);
+
+ proto_do_irp = proto_register_protocol("Digital Object Identifier Resolution Protocol", "DO-IRP", "do-irp");
+ expert_do_irp = expert_register_protocol(proto_do_irp);
+
+ proto_register_field_array(proto_do_irp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_register_field_array(expert_do_irp, ei, array_length(ei));
+
+ reassembly_table_register(&do_irp_reassemble_table, &addresses_ports_reassembly_table_functions);
+
+ do_irp_handle_udp = register_dissector("do-irp_udp", dissect_do_irp_udp, proto_do_irp);
+ do_irp_handle_tcp = register_dissector("do-irp_tcp", dissect_do_irp_tcp, proto_do_irp);
+}
+
+void
+proto_reg_handoff_do_irp(void)
+{
+ dissector_add_uint_with_preference("udp.port", DO_IRP_UDP_PORT, do_irp_handle_udp);
+ dissector_add_uint_with_preference("tcp.port", DO_IRP_TCP_PORT, do_irp_handle_tcp);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */