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