/* packet-hip.c * Definitions and routines for HIP control packet disassembly * Samu Varjonen * * Based on dissector originally created by * Jeff Ahrenholz * Thomas Henderson * Samu Varjonen * Thomas Jansen * * Packet dissector for Host Identity Protocol (HIP) packets. * This tool displays the TLV structure, verifies checksums, * and shows NULL encrypted parameters, but will not verify * signatures or decode encrypted parameters. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include void proto_register_hip(void); void proto_reg_handoff_hip(void); static dissector_handle_t hip_ip_handle; static dissector_handle_t hip_udp_handle; #define HIP_UDP_PORT 10500 #define HI_ALG_DSA 3 #define HI_ALG_RSA 5 /* HIP packet types */ typedef enum { HIP_I1=1, HIP_R1, HIP_I2, HIP_R2, HIP_UPDATE=16, HIP_NOTIFY=17, HIP_CLOSE=18, HIP_CLOSE_ACK=19 } HIP_PACKETS; /* HIP TLV parameters listed in order of RFCs */ /* RFC 5201 */ #define PARAM_R1_COUNTER 128 #define PARAM_PUZZLE 257 #define PARAM_SOLUTION 321 #define PARAM_SEQ 385 #define PARAM_ACK 449 #define PARAM_DIFFIE_HELLMAN 513 #define PARAM_HIP_TRANSFORM 577 #define PARAM_ENCRYPTED 641 #define PARAM_HOST_ID 705 /* Type number defined in RFC 5201 contents in draft-ietf-hip-cert-00 */ #define PARAM_CERT 768 #define PARAM_NOTIFICATION 832 #define PARAM_ECHO_REQUEST_SIGNED 897 #define PARAM_ECHO_RESPONSE_SIGNED 961 #define PARAM_HMAC 61505 #define PARAM_HMAC_2 61569 #define PARAM_HIP_SIGNATURE_2 61633 #define PARAM_HIP_SIGNATURE 61697 #define PARAM_ECHO_REQUEST_UNSIGNED 63661 #define PARAM_ECHO_RESPONSE_UNSIGNED 63425 /* RFC 5202 */ #define PARAM_ESP_INFO 65 #define PARAM_ESP_TRANSFORM 4095 /* RFC 5203 */ #define PARAM_REG_INFO 930 #define PARAM_REG_REQUEST 932 #define PARAM_REG_RESPONSE 934 #define PARAM_REG_FAILED 936 /* RFC 5204 */ #define PARAM_FROM 65498 #define PARAM_RVS_HMAC 65500 #define PARAM_VIA_RVS 65502 /* RFC 5206 */ #define PARAM_LOCATOR 193 /* RFC 5770 */ #define PARAM_NAT_TRAVERSAL_MODE 608 #define PARAM_TRANSACTION_PACING 610 #define PARAM_REG_FROM 950 #define PARAM_RELAY_FROM 63998 #define PARAM_RELAY_TO 64002 #define PARAM_RELAY_HMAC 65520 /* HIPv2 draft-ietf-hip-rfc5201-bis-08 see section 5.2 */ #define PARAM_HIP_CIPHER 579 #define PARAM_HIT_SUITE_LIST 715 /* Bit masks */ #define PARAM_CRITICAL_BIT 0x0001 /* See RFC 5201 section 5.1 */ #define HIP_PACKET_TYPE_MASK 0x7F /* draft-ietf-shim6-proto-12 see section 5.3 */ #define HIP_SHIM6_FIXED_BIT_P_MASK 0x80 #define HIP_SHIM6_FIXED_BIT_S_MASK 0x01 /* 00001110 Excluding the shim6 compatibility bit */ #define HIP_RESERVED_MASK 0x0E #define HIP_VERSION_MASK 0xF0 #define HIP_CONTROL_A_MASK 0x0001 #define HIP_CONTROL_C_MASK 0x0002 #define HI_HDR_FLAGS_MASK 0xFFFF0000 #define HI_HDR_PROTO_MASK 0x0000FF00 #define HI_HDR_ALG_MASK 0x000000FF static const value_string pinfo_vals[] = { { HIP_I1, "HIP I1 (HIP Initiator Packet)" }, { HIP_R1, "HIP R1 (HIP Responder Packet)" }, { HIP_I2, "HIP I2 (Second HIP Initiator Packet)" }, { HIP_R2, "HIP R2 (Second HIP Responder Packet)" }, { HIP_UPDATE, "HIP UPDATE (HIP Update Packet)" }, { HIP_NOTIFY, "HIP NOTIFY (HIP Notify Packet)" }, { HIP_CLOSE, "HIP CLOSE (HIP Close Packet)" }, { HIP_CLOSE_ACK, "HIP CLOSE_ACK (HIP Close Acknowledgment Packet)" }, { 0, NULL } }; static const value_string hip_param_vals[] = { { PARAM_ESP_INFO, "ESP_INFO" }, { PARAM_R1_COUNTER, "R1_COUNTER" }, { PARAM_LOCATOR, "LOCATOR" }, { PARAM_PUZZLE, "PUZZLE" }, { PARAM_SOLUTION, "SOLUTION" }, { PARAM_SEQ, "SEQ" }, { PARAM_ACK, "ACK" }, { PARAM_DIFFIE_HELLMAN, "DIFFIE_HELLMAN" }, { PARAM_HIP_TRANSFORM, "HIP_TRANSFORM" }, { PARAM_ENCRYPTED, "ENCRYPTED" }, { PARAM_HOST_ID, "HOST_ID" }, { PARAM_CERT, "CERT" }, { PARAM_NOTIFICATION, "NOTIFICATION" }, { PARAM_ECHO_REQUEST_SIGNED, "ECHO_REQUEST_SIGNED" }, { PARAM_ECHO_RESPONSE_SIGNED, "ECHO_RESPONSE_SIGNED" }, { PARAM_ESP_TRANSFORM, "ESP_TRANSFORM" }, { PARAM_HMAC, "HMAC" }, { PARAM_HMAC_2, "HMAC_2" }, { PARAM_HIP_SIGNATURE, "HIP_SIGNATURE" }, { PARAM_HIP_SIGNATURE_2, "HIP_SIGNATURE_2" }, { PARAM_ECHO_REQUEST_UNSIGNED, "ECHO_REQUEST_UNSIGNED" }, { PARAM_ECHO_RESPONSE_UNSIGNED, "ECHO_RESPONSE_UNSIGNED" }, { PARAM_NAT_TRAVERSAL_MODE, "NAT_TRAVERSAL_MODE" }, { PARAM_TRANSACTION_PACING, "TRANSACTION_PACING" }, { PARAM_RELAY_FROM, "RELAY_FROM" }, { PARAM_RELAY_TO, "RELAY_TO" }, { PARAM_RELAY_HMAC, "RELAY_HMAC" }, { PARAM_REG_INFO, "REG_INFO" }, { PARAM_REG_REQUEST, "REG_REQUEST" }, { PARAM_REG_RESPONSE, "REG_RESPONSE" }, { PARAM_REG_FROM, "REG_FROM" }, { PARAM_HIP_CIPHER, "HIP_CIPHER"}, { PARAM_HIT_SUITE_LIST, "HIT_SUITE_LIST"}, { 0, NULL } }; /* RFC 5201 section 5.2.6. */ static const value_string dh_group_id_vals[] = { { 0x0, "Reserved" }, { 0x01, "384-bit group" }, { 0x02, "OAKLEY well-known group 1" }, { 0x03, "1536-bit MODP group" }, { 0x04, "3072-bit MODP group" }, { 0x05, "6144-bit MODP group" }, { 0x06, "8192-bit MODP group" }, { 0, NULL } }; /* RFC 5202 section 5.1.2. */ static const value_string transform_id_vals[] = { { 0x0, "Reserved" }, { 0x01, "AES-CBC with HMAC-SHA1" }, { 0x02, "3DES-CBC with HMAC-SHA1" }, { 0x03, "3DES-CBC with HMAC-MD5" }, { 0x04, "BLOWFISH-CBC with HMAC-SHA1" }, { 0x05, "NULL with HMAC-SHA1" }, { 0x06, "NULL with HMAC-MD5" }, { 0, NULL } }; static const value_string reg_type_vals[] = { { 0x01, "RENDEZVOUS" }, /* RFC 5204 */ { 0x02, "RELAY_UDP_HIP" }, /* RFC 5770 */ { 0, NULL } }; /* RFC 5201 section 5.2.8 */ static const value_string sig_alg_vals[] = { { 0x0, "Reserved" }, { HI_ALG_DSA, "DSA" }, { HI_ALG_RSA, "RSA" }, { 0, NULL } }; /* RFC 5770 */ static const value_string mode_id_vals[] = { { 0x0, "Reserved" }, { 0x01, "UDP-encapsulation" }, { 0x02, "ICE-STUN-UDP" }, { 0, NULL } }; static const value_string hi_hdr_flags_vals[] = { { 0x0, "Other" }, { 0x0200, "Key is associated with a user" }, { 0x0201, "Zone key" }, { 0x0202, "Key is associated with non-zone entity" }, { 0, NULL } }; /* RFC 2535 section 3.1.3 */ static const value_string hi_hdr_proto_vals[] = { { 0x01, "Key is used for TLS" }, { 0x02, "Key is used for email" }, { 0x03, "Key is used for DNS security" }, { 0x04, "Key is used for Oakley/IPSEC" }, { 0xFF, "Key is valid for any protocol" }, { 0, NULL } }; /* RFC 2535 section 3.2 */ static const value_string hi_hdr_alg_vals[] = { { 0x00, "Reserved" }, { 0x01, "RSA/MD5" }, { 0x02, "Diffie-Hellman" }, { 0x03, "DSA" }, { 0x04, "elliptic curve crypto" }, { 0x05, "RSA" }, { 0xFF, "Reserved" }, { 0, NULL } }; /* RFC 5201 */ static const value_string notification_vals[] = { { 1, "Unsupported critical parameter type" }, { 7, "Invalid syntax" }, { 14, "No Diffie-Hellman proposal chosen" }, { 15, "Invalid Diffie-Hellman chosen" }, { 16, "No HIP proposal chosen" }, { 17, "Invalid HIP transform chosen" }, { 18, "No ESP proposal chosen" }, { 19, "Invalid ESP transform chosen" }, { 24, "Authentication failed" }, { 26, "Checksum failed" }, { 28, "HMAC failed" }, { 32, "Encryption failed" }, { 40, "Invalid HIT" }, { 42, "Blocked by policy" }, { 44, "Server busy please retry" }, { 0, NULL } }; #if 0 /* RFC 5770 */ static const value_string nat_traversal_mode_vals[] = { { 0, "Reserved"}, { 1, "UDP-encapsulation"}, { 2, "ICE-STUN-UDP"}, { 0, NULL } }; #endif /* HIPv2 draft-ietf-hip-rfc5201-bis-08 Section 5.2 */ static const value_string cipher_vals[] = { { 0x0, "Reserved" }, { 0x01, "NULL-ENCRYPT" }, { 0x02, "AES-128-CBC" }, { 0x03, "3DES-CBC" }, { 0x04, "AES-256-CBC" }, { 0, NULL } }; static const value_string hit_suite_vals[] = { { 0x00, "Reserved" }, { 0x01, "RSA,DSA/SHA-256" }, { 0x02, "ECDSA/SHA384" }, { 0x03, "ECDSA_LOW/SHA-1" }, { 0, NULL } }; /* functions */ static int dissect_hip_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_item *ti, int type, int tlv_len); static int proto_hip; static int hf_hip_proto; static int hf_hip_hdr_len; static int hf_hip_shim6_fixed_bit_p; static int hf_hip_packet_type; static int hf_hip_version; static int hf_hip_shim6_fixed_bit_s; static int hf_hip_controls; static int hf_hip_controls_anon; static int hf_hip_checksum; static int hf_hip_checksum_status; static int hf_hip_hit_sndr; static int hf_hip_hit_rcvr; static int hf_hip_type; static int hf_hip_tlv_ei_res; static int hf_hip_tlv_ei_keyidx; static int hf_hip_tlv_ei_oldspi; static int hf_hip_tlv_ei_newspi; static int hf_hip_tlv_r1_res; static int hf_hip_tlv_r1count; static int hf_hip_tlv_puzzle_k; static int hf_hip_tlv_puzzle_life; static int hf_hip_tlv_puzzle_o; static int hf_hip_tlv_puzzle_i; static int hf_hip_tlv_solution_k; static int hf_hip_tlv_solution_reserved; static int hf_hip_tlv_solution_o; static int hf_hip_tlv_solution_i; static int hf_hip_tlv_solution_j; static int hf_hip_tlv_seq_updid; static int hf_hip_tlv_ack_updid; static int hf_hip_tlv_dh_group_id; static int hf_hip_tlv_dh_pub; static int hf_hip_tlv_dh_pv_length; static int hf_hip_tlv_trans_id; static int hf_hip_tlv_esp_reserved; static int hf_hip_tlv_cipher_id; static int hf_hip_tlv_hit_suite_id; static int hf_hip_tlv_host_id_len; static int hf_hip_tlv_host_di_type; static int hf_hip_tlv_host_di_len; static int hf_hip_tlv_host_id_hdr; static int hf_hip_tlv_host_id_hdr_flags; static int hf_hip_tlv_host_id_hdr_proto; static int hf_hip_tlv_host_id_hdr_alg; static int hf_hip_tlv_host_id_t; static int hf_hip_tlv_host_id_q; static int hf_hip_tlv_host_id_p; static int hf_hip_tlv_host_id_g; static int hf_hip_tlv_host_id_y; static int hf_hip_tlv_host_id_e_len; static int hf_hip_tlv_host_id_e; static int hf_hip_tlv_host_id_n; static int hf_hip_tlv_notification_res; static int hf_hip_tlv_notification_type; static int hf_hip_tlv_notification_data; static int hf_hip_tlv_opaque_data; static int hf_hip_tlv_reg_ltmin; static int hf_hip_tlv_reg_ltmax; static int hf_hip_tlv_reg_lt; static int hf_hip_tlv_reg_type; static int hf_hip_tlv_reg_failtype; static int hf_hip_tlv_hmac; static int hf_hip_tlv_sig_alg; static int hf_hip_tlv_sig; static int hf_hip_tlv_enc_reserved; static int hf_hip_tlv_locator_traffic_type; static int hf_hip_tlv_locator_type; static int hf_hip_tlv_locator_len; static int hf_hip_tlv_locator_reserved; static int hf_hip_tlv_locator_lifetime; static int hf_hip_tlv_locator_port; static int hf_hip_tlv_locator_transport_protocol; static int hf_hip_tlv_locator_kind; static int hf_hip_tlv_locator_priority; static int hf_hip_tlv_locator_spi; static int hf_hip_tlv_locator_address; static int hf_hip_tlv_cert_group; static int hf_hip_tlv_cert_count; static int hf_hip_tlv_cert_id; static int hf_hip_tlv_cert_type; static int hf_hip_tlv_certificate; static int hf_hip_tlv_from_address; static int hf_hip_tlv_rvs_address; static int hf_hip_tlv_nat_traversal_mode_id; static int hf_hip_tlv_transaction_minta; static int hf_hip_tlv_relay_from_port; static int hf_hip_tlv_relay_from_protocol; static int hf_hip_tlv_relay_from_reserved; static int hf_hip_tlv_relay_from_address; static int hf_hip_tlv_relay_to_port; static int hf_hip_tlv_relay_to_protocol; static int hf_hip_tlv_relay_to_reserved; static int hf_hip_tlv_relay_to_address; static int hf_hip_tlv_reg_from_port; static int hf_hip_tlv_reg_from_protocol; static int hf_hip_tlv_reg_from_reserved; static int hf_hip_tlv_reg_from_address; static int hf_hip_encrypted_parameter_data; static int hf_hip_fqdn; static int hf_hip_nai; static gint ett_hip; static gint ett_hip_controls; static gint ett_hip_tlv; static gint ett_hip_tlv_data; static gint ett_hip_tlv_host_id_hdr; static gint ett_hip_locator_data; static expert_field ei_hip_tlv_host_id_len; /* static expert_field ei_hip_tlv_host_id_e_len; */ static expert_field ei_hip_tlv_host_id_hdr_alg; static expert_field ei_hip_checksum; /* Dissect the HIP packet */ static void dissect_hip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean udp) { proto_tree *hip_tree, *hip_tlv_tree=NULL; proto_item *ti, *ti_tlv; int length, offset = 0, newoffset = 0; guint16 control_h, checksum_h; guint16 tlv_type_h, tlv_length_h; /* For storing in host order */ guint len; guint reported_len; vec_t cksum_vec[4]; guint32 phdr[2]; /* Payload format RFC 5201 section 5.1 */ /* hiph_proto; */ /* payload protocol */ guint8 hiph_hdr_len; /* header length */ guint8 hiph_shim6_fixed_bit_s; /* This is always 0 */ guint8 hiph_packet_type; /* packet type */ guint8 hiph_res_ver, hiph_version, hiph_reserved; /* byte for reserved and version */ guint8 hiph_shim6_fixed_bit_p; /* This is always 1 */ /* checksum_h */ /* checksum */ /* control_h */ /* control */ /* HIP parameters ... */ /* load the top pane info. This should be overwritten by the next protocol in the stack */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HIP"); col_clear(pinfo->cinfo, COL_INFO); newoffset = offset; /* hiph Proto */ newoffset++; hiph_hdr_len = tvb_get_guint8(tvb, newoffset); newoffset++; hiph_packet_type = tvb_get_guint8(tvb, newoffset); /* draft-ietf-shim6-proto-12 see section 5.3 */ hiph_shim6_fixed_bit_p = (hiph_packet_type & HIP_SHIM6_FIXED_BIT_P_MASK) >> 7; hiph_packet_type = hiph_packet_type & HIP_PACKET_TYPE_MASK; newoffset++; hiph_res_ver = tvb_get_guint8(tvb, newoffset); /* divide to reserved and version and shim6_fixed_bit_s draft-ietf-shim6-proto-12 see section 5.3 */ hiph_version = (hiph_res_ver & HIP_VERSION_MASK) >> 4; hiph_reserved = hiph_res_ver & HIP_RESERVED_MASK; hiph_shim6_fixed_bit_s = hiph_res_ver & HIP_SHIM6_FIXED_BIT_S_MASK; newoffset++; checksum_h = tvb_get_ntohs(tvb, newoffset); newoffset += 2; control_h = tvb_get_ntohs(tvb, newoffset); col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(hiph_packet_type, pinfo_vals, "Unknown")); /* populate a tree in the second pane with the status of the link layer (i.e. none) */ ti = proto_tree_add_item(tree, proto_hip, tvb, 0, -1, ENC_NA); hip_tree = proto_item_add_subtree(ti, ett_hip); proto_tree_add_item(hip_tree, hf_hip_proto, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(hip_tree, hf_hip_hdr_len, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_uint_format(hip_tree, hf_hip_shim6_fixed_bit_p, tvb, offset+2, 1, hiph_shim6_fixed_bit_p, "Fixed P-bit: %u (Always zero)", hiph_shim6_fixed_bit_p); proto_tree_add_uint(hip_tree, hf_hip_packet_type, tvb, offset+2, 1, hiph_packet_type); proto_tree_add_uint_format_value(hip_tree, hf_hip_version, tvb, offset+3, 1, hiph_version, "%u, Reserved: %u", hiph_version, hiph_reserved); proto_tree_add_uint_format(hip_tree, hf_hip_shim6_fixed_bit_s, tvb, offset+3, 1, hiph_shim6_fixed_bit_s, "Fixed S-bit: %u (%s)", hiph_shim6_fixed_bit_s, ((hiph_shim6_fixed_bit_s) ? "HIP" : "SHIM6")); /* Checksum - this is the same algorithm from UDP, ICMPv6 */ reported_len = tvb_reported_length(tvb); len = tvb_captured_length(tvb); if (!pinfo->fragmented && len >= reported_len) { /* IPv4 or IPv6 addresses */ SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len); SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len); /* the rest of the pseudo-header */ if (pinfo->src.type == AT_IPv6) { phdr[0] = reported_len; phdr[0] = g_htonl(phdr[0]); /* Note: g_htonl() macro may eval arg multiple times */ phdr[1] = g_htonl(IP_PROTO_HIP); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)&phdr, 8); } else { phdr[0] = (IP_PROTO_HIP<<16)+reported_len; phdr[0] = g_htonl(phdr[0]); /* Note: g_htonl() macro may eval arg multiple times */ SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)&phdr, 4); } /* pointer to the HIP header (packet data) */ SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, reported_len); if (checksum_h == 0 && udp) { proto_tree_add_checksum(hip_tree, tvb, offset+4, hf_hip_checksum, hf_hip_checksum_status, &ei_hip_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); } else { proto_tree_add_checksum(hip_tree, tvb, offset+4, hf_hip_checksum, hf_hip_checksum_status, &ei_hip_checksum, pinfo, in_cksum(cksum_vec, 4), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM); } } else { proto_tree_add_checksum(hip_tree, tvb, offset+4, hf_hip_checksum, hf_hip_checksum_status, &ei_hip_checksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); } ti = proto_tree_add_item(hip_tree, hf_hip_controls, tvb, offset+6, 2, ENC_BIG_ENDIAN); if (ti) { /* HIP Controls subtree */ ti = proto_item_add_subtree(ti, ett_hip_controls); proto_tree_add_boolean(ti, hf_hip_controls_anon, tvb, offset+7,1, control_h); } offset += 8; proto_tree_add_item(hip_tree, hf_hip_hit_sndr, tvb, offset, 16, ENC_NA); offset += 16; proto_tree_add_item(hip_tree, hf_hip_hit_rcvr, tvb, offset, 16, ENC_NA); offset += 16; length = (hiph_hdr_len + 1) * 8; /* Begin TLV parsing */ if (offset < length) { hip_tlv_tree = proto_tree_add_subtree(hip_tree, tvb, offset, -1, ett_hip_tlv, NULL, "HIP Parameters"); } /* Parse type and length in TLV */ while (offset < length) { tlv_type_h = tvb_get_ntohs(tvb, offset); tlv_length_h = tvb_get_ntohs(tvb, offset + 2); ti_tlv = proto_tree_add_uint_format(hip_tlv_tree, hf_hip_type, tvb, offset, 4 + tlv_length_h, tlv_type_h, "%s (type=%u, length=%u)", val_to_str_const(tlv_type_h, hip_param_vals, "Unknown"), tlv_type_h, tlv_length_h); /* Parse value */ dissect_hip_tlv(tvb, pinfo, offset, ti_tlv, tlv_type_h, tlv_length_h); offset += 11 + tlv_length_h - (tlv_length_h + 3) % 8; } } static int dissect_hip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { dissect_hip_common(tvb, pinfo, tree, FALSE); return tvb_captured_length(tvb); } static int dissect_hip_in_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { guint32 nullbytes; tvbuff_t *newtvb; if (tvb_captured_length(tvb) < 4) return 0; nullbytes = tvb_get_ntohl(tvb, 0); if (nullbytes != 0) return 0; newtvb = tvb_new_subset_remaining(tvb, 4); dissect_hip_common(newtvb, pinfo, tree, TRUE); return tvb_captured_length(tvb); } static int dissect_hip_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_item *ti, int type, int tlv_len) { proto_tree *t=NULL; proto_item *ti_tlv, *ti_loc, *hi_len_item, *e_len_item, *arg_item; guint8 n, algorithm, reg_type; guint16 trans, hi_len, di_len, di_type, e_len, pv_len; guint32 reserved, hi_hdr; guint8 transport_proto; guint8 locator_type; int newoffset, newlen, hi_t; /* move over the TLV */ newoffset = offset + 4; t = proto_item_add_subtree(ti, ett_hip_tlv_data); switch (type) { case PARAM_ESP_INFO: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_ei_res, tvb, newoffset, 2, ENC_BIG_ENDIAN); /* KEYMAT index */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_ei_keyidx, tvb, newoffset, 2, ENC_BIG_ENDIAN); /* OLD SPI */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_ei_oldspi, tvb, newoffset, 4, ENC_BIG_ENDIAN); /* NEW SPI */ newoffset += 4; proto_tree_add_item(t, hf_hip_tlv_ei_newspi, tvb, newoffset, 4, ENC_BIG_ENDIAN); break; case PARAM_R1_COUNTER: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_r1_res, tvb, newoffset, 4, ENC_BIG_ENDIAN); /* R1 generation counter */ newoffset += 4; proto_tree_add_item(t, hf_hip_tlv_r1count, tvb, newoffset, 8, ENC_NA); break; case PARAM_LOCATOR: /* RFC 5206 section 4. and RFC 5770 section 5.7. for type 2 locators */ tlv_len -= 4; /* loop through included locators */ while (tlv_len > 0) { /* Every locator to new tree node * Skip ahead and read the 0 or 1 type locator from 8 bytes * and type 2 locator from 20 bytes to be used as the top level * tree_item for this subtree */ locator_type = tvb_get_guint8(tvb, newoffset + 1); if (locator_type == 0) { ti_loc = proto_tree_add_item(t, hf_hip_tlv_locator_address, tvb, newoffset + 8, 16, ENC_NA); } else if (locator_type == 1) { ti_loc = proto_tree_add_item(t, hf_hip_tlv_locator_address, tvb, newoffset + 12, 16, ENC_NA); } else if (locator_type == 2) { ti_loc = proto_tree_add_item(t, hf_hip_tlv_locator_address, tvb, newoffset + 20, 16, ENC_NA); } else { /* unknown or malformed locator type jumping over it */ ti_loc = NULL; newoffset += (1 + tvb_get_guint8(tvb, newoffset + 2)); tlv_len -= (1 + tvb_get_guint8(tvb, newoffset + 2)); } if (locator_type <= 2) { ti_loc = proto_item_add_subtree(ti_loc, ett_hip_locator_data); /* Traffic type */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_traffic_type, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Locator type */ #if 0 locator_type = tvb_get_guint8(tvb, newoffset); #endif proto_tree_add_item(ti_loc, hf_hip_tlv_locator_type, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Locator length */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_len, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Reserved includes the Preferred bit */ reserved = tvb_get_guint8(tvb, newoffset); proto_tree_add_uint_format_value(ti_loc, hf_hip_tlv_locator_reserved, tvb, newoffset, 1, reserved, "0x%x %s", reserved, (reserved >> 31) ? "(Preferred)" : ""); newoffset++; /* Locator lifetime */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_lifetime, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; if (locator_type == 0) { /* Locator types 1 and 0 RFC 5206 section 4.2.*/ /* Locator */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_address, tvb, newoffset, 16, ENC_NA); newoffset += 16; tlv_len -= 24; } else if (locator_type == 1) { /* Locator types 1 and 0 RFC 5206 section 4.2.*/ /* SPI */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_spi, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; /* Locator */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_address, tvb, newoffset, 16, ENC_NA); newoffset += 16; tlv_len -= 28; } else if (locator_type == 2) { /* Locator type 2 RFC 5770 section 5.7. */ /* Tansport port */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_port, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Transport protocol */ transport_proto = tvb_get_guint8(tvb, newoffset); /* RFC 5770 section 5.6 */ proto_tree_add_uint_format(ti_loc, hf_hip_tlv_locator_transport_protocol, tvb, newoffset, 1, transport_proto, "Transport protocol: %d %s", transport_proto, (transport_proto == 17) ? "(UDP)" : ""); newoffset++; /* Kind */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_kind, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Priority */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_priority, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; /* SPI */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_spi, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; /* Locator */ proto_tree_add_item(ti_loc, hf_hip_tlv_locator_address, tvb, newoffset, 16, ENC_NA); newoffset += 16; tlv_len -= 36; } } } break; case PARAM_PUZZLE: /* K number of verified bits */ proto_tree_add_item(t, hf_hip_tlv_puzzle_k, tvb, newoffset, 1, ENC_BIG_ENDIAN); /* Puzzle lifetime */ newoffset++; proto_tree_add_item(t, hf_hip_tlv_puzzle_life, tvb, newoffset, 1, ENC_BIG_ENDIAN); /* Puzzle O*/ newoffset++; proto_tree_add_item(t, hf_hip_tlv_puzzle_o, tvb, newoffset, 2, ENC_BIG_ENDIAN); /* Puzzle I */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_puzzle_i, tvb,newoffset, tlv_len - 4, ENC_NA); break; case PARAM_SOLUTION: /* K number of verified bits */ proto_tree_add_item(t, hf_hip_tlv_solution_k, tvb, newoffset, 1, ENC_BIG_ENDIAN); /* Solution Reserved */ newoffset++; proto_tree_add_item(t, hf_hip_tlv_solution_reserved, tvb, newoffset, 1, ENC_BIG_ENDIAN); /* Solution Opaque */ newoffset++; proto_tree_add_item(t, hf_hip_tlv_solution_o, tvb,newoffset, 2, ENC_BIG_ENDIAN); /* Solution I */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_solution_i, tvb, newoffset, (tlv_len - 4)/2, ENC_NA); /* Solution J */ newoffset += (tlv_len - 4) /2; proto_tree_add_item(t, hf_hip_tlv_solution_j, tvb, newoffset, (tlv_len -4)/2, ENC_NA); break; case PARAM_SEQ: /* Update ID */ proto_tree_add_item(t, hf_hip_tlv_seq_updid, tvb, newoffset, 4, ENC_BIG_ENDIAN); break; case PARAM_ACK: /* Can contain multiple Update IDs from peer */ while (tlv_len > 0) { /* peer Update ID */ proto_tree_add_item(t, hf_hip_tlv_ack_updid, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; tlv_len -= 4; } break; case PARAM_DIFFIE_HELLMAN: n = tvb_get_guint8(tvb, newoffset); /* First Group ID*/ proto_tree_add_uint_format(t, hf_hip_tlv_dh_group_id, tvb, newoffset, 1, n, "%u (%s)", n, val_to_str_const(n, dh_group_id_vals, "Unknown")); /* First Public value len */ newoffset++; pv_len = tvb_get_ntohs(tvb, newoffset); proto_tree_add_item(t, hf_hip_tlv_dh_pv_length, tvb, newoffset, 2, ENC_BIG_ENDIAN); /* First Public value */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_dh_pub, tvb, newoffset, pv_len, ENC_NA); /* Check for the second group */ if ((pv_len + newoffset) < tlv_len) { /* Second Group ID*/ newoffset += pv_len; proto_tree_add_uint_format(t, hf_hip_tlv_dh_group_id, tvb, newoffset, 1, n, "%u (%s)", n, val_to_str_const(n, dh_group_id_vals, "Unknown")); /* Second Public value len */ newoffset += 1; pv_len = tvb_get_ntohs(tvb, newoffset); proto_tree_add_item(t, hf_hip_tlv_dh_pv_length, tvb, newoffset, 2, ENC_BIG_ENDIAN); /* Second Public Value */ newoffset += 2; proto_tree_add_item(t, hf_hip_tlv_dh_pub, tvb, newoffset, pv_len, ENC_NA); } break; case PARAM_ESP_TRANSFORM: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_esp_reserved, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset +=2; tlv_len -= 2; while (tlv_len > 0) { /* Suite # 1, 2, ..., n * two bytes per transform id */ trans = tvb_get_ntohs(tvb, newoffset); proto_tree_add_uint_format(t, hf_hip_tlv_trans_id, tvb, newoffset, 2, trans, "%u (%s)", trans, val_to_str_const(trans, transform_id_vals, "Unknown")); tlv_len -= 2; newoffset += 2; } break; case PARAM_HIP_TRANSFORM: while (tlv_len > 0) { /* Suite # 1, 2, ..., n two bytes per transform id */ trans = tvb_get_ntohs(tvb, newoffset); proto_tree_add_uint_format(t, hf_hip_tlv_trans_id, tvb, newoffset, 2, trans, "%u (%s)", trans, val_to_str_const(trans, transform_id_vals, "Unknown")); tlv_len -= 2; newoffset += 2; } break; case PARAM_NAT_TRAVERSAL_MODE: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_esp_reserved, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; tlv_len -= 2; while (tlv_len > 0) { /* Suite # 1, 2, ..., n two bytes per mode id */ trans = tvb_get_ntohs(tvb, newoffset); proto_tree_add_uint_format(t, hf_hip_tlv_nat_traversal_mode_id, tvb, newoffset, 2, trans, "%u (%s)", trans, val_to_str_const(trans, mode_id_vals, "Unknown")); tlv_len -= 2; newoffset += 2; } break; case PARAM_TRANSACTION_PACING: /* Min Ta */ proto_tree_add_item(t, hf_hip_tlv_transaction_minta, tvb, newoffset, 4, ENC_BIG_ENDIAN); break; case PARAM_ENCRYPTED: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_enc_reserved, tvb, newoffset, 4, ENC_BIG_ENDIAN); newoffset += 4; /* IV * 16 bytes IV for AES CBC RFC 3602 * 8 bytes IV for 3DES CBC RFC 2405 * 0 bytes IV for NULL * and * encrypted data after that. */ proto_tree_add_item(t, hf_hip_encrypted_parameter_data, tvb, newoffset, tlv_len - 4, ENC_NA); break; case PARAM_HIP_CIPHER: while (tlv_len > 0) { /* Suite # 1, 2, ..., n two bytes per Cipher Suite id */ proto_tree_add_item(t, hf_hip_tlv_cipher_id, tvb, newoffset, 2, ENC_BIG_ENDIAN); tlv_len -= 2; newoffset += 2; } break; case PARAM_HIT_SUITE_LIST: while (tlv_len > 0) { /* Suite # 1, 2, ..., n one byte per HIT Suite id. According to specification, HIT_SUITE_LIST is defined as eight-bit field, current four-bit HIT Suite-IDs only use the four higher order bits in the ID Field.*/ proto_tree_add_item(t, hf_hip_tlv_hit_suite_id, tvb, newoffset, 1, ENC_BIG_ENDIAN); tlv_len -= 1; newoffset += 1; } break; case PARAM_HOST_ID: hi_len = tvb_get_ntohs(tvb, newoffset); hi_len_item = proto_tree_add_item(t, hf_hip_tlv_host_id_len, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; di_len = tvb_get_ntohs(tvb, newoffset); di_type = (di_len >> 12) & 0x000F; /* get 4 bits for DI type */ di_len = di_len & 0x0FFF; /* 12 bits for DI length */ /* DI type */ proto_tree_add_item(t, hf_hip_tlv_host_di_type, tvb, newoffset, 1, ENC_BIG_ENDIAN); /* DI len */ proto_tree_add_item(t, hf_hip_tlv_host_di_len, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* hi_hdr - first 4 bytes are 0200ff03 (KEY RR in RFC 2535) * flags 2 octets * protocol 1 octet * algorithm 1 octet (DSA or RSA) * */ hi_hdr = tvb_get_ntohl(tvb, newoffset); ti_tlv = proto_tree_add_item(t, hf_hip_tlv_host_id_hdr, tvb, newoffset, 4, ENC_BIG_ENDIAN); ti_tlv = proto_item_add_subtree(ti_tlv, ett_hip_tlv_host_id_hdr); /* HDR Flags*/ proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_flags, tvb, newoffset, 2, hi_hdr); newoffset += 2; /* HDR Protocol */ proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_proto, tvb, newoffset, 1, hi_hdr); newoffset += 1; /* HDR Algorithm */ algorithm = tvb_get_guint8(tvb, newoffset); arg_item = proto_tree_add_uint(ti_tlv, hf_hip_tlv_host_id_hdr_alg, tvb, newoffset, 1, hi_hdr); switch (algorithm) { case HI_ALG_DSA: /* DSA KEY RR RFC 2536 * T 1 octet * Q 20 octets * P 64 + T*8 octets * G 64 + T*8 octets * Y 64 + T*8 octets */ newoffset++; /* 12 + offset */ /* T */ proto_tree_add_item(t, hf_hip_tlv_host_id_t, tvb, newoffset, 1, ENC_BIG_ENDIAN); hi_t = tvb_get_guint8(tvb, newoffset); newoffset++; /* Q */ proto_tree_add_item(t, hf_hip_tlv_host_id_q, tvb, newoffset, 20, ENC_NA); newoffset += 20; if (hi_t > 56) /* max 4096 bits */ break; /* P */ newlen = 64 + (hi_t * 8); proto_tree_add_item(t, hf_hip_tlv_host_id_p, tvb, newoffset, newlen, ENC_NA); /* G */ newoffset += newlen; proto_tree_add_item(t, hf_hip_tlv_host_id_g, tvb, newoffset, newlen, ENC_NA); /* Y */ newoffset += newlen; proto_tree_add_item(t, hf_hip_tlv_host_id_y, tvb, newoffset, newlen, ENC_NA); break; case HI_ALG_RSA: /* RSA KEY RR RFC 3110 * e_len 1 or 3 octets * e specified by e_len * n variable length public modulus */ newoffset++; /* 12 + offset */ /* E len */ e_len = tvb_get_guint8(tvb, newoffset); e_len_item = proto_tree_add_item(t, hf_hip_tlv_host_id_e_len, tvb, newoffset, (e_len > 255) ? 3 : 1, ENC_BIG_ENDIAN); newoffset++; hi_len -= 5; /* subtract RDATA + e_len */ if (e_len == 0) { /* e_len is 0 followed by 16-bit value */ e_len = tvb_get_ntohs(tvb, newoffset); newoffset += 2; hi_len -= 2; } if (e_len > 512) { /* per, RFC 3110 < 4096 bits */ expert_add_info(pinfo, e_len_item, &ei_hip_tlv_host_id_len); break; } /* e */ proto_tree_add_item(t, hf_hip_tlv_host_id_e, tvb, newoffset, e_len, ENC_NA); newoffset += e_len; hi_len -= e_len; if (hi_len > 512) { expert_add_info(pinfo, hi_len_item, &ei_hip_tlv_host_id_len); break; } /* RSA public modulus n */ proto_tree_add_item(t, hf_hip_tlv_host_id_n, tvb, newoffset, hi_len, ENC_NA); break; default: expert_add_info(pinfo, arg_item, &ei_hip_tlv_host_id_hdr_alg); break; } /* FQDN */ if (di_type == 0) break; if (di_type == 1) { /* RFC 1035 */ proto_tree_add_item(t, hf_hip_fqdn, tvb, offset+16+hi_len, di_len, ENC_ASCII); } else if (di_type == 2) { /* RFC 4282 */ proto_tree_add_item(t, hf_hip_nai, tvb, offset+16+hi_len, di_len, ENC_ASCII); } break; case PARAM_CERT: /* CERT */ /* Cert Group */ proto_tree_add_item(t, hf_hip_tlv_cert_group, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Cert Count */ proto_tree_add_item(t, hf_hip_tlv_cert_count, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Cert ID */ proto_tree_add_item(t, hf_hip_tlv_cert_id, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Cert Type */ proto_tree_add_item(t, hf_hip_tlv_cert_type, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Certificate */ proto_tree_add_item(t, hf_hip_tlv_certificate, tvb, newoffset, tlv_len-4, ENC_NA); break; case PARAM_NOTIFICATION: /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_notification_res, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Notification Message Type */ proto_tree_add_item(t, hf_hip_tlv_notification_type, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Notification Data */ proto_tree_add_item(t, hf_hip_tlv_notification_data, tvb, newoffset, tlv_len-4, ENC_NA); break; case PARAM_ECHO_REQUEST_SIGNED: case PARAM_ECHO_RESPONSE_SIGNED: case PARAM_ECHO_REQUEST_UNSIGNED: case PARAM_ECHO_RESPONSE_UNSIGNED: /* Variable length Opaque Data */ proto_tree_add_item(t, hf_hip_tlv_opaque_data, tvb, newoffset, tlv_len, ENC_NA); break; case PARAM_REG_INFO: case PARAM_REG_REQUEST: case PARAM_REG_RESPONSE: case PARAM_REG_FAILED: if (type == PARAM_REG_INFO) { /* Min Lifetime */ proto_tree_add_item(t, hf_hip_tlv_reg_ltmin, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; /* Max Lifetime */ proto_tree_add_item(t, hf_hip_tlv_reg_ltmax, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; tlv_len -= 2; } else if (type == PARAM_REG_FAILED) { /* Failure Type */ proto_tree_add_item(t, hf_hip_tlv_reg_failtype, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; tlv_len--; } else { /* Lifetime */ proto_tree_add_item(t, hf_hip_tlv_reg_lt, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset++; tlv_len--; } /* Reg Type 1 ... n, Padding */ while (tlv_len > 0) { reg_type = tvb_get_guint8(tvb, newoffset); proto_tree_add_uint_format(t, hf_hip_tlv_reg_type, tvb, newoffset, 1, reg_type, "%u (%s)", reg_type, val_to_str_const(reg_type, reg_type_vals, "Unknown")); /* one byte per registration type */ tlv_len--; newoffset++; } break; case PARAM_HMAC: case PARAM_HMAC_2: case PARAM_RVS_HMAC: case PARAM_RELAY_HMAC: /* HMAC */ proto_tree_add_item(t, hf_hip_tlv_hmac, tvb, offset+4, tlv_len, ENC_NA); break; case PARAM_HIP_SIGNATURE: case PARAM_HIP_SIGNATURE_2: /* Signature algorithm */ n = tvb_get_guint8(tvb, offset+4); proto_tree_add_uint_format(t, hf_hip_tlv_sig_alg, tvb, newoffset, 1, n, "%u (%s)", n, val_to_str_const(n, sig_alg_vals, "Unknown")); newoffset++; /* Signature */ proto_tree_add_item(t, hf_hip_tlv_sig, tvb, newoffset, tlv_len-1, ENC_NA); break; case PARAM_FROM: /* Address */ proto_tree_add_item(t, hf_hip_tlv_from_address, tvb, newoffset, 16, ENC_NA); break; case PARAM_VIA_RVS: /* RVS Addresses */ while (tlv_len > 0) { proto_tree_add_item(t, hf_hip_tlv_rvs_address, tvb, newoffset, 16, ENC_NA); tlv_len -= 16; newoffset += 16; } break; case PARAM_RELAY_FROM: /* Port */ proto_tree_add_item(t, hf_hip_tlv_relay_from_port, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Protocol */ proto_tree_add_item(t, hf_hip_tlv_relay_from_protocol, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_relay_from_reserved, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Address */ proto_tree_add_item(t, hf_hip_tlv_relay_from_address, tvb, newoffset, 16, ENC_NA); break; case PARAM_RELAY_TO: /* Port */ proto_tree_add_item(t, hf_hip_tlv_relay_to_port, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Protocol */ proto_tree_add_item(t, hf_hip_tlv_relay_to_protocol, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_relay_to_reserved, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Address */ proto_tree_add_item(t, hf_hip_tlv_relay_to_address, tvb, newoffset, 16, ENC_NA); break; case PARAM_REG_FROM: /* Port */ proto_tree_add_item(t, hf_hip_tlv_reg_from_port, tvb, newoffset, 2, ENC_BIG_ENDIAN); newoffset += 2; /* Protocol */ proto_tree_add_item(t, hf_hip_tlv_reg_from_protocol, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Reserved */ proto_tree_add_item(t, hf_hip_tlv_reg_from_reserved, tvb, newoffset, 1, ENC_BIG_ENDIAN); newoffset += 1; /* Address */ proto_tree_add_item(t, hf_hip_tlv_reg_from_address, tvb, newoffset, 16, ENC_NA); break; default: break; } return (0); } void proto_register_hip(void) { static hf_register_info hf[] = { { &hf_hip_proto, { "Payload Protocol", "hip.proto", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_hdr_len, { "Header Length", "hip.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_packet_type, { "Packet Type", "hip.packet_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_shim6_fixed_bit_p, { "Header fixed bit P", "hip.shim6_fixed_p", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_version, { "Version", "hip.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_shim6_fixed_bit_s, { "Header fixed bit S", "hip.shim6_fixed_s", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_controls, { "HIP Controls", "hip.controls", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_controls_anon, { "Anonymous (Sender's HI is anonymous)", "hip.controls.a", FT_BOOLEAN, 16, NULL, HIP_CONTROL_A_MASK, NULL, HFILL }}, { &hf_hip_checksum, { "Checksum", "hip.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_checksum_status, { "Checksum Status", "hip.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }}, { &hf_hip_hit_sndr, { "Sender's HIT", "hip.hit_sndr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_hit_rcvr, { "Receiver's HIT", "hip.hit_rcvr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_type, { "Type", "hip.type", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_r1_res, { "Reserved", "hip.tlv.r1_reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_r1count, { "R1 Counter", "hip.tlv.r1_counter", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_puzzle_k, { "Difficulty (K)", "hip.tlv_puzzle_k", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_puzzle_life, { "Lifetime", "hip.tlv_puzzle_lifetime", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_puzzle_o, { "Opaque Data", "hip.tlv_puzzle_opaque", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_puzzle_i, { "Random number (I)", "hip.tlv.puzzle_random_i", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_solution_k, { "Difficulty (K)", "hip.tlv_solution_k", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_solution_reserved, { "Reserved", "hip.tlv_solution_reserved", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_solution_o, { "Opaque Data", "hip.tlv_solution_opaque", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_solution_i, { "Random number (I)", "hip.tlv.solution_random_i", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_solution_j, { "Solution (J)", "hip.tlv_solution_j", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_ei_res, { "Reserved", "hip.tlv_esp_info_reserved", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_ei_keyidx, { "Keymaterial Index", "hip.tlv_esp_info_key_index", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_ei_oldspi, { "Old SPI", "hip.tlv_esp_info_old_spi", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_ei_newspi, { "New SPI", "hip.tlv_esp_info_new_spi", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_seq_updid, { "Seq Update ID", "hip.tlv_seq_update_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_ack_updid, { "ACKed Peer Update ID", "hip.tlv_ack_updid", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_dh_group_id, { "Group ID", "hip.tlv.dh_group_id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_dh_pv_length, { "Public Value Length", "hip.tlv.dh_pv_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_dh_pub, { "Public Value", "hip.tlv.dh_public_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_trans_id, { "Transform ID", "hip.tlv.trans_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_esp_reserved, { "Reserved", "hip.tlv.esp_trans_res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_cipher_id, { "Cipher ID", "hip.tlv.cipher_id", FT_UINT16, BASE_DEC, VALS(cipher_vals), 0x0, NULL, HFILL }}, { &hf_hip_tlv_hit_suite_id, { "HIT Suite ID", "hip.tlv.hit_suite_id", FT_UINT8, BASE_DEC, VALS(hit_suite_vals), 0xF0, NULL, HFILL }}, { &hf_hip_tlv_host_id_len, { "Host Identity Length", "hip.tlv.host_id_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_di_type, { "Domain Identifier Type", "hip.tlv.host_domain_id_type", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL }}, { &hf_hip_tlv_host_di_len, { "Domain Identifier Length", "hip.tlv.host_domain_id_length", FT_UINT16, BASE_DEC, NULL, 0x0FFF, NULL, HFILL }}, { &hf_hip_tlv_host_id_hdr, { "Host Identity flags", "hip.tlv.host_id_hdr", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_hdr_flags, { "Host Identity Header Flags", "hip.tlv.host_id_header_flags", FT_UINT32, BASE_HEX, VALS(hi_hdr_flags_vals), HI_HDR_FLAGS_MASK, NULL, HFILL }}, { &hf_hip_tlv_host_id_hdr_proto, { "Host Identity Header Protocol", "hip.tlv.host_id_header_proto", FT_UINT32, BASE_HEX, VALS(hi_hdr_proto_vals), HI_HDR_PROTO_MASK, NULL, HFILL }}, { &hf_hip_tlv_host_id_hdr_alg, { "Host Identity Header Algorithm", "hip.tlv.host_id_header_algo", FT_UINT32, BASE_HEX, VALS(hi_hdr_alg_vals), HI_HDR_ALG_MASK, NULL, HFILL }}, { &hf_hip_tlv_host_id_t, { "Host Identity T", "hip.tlv.host_identity_t", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_q, { "Host Identity Q", "hip.tlv.host_identity_q", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_p, { "Host Identity P", "hip.tlv.host_id_p", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_g, { "Host Identity G", "hip.tlv.host_id_g", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_y, { "Host Identity Y (public value)", "hip.tlv.host_id_y", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_e_len, { "RSA Host Identity exponent length (e_len)", "hip.tlv.host_id_e_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_e, { "RSA Host Identity exponent (e)", "hip.tlv.host_id_e", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_host_id_n, { "RSA Host Identity public modulus (n)", "hip.tlv.host_id_n", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_notification_res, { "Notification Reserved", "hip.tlv.notification_res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_notification_type, { "Notification Message Type", "hip.tlv.notification_type", FT_UINT16, BASE_DEC, VALS(notification_vals), 0x0, NULL, HFILL }}, { &hf_hip_tlv_notification_data, { "Notification Data", "hip.tlv.notification_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_opaque_data, { "Opaque Data", "hip.tlv.opaque_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_ltmin, { "Minimum Registration Lifetime", "hip.tlv.reg_ltmin", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_ltmax, { "Maximum Registration Lifetime", "hip.tlv.reg_ltmax", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_lt, { "Registration Lifetime", "hip.tlv.reg_lt", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_type, { "Registration Type", "hip.tlv.reg_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_failtype, { "Registration Failure Type", "hip.tlv.reg_failtype", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_hmac, { "HMAC", "hip.tlv.hmac", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_sig_alg, { "Signature Algorithm", "hip.tlv.sig_alg", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_sig, { "Signature", "hip.tlv.sig", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_enc_reserved, { "Reserved", "hip.tlv.enc_reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_traffic_type, { "Traffic Type", "hip.tlv.locator_traffic_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_type, { "Locator Type", "hip.tlv.locator_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_len, { "Locator Length", "hip.tlv.locator_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_reserved, { "Reserved", "hip.tlv.locator_reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_lifetime, { "Locator Lifetime", "hip.tlv.locator_lifetime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_port, { "Locator port", "hip.tlv.locator_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_transport_protocol, { "Locator transport protocol", "hip.tlv.locator_transport_protocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_kind, { "Locator kind", "hip.tlv.locator_kind", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_priority, { "Locator priority", "hip.tlv.locator_priority", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_spi, { "Locator SPI", "hip.tlv.locator_spi", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_locator_address, { "Locator", "hip.tlv.locator_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_cert_group, { "Cert group", "hip.tlv.cert_group", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_cert_count, { "Cert count", "hip.tlv.cert_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_cert_id, { "Cert ID", "hip.tlv.cert_id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_cert_type, { "Cert type", "hip.tlv.cert_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_certificate, { "Certificate", "hip.tlv.certificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_nat_traversal_mode_id, { "NAT Traversal Mode ID", "hip.tlv.nat_traversal_mode_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_from_port, { "Relay From Port", "hip.tlv.relay_from_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_to_port, { "Relay To Port", "hip.tlv.relay_to_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_from_port, { "Port", "hip.tlv.reg_from_port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_transaction_minta, { "Min Ta", "hip.tlv_transaction_minta", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_from_address, { "Address", "hip.tlv_from_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_rvs_address, { "RVS Address", "hip.tlv_rvs_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_from_protocol, { "Protocol", "hip.tlv_relay_from_protocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_from_reserved, { "Reserved", "hip.tlv_relay_from_reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_from_address, { "Address", "hip.tlv_relay_from_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_to_protocol, { "Protocol", "hip.tlv_relay_to_protocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_to_reserved, { "Reserved", "hip.tlv_relay_to_reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_relay_to_address, { "Address", "hip.tlv_relay_to_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_from_protocol, { "Protocol", "hip.tlv_reg_from_protocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_from_reserved, { "Reserved", "hip.tlv_reg_from_reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_hip_tlv_reg_from_address, { "Address", "hip.tlv_reg_from_address", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_encrypted_parameter_data, { "Encrypted Parameter Data", "hip.encrypted_parameter_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_fqdn, { "FQDN", "hip.fqdn", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_hip_nai, { "NAI", "hip.nai", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, }; static gint *ett[] = { &ett_hip, &ett_hip_controls, &ett_hip_tlv, &ett_hip_tlv_data, &ett_hip_tlv_host_id_hdr, &ett_hip_locator_data, }; static ei_register_info ei[] = { { &ei_hip_tlv_host_id_len, { "hip.tlv.host_id_length.invalid", PI_PROTOCOL, PI_WARN, "Invalid HI length", EXPFILL }}, #if 0 { &ei_hip_tlv_host_id_e_len, { "hip.tlv.host_id_e_length.invalid", PI_PROTOCOL, PI_WARN, "e_len too large", EXPFILL }}, #endif { &ei_hip_tlv_host_id_hdr_alg, { "hip.tlv.host_id_header_algo.invalid", PI_PROTOCOL, PI_WARN, "Unknown algorithm type", EXPFILL }}, { &ei_hip_checksum, { "hip.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, }; expert_module_t* expert_hip; proto_hip = proto_register_protocol("Host Identity Protocol", "HIP", "hip"); hip_ip_handle = register_dissector("hip", dissect_hip, proto_hip); hip_udp_handle = register_dissector("hip_udp", dissect_hip_in_udp, proto_hip); proto_register_field_array(proto_hip, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_hip = expert_register_protocol(proto_hip); expert_register_field_array(expert_hip, ei, array_length(ei)); } void proto_reg_handoff_hip(void) { dissector_add_uint("ip.proto", IP_PROTO_HIP, hip_ip_handle); dissector_add_uint_with_preference("udp.port", HIP_UDP_PORT, hip_udp_handle); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=8 tabstop=8 expandtab: * :indentSize=8:tabSize=8:noTabs=true: */