Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-ismacryp.c
1 /* packet-ismacryp.c
2  * ISMACryp 1.1 & 2.0 protocol as defined in ISMA Encryption and Authentication see http://www.isma.tv
3  *
4  * David Castleford, Orange Labs / France Telecom R&D
5  * March 2009
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 /*      TODO: get ISMACryp parameters automatically from SDP info,
29  *             if present (typically sent via SAP/SDP),
30  *             rather than having manual insertion via preferences
31  *      TODO: perhaps better check coherence of certain information?
32 */
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <glib.h>
38 #include <epan/packet.h>
39 #include <epan/prefs.h>
40
41 /* keeps track of current position in buffer in terms of bit and byte offset */
42 typedef struct Toffset_struct
43 {
44         gint offset_bytes;
45         guint8 offset_bits;
46
47 } offset_struct;
48
49 static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version);
50 static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *tree, guint set_version );
51 void proto_reg_handoff_ismacryp(void);
52 static void add_bits(offset_struct* poffset, gint len_bits);
53
54 #define PROTO_TAG_ISMACRYP      "ISMACRYP"
55 #define PROTO_TAG_ISMACRYP_11   "ISMACryp_11"
56 #define PROTO_TAG_ISMACRYP_20   "ISMACryp_20"
57 #define V11                                     11
58 #define V20                                     20
59 #define AAC_HBR_MODE                            0
60 #define MPEG4_VIDEO_MODE                        1
61 #define AVC_VIDEO_MODE                          2
62 /* #define USERMODE                             3 */
63 #define DEFAULT_SELECTIVE_ENCRYPTION            TRUE
64 #define DEFAULT_SLICE_INDICATION                FALSE
65 #define DEFAULT_PADDING_INDICATION              FALSE
66 #define DEFAULT_IV_LENGTH                       4
67 #define DEFAULT_DELTA_IV_LENGTH                 0
68 #define DEFAULT_KEY_INDICATOR_LENGTH            0
69 #define DEFAULT_KEY_INDICATOR_PER_AU            FALSE
70 #define AU_HEADERS_LENGTH_SIZE                  2 /* size in bytes */
71 #define DEFAULT_AU_SIZE_LENGTH                  0
72 #define DEFAULT_AU_INDEX_LENGTH                 0
73 #define DEFAULT_AU_INDEX_DELTA_LENGTH           0
74 #define DEFAULT_CTS_DELTA_LENGTH                0
75 #define DEFAULT_DTS_DELTA_LENGTH                0
76 #define DEFAULT_RANDOM_ACCESS_INDICATION        FALSE
77 #define DEFAULT_STREAM_STATE_INDICATION         0
78
79 /* Wireshark ID of the ISMACRYP protocol */
80 static int proto_ismacryp = -1;
81
82 /* parameters set in preferences */
83 static guint    pref_dynamic_payload_type     = 0; /* RTP dynamic payload type */
84 static guint    pref_au_size_length           = DEFAULT_AU_SIZE_LENGTH;            /* default Au size length */
85 static guint    pref_au_index_length          = DEFAULT_AU_INDEX_LENGTH;           /* default Au index length */
86 static guint    pref_au_index_delta_length    = DEFAULT_AU_INDEX_DELTA_LENGTH;     /* default Au index delta length */
87 static guint    pref_cts_delta_length         = DEFAULT_CTS_DELTA_LENGTH;          /* default CTS delta  length */
88 static guint    pref_dts_delta_length         = DEFAULT_DTS_DELTA_LENGTH;          /* default DTS delta  length */
89 static gboolean pref_random_access_indication = DEFAULT_RANDOM_ACCESS_INDICATION;  /* default random access indication */
90 static guint    pref_stream_state_indication  = DEFAULT_STREAM_STATE_INDICATION;   /* default stream state indication */
91 static guint    version_type                  = V11;                               /* default to ISMACryp 1.1 */
92 static guint    mode                          = AVC_VIDEO_MODE;                    /* default codec mode */
93 static gboolean selective_encryption          = DEFAULT_SELECTIVE_ENCRYPTION;      /* default selective encryption flag */
94 static gboolean slice_indication              = DEFAULT_SLICE_INDICATION;          /* default slice indication */
95 static gboolean padding_indication            = DEFAULT_PADDING_INDICATION;        /* default padding indication */
96 static guint    key_indicator_length          = DEFAULT_KEY_INDICATOR_LENGTH;      /* default key indicator length */
97 static gboolean key_indicator_per_au_flag     = DEFAULT_KEY_INDICATOR_PER_AU;      /* default key indicator per au */
98 static guint    iv_length                     = DEFAULT_IV_LENGTH;                 /* default IV length */
99 static guint    delta_iv_length               = DEFAULT_DELTA_IV_LENGTH;           /* default delta IV length */
100 static gboolean pref_user_mode                = FALSE; /* preference user mode instead of RFC3640 mode? */
101 static gboolean override_flag                 = FALSE; /* override use of RTP payload type to deduce ISMACryp version */
102
103 /* */
104
105 static guint    au_size_length                = DEFAULT_AU_SIZE_LENGTH;            /* default Au size length */
106 static guint    au_index_length               = DEFAULT_AU_INDEX_LENGTH;           /* default Au index length */
107 static guint    au_index_delta_length         = DEFAULT_AU_INDEX_DELTA_LENGTH;     /* default Au index delta length */
108 static guint    cts_delta_length              = DEFAULT_CTS_DELTA_LENGTH;          /* default CTS delta  length */
109 static guint    dts_delta_length              = DEFAULT_DTS_DELTA_LENGTH;          /* default DTS delta  length */
110 static gboolean random_access_indication      = DEFAULT_RANDOM_ACCESS_INDICATION;  /* default random access indication */
111 static guint    stream_state_indication       = DEFAULT_STREAM_STATE_INDICATION;   /* default stream state indication */
112 static gboolean user_mode                     = FALSE; /* selected user mode instead of RFC3640 mode? */
113
114 /*static const value_string messagetypenames[] = {};    */
115
116 /* ismacryp Parameter Types */
117 /*static const value_string parametertypenames[] = {}; */
118 static const value_string modetypenames[] = {
119         { AAC_HBR_MODE, "aac-hbr" },
120         { MPEG4_VIDEO_MODE, "mpeg4-video" },
121         { AVC_VIDEO_MODE, "avc-video" },
122         { 0, NULL}
123 };
124 /* The following hf_* variables are used to hold the Wireshark IDs of
125 * our header fields; they are filled out when we call
126 * proto_register_field_array() in proto_register_ismacryp()
127 */
128 /** Kts attempt at defining the protocol */
129 static gint hf_ismacryp = -1;
130 static gint hf_ismacryp_header = -1;
131 static gint hf_ismacryp_au_headers_length = -1;
132 static gint hf_ismacryp_header_length = -1;
133 static gint hf_ismacryp_header_byte = -1;
134 static gint hf_ismacryp_version = -1;
135 static gint hf_ismacryp_length = -1;
136 /* static gint hf_ismacryp_message_type = -1; */
137 static gint hf_ismacryp_message_length = -1;
138 static gint hf_ismacryp_message = -1;
139 static gint hf_ismacryp_parameter = -1;
140 /* static gint hf_ismacryp_parameter_type = -1; */
141 static gint hf_ismacryp_parameter_length = -1;
142 static gint hf_ismacryp_parameter_value = -1;
143 static gint hf_ismacryp_iv = -1;
144 static gint hf_ismacryp_delta_iv = -1;
145 static gint hf_ismacryp_key_indicator = -1;
146 /* static gint hf_ismacryp_delta_iv_length = -1; */
147 static gint hf_ismacryp_au_size = -1;
148 static gint hf_ismacryp_au_index = -1;
149 static gint hf_ismacryp_au_index_delta = -1;
150 static gint hf_ismacryp_cts_delta = -1;
151 static gint hf_ismacryp_cts_flag = -1;
152 static gint hf_ismacryp_dts_flag = -1;
153 static gint hf_ismacryp_dts_delta = -1;
154 static gint hf_ismacryp_rap_flag = -1;
155 static gint hf_ismacryp_au_is_encrypted = -1;
156 static gint hf_ismacryp_slice_start = -1;
157 static gint hf_ismacryp_slice_end = -1;
158 static gint hf_ismacryp_padding_bitcount = -1;
159 static gint hf_ismacryp_padding = -1;
160 static gint hf_ismacryp_reserved_bits = -1;
161 static gint hf_ismacryp_unused_bits = -1;
162 static gint hf_ismacryp_stream_state = -1;
163
164 /* These are the ids of the subtrees that we may be creating */
165 static gint ett_ismacryp = -1;
166 static gint ett_ismacryp_header = -1;
167 static gint ett_ismacryp_header_byte = -1;
168 static gint ett_ismacryp_message = -1;
169
170 /* Informative tree structure is shown here:
171 * TREE  -
172 *       AU Headers Length (2 bytes) - total length of AU header(s)
173 *       - HEADER1
174 *               HEADER BYTE (if present - 1 byte)
175 *                       -AU_is_encrypted (1 bit)
176 *                       -Slice_start (1 bit)
177 *                       -Slice_end (1 bit)
178 *                       -Padding_bitcount (3 bits)
179 *                       -Reserved (2 bits)
180 *               IV (variable length)
181 *               Key Indicator (variable length)
182 *               AU size (if present - variable length)
183 *               AU index (if present - variable length)
184 *               CTS delta (if present - variable length)
185 *               DTS delta (if present - variable length)
186 *               RAP flag (if present - 1 bit)
187 *               Stream State Indication (if present - variable length)
188 *       - HEADER2 if 2nd header present (depends on AU headers length)
189 *               Header Byte (if present - 1 byte)
190 *                       -AU_is_encrypted (1 bit)
191 *                       -Slice_start (1 bit)
192 *                       -Slice_end (1 bit)
193 *                       -Padding_bitcount (3 bits)
194 *                       -Reserved (2 bits)
195 *               IV (variable length)
196 *               Key Indicator (variable length)
197 *               AU size (if present - variable length)
198 *               AU index delta(if present - variable length)
199 *               CTS delta (if present - variable length)
200 *               DTS delta (if present - variable length)
201 *               RAP flag (if present - 1 bit)
202 *               Stream State Indication (if present - variable length)
203 *       - more HEADERS if present
204 *       - MESSAGE
205 *               encrypted AU
206 * End informative tree structure
207 */
208
209 /* Note that check coherence of total AU headers length and that calculated from size of parameters defined by default or preferences.
210 * These are found in SDP and vary e.g. between audio and video and depend on ISMACryp encoding parameters
211 * hence if these values are incorrect displayed values will be strange and can see errors
212 * this could be improved of course
213 */
214
215 /* dissect_ismacryp_v11 gets called if rtp_dyn_payload_type = "enc-mpeg4-generic" i.e. is set via SDP */
216 static void dissect_ismacryp_v11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
217 {
218         /* display ISMACryp version */
219         col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11);
220
221         /* display RTP payload type */
222         col_set_str(pinfo->cinfo, COL_INFO, "(PT=enc-mpeg4-generic)");
223
224         dissect_ismacryp_common( tvb, pinfo, tree, V11);
225 }
226
227 /* dissect_ismacryp_v20 gets called if rtp_dyn_payload_type = "enc-isoff-generic" i.e. is set via SDP */
228 static void dissect_ismacryp_v20(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
229 {
230         /* display ISMACryp version */
231         col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20);
232
233         /* display RTP payload type */
234         col_set_str(pinfo->cinfo, COL_INFO, "(PT=enc-isoff-generic)");
235
236         dissect_ismacryp_common( tvb, pinfo, tree, V20);
237 }
238
239 static void dissect_ismacryp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
240 {
241         col_set_str(pinfo->cinfo, COL_INFO, "Manual version");
242         dissect_ismacryp_common( tvb, pinfo, tree, version_type);   /* Unknown version type: Use preference */
243 }
244
245 static void dissect_ismacryp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint ismacryp_version)
246 {
247         guint set_version;           /* ISMACryp version used during dissection */
248         proto_item *ismacryp_item;
249         proto_tree *ismacryp_tree;
250         proto_tree *ismacryp_message_tree;
251
252         /* select and display ISMACryp version */
253         if ((ismacryp_version!=version_type) && override_flag){
254                 /* override -> use manual preference setting */
255                 col_append_str(pinfo->cinfo, COL_INFO, " Manual version");
256                 set_version = version_type; /* set to preference value */
257         }
258         else {
259                 set_version = ismacryp_version;
260         }
261
262         if (set_version == V11){
263                 if (check_col(pinfo->cinfo, COL_PROTOCOL))
264                         col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_11);
265                 /* display mode */
266                 if (pref_user_mode == FALSE){
267                         if (check_col( pinfo->cinfo, COL_INFO))
268                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",val_to_str(mode, modetypenames, "user mode"));
269                 }
270                 if (pref_user_mode == TRUE){
271                         if ( check_col( pinfo->cinfo, COL_INFO))
272                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s","user mode");
273                 }
274                 user_mode = pref_user_mode;
275         }
276         if (set_version == V20){
277                 if (check_col(pinfo->cinfo, COL_PROTOCOL))
278                         col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_ISMACRYP_20);
279                 user_mode = TRUE;
280                 /* display mode */
281                 if (check_col( pinfo->cinfo, COL_INFO))
282                         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s","user mode");
283         }
284         /* select correct AU values depending on version & selected mode in preferences menu if not in user_mode */
285         if (user_mode == TRUE){ /* use values set in preference menu */
286                 au_size_length = pref_au_size_length;
287                 au_index_length = pref_au_index_length;
288                 au_index_delta_length = pref_au_index_delta_length;
289                 cts_delta_length = pref_cts_delta_length;
290                 dts_delta_length = pref_dts_delta_length;
291                 random_access_indication = pref_random_access_indication;
292                 stream_state_indication = pref_stream_state_indication;
293         } /* end if user_mode == TRUE */
294         if (user_mode == FALSE){
295                 switch (mode){
296                         case AAC_HBR_MODE:
297                                 au_size_length = 13;
298                                 au_index_length = 3;
299                                 au_index_delta_length = 3;
300                                 cts_delta_length = 0;
301                                 dts_delta_length = 0;
302                                 random_access_indication = FALSE;
303                                 stream_state_indication = 0;
304                                 break;
305                         case MPEG4_VIDEO_MODE:
306                                 au_size_length = 0;
307                                 au_index_length = 0;
308                                 au_index_delta_length = 0;
309                                 cts_delta_length = 0;
310                                 dts_delta_length = 22;
311                                 random_access_indication = TRUE;
312                                 stream_state_indication = 0;
313                                 break;
314                         case AVC_VIDEO_MODE:
315                                 au_size_length = 0;
316                                 au_index_length = 0;
317                                 au_index_delta_length = 0;
318                                 cts_delta_length = 0;
319                                 dts_delta_length = 22;
320                                 random_access_indication = TRUE;
321                                 stream_state_indication = 0;
322                                 break;
323                         default:
324                                 DISSECTOR_ASSERT_NOT_REACHED();
325                                 break;
326                 } /* end switch */
327         } /* end if user_mode == FALSE */
328
329         /* navigate through buffer */
330         if (tree)
331         {
332                 /* we are being asked for details */
333
334                 guint16 au_headers_length = 0; /* total length of AU headers */
335                 guint16 totalbits =0;          /* keeps track of total number of AU header bits treated (used to determine end of AU headers) */
336                 int deltabits = -1;            /* keeps track of extra bits per AU header treated (used to determine end of AU heafers ) */
337                 guint16 totalbit_offset = 0;   /* total offset in bits*/
338                 int nbpadding_bits = 0;        /* number of padding bits*/
339                 offset_struct s_offset;
340                 offset_struct* poffset;
341                 guint16 nbmessage_bytes = 0;   /*nb of message data bytes */
342                 s_offset.offset_bytes = 0;     /* initialise byte offset */
343                 s_offset.offset_bits = 0;      /* initialise bit offset */
344                 poffset = &s_offset;
345
346                 ismacryp_item = proto_tree_add_item(tree, proto_ismacryp, tvb, 0, -1, FALSE);
347                 ismacryp_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp);
348                 proto_item_append_text(tree, ", %s", "ismacryp packet"); /* add text to tree */
349
350                 /* ismacryp_tree analysis */
351                 /* we are being asked for details */
352                 /* get total length of AU headers (first 2 bytes) */
353                 ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_au_headers_length,
354                                                     tvb, poffset->offset_bytes, AU_HEADERS_LENGTH_SIZE, FALSE );
355                 proto_item_append_text(ismacryp_item, " (bits)"); /* add text to AU Header tree indicating length */
356                 au_headers_length=tvb_get_ntohs(tvb,poffset->offset_bytes); /* 2 byte au headers length */
357                 poffset->offset_bytes+=AU_HEADERS_LENGTH_SIZE;
358                 /* ADD HEADER(S) BRANCH  */
359
360                 /* AU Header loop */
361                 totalbits=(poffset->offset_bytes*8)+poffset->offset_bits;
362                 while( ((totalbits-8*AU_HEADERS_LENGTH_SIZE)<au_headers_length) && deltabits!=0 ) /* subtract AU headers length bits*/
363                 {
364                         poffset=dissect_auheader( tvb, poffset, pinfo, ismacryp_tree, set_version);
365                         deltabits=(poffset->offset_bytes*8)+poffset->offset_bits - totalbits; /* if zero this means no actual AU header so exit while loop */
366                         totalbits+=deltabits;
367                 }
368                 /* reached end of AU Header(s) */
369                 /* sanity check if actual total AU headers length in bits i.e. totalbits is */
370                 /*  the same as expected AU headers length from 2 bytes at start of buffer */
371                 if ( (totalbits-8*AU_HEADERS_LENGTH_SIZE) != au_headers_length) /* something wrong */
372                 {
373                         proto_item_append_text(ismacryp_item,
374                                                " Error - expected total AU headers size (%d bits) "
375                                                "does not match calculated size (%d bits) - check parameters!",
376                                                au_headers_length,(totalbits-8*AU_HEADERS_LENGTH_SIZE));
377                 }
378                 /* add padding if need to byte align */
379                 if (poffset->offset_bits!=0)
380                 {
381                         totalbit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
382                         nbpadding_bits = (8-poffset->offset_bits); /* number of padding bits for byte alignment */
383                         ismacryp_item = proto_tree_add_bits_item(ismacryp_tree, hf_ismacryp_padding,
384                                                                  tvb, totalbit_offset, nbpadding_bits , FALSE); /* padding bits */
385                         proto_item_append_text(ismacryp_item, ": Length=%d bits",nbpadding_bits); /* add padding info */
386                         add_bits(poffset, nbpadding_bits);
387                 }
388                 /* ADD MESSAGE BRANCH  */
389                 ismacryp_item = proto_tree_add_item( ismacryp_tree, hf_ismacryp_message,
390                                                      tvb, poffset->offset_bytes, -1, ENC_NA );
391                 ismacryp_message_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_message);
392                 proto_item_append_text(ismacryp_item, ", %s", "Encrypted data"); /* add text to Message tree */
393                 nbmessage_bytes = tvb_reported_length_remaining(tvb, poffset->offset_bytes);
394                 proto_item_append_text(ismacryp_item, ", Length= %d bytes", nbmessage_bytes ); /* add length of message */
395
396                 /* ismacryp message tree analysis (encrypted AUs) */
397                 if (ismacryp_message_tree)
398                 {       /* we are being asked for details */
399                         poffset->offset_bytes+= nbmessage_bytes;        /* */
400                 }  /* end message details */
401                 /* end ismacryp tree details */
402         } /* end if tree */
403 }
404 /* AU Header dissection */
405 static offset_struct* dissect_auheader( tvbuff_t *tvb, offset_struct *poffset, packet_info *pinfo, proto_tree *ismacryp_tree, guint set_version )
406 {
407         proto_item *ismacryp_item;
408         proto_tree *ismacryp_header_tree;
409         proto_tree *ismacryp_header_byte_tree;
410
411         guint16 header_len_bytes = 0; /* total length of non-first AU header in bytes (rounded up) */
412         gint header_len = 0; /* length of AU headers in bits */
413         gint cts_flag =0;
414         gint dts_flag =0;
415         gboolean first_au_flag=FALSE;
416         gint bit_offset = 0;
417
418         /*first determine total AU header length */
419         /* calculate each AU header length in bits first */
420         switch (set_version) {
421                 case V11:
422                         if (selective_encryption)
423                                 header_len+=8; /* add one byte to header length */
424                         break;
425                 case V20:
426                         if (selective_encryption || slice_indication || padding_indication)
427                                 header_len+=8; /* add one byte to header length */
428                         break;
429                 default:
430                         DISSECTOR_ASSERT_NOT_REACHED();
431                         break;
432         }       /* end switch */
433         header_len+=au_size_length; /* add au size length */
434
435         if (poffset->offset_bytes==AU_HEADERS_LENGTH_SIZE){     /*first AU */
436                 header_len+=8*(iv_length);                      /* add IV length */
437                 header_len+=8*key_indicator_length;             /* add key indicator length */
438                 header_len+=au_index_length;                    /* add AU index length */
439                 first_au_flag = TRUE;
440         }
441         else { /* not the first AU */
442                 if (key_indicator_per_au_flag == TRUE)
443                         header_len+=8*key_indicator_length; /* add key indicator length */
444                 header_len+=8*(delta_iv_length);                /* add delta IV length */
445                 header_len+=au_index_delta_length;              /* add AU delta index length */
446         }
447         /* CTS flag is present? */
448         if (cts_delta_length != 0){    /* need to test whether cts_delta_flag is TRUE or FALSE */
449                 cts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit CTS flag  */
450                 header_len+=1;         /* add CTS flag bit */
451                 if (cts_flag==1)
452                         header_len+=cts_delta_length; /* add CTS delta length bits if CTS flag SET */
453         }
454         /* DTS flag is present? */
455         if (dts_delta_length != 0){ /* need to test whether dts_delta_flag is TRUE or FALSE */
456                 dts_flag=tvb_get_bits8(tvb, AU_HEADERS_LENGTH_SIZE*8+header_len, 1); /*fetch 1 bit DTS flag */
457                 header_len+=1;      /* add DTS flag bit */
458                 if (dts_flag==1)
459                         header_len+=dts_delta_length; /* add DTS delta length bits if DTS flag SET */
460         }
461         /* RAP flag present? */
462         if (random_access_indication != FALSE)
463                 header_len+=1;      /* add 1 bit RAP flag */
464
465         /* stream state indication present */
466         if (stream_state_indication !=0)
467                 header_len+=stream_state_indication; /* add stream state indication bits */
468
469         /* convert header_len to bytes (rounded up) */
470         if (header_len% 8!=0)
471         {
472                 header_len_bytes=((header_len)/8)+1; /*add 1 */
473         }
474         else
475                 header_len_bytes=((header_len)/8);
476
477         /* add AU header tree  */
478         ismacryp_item = proto_tree_add_item(ismacryp_tree, hf_ismacryp_header, tvb, poffset->offset_bytes, header_len_bytes, ENC_NA );
479         proto_item_append_text(ismacryp_item, ": Length=%d bits", header_len); /* add text to Header tree indicating length */
480         /* sanity check if actual AU header length is zero bits, which indicates an error */
481         if ( header_len == 0) /* something wrong */
482         {
483                 proto_item_append_text(ismacryp_item, " Error - zero bit AU header size - check parameters!");
484         }
485         ismacryp_header_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header);
486
487         /* ismacryp header analysis */
488         /* we are being asked for details  */
489
490         /* Extra 1 Byte Header? */
491
492         if ((set_version==V20 && (selective_encryption || slice_indication || padding_indication))
493                 || (set_version==V11 && selective_encryption)){
494
495                 /* add  header byte tree        */
496                 ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_header_byte,
497                                                     tvb, poffset->offset_bytes, 1, ENC_NA );
498                 proto_item_append_text(ismacryp_item, ": Length=8 bits"); /* add text to Header byte tree indicating length */
499                 ismacryp_header_byte_tree = proto_item_add_subtree(ismacryp_item, ett_ismacryp_header_byte);
500
501                 /*ismacryp_header_byte_tree */
502                 /* we are being asked for details */
503                 /* tvb is network order, so get MSB bits first, so shift 8 bits and work "backwards" */
504                 add_bits(poffset,7);   /*shift 7 bits to get correct bit */
505                 /* AU_is_encrypted bit */
506                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
507                 if (selective_encryption){ /* bit used */
508                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_au_is_encrypted,
509                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit AU_is_encrypted */
510                 }
511                 else { /* bit unused */
512                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
513                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */
514                 }
515                 switch (set_version){ /* ISMACryp version? */
516                         case V11:
517                                 /* Reserved bits */
518                                 add_bits(poffset, -7); /* move back 7 bits for reserved bits */
519                                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
520                                 proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
521                                                          tvb, bit_offset, 7, FALSE); /*fetch 7 bits reserved */
522                                 add_bits(poffset,8);   /* offset to next byte */
523                                 break;
524                         case V20:
525                                 /* Slice_start bit */
526                                 add_bits(poffset, -1); /* move back 1 bit for slice_start */
527                                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
528                                 if (slice_indication){
529                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_start,
530                                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit slice_start */
531                                 }
532                                 else { /* bit unused */
533                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
534                                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */
535                                 }
536                                 add_bits(poffset, -1); /* move back 1 bit for slice_end */
537
538                                 /* Slice_end bit */
539                                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
540                                 if (slice_indication){
541                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_slice_end,
542                                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit Slice_end */
543                                 }
544                                 else { /* bit unused */
545                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
546                                                                  tvb, bit_offset, 1, FALSE); /*fetch 1 bit unused */
547                                 }
548                                 add_bits(poffset, -3); /* move back 3 bits for padding_bitcount */
549
550                                 /* Padding_bitcount bits */
551                                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
552                                 if (padding_indication){
553                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_padding_bitcount,
554                                                                  tvb, bit_offset, 3, FALSE); /*fetch 3 bits padding_bitcount */
555                                 }
556                                 else { /* bits unused */
557                                         proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_unused_bits,
558                                                                  tvb, bit_offset, 3, FALSE); /*fetch 3 bits unused */
559                                 }
560                                 add_bits(poffset, -2); /* move back 2 bits for reserved bits */
561
562                                 /* Reserved bits */
563                                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
564                                 proto_tree_add_bits_item(ismacryp_header_byte_tree, hf_ismacryp_reserved_bits,
565                                                          tvb, bit_offset, 2, FALSE); /*fetch 2 bits reserved */
566                                 add_bits(poffset,8); /* offset to next byte */
567                                 break;
568                         default:
569                                 DISSECTOR_ASSERT_NOT_REACHED();
570                                 break;
571                 } /* end switch set_version */
572         } /* end selective encryption */
573         /* IV */
574         if (first_au_flag == TRUE && iv_length != 0)
575         {
576                 ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_iv, tvb, poffset->offset_bytes, iv_length, FALSE);
577                 proto_item_append_text(ismacryp_item, ": Length=%d bytes",iv_length); /* add IV info */
578                 if ( check_col( pinfo->cinfo, COL_INFO) ) {
579                         col_append_fstr( pinfo->cinfo, COL_INFO,
580                         ", IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, iv_length,' '));
581                 }
582                 poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */
583         }
584         /*Delta  IV */
585         if (first_au_flag == FALSE && delta_iv_length != 0)
586         {
587                 ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_delta_iv,
588                                                     tvb, poffset->offset_bytes, delta_iv_length, FALSE);
589                 proto_item_append_text(ismacryp_item, ": Length=%d bytes",delta_iv_length); /* add delta IV info */
590                 if ( check_col( pinfo->cinfo, COL_INFO) ) {
591                         col_append_fstr( pinfo->cinfo, COL_INFO,
592                         ", Delta IV=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, delta_iv_length,' '));
593                 }
594                 poffset->offset_bytes+=iv_length; /* add IV length to offset_bytes */
595         }
596         /* Key Indicator */
597         if ( key_indicator_length != 0 && ( first_au_flag == TRUE || key_indicator_per_au_flag == TRUE) )
598         {
599                 /* (first AU or KI for each AU) and non-zero KeyIndicator size */
600                 ismacryp_item = proto_tree_add_item(ismacryp_header_tree, hf_ismacryp_key_indicator,
601                                                     tvb, poffset->offset_bytes, key_indicator_length, FALSE);
602                 proto_item_append_text(ismacryp_item,": Length=%d bytes",key_indicator_length); /* add KI info */
603                 if ( check_col( pinfo->cinfo, COL_INFO) ) {
604                         col_append_fstr( pinfo->cinfo, COL_INFO,
605                                          ", KI=0x%s", tvb_bytes_to_str_punct(tvb, poffset->offset_bytes, key_indicator_length,' '));
606                 }
607                 poffset->offset_bytes+=key_indicator_length; /* add KI length to offset_bytes */
608         }
609         /* AU size */
610         if (au_size_length != 0) /* in bits */
611         {
612                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
613                 ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_size,
614                                                          tvb, bit_offset, au_size_length, FALSE);
615                 proto_item_append_text(ismacryp_item, " bytes: Length=%d bits",au_size_length); /* add AU size info */
616                 bit_offset+=au_size_length;
617                 add_bits(poffset, au_size_length);
618         }
619         /* AU Index */
620         if (first_au_flag == TRUE && au_index_length != 0) /* first AU and non-zero AU size */
621         {
622                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
623                 ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index,
624                                                          tvb, bit_offset, au_index_length, FALSE);
625                 proto_item_append_text(ismacryp_item, " bits: Length=%d bits",au_index_length); /* add AU index info */
626                 bit_offset+=au_index_length;
627                 add_bits(poffset, au_index_length);
628         }
629         /* AU index delta */
630         if (first_au_flag == FALSE && au_index_delta_length != 0) /* not first AU and non-zero AU delta size */
631         {
632                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
633                 ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree,hf_ismacryp_au_index_delta,
634                                                          tvb, bit_offset, au_index_delta_length, FALSE);
635                 proto_item_append_text(ismacryp_item, ": Length=%d bits", au_index_delta_length); /* add AU index info */
636                 bit_offset+=au_index_delta_length;
637                 add_bits(poffset, au_index_delta_length);
638         }
639         /* CTS delta value */
640         if (cts_delta_length != 0)
641         {
642                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
643                 proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_flag,
644                                          tvb, bit_offset, 1, FALSE); /* read CTS flag */
645                 add_bits(poffset, 1);
646                 if (cts_flag==1)
647                 {
648                         /* now fetch CTS delta value (remember offset 1 bit due to CTS flag) */
649                         bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
650                         ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_cts_delta,
651                                                                  tvb, bit_offset, cts_delta_length, FALSE); /* read CTS delta value */
652                         proto_item_append_text(ismacryp_item, ": Length=%d bits",cts_delta_length); /* add CTS delta info */
653                         add_bits(poffset, cts_delta_length);
654                 }
655         }
656         /* DTS delta value */
657         if (dts_delta_length != 0)
658         {
659                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
660                 proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_flag,
661                                          tvb, bit_offset, 1, FALSE); /* read DTS flag */
662                 add_bits(poffset, 1);
663
664                 /* now fetch DTS delta value (remember offset x bits due to DTS flag) */
665                 if (dts_flag ==1)
666                 {
667                         bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
668                         ismacryp_item = proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_dts_delta,
669                                                                  tvb, bit_offset, dts_delta_length, FALSE); /* read DTS delta value */
670                         proto_item_append_text(ismacryp_item, ": Length=%d bits",dts_delta_length); /* add DTS delta info */
671                         add_bits(poffset, dts_delta_length);
672                 }
673         }
674         /* RAP */
675         if (random_access_indication != FALSE)
676         {
677                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
678                 proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_rap_flag,
679                                          tvb, bit_offset, 1, FALSE); /* read RAP flag */
680                 add_bits(poffset, 1);
681         }
682         /*STREAM STATE */
683         if (stream_state_indication != 0)
684         {
685                 bit_offset = (poffset->offset_bytes)*8+poffset->offset_bits; /* offset in bits */
686                 proto_tree_add_bits_item(ismacryp_header_tree, hf_ismacryp_stream_state,
687                                          tvb, bit_offset, stream_state_indication, FALSE); /* read stream state */
688                 add_bits(poffset, stream_state_indication);
689         }
690         /* end header details */
691 return poffset;
692 }
693
694 /* add len_bits to offset bits and  bytes, handling bits overflow */
695 static void add_bits(offset_struct* poffset, gint len_bits)
696 {
697         gint nbbitstotal=0;
698         nbbitstotal=poffset->offset_bytes*8+(poffset->offset_bits)+len_bits; /* total offset in bits */
699         /* now calculate bytes and bit offsets */
700         poffset->offset_bytes=(nbbitstotal / 8); /* add integer no. of bytes */
701         poffset->offset_bits=(nbbitstotal % 8); /* add remaining bits */
702 }
703
704 void proto_register_ismacryp (void)
705 {
706         /* A header field is something you can search/filter on.
707         *
708         * We create a structure to register our fields. It consists of an
709         * array of hf_register_info structures, each of which are of the format
710         * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
711         */
712         static hf_register_info hf[] = {
713                 { &hf_ismacryp,
714                   { "Data", "ismacryp.data", FT_NONE, BASE_NONE, NULL, 0x0,
715                     NULL, HFILL }},
716
717                 { &hf_ismacryp_length,
718                   { "Total Length", "ismacryp.len", FT_UINT16, BASE_DEC, NULL, 0x0,     /* length 2 bytes, print as decimal value */
719                     NULL, HFILL }},
720
721                 { &hf_ismacryp_header,
722                   { "AU Header", "ismacryp.header", FT_NONE, BASE_NONE, NULL, 0x0,
723                     NULL, HFILL }},
724
725                 { &hf_ismacryp_header_length,
726                   { "Header Length", "ismacryp.header.length", FT_UINT16, BASE_DEC, NULL, 0x0,
727                     NULL, HFILL }},
728
729                 { &hf_ismacryp_au_headers_length,
730                   { "AU Headers Length", "ismacryp.au_headers.length", FT_UINT16, BASE_DEC, NULL, 0x0,
731                     NULL, HFILL }},
732
733                 { &hf_ismacryp_header_byte,
734                   { "Header Byte", "ismacryp.header.byte", FT_NONE, BASE_NONE, NULL, 0x0, /* 1 byte */
735                     NULL, HFILL }},
736 #if 0
737                 { &hf_ismacryp_header_byte,
738                   { "Header Byte", "ismacryp.header.byte", FT_NONE, BASE_NONE, NULL, 0x0,
739                     NULL, HFILL }},
740 #endif
741
742                 { &hf_ismacryp_version,
743                   { "Version", "ismacryp.version", FT_UINT8, BASE_HEX, NULL, 0x0,       /* version 1 byte */
744                     NULL, HFILL }},
745
746                 { &hf_ismacryp_message,
747                   { "Message", "ismacryp.message", FT_NONE, BASE_NONE, NULL, 0x0,
748                     NULL, HFILL }},
749
750                 { &hf_ismacryp_message_length,
751                   { "Message Length", "ismacryp.message.len", FT_UINT16, BASE_DEC, NULL, 0x0,   /* length 2 bytes, print as decimal value */
752                     NULL, HFILL }},
753
754                 { &hf_ismacryp_parameter,
755                   { "Parameter", "ismacryp.parameter", FT_NONE, BASE_NONE, NULL, 0x0,
756                     NULL, HFILL }},
757
758                 { &hf_ismacryp_parameter_length,
759                   { "Parameter Length", "ismacryp.parameter.len", FT_UINT16, BASE_DEC, NULL, 0x0, /* length 2 bytes, print as decimal value */
760                     NULL, HFILL }},
761
762                 { &hf_ismacryp_iv,
763                   { "IV", "ismacryp.iv", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
764                     NULL, HFILL }},
765
766                 { &hf_ismacryp_delta_iv,
767                   { "Delta IV", "ismacryp.delta_iv", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
768                     NULL, HFILL }},
769
770                 { &hf_ismacryp_key_indicator,
771                   { "Key Indicator", "ismacryp.key_indicator", FT_BYTES, BASE_NONE, NULL, 0x0, /* variable length */
772                     NULL, HFILL }},
773
774                 { &hf_ismacryp_parameter_value,
775                   { "Parameter Value", "ismacryp.parameter.value", FT_NONE, BASE_NONE, NULL, 0x0,
776                     NULL, HFILL }},
777
778                 { &hf_ismacryp_au_size,
779                   { "AU size", "ismacryp.au.size", FT_UINT64, BASE_DEC, NULL, 0x0,
780                     NULL, HFILL }},
781
782                 { &hf_ismacryp_au_index,
783                   { "AU index", "ismacryp.au.index", FT_UINT64, BASE_DEC, NULL, 0x0,
784                     NULL, HFILL }},
785
786                 { &hf_ismacryp_au_index_delta,
787                   { "AU index delta", "ismacryp.au.index_delta", FT_UINT64, BASE_DEC, NULL, 0x0,
788                     NULL, HFILL }},
789
790                 { &hf_ismacryp_cts_delta,
791                   { "CTS delta", "ismacryp.cts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
792                     NULL, HFILL }},
793
794                 { &hf_ismacryp_cts_flag,
795                   { "CTS flag", "ismacryp.cts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
796                     NULL, HFILL }},
797
798                 { &hf_ismacryp_dts_delta,
799                   { "DTS delta", "ismacryp.dts_delta", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
800                     NULL, HFILL }},
801
802                 { &hf_ismacryp_dts_flag,
803                   { "DTS flag", "ismacryp.dts_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
804                     NULL, HFILL }},
805
806                 { &hf_ismacryp_rap_flag,
807                   { "RAP flag", "ismacryp.rap_flag", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
808                     NULL, HFILL }},
809
810                 { &hf_ismacryp_stream_state,
811                   { "Stream state", "ismacryp.stream_state", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
812                     NULL, HFILL }},
813
814                 { &hf_ismacryp_au_is_encrypted,
815                   { "AU_is_encrypted flag", "ismacryp.au_is_encrypted", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
816                     NULL, HFILL }},
817
818                 { &hf_ismacryp_slice_start,
819                   { "Slice_start flag", "ismacryp.slice_start", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
820                     NULL, HFILL }},
821
822                 { &hf_ismacryp_slice_end,
823                   { "Slice_end flag", "ismacryp.slice_end", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
824                     NULL, HFILL }},
825
826                 { &hf_ismacryp_padding_bitcount,
827                   { "Padding_bitcount bits", "ismacryp.padding_bitcount", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
828                     NULL, HFILL }},
829
830                 { &hf_ismacryp_padding,
831                   { "Padding bits", "ismacryp.padding", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
832                     NULL, HFILL }},
833
834                 { &hf_ismacryp_reserved_bits,
835                   { "Reserved bits", "ismacryp.reserved", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
836                     NULL, HFILL }},
837
838                 { &hf_ismacryp_unused_bits,
839                   { "Unused bits", "ismacryp.unused", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
840                     NULL, HFILL }}
841         };
842
843         static gint *ett[] =
844         {
845                 &ett_ismacryp,
846                 &ett_ismacryp_header,
847                 &ett_ismacryp_header_byte,
848                 &ett_ismacryp_message
849         };
850
851         static enum_val_t version_types[] = {
852                 {PROTO_TAG_ISMACRYP_11, "ISMACryp v1.1", V11},
853                 {PROTO_TAG_ISMACRYP_20, "ISMACryp v2.0", V20},
854                 {NULL, NULL, -1}
855         };
856
857         static enum_val_t mode_types[] = {
858                 {"aac-hbr", "aac-hbr", AAC_HBR_MODE},
859                 {"mpeg4-video", "mpeg4-video", MPEG4_VIDEO_MODE},
860                 {"avc-video", "avc-video", AVC_VIDEO_MODE},
861                 {NULL, NULL, -1}
862         };
863
864         module_t *ismacryp_module;
865
866         proto_ismacryp = proto_register_protocol ("ISMACryp Protocol", "ISMACRYP", "ismacryp");
867         proto_register_field_array (proto_ismacryp, hf, array_length (hf));
868         proto_register_subtree_array (ett, array_length (ett));
869
870         /* Register our configuration options for ismacryp */
871         /* this registers our preferences, function proto_reg_handoff_ismacryp is called when preferences are applied */
872         ismacryp_module = prefs_register_protocol(proto_ismacryp, proto_reg_handoff_ismacryp);
873
874         prefs_register_uint_preference(ismacryp_module, "dynamic.payload.type",
875                                                            "ISMACryp dynamic payload type",
876                                                            "The dynamic payload type which will be interpreted as ISMACryp",
877                                                            10,
878                                                            &pref_dynamic_payload_type);
879
880         prefs_register_enum_preference(ismacryp_module, "version",
881                                                "ISMACryp version",
882                                                "ISMACryp version",
883                                                &version_type, version_types, TRUE);
884
885         prefs_register_static_text_preference(ismacryp_module, "text_override",
886                                               "The following option allows the version to be set manually"
887                                               " and to override the version if detected from RTP payload type:",
888                                               "The following option allows the version to be set manually"
889                                               " and to override the version if detected from RTP payload type:");
890
891         prefs_register_bool_preference(ismacryp_module,
892                                        "override_rtp_pt","Override RTP payload type for version",
893                                        "Indicates whether or not the ISMACryp version deduced"
894                                        " from RTP payload type, if present, is used or whether the"
895                                        " version above is used",
896                                        &override_flag);
897
898         /* ISMACryp v11 parameters */
899         prefs_register_static_text_preference(ismacryp_module,
900                                               "v11_parameters",
901                                               "ISMACryp v1.1 parameters:",
902                                               "ISMACryp v1.1 parameters declared in SDP");
903
904         prefs_register_uint_preference(ismacryp_module,
905                                        "iv_length","ISMACrypIVLength (bytes)",
906                                        "Set the length of the IV in the ISMACryp AU Header in bytes",
907                                        10, &iv_length);
908
909         prefs_register_uint_preference(ismacryp_module,
910                                        "delta_iv_length","ISMACrypDeltaIVLength (bytes)",
911                                        "Set the length of the Delta IV in the ISMACryp AU Header in bytes",
912                                        10, &delta_iv_length);
913
914         prefs_register_uint_preference(ismacryp_module,
915                                        "key_indicator_length","ISMACrypKeyIndicatorLength (bytes)",
916                                        "Set the length of the Key Indicator in the ISMACryp AU Header in bytes",
917                                        10, &key_indicator_length);
918
919         prefs_register_bool_preference(ismacryp_module,
920                                        "key_indicator_per_au_flag","ISMACrypKeyIndicatorPerAU (T/F)",
921                                        "Indicates whether or not the Key Indicator is present in all AU Headers (T/F)",
922                                        &key_indicator_per_au_flag);
923
924         prefs_register_bool_preference(ismacryp_module,
925                                        "selective_encryption","ISMACrypSelectiveEncryption (T/F)",
926                                        "Indicates whether or not selective encryption is enabled (T/F)",
927                                        &selective_encryption);
928
929         /* ISMACryp v20 parameters */
930         prefs_register_static_text_preference(ismacryp_module,
931                                               "v20_parameters",
932                                               "ISMACryp v2.0 parameters:",
933                                               "ISMACryp v2.0 parameters declared in SDP");
934
935         prefs_register_bool_preference(ismacryp_module,
936                                        "slice_indication","ISMACrypSliceIndication (T/F)",
937                                        "Indicates whether or not slice start / end is present (T/F)",
938                                        &slice_indication);
939
940         prefs_register_bool_preference(ismacryp_module,
941                                        "padding_indication","ISMACrypPaddingIndication (T/F)",
942                                        "Indicates whether or not padding information is present (T/F)",
943                                        &padding_indication);
944
945         /* RFC3640 mode - ISMACryp v11 */
946         prefs_register_static_text_preference(ismacryp_module,
947                                               "codec_modes",
948                                               "Codec mode selection (RFC3640 for ISMACryp v1.1 only):",
949                                               "AU parameters set according to RFC3640 mode or user defined");
950
951         prefs_register_enum_preference(ismacryp_module,
952                                        "rfc3640_mode",
953                                        "RFC3640 mode",
954                                        "RFC3640 mode",
955                                        &mode, mode_types, TRUE);
956
957         /* User defined mode */
958         prefs_register_bool_preference(ismacryp_module,
959                                        "user_mode","User mode (T/F)",
960                                        "Indicates use of user mode instead of RFC3640 modes (T/F)",
961                                        &pref_user_mode);
962
963         /* following preference values only used if user mode is selected above */
964         prefs_register_static_text_preference(ismacryp_module,
965                                               "user_defined_modes",
966                                               "Following parameters only valid and used for user mode:",
967                                               "AU parameters defined by the user");
968
969         /* ideally would grey this out or disable this if in user mode */
970         prefs_register_uint_preference(ismacryp_module,
971                                        "au_size_length","User mode: SizeLength (bits)",
972                                        "Set the length of the AU size in the AU Header in bits",
973                                        10, &pref_au_size_length);
974
975         prefs_register_uint_preference(ismacryp_module,
976                                        "au_index_length","User mode: IndexLength (bits)",
977                                        "Set the length of the AU index in the AU Header in bits",
978                                        10, &pref_au_index_length);
979
980         prefs_register_uint_preference(ismacryp_module,
981                                        "au_index_delta_length","User mode: IndexDeltaLength (bits)",
982                                        "Set the length of the AU delta index in the AU Header in bits",
983                                        10, &pref_au_index_delta_length);
984
985         prefs_register_uint_preference(ismacryp_module,
986                                        "cts_delta_length","User mode: CTSDeltaLength (bits)",
987                                        "Set the length of the CTS delta field in the AU Header in bits",
988                                        10, &pref_cts_delta_length);
989
990         prefs_register_uint_preference(ismacryp_module,
991                                        "dts_delta_length","User mode: DTSDeltaLength (bits)",
992                                        "Set the length of the DTS delta field in the AU Header in bits",
993                                        10, &pref_dts_delta_length);
994
995         prefs_register_bool_preference(ismacryp_module,
996                                        "random_access_indication","User mode: RandomAccessIndication (T/F)",
997                                        "Indicates whether or not the RAP field is present in the AU Header (T/F)",
998                                        &pref_random_access_indication);
999
1000         prefs_register_uint_preference(ismacryp_module,
1001                                        "stream_state_indication","User mode: StreamStateIndication (number of bits)",
1002                                        "Indicates the number of bits on which the stream state field is encoded"
1003                                        " in the AU Header (bits)",
1004                                        10, &pref_stream_state_indication);
1005
1006 }
1007
1008 void proto_reg_handoff_ismacryp(void)
1009 {
1010         static gboolean ismacryp_prefs_initialized=FALSE;
1011         static dissector_handle_t ismacryp_handle;
1012         static guint dynamic_payload_type;
1013
1014         if (!ismacryp_prefs_initialized) {
1015                 dissector_handle_t ismacryp_v11_handle;
1016                 dissector_handle_t ismacryp_v20_handle;
1017                 ismacryp_handle = create_dissector_handle(dissect_ismacryp, proto_ismacryp);
1018                 ismacryp_v11_handle = create_dissector_handle(dissect_ismacryp_v11, proto_ismacryp);
1019                 ismacryp_v20_handle = create_dissector_handle(dissect_ismacryp_v20, proto_ismacryp);
1020                 ismacryp_prefs_initialized = TRUE;
1021                 dissector_add_string("rtp_dyn_payload_type", "ISMACRYP", ismacryp_handle);
1022                 dissector_add_string("rtp_dyn_payload_type", "enc-mpeg4-generic", ismacryp_v11_handle);
1023                 dissector_add_string("rtp_dyn_payload_type", "enc-isoff-generic", ismacryp_v20_handle);
1024           }
1025         else { /* ismacryp_prefs_initialized = TRUE */
1026                 /* delete existing association of ismacryp with payload_type */
1027                 if ( dynamic_payload_type > 95 ){
1028                         dissector_delete_uint("rtp.pt", dynamic_payload_type, ismacryp_handle);
1029                 }
1030         }
1031         /* always do the following */
1032         dynamic_payload_type = pref_dynamic_payload_type; /*update payload_type to new value */
1033         if ( dynamic_payload_type > 95 ){
1034                 dissector_add_uint("rtp.pt", dynamic_payload_type, ismacryp_handle);
1035         }
1036
1037 }