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
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <epan/packet.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2007-05-03 09:15:04 +00:00
|
|
|
#include <stdlib.h>
|
2003-07-12 22:35:21 +00:00
|
|
|
#include <string.h>
|
2007-05-03 09:15:04 +00:00
|
|
|
#include <math.h>
|
2003-07-12 22:35:21 +00:00
|
|
|
|
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 */
|
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;}
|
|
|
|
|
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;
|
|
|
|
|
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;
|
2008-03-18 20:10:50 +00:00
|
|
|
buf = ep_alloc(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);
|
|
|
|
}
|
2008-03-18 20:10:50 +00:00
|
|
|
sub_tvb = tvb_new_real_data(buf, actual_length, length);
|
2007-05-03 09:15:04 +00:00
|
|
|
tvb_set_child_real_data_tvbuff(tvb, sub_tvb);
|
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
|
|
|
|
2007-09-04 16:57:07 +00:00
|
|
|
static const guint16 bit_mask16[] = {
|
|
|
|
0xffff,
|
|
|
|
0x7fff,
|
|
|
|
0x3fff,
|
|
|
|
0x1fff,
|
|
|
|
0x0fff,
|
|
|
|
0x07ff,
|
|
|
|
0x03ff,
|
|
|
|
0x01ff
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Fetch a number of bits to a new tvb right adjusted to the nearest number of bytes.
|
|
|
|
* (add proceeding zeros).
|
|
|
|
*/
|
2008-04-13 16:42:41 +00:00
|
|
|
static tvbuff_t *new_octet_aligned_subset_bits(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, guint32 no_of_bits)
|
2007-09-04 16:57:07 +00:00
|
|
|
{
|
|
|
|
tvbuff_t *sub_tvb = NULL;
|
|
|
|
guint32 boffset = offset >> 3;
|
|
|
|
unsigned int i, shift0, shift1;
|
|
|
|
guint8 octet0, octet1, *buf;
|
|
|
|
guint16 word;
|
|
|
|
|
|
|
|
guint32 length;
|
|
|
|
guint32 remainder;
|
|
|
|
|
|
|
|
/* Calculate the size reqired */
|
|
|
|
|
|
|
|
length = no_of_bits/8;
|
|
|
|
remainder = no_of_bits % 8;
|
|
|
|
if(remainder){
|
|
|
|
length++;
|
|
|
|
}else{
|
|
|
|
/* Number of bits = even number of octets */
|
2008-04-13 16:42:41 +00:00
|
|
|
return new_octet_aligned_subset(tvb, offset, actx, length);
|
2007-09-04 16:57:07 +00:00
|
|
|
}
|
|
|
|
buf = ep_alloc(length);
|
|
|
|
|
|
|
|
/* get the 'odd' bits */
|
|
|
|
shift1 = offset & 0x07;
|
|
|
|
word = tvb_get_ntohs(tvb,boffset) & bit_mask16[offset & 0x07];
|
|
|
|
word = word >> (16-(shift1+remainder));
|
|
|
|
buf[0] = word & 0x00ff;
|
|
|
|
|
|
|
|
offset = offset + remainder;
|
|
|
|
boffset = offset >> 3;
|
|
|
|
if (length >1){
|
|
|
|
shift1 = offset & 0x07;
|
|
|
|
shift0 = 8 - shift1;
|
|
|
|
octet0 = tvb_get_guint8(tvb, boffset);
|
|
|
|
for (i=1; i<length; i++) {
|
|
|
|
octet1 = octet0;
|
|
|
|
octet0 = tvb_get_guint8(tvb, boffset + i);
|
|
|
|
buf[i] = (octet1 << shift1) | (octet0 >> shift0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sub_tvb = tvb_new_real_data(buf, length, length);
|
|
|
|
tvb_set_child_real_data_tvbuff(tvb, sub_tvb);
|
2008-04-13 16:42:41 +00:00
|
|
|
add_new_data_source(actx->pinfo, sub_tvb, "Unaligned OCTET STRING");
|
2007-09-04 16:57:07 +00:00
|
|
|
|
|
|
|
return sub_tvb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-06-05 06:49:52 +00:00
|
|
|
/* 10 Encoding procedures -------------------------------------------------- */
|
|
|
|
|
|
|
|
/* 10.2 Open type fields --------------------------------------------------- */
|
2007-05-14 13:39:31 +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 {
|
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, val_tvb, 0, type_length, FALSE);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-05-14 13:39:31 +00:00
|
|
|
guint32
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
guint32
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
guint32
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2006-09-27 19:30:22 +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
|
|
|
|
(with the length count in components of a sequence-of or set-of).
|
|
|
|
|
|
|
|
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 64K, 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)
|
|
|
|
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 16K) two octets containing "n" with bit 8 of the first octet set to 1 and bit 7 set to zero;
|
|
|
|
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
|
|
|
|
(a multiple "m" of 16K items). For all values of "m", the fragment is then followed by another length encoding
|
|
|
|
for the remainder of the material.
|
|
|
|
|
|
|
|
NOTE 3 - (Tutorial) In the UNALIGNED variant, if the length count is bounded above by an upper bound that is less
|
|
|
|
than 64K, 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
|
|
|
|
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;
|
|
|
|
int i, bit;
|
|
|
|
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;
|
|
|
|
gint val_start;
|
|
|
|
|
|
|
|
val_start = offset>>3;
|
|
|
|
val = 0;
|
|
|
|
str=ep_alloc(256);
|
|
|
|
|
|
|
|
g_snprintf(str, 256, " ");
|
|
|
|
for(bit=0;bit<((int)(offset&0x07));bit++){
|
|
|
|
if(bit&&(!(bit%4))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2006-09-27 19:30:22 +00:00
|
|
|
}
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str,".", 256);
|
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))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2006-09-27 19:30:22 +00:00
|
|
|
}
|
|
|
|
if(bit&&(!(bit%8))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
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;
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "1", 256);
|
2006-09-27 19:30:22 +00:00
|
|
|
} else {
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "0", 256);
|
2006-09-27 19:30:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if((val&0x80)==0){
|
|
|
|
*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
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
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
|
|
|
{
|
|
|
|
gboolean small_number;
|
|
|
|
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++){
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_boolean(tvb, offset, actx, tree, -1, &small_number);
|
2003-07-12 22:35:21 +00:00
|
|
|
*length<<=1;
|
|
|
|
if(small_number){
|
|
|
|
*length|=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(hf_index!=-1){
|
|
|
|
if((offset&0x07)<7){
|
2005-08-29 10:43:33 +00:00
|
|
|
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
|
2003-07-12 22:35:21 +00:00
|
|
|
} else {
|
2005-08-29 10:43:33 +00:00
|
|
|
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3), 1, *length);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
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
|
|
|
|
|
|
|
proto_tree_add_item(tree, hf_index, tvb, offset>>3, length, FALSE);
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
ti_tmp = proto_tree_add_item(tree, hf_index, tvb, offset>>8, 0, FALSE);
|
|
|
|
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)) {
|
|
|
|
item = proto_tree_add_uint(parent_tree, hf_index, tvb, offset>>3, 0, length);
|
|
|
|
proto_item_append_text(item, (length==1)?" item":" items");
|
|
|
|
} else {
|
|
|
|
item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* dissect a constrained IA5String that consists of the full ASCII set,
|
2003-10-27 22:28:48 +00:00
|
|
|
i.e. no FROM stuff limiting the alphabet
|
2003-07-12 22:35:21 +00:00
|
|
|
*/
|
|
|
|
guint32
|
2006-07-04 06:49:53 +00:00
|
|
|
dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len)
|
2003-07-12 22:35:21 +00:00
|
|
|
{
|
2007-10-29 19:25:37 +00:00
|
|
|
offset=dissect_per_octet_string(tvb, offset, actx, tree, hf_index, min_len, max_len, FALSE, NULL);
|
2003-07-12 22:35:21 +00:00
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2003-07-13 01:43:33 +00:00
|
|
|
/* XXX we dont do >64k length strings yet */
|
2005-08-29 10:43:33 +00:00
|
|
|
static guint32
|
2006-07-04 06:49:53 +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, 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) {
|
|
|
|
*value_tvb = tvb_new_real_data(NULL, 0, 0);
|
2005-08-18 18:12:55 +00:00
|
|
|
tvb_set_child_real_data_tvbuff(tvb, *value_tvb);
|
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
|
|
|
}
|
|
|
|
|
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){
|
|
|
|
/* there is no string at all, so dont 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;
|
|
|
|
}
|
2004-10-11 12:00:08 +00:00
|
|
|
/* ALIGNED PER does not do any remapping of chars if
|
|
|
|
bitsperchar is 8
|
|
|
|
*/
|
|
|
|
if(bits_per_char==8){
|
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) {
|
|
|
|
*value_tvb = tvb_new_real_data(buf, length, length);
|
2005-08-18 18:12:55 +00:00
|
|
|
tvb_set_free_cb(*value_tvb, g_free);
|
|
|
|
tvb_set_child_real_data_tvbuff(tvb, *value_tvb);
|
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
|
2006-07-04 06:49:53 +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, 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);
|
|
|
|
}
|
2006-05-22 11:49:50 +00:00
|
|
|
return dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, alphabet_ptr, alphabet_length, value_tvb);
|
2005-08-29 10:43:33 +00:00
|
|
|
}
|
|
|
|
|
2003-07-13 01:43:33 +00:00
|
|
|
guint32
|
2006-07-04 06:49:53 +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)
|
2003-07-13 01:43:33 +00:00
|
|
|
{
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len,
|
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
|
2006-07-04 06:49:53 +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)
|
2003-07-19 03:45:04 +00:00
|
|
|
{
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len,
|
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
|
2006-07-04 06:49:53 +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)
|
2005-01-17 10:09:43 +00:00
|
|
|
{
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len,
|
2005-08-18 14:32:49 +00:00
|
|
|
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 95, NULL);
|
2005-01-17 10:09:43 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
guint32
|
2006-07-04 06:49:53 +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)
|
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;
|
|
|
|
}
|
|
|
|
|
2005-08-10 14:17:27 +00:00
|
|
|
str = tvb_get_ephemeral_faked_unicode(tvb, offset>>3, length, FALSE);
|
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
|
|
|
|
2007-05-02 12:13:29 +00:00
|
|
|
guint32
|
|
|
|
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
|
2006-07-04 06:49:53 +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)
|
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");
|
|
|
|
|
|
|
|
/* 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 {
|
|
|
|
item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this function dissects a constrained set of */
|
|
|
|
guint32
|
2006-07-04 06:49:53 +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)
|
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");
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_constrained_sequence_of(tvb, offset, actx, parent_tree, hf_index, ett_index, seq, min_len, max_len);
|
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);
|
2005-12-05 17:24:19 +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) {
|
2008-01-03 08:19:27 +00:00
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, val_tvb, 0, length, FALSE);
|
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
|
2006-07-04 06:49: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_string)
|
2005-09-20 10:56:08 +00:00
|
|
|
{
|
|
|
|
tvbuff_t *value_tvb = NULL;
|
|
|
|
guint length;
|
|
|
|
|
2006-05-22 11:49:50 +00:00
|
|
|
offset = dissect_per_object_identifier(tvb, offset, actx, tree, hf_index, (value_string) ? &value_tvb : NULL);
|
2005-09-20 10:56:08 +00:00
|
|
|
|
|
|
|
if (value_string) {
|
|
|
|
if (value_tvb && (length = tvb_length(value_tvb))) {
|
2007-11-01 22:07:43 +00:00
|
|
|
*value_string = oid_encoded2string(tvb_get_ptr(value_tvb, 0, length), length);
|
2005-09-20 10:56:08 +00:00
|
|
|
} else {
|
|
|
|
*value_string = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
2003-07-12 22:35:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* this function reads a single bit */
|
|
|
|
guint32
|
2006-07-04 06:49:53 +00:00
|
|
|
dissect_per_boolean(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _U_, proto_tree *tree, int hf_index, gboolean *bool)
|
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);
|
2005-08-20 02:51:13 +00:00
|
|
|
str=ep_alloc(256);
|
|
|
|
g_snprintf(str, 256, "%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
|
|
|
);
|
2006-05-22 11:49:50 +00:00
|
|
|
actx->created_item = proto_tree_add_boolean_format(tree, hf_index, tvb, offset>>3, 1, value, str);
|
|
|
|
} else {
|
|
|
|
actx->created_item = NULL;
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(bool){
|
|
|
|
*bool=value;
|
|
|
|
}
|
|
|
|
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 */
|
2006-05-22 11:49:50 +00:00
|
|
|
offset=dissect_per_length_determinant(tvb, offset, actx, tree, -1, &length);
|
2003-07-12 22:35:21 +00:00
|
|
|
/* gassert here? */
|
|
|
|
if(length>4){
|
2004-05-17 20:03:36 +00:00
|
|
|
PER_NOT_DECODED_YET("too long 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){
|
|
|
|
PER_NOT_DECODED_YET("too long integer");
|
|
|
|
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;
|
|
|
|
int pad;
|
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);
|
|
|
|
|
2006-05-13 12:06:56 +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".
|
|
|
|
* 10.5.7 In the case of the ALIGNED variant the encoding depends on whether
|
|
|
|
* d) "range" is greater than 64K (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
|
|
|
}
|
|
|
|
|
|
|
|
num_bits=0;
|
|
|
|
pad=0;
|
|
|
|
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;
|
|
|
|
val = min;
|
2006-05-22 11:49:50 +00:00
|
|
|
} else if((range<=255)||(!actx->aligned)) {
|
2006-05-13 12:06:56 +00:00
|
|
|
/* 10.5.7.1
|
|
|
|
* 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;
|
2003-07-12 22:35:21 +00:00
|
|
|
int i, bit, 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
|
|
|
|
2003-07-12 22:35:21 +00:00
|
|
|
/* prepare the string */
|
2005-08-20 02:51:13 +00:00
|
|
|
str=ep_alloc(256);
|
|
|
|
g_snprintf(str, 256, "%s: ", hfi->name);
|
2003-07-12 22:35:21 +00:00
|
|
|
for(bit=0;bit<((int)(offset&0x07));bit++){
|
|
|
|
if(bit&&(!(bit%4))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str,".", 256);
|
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))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
if(bit&&(!(bit%8))){
|
|
|
|
length+=1;
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
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;
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "1", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
} else {
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "0", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for(;bit%8;bit++){
|
|
|
|
if(bit&&(!(bit%4))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str,".", 256);
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
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)
|
2006-09-29 11:09:17 +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 */
|
|
|
|
num_bits=8;
|
|
|
|
pad=7-(offset&0x07);
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
num_bits=16;
|
|
|
|
pad=7-(offset&0x07);
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
} else if (IS_FT_INT(hfi->type)) {
|
|
|
|
it = proto_tree_add_int(tree, hf_index, tvb, val_start, val_length, val);
|
|
|
|
} 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;
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
proto_item *it=NULL;
|
|
|
|
guint64 range, val;
|
|
|
|
gint val_start, val_length;
|
|
|
|
nstime_t timeval;
|
|
|
|
header_field_info *hfi;
|
|
|
|
int num_bits;
|
|
|
|
int pad;
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* 10.5.3 Let "range" be defined as the integer value ("ub" - "lb" 1), and let the value to be encoded be "n".
|
|
|
|
* 10.5.7 In the case of the ALIGNED variant the encoding depends on whether
|
|
|
|
* d) "range" is greater than 64K (the indefinite length case).
|
|
|
|
*/
|
|
|
|
if(((max-min)>65536)&&(actx->aligned)){
|
|
|
|
/* just set range really big so it will fall through
|
|
|
|
to the bottom of the encoding */
|
|
|
|
range=1000000;
|
|
|
|
} else {
|
|
|
|
/* Copied from the 32 bit version, asuming the same problem occures
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
num_bits=0;
|
|
|
|
pad=0;
|
|
|
|
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;
|
|
|
|
val = min;
|
|
|
|
} else if((range<=255)||(!actx->aligned)) {
|
|
|
|
/* 10.5.7.1
|
|
|
|
* 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;
|
|
|
|
int i, bit, length;
|
|
|
|
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;
|
|
|
|
|
|
|
|
num_bits = i;
|
|
|
|
length=1;
|
|
|
|
if(range<=2){
|
|
|
|
num_bits=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* prepare the string */
|
|
|
|
str=ep_alloc(256);
|
|
|
|
g_snprintf(str, 256, "%s: ", hfi->name);
|
|
|
|
for(bit=0;bit<((int)(offset&0x07));bit++){
|
|
|
|
if(bit&&(!(bit%4))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2008-01-15 17:59:43 +00:00
|
|
|
}
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str,".", 256);
|
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))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2008-01-15 17:59:43 +00:00
|
|
|
}
|
|
|
|
if(bit&&(!(bit%8))){
|
|
|
|
length+=1;
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
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;
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "1", 256);
|
2008-01-15 17:59:43 +00:00
|
|
|
} else {
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, "0", 256);
|
2008-01-15 17:59:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for(;bit%8;bit++){
|
|
|
|
if(bit&&(!(bit%4))){
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str, " ", 256);
|
2008-01-15 17:59:43 +00:00
|
|
|
}
|
2008-03-01 17:23:39 +00:00
|
|
|
g_strlcat(str,".", 256);
|
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 */
|
|
|
|
num_bits=8;
|
|
|
|
pad=7-(offset&0x07);
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
num_bits=16;
|
|
|
|
pad=7-(offset&0x07);
|
|
|
|
|
|
|
|
/* 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 {
|
|
|
|
int i,num_bytes;
|
|
|
|
gboolean bit;
|
|
|
|
|
|
|
|
/* 10.5.7.4 */
|
|
|
|
/* 12.2.6 */
|
|
|
|
offset=dissect_per_boolean(tvb, offset, actx, tree, -1, &bit);
|
|
|
|
num_bytes=bit;
|
|
|
|
offset=dissect_per_boolean(tvb, offset, actx, tree, -1, &bit);
|
|
|
|
num_bytes=(num_bytes<<1)|bit;
|
|
|
|
|
|
|
|
num_bytes++; /* lower bound for length determinant is 1 */
|
|
|
|
if (display_internal_per_fields)
|
|
|
|
proto_tree_add_uint(tree, hf_per_const_int_len, tvb, (offset>>3), 1, num_bytes);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (IS_FT_UINT(hfi->type)) {
|
|
|
|
it = proto_tree_add_uint64(tree, hf_index, tvb, val_start, val_length, val);
|
|
|
|
} else if (IS_FT_INT(hfi->type)) {
|
|
|
|
it = proto_tree_add_int64(tree, hf_index, tvb, val_start, val_length, val);
|
|
|
|
} 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;
|
|
|
|
return offset;}
|
|
|
|
|
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
|
|
|
|
* normally small non-negative whole number whose value is the
|
|
|
|
* 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 */
|
|
|
|
guint32
|
|
|
|
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
|
|
|
{
|
|
|
|
gboolean extension_present, extension_flag;
|
|
|
|
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;
|
2005-09-09 15:36:39 +00:00
|
|
|
int i, index, cidx;
|
|
|
|
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){
|
|
|
|
extension_present = FALSE;
|
|
|
|
extension_flag = FALSE;
|
2003-07-12 22:35:21 +00:00
|
|
|
} else {
|
2005-09-09 15:36:39 +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
|
|
|
}
|
|
|
|
|
2005-09-09 15:36:39 +00:00
|
|
|
index = -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){
|
|
|
|
if (!cidx) { index = 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
|
|
|
|
|
|
|
index = -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){
|
|
|
|
if (!cidx) { index = i; break; }
|
|
|
|
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
|
|
|
|
2005-09-09 15:36:39 +00:00
|
|
|
if (index != -1) {
|
|
|
|
choice_item = proto_tree_add_uint(tree, hf_index, tvb, old_offset>>3, 0, choice[index].value);
|
|
|
|
choice_tree = proto_item_add_subtree(choice_item, ett_index);
|
|
|
|
if (!extension_flag) {
|
2006-06-29 15:26:41 +00:00
|
|
|
offset = choice[index].func(tvb, offset, actx, choice_tree, *choice[index].p_id);
|
2005-08-29 10:43:33 +00:00
|
|
|
} else {
|
2006-06-29 15:26:41 +00:00
|
|
|
choice[index].func(tvb, offset, actx, choice_tree, *choice[index].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);
|
|
|
|
PER_NOT_DECODED_YET("unknown choice extension");
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-18 13:15:36 +00:00
|
|
|
if (value && (index != -1))
|
|
|
|
*value = choice[index].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 *
|
2004-10-11 06:38:12 +00:00
|
|
|
index_get_optional_name(const per_sequence_t *sequence, int index)
|
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)){
|
2006-07-03 07:03:57 +00:00
|
|
|
if (index == 0) {
|
|
|
|
hfi = proto_registrar_get_nth(*sequence[i].p_id);
|
|
|
|
return (hfi) ? hfi->name : "<unknown filed>";
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
index--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "<unknown type>";
|
|
|
|
}
|
|
|
|
|
2005-07-30 01:01:02 +00:00
|
|
|
static const char *
|
2004-10-11 06:38:12 +00:00
|
|
|
index_get_extension_name(const per_sequence_t *sequence, int index)
|
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){
|
2006-07-03 07:03:57 +00:00
|
|
|
if (index == 0) {
|
|
|
|
hfi = proto_registrar_get_nth(*sequence[i].p_id);
|
|
|
|
return (hfi) ? hfi->name : "<unknown filed>";
|
2003-07-12 22:35:21 +00:00
|
|
|
}
|
|
|
|
index--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "<unknown type>";
|
|
|
|
}
|
|
|
|
|
2006-07-03 07:03:57 +00:00
|
|
|
static const char *
|
|
|
|
index_get_field_name(const per_sequence_t *sequence, int index)
|
|
|
|
{
|
|
|
|
header_field_info *hfi;
|
|
|
|
|
|
|
|
hfi = proto_registrar_get_nth(*sequence[index].p_id);
|
|
|
|
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>64K
|
|
|
|
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
|
|
|
{
|
|
|
|
gboolean extension_present, extension_flag, optional_field_flag;
|
|
|
|
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
|
|
|
|
2003-07-12 22:35:21 +00:00
|
|
|
item=proto_tree_add_item(parent_tree, hf_index, tvb, offset>>3, 0, FALSE);
|
|
|
|
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){
|
2003-07-12 22:35:21 +00:00
|
|
|
extension_present=0;
|
|
|
|
} else {
|
|
|
|
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;
|
|
|
|
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.
|
|
|
|
I dont know if this is right or not but it makes
|
|
|
|
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.
|
|
|
|
If this is wrong and you dont report it as a bug
|
|
|
|
then it wont get fixed!
|
|
|
|
*/
|
|
|
|
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){
|
|
|
|
/* we dont know how to decode this extension */
|
|
|
|
offset+=length*8;
|
2004-05-17 20:03:36 +00:00
|
|
|
PER_NOT_DECODED_YET("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 */
|
|
|
|
if(difference > 7){
|
|
|
|
cause=proto_tree_add_text(tree, tvb, new_offset>>3, (offset-new_offset)>>3,
|
|
|
|
"[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);
|
|
|
|
expert_add_info_format(actx->pinfo, cause, PI_MALFORMED, PI_WARN,
|
|
|
|
"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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
*/
|
|
|
|
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
|
|
|
{
|
2006-06-08 06:06:17 +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
|
|
|
}
|
|
|
|
|
|
|
|
/* 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)) {
|
2008-04-13 16:42:41 +00:00
|
|
|
out_tvb = new_octet_aligned_subset_bits(tvb, offset, actx, min_len);
|
2004-02-16 18:31:40 +00:00
|
|
|
if (hfi) {
|
2007-09-04 19:36:07 +00:00
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, out_tvb, 0, -1, FALSE);
|
2007-09-18 11:46:50 +00:00
|
|
|
proto_item_append_text(actx->created_item, " [bit length %u]", max_len);
|
2004-02-16 18:31:40 +00:00
|
|
|
}
|
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)){
|
2007-08-30 19:44:22 +00:00
|
|
|
/* (octet-aligned in the ALIGNED variant)
|
|
|
|
* align to byte
|
|
|
|
*/
|
|
|
|
if (actx->aligned){
|
|
|
|
/* TODO the displayed value will be wrong for the unaligned variant */
|
|
|
|
BYTE_ALIGN_OFFSET(offset);
|
|
|
|
}
|
2008-04-13 16:42:41 +00:00
|
|
|
out_tvb = new_octet_aligned_subset_bits(tvb, offset, actx, min_len);
|
2004-02-16 18:31:40 +00:00
|
|
|
if (hfi) {
|
2007-09-04 16:57:07 +00:00
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, out_tvb, 0, -1, FALSE);
|
2008-04-13 16:42:41 +00:00
|
|
|
proto_item_append_text(actx->created_item, " [bit length %u]", max_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,
|
2006-05-22 11:49:50 +00:00
|
|
|
&length, has_extension);
|
|
|
|
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);
|
|
|
|
}
|
2008-04-13 16:42:41 +00:00
|
|
|
out_tvb = new_octet_aligned_subset_bits(tvb, offset, actx, length);
|
2004-02-16 18:31:40 +00:00
|
|
|
if (hfi) {
|
2007-09-04 16:57:07 +00:00
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, out_tvb, 0, -1, FALSE);
|
2008-04-13 16:42:41 +00:00
|
|
|
proto_item_append_text(actx->created_item, " [bit length %u]", length);
|
2004-02-16 18:31:40 +00:00
|
|
|
}
|
|
|
|
}
|
2006-06-08 06:06:17 +00:00
|
|
|
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;
|
2003-07-12 22:35:21 +00:00
|
|
|
guint32 length;
|
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 */
|
|
|
|
val_start = offset>>3;
|
|
|
|
val_length = 0;
|
2003-07-12 22:35:21 +00:00
|
|
|
|
2007-09-04 16:57:07 +00:00
|
|
|
} else if((min_len==max_len)&&(max_len<=2)) {
|
|
|
|
/* 16.6 if length is fixed and less than or equal to two bytes*/
|
|
|
|
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
|
|
|
|
2007-09-04 16:57:07 +00:00
|
|
|
} else if ((min_len==max_len)&&(min_len<65536)) {
|
|
|
|
/* 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 */
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (!display_internal_per_fields)
|
|
|
|
PROTO_ITEM_SET_HIDDEN(actx->created_item);
|
2004-06-24 21:50:05 +00:00
|
|
|
} else {
|
2006-05-22 11:49:50 +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 {
|
|
|
|
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){
|
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, out_tvb, 0, val_length, FALSE);
|
|
|
|
}else{
|
|
|
|
/* Length = 0 */
|
2007-05-23 13:36:25 +00:00
|
|
|
actx->created_item = proto_tree_add_item(tree, hf_index, tvb, val_start, val_length, FALSE);
|
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,
|
|
|
|
arbitrary [2] IMPLICIT BIT STRING
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
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
|
|
|
|
dissect_per_T_direct_reference(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
|
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
|
|
|
|
dissect_per_T_data_value_descriptor(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
|
|
|
|
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
|
|
|
|
dissect_per_T_octet_aligned(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
|
|
|
|
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
|
|
|
|
dissect_per_T_arbitrary(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
|
|
|
|
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
|
|
|
|
dissect_per_External_encoding(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
{ "Raal Length", "per.real_length", FT_UINT32, BASE_DEC,
|
|
|
|
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,
|
|
|
|
{ "Constrained Integer Length", "per._const_int_len", FT_UINT32, BASE_DEC,
|
|
|
|
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",
|
|
|
|
FT_BYTES, BASE_HEX, NULL, 0,
|
|
|
|
"per.T_octet_aligned", HFILL }},
|
|
|
|
{ &hf_per_arbitrary,
|
|
|
|
{ "arbitrary", "per.arbitrary",
|
|
|
|
FT_BYTES, BASE_HEX, NULL, 0,
|
|
|
|
"per.T_arbitrary", 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)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|