aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-per.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-per.c')
-rw-r--r--epan/dissectors/packet-per.c368
1 files changed, 235 insertions, 133 deletions
diff --git a/epan/dissectors/packet-per.c b/epan/dissectors/packet-per.c
index 15f05965d7..5c9da0119b 100644
--- a/epan/dissectors/packet-per.c
+++ b/epan/dissectors/packet-per.c
@@ -1,5 +1,5 @@
/*
-XXX all this offset>>3 and calculations of bytes in the tvb everytime
+XXX all this offset>>3 and calculations of bytes in the tvb every time
we put something in the tree is just silly. should be replaced with some
proper helper routines
*/
@@ -29,58 +29,59 @@ proper helper routines
void proto_register_per(void);
-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;
-static int hf_per_choice_index = -1;
-static int hf_per_choice_extension_index = -1;
-static int hf_per_enum_index = -1;
-static int hf_per_enum_extension_index = -1;
-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;
-static int hf_per_real_length = -1;
-static int hf_per_octet_string_length = -1;
-static int hf_per_bit_string_length = -1;
-static int hf_per_normally_small_nonnegative_whole_number_length = -1;
-static int hf_per_const_int_len = -1;
-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 */
-static int hf_per_integer_length = -1; /* Show integer length if "show internal per fields" */
-/* static int hf_per_debug_pos = -1; */
-static int hf_per_internal_range = -1;
-static int hf_per_internal_num_bits = -1;
-static int hf_per_internal_min = -1;
-static int hf_per_internal_value = -1;
-
-static gint ett_per_open_type = -1;
-static gint ett_per_containing = -1;
-static gint ett_per_sequence_of_item = -1;
-static gint ett_per_External = -1;
-static gint ett_per_External_encoding = -1;
-static gint ett_per_named_bits = -1;
-
-static expert_field ei_per_size_constraint_value = EI_INIT;
-static expert_field ei_per_size_constraint_too_few = EI_INIT;
-static expert_field ei_per_size_constraint_too_many = EI_INIT;
-static expert_field ei_per_choice_extension_unknown = EI_INIT;
-static expert_field ei_per_sequence_extension_unknown = EI_INIT;
-static expert_field ei_per_encoding_error = EI_INIT;
-static expert_field ei_per_oid_not_implemented = EI_INIT;
-static expert_field ei_per_undecoded = EI_INIT;
-static expert_field ei_per_field_not_integer = EI_INIT;
-static expert_field ei_per_external_type = EI_INIT;
-static expert_field ei_per_open_type = EI_INIT;
-static expert_field ei_per_open_type_len = EI_INIT;
+static int proto_per;
+static int hf_per_GeneralString_length;
+static int hf_per_extension_bit;
+static int hf_per_extension_present_bit;
+static int hf_per_choice_index;
+static int hf_per_choice_extension_index;
+static int hf_per_enum_index;
+static int hf_per_enum_extension_index;
+static int hf_per_num_sequence_extensions;
+static int hf_per_small_number_bit;
+static int hf_per_optional_field_bit;
+static int hf_per_sequence_of_length;
+static int hf_per_object_identifier_length;
+static int hf_per_open_type_length;
+static int hf_per_real_length;
+static int hf_per_octet_string_length;
+static int hf_per_bit_string_length;
+static int hf_per_normally_small_nonnegative_whole_number_length;
+static int hf_per_const_int_len;
+static int hf_per_direct_reference; /* T_direct_reference */
+static int hf_per_indirect_reference; /* T_indirect_reference */
+static int hf_per_data_value_descriptor; /* T_data_value_descriptor */
+static int hf_per_encoding; /* External_encoding */
+static int hf_per_single_ASN1_type; /* T_single_ASN1_type */
+static int hf_per_octet_aligned; /* T_octet_aligned */
+static int hf_per_arbitrary; /* T_arbitrary */
+static int hf_per_integer_length; /* Show integer length if "show internal per fields" */
+/* static int hf_per_debug_pos; */
+static int hf_per_internal_range;
+static int hf_per_internal_num_bits;
+static int hf_per_internal_min;
+static int hf_per_internal_value;
+static int hf_per_encoding_boiler_plate;
+
+static gint ett_per_open_type;
+static gint ett_per_containing;
+static gint ett_per_sequence_of_item;
+static gint ett_per_External;
+static gint ett_per_External_encoding;
+static gint ett_per_named_bits;
+
+static expert_field ei_per_size_constraint_value;
+static expert_field ei_per_size_constraint_too_few;
+static expert_field ei_per_size_constraint_too_many;
+static expert_field ei_per_choice_extension_unknown;
+static expert_field ei_per_sequence_extension_unknown;
+static expert_field ei_per_encoding_error;
+static expert_field ei_per_oid_not_implemented;
+static expert_field ei_per_undecoded;
+static expert_field ei_per_field_not_integer;
+static expert_field ei_per_external_type;
+static expert_field ei_per_open_type;
+static expert_field ei_per_open_type_len;
static dissector_table_t per_oid_dissector_table = NULL;
@@ -109,6 +110,15 @@ static const true_false_string tfs_small_number_bit = {
"The number is large, >63"
};
+void
+add_per_encoded_label(tvbuff_t* tvb, packet_info* pinfo _U_, proto_tree* tree)
+{
+ proto_item* ti;
+
+ ti = proto_tree_add_item(tree, hf_per_encoding_boiler_plate, tvb, 0, -1, ENC_NA);
+ proto_item_set_generated(ti);
+
+}
#define BYTE_ALIGN_OFFSET(offset) if(offset&0x07){offset=(offset&0xfffffff8)+8;}
@@ -126,9 +136,9 @@ static void per_check_value(guint32 value, guint32 min_len, guint32 max_len, asn
static void per_check_value64(guint64 value, guint64 min_len, guint64 max_len, asn1_ctx_t *actx, proto_item *item, gboolean is_signed)
{
if ((is_signed == FALSE) && (value > max_len)) {
- expert_add_info_format(actx->pinfo, item, &ei_per_size_constraint_value, "Size constraint: value too big: %" G_GINT64_MODIFIER "u (%" G_GINT64_MODIFIER "u .. %" G_GINT64_MODIFIER "u)", value, min_len, max_len);
+ expert_add_info_format(actx->pinfo, item, &ei_per_size_constraint_value, "Size constraint: value too big: %" PRIu64 " (%" PRIu64 " .. %" PRIu64 ")", value, min_len, max_len);
} else if ((is_signed == TRUE) && ((gint64)value > (gint64)max_len)) {
- expert_add_info_format(actx->pinfo, item, &ei_per_size_constraint_value, "Size constraint: value too big: %" G_GINT64_MODIFIER "d (%" G_GINT64_MODIFIER "d .. %" G_GINT64_MODIFIER "d)", (gint64)value, (gint64)min_len, (gint64)max_len);
+ expert_add_info_format(actx->pinfo, item, &ei_per_size_constraint_value, "Size constraint: value too big: %" PRId64 " (%" PRId64 " .. %" PRId64 ")", (gint64)value, (gint64)min_len, (gint64)max_len);
}
}
@@ -156,23 +166,24 @@ static guint32
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)
{
int type_length, start_offset, end_offset, fragmented_length = 0, pdu_length, pdu_offset;
- tvbuff_t *val_tvb = NULL, *pdu_tvb = NULL;
+ tvbuff_t *val_tvb = NULL, *pdu_tvb = NULL, *fragment_tvb = NULL;
header_field_info *hfi;
proto_tree *subtree = tree;
gboolean is_fragmented;
int captured_pdu_length;
- hfi = (hf_index == -1) ? NULL : proto_registrar_get_nth(hf_index);
+ hfi = (hf_index <= 0) ? NULL : proto_registrar_get_nth(hf_index);
start_offset = offset;
do {
offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_open_type_length, &type_length, &is_fragmented);
if (actx->aligned) BYTE_ALIGN_OFFSET(offset);
if (is_fragmented) {
+ fragment_tvb = tvb_new_octet_aligned(tvb, offset, 8*type_length);
if (fragmented_length == 0) {
pdu_tvb = tvb_new_composite();
}
- tvb_composite_append(pdu_tvb, tvb_new_octet_aligned(tvb, offset, 8*type_length));
+ tvb_composite_append(pdu_tvb, fragment_tvb);
offset += 8*type_length;
fragmented_length += type_length;
}
@@ -216,8 +227,8 @@ dissect_per_open_type_internal(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx,
}
}
if (hfi) {
- if (IS_FT_UINT(hfi->type)||IS_FT_INT(hfi->type)) {
- if (IS_FT_UINT(hfi->type))
+ if (FT_IS_UINT(hfi->type)||FT_IS_INT(hfi->type)) {
+ if (FT_IS_UINT(hfi->type))
actx->created_item = proto_tree_add_uint(tree, hf_index, val_tvb, 0, pdu_length, pdu_length);
else
actx->created_item = proto_tree_add_int(tree, hf_index, val_tvb, 0, pdu_length, pdu_length);
@@ -319,7 +330,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
str=(char *)wmem_alloc(wmem_packet_scope(), str_length+1);
str_index = 0;
- str_length = g_snprintf(str, str_length+1, " ");
+ str_length = snprintf(str, str_length+1, " ");
for(bit=0;bit<((int)(offset&0x07));bit++){
if(bit&&(!(bit%4))){
if (str_index < str_length) str[str_index++] = ' ';
@@ -368,7 +379,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
return offset;
}
*length *= 0x4000;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
if (display_internal_per_fields)
proto_item_append_text(pi," %s", str);
@@ -380,7 +391,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
}
else if((val&0x80)==0 && num_bits==8){
*length = val;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
if (display_internal_per_fields)
proto_item_append_text(pi," %s", str);
@@ -392,7 +403,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
}
else if (num_bits==16) {
*length = val&0x3fff;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-2, 2, *length);
if (display_internal_per_fields)
proto_item_append_text(pi," %s", str);
@@ -411,7 +422,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
/* 10.9.3.6 */
if((byte&0x80)==0){
*length=byte;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
if (!display_internal_per_fields) proto_item_set_hidden(pi);
}
@@ -423,7 +434,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
*length=(byte&0x3f);
*length=((*length)<<8)+tvb_get_guint8(tvb, offset>>3);
offset+=8;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-2, 2, *length);
if (!display_internal_per_fields) proto_item_set_hidden(pi);
}
@@ -439,7 +450,7 @@ dissect_per_length_determinant(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _
}
*length *= 0x4000;
*is_fragmented = TRUE;
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-1, 1, *length);
if (!display_internal_per_fields) proto_item_set_hidden(pi);
}
@@ -476,7 +487,7 @@ DEBUG_ENTRY("dissect_per_normally_small_nonnegative_whole_number");
*length|=1;
}
}
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset-6)>>3, (offset%8<6)?2:1, *length);
if (!display_internal_per_fields) proto_item_set_hidden(pi);
}
@@ -511,7 +522,7 @@ DEBUG_ENTRY("dissect_per_normally_small_nonnegative_whole_number");
*length = 0;
return offset;
}
- if(hf_index!=-1){
+ if(hf_index > 0){
pi = proto_tree_add_uint(tree, hf_index, tvb, (offset-(8*length_determinant))>>3, length_determinant, *length);
if (!display_internal_per_fields) proto_item_set_hidden(pi);
}
@@ -548,19 +559,23 @@ guint32
dissect_per_null(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx _U_, proto_tree *tree, int hf_index) {
proto_item *ti_tmp;
- ti_tmp = proto_tree_add_item(tree, hf_index, tvb, offset>>3, 1, ENC_BIG_ENDIAN);
+ ti_tmp = proto_tree_add_item(tree, hf_index, tvb, offset>>3, 0, ENC_BIG_ENDIAN);
proto_item_append_text(ti_tmp, ": NULL");
return offset;
}
/* 19 this function dissects a sequence of */
+// Arbitrary. Allow a sequence of NULLs, but not too many since we might add
+// a hierarchy of tree items per NULL
+#define PER_SEQUENCE_OF_MAX_NULLS 10
static guint32
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)
{
guint32 i;
DEBUG_ENTRY("dissect_per_sequence_of_helper");
+ guint32 old_offset = offset;
for(i=0;i<length;i++){
guint32 lold_offset=offset;
proto_item *litem;
@@ -570,6 +585,9 @@ DEBUG_ENTRY("dissect_per_sequence_of_helper");
offset=(*func)(tvb, offset, actx, ltree, hf_index);
proto_item_set_len(litem, (offset>>3)!=(lold_offset>>3)?(offset>>3)-(lold_offset>>3):1);
+ if (i >= PER_SEQUENCE_OF_MAX_NULLS-1 && offset <= old_offset) {
+ dissect_per_not_decoded_yet(tree, actx->pinfo, tvb, "too many nulls in sequence");
+ }
}
return offset;
@@ -591,7 +609,7 @@ DEBUG_ENTRY("dissect_per_sequence_of");
offset=dissect_per_length_determinant(tvb, offset, actx, parent_tree, hf_per_sequence_of_length, &length, NULL);
hfi = proto_registrar_get_nth(hf_index);
- if (IS_FT_UINT(hfi->type)) {
+ if (FT_IS_UINT(hfi->type)) {
item = proto_tree_add_uint(parent_tree, hf_index, tvb, old_offset>>3, 0, length);
proto_item_append_text(item, (length==1)?" item":" items");
} else {
@@ -606,14 +624,15 @@ DEBUG_ENTRY("dissect_per_sequence_of");
return offset;
}
-
/* XXX we don't do >64k length strings yet */
static guint32
-dissect_per_restricted_character_string_sorted(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension _U_, guint16 lb _U_, guint16 ub, const char *alphabet, int alphabet_length, tvbuff_t **value_tvb)
+dissect_per_restricted_character_string_sorted(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension, guint16 lb, guint16 ub, const char *alphabet, int alphabet_length, tvbuff_t **value_tvb)
{
guint32 length;
gboolean byte_aligned, use_canonical_order;
- guint8 *buf;
+ wmem_strbuf_t *buf;
+ int str_len;
+ char *str;
guint char_pos;
int bits_per_char;
guint32 old_offset;
@@ -667,6 +686,7 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
bits_per_char=8;
}
}
+
/* 27.4 If the type is extensible for PER encodings (see 9.3.16),
* then a bit-field consisting of a single bit shall be added to the field-list.
* The single bit shall be set to zero if the value is within the range of the extension root,
@@ -698,6 +718,7 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
/* xx.x */
length=max_len;
+ old_offset = offset;
if (max_len == NO_BOUND) {
offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_octet_string_length, &length, NULL);
/* the unconstrained strings are always byte aligned (27.6.3)*/
@@ -713,7 +734,9 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
/* there is no string at all, so don't do any byte alignment */
/* byte_aligned=FALSE; */
/* Advance offset to next 'element' */
- offset = offset + 1; }
+ if (offset == old_offset)
+ offset = offset + 1;
+ }
if((byte_aligned)&&(actx->aligned)){
BYTE_ALIGN_OFFSET(offset);
@@ -725,7 +748,7 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
that is one greater than the value assigned to the previous character in the canonical order. These are the values "v" */
use_canonical_order = (ub <= ((guint16)(1<<bits_per_char)-1)) ? FALSE : TRUE;
- buf = (guint8 *)wmem_alloc(actx->pinfo->pool, length+1);
+ buf = wmem_strbuf_new_len(actx->pinfo->pool, NULL, length);
old_offset=offset;
for(char_pos=0;char_pos<length;char_pos++){
guchar val;
@@ -738,25 +761,31 @@ DEBUG_ENTRY("dissect_per_restricted_character_string");
val=(val<<1)|bit;
}
if(use_canonical_order == FALSE){
- buf[char_pos]=val;
+ if (val > ub || val < lb) {
+ wmem_strbuf_append_unichar_repl(buf);
+ } else {
+ wmem_strbuf_append_c(buf, val);
+ }
} else {
if (val < alphabet_length){
- buf[char_pos]=alphabet[val];
+ wmem_strbuf_append_c(buf, alphabet[val]);
} else {
- buf[char_pos] = '?'; /* XXX - how to mark this? */
+ wmem_strbuf_append_unichar_repl(buf);
}
}
}
- buf[char_pos]=0;
- proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), (offset>>3)-(old_offset>>3), (char*)buf);
+ str_len = (int)wmem_strbuf_get_len(buf);
+ str = wmem_strbuf_finalize(buf);
+ /* Note that str can contain embedded nulls. Length claims any bytes partially used. */
+ proto_tree_add_string(tree, hf_index, tvb, (old_offset>>3), ((offset+7)>>3)-(old_offset>>3), str);
if (value_tvb) {
- *value_tvb = tvb_new_child_real_data(tvb, buf, length, length);
+ *value_tvb = tvb_new_child_real_data(tvb, str, str_len, str_len);
}
return offset;
}
static const char*
-sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
+sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length, guint16 *lb, guint16 *ub)
{
int i, j;
guchar c, c_max, c_min;
@@ -764,7 +793,10 @@ sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
/*
* XXX - presumably all members of alphabet will be in the
- * range 0 to 127.
+ * range 0 to 127. asn2wrs.py doesn't properly handle the
+ * Quadruple or CharacterStringList types needed for other
+ * characters, nor representing characters outside ASCII
+ * in the "cstring" notation (possibly in UTF-8?)
*/
if (!alphabet_length) return sorted_alphabet;
memset(tmp_buf, 0, 256);
@@ -778,6 +810,8 @@ sort_alphabet(char *sorted_alphabet, const char *alphabet, int alphabet_length)
for (i=c_min,j=0; i<=c_max; i++) {
if (tmp_buf[i]) sorted_alphabet[j++] = i;
}
+ *lb = (guint16)c_min;
+ *ub = (guint16)c_max;
return sorted_alphabet;
}
@@ -786,45 +820,55 @@ dissect_per_restricted_character_string(tvbuff_t *tvb, guint32 offset, asn1_ctx_
{
const char *alphabet_ptr;
char sorted_alphabet[128];
+ guint16 lb = 0;
+ guint16 ub = 65535;
+ /* XXX: We don't handle permitted-alphabet characters outside the
+ * ASCII range if used in BMPString (UCS2) or UniversalString (UCS4)
+ */
if (alphabet_length > 127) {
alphabet_ptr = alphabet;
} else {
- alphabet_ptr = sort_alphabet(sorted_alphabet, alphabet, alphabet_length);
+ alphabet_ptr = sort_alphabet(sorted_alphabet, alphabet, alphabet_length, &lb, &ub);
}
- /* Not a known-multiplier character string: enforce lb and ub to max values */
- return dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension, 0, 65535, alphabet_ptr, alphabet_length, value_tvb);
+
+ /* This is for a restricted character string type with a permitted-
+ * alphabet constraint type. Such constraints are only PER-visible for
+ * the known-multiplier character string types.
+ */
+
+ return dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension, lb, ub, alphabet_ptr, alphabet_length, value_tvb);
}
guint32
-dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension)
+dissect_per_IA5String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension, tvbuff_t **value_tvb)
{
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension,
- 0, 127, NULL, 128, NULL);
+ 0, 127, NULL, 128, value_tvb);
return offset;
}
guint32
-dissect_per_NumericString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension)
+dissect_per_NumericString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension, tvbuff_t **value_tvb)
{
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension,
- 32, 57, " 0123456789", 11, NULL);
+ 32, 57, " 0123456789", 11, value_tvb);
return offset;
}
guint32
-dissect_per_PrintableString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension)
+dissect_per_PrintableString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension, tvbuff_t **value_tvb)
{
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension,
- 32, 122, " '()+,-.*0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 74, NULL);
+ 32, 122, " '()+,-.*0123456789:=?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 74, value_tvb);
return offset;
}
guint32
-dissect_per_VisibleString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension)
+dissect_per_VisibleString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension, tvbuff_t **value_tvb)
{
offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree, hf_index, min_len, max_len, has_extension,
- 32, 126, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 95, NULL);
+ 32, 126, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 95, value_tvb);
return offset;
}
guint32
@@ -868,10 +912,43 @@ dissect_per_BMPString(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tre
return offset;
}
guint32
-dissect_per_UTF8String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len, int max_len, gboolean has_extension _U_)
+dissect_per_UTF8String(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, int min_len _U_, int max_len _U_, gboolean has_extension _U_)
{
- offset=dissect_per_restricted_character_string_sorted(tvb, offset, actx, tree,
- hf_index, min_len, max_len, has_extension, 0, 255, NULL, 256, NULL);
+ tvbuff_t *val_tvb;
+ guint32 length;
+
+ /* UTF8String is not a known-multiplier character string (UTF8
+ * characters are variable width.) Hence subclause 27.6 applies,
+ * and "constraints are never PER-visible, and the type can never
+ * be extensible for PER encoding."
+ */
+
+ /* 27.6.3 unconstrained length determinant with "n" in octets */
+ offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_octet_string_length, &length, NULL);
+
+ if(length){
+
+ /* Unnecessary because the length determinant is aligned. */
+ if(actx->aligned) {
+ BYTE_ALIGN_OFFSET(offset);
+ }
+
+ val_tvb = tvb_new_octet_aligned(tvb, offset, length * 8);
+ /* Add new data source if the offset was unaligned */
+ if ((offset & 7) != 0) {
+ add_new_data_source(actx->pinfo, val_tvb, "Unaligned UTF8String");
+ }
+
+ proto_tree_add_item(tree, hf_index, val_tvb, 0, length, ENC_UTF_8);
+ } else {
+ /* tvb_new_octet_aligned doesn't like zero length.
+ * length zero indicates a present but empty string, so add it
+ */
+ proto_tree_add_item(tree, hf_index, tvb, (offset-1)>>3, length, ENC_UTF_8);
+ }
+
+ offset+=(length<<3);
+
return offset;
}
@@ -933,7 +1010,7 @@ DEBUG_ENTRY("dissect_per_constrained_sequence_of");
call_sohelper:
hfi = proto_registrar_get_nth(hf_index);
- if (IS_FT_UINT(hfi->type)) {
+ if (FT_IS_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 {
@@ -997,6 +1074,9 @@ dissect_per_any_oid(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree
DEBUG_ENTRY("dissect_per_any_oid");
offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_object_identifier_length, &length, NULL);
+ if(length == 0){
+ dissect_per_not_decoded_yet(tree, actx->pinfo, tvb, "unexpected length");
+ }
if (actx->aligned) BYTE_ALIGN_OFFSET(offset);
val_tvb = tvb_new_octet_aligned(tvb, offset, length * 8);
/* Add new data source if the offet was unaligned */
@@ -1007,7 +1087,7 @@ dissect_per_any_oid(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree
hfi = proto_registrar_get_nth(hf_index);
if ((is_absolute && hfi->type == FT_OID) || (is_absolute && hfi->type == FT_REL_OID)) {
actx->created_item = proto_tree_add_item(tree, hf_index, val_tvb, 0, length, ENC_BIG_ENDIAN);
- } else if (IS_FT_STRING(hfi->type)) {
+ } else if (FT_IS_STRING(hfi->type)) {
str = oid_encoded2string(wmem_packet_scope(), tvb_get_ptr(val_tvb, 0, length), length);
actx->created_item = proto_tree_add_string(tree, hf_index, val_tvb, 0, length, str);
} else {
@@ -1083,7 +1163,7 @@ DEBUG_ENTRY("dissect_per_boolean");
} else {
value=0;
}
- if(hf_index!=-1){
+ if(hf_index > 0){
char bits[10];
bits[0] = mask&0x80?'0'+value:'.';
bits[1] = mask&0x40?'0'+value:'.';
@@ -1131,6 +1211,10 @@ dissect_per_integer(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree
length=4;
}
+ if(length == 0){
+ dissect_per_not_decoded_yet(tree, actx->pinfo, tvb, "unexpected length");
+ }
+
if (actx->aligned) BYTE_ALIGN_OFFSET(offset);
val_tvb = tvb_new_octet_aligned(tvb, offset, length * 8);
val=0;
@@ -1151,9 +1235,9 @@ dissect_per_integer(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree
hfi = proto_registrar_get_nth(hf_index);
if (! hfi)
THROW(ReportedBoundsError);
- if (IS_FT_INT(hfi->type)) {
+ if (FT_IS_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)) {
+ } else if (FT_IS_UINT(hfi->type)) {
it=proto_tree_add_uint(tree, hf_index, tvb, (offset>>3)-(length+1), length+1, val);
} else {
proto_tree_add_expert_format(tree, actx->pinfo, &ei_per_field_not_integer, tvb, (offset>>3)-(length+1), length+1,
@@ -1205,9 +1289,9 @@ dissect_per_integer64b(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tr
hfi = proto_registrar_get_nth(hf_index);
if (! hfi)
THROW(ReportedBoundsError);
- if (IS_FT_INT(hfi->type)) {
+ if (FT_IS_INT(hfi->type)) {
it=proto_tree_add_int64(tree, hf_index, tvb, (offset>>3)-(length+1), length+1, (gint64)val);
- } else if (IS_FT_UINT(hfi->type)) {
+ } else if (FT_IS_UINT(hfi->type)) {
it=proto_tree_add_uint64(tree, hf_index, tvb, (offset>>3)-(length+1), length+1, val);
} else {
proto_tree_add_expert_format(tree, actx->pinfo, &ei_per_field_not_integer, tvb, (offset>>3)-(length+1), length+1,
@@ -1393,13 +1477,13 @@ DEBUG_ENTRY("dissect_per_constrained_integer");
}
timeval.secs = val;
- if (IS_FT_UINT(hfi->type)) {
+ if (FT_IS_UINT(hfi->type)) {
it = proto_tree_add_uint(tree, hf_index, tvb, val_start, val_length, val);
per_check_value(val, min, max, actx, it, FALSE);
- } else if (IS_FT_INT(hfi->type)) {
+ } else if (FT_IS_INT(hfi->type)) {
it = proto_tree_add_int(tree, hf_index, tvb, val_start, val_length, val);
per_check_value(val, min, max, actx, it, TRUE);
- } else if (IS_FT_TIME(hfi->type)) {
+ } else if (FT_IS_TIME(hfi->type)) {
it = proto_tree_add_time(tree, hf_index, tvb, val_start, val_length, &timeval);
} else {
THROW(ReportedBoundsError);
@@ -1539,7 +1623,7 @@ DEBUG_ENTRY("dissect_per_constrained_integer_64b");
if (display_internal_per_fields) {
proto_tree_add_uint64(tree, hf_per_internal_range, tvb, val_start, val_length, range);
proto_tree_add_uint(tree, hf_per_internal_num_bits, tvb, val_start,val_length, num_bits);
- proto_tree_add_uint64_format_value(tree, hf_per_internal_value, tvb, val_start, val_length, val, "%s decimal value: %" G_GINT64_MODIFIER "u", str, val);
+ proto_tree_add_uint64_format_value(tree, hf_per_internal_value, tvb, val_start, val_length, val, "%s decimal value: %" PRIu64, str, val);
}
} else if(range==256){
/* 10.5.7.2 */
@@ -1579,7 +1663,7 @@ DEBUG_ENTRY("dissect_per_constrained_integer_64b");
num_bytes++; /* lower bound for length determinant is 1 */
if (display_internal_per_fields){
int_item = proto_tree_add_bits_item(tree, hf_per_const_int_len, tvb, offset,n_bits, ENC_BIG_ENDIAN);
- proto_item_append_text(int_item,"+1=%u bytes, Range = (%" G_GINT64_MODIFIER "u)",num_bytes, range);
+ proto_item_append_text(int_item,"+1=%u bytes, Range = (%" PRIu64 ")",num_bytes, range);
}
offset = offset+n_bits;
/* byte aligned */
@@ -1594,13 +1678,13 @@ DEBUG_ENTRY("dissect_per_constrained_integer_64b");
}
- if (IS_FT_UINT(hfi->type)) {
+ if (FT_IS_UINT(hfi->type)) {
it = proto_tree_add_uint64(tree, hf_index, tvb, val_start, val_length, val);
per_check_value64(val, min, max, actx, it, FALSE);
- } else if (IS_FT_INT(hfi->type)) {
+ } else if (FT_IS_INT(hfi->type)) {
it = proto_tree_add_int64(tree, hf_index, tvb, val_start, val_length, val);
per_check_value64(val, min, max, actx, it, TRUE);
- } else if (IS_FT_TIME(hfi->type)) {
+ } else if (FT_IS_TIME(hfi->type)) {
timeval.secs = (guint32)val;
it = proto_tree_add_time(tree, hf_index, tvb, val_start, val_length, &timeval);
} else {
@@ -1642,7 +1726,7 @@ dissect_per_enumerated(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tr
}
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)) {
+ if (FT_IS_UINT(hfi->type)) {
it = proto_tree_add_uint(tree, hf_index, tvb, start_offset>>3, BLEN(start_offset, offset), val);
} else {
THROW(ReportedBoundsError);
@@ -1661,6 +1745,9 @@ dissect_per_real(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tr
double val = 0;
offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_real_length, &val_length, NULL);
+ if(val_length == 0){
+ dissect_per_not_decoded_yet(tree, actx->pinfo, tvb, "unexpected length");
+ }
if (actx->aligned) BYTE_ALIGN_OFFSET(offset);
val_tvb = tvb_new_octet_aligned(tvb, offset, val_length * 8);
/* Add new data source if the offet was unaligned */
@@ -1683,7 +1770,6 @@ dissect_per_choice(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *
{
gboolean /*extension_present,*/ extension_flag;
int extension_root_entries;
- int extension_addition_entries;
guint32 choice_index;
int i, idx, cidx;
guint32 ext_length = 0;
@@ -1707,7 +1793,6 @@ DEBUG_ENTRY("dissect_per_choice");
/* count the number of entries in the extension root and extension addition */
extension_root_entries = 0;
- extension_addition_entries = 0;
for (i=0; choice[i].p_id; i++) {
switch(choice[i].extension){
case ASN1_NO_EXTENSIONS:
@@ -1715,7 +1800,6 @@ DEBUG_ENTRY("dissect_per_choice");
extension_root_entries++;
break;
case ASN1_NOT_EXTENSION_ROOT:
- extension_addition_entries++;
break;
}
}
@@ -1788,7 +1872,7 @@ index_get_optional_name(const per_sequence_t *sequence, int idx)
if((sequence[i].extension!=ASN1_NOT_EXTENSION_ROOT)&&(sequence[i].optional==ASN1_OPTIONAL)){
if (idx == 0) {
hfi = proto_registrar_get_nth(*sequence[i].p_id);
- return (hfi) ? hfi->name : "<unknown filed>";
+ return (hfi) ? hfi->name : "<unknown field>";
}
idx--;
}
@@ -1805,9 +1889,9 @@ index_get_extension_name(const per_sequence_t *sequence, int idx)
for(i=0;sequence[i].p_id;i++){
if(sequence[i].extension==ASN1_NOT_EXTENSION_ROOT){
if (idx == 0) {
- if (*sequence[i].p_id == -1) return "extension addition group";
+ if (*sequence[i].p_id == -1 || *sequence[i].p_id == 0) return "extension addition group";
hfi = proto_registrar_get_nth(*sequence[i].p_id);
- return (hfi) ? hfi->name : "<unknown filed>";
+ return (hfi) ? hfi->name : "<unknown field>";
}
idx--;
}
@@ -2133,7 +2217,7 @@ static tvbuff_t *dissect_per_bit_string_display(tvbuff_t *tvb, guint32 offset, a
}else {
value = tvb_get_bits64(out_tvb, 0, length, ENC_BIG_ENDIAN);
}
- proto_item_append_text(actx->created_item, ", %s decimal value %" G_GINT64_MODIFIER "u",
+ proto_item_append_text(actx->created_item, ", %s decimal value %" PRIu64,
decode_bits_in_field(actx->pinfo->pool, 0, length, value, ENC_BIG_ENDIAN), value);
if (named_bits) {
const guint32 named_bits_bytelen = (num_named_bits + 7) / 8;
@@ -2176,9 +2260,9 @@ dissect_per_bit_string(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tr
guint32 length, fragmented_length = 0;
header_field_info *hfi;
gboolean is_fragmented = FALSE;
- tvbuff_t *fragmented_tvb = NULL, *out_tvb = NULL;
+ tvbuff_t *fragmented_tvb = NULL, *out_tvb = NULL, *fragment_tvb = NULL;
- hfi = (hf_index==-1) ? NULL : proto_registrar_get_nth(hf_index);
+ hfi = (hf_index <= 0) ? 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 */
@@ -2211,9 +2295,10 @@ DEBUG_ENTRY("dissect_per_bit_string");
BYTE_ALIGN_OFFSET(offset);
}
if(is_fragmented){
+ fragment_tvb = tvb_new_octet_aligned(tvb, offset, length);
if(fragmented_length==0)
fragmented_tvb = tvb_new_composite();
- tvb_composite_append(fragmented_tvb, tvb_new_octet_aligned(tvb, offset, length));
+ tvb_composite_append(fragmented_tvb, fragment_tvb);
offset += length;
fragmented_length += length;
goto next_fragment1;
@@ -2290,9 +2375,10 @@ DEBUG_ENTRY("dissect_per_bit_string");
BYTE_ALIGN_OFFSET(offset);
}
if(is_fragmented){
+ fragment_tvb = tvb_new_octet_aligned(tvb, offset, length);
if(fragmented_length==0)
fragmented_tvb = tvb_new_composite();
- tvb_composite_append(fragmented_tvb, tvb_new_octet_aligned(tvb, offset, length));
+ tvb_composite_append(fragmented_tvb, fragment_tvb);
offset += length;
fragmented_length += length;
goto next_fragment2;
@@ -2356,12 +2442,12 @@ guint32
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)
{
gint val_start = 0, val_length;
- guint32 length = 0, fragmented_length = 0;;
+ guint32 length = 0, fragmented_length = 0;
header_field_info *hfi;
gboolean is_fragmented = FALSE;
- tvbuff_t *out_tvb = NULL;
+ tvbuff_t *out_tvb = NULL, *fragment_tvb = NULL;
- hfi = (hf_index==-1) ? NULL : proto_registrar_get_nth(hf_index);
+ hfi = (hf_index <= 0) ? NULL : proto_registrar_get_nth(hf_index);
DEBUG_ENTRY("dissect_per_octet_string");
@@ -2424,9 +2510,10 @@ DEBUG_ENTRY("dissect_per_octet_string");
BYTE_ALIGN_OFFSET(offset);
}
if (is_fragmented) {
+ fragment_tvb = tvb_new_octet_aligned(tvb, offset, length * 8);
if (fragmented_length == 0)
out_tvb = tvb_new_composite();
- tvb_composite_append(out_tvb, tvb_new_octet_aligned(tvb, offset, length * 8));
+ tvb_composite_append(out_tvb, fragment_tvb);
offset += length * 8;
fragmented_length += length;
goto next_fragment;
@@ -2452,11 +2539,11 @@ DEBUG_ENTRY("dissect_per_octet_string");
}
if (hfi) {
- if (IS_FT_UINT(hfi->type)||IS_FT_INT(hfi->type)) {
+ if (FT_IS_UINT(hfi->type)||FT_IS_INT(hfi->type)) {
/* 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
*/
- if (IS_FT_UINT(hfi->type))
+ if (FT_IS_UINT(hfi->type))
actx->created_item = proto_tree_add_uint(tree, hf_index, out_tvb, 0, val_length, val_length);
else
actx->created_item = proto_tree_add_int(tree, hf_index, out_tvb, 0, val_length, val_length);
@@ -2688,11 +2775,15 @@ call_per_oid_callback(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_
start_offset = offset;
offset = dissect_per_length_determinant(tvb, offset, actx, tree, hf_per_open_type_length, &type_length, NULL);
+ if(type_length == 0){
+ dissect_per_not_decoded_yet(tree, actx->pinfo, tvb, "unexpected length");
+ }
if (actx->aligned) BYTE_ALIGN_OFFSET(offset);
end_offset = offset + type_length;
- val_tvb = tvb_new_octet_aligned(tvb, offset, type_length);
+ /* length in bits */
+ val_tvb = tvb_new_octet_aligned(tvb, offset, type_length * 8);
if ((offset & 7) != 0) {
add_new_data_source(actx->pinfo, val_tvb, "Unaligned OCTET STRING");
}
@@ -2712,6 +2803,12 @@ register_per_oid_dissector(const char *oid, dissector_t dissector, int proto, co
{
dissector_handle_t dissector_handle;
+ /* FIXME: This would be better as register_dissector()
+ * so the dissector could be referenced by name
+ * from the command line, Lua, etc.
+ * But can we blindly trust name to be a unique dissector name,
+ * or should we prefix "per." or something?
+ */
dissector_handle = create_dissector_handle(dissector, proto);
dissector_add_string("per.oid", oid, dissector_handle);
oid_add_from_string(name, oid);
@@ -2830,6 +2927,11 @@ proto_register_per(void)
{ "Bits", "per.internal.value",
FT_UINT64, BASE_DEC, NULL, 0,
NULL, HFILL }},
+ { &hf_per_encoding_boiler_plate,
+ { "PER encoded protocol, to see PER internal fields set protocol PER preferences", "per.encoding_boiler_plate",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL } },
+
};
static gint *ett[] = {
@@ -2884,7 +2986,7 @@ proto_register_per(void)
"Whether the dissector should put the internal PER data in the tree or if it should hide it",
&display_internal_per_fields);
- per_oid_dissector_table = register_dissector_table("per.oid", "PER OID", proto_per, FT_STRING, BASE_NONE);
+ per_oid_dissector_table = register_dissector_table("per.oid", "PER OID", proto_per, FT_STRING, STRING_CASE_SENSITIVE);
}