add new dissect_ber_integer64() that can handle 8,16,24,32 and 64bit integers.

use proto_tree_add_[u]int[8,16,24,32,64]() instread of proto_tree_add_item()
since BER integers may well be encoded in less bytes than the type requires.
(i do not think the old code with proto_tree_add_item() could have handleded negative values very well    or at all.)




svn path=/trunk/; revision=17425
This commit is contained in:
Ronnie Sahlberg 2006-02-28 09:39:53 +00:00
parent f85a158981
commit 590d27a8c0
4 changed files with 57 additions and 55 deletions

View File

@ -797,14 +797,13 @@ if (!implicit_tag)
}
int
dissect_ber_integer(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
dissect_ber_integer64(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint64 *value)
{
gint8 class;
gboolean pc;
gint32 tag;
guint32 len;
gint32 val;
gint64 val64;
gint64 val;
guint32 i;
#ifdef DEBUG_BER
@ -833,18 +832,7 @@ printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n",name,impl
len=tvb_length_remaining(tvb, offset);
}
/* ok, we cant handle >4 byte integers so lets fake them */
/*
* XXX - should we handle large integers with a bignum type,
* and an FT_BIGNUM field type? This code currently has trouble
* with, for example, INTEGER (0..4294967295), as a value in the
* range 2147483648 to 0..4294967295 is represented as 5 bytes.
*
* There should at least be a way to indicate that the value we
* returned didn't fit in a 32-bit signed integer, so our caller
* can, if they didn't supply an hf_id, indicate that the value
* didn't fit.
*/
/* we cant handle integers > 64 bits */
if(len>8){
header_field_info *hfinfo;
proto_item *pi = NULL;
@ -863,45 +851,51 @@ printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n",name,impl
}
return offset;
}
if(len>4){
header_field_info *hfinfo;
val64=0;
if(len > 0) {
/* extend sign bit */
val64 = (gint8)tvb_get_guint8(tvb, offset);
offset++;
}
for(i=1;i<len;i++){
val64=(val64<<8)|tvb_get_guint8(tvb, offset);
offset++;
}
if (hf_id >= 0) {
hfinfo = proto_registrar_get_nth(hf_id);
proto_tree_add_text(tree, tvb, offset-len, len, "%s: %" PRIu64, hfinfo->name, val64);
}
return offset;
}
val=0;
if(len > 0) {
/* extend sign bit */
val = (gint8)tvb_get_guint8(tvb, offset);
offset++;
}
for(i=1;i<len;i++){
val=(val<<8)|tvb_get_guint8(tvb, offset);
offset++;
if(tvb_get_guint8(tvb, offset)&0x80){
val=-1;
}
for(i=0;i<len;i++){
val=(val<<8)|tvb_get_guint8(tvb, offset);
offset++;
}
}
ber_last_created_item=NULL;
if(hf_id >= 0){
/* */
if(len < 1 || len > 4) {
if(len < 1 || len > 8) {
proto_tree_add_text(tree, tvb, offset-len, len, "Can't handle integer length: %u", len);
} else {
ber_last_created_item=proto_tree_add_item(tree, hf_id, tvb, offset-len, len, FALSE);
header_field_info* hfi;
hfi = proto_registrar_get_nth(hf_id);
switch(hfi->type){
case FT_UINT8:
case FT_UINT16:
case FT_UINT24:
case FT_UINT32:
ber_last_created_item=proto_tree_add_uint(tree, hf_id, tvb, offset-len, len, (guint32)val);
break;
case FT_INT8:
case FT_INT16:
case FT_INT24:
case FT_INT32:
ber_last_created_item=proto_tree_add_int(tree, hf_id, tvb, offset-len, len, (gint32)val);
break;
case FT_INT64:
ber_last_created_item=proto_tree_add_int64(tree, hf_id, tvb, offset-len, len, val);
break;
case FT_UINT64:
ber_last_created_item=proto_tree_add_uint64(tree, hf_id, tvb, offset-len, len, (guint64)val);
break;
default:
DISSECTOR_ASSERT_NOT_REACHED();
}
}
}
if(value){
@ -911,6 +905,19 @@ printf("INTEGERnew dissect_ber_integer(%s) entered implicit_tag:%d \n",name,impl
return offset;
}
int
dissect_ber_integer(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value)
{
gint64 val;
offset=dissect_ber_integer64(implicit_tag, pinfo, tree, tvb, offset, hf_id, &val);
if(value){
*value=(guint32)val;
}
return offset;
}
int
dissect_ber_boolean(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id)

View File

@ -90,6 +90,8 @@ extern int dissect_ber_length(packet_info *pinfo, proto_tree *tree, tvbuff_t *tv
extern int dissect_ber_octet_string(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, tvbuff_t **out_tvb);
extern int dissect_ber_octet_string_wcb(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, ber_callback func);
extern int dissect_ber_integer64(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, gint64 *value);
extern int dissect_ber_integer(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id, guint32 *value);
extern int dissect_ber_null(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gint hf_id);

View File

@ -173,6 +173,7 @@ static int hf_snmp_engineid_mac = -1;
static int hf_snmp_engineid_text = -1;
static int hf_snmp_engineid_time = -1;
static int hf_snmp_engineid_data = -1;
static int hf_snmp_counter64 = -1;
static int proto_smux = -1;
@ -1002,7 +1003,6 @@ snmp_variable_decode(proto_tree *snmp_tree, packet_info *pinfo,
subid_t *vb_oid;
guint vb_oid_length;
gchar *vb_display_string;
gint64 i64;
#ifdef HAVE_SOME_SNMP
struct variable_list variable;
@ -1095,18 +1095,7 @@ snmp_variable_decode(proto_tree *snmp_tree, packet_info *pinfo,
}
break;
case SNMP_COUNTER64:
i64=0;
if(tvb_get_guint8(asn1->tvb, asn1->offset)&0x80){
i64=-1;
}
while(tvb_length_remaining(asn1->tvb, asn1->offset)){
i64=(i64<<8)|tvb_get_guint8(asn1->tvb, asn1->offset);
asn1->offset++;
}
proto_tree_add_text(snmp_tree, asn1->tvb, start,
asn1->offset-start,
"Value: %s: %" PRId64, vb_type_name,
i64);
asn1->offset=dissect_ber_integer64(TRUE, pinfo, snmp_tree, asn1->tvb, asn1->offset, hf_snmp_counter64, NULL);
break;
case SNMP_OCTETSTR:
case SNMP_IPADDR:
@ -2768,6 +2757,9 @@ proto_register_snmp(void)
{ &hf_snmp_engineid_data, {
"Engine ID Data", "snmp.engineid.data", FT_BYTES, BASE_HEX,
NULL, 0, "Engine ID Data", HFILL }},
{ &hf_snmp_counter64, {
"Value", "snmp.counter64", FT_INT64, BASE_DEC,
NULL, 0, "A counter64 value", HFILL }},
};
static gint *ett[] = {
&ett_snmp,

View File

@ -140,6 +140,7 @@ dissect_ber_choice
dissect_ber_GeneralizedTime
dissect_ber_identifier
dissect_ber_integer
dissect_ber_integer64
dissect_ber_length
dissect_ber_null
dissect_ber_object_identifier