2003-07-12 22:35:21 +00:00
/*
XXX all this offset > > 3 and calculations of bytes in the tvb everytime
we put something in the tree is just silly . should be replaced with some
2003-10-27 22:28:48 +00:00
proper helper routines
2003-07-12 22:35:21 +00:00
*/
/* packet-per.c
* Routines for dissection of ASN .1 Aligned PER
* 2003 Ronnie Sahlberg
*
2004-07-18 00:24:25 +00:00
* $ Id $
2003-07-12 22:35:21 +00:00
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2003-07-12 22:35:21 +00:00
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2003-07-12 22:35:21 +00:00
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <string.h>
2007-05-03 09:15:04 +00:00
# include <math.h>
2003-07-12 22:35:21 +00:00
2012-05-15 19:23:35 +00:00
# include <glib.h>
# include <epan/packet.h>
2007-08-25 17:29:55 +00:00
# include <epan/oids.h>
2005-04-28 09:54:03 +00:00
# include <epan/to_str.h>
2004-09-27 22:55:15 +00:00
# include <epan/prefs.h>
2005-08-20 02:33:33 +00:00
# include <epan/emem.h>
2007-05-01 22:05:11 +00:00
# include <epan/asn1.h>
2008-03-01 17:23:39 +00:00
# include <epan/strutil.h>
2008-06-19 12:16:26 +00:00
# include <epan/expert.h>
2003-07-12 22:35:21 +00:00
# include "packet-per.h"
static int proto_per = - 1 ;
static int hf_per_GeneralString_length = - 1 ;
static int hf_per_extension_bit = - 1 ;
static int hf_per_extension_present_bit = - 1 ;
2005-09-09 15:36:39 +00:00
static int hf_per_choice_index = - 1 ;
static int hf_per_choice_extension_index = - 1 ;
2006-03-08 13:50:04 +00:00
static int hf_per_enum_index = - 1 ;
static int hf_per_enum_extension_index = - 1 ;
2003-07-12 22:35:21 +00:00
static int hf_per_num_sequence_extensions = - 1 ;
static int hf_per_small_number_bit = - 1 ;
static int hf_per_optional_field_bit = - 1 ;
static int hf_per_sequence_of_length = - 1 ;
static int hf_per_object_identifier_length = - 1 ;
static int hf_per_open_type_length = - 1 ;
2007-05-03 09:15:04 +00:00
static int hf_per_real_length = - 1 ;
2003-07-12 22:35:21 +00:00
static int hf_per_octet_string_length = - 1 ;
2004-02-16 18:31:40 +00:00
static int hf_per_bit_string_length = - 1 ;
2006-09-27 19:30:22 +00:00
static int hf_per_const_int_len = - 1 ;
2007-05-02 12:13:29 +00:00
static int hf_per_direct_reference = - 1 ; /* T_direct_reference */
static int hf_per_indirect_reference = - 1 ; /* T_indirect_reference */
static int hf_per_data_value_descriptor = - 1 ; /* T_data_value_descriptor */
static int hf_per_encoding = - 1 ; /* External_encoding */
static int hf_per_single_ASN1_type = - 1 ; /* T_single_ASN1_type */
static int hf_per_octet_aligned = - 1 ; /* T_octet_aligned */
static int hf_per_arbitrary = - 1 ; /* T_arbitrary */
2009-04-10 09:24:10 +00:00
static int hf_per_integer_length = - 1 ; /* Show integer length if "show internal per fields" */
2011-01-27 15:48:02 +00:00
static int hf_per_debug_pos = - 1 ;
2003-07-12 22:35:21 +00:00
2007-05-14 13:39:31 +00:00
static gint ett_per_open_type = - 1 ;
2007-05-23 13:36:25 +00:00
static gint ett_per_containing = - 1 ;
2003-07-12 22:35:21 +00:00
static gint ett_per_sequence_of_item = - 1 ;
2007-05-02 12:13:29 +00:00
static gint ett_per_External = - 1 ;
static gint ett_per_External_encoding = - 1 ;
2003-07-12 22:35:21 +00:00
/*
# define DEBUG_ENTRY(x) \
2007-04-16 04:52:51 +00:00
printf ( " #%u %s tvb:0x%08x \n " , actx - > pinfo - > fd - > num , x , ( int ) tvb ) ;
2003-07-12 22:35:21 +00:00
*/
# define DEBUG_ENTRY(x) \
;
2005-09-09 15:36:39 +00:00
# define BLEN(old_offset, offset) (((offset)>>3)!=((old_offset)>>3)?((offset)>>3)-((old_offset)>>3):1)
2003-07-12 22:35:21 +00:00
/* whether the PER helpers should put the internal PER fields into the tree
or not .
*/
2005-08-29 13:00:53 +00:00
static gboolean display_internal_per_fields = FALSE ;
2003-07-12 22:35:21 +00:00
static const true_false_string tfs_extension_present_bit = {
" " ,
" "
} ;
static const true_false_string tfs_extension_bit = {
" Extension bit is set " ,
" Extension bit is clear "
} ;
static const true_false_string tfs_small_number_bit = {
" The number is small, 0-63 " ,
" The number is large, >63 "
} ;
static const true_false_string tfs_optional_field_bit = {
" " ,
" "
} ;
2007-05-03 09:15:04 +00:00
# define BYTE_ALIGN_OFFSET(offset) if(offset&0x07){offset=(offset&0xfffffff8)+8;}
2010-10-17 14:07:05 +00:00
static void per_check_value ( guint32 value , guint32 min_len , guint32 max_len , asn1_ctx_t * actx , proto_item * item , gboolean is_signed )
{
if ( ( is_signed = = FALSE ) & & ( value > max_len ) ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: %u (%u .. %u) " , value , min_len , max_len ) ;
} else if ( ( is_signed = = TRUE ) & & ( ( gint32 ) value > ( gint32 ) max_len ) ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: %d (%d .. %d) " , ( gint32 ) value , ( gint32 ) min_len , ( gint32 ) max_len ) ;
}
}
static void per_check_value64 ( guint64 value , guint64 min_len , guint64 max_len , asn1_ctx_t * actx , proto_item * item , gboolean is_signed )
{
if ( ( is_signed = = FALSE ) & & ( value > max_len ) ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: % " G_GINT64_MODIFIER " u (% " G_GINT64_MODIFIER " u .. % " G_GINT64_MODIFIER " u) " , value , min_len , max_len ) ;
} else if ( ( is_signed = = TRUE ) & & ( ( gint64 ) value > ( gint64 ) max_len ) ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: value too big: % " G_GINT64_MODIFIER " d (% " G_GINT64_MODIFIER " d .. % " G_GINT64_MODIFIER " d) " , ( gint64 ) value , ( gint64 ) min_len , ( gint64 ) max_len ) ;
}
}
static void per_check_items ( guint32 cnt , int min_len , int max_len , asn1_ctx_t * actx , proto_item * item )
{
if ( min_len ! = NO_BOUND & & cnt < ( guint32 ) min_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: too few items: %d (%d .. %d) " , cnt , min_len , max_len ) ;
} else if ( max_len ! = NO_BOUND & & cnt > ( guint32 ) max_len ) {
expert_add_info_format ( actx - > pinfo , item , PI_PROTOCOL , PI_WARN , " Size constraint: too many items: %d (%d .. %d) " , cnt , min_len , max_len ) ;
}
}
2008-04-13 16:42:41 +00:00
static tvbuff_t * new_octet_aligned_subset ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , guint32 length )
2007-05-03 09:15:04 +00:00
{
tvbuff_t * sub_tvb = NULL ;
guint32 boffset = offset > > 3 ;
unsigned int i , shift0 , shift1 ;
guint8 octet0 , octet1 , * buf ;
2008-03-18 20:10:50 +00:00
guint32 actual_length ;
2009-10-18 23:19:44 +00:00
/* XXX - why are we doing this? Shouldn't we throw an exception if we've
* been asked to decode more octets than exist ?
*/
2008-03-19 09:14:47 +00:00
actual_length = tvb_length_remaining ( tvb , boffset ) ;
2008-03-18 20:10:50 +00:00
if ( length < = actual_length )
actual_length = length ;
2007-05-03 09:15:04 +00:00
if ( offset & 0x07 ) { /* unaligned */
shift1 = offset & 0x07 ;
shift0 = 8 - shift1 ;
2009-10-06 19:15:58 +00:00
buf = g_malloc ( actual_length ) ;
2007-05-03 09:15:04 +00:00
octet0 = tvb_get_guint8 ( tvb , boffset ) ;
2008-03-18 20:10:50 +00:00
for ( i = 0 ; i < actual_length ; i + + ) {
2007-05-03 09:15:04 +00:00
octet1 = octet0 ;
octet0 = tvb_get_guint8 ( tvb , boffset + i + 1 ) ;
buf [ i ] = ( octet1 < < shift1 ) | ( octet0 > > shift0 ) ;
}
2009-05-13 19:46:11 +00:00
sub_tvb = tvb_new_child_real_data ( tvb , buf , actual_length , length ) ;
2009-10-06 19:15:58 +00:00
tvb_set_free_cb ( sub_tvb , g_free ) ;
2008-04-13 16:42:41 +00:00
add_new_data_source ( actx - > pinfo , sub_tvb , " Unaligned OCTET STRING " ) ;
2007-05-03 09:15:04 +00:00
} else { /* aligned */
2008-03-18 20:10:50 +00:00
sub_tvb = tvb_new_subset ( tvb , boffset , actual_length , length ) ;
2007-05-03 09:15:04 +00:00
}
return sub_tvb ;
}
2003-07-12 22:35:21 +00:00
2006-06-05 06:49:52 +00:00
/* 10 Encoding procedures -------------------------------------------------- */
/* 10.2 Open type fields --------------------------------------------------- */
2009-10-18 23:19:44 +00:00
static guint32
2007-07-13 11:25:53 +00:00
dissect_per_open_type_internal ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , void * type_cb , asn1_cb_variant variant )
2006-06-05 06:49:52 +00:00
{
guint32 type_length , end_offset ;
2007-05-14 14:17:42 +00:00
tvbuff_t * val_tvb = NULL ;
2007-05-14 13:39:31 +00:00
header_field_info * hfi ;
proto_tree * subtree = tree ;
hfi = ( hf_index = = - 1 ) ? NULL : proto_registrar_get_nth ( hf_index ) ;
2006-06-05 06:49:52 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_open_type_length , & type_length ) ;
if ( actx - > aligned ) BYTE_ALIGN_OFFSET ( offset ) ;
end_offset = offset + type_length * 8 ;
2007-05-14 13:39:31 +00:00
if ( ( variant = = CB_DISSECTOR ) | | ( variant = = CB_NEW_DISSECTOR ) ) {
2008-04-13 16:42:41 +00:00
val_tvb = new_octet_aligned_subset ( tvb , offset , actx , type_length ) ;
2007-05-14 13:39:31 +00:00
if ( hfi ) {
if ( IS_FT_UINT ( hfi - > type ) | | IS_FT_INT ( hfi - > type ) ) {
if ( IS_FT_UINT ( hfi - > type ) )
actx - > created_item = proto_tree_add_uint ( tree , hf_index , val_tvb , 0 , type_length , type_length ) ;
else
actx - > created_item = proto_tree_add_int ( tree , hf_index , val_tvb , 0 , type_length , type_length ) ;
proto_item_append_text ( actx - > created_item , plurality ( type_length , " octet " , " octets " ) ) ;
} else {
2012-05-04 16:35:59 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_index , val_tvb , 0 , type_length , ENC_BIG_ENDIAN ) ;
2007-05-14 13:39:31 +00:00
}
subtree = proto_item_add_subtree ( actx - > created_item , ett_per_open_type ) ;
}
}
2007-05-02 12:13:29 +00:00
if ( type_cb ) {
2007-05-14 13:39:31 +00:00
switch ( variant ) {
case CB_ASN1_ENC :
( ( per_type_fn ) type_cb ) ( tvb , offset , actx , tree , hf_index ) ;
break ;
case CB_DISSECTOR :
( ( dissector_t ) type_cb ) ( val_tvb , actx - > pinfo , subtree ) ;
break ;
case CB_NEW_DISSECTOR :
( ( new_dissector_t ) type_cb ) ( val_tvb , actx - > pinfo , subtree ) ;
break ;
2007-05-23 14:31:12 +00:00
case CB_DISSECTOR_HANDLE :
break ;
2007-05-14 13:39:31 +00:00
}
2006-06-05 06:49:52 +00:00
} else {
actx - > created_item = proto_tree_add_text ( tree , tvb , offset > > 3 , BLEN ( offset , end_offset ) , " Unknown Open Type " ) ;
}
return end_offset ;
}
2009-10-18 23:19:44 +00:00
guint32
2007-05-14 13:39:31 +00:00
dissect_per_open_type ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , per_type_fn type_cb )
{
2008-07-26 15:28:04 +00:00
return dissect_per_open_type_internal ( tvb , offset , actx , tree , hf_index , ( void * ) type_cb , CB_ASN1_ENC ) ;
2007-05-14 13:39:31 +00:00
}
2009-10-18 23:19:44 +00:00
guint32
2007-05-14 13:39:31 +00:00
dissect_per_open_type_pdu ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , dissector_t type_cb )
{
2008-07-26 15:28:04 +00:00
return dissect_per_open_type_internal ( tvb , offset , actx , tree , hf_index , ( void * ) type_cb , CB_DISSECTOR ) ;
2007-05-14 13:39:31 +00:00
}
2009-10-18 23:19:44 +00:00
guint32
2007-05-14 13:39:31 +00:00
dissect_per_open_type_pdu_new ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , new_dissector_t type_cb )
{
2008-07-26 15:28:04 +00:00
return dissect_per_open_type_internal ( tvb , offset , actx , tree , hf_index , ( void * ) type_cb , CB_NEW_DISSECTOR ) ;
2007-05-14 13:39:31 +00:00
}
2009-10-18 23:19:44 +00:00
/* 10.9 General rules for encoding a length determinant --------------------
NOTE 1 - ( Tutorial ) The procedures of this subclause are invoked when an explicit length field is needed
for some part of the encoding regardless of whether the length count is bounded above
( by PER - visible constraints ) or not . The part of the encoding to which the length applies may
be a bit string ( with the length count in bits ) , an octet string ( with the length count in octets ) ,
a known - multiplier character string ( with the length count in characters ) , or a list of fields
2006-09-27 19:30:22 +00:00
( with the length count in components of a sequence - of or set - of ) .
2009-10-18 23:19:44 +00:00
NOTE 2 - ( Tutorial ) In the case of the ALIGNED variant if the length count is bounded above by an upper bound
that is less than 64 K , then the constrained whole number encoding is used for the length .
For sufficiently small ranges the result is a bit - field , otherwise the unconstrained length ( " n " say )
2006-09-27 19:30:22 +00:00
is encoded into an octet - aligned bit - field in one of three ways ( in order of increasing size ) :
a ) ( " n " less than 128 ) a single octet containing " n " with bit 8 set to zero ;
b ) ( " n " less than 16 K ) two octets containing " n " with bit 8 of the first octet set to 1 and bit 7 set to zero ;
2009-10-18 23:19:44 +00:00
c ) ( large " n " ) a single octet containing a count " m " with bit 8 set to 1 and bit 7 set to 1.
The count " m " is one to four , and the length indicates that a fragment of the material follows
2006-09-27 19:30:22 +00:00
( a multiple " m " of 16 K items ) . For all values of " m " , the fragment is then followed by another length encoding
for the remainder of the material .
2009-10-18 23:19:44 +00:00
2006-09-27 19:30:22 +00:00
NOTE 3 - ( Tutorial ) In the UNALIGNED variant , if the length count is bounded above by an upper bound that is less
2009-10-18 23:19:44 +00:00
than 64 K , then the constrained whole number encoding is used to encode the length in the minimum number of
bits necessary to represent the range . Otherwise , the unconstrained length ( " n " say ) is encoded into a bit
2006-09-27 19:30:22 +00:00
field in the manner described above in Note 2.
*/
2008-03-18 20:10:50 +00:00
guint32
2006-07-04 06:49:53 +00:00
dissect_per_length_determinant ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx _U_ , proto_tree * tree , int hf_index , guint32 * length )
2003-07-12 22:35:21 +00:00
{
guint8 byte ;
guint32 len ;
2005-08-29 10:43:33 +00:00
proto_item * pi ;
2006-09-27 19:30:22 +00:00
int num_bits ;
2012-08-19 18:15:20 +00:00
int i , bit , str_length , str_index ;
2006-09-27 19:30:22 +00:00
gboolean tmp ;
2003-07-12 22:35:21 +00:00
if ( ! length ) {
length = & len ;
}
/* byte aligned */
2006-09-27 19:30:22 +00:00
if ( actx - > aligned ) {
BYTE_ALIGN_OFFSET ( offset ) ;
byte = tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
} else {
char * str ;
guint32 val ;
2009-10-18 23:19:44 +00:00
2006-09-27 19:30:22 +00:00
val = 0 ;
2012-08-19 18:15:20 +00:00
/* prepare the string (max number of bits + quartet separators + prepended space) */
str_length = 256 + 64 + 1 ;
str = ep_alloc ( str_length + 1 ) ;
str_index = 0 ;
str_length = g_snprintf ( str , str_length + 1 , " " ) ;
2006-09-27 19:30:22 +00:00
for ( bit = 0 ; bit < ( ( int ) ( offset & 0x07 ) ) ; bit + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2006-09-27 19:30:22 +00:00
}
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' . ' ;
2006-09-27 19:30:22 +00:00
}
/* read the bits for the int */
num_bits = 8 ;
for ( i = 0 ; i < num_bits ; i + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2006-09-27 19:30:22 +00:00
}
if ( bit & & ( ! ( bit % 8 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2006-09-27 19:30:22 +00:00
}
bit + + ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & tmp ) ;
val < < = 1 ;
if ( tmp ) {
val | = 1 ;
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 1 ' ;
2009-03-03 22:46:47 +00:00
if ( i = = 0 ) { /* bit 8 is 1, so not a single byte length */
num_bits = 16 ;
}
else if ( i = = 1 & & val = = 3 ) { /* bits 8 and 7 both 1, so unconstrained */
PER_NOT_DECODED_YET ( " 10.9 Unconstrained " ) ;
return offset ;
}
2006-09-27 19:30:22 +00:00
} else {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 0 ' ;
2006-09-27 19:30:22 +00:00
}
}
2012-08-19 18:15:20 +00:00
str [ str_index ] = ' \0 ' ; /* Terminate string */
2009-03-03 22:46:47 +00:00
if ( ( val & 0x80 ) = = 0 & & num_bits = = 8 ) {
2006-09-27 19:30:22 +00:00
* length = val ;
if ( hf_index ! = - 1 ) {
pi = proto_tree_add_uint ( tree , hf_index , tvb , ( offset > > 3 ) - 1 , 1 , * length ) ;
2006-10-19 09:14:27 +00:00
if ( display_internal_per_fields )
proto_item_append_text ( pi , " %s " , str ) ;
else
PROTO_ITEM_SET_HIDDEN ( pi ) ;
2006-09-27 19:30:22 +00:00
}
2009-10-18 23:19:44 +00:00
2006-09-27 19:30:22 +00:00
return offset ;
}
2009-03-03 22:46:47 +00:00
else if ( num_bits = = 16 ) {
* length = val & 0x3fff ;
if ( hf_index ! = - 1 ) {
pi = proto_tree_add_uint ( tree , hf_index , tvb , ( offset > > 3 ) - 1 , 1 , * length ) ;
if ( display_internal_per_fields )
proto_item_append_text ( pi , " %s " , str ) ;
else
PROTO_ITEM_SET_HIDDEN ( pi ) ;
}
2009-10-18 23:19:44 +00:00
2009-03-03 22:46:47 +00:00
return offset ;
}
2006-09-27 19:30:22 +00:00
PER_NOT_DECODED_YET ( " 10.9 Unaligned " ) ;
return offset ;
}
2003-07-12 22:35:21 +00:00
2005-08-29 10:43:33 +00:00
/* 10.9.3.6 */
2003-07-12 22:35:21 +00:00
if ( ( byte & 0x80 ) = = 0 ) {
* length = byte ;
if ( hf_index ! = - 1 ) {
2005-08-29 10:43:33 +00:00
pi = proto_tree_add_uint ( tree , hf_index , tvb , ( offset > > 3 ) - 1 , 1 , * length ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( pi ) ;
2003-07-12 22:35:21 +00:00
}
return offset ;
}
2005-08-29 10:43:33 +00:00
/* 10.9.3.7 */
2003-07-12 22:35:21 +00:00
if ( ( byte & 0xc0 ) = = 0x80 ) {
* length = ( byte & 0x3f ) ;
* length = ( ( * length ) < < 8 ) + tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
if ( hf_index ! = - 1 ) {
2005-08-29 10:43:33 +00:00
pi = proto_tree_add_uint ( tree , hf_index , tvb , ( offset > > 3 ) - 2 , 2 , * length ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( pi ) ;
2003-07-12 22:35:21 +00:00
}
return offset ;
}
2004-05-17 20:03:36 +00:00
PER_NOT_DECODED_YET ( " 10.9.3.8.1 " ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
/* 10.6 normally small non-negative whole number */
2004-02-16 18:31:40 +00:00
static guint32
2006-07-04 06:49:53 +00:00
dissect_per_normally_small_nonnegative_whole_number ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , guint32 * length )
2003-07-12 22:35:21 +00:00
{
2009-04-14 07:38:02 +00:00
gboolean small_number , length_bit ;
2003-07-12 22:35:21 +00:00
guint32 len ;
2005-08-29 10:43:33 +00:00
proto_item * pi ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_normally_small_nonnegative_whole_number " ) ;
if ( ! length ) {
length = & len ;
}
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_small_number_bit , & small_number ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
if ( ! small_number ) {
int i ;
/* 10.6.1 */
* length = 0 ;
for ( i = 0 ; i < 6 ; i + + ) {
2009-04-14 07:38:02 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & length_bit ) ;
2003-07-12 22:35:21 +00:00
* length < < = 1 ;
2009-04-14 07:38:02 +00:00
if ( length_bit ) {
2003-07-12 22:35:21 +00:00
* length | = 1 ;
}
}
if ( hf_index ! = - 1 ) {
2009-04-14 07:38:02 +00:00
pi = proto_tree_add_uint ( tree , hf_index , tvb , ( offset - 6 ) > > 3 , ( offset % 8 < 6 ) ? 2 : 1 , * length ) ;
2005-08-29 11:37:08 +00:00
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( pi ) ;
2003-07-12 22:35:21 +00:00
}
return offset ;
}
/* 10.6.2 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_index , length ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
2003-10-27 22:28:48 +00:00
2003-07-12 22:35:21 +00:00
/* this function reads a GeneralString */
/* currently based on pure guesswork since RFC2833 didnt tell me much
i guess that the PER encoding for this is a normally - small - whole - number
followed by a ascii string .
2003-10-27 22:28:48 +00:00
based on pure guesswork . it looks ok in the only capture i have where
2003-07-12 22:35:21 +00:00
there is a 1 byte general string encoded
*/
guint32
2006-07-04 06:49:53 +00:00
dissect_per_GeneralString ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index )
2003-07-12 22:35:21 +00:00
{
guint32 length ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_GeneralString_length , & length ) ;
2003-07-12 22:35:21 +00:00
2012-05-04 16:35:59 +00:00
proto_tree_add_item ( tree , hf_index , tvb , offset > > 3 , length , ENC_BIG_ENDIAN ) ;
2003-07-12 22:35:21 +00:00
offset + = length * 8 ;
2003-10-27 22:28:48 +00:00
2003-07-12 22:35:21 +00:00
return offset ;
}
2005-04-27 14:17:14 +00:00
/* 17 Encoding the null type */
guint32
2006-07-04 06:49:53 +00:00
dissect_per_null ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx _U_ , proto_tree * tree , int hf_index ) {
2005-04-27 14:17:14 +00:00
proto_item * ti_tmp ;
2012-05-04 16:35:59 +00:00
ti_tmp = proto_tree_add_item ( tree , hf_index , tvb , offset > > 3 , 1 , ENC_BIG_ENDIAN ) ;
2005-04-27 14:17:14 +00:00
proto_item_append_text ( ti_tmp , " : NULL " ) ;
return offset ;
}
2003-07-12 22:35:21 +00:00
/* 19 this function dissects a sequence of */
static guint32
2006-07-04 06:49:53 +00:00
dissect_per_sequence_of_helper ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , per_type_fn func , int hf_index , guint32 length )
2003-07-12 22:35:21 +00:00
{
guint32 i ;
DEBUG_ENTRY ( " dissect_per_sequence_of_helper " ) ;
for ( i = 0 ; i < length ; i + + ) {
guint32 lold_offset = offset ;
proto_item * litem ;
proto_tree * ltree ;
litem = proto_tree_add_text ( tree , tvb , offset > > 3 , 0 , " Item %d " , i ) ;
ltree = proto_item_add_subtree ( litem , ett_per_sequence_of_item ) ;
2006-06-29 15:26:41 +00:00
offset = ( * func ) ( tvb , offset , actx , ltree , hf_index ) ;
2003-07-12 22:35:21 +00:00
proto_item_set_len ( litem , ( offset > > 3 ) ! = ( lold_offset > > 3 ) ? ( offset > > 3 ) - ( lold_offset > > 3 ) : 1 ) ;
}
return offset ;
}
guint32
2006-07-04 06:49:53 +00:00
dissect_per_sequence_of ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * parent_tree , int hf_index , gint ett_index , const per_sequence_t * seq )
2003-07-12 22:35:21 +00:00
{
proto_item * item ;
proto_tree * tree ;
guint32 old_offset = offset ;
guint32 length ;
2005-07-15 15:20:40 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_sequence_of " ) ;
/* semi-constrained whole number for number of elements */
/* each element encoded as 10.9 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , parent_tree , hf_per_sequence_of_length , & length ) ;
2003-07-12 22:35:21 +00:00
2005-07-15 15:20:40 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
if ( IS_FT_UINT ( hfi - > type ) ) {
2010-09-03 10:31:56 +00:00
item = proto_tree_add_uint ( parent_tree , hf_index , tvb , old_offset > > 3 , 0 , length ) ;
2005-07-15 15:20:40 +00:00
proto_item_append_text ( item , ( length = = 1 ) ? " item " : " items " ) ;
} else {
2012-05-04 16:35:59 +00:00
item = proto_tree_add_item ( parent_tree , hf_index , tvb , old_offset > > 3 , 0 , ENC_BIG_ENDIAN ) ;
2005-07-15 15:20:40 +00:00
}
tree = proto_item_add_subtree ( item , ett_index ) ;
2006-06-29 15:26:41 +00:00
offset = dissect_per_sequence_of_helper ( tvb , offset , actx , tree , seq - > func , * seq - > p_id , length ) ;
2003-07-12 22:35:21 +00:00
proto_item_set_len ( item , ( offset > > 3 ) ! = ( old_offset > > 3 ) ? ( offset > > 3 ) - ( old_offset > > 3 ) : 1 ) ;
return offset ;
}
2011-07-18 19:11:32 +00:00
/* XXX we don't do >64k length strings yet */
2005-08-29 10:43:33 +00:00
static guint32
2009-11-22 17:00:45 +00:00
dissect_per_restricted_character_string_sorted ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension _U_ , const char * alphabet , int alphabet_length , tvbuff_t * * value_tvb )
2003-07-13 01:43:33 +00:00
{
guint32 length ;
gboolean byte_aligned ;
2005-09-06 14:18:49 +00:00
guint8 * buf ;
2003-07-16 21:05:12 +00:00
guint char_pos ;
int bits_per_char ;
2003-07-13 01:43:33 +00:00
guint32 old_offset ;
2003-10-27 22:28:48 +00:00
2003-07-13 01:43:33 +00:00
DEBUG_ENTRY ( " dissect_per_restricted_character_string " ) ;
2004-10-11 12:00:08 +00:00
2003-07-13 01:43:33 +00:00
/* xx.x if the length is 0 bytes there will be no encoding */
if ( max_len = = 0 ) {
2005-08-18 14:32:49 +00:00
if ( value_tvb ) {
2009-10-18 23:19:44 +00:00
* value_tvb = tvb_new_child_real_data ( tvb , NULL , 0 , 0 ) ;
2005-02-07 08:57:47 +00:00
}
2003-07-13 01:43:33 +00:00
return offset ;
}
2005-11-14 13:05:17 +00:00
if ( min_len = = NO_BOUND ) {
2003-07-13 01:43:33 +00:00
min_len = 0 ;
}
/* 27.5.2 depending of the alphabet length, find how many bits
are used to encode each character */
2006-09-27 19:30:22 +00:00
/* unaligned PER */
if ( actx - > aligned ) {
if ( alphabet_length < = 2 ) {
bits_per_char = 1 ;
} else if ( alphabet_length < = 4 ) {
bits_per_char = 2 ;
} else if ( alphabet_length < = 16 ) {
bits_per_char = 4 ;
} else {
bits_per_char = 8 ;
}
} else {
if ( alphabet_length < = 2 ) {
bits_per_char = 1 ;
} else if ( alphabet_length < = 4 ) {
bits_per_char = 2 ;
} else if ( alphabet_length < = 8 ) {
bits_per_char = 3 ;
} else if ( alphabet_length < = 16 ) {
bits_per_char = 4 ;
} else if ( alphabet_length < = 32 ) {
bits_per_char = 5 ;
} else if ( alphabet_length < = 64 ) {
bits_per_char = 6 ;
} else if ( alphabet_length < = 128 ) {
bits_per_char = 7 ;
} else {
bits_per_char = 8 ;
}
2003-07-13 01:43:33 +00:00
}
2011-07-18 19:11:32 +00:00
/* 27.4 If the type is extensible for PER encodings (see 9.3.16),
* then a bit - field consisting of a single bit shall be added to the field - list .
2009-11-22 17:00:45 +00:00
* The single bit shall be set to zero if the value is within the range of the extension root ,
2011-07-18 19:11:32 +00:00
* and to one otherwise . If the value is outside the range of the extension root ,
* then the following encoding shall be as if there was no effective size constraint ,
* and shall have an effective permitted - alphabet constraint that consists of the set of characters
2009-11-22 17:00:45 +00:00
* of the unconstrained type .
2011-07-18 19:11:32 +00:00
* NOTE - Only the known - multiplier character string types can be extensible for PER encodings .
2009-11-22 17:00:45 +00:00
* Extensibility markers on other character string types do not affect the PER encoding .
*/
if ( has_extension ) {
gboolean extension_present ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( extension_present ) {
min_len = NO_BOUND ;
max_len = NO_BOUND ;
}
}
2003-07-13 01:43:33 +00:00
2004-10-11 12:00:08 +00:00
byte_aligned = TRUE ;
if ( ( min_len = = max_len ) & & ( max_len < = 2 ) ) {
byte_aligned = FALSE ;
}
2005-11-14 13:05:17 +00:00
if ( ( max_len ! = NO_BOUND ) & & ( max_len < 2 ) ) {
2004-10-11 12:00:08 +00:00
byte_aligned = FALSE ;
}
/* xx.x */
length = max_len ;
2005-11-14 13:05:17 +00:00
if ( max_len = = NO_BOUND ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_octet_string_length , & length ) ;
2004-10-11 12:00:08 +00:00
/* the unconstrained strings are always byte aligned (27.6.3)*/
byte_aligned = TRUE ;
} else if ( min_len ! = max_len ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx ,
2005-08-29 10:43:33 +00:00
tree , hf_per_octet_string_length , min_len , max_len ,
2006-05-22 11:49:50 +00:00
& length , FALSE ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2004-10-11 12:00:08 +00:00
}
2004-10-12 17:51:13 +00:00
if ( ! length ) {
2011-07-18 19:11:32 +00:00
/* there is no string at all, so don't do any byte alignment */
2005-01-17 22:25:36 +00:00
/* byte_aligned=FALSE; */
/* Advance offset to next 'element' */
offset = offset + 1 ; }
2004-10-11 12:00:08 +00:00
2006-09-27 19:30:22 +00:00
if ( ( byte_aligned ) & & ( actx - > aligned ) ) {
2004-10-27 02:34:30 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2004-10-11 12:00:08 +00:00
}
2005-08-18 14:32:49 +00:00
buf = g_malloc ( length + 1 ) ;
2003-07-13 01:43:33 +00:00
old_offset = offset ;
for ( char_pos = 0 ; char_pos < length ; char_pos + + ) {
2003-07-16 21:05:12 +00:00
guchar val ;
2003-07-13 01:43:33 +00:00
int i ;
gboolean bit ;
val = 0 ;
for ( i = 0 ; i < bits_per_char ; i + + ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & bit ) ;
2003-07-13 01:43:33 +00:00
val = ( val < < 1 ) | bit ;
}
2009-10-18 23:19:44 +00:00
/* ALIGNED PER does not do any remapping of chars if
bitsperchar is 8
2004-10-11 12:00:08 +00:00
*/
2012-06-11 13:54:06 +00:00
/* If alphabet is not provided, do not do any remapping either */
if ( ( bits_per_char = = 8 ) | | ( alphabet = = NULL ) ) {
2005-08-18 14:32:49 +00:00
buf [ char_pos ] = val ;
2004-10-11 12:00:08 +00:00
} else {
if ( val < alphabet_length ) {
2005-08-18 14:32:49 +00:00
buf [ char_pos ] = alphabet [ val ] ;
2004-10-11 12:00:08 +00:00
} else {
2005-08-18 14:32:49 +00:00
buf [ char_pos ] = ' ? ' ; /* XXX - how to mark this? */
2004-10-11 12:00:08 +00:00
}
}
2003-07-13 01:43:33 +00:00
}
2005-08-18 14:32:49 +00:00
buf [ char_pos ] = 0 ;
2005-09-06 14:18:49 +00:00
proto_tree_add_string ( tree , hf_index , tvb , ( old_offset > > 3 ) , ( offset > > 3 ) - ( old_offset > > 3 ) , ( char * ) buf ) ;
2005-08-18 14:32:49 +00:00
if ( value_tvb ) {
2009-10-18 23:19:44 +00:00
* value_tvb = tvb_new_child_real_data ( tvb , buf , length , length ) ;
2005-08-18 18:12:55 +00:00
tvb_set_free_cb ( * value_tvb , g_free ) ;
2005-08-18 14:32:49 +00:00
} else {
g_free ( buf ) ;
2005-02-07 08:57:47 +00:00
}
2003-07-13 01:43:33 +00:00
return offset ;
}
2005-08-29 10:43:33 +00:00
static const char *
sort_alphabet ( char * sorted_alphabet , const char * alphabet , int alphabet_length )
{
int i , j ;
char c , c_max , c_min ;
char tmp_buf [ 256 ] ;
if ( ! alphabet_length ) return sorted_alphabet ;
memset ( tmp_buf , 0 , 256 ) ;
c_min = c_max = alphabet [ 0 ] ;
for ( i = 0 ; i < alphabet_length ; i + + ) {
c = alphabet [ i ] ;
2005-08-29 13:00:53 +00:00
tmp_buf [ ( int ) c ] = 1 ;
2005-08-29 10:43:33 +00:00
if ( c > c_max ) c_max = c ;
else if ( c < c_min ) c_min = c ;
}
for ( i = c_min , j = 0 ; i < = c_max ; i + + ) {
if ( tmp_buf [ i ] ) sorted_alphabet [ j + + ] = i ;
}
return sorted_alphabet ;
}
guint32
2009-11-22 17:00:45 +00:00
dissect_per_restricted_character_string ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , const char * alphabet , int alphabet_length , tvbuff_t * * value_tvb )
2005-08-29 10:43:33 +00:00
{
const char * alphabet_ptr ;
char sorted_alphabet [ 128 ] ;
if ( alphabet_length > 127 ) {
alphabet_ptr = alphabet ;
} else {
alphabet_ptr = sort_alphabet ( sorted_alphabet , alphabet , alphabet_length ) ;
}
2009-11-22 17:00:45 +00:00
return dissect_per_restricted_character_string_sorted ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension , alphabet_ptr , alphabet_length , value_tvb ) ;
2005-08-29 10:43:33 +00:00
}
2012-06-11 13:54:06 +00:00
/* dissect a constrained IA5String that consists of the full ASCII set,
i . e . no FROM stuff limiting the alphabet
*/
guint32
dissect_per_IA5String ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension )
{
offset = dissect_per_restricted_character_string_sorted ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension ,
NULL , 128 , NULL ) ;
return offset ;
}
2003-07-13 01:43:33 +00:00
guint32
2009-11-22 17:00:45 +00:00
dissect_per_NumericString ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension )
2003-07-13 01:43:33 +00:00
{
2009-11-22 17:00:45 +00:00
offset = dissect_per_restricted_character_string_sorted ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension ,
2005-08-29 10:43:33 +00:00
" 0123456789 " , 11 , NULL ) ;
2003-07-13 01:43:33 +00:00
return offset ;
}
2003-07-19 03:45:04 +00:00
guint32
2009-11-22 17:00:45 +00:00
dissect_per_PrintableString ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension )
2003-07-19 03:45:04 +00:00
{
2009-11-22 17:00:45 +00:00
offset = dissect_per_restricted_character_string_sorted ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension ,
2005-08-29 10:43:33 +00:00
" '()+,-.*0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " , 74 , NULL ) ;
2003-07-19 03:45:04 +00:00
return offset ;
}
2003-07-31 10:26:36 +00:00
guint32
2009-11-22 17:00:45 +00:00
dissect_per_VisibleString ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension )
2005-01-17 10:09:43 +00:00
{
2009-11-22 17:00:45 +00:00
offset = dissect_per_restricted_character_string_sorted ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension ,
2005-08-18 14:32:49 +00:00
" ! \" #$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[ \\ ]^_`abcdefghijklmnopqrstuvwxyz{|}~ " , 95 , NULL ) ;
2005-01-17 10:09:43 +00:00
return offset ;
}
guint32
2009-11-22 17:00:45 +00:00
dissect_per_BMPString ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension _U_ )
2003-07-31 10:26:36 +00:00
{
guint32 length ;
static char * str ;
/* xx.x if the length is 0 bytes there will be no encoding */
if ( max_len = = 0 ) {
return offset ;
}
2005-11-14 13:05:17 +00:00
if ( min_len = = NO_BOUND ) {
min_len = 0 ;
2003-07-31 10:26:36 +00:00
}
/* xx.x */
length = max_len ;
if ( min_len ! = max_len ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx ,
2005-08-29 10:43:33 +00:00
tree , hf_per_octet_string_length , min_len , max_len ,
2006-05-22 11:49:50 +00:00
& length , FALSE ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-10-27 22:28:48 +00:00
}
2003-07-31 10:26:36 +00:00
/* align to byte boundary */
2004-10-27 02:34:30 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2003-07-31 10:26:36 +00:00
if ( length > = 1024 ) {
2004-05-17 20:03:36 +00:00
PER_NOT_DECODED_YET ( " BMPString too long " ) ;
2003-07-31 10:26:36 +00:00
length = 1024 ;
}
2012-03-31 20:57:15 +00:00
str = tvb_get_ephemeral_unicode_string ( tvb , offset > > 3 , length * 2 , ENC_BIG_ENDIAN ) ;
2003-07-31 10:26:36 +00:00
proto_tree_add_string ( tree , hf_index , tvb , offset > > 3 , length * 2 , str ) ;
offset + = ( length < < 3 ) * 2 ;
return offset ;
}
2003-07-13 01:43:33 +00:00
2009-10-18 23:19:44 +00:00
guint32
2007-05-02 12:13:29 +00:00
dissect_per_object_descriptor ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , tvbuff_t * * value_tvb )
{
2007-10-29 19:25:37 +00:00
offset = dissect_per_octet_string ( tvb , offset , actx , tree , hf_index , - 1 , - 1 , FALSE , value_tvb ) ;
2007-05-02 12:13:29 +00:00
return offset ;
}
2003-07-12 22:35:21 +00:00
/* this function dissects a constrained sequence of */
guint32
2009-03-25 22:04:23 +00:00
dissect_per_constrained_sequence_of ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * parent_tree , int hf_index , gint ett_index , const per_sequence_t * seq , int min_len , int max_len , gboolean has_extension _U_ )
2003-07-12 22:35:21 +00:00
{
proto_item * item ;
proto_tree * tree ;
guint32 old_offset = offset ;
guint32 length ;
2005-07-15 15:20:40 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_constrained_sequence_of " ) ;
2009-10-18 23:19:44 +00:00
/* 19.4 If there is a PER-visible constraint and an extension marker is present in it,
2009-03-25 22:04:23 +00:00
* a single bit shall be added to the field - list in a bit - field of length one
*/
if ( has_extension ) {
gboolean extension_present ;
2009-03-26 18:01:26 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , parent_tree , hf_per_extension_present_bit , & extension_present ) ;
2009-03-25 22:04:23 +00:00
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
if ( extension_present ) {
2009-10-18 23:19:44 +00:00
/* 10.9 shall be invoked to add the length determinant as a semi-constrained whole number to the field-list,
2009-03-25 22:04:23 +00:00
* followed by the component values
* TODO : Handle extension
*/
2009-04-02 17:04:04 +00:00
proto_tree_add_text ( parent_tree , tvb , ( offset > > 3 ) , 1 , " dissect_per_constrained_sequence_of with extension is not handled " ) ;
2009-03-25 22:04:23 +00:00
}
}
2003-07-12 22:35:21 +00:00
/* 19.5 if min==max and min,max<64k ==> no length determinant */
if ( ( min_len = = max_len ) & & ( min_len < 65536 ) ) {
length = min_len ;
goto call_sohelper ;
}
/* 19.6 ub>=64k or unset */
2007-07-30 08:01:59 +00:00
if ( ( max_len > = 65536 ) | | ( max_len = = NO_BOUND ) ) {
/* no constraint, see 10.9.4.2 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , parent_tree , hf_per_sequence_of_length , & length ) ;
2003-07-12 22:35:21 +00:00
goto call_sohelper ;
}
/* constrained whole number for number of elements */
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx ,
2005-07-15 15:20:40 +00:00
parent_tree , hf_per_sequence_of_length , min_len , max_len ,
2006-05-22 11:49:50 +00:00
& length , FALSE ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
call_sohelper :
2005-07-15 15:20:40 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
if ( IS_FT_UINT ( hfi - > type ) ) {
item = proto_tree_add_uint ( parent_tree , hf_index , tvb , offset > > 3 , 0 , length ) ;
proto_item_append_text ( item , ( length = = 1 ) ? " item " : " items " ) ;
} else {
2012-05-04 16:35:59 +00:00
item = proto_tree_add_item ( parent_tree , hf_index , tvb , offset > > 3 , 0 , ENC_BIG_ENDIAN ) ;
2005-07-15 15:20:40 +00:00
}
tree = proto_item_add_subtree ( item , ett_index ) ;
2010-10-17 14:07:05 +00:00
per_check_items ( length , min_len , max_len , actx , item ) ;
2005-07-15 15:20:40 +00:00
2009-12-09 21:18:04 +00:00
old_offset = offset ;
2006-06-29 15:26:41 +00:00
offset = dissect_per_sequence_of_helper ( tvb , offset , actx , tree , seq - > func , * seq - > p_id , length ) ;
2003-07-12 22:35:21 +00:00
2009-12-09 21:18:04 +00:00
if ( offset = = old_offset )
length = 0 ;
else if ( offset > > 3 = = old_offset > > 3 )
length = 1 ;
else
length = ( offset > > 3 ) - ( old_offset > > 3 ) ;
2003-07-12 22:35:21 +00:00
2009-12-09 21:18:04 +00:00
proto_item_set_len ( item , length ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
/* this function dissects a constrained set of */
guint32
2009-03-25 22:04:23 +00:00
dissect_per_constrained_set_of ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * parent_tree , int hf_index , gint ett_index , const per_sequence_t * seq , int min_len , int max_len , gboolean has_extension )
2003-07-12 22:35:21 +00:00
{
/* for basic-per a set-of is encoded in the same way as a sequence-of */
DEBUG_ENTRY ( " dissect_per_constrained_set_of " ) ;
2009-03-25 22:04:23 +00:00
offset = dissect_per_constrained_sequence_of ( tvb , offset , actx , parent_tree , hf_index , ett_index , seq , min_len , max_len , has_extension ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
/* this function dissects a set of */
guint32
2006-07-04 06:49:53 +00:00
dissect_per_set_of ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * parent_tree , int hf_index , gint ett_index , const per_sequence_t * seq )
2003-07-12 22:35:21 +00:00
{
/* for basic-per a set-of is encoded in the same way as a sequence-of */
DEBUG_ENTRY ( " dissect_per_set_of " ) ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_sequence_of ( tvb , offset , actx , parent_tree , hf_index , ett_index , seq ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
2005-04-28 09:54:03 +00:00
/* 23 Encoding the object identifier type */
2003-07-12 22:35:21 +00:00
guint32
2006-07-04 06:49:53 +00:00
dissect_per_object_identifier ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx _U_ , proto_tree * tree , int hf_index , tvbuff_t * * value_tvb )
2003-07-12 22:35:21 +00:00
{
2005-09-20 10:56:08 +00:00
guint length ;
2007-08-25 17:29:55 +00:00
const char * str ;
2007-05-03 09:15:04 +00:00
tvbuff_t * val_tvb = NULL ;
2005-09-20 10:56:08 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_object_identifier " ) ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_object_identifier_length , & length ) ;
2007-05-03 09:15:04 +00:00
if ( actx - > aligned ) BYTE_ALIGN_OFFSET ( offset ) ;
2008-04-13 16:42:41 +00:00
val_tvb = new_octet_aligned_subset ( tvb , offset , actx , length ) ;
2009-10-18 23:19:44 +00:00
2005-09-20 10:56:08 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
2005-12-02 13:16:58 +00:00
if ( hfi - > type = = FT_OID ) {
2012-05-04 16:35:59 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_index , val_tvb , 0 , length , ENC_BIG_ENDIAN ) ;
2005-12-02 13:16:58 +00:00
} else if ( IS_FT_STRING ( hfi - > type ) ) {
2007-11-01 22:07:43 +00:00
str = oid_encoded2string ( tvb_get_ptr ( val_tvb , 0 , length ) , length ) ;
2008-01-03 08:19:27 +00:00
actx - > created_item = proto_tree_add_string ( tree , hf_index , val_tvb , 0 , length , str ) ;
2005-09-20 10:56:08 +00:00
} else {
DISSECTOR_ASSERT_NOT_REACHED ( ) ;
}
2007-05-03 09:15:04 +00:00
if ( value_tvb ) * value_tvb = val_tvb ;
2003-07-12 22:35:21 +00:00
2005-09-20 10:56:08 +00:00
offset + = 8 * length ;
2003-07-12 22:35:21 +00:00
2005-09-20 10:56:08 +00:00
return offset ;
2003-07-12 22:35:21 +00:00
}
2005-09-20 10:56:08 +00:00
guint32
2008-10-31 18:42:53 +00:00
dissect_per_object_identifier_str ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , const char * * value_stringx )
2005-09-20 10:56:08 +00:00
{
tvbuff_t * value_tvb = NULL ;
guint length ;
2008-10-31 18:42:53 +00:00
offset = dissect_per_object_identifier ( tvb , offset , actx , tree , hf_index , ( value_stringx ) ? & value_tvb : NULL ) ;
2005-09-20 10:56:08 +00:00
2008-10-31 18:42:53 +00:00
if ( value_stringx ) {
2005-09-20 10:56:08 +00:00
if ( value_tvb & & ( length = tvb_length ( value_tvb ) ) ) {
2008-10-31 18:42:53 +00:00
* value_stringx = oid_encoded2string ( tvb_get_ptr ( value_tvb , 0 , length ) , length ) ;
2005-09-20 10:56:08 +00:00
} else {
2008-10-31 18:42:53 +00:00
* value_stringx = " " ;
2005-09-20 10:56:08 +00:00
}
}
return offset ;
}
2003-07-12 22:35:21 +00:00
/* this function reads a single bit */
guint32
2012-05-02 21:55:59 +00:00
dissect_per_boolean ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , gboolean * bool_val )
2003-07-12 22:35:21 +00:00
{
guint8 ch , mask ;
gboolean value ;
header_field_info * hfi ;
DEBUG_ENTRY ( " dissect_per_boolean " ) ;
ch = tvb_get_guint8 ( tvb , offset > > 3 ) ;
mask = 1 < < ( 7 - ( offset & 0x07 ) ) ;
if ( ch & mask ) {
value = 1 ;
} else {
value = 0 ;
}
if ( hf_index ! = - 1 ) {
2005-08-20 02:51:13 +00:00
char * str ;
2003-07-12 22:35:21 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
2009-10-25 11:43:30 +00:00
str = ep_strdup_printf ( " %c%c%c%c %c%c%c%c %s: %s " ,
2003-10-27 22:28:48 +00:00
mask & 0x80 ? ' 0 ' + value : ' . ' ,
mask & 0x40 ? ' 0 ' + value : ' . ' ,
mask & 0x20 ? ' 0 ' + value : ' . ' ,
mask & 0x10 ? ' 0 ' + value : ' . ' ,
mask & 0x08 ? ' 0 ' + value : ' . ' ,
mask & 0x04 ? ' 0 ' + value : ' . ' ,
mask & 0x02 ? ' 0 ' + value : ' . ' ,
2003-07-12 22:35:21 +00:00
mask & 0x01 ? ' 0 ' + value : ' . ' ,
2005-01-13 07:43:17 +00:00
hfi - > name ,
2003-08-31 00:49:37 +00:00
value ? " True " : " False "
2003-07-12 22:35:21 +00:00
) ;
2008-10-31 15:34:00 +00:00
actx - > created_item = proto_tree_add_boolean_format ( tree , hf_index , tvb , offset > > 3 , 1 , value , " %s " , str ) ;
2006-05-22 11:49:50 +00:00
} else {
actx - > created_item = NULL ;
2003-07-12 22:35:21 +00:00
}
2011-11-20 08:59:19 +00:00
if ( bool_val ) {
* bool_val = value ;
2003-07-12 22:35:21 +00:00
}
return offset + 1 ;
}
/* we currently only handle integers up to 32 bits in length. */
guint32
2006-07-04 06:49:53 +00:00
dissect_per_integer ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , gint32 * value )
2003-07-12 22:35:21 +00:00
{
guint32 i , length ;
gint32 val ;
proto_item * it = NULL ;
2005-06-15 22:56:23 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
/* 12.2.6 b */
2009-04-10 09:24:10 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_integer_length , & length ) ;
2003-07-12 22:35:21 +00:00
/* gassert here? */
if ( length > 4 ) {
2009-04-10 09:24:10 +00:00
PER_NOT_DECODED_YET ( " too long integer(per_integer) " ) ;
2003-07-12 22:35:21 +00:00
length = 4 ;
}
val = 0 ;
for ( i = 0 ; i < length ; i + + ) {
if ( i = = 0 ) {
if ( tvb_get_guint8 ( tvb , offset > > 3 ) & 0x80 ) {
/* negative number */
val = 0xffffffff ;
} else {
/* positive number */
val = 0 ;
}
}
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
}
2005-06-15 22:56:23 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
if ( ! hfi )
THROW ( ReportedBoundsError ) ;
if ( IS_FT_INT ( hfi - > type ) ) {
it = proto_tree_add_int ( tree , hf_index , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , val ) ;
} else if ( IS_FT_UINT ( hfi - > type ) ) {
it = proto_tree_add_uint ( tree , hf_index , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , val ) ;
} else {
2005-06-16 06:30:33 +00:00
proto_tree_add_text ( tree , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , " Field is not an integer: %s " , hfi - > abbrev ) ;
REPORT_DISSECTOR_BUG ( " PER integer field that's not an FT_INT* or FT_UINT* " ) ;
2005-06-15 22:56:23 +00:00
}
2003-10-27 22:28:48 +00:00
2006-05-22 11:49:50 +00:00
actx - > created_item = it ;
2003-07-12 22:35:21 +00:00
if ( value ) {
* value = val ;
}
return offset ;
}
2008-01-15 17:59:43 +00:00
/* 64 bits experimental version, internal for now */
static guint32
dissect_per_integer64b ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , gint64 * value )
{
guint32 i , length ;
gint64 val ;
proto_item * it = NULL ;
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
2008-01-15 17:59:43 +00:00
/* 12.2.6 b */
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , - 1 , & length ) ;
/* gassert here? */
if ( length > 8 ) {
2009-04-10 09:24:10 +00:00
PER_NOT_DECODED_YET ( " too long integer (64b) " ) ;
2008-01-15 17:59:43 +00:00
length = 4 ;
}
2003-07-12 22:35:21 +00:00
2008-01-15 17:59:43 +00:00
val = 0 ;
for ( i = 0 ; i < length ; i + + ) {
if ( i = = 0 ) {
if ( tvb_get_guint8 ( tvb , offset > > 3 ) & 0x80 ) {
/* negative number */
2008-01-15 22:23:57 +00:00
val = G_GINT64_CONSTANT ( 0xffffffffffffffff ) ;
2008-01-15 17:59:43 +00:00
} else {
/* positive number */
val = 0 ;
}
}
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
}
hfi = proto_registrar_get_nth ( hf_index ) ;
if ( ! hfi )
THROW ( ReportedBoundsError ) ;
if ( IS_FT_INT ( hfi - > type ) ) {
it = proto_tree_add_int64 ( tree , hf_index , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , val ) ;
} else if ( IS_FT_UINT ( hfi - > type ) ) {
it = proto_tree_add_uint64 ( tree , hf_index , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , val ) ;
} else {
proto_tree_add_text ( tree , tvb , ( offset > > 3 ) - ( length + 1 ) , length + 1 , " Field is not an integer: %s " , hfi - > abbrev ) ;
REPORT_DISSECTOR_BUG ( " PER integer field that's not an FT_INT* or FT_UINT* " ) ;
}
actx - > created_item = it ;
if ( value ) {
* value = val ;
}
return offset ;
}
2003-07-16 09:23:56 +00:00
/* this function reads a constrained integer with or without a
PER visible extension marker present
has_extension = = TRUE would map to asn constructs such as :
rfc - number INTEGER ( 1. .32768 , . . . )
while has_extension = = FALSE would map to :
t35CountryCode INTEGER ( 0. .255 )
2003-07-12 22:35:21 +00:00
it only handles integers that fit inside a 32 bit integer
10.5 .1 info only
10.5 .2 info only
10.5 .3 range = ub - lb + 1
10.5 .4 empty range
10.5 .5 info only
10.5 .6 unaligned version
10.5 .7 aligned version
10.5 .7 .1 decoding of 0 - 255 1 - 8 bits
10.5 .7 .2 decoding og 0 - 256 8 bits
10.5 .7 .3 decoding of 0 - 65535 16 bits
10.5 .7 .4
*/
guint32
2006-07-04 06:49:53 +00:00
dissect_per_constrained_integer ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , guint32 min , guint32 max , guint32 * value , gboolean has_extension )
2003-07-12 22:35:21 +00:00
{
proto_item * it = NULL ;
guint32 range , val ;
2004-06-24 21:50:05 +00:00
gint val_start , val_length ;
nstime_t timeval ;
2003-07-12 22:35:21 +00:00
header_field_info * hfi ;
int num_bits ;
2005-08-29 13:00:53 +00:00
gboolean tmp ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_constrained_integer " ) ;
2003-07-16 09:23:56 +00:00
if ( has_extension ) {
gboolean extension_present ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-16 09:23:56 +00:00
if ( extension_present ) {
2006-05-31 13:38:10 +00:00
offset = dissect_per_integer ( tvb , offset , actx , tree , hf_index , ( gint32 * ) value ) ;
2003-07-16 09:23:56 +00:00
return offset ;
}
}
2003-07-12 22:35:21 +00:00
hfi = proto_registrar_get_nth ( hf_index ) ;
2009-10-18 23:19:44 +00:00
/* 10.5.3 Let "range" be defined as the integer value ("ub" - "lb" 1), and let the value to be encoded be "n".
2006-05-13 12:06:56 +00:00
* 10.5 .7 In the case of the ALIGNED variant the encoding depends on whether
* d ) " range " is greater than 64 K ( the indefinite length case ) .
*/
2006-05-22 11:49:50 +00:00
if ( ( ( max - min ) > 65536 ) & & ( actx - > aligned ) ) {
2003-07-12 22:35:21 +00:00
/* just set range really big so it will fall through
to the bottom of the encoding */
range = 1000000 ;
} else {
2006-06-01 10:16:43 +00:00
/* Really ugly hack.
* We should really use guint64 as parameters for min / max .
* This is to prevent range from being 0 if
* the range for a signed integer spans the entire 32 bit range .
* Special case the 2 common cases when this can happen until
* a real fix is implemented .
*/
if ( ( max = = 0x7fffffff & & min = = 0x80000000 )
| | ( max = = 0xffffffff & & min = = 0x00000000 ) ) {
range = 0xffffffff ;
} else {
range = max - min + 1 ;
}
2003-07-12 22:35:21 +00:00
}
val = 0 ;
2004-06-24 21:50:05 +00:00
timeval . secs = val ; timeval . nsecs = 0 ;
2006-05-13 12:06:56 +00:00
/* 10.5.4 If "range" has the value 1, then the result of the encoding shall be an empty bit-field (no bits).*/
2006-06-01 10:16:43 +00:00
2007-04-10 14:48:06 +00:00
/* something is really wrong if range is 0 */
DISSECTOR_ASSERT ( range ! = 0 ) ;
2006-06-01 10:16:43 +00:00
2003-07-12 22:35:21 +00:00
if ( range = = 1 ) {
2004-06-24 21:50:05 +00:00
val_start = offset > > 3 ; val_length = 0 ;
2009-10-18 23:19:44 +00:00
val = min ;
2006-05-22 11:49:50 +00:00
} else if ( ( range < = 255 ) | | ( ! actx - > aligned ) ) {
2009-10-18 23:19:44 +00:00
/* 10.5.7.1
2006-05-13 12:06:56 +00:00
* 10.5 .6 In the case of the UNALIGNED variant the value ( " n " - " lb " ) shall be encoded
* as a non - negative binary integer in a bit field as specified in 10.3 with the minimum
* number of bits necessary to represent the range .
*/
2005-08-20 02:51:13 +00:00
char * str ;
2012-08-19 03:55:51 +00:00
int str_index = 0 ;
2012-08-19 18:15:20 +00:00
int i , bit , length , str_length ;
2006-05-13 12:06:56 +00:00
guint32 mask , mask2 ;
/* We only handle 32 bit integers */
mask = 0x80000000 ;
mask2 = 0x7fffffff ;
i = 32 ;
while ( ( range & mask ) = = 0 ) {
i = i - 1 ;
mask = mask > > 1 ;
mask2 = mask2 > > 1 ;
}
if ( ( range & mask2 ) = = 0 )
i = i - 1 ;
2003-07-12 22:35:21 +00:00
2006-05-13 12:06:56 +00:00
num_bits = i ;
2003-07-12 22:35:21 +00:00
length = 1 ;
if ( range < = 2 ) {
num_bits = 1 ;
}
2006-05-13 12:06:56 +00:00
2012-08-19 18:15:20 +00:00
/* prepare the string (max number of bits + quartet separators + field name + ": ") */
2012-08-19 21:08:54 +00:00
str_length = 256 + 64 + ( int ) strlen ( hfi - > name ) + 2 ;
2012-08-19 18:15:20 +00:00
str = ep_alloc ( str_length + 1 ) ;
str_index = g_snprintf ( str , str_length + 1 , " %s: " , hfi - > name ) ;
2003-07-12 22:35:21 +00:00
for ( bit = 0 ; bit < ( ( int ) ( offset & 0x07 ) ) ; bit + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2003-07-12 22:35:21 +00:00
}
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' . ' ;
2003-07-12 22:35:21 +00:00
}
/* read the bits for the int */
for ( i = 0 ; i < num_bits ; i + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2003-07-12 22:35:21 +00:00
}
if ( bit & & ( ! ( bit % 8 ) ) ) {
length + = 1 ;
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2003-07-12 22:35:21 +00:00
}
bit + + ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & tmp ) ;
2003-07-12 22:35:21 +00:00
val < < = 1 ;
if ( tmp ) {
2005-08-29 13:00:53 +00:00
val | = 1 ;
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 1 ' ;
2003-07-12 22:35:21 +00:00
} else {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 0 ' ;
2003-07-12 22:35:21 +00:00
}
}
for ( ; bit % 8 ; bit + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2003-07-12 22:35:21 +00:00
}
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' . ' ;
2003-07-12 22:35:21 +00:00
}
2012-08-19 03:55:51 +00:00
str [ str_index ] = ' \0 ' ; /* Terminate string */
2004-06-24 21:50:05 +00:00
val_start = ( offset - num_bits ) > > 3 ; val_length = length ;
2003-07-12 22:35:21 +00:00
val + = min ;
2006-06-19 10:18:42 +00:00
if ( display_internal_per_fields )
2012-08-19 03:55:51 +00:00
proto_tree_add_text ( tree , tvb , val_start , val_length , " Range = %u Bitfield length %u, %s " , range , num_bits , str ) ;
2003-07-12 22:35:21 +00:00
} else if ( range = = 256 ) {
/* 10.5.7.2 */
/* in the aligned case, align to byte boundary */
2004-10-27 02:34:30 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2003-07-12 22:35:21 +00:00
val = tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
2004-06-24 21:50:05 +00:00
val_start = ( offset > > 3 ) - 1 ; val_length = 1 ;
2003-07-12 22:35:21 +00:00
val + = min ;
} else if ( range < = 65536 ) {
/* 10.5.7.3 */
/* in the aligned case, align to byte boundary */
2004-10-27 02:34:30 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2003-07-12 22:35:21 +00:00
val = tvb_get_guint8 ( tvb , offset > > 3 ) ;
val < < = 8 ;
offset + = 8 ;
val | = tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
2004-06-24 21:50:05 +00:00
val_start = ( offset > > 3 ) - 2 ; val_length = 2 ;
2003-07-12 22:35:21 +00:00
val + = min ;
} else {
int i , num_bytes ;
gboolean bit ;
2003-10-27 22:28:48 +00:00
2003-07-12 22:35:21 +00:00
/* 10.5.7.4 */
/* 12.2.6 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & bit ) ;
2003-07-12 22:35:21 +00:00
num_bytes = bit ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & bit ) ;
2003-07-12 22:35:21 +00:00
num_bytes = ( num_bytes < < 1 ) | bit ;
2003-10-27 22:28:48 +00:00
2003-07-12 22:35:21 +00:00
num_bytes + + ; /* lower bound for length determinant is 1 */
2005-10-10 20:38:28 +00:00
if ( display_internal_per_fields )
proto_tree_add_uint ( tree , hf_per_const_int_len , tvb , ( offset > > 3 ) , 1 , num_bytes ) ;
2003-07-12 22:35:21 +00:00
/* byte aligned */
2004-10-27 02:34:30 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2003-07-12 22:35:21 +00:00
val = 0 ;
for ( i = 0 ; i < num_bytes ; i + + ) {
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
}
2004-06-24 21:50:05 +00:00
val_start = ( offset > > 3 ) - ( num_bytes + 1 ) ; val_length = num_bytes + 1 ;
2003-07-12 22:35:21 +00:00
val + = min ;
}
2004-06-24 21:50:05 +00:00
timeval . secs = val ;
if ( IS_FT_UINT ( hfi - > type ) ) {
it = proto_tree_add_uint ( tree , hf_index , tvb , val_start , val_length , val ) ;
2010-10-17 14:07:05 +00:00
per_check_value ( val , min , max , actx , it , FALSE ) ;
2004-06-24 21:50:05 +00:00
} else if ( IS_FT_INT ( hfi - > type ) ) {
it = proto_tree_add_int ( tree , hf_index , tvb , val_start , val_length , val ) ;
2010-10-17 14:07:05 +00:00
per_check_value ( val , min , max , actx , it , TRUE ) ;
2004-06-24 21:50:05 +00:00
} else if ( IS_FT_TIME ( hfi - > type ) ) {
it = proto_tree_add_time ( tree , hf_index , tvb , val_start , val_length , & timeval ) ;
} else {
2005-05-24 13:50:20 +00:00
THROW ( ReportedBoundsError ) ;
2004-06-24 21:50:05 +00:00
}
2006-05-22 11:49:50 +00:00
actx - > created_item = it ;
2004-06-24 21:50:05 +00:00
if ( value ) * value = val ;
2012-08-14 22:12:31 +00:00
return offset ;
}
2003-07-12 22:35:21 +00:00
2008-01-15 17:59:43 +00:00
guint32
dissect_per_constrained_integer_64b ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , guint64 min , guint64 max , guint64 * value , gboolean has_extension )
{
2009-04-10 09:24:10 +00:00
proto_item * it = NULL , * int_item = NULL ;
2008-01-15 17:59:43 +00:00
guint64 range , val ;
gint val_start , val_length ;
nstime_t timeval ;
header_field_info * hfi ;
int num_bits ;
gboolean tmp ;
DEBUG_ENTRY ( " dissect_per_constrained_integer_64b " ) ;
if ( has_extension ) {
gboolean extension_present ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
if ( extension_present ) {
offset = dissect_per_integer64b ( tvb , offset , actx , tree , hf_index , ( gint64 * ) value ) ;
return offset ;
}
}
hfi = proto_registrar_get_nth ( hf_index ) ;
2009-10-18 23:19:44 +00:00
/* 10.5.3 Let "range" be defined as the integer value ("ub" - "lb" 1), and let the value to be encoded be "n".
2008-01-15 17:59:43 +00:00
* 10.5 .7 In the case of the ALIGNED variant the encoding depends on whether
* d ) " range " is greater than 64 K ( the indefinite length case ) .
*/
if ( ( ( max - min ) > 65536 ) & & ( actx - > aligned ) ) {
2012-08-14 22:12:31 +00:00
/* just set range really big so it will fall through
to the bottom of the encoding */
/* range=1000000; */
range = max - min ;
if ( range = = 65536 )
range + + ; /* make it fall trough? */
2008-01-15 17:59:43 +00:00
} else {
2012-08-14 22:12:31 +00:00
/* Copied from the 32 bit version, assuming the same problem occurs
2008-01-15 17:59:43 +00:00
* at 64 bit boundary .
* Really ugly hack .
* We should really use guint64 as parameters for min / max .
* This is to prevent range from being 0 if
* the range for a signed integer spans the entire 32 bit range .
* Special case the 2 common cases when this can happen until
* a real fix is implemented .
*/
2008-01-15 22:07:29 +00:00
if ( ( max = = G_GINT64_CONSTANT ( 0x7fffffffffffffff ) & & min = = G_GINT64_CONSTANT ( 0x8000000000000000 ) )
2008-01-15 23:25:40 +00:00
| | ( max = = G_GINT64_CONSTANT ( 0xffffffffffffffff ) & & min = = 0 ) ) {
2008-01-15 22:07:29 +00:00
range = G_GINT64_CONSTANT ( 0xffffffffffffffff ) ;
2008-01-15 17:59:43 +00:00
} else {
range = max - min + 1 ;
}
}
val = 0 ;
timeval . secs = 0 ; timeval . nsecs = 0 ;
/* 10.5.4 If "range" has the value 1, then the result of the encoding shall be an empty bit-field (no bits).*/
/* something is really wrong if range is 0 */
DISSECTOR_ASSERT ( range ! = 0 ) ;
if ( range = = 1 ) {
val_start = offset > > 3 ; val_length = 0 ;
2009-10-18 23:19:44 +00:00
val = min ;
2008-01-15 17:59:43 +00:00
} else if ( ( range < = 255 ) | | ( ! actx - > aligned ) ) {
2009-10-18 23:19:44 +00:00
/* 10.5.7.1
2008-01-15 17:59:43 +00:00
* 10.5 .6 In the case of the UNALIGNED variant the value ( " n " - " lb " ) shall be encoded
* as a non - negative binary integer in a bit field as specified in 10.3 with the minimum
* number of bits necessary to represent the range .
*/
char * str ;
2012-08-19 18:15:20 +00:00
int i , bit , length , str_length , str_index ;
2012-08-14 22:12:31 +00:00
guint64 mask , mask2 ;
/* We only handle 64 bit integers */
mask = G_GINT64_CONSTANT ( 0x8000000000000000 ) ;
mask2 = G_GINT64_CONSTANT ( 0x7fffffffffffffff ) ;
i = 64 ;
2008-01-15 17:59:43 +00:00
while ( ( range & mask ) = = 0 ) {
i = i - 1 ;
mask = mask > > 1 ;
mask2 = mask2 > > 1 ;
}
if ( ( range & mask2 ) = = 0 )
i = i - 1 ;
num_bits = i ;
length = 1 ;
if ( range < = 2 ) {
num_bits = 1 ;
}
2012-08-19 18:15:20 +00:00
/* prepare the string (max number of bits + quartet separators + field name + ": ") */
2012-08-19 21:08:54 +00:00
str_length = 512 + 128 + ( int ) strlen ( hfi - > name ) + 2 ;
2012-08-19 18:15:20 +00:00
str = ep_alloc ( str_length + 1 ) ;
str_index = 0 ;
str_index = g_snprintf ( str , str_length + 1 , " %s: " , hfi - > name ) ;
2008-01-15 17:59:43 +00:00
for ( bit = 0 ; bit < ( ( int ) ( offset & 0x07 ) ) ; bit + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2008-01-15 17:59:43 +00:00
}
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' . ' ;
2008-01-15 17:59:43 +00:00
}
/* read the bits for the int */
for ( i = 0 ; i < num_bits ; i + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2008-01-15 17:59:43 +00:00
}
if ( bit & & ( ! ( bit % 8 ) ) ) {
length + = 1 ;
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2008-01-15 17:59:43 +00:00
}
bit + + ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , - 1 , & tmp ) ;
val < < = 1 ;
if ( tmp ) {
val | = 1 ;
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 1 ' ;
2008-01-15 17:59:43 +00:00
} else {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' 0 ' ;
2008-01-15 17:59:43 +00:00
}
}
for ( ; bit % 8 ; bit + + ) {
if ( bit & & ( ! ( bit % 4 ) ) ) {
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' ' ;
2008-01-15 17:59:43 +00:00
}
2012-08-19 18:15:20 +00:00
if ( str_index < str_length ) str [ str_index + + ] = ' . ' ;
2008-01-15 17:59:43 +00:00
}
2012-08-19 18:15:20 +00:00
str [ str_index ] = ' \0 ' ; /* Terminate string */
2008-01-15 17:59:43 +00:00
val_start = ( offset - num_bits ) > > 3 ; val_length = length ;
val + = min ;
if ( display_internal_per_fields )
2008-01-15 21:57:50 +00:00
proto_tree_add_text ( tree , tvb , val_start , val_length , " Range = (% " G_GINT64_MODIFIER " u) Bitfield length %u, %s " , range , num_bits , str ) ;
2008-01-15 17:59:43 +00:00
} else if ( range = = 256 ) {
/* 10.5.7.2 */
/* in the aligned case, align to byte boundary */
BYTE_ALIGN_OFFSET ( offset ) ;
val = tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
val_start = ( offset > > 3 ) - 1 ; val_length = 1 ;
val + = min ;
} else if ( range < = 65536 ) {
/* 10.5.7.3 */
/* in the aligned case, align to byte boundary */
BYTE_ALIGN_OFFSET ( offset ) ;
val = tvb_get_guint8 ( tvb , offset > > 3 ) ;
val < < = 8 ;
offset + = 8 ;
val | = tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
val_start = ( offset > > 3 ) - 2 ; val_length = 2 ;
val + = min ;
} else {
2010-01-19 00:37:39 +00:00
int i , num_bytes , n_bits ;
2008-01-15 17:59:43 +00:00
/* 10.5.7.4 */
/* 12.2.6 */
2009-04-10 09:24:10 +00:00
/* calculate the number of bits to hold the length */
if ( ( range & G_GINT64_CONSTANT ( 0xffffffff0000000 ) ) ! = 0 ) {
2010-01-19 00:37:39 +00:00
n_bits = 3 ;
2009-04-10 09:24:10 +00:00
} else {
2010-01-19 00:37:39 +00:00
n_bits = 2 ;
2009-04-10 09:24:10 +00:00
}
2010-01-19 00:37:39 +00:00
num_bytes = tvb_get_bits8 ( tvb , offset , n_bits ) ;
2008-01-15 17:59:43 +00:00
num_bytes + + ; /* lower bound for length determinant is 1 */
2009-04-10 09:24:10 +00:00
if ( display_internal_per_fields ) {
2011-10-24 19:57:53 +00:00
int_item = proto_tree_add_bits_item ( tree , hf_per_const_int_len , tvb , offset , n_bits , ENC_BIG_ENDIAN ) ;
2009-04-10 09:24:10 +00:00
proto_item_append_text ( int_item , " +1=%u bytes, Range = (% " G_GINT64_MODIFIER " u) " , num_bytes , range ) ;
}
2010-01-19 00:37:39 +00:00
offset = offset + n_bits ;
2008-01-15 17:59:43 +00:00
/* byte aligned */
BYTE_ALIGN_OFFSET ( offset ) ;
val = 0 ;
for ( i = 0 ; i < num_bytes ; i + + ) {
val = ( val < < 8 ) | tvb_get_guint8 ( tvb , offset > > 3 ) ;
offset + = 8 ;
}
val_start = ( offset > > 3 ) - ( num_bytes + 1 ) ; val_length = num_bytes + 1 ;
val + = min ;
}
2009-10-18 23:19:44 +00:00
2008-01-15 17:59:43 +00:00
if ( IS_FT_UINT ( hfi - > type ) ) {
it = proto_tree_add_uint64 ( tree , hf_index , tvb , val_start , val_length , val ) ;
2010-10-17 14:07:05 +00:00
per_check_value64 ( val , min , max , actx , it , FALSE ) ;
2008-01-15 17:59:43 +00:00
} else if ( IS_FT_INT ( hfi - > type ) ) {
it = proto_tree_add_int64 ( tree , hf_index , tvb , val_start , val_length , val ) ;
2010-10-17 14:07:05 +00:00
per_check_value64 ( val , min , max , actx , it , TRUE ) ;
2008-01-15 17:59:43 +00:00
} else if ( IS_FT_TIME ( hfi - > type ) ) {
timeval . secs = ( guint32 ) val ;
it = proto_tree_add_time ( tree , hf_index , tvb , val_start , val_length , & timeval ) ;
} else {
THROW ( ReportedBoundsError ) ;
}
actx - > created_item = it ;
if ( value ) * value = val ;
2011-07-18 19:11:32 +00:00
return offset ;
}
2008-01-15 17:59:43 +00:00
2007-05-03 09:15:04 +00:00
/* 13 Encoding the enumerated type */
2006-03-05 20:21:19 +00:00
guint32
2006-07-04 06:49:53 +00:00
dissect_per_enumerated ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , guint32 root_num , guint32 * value , gboolean has_extension , guint32 ext_num , guint32 * value_map )
2006-03-05 20:21:19 +00:00
{
proto_item * it = NULL ;
2006-03-08 13:50:04 +00:00
guint32 enum_index , val ;
2006-03-05 20:21:19 +00:00
guint32 start_offset = offset ;
2006-03-08 13:50:04 +00:00
gboolean extension_present = FALSE ;
2006-03-05 20:21:19 +00:00
header_field_info * hfi ;
2006-03-08 13:50:04 +00:00
if ( has_extension ) {
/* Extension bit */
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2006-03-08 13:50:04 +00:00
}
2006-03-05 20:21:19 +00:00
2006-03-08 13:50:04 +00:00
if ( ! extension_present ) {
/* 13.2 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx , tree , hf_per_enum_index , 0 , root_num - 1 , & enum_index , FALSE ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2006-03-08 13:50:04 +00:00
} else {
2006-03-05 20:21:19 +00:00
/* 13.3 */
2006-03-08 13:50:04 +00:00
if ( ext_num = = 1 ) {
2006-03-05 20:21:19 +00:00
/* 10.5.4 If "range" has the value 1,
* then the result of the encoding shall be
* an empty bit - field ( no bits ) .
*/
2006-03-08 13:50:04 +00:00
enum_index = 0 ;
} else {
2006-03-05 20:21:19 +00:00
/* 13.3 ".. and the value shall be added to the field-list as a
2009-10-18 23:19:44 +00:00
* normally small non - negative whole number whose value is the
2006-03-05 20:21:19 +00:00
* enumeration index of the additional enumeration and with " lb " set to 0. . "
*/
2006-05-22 11:49:50 +00:00
offset = dissect_per_normally_small_nonnegative_whole_number ( tvb , offset , actx , tree , hf_per_enum_extension_index , & enum_index ) ;
2006-03-05 20:21:19 +00:00
}
2006-03-08 13:50:04 +00:00
enum_index + = root_num ;
2006-03-05 20:21:19 +00:00
}
2006-03-08 13:50:04 +00:00
val = ( value_map & & ( enum_index < ( root_num + ext_num ) ) ) ? value_map [ enum_index ] : enum_index ;
hfi = proto_registrar_get_nth ( hf_index ) ;
if ( IS_FT_UINT ( hfi - > type ) ) {
it = proto_tree_add_uint ( tree , hf_index , tvb , start_offset > > 3 , BLEN ( start_offset , offset ) , val ) ;
} else {
THROW ( ReportedBoundsError ) ;
}
2006-05-22 11:49:50 +00:00
actx - > created_item = it ;
2006-03-08 13:50:04 +00:00
if ( value ) * value = val ;
2006-03-05 20:21:19 +00:00
return offset ;
}
2007-05-03 09:15:04 +00:00
/* 14 Encoding the real type */
2009-10-18 23:19:44 +00:00
guint32
2007-05-03 09:15:04 +00:00
dissect_per_real ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , double * value )
{
guint32 val_length , end_offset ;
tvbuff_t * val_tvb ;
double val = 0 ;
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_real_length , & val_length ) ;
if ( actx - > aligned ) BYTE_ALIGN_OFFSET ( offset ) ;
2008-04-13 16:42:41 +00:00
val_tvb = new_octet_aligned_subset ( tvb , offset , actx , val_length ) ;
2007-05-03 09:15:04 +00:00
end_offset = offset + val_length * 8 ;
val = asn1_get_real ( tvb_get_ptr ( val_tvb , 0 , val_length ) , val_length ) ;
actx - > created_item = proto_tree_add_double ( tree , hf_index , val_tvb , 0 , val_length , val ) ;
if ( value ) * value = val ;
return end_offset ;
}
2005-09-09 15:36:39 +00:00
/* 22 Encoding the choice type */
2003-07-12 22:35:21 +00:00
guint32
2007-07-18 13:15:36 +00:00
dissect_per_choice ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , gint ett_index , const per_choice_t * choice , gint * value )
2003-07-12 22:35:21 +00:00
{
2011-07-18 19:11:32 +00:00
gboolean /*extension_present,*/ extension_flag ;
2003-07-12 22:35:21 +00:00
int extension_root_entries ;
2005-09-09 15:36:39 +00:00
int extension_addition_entries ;
2003-07-12 22:35:21 +00:00
guint32 choice_index ;
2010-01-19 00:37:39 +00:00
int i , idx , cidx ;
2005-09-09 15:36:39 +00:00
guint32 ext_length ;
guint32 old_offset = offset ;
proto_item * choice_item = NULL ;
proto_tree * choice_tree = NULL ;
2003-07-12 22:35:21 +00:00
DEBUG_ENTRY ( " dissect_per_choice " ) ;
2007-07-18 13:15:36 +00:00
if ( value ) * value = - 1 ;
2005-09-09 15:36:39 +00:00
/* 22.5 */
if ( choice [ 0 ] . extension = = ASN1_NO_EXTENSIONS ) {
2011-07-18 19:11:32 +00:00
/*extension_present = FALSE; ?? */
2005-09-09 15:36:39 +00:00
extension_flag = FALSE ;
2003-07-12 22:35:21 +00:00
} else {
2011-07-18 19:11:32 +00:00
/*extension_present = TRUE; ?? */
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_bit , & extension_flag ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
}
2005-09-09 15:36:39 +00:00
/* count the number of entries in the extension root and extension addition */
extension_root_entries = 0 ;
extension_addition_entries = 0 ;
2006-06-29 15:26:41 +00:00
for ( i = 0 ; choice [ i ] . p_id ; i + + ) {
2003-07-12 22:35:21 +00:00
switch ( choice [ i ] . extension ) {
2005-09-09 15:36:39 +00:00
case ASN1_NO_EXTENSIONS :
case ASN1_EXTENSION_ROOT :
extension_root_entries + + ;
break ;
case ASN1_NOT_EXTENSION_ROOT :
extension_addition_entries + + ;
break ;
2003-07-12 22:35:21 +00:00
}
}
2005-09-09 15:36:39 +00:00
if ( ! extension_flag ) { /* 22.6, 22.7 */
if ( extension_root_entries = = 1 ) { /* 22.5 */
choice_index = 0 ;
} else {
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx ,
2005-09-09 15:36:39 +00:00
tree , hf_per_choice_index , 0 , extension_root_entries - 1 ,
2006-05-22 11:49:50 +00:00
& choice_index , FALSE ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
}
2010-01-19 00:37:39 +00:00
idx = - 1 ; cidx = choice_index ;
2006-06-29 15:26:41 +00:00
for ( i = 0 ; choice [ i ] . p_id ; i + + ) {
2005-09-09 15:36:39 +00:00
if ( choice [ i ] . extension ! = ASN1_NOT_EXTENSION_ROOT ) {
2010-01-19 00:37:39 +00:00
if ( ! cidx ) { idx = i ; break ; }
2005-08-29 10:43:33 +00:00
cidx - - ;
2003-07-12 22:35:21 +00:00
}
}
2005-09-09 15:36:39 +00:00
} else { /* 22.8 */
2006-05-22 11:49:50 +00:00
offset = dissect_per_normally_small_nonnegative_whole_number ( tvb , offset , actx , tree , hf_per_choice_extension_index , & choice_index ) ;
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_open_type_length , & ext_length ) ;
2005-09-09 15:36:39 +00:00
2010-01-19 00:37:39 +00:00
idx = - 1 ; cidx = choice_index ;
2006-06-29 15:26:41 +00:00
for ( i = 0 ; choice [ i ] . p_id ; i + + ) {
2005-09-09 15:36:39 +00:00
if ( choice [ i ] . extension = = ASN1_NOT_EXTENSION_ROOT ) {
2010-01-19 00:37:39 +00:00
if ( ! cidx ) { idx = i ; break ; }
2005-09-09 15:36:39 +00:00
cidx - - ;
2003-07-12 22:35:21 +00:00
}
}
2005-09-09 15:36:39 +00:00
}
2003-07-12 22:35:21 +00:00
2010-01-19 00:37:39 +00:00
if ( idx ! = - 1 ) {
choice_item = proto_tree_add_uint ( tree , hf_index , tvb , old_offset > > 3 , 0 , choice [ idx ] . value ) ;
2005-09-09 15:36:39 +00:00
choice_tree = proto_item_add_subtree ( choice_item , ett_index ) ;
if ( ! extension_flag ) {
2010-01-19 00:37:39 +00:00
offset = choice [ idx ] . func ( tvb , offset , actx , choice_tree , * choice [ idx ] . p_id ) ;
2005-08-29 10:43:33 +00:00
} else {
2010-01-19 00:37:39 +00:00
choice [ idx ] . func ( tvb , offset , actx , choice_tree , * choice [ idx ] . p_id ) ;
2005-09-09 15:36:39 +00:00
offset + = ext_length * 8 ;
2005-08-29 10:43:33 +00:00
}
2005-09-09 15:36:39 +00:00
proto_item_set_len ( choice_item , BLEN ( old_offset , offset ) ) ;
} else {
if ( ! extension_flag ) {
PER_NOT_DECODED_YET ( " unknown extension root index in choice " ) ;
2003-07-12 22:35:21 +00:00
} else {
2005-09-09 15:36:39 +00:00
offset + = ext_length * 8 ;
proto_tree_add_text ( tree , tvb , old_offset > > 3 , BLEN ( old_offset , offset ) , " Choice no. %d in extension " , choice_index ) ;
2011-07-04 06:22:15 +00:00
expert_add_info_format ( actx - > pinfo , choice_item , PI_UNDECODED , PI_NOTE , " unknown choice extension " ) ;
2003-07-12 22:35:21 +00:00
}
}
2010-01-19 00:37:39 +00:00
if ( value & & ( idx ! = - 1 ) )
* value = choice [ idx ] . value ;
2005-09-09 15:36:39 +00:00
2003-07-12 22:35:21 +00:00
return offset ;
}
2005-07-30 01:01:02 +00:00
static const char *
2010-01-19 00:37:39 +00:00
index_get_optional_name ( const per_sequence_t * sequence , int idx )
2003-07-12 22:35:21 +00:00
{
int i ;
2006-07-03 07:03:57 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
2006-07-03 07:03:57 +00:00
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
2003-10-09 22:35:07 +00:00
if ( ( sequence [ i ] . extension ! = ASN1_NOT_EXTENSION_ROOT ) & & ( sequence [ i ] . optional = = ASN1_OPTIONAL ) ) {
2010-01-19 00:37:39 +00:00
if ( idx = = 0 ) {
2006-07-03 07:03:57 +00:00
hfi = proto_registrar_get_nth ( * sequence [ i ] . p_id ) ;
return ( hfi ) ? hfi - > name : " <unknown filed> " ;
2003-07-12 22:35:21 +00:00
}
2010-01-19 00:37:39 +00:00
idx - - ;
2003-07-12 22:35:21 +00:00
}
}
return " <unknown type> " ;
}
2005-07-30 01:01:02 +00:00
static const char *
2010-01-19 00:37:39 +00:00
index_get_extension_name ( const per_sequence_t * sequence , int idx )
2003-07-12 22:35:21 +00:00
{
int i ;
2006-07-03 07:03:57 +00:00
header_field_info * hfi ;
2003-07-12 22:35:21 +00:00
2006-07-03 07:03:57 +00:00
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
2003-10-09 22:35:07 +00:00
if ( sequence [ i ] . extension = = ASN1_NOT_EXTENSION_ROOT ) {
2010-01-19 00:37:39 +00:00
if ( idx = = 0 ) {
2011-08-09 08:00:06 +00:00
if ( * sequence [ i ] . p_id = = - 1 ) return " extension addition group " ;
2006-07-03 07:03:57 +00:00
hfi = proto_registrar_get_nth ( * sequence [ i ] . p_id ) ;
return ( hfi ) ? hfi - > name : " <unknown filed> " ;
2003-07-12 22:35:21 +00:00
}
2010-01-19 00:37:39 +00:00
idx - - ;
2003-07-12 22:35:21 +00:00
}
}
return " <unknown type> " ;
}
2006-07-03 07:03:57 +00:00
static const char *
2010-01-19 00:37:39 +00:00
index_get_field_name ( const per_sequence_t * sequence , int idx )
2006-07-03 07:03:57 +00:00
{
header_field_info * hfi ;
2010-01-19 00:37:39 +00:00
hfi = proto_registrar_get_nth ( * sequence [ idx ] . p_id ) ;
2006-07-03 07:03:57 +00:00
return ( hfi ) ? hfi - > name : " <unknown filed> " ;
}
2003-07-12 22:35:21 +00:00
/* this functions decodes a SEQUENCE
it can only handle SEQUENCES with at most 32 DEFAULT or OPTIONAL fields
18.1 extension bit
2003-10-27 22:28:48 +00:00
18.2 optinal / default items in root
2003-07-12 22:35:21 +00:00
18.3 we ignore the case where n > 64 K
18.4 the root sequence
18.5
18.6
18.7
18.8
18.9
*/
guint32
2006-07-04 06:49:53 +00:00
dissect_per_sequence ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * parent_tree , int hf_index , gint ett_index , const per_sequence_t * sequence )
2003-07-12 22:35:21 +00:00
{
2011-07-18 19:11:32 +00:00
gboolean /*extension_present,*/ extension_flag , optional_field_flag ;
2003-07-12 22:35:21 +00:00
proto_item * item ;
proto_tree * tree ;
guint32 old_offset = offset ;
2003-07-16 21:05:12 +00:00
guint32 i , num_opts ;
2003-07-12 22:35:21 +00:00
guint32 optional_mask ;
DEBUG_ENTRY ( " dissect_per_sequence " ) ;
2003-07-29 08:59:14 +00:00
2012-05-04 16:35:59 +00:00
item = proto_tree_add_item ( parent_tree , hf_index , tvb , offset > > 3 , 0 , ENC_BIG_ENDIAN ) ;
2003-07-12 22:35:21 +00:00
tree = proto_item_add_subtree ( item , ett_index ) ;
/* first check if there should be an extension bit for this CHOICE.
2003-10-27 22:28:48 +00:00
we do this by just checking the first choice arm
2003-07-12 22:35:21 +00:00
*/
/* 18.1 */
extension_flag = 0 ;
2003-10-09 22:35:07 +00:00
if ( sequence [ 0 ] . extension = = ASN1_NO_EXTENSIONS ) {
2011-07-18 19:11:32 +00:00
/*extension_present=0; ?? */
2003-07-12 22:35:21 +00:00
} else {
2011-07-18 19:11:32 +00:00
/*extension_present=1; ?? */
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_bit , & extension_flag ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
}
/* 18.2 */
num_opts = 0 ;
2006-07-03 07:03:57 +00:00
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
2003-10-09 22:35:07 +00:00
if ( ( sequence [ i ] . extension ! = ASN1_NOT_EXTENSION_ROOT ) & & ( sequence [ i ] . optional = = ASN1_OPTIONAL ) ) {
2003-07-12 22:35:21 +00:00
num_opts + + ;
}
}
2003-07-29 08:59:14 +00:00
2003-07-12 22:35:21 +00:00
optional_mask = 0 ;
for ( i = 0 ; i < num_opts ; i + + ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_optional_field_bit , & optional_field_flag ) ;
2006-07-03 07:03:57 +00:00
if ( tree ) {
proto_item_append_text ( actx - > created_item , " (%s %s present) " ,
index_get_optional_name ( sequence , i ) , optional_field_flag ? " is " : " is NOT " ) ;
}
2006-05-22 11:49:50 +00:00
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-07-12 22:35:21 +00:00
optional_mask < < = 1 ;
if ( optional_field_flag ) {
optional_mask | = 0x01 ;
}
}
/* 18.4 */
2006-07-03 07:03:57 +00:00
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
2003-10-09 22:35:07 +00:00
if ( ( sequence [ i ] . extension = = ASN1_NO_EXTENSIONS )
| | ( sequence [ i ] . extension = = ASN1_EXTENSION_ROOT ) ) {
2003-10-09 20:52:57 +00:00
if ( sequence [ i ] . optional = = ASN1_OPTIONAL ) {
2003-07-12 22:35:21 +00:00
gboolean is_present ;
2009-10-12 14:43:09 +00:00
if ( num_opts = = 0 ) {
continue ;
}
2003-07-12 22:35:21 +00:00
is_present = ( 1 < < ( num_opts - 1 ) ) & optional_mask ;
num_opts - - ;
if ( ! is_present ) {
continue ;
}
}
if ( sequence [ i ] . func ) {
2006-06-29 15:26:41 +00:00
offset = sequence [ i ] . func ( tvb , offset , actx , tree , * sequence [ i ] . p_id ) ;
2003-07-12 22:35:21 +00:00
} else {
2006-07-03 07:03:57 +00:00
PER_NOT_DECODED_YET ( index_get_field_name ( sequence , i ) ) ;
2003-07-12 22:35:21 +00:00
}
}
}
if ( extension_flag ) {
gboolean extension_bit ;
guint32 num_known_extensions ;
guint32 num_extensions ;
guint32 extension_mask ;
2006-05-22 11:49:50 +00:00
offset = dissect_per_normally_small_nonnegative_whole_number ( tvb , offset , actx , tree , hf_per_num_sequence_extensions , & num_extensions ) ;
2003-07-12 22:35:21 +00:00
/* the X.691 standard is VERY unclear here.
there is no mention that the lower bound lb for this
( apparently ) semiconstrained value is 1 ,
apart from the NOTE : comment in 18.8 that this value can
not be 0.
In my book , there is a semantic difference between having
a comment that says that the value can not be zero
and stating that the lb is 1.
2011-07-18 19:11:32 +00:00
I don ' t know if this is right or not but it makes
2003-07-12 22:35:21 +00:00
some of the very few captures I have decode properly .
2003-10-27 22:28:48 +00:00
It could also be that the captures I have are generated by
2003-07-12 22:35:21 +00:00
a broken implementation .
2011-07-18 19:11:32 +00:00
If this is wrong and you don ' t report it as a bug
then it won ' t get fixed !
2003-07-12 22:35:21 +00:00
*/
num_extensions + = 1 ;
extension_mask = 0 ;
2003-07-16 21:05:12 +00:00
for ( i = 0 ; i < num_extensions ; i + + ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_bit ) ;
2006-07-03 07:03:57 +00:00
if ( tree ) {
proto_item_append_text ( actx - > created_item , " (%s %s present) " ,
index_get_extension_name ( sequence , i ) , extension_bit ? " is " : " is NOT " ) ;
}
2006-05-22 11:49:50 +00:00
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2003-10-27 22:28:48 +00:00
2006-06-24 11:50:47 +00:00
extension_mask = ( extension_mask < < 1 ) | extension_bit ;
2003-07-12 22:35:21 +00:00
}
/* find how many extensions we know about */
num_known_extensions = 0 ;
2006-07-03 07:03:57 +00:00
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
2003-10-09 22:35:07 +00:00
if ( sequence [ i ] . extension = = ASN1_NOT_EXTENSION_ROOT ) {
2003-07-12 22:35:21 +00:00
num_known_extensions + + ;
}
}
/* decode the extensions one by one */
for ( i = 0 ; i < num_extensions ; i + + ) {
2008-06-19 12:16:26 +00:00
proto_item * cause ;
2003-07-12 22:35:21 +00:00
guint32 length ;
guint32 new_offset ;
2008-06-19 12:16:26 +00:00
guint32 difference ;
2003-07-12 22:35:21 +00:00
guint32 extension_index ;
2003-07-16 21:05:12 +00:00
guint32 j , k ;
2003-07-12 22:35:21 +00:00
if ( ! ( ( 1L < < ( num_extensions - 1 - i ) ) & extension_mask ) ) {
/* this extension is not encoded in this PDU */
continue ;
}
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_open_type_length , & length ) ;
2003-07-12 22:35:21 +00:00
if ( i > = num_known_extensions ) {
2011-07-18 19:11:32 +00:00
/* we don't know how to decode this extension */
2003-07-12 22:35:21 +00:00
offset + = length * 8 ;
2011-07-04 06:22:15 +00:00
expert_add_info_format ( actx - > pinfo , item , PI_UNDECODED , PI_NOTE , " unknown sequence extension " ) ;
2003-07-12 22:35:21 +00:00
continue ;
}
extension_index = 0 ;
2006-07-03 07:03:57 +00:00
for ( j = 0 , k = 0 ; sequence [ j ] . p_id ; j + + ) {
2003-10-09 22:35:07 +00:00
if ( sequence [ j ] . extension = = ASN1_NOT_EXTENSION_ROOT ) {
2003-07-12 22:35:21 +00:00
if ( k = = i ) {
extension_index = j ;
break ;
}
k + + ;
}
}
if ( sequence [ extension_index ] . func ) {
2006-06-29 15:26:41 +00:00
new_offset = sequence [ extension_index ] . func ( tvb , offset , actx , tree , * sequence [ extension_index ] . p_id ) ;
2008-06-19 14:19:13 +00:00
offset + = length * 8 ;
difference = offset - new_offset ;
/* A difference of 7 or less might be byte aligning */
2011-11-16 08:55:02 +00:00
/* Difference could be 8 if open type has no bits and the length is 1 */
if ( ( length > 1 ) & & ( difference > 7 ) ) {
2009-10-18 23:19:44 +00:00
cause = proto_tree_add_text ( tree , tvb , new_offset > > 3 , ( offset - new_offset ) > > 3 ,
2008-06-19 14:19:13 +00:00
" [Possible encoding error full length not decoded. Open type length %u ,decoded %u] " , length , length - ( difference > > 3 ) ) ;
proto_item_set_expert_flags ( cause , PI_MALFORMED , PI_WARN ) ;
2009-10-18 23:19:44 +00:00
expert_add_info_format ( actx - > pinfo , cause , PI_MALFORMED , PI_WARN ,
2008-06-19 14:19:13 +00:00
" Possible encoding error full length not decoded. Open type length %u ,decoded %u " , length , length - ( difference > > 3 ) ) ;
}
2003-07-12 22:35:21 +00:00
} else {
2006-07-03 07:03:57 +00:00
PER_NOT_DECODED_YET ( index_get_field_name ( sequence , extension_index ) ) ;
2008-06-19 14:19:13 +00:00
offset + = length * 8 ;
2003-07-12 22:35:21 +00:00
}
2003-10-27 22:28:48 +00:00
}
2003-07-12 22:35:21 +00:00
}
proto_item_set_len ( item , ( offset > > 3 ) ! = ( old_offset > > 3 ) ? ( offset > > 3 ) - ( old_offset > > 3 ) : 1 ) ;
2006-07-03 07:03:57 +00:00
actx - > created_item = item ;
2003-07-12 22:35:21 +00:00
return offset ;
}
2011-08-09 08:00:06 +00:00
guint32
dissect_per_sequence_eag ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , const per_sequence_t * sequence )
{
gboolean optional_field_flag ;
guint32 i , num_opts ;
guint32 optional_mask ;
DEBUG_ENTRY ( " dissect_per_sequence_eag " ) ;
num_opts = 0 ;
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
if ( sequence [ i ] . optional = = ASN1_OPTIONAL ) {
num_opts + + ;
}
}
optional_mask = 0 ;
for ( i = 0 ; i < num_opts ; i + + ) {
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_optional_field_bit , & optional_field_flag ) ;
if ( tree ) {
proto_item_append_text ( actx - > created_item , " (%s %s present) " ,
index_get_optional_name ( sequence , i ) , optional_field_flag ? " is " : " is NOT " ) ;
}
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
optional_mask < < = 1 ;
if ( optional_field_flag ) {
optional_mask | = 0x01 ;
}
}
for ( i = 0 ; sequence [ i ] . p_id ; i + + ) {
if ( sequence [ i ] . optional = = ASN1_OPTIONAL ) {
gboolean is_present ;
if ( num_opts = = 0 ) {
continue ;
}
is_present = ( 1 < < ( num_opts - 1 ) ) & optional_mask ;
num_opts - - ;
if ( ! is_present ) {
continue ;
}
}
if ( sequence [ i ] . func ) {
offset = sequence [ i ] . func ( tvb , offset , actx , tree , * sequence [ i ] . p_id ) ;
} else {
PER_NOT_DECODED_YET ( index_get_field_name ( sequence , i ) ) ;
}
}
return offset ;
}
2003-07-12 22:35:21 +00:00
2004-02-16 18:31:40 +00:00
/* 15 Encoding the bitstring type
2005-11-14 13:05:17 +00:00
max_len or min_len = = NO_BOUND means there is no lower / upper constraint
2004-02-16 18:31:40 +00:00
*/
2010-05-25 19:29:23 +00:00
static tvbuff_t * dissect_per_bit_string_display ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , header_field_info * hfi , guint32 length )
{
tvbuff_t * out_tvb = NULL ;
2010-08-14 16:42:41 +00:00
guint32 pad_length = 0 ;
guint64 value ;
2011-07-18 19:11:32 +00:00
2011-09-26 15:11:14 +00:00
out_tvb = tvb_new_octet_aligned ( tvb , offset , length ) ;
2011-10-02 15:12:47 +00:00
add_new_data_source ( actx - > pinfo , out_tvb , " Bitstring tvb " ) ;
2011-07-18 19:11:32 +00:00
2010-05-25 19:29:23 +00:00
if ( hfi ) {
2012-05-04 16:35:59 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_index , out_tvb , 0 , - 1 , ENC_BIG_ENDIAN ) ;
2010-05-25 19:29:23 +00:00
proto_item_append_text ( actx - > created_item , " [bit length %u " , length ) ;
if ( length % 8 ) {
pad_length = 8 - ( length % 8 ) ;
2011-01-27 15:48:02 +00:00
proto_item_append_text ( actx - > created_item , " , %u LSB pad bits " , pad_length ) ;
2010-05-25 19:29:23 +00:00
}
2011-07-18 19:11:32 +00:00
2010-11-24 16:35:23 +00:00
if ( length < = 64 ) { /* if read into 64 bits also handle length <= 24, 40, 48, 56 bits */
if ( length < = 8 ) {
value = tvb_get_bits8 ( out_tvb , 0 , length ) ;
} else if ( length < = 16 ) {
2011-10-24 19:57:53 +00:00
value = tvb_get_bits16 ( out_tvb , 0 , length , ENC_BIG_ENDIAN ) ;
2010-11-24 16:35:23 +00:00
} else if ( length < = 24 ) { /* first read 16 and then the remaining bits */
2011-10-24 19:57:53 +00:00
value = tvb_get_bits16 ( out_tvb , 0 , 16 , ENC_BIG_ENDIAN ) ;
2011-10-25 05:46:31 +00:00
value < < = 8 - pad_length ;
2010-11-24 16:35:23 +00:00
value | = tvb_get_bits8 ( out_tvb , 16 , length - 16 ) ;
} else if ( length < = 32 ) {
2011-10-24 19:57:53 +00:00
value = tvb_get_bits32 ( out_tvb , 0 , length , ENC_BIG_ENDIAN ) ;
2010-11-24 16:35:23 +00:00
} else if ( length < = 40 ) { /* first read 32 and then the remaining bits */
2011-10-24 19:57:53 +00:00
value = tvb_get_bits32 ( out_tvb , 0 , 32 , ENC_BIG_ENDIAN ) ;
2011-10-25 05:46:31 +00:00
value < < = 8 - pad_length ;
2010-11-24 16:35:23 +00:00
value | = tvb_get_bits8 ( out_tvb , 32 , length - 32 ) ;
} else if ( length < = 48 ) { /* first read 32 and then the remaining bits */
2011-10-24 19:57:53 +00:00
value = tvb_get_bits32 ( out_tvb , 0 , 32 , ENC_BIG_ENDIAN ) ;
2011-10-25 05:46:31 +00:00
value < < = 16 - pad_length ;
2011-10-24 19:57:53 +00:00
value | = tvb_get_bits16 ( out_tvb , 32 , length - 32 , ENC_BIG_ENDIAN ) ;
2010-11-24 16:35:23 +00:00
} else if ( length < = 56 ) { /* first read 32 and 16 then the remaining bits */
2011-10-24 19:57:53 +00:00
value = tvb_get_bits32 ( out_tvb , 0 , 32 , ENC_BIG_ENDIAN ) ;
2011-10-25 06:08:16 +00:00
value < < = 16 ;
2011-10-24 19:57:53 +00:00
value | = tvb_get_bits16 ( out_tvb , 32 , 16 , ENC_BIG_ENDIAN ) ;
2011-10-25 05:46:31 +00:00
value < < = 8 - pad_length ;
2010-11-24 16:35:23 +00:00
value | = tvb_get_bits8 ( out_tvb , 48 , length - 48 ) ;
} else {
2011-10-24 19:57:53 +00:00
value = tvb_get_bits64 ( out_tvb , 0 , length , ENC_BIG_ENDIAN ) ;
2010-11-24 16:35:23 +00:00
}
2011-07-18 19:11:32 +00:00
proto_item_append_text ( actx - > created_item , " , %s decimal value % " G_GINT64_MODIFIER " u " ,
2011-01-27 15:48:02 +00:00
decode_bits_in_field ( 0 , length , value ) , value ) ;
2010-05-25 19:29:23 +00:00
}
proto_item_append_text ( actx - > created_item , " ] " ) ;
}
return out_tvb ;
}
2004-02-16 18:31:40 +00:00
guint32
2006-07-04 06:49:53 +00:00
dissect_per_bit_string ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , tvbuff_t * * value_tvb )
2004-02-16 18:31:40 +00:00
{
2011-07-18 19:11:32 +00:00
/*gint val_start, val_length;*/
2004-02-16 18:31:40 +00:00
guint32 length ;
header_field_info * hfi ;
2007-09-04 16:57:07 +00:00
tvbuff_t * out_tvb = NULL ;
2004-02-16 18:31:40 +00:00
hfi = ( hf_index = = - 1 ) ? NULL : proto_registrar_get_nth ( hf_index ) ;
DEBUG_ENTRY ( " dissect_per_bit_string " ) ;
/* 15.8 if the length is 0 bytes there will be no encoding */
if ( max_len = = 0 ) {
return offset ;
}
2005-11-14 13:05:17 +00:00
if ( min_len = = NO_BOUND ) {
min_len = 0 ;
2004-02-16 18:31:40 +00:00
}
2009-11-20 21:40:28 +00:00
/* 15.6 If an extension marker is present in the size constraint specification of the bitstring type,
2011-07-18 19:11:32 +00:00
* a single bit shall be added to the field - list in a bit - field of length one .
2009-11-20 21:40:28 +00:00
* The bit shall be set to 1 if the length of this encoding is not within the range of the extension root ,
* and zero otherwise .
*/
if ( has_extension ) {
gboolean extension_present ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( extension_present ) {
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_bit_string_length , & length ) ;
if ( length ) {
/* align to byte */
if ( actx - > aligned ) {
BYTE_ALIGN_OFFSET ( offset ) ;
}
2010-05-25 19:29:23 +00:00
out_tvb = dissect_per_bit_string_display ( tvb , offset , actx , tree , hf_index , hfi , length ) ;
2009-11-20 21:40:28 +00:00
}
2011-07-18 19:11:32 +00:00
/* XXX: ?? */
/*val_start = offset>>3;*/
/*val_length = (length+7)/8;*/
2009-11-20 21:40:28 +00:00
offset + = length ;
if ( value_tvb )
* value_tvb = out_tvb ;
return offset ;
}
}
2004-02-16 18:31:40 +00:00
/* 15.9 if length is fixed and less than or equal to sixteen bits*/
2007-09-18 11:46:50 +00:00
if ( ( min_len = = max_len ) & & ( max_len < = 16 ) ) {
2010-05-25 19:29:23 +00:00
out_tvb = dissect_per_bit_string_display ( tvb , offset , actx , tree , hf_index , hfi , min_len ) ;
2007-09-18 11:46:50 +00:00
offset + = min_len ;
2008-03-19 19:10:31 +00:00
if ( value_tvb )
* value_tvb = out_tvb ;
2004-02-16 18:31:40 +00:00
return offset ;
}
/* 15.10 if length is fixed and less than to 64kbits*/
if ( ( min_len = = max_len ) & & ( min_len < 65536 ) ) {
2009-10-18 23:19:44 +00:00
/* (octet-aligned in the ALIGNED variant)
* align to byte
2007-08-30 19:44:22 +00:00
*/
if ( actx - > aligned ) {
BYTE_ALIGN_OFFSET ( offset ) ;
}
2010-05-25 19:29:23 +00:00
out_tvb = dissect_per_bit_string_display ( tvb , offset , actx , tree , hf_index , hfi , min_len ) ;
2004-02-16 18:31:40 +00:00
offset + = min_len ;
2008-03-19 19:10:31 +00:00
if ( value_tvb )
* value_tvb = out_tvb ;
2004-02-16 18:31:40 +00:00
return offset ;
}
/* 15.11 */
2005-11-14 13:05:17 +00:00
if ( max_len ! = NO_BOUND ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx ,
2005-08-29 10:43:33 +00:00
tree , hf_per_bit_string_length , min_len , max_len ,
2009-11-20 21:40:28 +00:00
& length , FALSE ) ;
2006-05-22 11:49:50 +00:00
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2004-02-16 18:31:40 +00:00
} else {
2006-05-22 11:49:50 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree , hf_per_bit_string_length , & length ) ;
2004-02-16 18:31:40 +00:00
}
if ( length ) {
/* align to byte */
2007-08-30 19:44:22 +00:00
if ( actx - > aligned ) {
BYTE_ALIGN_OFFSET ( offset ) ;
}
2010-05-25 19:29:23 +00:00
out_tvb = dissect_per_bit_string_display ( tvb , offset , actx , tree , hf_index , hfi , length ) ;
2004-02-16 18:31:40 +00:00
}
2011-07-18 19:11:32 +00:00
/* XXX: ?? */
/*val_start = offset>>3;*/
/*val_length = (length+7)/8;*/
2004-02-16 18:31:40 +00:00
offset + = length ;
2006-06-08 06:06:17 +00:00
if ( value_tvb )
2007-09-04 19:36:07 +00:00
* value_tvb = out_tvb ;
2006-06-08 06:06:17 +00:00
2004-02-16 18:31:40 +00:00
return offset ;
}
2003-07-12 22:35:21 +00:00
2007-05-23 13:36:25 +00:00
guint32 dissect_per_bit_string_containing_pdu ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , dissector_t type_cb )
{
tvbuff_t * val_tvb = NULL ;
proto_tree * subtree = tree ;
offset = dissect_per_bit_string ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension , & val_tvb ) ;
if ( type_cb & & val_tvb ) {
subtree = proto_item_add_subtree ( actx - > created_item , ett_per_containing ) ;
type_cb ( val_tvb , actx - > pinfo , subtree ) ;
}
return offset ;
}
guint32 dissect_per_bit_string_containing_pdu_new ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , new_dissector_t type_cb )
{
tvbuff_t * val_tvb = NULL ;
proto_tree * subtree = tree ;
offset = dissect_per_bit_string ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension , & val_tvb ) ;
if ( type_cb & & val_tvb ) {
subtree = proto_item_add_subtree ( actx - > created_item , ett_per_containing ) ;
type_cb ( val_tvb , actx - > pinfo , subtree ) ;
}
return offset ;
}
2003-07-12 22:35:21 +00:00
/* this fucntion dissects an OCTET STRING
16.1
16.2
16.3
16.4
16.5
16.6
16.7
16.8
2005-11-14 13:05:17 +00:00
max_len or min_len = = NO_BOUND means there is no lower / upper constraint
2003-07-31 10:26:36 +00:00
hf_index can either be a FT_BYTES or an FT_STRING
2003-07-12 22:35:21 +00:00
*/
guint32
2007-10-29 19:25:37 +00:00
dissect_per_octet_string ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , tvbuff_t * * value_tvb )
2003-07-12 22:35:21 +00:00
{
2007-09-04 21:49:14 +00:00
gint val_start = 0 , val_length ;
2012-05-02 21:55:59 +00:00
guint32 length = 0 ;
2003-07-31 10:26:36 +00:00
header_field_info * hfi ;
2006-05-16 22:00:18 +00:00
tvbuff_t * out_tvb = NULL ;
2003-07-31 10:26:36 +00:00
2003-08-21 18:00:22 +00:00
hfi = ( hf_index = = - 1 ) ? NULL : proto_registrar_get_nth ( hf_index ) ;
2003-07-12 22:35:21 +00:00
2004-06-24 21:50:05 +00:00
DEBUG_ENTRY ( " dissect_per_octet_string " ) ;
2003-07-12 22:35:21 +00:00
2007-10-29 19:25:37 +00:00
if ( has_extension ) { /* 16.3 an extension marker is present */
gboolean extension_present ;
offset = dissect_per_boolean ( tvb , offset , actx , tree , hf_per_extension_present_bit , & extension_present ) ;
if ( ! display_internal_per_fields ) PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
if ( extension_present ) max_len = NO_BOUND ; /* skip to 16.8 */
}
2005-11-14 13:05:17 +00:00
if ( min_len = = NO_BOUND ) {
min_len = 0 ;
2003-07-12 22:35:21 +00:00
}
2004-06-24 21:50:05 +00:00
if ( max_len = = 0 ) { /* 16.5 if the length is 0 bytes there will be no encoding */
2009-10-18 23:19:44 +00:00
val_start = offset > > 3 ;
2004-06-24 21:50:05 +00:00
val_length = 0 ;
2003-07-12 22:35:21 +00:00
2009-10-18 23:19:44 +00:00
} else if ( ( min_len = = max_len ) & & ( max_len < = 2 ) ) {
2007-09-04 16:57:07 +00:00
/* 16.6 if length is fixed and less than or equal to two bytes*/
2009-10-18 23:19:44 +00:00
val_start = offset > > 3 ;
2007-09-04 16:57:07 +00:00
val_length = min_len ;
2008-04-13 16:42:41 +00:00
out_tvb = new_octet_aligned_subset ( tvb , offset , actx , val_length ) ;
2007-09-04 16:57:07 +00:00
offset + = min_len * 8 ;
2003-07-12 22:35:21 +00:00
2009-10-18 23:19:44 +00:00
} else if ( ( min_len = = max_len ) & & ( min_len < 65536 ) ) {
2007-09-04 16:57:07 +00:00
/* 16.7 if length is fixed and less than to 64k*/
2006-05-16 22:00:18 +00:00
2006-05-22 11:49:50 +00:00
/* align to byte */
if ( actx - > aligned ) {
2007-09-04 16:57:07 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2006-05-16 22:00:18 +00:00
}
2007-09-04 16:57:07 +00:00
val_start = offset > > 3 ;
val_length = min_len ;
2008-04-13 16:42:41 +00:00
out_tvb = new_octet_aligned_subset ( tvb , offset , actx , val_length ) ;
2007-09-04 16:57:07 +00:00
offset + = min_len * 8 ;
2003-07-12 22:35:21 +00:00
2004-06-24 21:50:05 +00:00
} else { /* 16.8 */
2009-10-18 23:19:44 +00:00
if ( max_len > 0 ) {
2006-05-22 11:49:50 +00:00
offset = dissect_per_constrained_integer ( tvb , offset , actx , tree ,
2007-09-04 16:57:07 +00:00
hf_per_octet_string_length , min_len , max_len , & length , FALSE ) ;
2009-10-18 23:19:44 +00:00
if ( ! display_internal_per_fields )
2007-09-04 16:57:07 +00:00
PROTO_ITEM_SET_HIDDEN ( actx - > created_item ) ;
2004-06-24 21:50:05 +00:00
} else {
2009-10-18 23:19:44 +00:00
offset = dissect_per_length_determinant ( tvb , offset , actx , tree ,
2004-06-24 21:50:05 +00:00
hf_per_octet_string_length , & length ) ;
}
2003-08-31 00:49:37 +00:00
2004-06-24 21:50:05 +00:00
if ( length ) {
/* align to byte */
2006-05-22 11:49:50 +00:00
if ( actx - > aligned ) {
2006-05-13 12:06:56 +00:00
BYTE_ALIGN_OFFSET ( offset ) ;
2006-05-16 22:00:18 +00:00
}
2008-04-13 16:42:41 +00:00
out_tvb = new_octet_aligned_subset ( tvb , offset , actx , length ) ;
2006-05-31 13:38:10 +00:00
} else {
2009-10-18 23:19:44 +00:00
val_start = offset > > 3 ;
2003-08-31 00:49:37 +00:00
}
2004-06-24 21:50:05 +00:00
val_length = length ;
2007-09-04 16:57:07 +00:00
offset + = length * 8 ;
2003-07-12 22:35:21 +00:00
}
2004-06-24 21:50:05 +00:00
if ( hfi ) {
if ( IS_FT_UINT ( hfi - > type ) | | IS_FT_INT ( hfi - > type ) ) {
2007-09-04 16:57:07 +00:00
/* If the type has been converted to FT_UINT or FT_INT in the .cnf file
* display the length of this octet string instead of the octetstring itself
*/
2004-06-24 21:50:05 +00:00
if ( IS_FT_UINT ( hfi - > type ) )
2007-09-04 16:57:07 +00:00
actx - > created_item = proto_tree_add_uint ( tree , hf_index , out_tvb , 0 , val_length , val_length ) ;
2004-06-24 21:50:05 +00:00
else
2007-09-04 16:57:07 +00:00
actx - > created_item = proto_tree_add_int ( tree , hf_index , out_tvb , 0 , val_length , val_length ) ;
2007-09-06 16:28:08 +00:00
proto_item_append_text ( actx - > created_item , plurality ( val_length , " octet " , " octets " ) ) ;
2004-06-24 21:50:05 +00:00
} else {
2007-09-04 16:57:07 +00:00
if ( out_tvb ) {
2012-05-04 16:35:59 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_index , out_tvb , 0 , val_length , ENC_BIG_ENDIAN ) ;
2007-09-04 16:57:07 +00:00
} else {
/* Length = 0 */
2012-05-04 16:35:59 +00:00
actx - > created_item = proto_tree_add_item ( tree , hf_index , tvb , val_start , val_length , ENC_BIG_ENDIAN ) ;
2004-06-24 21:50:05 +00:00
}
2003-07-31 10:26:36 +00:00
}
2003-07-12 22:35:21 +00:00
}
2006-05-31 13:38:10 +00:00
2005-07-04 09:35:25 +00:00
if ( value_tvb )
2006-05-31 13:38:10 +00:00
* value_tvb = ( out_tvb ) ? out_tvb : tvb_new_subset ( tvb , val_start , val_length , val_length ) ;
2003-07-12 22:35:21 +00:00
return offset ;
}
2007-10-29 19:25:37 +00:00
guint32 dissect_per_octet_string_containing_pdu ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , dissector_t type_cb )
2007-05-23 13:36:25 +00:00
{
tvbuff_t * val_tvb = NULL ;
proto_tree * subtree = tree ;
2007-10-29 19:25:37 +00:00
offset = dissect_per_octet_string ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension , & val_tvb ) ;
2007-05-23 13:36:25 +00:00
if ( type_cb & & val_tvb ) {
subtree = proto_item_add_subtree ( actx - > created_item , ett_per_containing ) ;
type_cb ( val_tvb , actx - > pinfo , subtree ) ;
}
return offset ;
}
2007-10-29 19:25:37 +00:00
guint32 dissect_per_octet_string_containing_pdu_new ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , int min_len , int max_len , gboolean has_extension , new_dissector_t type_cb )
2007-05-23 13:36:25 +00:00
{
tvbuff_t * val_tvb = NULL ;
proto_tree * subtree = tree ;
2007-10-29 19:25:37 +00:00
offset = dissect_per_octet_string ( tvb , offset , actx , tree , hf_index , min_len , max_len , has_extension , & val_tvb ) ;
2007-05-23 13:36:25 +00:00
if ( type_cb & & val_tvb ) {
subtree = proto_item_add_subtree ( actx - > created_item , ett_per_containing ) ;
type_cb ( val_tvb , actx - > pinfo , subtree ) ;
}
return offset ;
}
2007-12-28 10:42:44 +00:00
guint32 dissect_per_size_constrained_type ( tvbuff_t * tvb , guint32 offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index , per_type_fn type_cb , const gchar * name , int min_len , int max_len , gboolean has_extension )
{
asn1_stack_frame_push ( actx , name ) ;
asn1_param_push_integer ( actx , min_len ) ;
asn1_param_push_integer ( actx , max_len ) ;
asn1_param_push_boolean ( actx , has_extension ) ;
offset = type_cb ( tvb , offset , actx , tree , hf_index ) ;
asn1_stack_frame_pop ( actx , name ) ;
return offset ;
}
gboolean get_size_constraint_from_stack ( asn1_ctx_t * actx , const gchar * name , int * pmin_len , int * pmax_len , gboolean * phas_extension )
{
asn1_par_t * par ;
if ( pmin_len ) * pmin_len = NO_BOUND ;
if ( pmax_len ) * pmax_len = NO_BOUND ;
if ( phas_extension ) * phas_extension = FALSE ;
if ( ! actx - > stack ) return FALSE ;
if ( strcmp ( actx - > stack - > name , name ) ) return FALSE ;
par = actx - > stack - > par ;
if ( ! par | | ( par - > ptype ! = ASN1_PAR_INTEGER ) ) return FALSE ;
if ( pmin_len ) * pmin_len = par - > value . v_integer ;
par = par - > next ;
if ( ! par | | ( par - > ptype ! = ASN1_PAR_INTEGER ) ) return FALSE ;
if ( pmax_len ) * pmax_len = par - > value . v_integer ;
par = par - > next ;
if ( ! par | | ( par - > ptype ! = ASN1_PAR_BOOLEAN ) ) return FALSE ;
if ( phas_extension ) * phas_extension = par - > value . v_boolean ;
return TRUE ;
}
2007-05-23 13:36:25 +00:00
2007-05-02 12:13:29 +00:00
/* 26 Encoding of a value of the external type */
/* code generated from definition in 26.1 */
2007-05-07 11:25:21 +00:00
/*
[ UNIVERSAL 8 ] IMPLICIT SEQUENCE {
direct - reference OBJECT IDENTIFIER OPTIONAL ,
indirect - reference INTEGER OPTIONAL ,
data - value - descriptor ObjectDescriptor OPTIONAL ,
encoding CHOICE {
single - ASN1 - type [ 0 ] ABSTRACT - SYNTAX . & Type ,
octet - aligned [ 1 ] IMPLICIT OCTET STRING ,
2009-10-18 23:19:44 +00:00
arbitrary [ 2 ] IMPLICIT BIT STRING
}
2007-05-07 11:25:21 +00:00
}
*/
2008-01-23 20:15:13 +00:00
/* NOTE: This sequence type differs from that in ITU-T Rec. X.680 | ISO/IEC 8824-1 for historical reasons. */
2007-05-07 11:25:21 +00:00
2007-05-02 12:13:29 +00:00
static int
2012-05-02 21:55:59 +00:00
dissect_per_T_direct_reference ( tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-06-14 05:17:07 +00:00
offset = dissect_per_object_identifier_str ( tvb , offset , actx , tree , hf_index , & actx - > external . direct_reference ) ;
2007-05-02 12:13:29 +00:00
2007-10-22 12:25:56 +00:00
actx - > external . direct_ref_present = TRUE ;
2007-05-02 12:13:29 +00:00
return offset ;
}
static int
dissect_per_T_indirect_reference ( tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ ) {
2007-05-07 11:25:21 +00:00
offset = dissect_per_integer ( tvb , offset , actx , tree , hf_index , & actx - > external . indirect_reference ) ;
2007-05-02 12:13:29 +00:00
2007-10-22 12:25:56 +00:00
actx - > external . indirect_ref_present = TRUE ;
2007-05-02 12:13:29 +00:00
return offset ;
}
static int
2012-05-02 21:55:59 +00:00
dissect_per_T_data_value_descriptor ( tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-05-02 12:13:29 +00:00
offset = dissect_per_object_descriptor ( tvb , offset , actx , tree , hf_index , & actx - > external . data_value_descriptor ) ;
2007-10-22 12:25:56 +00:00
actx - > external . data_value_descr_present = TRUE ;
2007-05-02 12:13:29 +00:00
return offset ;
}
static int
dissect_per_T_single_ASN1_type ( tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ ) {
2007-07-13 11:25:53 +00:00
offset = dissect_per_open_type ( tvb , offset , actx , tree , actx - > external . hf_index , actx - > external . u . per . type_cb ) ;
2007-05-02 12:13:29 +00:00
return offset ;
}
static int
2012-05-02 21:55:59 +00:00
dissect_per_T_octet_aligned ( tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-05-02 12:13:29 +00:00
offset = dissect_per_octet_string ( tvb , offset , actx , tree , hf_index ,
2007-10-29 19:25:37 +00:00
NO_BOUND , NO_BOUND , FALSE , & actx - > external . octet_aligned ) ;
2007-05-02 12:13:29 +00:00
2007-07-13 11:25:53 +00:00
if ( actx - > external . u . per . type_cb ) {
actx - > external . u . per . type_cb ( actx - > external . octet_aligned , 0 , actx , tree , actx - > external . hf_index ) ;
2007-05-02 12:13:29 +00:00
} else {
2007-05-07 11:25:21 +00:00
actx - > created_item = proto_tree_add_text ( tree , actx - > external . octet_aligned , 0 , - 1 , " Unknown EXTERNAL Type " ) ;
2007-05-02 12:13:29 +00:00
}
return offset ;
}
static int
2012-05-02 21:55:59 +00:00
dissect_per_T_arbitrary ( tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-05-02 12:13:29 +00:00
offset = dissect_per_bit_string ( tvb , offset , actx , tree , hf_index ,
2007-05-07 11:25:21 +00:00
NO_BOUND , NO_BOUND , FALSE , & actx - > external . arbitrary ) ;
2007-05-02 12:13:29 +00:00
2007-07-13 11:25:53 +00:00
if ( actx - > external . u . per . type_cb ) {
actx - > external . u . per . type_cb ( actx - > external . arbitrary , 0 , actx , tree , actx - > external . hf_index ) ;
2007-05-02 12:13:29 +00:00
} else {
2007-05-07 11:25:21 +00:00
actx - > created_item = proto_tree_add_text ( tree , actx - > external . arbitrary , 0 , - 1 , " Unknown EXTERNAL Type " ) ;
2007-05-02 12:13:29 +00:00
}
return offset ;
}
static const value_string per_External_encoding_vals [ ] = {
{ 0 , " single-ASN1-type " } ,
{ 1 , " octet-aligned " } ,
{ 2 , " arbitrary " } ,
{ 0 , NULL }
} ;
static const per_choice_t External_encoding_choice [ ] = {
{ 0 , & hf_per_single_ASN1_type , ASN1_NO_EXTENSIONS , dissect_per_T_single_ASN1_type } ,
{ 1 , & hf_per_octet_aligned , ASN1_NO_EXTENSIONS , dissect_per_T_octet_aligned } ,
{ 2 , & hf_per_arbitrary , ASN1_NO_EXTENSIONS , dissect_per_T_arbitrary } ,
{ 0 , NULL , 0 , NULL }
} ;
static int
2012-05-02 21:55:59 +00:00
dissect_per_External_encoding ( tvbuff_t * tvb , int offset , asn1_ctx_t * actx , proto_tree * tree , int hf_index ) {
2007-05-02 12:13:29 +00:00
offset = dissect_per_choice ( tvb , offset , actx , tree , hf_index ,
ett_per_External_encoding , External_encoding_choice ,
2007-05-07 11:25:21 +00:00
& actx - > external . encoding ) ;
2007-05-02 12:13:29 +00:00
return offset ;
}
static const per_sequence_t External_sequence [ ] = {
{ & hf_per_direct_reference , ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_per_T_direct_reference } ,
{ & hf_per_indirect_reference , ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_per_T_indirect_reference } ,
{ & hf_per_data_value_descriptor , ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_per_T_data_value_descriptor } ,
{ & hf_per_encoding , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL , dissect_per_External_encoding } ,
{ NULL , 0 , 0 , NULL }
} ;
static int
dissect_per_External ( tvbuff_t * tvb _U_ , int offset _U_ , asn1_ctx_t * actx _U_ , proto_tree * tree _U_ , int hf_index _U_ ) {
offset = dissect_per_sequence ( tvb , offset , actx , tree , hf_index ,
ett_per_External , External_sequence ) ;
return offset ;
}
2009-10-18 23:19:44 +00:00
guint32
2007-05-02 12:26:26 +00:00
dissect_per_external_type ( tvbuff_t * tvb _U_ , guint32 offset , asn1_ctx_t * actx , proto_tree * tree _U_ , int hf_index _U_ , per_type_fn type_cb )
2007-05-02 12:13:29 +00:00
{
asn1_ctx_clean_external ( actx ) ;
2007-07-13 11:25:53 +00:00
actx - > external . u . per . type_cb = type_cb ;
2007-05-02 12:48:22 +00:00
offset = dissect_per_External ( tvb , offset , actx , tree , hf_index ) ;
2007-05-02 12:13:29 +00:00
asn1_ctx_clean_external ( actx ) ;
return offset ;
}
2003-07-12 22:35:21 +00:00
void
proto_register_per ( void )
{
static hf_register_info hf [ ] =
{
{ & hf_per_num_sequence_extensions ,
{ " Number of Sequence Extensions " , " per.num_sequence_extensions " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Number of extensions encoded in this sequence " , HFILL } } ,
2005-09-09 15:36:39 +00:00
{ & hf_per_choice_index ,
{ " Choice Index " , " per.choice_index " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Which index of the Choice within extension root is encoded " , HFILL } } ,
{ & hf_per_choice_extension_index ,
{ " Choice Extension Index " , " per.choice_extension_index " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Which index of the Choice within extension addition is encoded " , HFILL } } ,
2006-03-08 13:50:04 +00:00
{ & hf_per_enum_index ,
{ " Enumerated Index " , " per.enum_index " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Which index of the Enumerated within extension root is encoded " , HFILL } } ,
{ & hf_per_enum_extension_index ,
{ " Enumerated Extension Index " , " per.enum_extension_index " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Which index of the Enumerated within extension addition is encoded " , HFILL } } ,
2003-07-12 22:35:21 +00:00
{ & hf_per_GeneralString_length ,
{ " GeneralString Length " , " per.generalstring_length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Length of the GeneralString " , HFILL } } ,
{ & hf_per_extension_bit ,
{ " Extension Bit " , " per.extension_bit " , FT_BOOLEAN , 8 ,
TFS ( & tfs_extension_bit ) , 0x01 , " The extension bit of an aggregate " , HFILL } } ,
{ & hf_per_extension_present_bit ,
{ " Extension Present Bit " , " per.extension_present_bit " , FT_BOOLEAN , 8 ,
TFS ( & tfs_extension_present_bit ) , 0x01 , " Whether this optional extension is present or not " , HFILL } } ,
{ & hf_per_small_number_bit ,
{ " Small Number Bit " , " per.small_number_bit " , FT_BOOLEAN , 8 ,
TFS ( & tfs_small_number_bit ) , 0x01 , " The small number bit for a section 10.6 integer " , HFILL } } ,
{ & hf_per_optional_field_bit ,
{ " Optional Field Bit " , " per.optional_field_bit " , FT_BOOLEAN , 8 ,
TFS ( & tfs_optional_field_bit ) , 0x01 , " This bit specifies the presence/absence of an optional field " , HFILL } } ,
{ & hf_per_sequence_of_length ,
{ " Sequence-Of Length " , " per.sequence_of_length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Number of items in the Sequence Of " , HFILL } } ,
{ & hf_per_object_identifier_length ,
2007-05-03 09:15:04 +00:00
{ " Object Identifier Length " , " per.object_length " , FT_UINT32 , BASE_DEC ,
2003-07-12 22:35:21 +00:00
NULL , 0 , " Length of the object identifier " , HFILL } } ,
{ & hf_per_open_type_length ,
{ " Open Type Length " , " per.open_type_length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Length of an open type encoding " , HFILL } } ,
2007-05-03 09:15:04 +00:00
{ & hf_per_real_length ,
2008-12-20 00:09:02 +00:00
{ " Real Length " , " per.real_length " , FT_UINT32 , BASE_DEC ,
2007-05-03 09:15:04 +00:00
NULL , 0 , " Length of an real encoding " , HFILL } } ,
2003-07-12 22:35:21 +00:00
{ & hf_per_octet_string_length ,
{ " Octet String Length " , " per.octet_string_length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Number of bytes in the Octet String " , HFILL } } ,
2004-02-16 18:31:40 +00:00
{ & hf_per_bit_string_length ,
{ " Bit String Length " , " per.bit_string_length " , FT_UINT32 , BASE_DEC ,
NULL , 0 , " Number of bits in the Bit String " , HFILL } } ,
2005-10-10 20:38:28 +00:00
{ & hf_per_const_int_len ,
2012-08-01 02:59:17 +00:00
{ " Constrained Integer Length " , " per.const_int_len " , FT_UINT32 , BASE_DEC ,
2005-10-10 20:38:28 +00:00
NULL , 0 , " Number of bytes in the Constrained Integer " , HFILL } } ,
2007-05-02 12:13:29 +00:00
{ & hf_per_direct_reference ,
{ " direct-reference " , " per.direct_reference " ,
FT_OID , BASE_NONE , NULL , 0 ,
" per.T_direct_reference " , HFILL } } ,
{ & hf_per_indirect_reference ,
{ " indirect-reference " , " per.indirect_reference " ,
FT_INT32 , BASE_DEC , NULL , 0 ,
" per.T_indirect_reference " , HFILL } } ,
{ & hf_per_data_value_descriptor ,
{ " data-value-descriptor " , " per.data_value_descriptor " ,
FT_STRING , BASE_NONE , NULL , 0 ,
" per.T_data_value_descriptor " , HFILL } } ,
{ & hf_per_encoding ,
{ " encoding " , " per.encoding " ,
FT_UINT32 , BASE_DEC , VALS ( per_External_encoding_vals ) , 0 ,
" per.External_encoding " , HFILL } } ,
{ & hf_per_single_ASN1_type ,
{ " single-ASN1-type " , " per.single_ASN1_type " ,
FT_NONE , BASE_NONE , NULL , 0 ,
" per.T_single_ASN1_type " , HFILL } } ,
{ & hf_per_octet_aligned ,
{ " octet-aligned " , " per.octet_aligned " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
FT_BYTES , BASE_NONE , NULL , 0 ,
2007-05-02 12:13:29 +00:00
" per.T_octet_aligned " , HFILL } } ,
{ & hf_per_arbitrary ,
{ " arbitrary " , " per.arbitrary " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
FT_BYTES , BASE_NONE , NULL , 0 ,
2007-05-02 12:13:29 +00:00
" per.T_arbitrary " , HFILL } } ,
2009-04-10 09:24:10 +00:00
{ & hf_per_integer_length ,
{ " integer length " , " per.integer_length " ,
2011-01-27 15:48:02 +00:00
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
{ & hf_per_debug_pos ,
{ " Current bit offset " , " per.debug_pos " ,
2009-04-10 09:24:10 +00:00
FT_UINT32 , BASE_DEC , NULL , 0 ,
NULL , HFILL } } ,
2003-07-12 22:35:21 +00:00
} ;
static gint * ett [ ] =
{
2007-05-14 13:39:31 +00:00
& ett_per_open_type ,
2007-05-23 13:36:25 +00:00
& ett_per_containing ,
2007-05-02 12:13:29 +00:00
& ett_per_sequence_of_item ,
& ett_per_External ,
& ett_per_External_encoding ,
2003-07-12 22:35:21 +00:00
} ;
module_t * per_module ;
2003-08-25 00:00:20 +00:00
proto_per = proto_register_protocol ( " Packed Encoding Rules (ASN.1 X.691) " , " PER " , " per " ) ;
2003-07-12 22:35:21 +00:00
proto_register_field_array ( proto_per , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2004-03-25 23:58:06 +00:00
proto_set_cant_toggle ( proto_per ) ;
2003-07-12 22:35:21 +00:00
per_module = prefs_register_protocol ( proto_per , NULL ) ;
prefs_register_bool_preference ( per_module , " display_internal_per_fields " ,
" Display the internal PER fields in the tree " ,
" Whether the dissector should put the internal PER data in the tree or if it should hide it " ,
& display_internal_per_fields ) ;
}
void
proto_reg_handoff_per ( void )
{
}