summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-zrtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-zrtp.c')
-rw-r--r--epan/dissectors/packet-zrtp.c1147
1 files changed, 1147 insertions, 0 deletions
diff --git a/epan/dissectors/packet-zrtp.c b/epan/dissectors/packet-zrtp.c
new file mode 100644
index 00000000..59a89b24
--- /dev/null
+++ b/epan/dissectors/packet-zrtp.c
@@ -0,0 +1,1147 @@
+/* packet-zrtp.c
+ * Routines for zrtp packet dissection
+ * IETF draft draft-zimmermann-avt-zrtp-22
+ * RFC 6189
+ * Copyright 2007, Sagar Pai <sagar@gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-pop.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/crc32-tvb.h>
+#include <wsutil/crc32.h>
+#include "packet-rtp.h"
+#include "packet-rtcp.h"
+
+void proto_reg_handoff_zrtp(void);
+void proto_register_zrtp(void);
+
+/*
+ RTP header
+*/
+static int proto_zrtp = -1;
+static int hf_zrtp_rtpversion = -1;
+static int hf_zrtp_rtppadding = -1;
+static int hf_zrtp_rtpextension = -1;
+/* static int hf_zrtp_id = -1; */
+static int hf_zrtp_sequence = -1;
+static int hf_zrtp_cookie = -1;
+static int hf_zrtp_source_id = -1;
+
+/*
+ ZRTP header
+*/
+static int hf_zrtp_signature = -1;
+static int hf_zrtp_msg_length = -1;
+static int hf_zrtp_msg_type = -1;
+static int hf_zrtp_msg_version = -1;
+
+/*
+ Hello Data
+*/
+static int hf_zrtp_msg_client_id = -1;
+static int hf_zrtp_msg_zid = -1;
+static int hf_zrtp_msg_sigcap = -1;
+static int hf_zrtp_msg_mitm = -1;
+static int hf_zrtp_msg_passive = -1;
+static int hf_zrtp_msg_hash_count = -1;
+static int hf_zrtp_msg_cipher_count = -1;
+static int hf_zrtp_msg_authtag_count = -1;
+static int hf_zrtp_msg_key_count = -1;
+static int hf_zrtp_msg_sas_count = -1;
+static int hf_zrtp_msg_hash = -1;
+static int hf_zrtp_msg_cipher = -1;
+static int hf_zrtp_msg_at = -1;
+static int hf_zrtp_msg_keya = -1;
+static int hf_zrtp_msg_sas = -1;
+static int hf_zrtp_msg_hash_image = -1;
+
+/*
+ Commit Data
+*/
+static int hf_zrtp_msg_hvi = -1;
+static int hf_zrtp_msg_nonce = -1;
+static int hf_zrtp_msg_key_id = -1;
+
+/*
+ DHParts Data
+*/
+static int hf_zrtp_msg_rs1ID = -1;
+static int hf_zrtp_msg_rs2ID = -1;
+static int hf_zrtp_msg_auxs = -1;
+static int hf_zrtp_msg_pbxs = -1;
+
+/*
+ Confirm Data
+*/
+static int hf_zrtp_msg_hmac = -1;
+static int hf_zrtp_msg_cfb = -1;
+
+/*
+ Error Data
+*/
+static int hf_zrtp_msg_error = -1;
+
+/*
+ Ping Data
+*/
+static int hf_zrtp_msg_ping_version = -1;
+static int hf_zrtp_msg_ping_endpointhash = -1;
+static int hf_zrtp_msg_pingack_endpointhash = -1;
+static int hf_zrtp_msg_ping_ssrc = -1;
+
+/*
+ Checksum Data
+*/
+static int hf_zrtp_checksum = -1;
+static int hf_zrtp_checksum_status = -1;
+
+/*
+ Sub-Tree
+*/
+static gint ett_zrtp = -1;
+static gint ett_zrtp_msg = -1;
+static gint ett_zrtp_msg_data = -1;
+
+static gint ett_zrtp_msg_hc = -1;
+static gint ett_zrtp_msg_kc = -1;
+static gint ett_zrtp_msg_ac = -1;
+static gint ett_zrtp_msg_cc = -1;
+static gint ett_zrtp_msg_sc = -1;
+
+static gint ett_zrtp_checksum = -1;
+
+
+static expert_field ei_zrtp_checksum = EI_INIT;
+
+static dissector_handle_t zrtp_handle;
+
+
+/*
+ Definitions
+*/
+#define ZRTP_ERR_10 0x10
+#define ZRTP_ERR_20 0x20
+#define ZRTP_ERR_30 0x30
+#define ZRTP_ERR_40 0x40
+#define ZRTP_ERR_51 0x51
+#define ZRTP_ERR_52 0x52
+#define ZRTP_ERR_53 0x53
+#define ZRTP_ERR_54 0x54
+#define ZRTP_ERR_55 0x55
+#define ZRTP_ERR_56 0x56
+#define ZRTP_ERR_61 0x61
+#define ZRTP_ERR_62 0x62
+#define ZRTP_ERR_63 0x63
+#define ZRTP_ERR_70 0x70
+#define ZRTP_ERR_80 0x80
+#define ZRTP_ERR_90 0x90
+#define ZRTP_ERR_91 0x91
+#define ZRTP_ERR_A0 0xA0
+#define ZRTP_ERR_B0 0xB0
+#define ZRTP_ERR_100 0x100
+
+/*
+ Text for Display
+*/
+typedef struct _value_zrtp_versions {
+ const gchar *version;
+} value_zrtp_versions;
+
+
+typedef struct _value_string_keyval {
+ const gchar *key;
+ const gchar *val;
+} value_string_keyval;
+
+
+static const value_zrtp_versions valid_zrtp_versions[] =
+ {
+ {"1.1x"},
+ {"1.0x"},
+ {"0.95"},
+ {"0.90"},
+ {"0.85"},
+ {NULL}
+ };
+
+static const value_string_keyval zrtp_hash_type_vals[] =
+ {
+ { "S256", "SHA-256 Hash"},
+ { "S384", "SHA-384 Hash"},
+ { "N256", "SHA-3 256-bit hash"},
+ { "N384", "SHA-3 384 bit hash"},
+ { NULL, NULL }
+ };
+
+static const value_string_keyval zrtp_cipher_type_vals[] =
+ {
+ { "AES1", "AES-CM with 128 bit keys"},
+ { "AES2", "AES-CM with 192 bit keys"},
+ { "AES3", "AES-CM with 256 bit keys"},
+ { "2FS1", "TwoFish with 128 bit keys"},
+ { "2FS2", "TwoFish with 192 bit keys"},
+ { "2FS3", "TwoFish with 256 bit keys"},
+ { "CAM1", "Camellia with 128 bit keys"},
+ { "CAM2", "Camellia with 192 bit keys"},
+ { "CAM3", "Camellia with 256 bit keys"},
+ { NULL, NULL }
+ };
+
+static const value_string_keyval zrtp_auth_tag_vals[] =
+ {
+ { "HS32", "HMAC-SHA1 32 bit authentication tag"},
+ { "HS80", "HMAC-SHA1 80 bit authentication tag"},
+ { "SK32", "Skein-512-MAC 32 bit authentication tag"},
+ { "SK64", "Skein-512-MAC 64 bit authentication tag"},
+ { NULL, NULL }
+ };
+
+static const value_string_keyval zrtp_sas_type_vals[] =
+ {
+ { "B32 ", "Short authentication string using base 32"},
+ { "B256", "Short authentication string using base 256"},
+ { NULL, NULL }
+ };
+
+static const value_string_keyval zrtp_key_agreement_vals[] =
+ {
+ { "DH2k", "DH mode with p=2048 bit prime"},
+ { "DH3k", "DH mode with p=3072 bit prime"},
+ { "DH4k", "DH mode with p=4096 bit prime"},
+ { "Prsh", "Preshared non-DH mode using shared secret"},
+ { "EC25", "Elliptic Curve DH-256"},
+ { "EC38", "Elliptic Curve DH-384"},
+ { "EC52", "Elliptic Curve DH-521"},
+ { "Mult", "Multistream mode"},
+ { NULL, NULL }
+ };
+
+static const value_string zrtp_error_vals[] =
+ {
+ { ZRTP_ERR_10, "Malformed Packet (CRC OK but wrong structure)"},
+ { ZRTP_ERR_20, "Critical Software Error"},
+ { ZRTP_ERR_30, "Unsupported ZRTP version"},
+ { ZRTP_ERR_40, "Hello Components mismatch"},
+ { ZRTP_ERR_51, "Hash type unsupported"},
+ { ZRTP_ERR_52, "Cipher type not supported"},
+ { ZRTP_ERR_53, "Public key exchange not supported"},
+ { ZRTP_ERR_54, "SRTP auth. tag not supported"},
+ { ZRTP_ERR_55, "SAS scheme not supported"},
+ { ZRTP_ERR_56, "No shared secret available, DH mode required"},
+ { ZRTP_ERR_61, "DH Error: bad pv for initiator/responder value is (1,0,p-1)"},
+ { ZRTP_ERR_62, "DH Error: bad hash commitment (hvi != hashed data)"},
+ { ZRTP_ERR_63, "Received relayed SAS from untrusted MiTM"},
+ { ZRTP_ERR_70, "Auth. Error Bad Confirm Packet HMAC"},
+ { ZRTP_ERR_80, "Nonce is reused"},
+ { ZRTP_ERR_90, "Equal ZID's in Hello"},
+ { ZRTP_ERR_91, "SSRC collision"},
+ { ZRTP_ERR_A0, "Service unavailable"},
+ { ZRTP_ERR_B0, "Protocol timeout error"},
+ { ZRTP_ERR_100, "GoClear packet received, but not allowed"},
+ { 0, NULL}
+ };
+
+static void
+dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_ErrorACK(packet_info *pinfo);
+static void
+dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_ClearACK( packet_info *pinfo);
+static void
+dissect_Conf2ACK(packet_info *pinfo);
+static void
+dissect_HelloACK( packet_info *pinfo);
+static void
+dissect_GoClear(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree, int part);
+static void
+dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree, int part);
+static void
+dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_RelayACK(packet_info *pinfo);
+static void
+dissect_Ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+static void
+dissect_PingACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree);
+
+
+static const gchar *
+key_to_val(const gchar *key, int keylen, const value_string_keyval *kv, const gchar *fmt) {
+ int i = 0;
+ while (kv[i].key) {
+ if (!strncmp(kv[i].key, key, keylen)) {
+ return(kv[i].val);
+ }
+ i++;
+ }
+ return wmem_strdup_printf(wmem_packet_scope(), fmt, key);
+}
+
+static const gchar *
+check_valid_version(const gchar *version) {
+ int i = 0;
+ int match_size = (version[0] == '0') ? 4 : 3;
+ while (valid_zrtp_versions[i].version) {
+ if (!strncmp(valid_zrtp_versions[i].version, version, match_size)) {
+ return(valid_zrtp_versions[i].version);
+ }
+ i++;
+ }
+ return NULL;
+}
+
+
+static int
+dissect_zrtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *zrtp_tree;
+ proto_tree *zrtp_msg_tree;
+ proto_tree *zrtp_msg_data_tree;
+ proto_item *ti;
+ int linelen;
+ int checksum_offset;
+ unsigned char message_type[9];
+ unsigned int prime_offset = 0;
+ unsigned int msg_offset = 12;
+ guint32 calc_crc;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZRTP");
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown ZRTP Packet");
+
+ ti = proto_tree_add_protocol_format(tree, proto_zrtp, tvb, 0, -1, "ZRTP protocol");
+ zrtp_tree = proto_item_add_subtree(ti, ett_zrtp);
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_rtpversion, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_rtppadding, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_rtpextension, tvb, prime_offset+0, 1, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_sequence, tvb, prime_offset+2, 2, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_cookie, tvb, prime_offset+4, 4, ENC_ASCII);
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_source_id, tvb, prime_offset+8, 4, ENC_BIG_ENDIAN);
+
+ linelen = tvb_reported_length_remaining(tvb, msg_offset);
+ checksum_offset = linelen-4;
+
+ ti = proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, msg_offset, linelen-4, "Message");
+ zrtp_msg_tree = proto_item_add_subtree(ti, ett_zrtp_msg);
+
+ proto_tree_add_item(zrtp_msg_tree, hf_zrtp_signature, tvb, msg_offset+0, 2, ENC_BIG_ENDIAN);
+
+ proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_length, tvb, msg_offset+2, 2, ENC_BIG_ENDIAN);
+
+ tvb_memcpy(tvb, (void *)message_type, msg_offset+4, 8);
+ message_type[8] = '\0';
+ proto_tree_add_item(zrtp_msg_tree, hf_zrtp_msg_type, tvb, msg_offset+4, 8, ENC_ASCII);
+
+ linelen = tvb_reported_length_remaining(tvb, msg_offset+12);
+
+ if (!strncmp(message_type, "Hello ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Hello(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "HelloACK", 8)) {
+ dissect_HelloACK(pinfo);
+ } else if (!strncmp(message_type, "Commit ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Commit(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "DHPart1 ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 1);
+ } else if (!strncmp(message_type, "DHPart2 ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_DHPart(tvb, pinfo, zrtp_msg_data_tree, 2);
+ } else if (!strncmp(message_type, "Confirm1", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 1);
+ } else if (!strncmp(message_type, "Confirm2", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Confirm(tvb, pinfo, zrtp_msg_data_tree, 2);
+ } else if (!strncmp(message_type, "Conf2ACK", 8)) {
+ dissect_Conf2ACK(pinfo);
+ } else if (!strncmp(message_type, "Error ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Error(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "ErrorACK", 8)) {
+ dissect_ErrorACK(pinfo);
+ } else if (!strncmp(message_type, "GoClear ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_GoClear(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "ClearACK", 8)) {
+ dissect_ClearACK(pinfo);
+ } else if (!strncmp(message_type, "SASrelay", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_SASrelay(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "RelayACK", 8)) {
+ dissect_RelayACK(pinfo);
+ } else if (!strncmp(message_type, "Ping ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_Ping(tvb, pinfo, zrtp_msg_data_tree);
+ } else if (!strncmp(message_type, "PingACK ", 8)) {
+ ti = proto_tree_add_protocol_format(zrtp_msg_tree, proto_zrtp, tvb, msg_offset+12, linelen-4, "Data");
+ zrtp_msg_data_tree = proto_item_add_subtree(ti, ett_zrtp_msg_data);
+ dissect_PingACK(tvb, pinfo, zrtp_msg_data_tree);
+ }
+
+ calc_crc = ~crc32c_tvb_offset_calculate(tvb, 0, msg_offset+checksum_offset, CRC32C_PRELOAD);
+
+ proto_tree_add_checksum(zrtp_tree, tvb, msg_offset+checksum_offset, hf_zrtp_checksum, hf_zrtp_checksum_status, &ei_zrtp_checksum, pinfo, calc_crc,
+ ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
+ return tvb_captured_length(tvb);
+}
+
+static void
+dissect_ErrorACK(packet_info *pinfo) {
+ col_set_str(pinfo->cinfo, COL_INFO, "ErrorACK Packet");
+}
+
+static void
+dissect_ClearACK(packet_info *pinfo) {
+ col_set_str(pinfo->cinfo, COL_INFO, "ClearACK Packet");
+}
+
+static void
+dissect_RelayACK(packet_info *pinfo) {
+ col_set_str(pinfo->cinfo, COL_INFO, "RelayACK Packet");
+}
+
+static void
+dissect_Conf2ACK(packet_info *pinfo) {
+
+ /* Signals start of SRT(C)P streams */
+ struct srtp_info *dummy_srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
+
+ dummy_srtp_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
+ dummy_srtp_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
+ dummy_srtp_info->mki_len = 0;
+ dummy_srtp_info->auth_tag_len = 4;
+
+ srtp_add_address(pinfo, PT_UDP, &pinfo->net_src, pinfo->srcport, pinfo->destport,
+ "ZRTP", pinfo->num, RTP_MEDIA_AUDIO, NULL, dummy_srtp_info, NULL);
+
+ srtp_add_address(pinfo, PT_UDP, &pinfo->net_dst, pinfo->destport, pinfo->srcport,
+ "ZRTP", pinfo->num, RTP_MEDIA_AUDIO, NULL, dummy_srtp_info, NULL);
+
+ srtcp_add_address(pinfo, &pinfo->net_src, pinfo->srcport+1, pinfo->destport+1,
+ "ZRTP", pinfo->num, dummy_srtp_info);
+
+ srtcp_add_address(pinfo, &pinfo->net_dst, pinfo->destport+1, pinfo->srcport+1,
+ "ZRTP", pinfo->num, dummy_srtp_info);
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Conf2ACK Packet");
+}
+
+static void
+dissect_HelloACK(packet_info *pinfo) {
+ col_set_str(pinfo->cinfo, COL_INFO, "HelloACK Packet");
+}
+
+static void
+dissect_Ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int data_offset = 24;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Ping Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_ping_version, tvb, data_offset, 4, ENC_ASCII);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_ping_endpointhash, tvb, data_offset+4, 8, ENC_BIG_ENDIAN);
+}
+
+static void
+dissect_PingACK(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int data_offset = 24;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "PingACK Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_ping_version, tvb, data_offset, 4, ENC_ASCII);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_pingack_endpointhash, tvb, data_offset+4, 8, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_ping_endpointhash, tvb, data_offset+12, 8, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_ping_ssrc, tvb, data_offset+20, 4, ENC_BIG_ENDIAN);
+}
+
+static void
+dissect_GoClear(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int data_offset = 24;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "GoClear Packet");
+
+ /* Now we should clear the SRT(C)P session... */
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, data_offset+0, 8, ENC_NA);
+}
+
+static void
+dissect_Error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int data_offset = 24;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Error Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_error, tvb, data_offset, 4, ENC_BIG_ENDIAN);
+}
+
+static void
+dissect_Confirm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree, int part) {
+ unsigned int data_offset = 24;
+ int linelen;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "Confirm1 Packet" : "Confirm2 Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, data_offset+0, 8, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_cfb, tvb, data_offset+8, 16, ENC_NA);
+ linelen = tvb_reported_length_remaining(tvb, data_offset+24);
+ proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, data_offset+24, linelen-4, "Encrypted Data");
+}
+
+static void
+dissect_SASrelay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int data_offset = 24;
+ int linelen;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "SASrelay Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, data_offset+0, 8, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_cfb, tvb, data_offset+8, 16, ENC_NA);
+ linelen = tvb_reported_length_remaining(tvb, data_offset+24);
+ proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, data_offset+24, linelen-4, "Encrypted Data");
+}
+
+static void
+dissect_DHPart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree, int part) {
+ unsigned int msg_offset = 12;
+ unsigned int data_offset = 56;
+ int linelen, pvr_len;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, (part == 1) ? "DHPart1 Packet" : "DHPart2 Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hash_image, tvb, msg_offset+12, 32, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_rs1ID, tvb, data_offset+0, 8, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_rs2ID, tvb, data_offset+8, 8, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_auxs, tvb, data_offset+16, 8, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_pbxs, tvb, data_offset+24, 8, ENC_NA);
+ linelen = tvb_reported_length_remaining(tvb, data_offset+32);
+ pvr_len = linelen-8-4;
+ proto_tree_add_protocol_format(zrtp_tree, proto_zrtp, tvb, data_offset+32, pvr_len, (part==1) ? "pvr Data" : "pvi Data");
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, data_offset+32+pvr_len, 8, ENC_NA);
+}
+
+static void
+dissect_Commit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ unsigned int msg_offset = 12;
+ unsigned int data_offset = 56;
+ gchar *value;
+ int key_type = 0;
+ /*
+ 0 - other type
+ 1 - "Mult"
+ 2 - "Prsh"
+ */
+ unsigned int offset;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Commit Packet");
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hash_image, tvb, msg_offset+12, 32, ENC_NA);
+ /* ZID */
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_zid, tvb, data_offset+0, 12, ENC_NA);
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset+12, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format_value(zrtp_tree, hf_zrtp_msg_hash, tvb, data_offset+12, 4, value,
+ "%s", key_to_val(value, 4, zrtp_hash_type_vals, "Unknown hash type %s"));
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset+16, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format_value(zrtp_tree, hf_zrtp_msg_cipher, tvb, data_offset+16, 4, value, "%s",
+ key_to_val(value, 4, zrtp_cipher_type_vals, "Unknown cipher type %s"));
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset+20, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(zrtp_tree, hf_zrtp_msg_at, tvb, data_offset+20, 4, value,
+ "Auth tag: %s", key_to_val(value, 4, zrtp_auth_tag_vals, "Unknown auth tag %s"));
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset+24, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format_value(zrtp_tree, hf_zrtp_msg_keya, tvb, data_offset+24, 4, value,
+ "%s", key_to_val(value, 4, zrtp_key_agreement_vals, "Unknown key agreement %s"));
+
+ if(!strncmp(value, "Mult", 4)) {
+ key_type = 1;
+ } else if (!strncmp(value, "Prsh", 4)) {
+ key_type = 2;
+ }
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, data_offset+28, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(zrtp_tree, hf_zrtp_msg_sas, tvb, data_offset+28, 4, value,
+ "SAS type: %s", key_to_val(value, 4, zrtp_sas_type_vals, "Unknown SAS type %s"));
+
+ switch (key_type) {
+ case 1: /*
+ Mult
+ */
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_nonce, tvb, data_offset+32, 16, ENC_NA);
+ offset = 48;
+ break;
+ case 2: /*
+ Prsh
+ */
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_nonce, tvb, data_offset+32, 16, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_key_id, tvb, data_offset+48, 8, ENC_NA);
+ offset = 56;
+ break;
+ default: /*
+ other
+ */
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hvi, tvb, data_offset+32, 32, ENC_NA);
+ offset = 64;
+ break;
+ }
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, data_offset+offset, 8, ENC_NA);
+}
+
+static void
+dissect_Hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *zrtp_tree) {
+ proto_item *ti;
+ unsigned int msg_offset = 12;
+ unsigned int data_offset = 88;
+ guint8 val_b;
+ unsigned int i;
+ unsigned int run_offset;
+ unsigned int hc, cc, ac, kc, sc;
+ unsigned int vhc, vcc, vac, vkc, vsc;
+ gchar *value;
+ gchar *version_str;
+ proto_tree *tmp_tree;
+
+ col_set_str(pinfo->cinfo, COL_INFO, "Hello Packet");
+
+ version_str = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, msg_offset+12, 4, ENC_ASCII|ENC_NA);
+ if (check_valid_version(version_str) == NULL) {
+ col_set_str(pinfo->cinfo, COL_INFO, "Unsupported version of ZRTP protocol");
+ }
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_version, tvb, msg_offset+12, 4, ENC_ASCII);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_client_id, tvb, msg_offset+16, 16, ENC_ASCII);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hash_image, tvb, msg_offset+32, 32, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_zid, tvb, msg_offset+64, 12, ENC_NA);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_sigcap, tvb, data_offset+0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_mitm, tvb, data_offset+0, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_passive, tvb, data_offset+0, 1, ENC_BIG_ENDIAN);
+
+ val_b = tvb_get_guint8(tvb, data_offset+1);
+ hc = val_b & 0x0F;
+ vhc = hc;
+
+ val_b = tvb_get_guint8(tvb, data_offset+2);
+ cc = val_b & 0xF0;
+ ac = val_b & 0x0F;
+ vcc = cc >> 4;
+ vac = ac;
+
+ val_b = tvb_get_guint8(tvb, data_offset+3);
+ kc = val_b & 0xF0;
+ sc = val_b & 0x0F;
+ vkc = kc >> 4;
+ vsc = sc;
+
+ ti = proto_tree_add_uint_format(zrtp_tree, hf_zrtp_msg_hash_count, tvb, data_offset+1, 1, hc, "Hash type count = %d", vhc);
+ tmp_tree = proto_item_add_subtree(ti, ett_zrtp_msg_hc);
+ run_offset = data_offset+4;
+ for (i=0; i<vhc; i++) {
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, run_offset, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(tmp_tree, hf_zrtp_msg_hash, tvb, run_offset, 4, value,
+ "Hash[%d]: %s", i, key_to_val(value, 4, zrtp_hash_type_vals, "Unknown hash type %s"));
+ run_offset += 4;
+ }
+ ti = proto_tree_add_uint_format(zrtp_tree, hf_zrtp_msg_cipher_count, tvb, data_offset+2, 1, cc, "Cipher type count = %d", vcc);
+ tmp_tree = proto_item_add_subtree(ti, ett_zrtp_msg_cc);
+ for (i=0; i<vcc; i++) {
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, run_offset, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(tmp_tree, hf_zrtp_msg_cipher, tvb, run_offset, 4, value, "Cipher[%d]: %s", i,
+ key_to_val(value, 4, zrtp_cipher_type_vals, "Unknown cipher type %s"));
+ run_offset += 4;
+ }
+ ti = proto_tree_add_uint_format(zrtp_tree, hf_zrtp_msg_authtag_count, tvb, data_offset+2, 1, ac, "Auth tag count = %d", vac);
+ tmp_tree = proto_item_add_subtree(ti, ett_zrtp_msg_ac);
+ for (i=0; i<vac; i++) {
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, run_offset, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(tmp_tree, hf_zrtp_msg_at, tvb, run_offset, 4, value,
+ "Auth tag[%d]: %s", i, key_to_val(value, 4, zrtp_auth_tag_vals, "Unknown auth tag %s"));
+ run_offset += 4;
+ }
+ ti = proto_tree_add_uint_format(zrtp_tree, hf_zrtp_msg_key_count, tvb, data_offset+3, 1, kc, "Key agreement type count = %d", vkc);
+ tmp_tree = proto_item_add_subtree(ti, ett_zrtp_msg_kc);
+ for (i=0; i<vkc; i++) {
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, run_offset, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(tmp_tree, hf_zrtp_msg_keya, tvb, run_offset, 4, value,
+ "Key agreement[%d]: %s", i, key_to_val(value, 4, zrtp_key_agreement_vals, "Unknown key agreement %s"));
+ run_offset += 4;
+ }
+ ti = proto_tree_add_uint_format(zrtp_tree, hf_zrtp_msg_sas_count, tvb, data_offset+3, 1, sc, "SAS type count = %d", vsc);
+ tmp_tree = proto_item_add_subtree(ti, ett_zrtp_msg_sc);
+ for (i=0; i<vsc; i++) {
+ value = (gchar *) tvb_get_string_enc(wmem_packet_scope(), tvb, run_offset, 4, ENC_ASCII|ENC_NA);
+ proto_tree_add_string_format(tmp_tree, hf_zrtp_msg_sas, tvb, run_offset, 4, value,
+ "SAS type[%d]: %s", i, key_to_val(value, 4, zrtp_sas_type_vals, "Unknown SAS type %s"));
+ run_offset += 4;
+ }
+
+ proto_tree_add_item(zrtp_tree, hf_zrtp_msg_hmac, tvb, run_offset, 8, ENC_NA);
+}
+
+void
+proto_register_zrtp(void)
+{
+ static hf_register_info hf[] = {
+ {&hf_zrtp_rtpversion,
+ {
+ "RTP Version", "zrtp.rtpversion",
+ FT_UINT8, BASE_DEC,
+ NULL, 0xC0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_rtppadding,
+ {
+ "RTP padding", "zrtp.rtppadding",
+ FT_BOOLEAN, 8,
+ NULL, 0x20,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_rtpextension,
+ {
+ "RTP Extension", "zrtp.rtpextension",
+ FT_BOOLEAN, 8,
+ NULL, 0x10,
+ NULL, HFILL
+ }
+ },
+
+#if 0
+ {&hf_zrtp_id,
+ {
+ "ID", "zrtp.id",
+ FT_UINT8, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+#endif
+
+ {&hf_zrtp_sequence,
+ {
+ "Sequence", "zrtp.sequence",
+ FT_UINT16, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_cookie,
+ {
+ "Magic Cookie", "zrtp.cookie",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_source_id,
+ {
+ "Source Identifier", "zrtp.source_id",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ /*
+ Message Types
+ */
+ {&hf_zrtp_signature,
+ {
+ "Signature", "zrtp.signature",
+ FT_UINT16, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_length,
+ {
+ "Length", "zrtp.length",
+ FT_UINT16, BASE_DEC,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_type,
+ {
+ "Type", "zrtp.type",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_version,
+ {
+ "ZRTP protocol version", "zrtp.version",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_client_id,
+ {
+ "Client Identifier", "zrtp.client_source_id",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_hash_image,
+ {
+ "Hash Image", "zrtp.hash_image",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_zid,
+ {
+ "ZID", "zrtp.zid",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_sigcap,
+ {
+ "Sig.capable", "zrtp.sigcap",
+ FT_BOOLEAN, 8,
+ NULL, 0x40,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_mitm,
+ {
+ "MiTM", "zrtp.mitm",
+ FT_BOOLEAN, 8,
+ NULL, 0x20,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_passive,
+ {
+ "Passive", "zrtp.passive",
+ FT_BOOLEAN, 8,
+ NULL, 0x10,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_hash_count,
+ {
+ "Hash Count", "zrtp.hc",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0F,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_cipher_count,
+ {
+ "Cipher Count", "zrtp.cc",
+ FT_UINT8, BASE_DEC,
+ NULL, 0xF0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_authtag_count,
+ {
+ "Auth tag Count", "zrtp.ac",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0F,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_key_count,
+ {
+ "Key Agreement Count", "zrtp.kc",
+ FT_UINT8, BASE_DEC,
+ NULL, 0xF0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_sas_count,
+ {
+ "SAS Count", "zrtp.sc",
+ FT_UINT8, BASE_DEC,
+ NULL, 0x0F,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_hash,
+ {
+ "Hash", "zrtp.hash",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_cipher,
+ {
+ "Cipher", "zrtp.cipher",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_at,
+ {
+ "AT", "zrtp.at",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_keya,
+ {
+ "Key Agreement", "zrtp.keya",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_sas,
+ {
+ "SAS", "zrtp.sas",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_rs1ID,
+ {
+ "rs1ID", "zrtp.rs1id",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_rs2ID,
+ {
+ "rs2ID", "zrtp.rs2id",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_auxs,
+ {
+ "auxs", "zrtp.auxs",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_pbxs,
+ {
+ "pbxs", "zrtp.pbxs",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_hmac,
+ {
+ "HMAC", "zrtp.hmac",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_cfb,
+ {
+ "CFB", "zrtp.cfb",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_error,
+ {
+ "Error", "zrtp.error",
+ FT_UINT32, BASE_DEC,
+ VALS(zrtp_error_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_ping_version,
+ {
+ "Ping Version", "zrtp.ping_version",
+ FT_STRING, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_ping_endpointhash,
+ {
+ "Ping Endpoint Hash", "zrtp.ping_endpointhash",
+ FT_UINT64, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_pingack_endpointhash,
+ {
+ "PingAck Endpoint Hash", "zrtp.pingack_endpointhash",
+ FT_UINT64, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_ping_ssrc,
+ {
+ "Ping SSRC", "zrtp.ping_ssrc",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_checksum,
+ {
+ "Checksum", "zrtp.checksum",
+ FT_UINT32, BASE_HEX,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_checksum_status,
+ {
+ "Checksum Status", "zrtp.checksum.status",
+ FT_UINT8, BASE_NONE,
+ VALS(proto_checksum_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_hvi,
+ {
+ "hvi", "zrtp.hvi",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_nonce,
+ {
+ "nonce", "zrtp.nonce",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
+ {&hf_zrtp_msg_key_id,
+ {
+ "key ID", "zrtp.key_id",
+ FT_BYTES, BASE_NONE,
+ NULL, 0x0,
+ NULL, HFILL
+ }
+ }
+ };
+
+ static gint *ett[] = {
+ &ett_zrtp,
+ &ett_zrtp_msg,
+ &ett_zrtp_msg_data,
+ &ett_zrtp_msg_hc,
+ &ett_zrtp_msg_kc,
+ &ett_zrtp_msg_ac,
+ &ett_zrtp_msg_cc,
+ &ett_zrtp_msg_sc,
+ &ett_zrtp_checksum
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_zrtp_checksum, { "zrtp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
+ };
+
+ expert_module_t* expert_zrtp;
+
+ proto_zrtp = proto_register_protocol("ZRTP", "ZRTP", "zrtp");
+ proto_register_field_array(proto_zrtp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ zrtp_handle = register_dissector("zrtp", dissect_zrtp, proto_zrtp);
+ expert_zrtp = expert_register_protocol(proto_zrtp);
+ expert_register_field_array(expert_zrtp, ei, array_length(ei));
+}
+
+void
+proto_reg_handoff_zrtp(void)
+{
+ dissector_add_for_decode_as_with_preference("udp.port", zrtp_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */