diff --git a/AUTHORS b/AUTHORS index cda48695a9..b355fe3334 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2786,6 +2786,7 @@ Joan RamiĆ³ { } David Castleford { + ISMACryp dissector Simulcrypt dissector } diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 2e0bc0085a..b84a0136af 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -548,6 +548,7 @@ DISSECTOR_SRC = \ packet-isis-snp.c \ packet-isis.c \ packet-isl.c \ + packet-ismacryp.c \ packet-ismp.c \ packet-isns.c \ packet-isup.c \ diff --git a/epan/dissectors/packet-ismacryp.c b/epan/dissectors/packet-ismacryp.c new file mode 100644 index 0000000000..28b7c94ae0 --- /dev/null +++ b/epan/dissectors/packet-ismacryp.c @@ -0,0 +1,1052 @@ +/* packet-ismacryp.c + * ISMACryp 1.1 & 2.0 protocol as defined in ISMA Encryption and Authentication see http://www.isma.tv + * + * David Castleford, Orange Labs / France Telecom R&D + * March 2009 + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* TODO: get ISMACryp parameters automatically from SDP info, + * if present (typically sent via SAP/SDP), + * rather than having manual insertion via preferences + * TODO: perhaps better check coherence of certain information? +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +/* keeps track of current position in buffer in terms of bit and byte offset */ +typedef struct Toffset_struct +{ + gint offset_bytes; + guint8 offset_bits; + +} offset_struct; + +static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version); +static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *tree, guint set_version ); +void proto_reg_handoff_ismacryp(void); +static void add_bits(offset_struct* poffset, gint len_bits); + +#define PROTO_TAG_ISMACRYP "ISMACRYP" +#define PROTO_TAG_ISMACRYP_11 "ISMACryp_11" +#define PROTO_TAG_ISMACRYP_20 "ISMACryp_20" +#define V11 11 +#define V20 20 +#define AAC_HBR_MODE 0 +#define MPEG4_VIDEO_MODE 1 +#define AVC_VIDEO_MODE 2 +/* #define USERMODE 3 */ +#define DEFAULT_SELECTIVE_ENCRYPTION TRUE +#define DEFAULT_SLICE_INDICATION FALSE +#define DEFAULT_PADDING_INDICATION FALSE +#define DEFAULT_IV_LENGTH 4 +#define DEFAULT_DELTA_IV_LENGTH 0 +#define DEFAULT_KEY_INDICATOR_LENGTH 0 +#define DEFAULT_KEY_INDICATOR_PER_AU FALSE +#define AU_HEADERS_LENGTH_SIZE 2 /* size in bytes */ +#define DEFAULT_AU_SIZE_LENGTH 0 +#define DEFAULT_AU_INDEX_LENGTH 0 +#define DEFAULT_AU_INDEX_DELTA_LENGTH 0 +#define DEFAULT_CTS_DELTA_LENGTH 0 +#define DEFAULT_DTS_DELTA_LENGTH 0 +#define DEFAULT_RANDOM_ACCESS_INDICATION FALSE +#define DEFAULT_STREAM_STATE_INDICATION 0 + +/* Wireshark ID of the ISMACRYP protocol */ +static int proto_ismacryp = -1; + +/* parameters set in preferences */ +static guint pref_dynamic_payload_type = 0; /* RTP dynamic payload type */ +static guint pref_au_size_length = DEFAULT_AU_SIZE_LENGTH; /* default Au size length */ +static guint pref_au_index_length = DEFAULT_AU_INDEX_LENGTH; /* default Au index length */ +static guint pref_au_index_delta_length = DEFAULT_AU_INDEX_DELTA_LENGTH; /* default Au index delta length */ +static guint pref_cts_delta_length = DEFAULT_CTS_DELTA_LENGTH; /* default CTS delta length */ +static guint pref_dts_delta_length = DEFAULT_DTS_DELTA_LENGTH; /* default DTS delta length */ +static gboolean pref_random_access_indication = DEFAULT_RANDOM_ACCESS_INDICATION; /* default random access indication */ +static guint pref_stream_state_indication = DEFAULT_STREAM_STATE_INDICATION; /* default stream state indication */ +static guint version_type = V11; /* default to ISMACryp 1.1 */ +static guint mode = AVC_VIDEO_MODE; /* default codec mode */ +static gboolean selective_encryption = DEFAULT_SELECTIVE_ENCRYPTION; /* default selective encryption flag */ +static gboolean slice_indication = DEFAULT_SLICE_INDICATION; /* default slice indication */ +static gboolean padding_indication = DEFAULT_PADDING_INDICATION; /* default padding indication */ +static guint key_indicator_length = DEFAULT_KEY_INDICATOR_LENGTH; /* default key indicator length */ +static gboolean key_indicator_per_au_flag = DEFAULT_KEY_INDICATOR_PER_AU; /* default key indicator per au */ +static guint iv_length = DEFAULT_IV_LENGTH; /* default IV length */ +static guint delta_iv_length = DEFAULT_DELTA_IV_LENGTH; /* default delta IV length */ +static gboolean pref_user_mode = FALSE; /* preference user mode instead of RFC3640 mode? */ +static gboolean override_flag = FALSE; /* override use of RTP payload type to deduce ISMACryp version */ + +/* */ + +static guint au_size_length = DEFAULT_AU_SIZE_LENGTH; /* default Au size length */ +static guint au_index_length = DEFAULT_AU_INDEX_LENGTH; /* default Au index length */ +static guint au_index_delta_length = DEFAULT_AU_INDEX_DELTA_LENGTH; /* default Au index delta length */ +static guint cts_delta_length = DEFAULT_CTS_DELTA_LENGTH; /* default CTS delta length */ +static guint dts_delta_length = DEFAULT_DTS_DELTA_LENGTH; /* default DTS delta length */ +static gboolean random_access_indication = DEFAULT_RANDOM_ACCESS_INDICATION; /* default random access indication */ +static guint stream_state_indication = DEFAULT_STREAM_STATE_INDICATION; /* default stream state indication */ +static gboolean user_mode = FALSE; /* selected user mode instead of RFC3640 mode? */ + +/*static const value_string messagetypenames[] = {}; */ + +/* ismacryp Parameter Types */ +/*static const value_string parametertypenames[] = {}; */ +static const value_string modetypenames[] = { + { AAC_HBR_MODE, "aac-hbr" }, + { MPEG4_VIDEO_MODE, "mpeg4-video" }, + { AVC_VIDEO_MODE, "avc-video" }, + { 0, NULL} +}; +/* The following hf_* variables are used to hold the Wireshark IDs of +* our header fields; they are filled out when we call +* proto_register_field_array() in proto_register_ismacryp() +*/ +/** Kts attempt at defining the protocol */ +static gint hf_ismacryp = -1; +static gint hf_ismacryp_header = -1; +static gint hf_ismacryp_au_headers_length = -1; +static gint hf_ismacryp_header_length = -1; +static gint hf_ismacryp_header_byte = -1; +static gint hf_ismacryp_version = -1; +static gint hf_ismacryp_length = -1; +/* static gint hf_ismacryp_message_type = -1; */ +static gint hf_ismacryp_message_length = -1; +static gint hf_ismacryp_message = -1; +static gint hf_ismacryp_parameter = -1; +/* static gint hf_ismacryp_parameter_type = -1; */ +static gint hf_ismacryp_parameter_length = -1; +static gint hf_ismacryp_parameter_value = -1; +static gint hf_ismacryp_iv = -1; +static gint hf_ismacryp_delta_iv = -1; +static gint hf_ismacryp_key_indicator = -1; +/* static gint hf_ismacryp_delta_iv_length = -1; */ +static gint hf_ismacryp_au_size = -1; +static gint hf_ismacryp_au_index = -1; +static gint hf_ismacryp_au_index_delta = -1; +static gint hf_ismacryp_cts_delta = -1; +static gint hf_ismacryp_cts_flag = -1; +static gint hf_ismacryp_dts_flag = -1; +static gint hf_ismacryp_dts_delta = -1; +static gint hf_ismacryp_rap_flag = -1; +static gint hf_ismacryp_au_is_encrypted = -1; +static gint hf_ismacryp_slice_start = -1; +static gint hf_ismacryp_slice_end = -1; +static gint hf_ismacryp_padding_bitcount = -1; +static gint hf_ismacryp_padding = -1; +static gint hf_ismacryp_reserved_bits = -1; +static gint hf_ismacryp_unused_bits = -1; +static gint hf_ismacryp_stream_state = -1; + +/* These are the ids of the subtrees that we may be creating */ +static gint ett_ismacryp = -1; +static gint ett_ismacryp_header = -1; +static gint ett_ismacryp_header_byte = -1; +static gint ett_ismacryp_message = -1; + +/* Informative tree structure is shown here: +* TREE - +* AU Headers Length (2 bytes) - total length of AU header(s) +* - HEADER1 +* HEADER BYTE (if present - 1 byte) +* -AU_is_encrypted (1 bit) +* -Slice_start (1 bit) +* -Slice_end (1 bit) +* -Padding_bitcount (3 bits) +* -Reserved (2 bits) +* IV (variable length) +* Key Indicator (variable length) +* AU size (if present - variable length) +* AU index (if present - variable length) +* CTS delta (if present - variable length) +* DTS delta (if present - variable length) +* RAP flag (if present - 1 bit) +* Stream State Indication (if present - variable length) +* - HEADER2 if 2nd header present (depends on AU headers length) +* Header Byte (if present - 1 byte) +* -AU_is_encrypted (1 bit) +* -Slice_start (1 bit) +* -Slice_end (1 bit) +* -Padding_bitcount (3 bits) +* -Reserved (2 bits) +* IV (variable length) +* Key Indicator (variable length) +* AU size (if present - variable length) +* AU index delta(if present - variable length) +* CTS delta (if present - variable length) +* DTS delta (if present - variable length) +* RAP flag (if present - 1 bit) +* Stream State Indication (if present - variable length) +* - more HEADERS if present +* - MESSAGE +* encrypted AU +* End informative tree structure +*/ + +/* Note that check coherence of total AU headers length and that calculated from size of parameters defined by default or preferences. +* These are found in SDP and vary e.g. between audio and video and depend on ISMACryp encoding parameters +* hence if these values are incorrect displayed values will be strange and can see errors +* this could be improved of course +*/ + +/* dissect_ismacryp_v11 gets called if rtp_dyn_payload_type = "enc-mpeg4-generic" i.e. is set via SDP */ +static void dissect_ismacryp_v11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + /* display ISMACryp version */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11); + + /* display RTP payload type */ + if ( check_col( pinfo->cinfo, COL_INFO) ) { + col_clear(pinfo->cinfo,COL_INFO); /* clear column info */ + + col_append_str(pinfo->cinfo, COL_INFO, "(PT=enc-mpeg4-generic)"); + } + + dissect_ismacryp_common( tvb, pinfo, tree, V11); +} + +/* dissect_ismacryp_v20 gets called if rtp_dyn_payload_type = "enc-isoff-generic" i.e. is set via SDP */ +static void dissect_ismacryp_v20(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + /* display ISMACryp version */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20); + + /* display RTP payload type */ + if (check_col(pinfo->cinfo, COL_INFO)){ + col_clear(pinfo->cinfo,COL_INFO); /* clear column info */ + col_append_str(pinfo->cinfo, COL_INFO, "(PT=enc-isoff-generic)"); + } + + dissect_ismacryp_common( tvb, pinfo, tree, V20); +} + +static void dissect_ismacryp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + if (check_col(pinfo->cinfo, COL_INFO)){ + col_clear(pinfo->cinfo,COL_INFO); /* clear column info */ + col_append_str(pinfo->cinfo, COL_INFO, "Manual version"); + } + dissect_ismacryp_common( tvb, pinfo, tree, version_type); /* Unknown version type: Use preference */ +} + +static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version) +{ + guint set_version; /* ISMACryp version used during dissection */ + proto_item *ismacryp_item; + proto_tree *ismacryp_tree; + proto_tree *ismacryp_message_tree; + + /* select and display ISMACryp version */ + if ((ismacryp_version!=version_type) && override_flag){ + /* override -> use manual preference setting */ + if (check_col(pinfo->cinfo, COL_INFO)){ + col_append_str(pinfo->cinfo, COL_INFO, " Manual version"); + } + set_version = version_type; /* set to preference value */ + } + else { + set_version = ismacryp_version; + } + + if (set_version == V11){ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11); + /* display mode */ + if (pref_user_mode == FALSE){ + if (check_col( pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str(mode, modetypenames, "user mode")); + } + if (pref_user_mode == TRUE){ + if ( check_col( pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s","user mode"); + } + user_mode = pref_user_mode; + } + if (set_version == V20){ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20); + user_mode = TRUE; + /* display mode */ + if (check_col( pinfo->cinfo, COL_INFO)) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s","user mode"); + } + /* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */ + if (user_mode == TRUE){ /* use values set in preference menu */ + au_size_length = pref_au_size_length; + au_index_length = pref_au_index_length; + au_index_delta_length = pref_au_index_delta_length; + cts_delta_length = pref_cts_delta_length; + dts_delta_length = pref_dts_delta_length; + random_access_indication = pref_random_access_indication; + stream_state_indication = pref_stream_state_indication; + } /* end if user_mode == TRUE */ + if (user_mode == FALSE){ + switch (mode){ + case AAC_HBR_MODE: + au_size_length = 13; + au_index_length = 3; + au_index_delta_length = 3; + cts_delta_length = 0; + dts_delta_length = 0; + random_access_indication = FALSE; + stream_state_indication = 0; + break; + case MPEG4_VIDEO_MODE: + au_size_length = 0; + au_index_length = 0; + au_index_delta_length = 0; + cts_delta_length = 0; + dts_delta_length = 22; + random_access_indication = TRUE; + stream_state_indication = 0; + break; + case AVC_VIDEO_MODE: + au_size_length = 0; + au_index_length = 0; + au_index_delta_length = 0; + cts_delta_length = 0; + dts_delta_length = 22; + random_access_indication = TRUE; + stream_state_indication = 0; + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + break; + } /* end switch */ + } /* end if user_mode == FALSE */ + + /* navigate through buffer */ + if (tree) + { + /* we are being asked for details */ + + guint16 au_headers_length = 0; /* total length of AU headers */ + guint16 totalbits =0; /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */ + int deltabits = -1; /* keeps track of extra bits per AU header treated (used to determine end of AU heafers ) */ + guint16 totalbit_offset = 0; /* total offset in bits*/ + int nbpadding_bits = 0; /* number of padding bits*/ + offset_struct s_offset; + offset_struct* poffset; + guint16 nbmessage_bytes = 0; /*nb of message data bytes */ + s_offset.offset_bytes = 0; /* initialise byte offset */ + s_offset.offset_bits = 0; /* initialise bit offset */ + poffset = &s_offset; + + ismacryp_item = proto_tree_add_item(tree, proto_ismacryp, tvb, 0, -1, FALSE); + ismacryp_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp); + proto_item_append_text(tree, ", %s", "ismacryp packet"); /* add text to tree */ + + /* ismacryp_tree analysis */ + /* we are being asked for details */ + /* get total length of AU headers (first 2 bytes) */ + ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_au_headers_length, + tvb, poffset->offset_bytes, AU_HEADERS_LENGTH_SIZE, FALSE ); + proto_item_append_text(ismacryp_item, " (bits)"); /* add text to AU Header tree indicating length */ + au_headers_length=tvb_get_ntohs(tvb,poffset->offset_bytes); /* 2 byte au headers length */ + poffset->offset_bytes+=AU_HEADERS_LENGTH_SIZE; + /* ADD HEADER(S) BRANCH */ + + /* AU Header loop */ + totalbits=(poffset->offset_bytes*8)+poffset->offset_bits; + while( ((totalbits-8*AU_HEADERS_LENGTH_SIZE)offset_bytes*8)+poffset->offset_bits - totalbits; /* if zero this means no actual AU header so exit while loop */ + totalbits+=deltabits; + } + /* reached end of AU Header(s) */ + /* sanity check if actual total AU headers length in bits i.e. totalbits is */ + /* the same as expected AU headers length from 2 bytes at start of buffer */ + if ( (totalbits-8*AU_HEADERS_LENGTH_SIZE) != au_headers_length) /* something wrong */ + { + proto_item_append_text(ismacryp_item, + " Error - expected total AU headers size (%d bits) " + "does not match calculated size (%d bits) - check parameters!", + au_headers_length,(totalbits-8*AU_HEADERS_LENGTH_SIZE)); + } + /* add padding if need to byte align */ + if (poffset->offset_bits!=0) + { + totalbit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + nbpadding_bits = (8-poffset->offset_bits); /* number of padding bits for byte alignment */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_tree, hf_ismacryp_padding, + tvb, totalbit_offset, nbpadding_bits , FALSE); /* padding bits */ + proto_item_append_text(ismacryp_item, ": Length=%d bits",nbpadding_bits); /* add padding info */ + add_bits(poffset, nbpadding_bits); + } + /* ADD MESSAGE BRANCH */ + ismacryp_item = proto_tree_add_item( ismacryp_tree, hf_ismacryp_message, + tvb, poffset->offset_bytes, -1, FALSE ); + ismacryp_message_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_message); + proto_item_append_text(ismacryp_item, ", %s", "Encrypted data"); /* add text to Message tree */ + nbmessage_bytes = tvb_reported_length_remaining(tvb, poffset->offset_bytes); + proto_item_append_text(ismacryp_item, ", Length= %d bytes", nbmessage_bytes ); /* add length of message */ + + /* ismacryp message tree analysis (encrypted AUs) */ + if (ismacryp_message_tree) + { /* we are being asked for details */ + poffset->offset_bytes+= nbmessage_bytes; /* */ + } /* end message details */ + /* end ismacryp tree details */ + } /* end if tree */ +} +/* AU Header dissection */ +static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *ismacryp_tree, guint set_version ) +{ + proto_item *ismacryp_item; + proto_tree *ismacryp_header_tree; + proto_tree *ismacryp_header_byte_tree; + + guint16 header_len_bytes = 0; /* total length of non-first AU header in bytes (rounded up) */ + gint header_len = 0; /* length of AU headers in bits */ + gint cts_flag =0; + gint dts_flag =0; + gboolean first_au_flag=FALSE; + gint bit_offset = 0; + + /*first determine total AU header length */ + /* calculate each AU header length in bits first */ + switch (set_version) { + case V11: + if (selective_encryption) + header_len+=8; /* add one byte to header length */ + break; + case V20: + if (selective_encryption || slice_indication || padding_indication) + header_len+=8; /* add one byte to header length */ + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + break; + } /* end switch */ + header_len+=au_size_length; /* add au size length */ + + if (poffset->offset_bytes==AU_HEADERS_LENGTH_SIZE){ /*first AU */ + header_len+=8*(iv_length); /* add IV length */ + header_len+=8*key_indicator_length; /* add key indicator length */ + header_len+=au_index_length; /* add AU index length */ + first_au_flag = TRUE; + } + else { /* not the first AU */ + if (key_indicator_per_au_flag == TRUE) + header_len+=8*key_indicator_length; /* add key indicator length */ + header_len+=8*(delta_iv_length); /* add delta IV length */ + header_len+=au_index_delta_length; /* add AU delta index length */ + } + /* CTS flag is present? */ + if (cts_delta_length != 0){ /* need to test whether cts_delta_flag is TRUE or FALSE */ + cts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit CTS flag */ + header_len+=1; /* add CTS flag bit */ + if (cts_flag==1) + header_len+=cts_delta_length; /* add CTS delta length bits if CTS flag SET */ + } + /* DTS flag is present? */ + if (dts_delta_length != 0){ /* need to test whether dts_delta_flag is TRUE or FALSE */ + dts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit DTS flag */ + header_len+=1; /* add DTS flag bit */ + if (dts_flag==1) + header_len+=dts_delta_length; /* add DTS delta length bits if DTS flag SET */ + } + /* RAP flag present? */ + if (random_access_indication != FALSE) + header_len+=1; /* add 1 bit RAP flag */ + + /* stream state indication present */ + if (stream_state_indication !=0) + header_len+=stream_state_indication; /* add stream state indication bits */ + + /* convert header_len to bytes (rounded up) */ + if (header_len% 8!=0) + { + header_len_bytes=((header_len)/8)+1; /*add 1 */ + } + else + header_len_bytes=((header_len)/8); + + /* add AU header tree */ + ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_header, tvb, poffset->offset_bytes, header_len_bytes, FALSE ); + proto_item_append_text(ismacryp_item, ": Length=%d bits", header_len); /* add text to Header tree indicating length */ + /* sanity check if actual AU header length is zero bits, which indicates an error */ + if ( header_len == 0) /* something wrong */ + { + proto_item_append_text(ismacryp_item, " Error - zero bit AU header size - check parameters!"); + } + ismacryp_header_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header); + + /* ismacryp header analysis */ + /* we are being asked for details */ + + /* Extra 1 Byte Header? */ + + if ((set_version==V20 && (selective_encryption || slice_indication || padding_indication)) + || (set_version==V11 && selective_encryption)){ + + /* add header byte tree */ + ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_header_byte, + tvb, poffset->offset_bytes, 1, FALSE ); + proto_item_append_text(ismacryp_item, ": Length=8 bits"); /* add text to Header byte tree indicating length */ + ismacryp_header_byte_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header_byte); + + /*ismacryp_header_byte_tree */ + /* we are being asked for details */ + /* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */ + add_bits(poffset,7); /*shift 7 bits to get correct bit */ + /* AU_is_encrypted bit */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + if (selective_encryption){ /* bit used */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_au_is_encrypted, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit AU_is_encrypted */ + } + else { /* bit unused */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */ + } + switch (set_version){ /* ISMACryp version? */ + case V11: + /* Reserved bits */ + add_bits(poffset, -7); /* move back 7 bits for reserved bits */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits, + tvb, bit_offset, 7, FALSE); /*fetch 7 bits reserved */ + add_bits(poffset,8); /* offset to next byte */ + break; + case V20: + /* Slice_start bit */ + add_bits(poffset, -1); /* move back 1 bit for slice_start */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + if (slice_indication){ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_start, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit slice_start */ + } + else { /* bit unused */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */ + } + add_bits(poffset, -1); /* move back 1 bit for slice_end */ + + /* Slice_end bit */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + if (slice_indication){ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_end, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit Slice_end */ + } + else { /* bit unused */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, + tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */ + } + add_bits(poffset, -3); /* move back 3 bits for padding_bitcount */ + + /* Padding_bitcount bits */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + if (padding_indication){ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_padding_bitcount, + tvb, bit_offset, 3, FALSE); /*fetch 3 bits padding_bitcount */ + } + else { /* bits unused */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits, + tvb, bit_offset, 3, FALSE); /*fetch 3 bits unused */ + } + add_bits(poffset, -2); /* move back 2 bits for reserved bits */ + + /* Reserved bits */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits, + tvb, bit_offset, 2, FALSE); /*fetch 2 bits reserved */ + add_bits(poffset,8); /* offset to next byte */ + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + break; + } /* end switch set_version */ + } /* end selective encryption */ + /* IV */ + if (first_au_flag == TRUE && iv_length != 0) + { + ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_iv, tvb, poffset->offset_bytes, iv_length, FALSE); + proto_item_append_text(ismacryp_item, ": Length=%d bytes",iv_length); /* add IV info */ + if ( check_col( pinfo->cinfo, COL_INFO) ) { + col_append_fstr( pinfo->cinfo, COL_INFO, + ", IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, iv_length,' ')); + } + poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */ + } + /*Delta IV */ + if (first_au_flag == FALSE && delta_iv_length != 0) + { + ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_delta_iv, + tvb, poffset->offset_bytes, delta_iv_length, FALSE); + proto_item_append_text(ismacryp_item, ": Length=%d bytes",delta_iv_length); /* add delta IV info */ + if ( check_col( pinfo->cinfo, COL_INFO) ) { + col_append_fstr( pinfo->cinfo, COL_INFO, + ", Delta IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, delta_iv_length,' ')); + } + poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */ + } + /* Key Indicator */ + if ( key_indicator_length != 0 && ( first_au_flag == TRUE || key_indicator_per_au_flag == TRUE) ) + { + /* (first AU or KI for each AU) and non-zero KeyIndicator size */ + ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_key_indicator, + tvb, poffset->offset_bytes, key_indicator_length, FALSE); + proto_item_append_text(ismacryp_item,": Length=%d bytes",key_indicator_length); /* add KI info */ + if ( check_col( pinfo->cinfo, COL_INFO) ) { + col_append_fstr( pinfo->cinfo, COL_INFO, + ", KI=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, key_indicator_length,' ')); + } + poffset->offset_bytes+=key_indicator_length; /* add KI length to offset_bytes */ + } + /* AU size */ + if (au_size_length != 0) /* in bits */ + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_size, + tvb, bit_offset, au_size_length, FALSE); + proto_item_append_text(ismacryp_item, " bytes: Length=%d bits",au_size_length); /* add AU size info */ + bit_offset+=au_size_length; + add_bits(poffset, au_size_length); + } + /* AU Index */ + if (first_au_flag == TRUE && au_index_length != 0) /* first AU and non-zero AU size */ + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index, + tvb, bit_offset, au_index_length, FALSE); + proto_item_append_text(ismacryp_item, " bits: Length=%d bits",au_index_length); /* add AU index info */ + bit_offset+=au_index_length; + add_bits(poffset, au_index_length); + } + /* AU index delta */ + if (first_au_flag == FALSE && au_index_delta_length != 0) /* not first AU and non-zero AU delta size */ + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index_delta, + tvb, bit_offset, au_index_delta_length, FALSE); + proto_item_append_text(ismacryp_item, ": Length=%d bits", au_index_delta_length); /* add AU index info */ + bit_offset+=au_index_delta_length; + add_bits(poffset, au_index_delta_length); + } + /* CTS delta value */ + if (cts_delta_length != 0) + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_flag, + tvb, bit_offset, 1, FALSE); /* read CTS flag */ + add_bits(poffset, 1); + if (cts_flag==1) + { + /* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */ + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_delta, + tvb, bit_offset, cts_delta_length, FALSE); /* read CTS delta value */ + proto_item_append_text(ismacryp_item, ": Length=%d bits",cts_delta_length); /* add CTS delta info */ + add_bits(poffset, cts_delta_length); + } + } + /* DTS delta value */ + if (dts_delta_length != 0) + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_flag, + tvb, bit_offset, 1, FALSE); /* read DTS flag */ + add_bits(poffset, 1); + + /* now fetch DTS delta value (remember offset x bits due to DTS flag) */ + if (dts_flag ==1) + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_delta, + tvb, bit_offset, dts_delta_length, FALSE); /* read DTS delta value */ + proto_item_append_text(ismacryp_item, ": Length=%d bits",dts_delta_length); /* add DTS delta info */ + add_bits(poffset, dts_delta_length); + } + } + /* RAP */ + if (random_access_indication != FALSE) + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_rap_flag, + tvb, bit_offset, 1, FALSE); /* read RAP flag */ + add_bits(poffset, 1); + } + /*STREAM STATE */ + if (stream_state_indication != 0) + { + bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */ + ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_stream_state, + tvb, bit_offset, stream_state_indication, FALSE); /* read stream state */ + add_bits(poffset, stream_state_indication); + } + /* end header details */ +return poffset; +} + +/* add len_bits to offset bits and bytes, handling bits overflow */ +static void add_bits(offset_struct* poffset, gint len_bits) +{ + gint nbbitstotal=0; + nbbitstotal=poffset->offset_bytes*8+(poffset->offset_bits)+len_bits; /* total offset in bits */ + /* now calculate bytes and bit offsets */ + poffset->offset_bytes=(nbbitstotal / 8); /* add integer no. of bytes */ + poffset->offset_bits=(nbbitstotal % 8); /* add remaining bits */ +} + +void proto_register_ismacryp (void) +{ + /* A header field is something you can search/filter on. + * + * We create a structure to register our fields. It consists of an + * array of hf_register_info structures, each of which are of the format + * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}. + */ + static hf_register_info hf[] = { + { &hf_ismacryp, + { "Data", "ismacryp.data", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_length, + { "Total Length", "ismacryp.len", FT_UINT16, BASE_DEC, NULL, 0x0, /* length 2 bytes, print as decimal value */ + NULL, HFILL }}, + + { &hf_ismacryp_header, + { "AU Header", "ismacryp.header", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_header_length, + { "Header Length", "ismacryp.header.length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_au_headers_length, + { "AU Headers Length", "ismacryp.au_headers.length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_header_byte, + { "Header Byte", "ismacryp.header.byte", FT_NONE, BASE_NONE, NULL, 0x0, /* 1 byte */ + NULL, HFILL }}, +#if 0 + { &hf_ismacryp_header_byte, + { "Header Byte", "ismacryp.header.byte", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, +#endif + + { &hf_ismacryp_version, + { "Version", "ismacryp.version", FT_UINT8, BASE_HEX, NULL, 0x0, /* version 1 byte */ + NULL, HFILL }}, + + { &hf_ismacryp_message, + { "Message", "ismacryp.message", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_message_length, + { "Message Length", "ismacryp.message.len", FT_UINT16, BASE_DEC, NULL, 0x0, /* length 2 bytes, print as decimal value */ + NULL, HFILL }}, + + { &hf_ismacryp_parameter, + { "Parameter", "ismacryp.parameter", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_parameter_length, + { "Parameter Length", "ismacryp.parameter.len", FT_UINT16, BASE_DEC, NULL, 0x0, /* length 2 bytes, print as decimal value */ + NULL, HFILL }}, + + { &hf_ismacryp_iv, + { "IV", "ismacryp.iv", FT_BYTES, BASE_HEX, NULL, 0x0, /* variable length */ + NULL, HFILL }}, + + { &hf_ismacryp_delta_iv, + { "Delta IV", "ismacryp.delta_iv", FT_BYTES, BASE_HEX, NULL, 0x0, /* variable length */ + NULL, HFILL }}, + + { &hf_ismacryp_key_indicator, + { "Key Indicator", "ismacryp.key_indicator", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */ + NULL, HFILL }}, + + { &hf_ismacryp_parameter_value, + { "Parameter Value", "ismacryp.parameter.value", FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_au_size, + { "AU size", "ismacryp.au.size", FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_au_index, + { "AU index", "ismacryp.au.index", FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_au_index_delta, + { "AU index delta", "ismacryp.au.index_delta", FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_cts_delta, + { "CTS delta", "ismacryp.cts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_cts_flag, + { "CTS flag", "ismacryp.cts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_dts_delta, + { "DTS delta", "ismacryp.dts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_dts_flag, + { "DTS flag", "ismacryp.dts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_rap_flag, + { "RAP flag", "ismacryp.rap_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_stream_state, + { "Stream state", "ismacryp.stream_state", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_au_is_encrypted, + { "AU_is_encrypted flag", "ismacryp.au_is_encrypted", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_slice_start, + { "Slice_start flag", "ismacryp.slice_start", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_slice_end, + { "Slice_end flag", "ismacryp.slice_end", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_padding_bitcount, + { "Padding_bitcount bits", "ismacryp.padding_bitcount", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_padding, + { "Padding bits", "ismacryp.padding", FT_BOOLEAN, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_ismacryp_reserved_bits, + { "Reserved bits", "ismacryp.reserved", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }}, + + { &hf_ismacryp_unused_bits, + { "Unused bits", "ismacryp.unused", FT_BOOLEAN, BASE_NONE, NULL, 0x00, + NULL, HFILL }} + }; + + static gint *ett[] = + { + &ett_ismacryp, + &ett_ismacryp_header, + &ett_ismacryp_header_byte, + &ett_ismacryp_message + }; + + static enum_val_t version_types[] = { + {PROTO_TAG_ISMACRYP_11, "ISMACryp v1.1", V11}, + {PROTO_TAG_ISMACRYP_20, "ISMACryp v2.0", V20}, + {NULL, NULL, -1} + }; + + static enum_val_t mode_types[] = { + {"aac-hbr", "aac-hbr", AAC_HBR_MODE}, + {"mpeg4-video", "mpeg4-video", MPEG4_VIDEO_MODE}, + {"avc-video", "avc-video", AVC_VIDEO_MODE}, + {NULL, NULL, -1} + }; + + module_t *ismacryp_module; + + proto_ismacryp = proto_register_protocol ("ISMACryp Protocol", "ISMACRYP", "ismacryp"); + proto_register_field_array (proto_ismacryp, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + + /* Register our configuration options for ismacryp */ + /* this registers our preferences, function proto_reg_handoff_ismacryp is called when preferences are applied */ + ismacryp_module = prefs_register_protocol(proto_ismacryp, proto_reg_handoff_ismacryp); + + prefs_register_uint_preference(ismacryp_module, "dynamic.payload.type", + "ISMACryp dynamic payload type", + "The dynamic payload type which will be interpreted as ISMACryp", + 10, + &pref_dynamic_payload_type); + + prefs_register_enum_preference(ismacryp_module, "version", + "ISMACryp version", + "ISMACryp version", + &version_type, version_types, TRUE); + + prefs_register_static_text_preference(ismacryp_module, "text_override", + "The following option allows the version to be set manually" + " and to override the version if detected from RTP payload type:", + "The following option allows the version to be set manually" + " and to override the version if detected from RTP payload type:"); + + prefs_register_bool_preference(ismacryp_module, + "override_rtp_pt","Override RTP payload type for version", + "Indicates whether or not the ISMACryp version deduced" + " from RTP payload type, if present, is used or whether the" + " version above is used", + &override_flag); + + /* ISMACryp v11 parameters */ + prefs_register_static_text_preference(ismacryp_module, + "v11_parameters", + "ISMACryp v1.1 parameters:", + "ISMACryp v1.1 parameters declared in SDP"); + + prefs_register_uint_preference(ismacryp_module, + "iv_length","ISMACrypIVLength (bytes)", + "Set the length of the IV in the ISMACryp AU Header in bytes", + 10, &iv_length); + + prefs_register_uint_preference(ismacryp_module, + "delta_iv_length","ISMACrypDeltaIVLength (bytes)", + "Set the length of the Delta IV in the ISMACryp AU Header in bytes", + 10, &delta_iv_length); + + prefs_register_uint_preference(ismacryp_module, + "key_indicator_length","ISMACrypKeyIndicatorLength (bytes)", + "Set the length of the Key Indicator in the ISMACryp AU Header in bytes", + 10, &key_indicator_length); + + prefs_register_bool_preference(ismacryp_module, + "key_indicator_per_au_flag","ISMACrypKeyIndicatorPerAU (T/F)", + "Indicates whether or not the Key Indicator is present in all AU Headers (T/F)", + &key_indicator_per_au_flag); + + prefs_register_bool_preference(ismacryp_module, + "selective_encryption","ISMACrypSelectiveEncryption (T/F)", + "Indicates whether or not selective encryption is enabled (T/F)", + &selective_encryption); + + /* ISMACryp v20 parameters */ + prefs_register_static_text_preference(ismacryp_module, + "v20_parameters", + "ISMACryp v2.0 parameters:", + "ISMACryp v2.0 parameters declared in SDP"); + + prefs_register_bool_preference(ismacryp_module, + "slice_indication","ISMACrypSliceIndication (T/F)", + "Indicates whether or not slice start / end is present (T/F)", + &slice_indication); + + prefs_register_bool_preference(ismacryp_module, + "padding_indication","ISMACrypPaddingIndication (T/F)", + "Indicates whether or not padding information is present (T/F)", + &padding_indication); + + /* RFC3640 mode - ISMACryp v11 */ + prefs_register_static_text_preference(ismacryp_module, + "codec_modes", + "Codec mode selection (RFC3640 for ISMACryp v1.1 only):", + "AU parameters set according to RFC3640 mode or user defined"); + + prefs_register_enum_preference(ismacryp_module, + "rfc3640_mode", + "RFC3640 mode", + "RFC3640 mode", + &mode, mode_types, TRUE); + + /* User defined mode */ + prefs_register_bool_preference(ismacryp_module, + "user_mode","User mode (T/F)", + "Indicates use of user mode instead of RFC3640 modes (T/F)", + &pref_user_mode); + + /* following preference values only used if user mode is selected above */ + prefs_register_static_text_preference(ismacryp_module, + "user_defined_modes", + "Following parameters only valid and used for user mode:", + "AU parameters defined by the user"); + + /* ideally would grey this out or disable this if in user mode */ + prefs_register_uint_preference(ismacryp_module, + "au_size_length","User mode: SizeLength (bits)", + "Set the length of the AU size in the AU Header in bits", + 10, &pref_au_size_length); + + prefs_register_uint_preference(ismacryp_module, + "au_index_length","User mode: IndexLength (bits)", + "Set the length of the AU index in the AU Header in bits", + 10, &pref_au_index_length); + + prefs_register_uint_preference(ismacryp_module, + "au_index_delta_length","User mode: IndexDeltaLength (bits)", + "Set the length of the AU delta index in the AU Header in bits", + 10, &pref_au_index_delta_length); + + prefs_register_uint_preference(ismacryp_module, + "cts_delta_length","User mode: CTSDeltaLength (bits)", + "Set the length of the CTS delta field in the AU Header in bits", + 10, &pref_cts_delta_length); + + prefs_register_uint_preference(ismacryp_module, + "dts_delta_length","User mode: DTSDeltaLength (bits)", + "Set the length of the DTS delta field in the AU Header in bits", + 10, &pref_dts_delta_length); + + prefs_register_bool_preference(ismacryp_module, + "random_access_indication","User mode: RandomAccessIndication (T/F)", + "Indicates whether or not the RAP field is present in the AU Header (T/F)", + &pref_random_access_indication); + + prefs_register_uint_preference(ismacryp_module, + "stream_state_indication","User mode: StreamStateIndication (number of bits)", + "Indicates the number of bits on which the stream state field is encoded" + " in the AU Header (bits)", + 10, &pref_stream_state_indication); + +} + +void proto_reg_handoff_ismacryp(void) +{ + static gboolean ismacryp_prefs_initialized=FALSE; + static dissector_handle_t ismacryp_handle; + static guint dynamic_payload_type; + + if (!ismacryp_prefs_initialized) { + dissector_handle_t ismacryp_v11_handle; + dissector_handle_t ismacryp_v20_handle; + ismacryp_handle = create_dissector_handle(dissect_ismacryp, proto_ismacryp); + ismacryp_v11_handle = create_dissector_handle(dissect_ismacryp_v11, proto_ismacryp); + ismacryp_v20_handle = create_dissector_handle(dissect_ismacryp_v20, proto_ismacryp); + ismacryp_prefs_initialized = TRUE; + dissector_add_string("rtp_dyn_payload_type", "ISMACRYP", ismacryp_handle); + dissector_add_string("rtp_dyn_payload_type", "enc-mpeg4-generic", ismacryp_v11_handle); + dissector_add_string("rtp_dyn_payload_type", "enc-isoff-generic", ismacryp_v20_handle); + } + else { /* ismacryp_prefs_initialized = TRUE */ + /* delete existing association of ismacryp with payload_type */ + if ( dynamic_payload_type > 95 ){ + dissector_delete("rtp.pt", dynamic_payload_type, ismacryp_handle); + } + } + /* always do the following */ + dynamic_payload_type = pref_dynamic_payload_type; /*update payload_type to new value */ + if ( dynamic_payload_type > 95 ){ + dissector_add("rtp.pt", dynamic_payload_type, ismacryp_handle); + } + +}