diff options
author | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2008-01-15 17:59:43 +0000 |
---|---|---|
committer | etxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7> | 2008-01-15 17:59:43 +0000 |
commit | d9011f3d2a03c238a9fe9d04884c5a83eb67720e (patch) | |
tree | dc5eefb2e31c7c98002669887513632ba215ebaa /epan/dissectors | |
parent | 60e301e0fe934d39a13351f45f3bd5e5041232a0 (diff) |
make per_constrained_integer handle 64bits needed for X2AP.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@24097 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/packet-per.c | 247 | ||||
-rw-r--r-- | epan/dissectors/packet-per.h | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-x2ap.c | 20 |
3 files changed, 259 insertions, 10 deletions
diff --git a/epan/dissectors/packet-per.c b/epan/dissectors/packet-per.c index f01360a7f7..37c6ba09f6 100644 --- a/epan/dissectors/packet-per.c +++ b/epan/dissectors/packet-per.c @@ -1014,8 +1014,59 @@ PER_NOT_DECODED_YET("too long integer"); return offset; } +/* 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; + /* 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; + } + val=0; + for(i=0;i<length;i++){ + if(i==0){ + if(tvb_get_guint8(tvb, offset>>3)&0x80){ + /* negative number */ + val=0xffffffffffffffff; + } 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; +} /* this function reads a constrained integer with or without a PER visible extension marker present @@ -1230,6 +1281,202 @@ DEBUG_ENTRY("dissect_per_constrained_integer"); if (value) *value = val; return offset;} +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. + */ + if( (max==0x7fffffffffffffff && min==0x8000000000000000) + || (max==0xffffffffffffffff && min==0x0000000000000000) ){ + range=0xffffffffffffffff; + } 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))){ + strcat(str, " "); + } + strcat(str,"."); + } + /* read the bits for the int */ + for(i=0;i<num_bits;i++){ + if(bit&&(!(bit%4))){ + strcat(str, " "); + } + if(bit&&(!(bit%8))){ + length+=1; + strcat(str, " "); + } + bit++; + offset=dissect_per_boolean(tvb, offset, actx, tree, -1, &tmp); + val<<=1; + if(tmp){ + val|=1; + strcat(str, "1"); + } else { + strcat(str, "0"); + } + } + for(;bit%8;bit++){ + if(bit&&(!(bit%4))){ + strcat(str, " "); + } + strcat(str,"."); + } + val_start = (offset-num_bits)>>3; val_length = length; + val+=min; + if (display_internal_per_fields) + proto_tree_add_text(tree, tvb, val_start,val_length,"Range = %u Bitfield length %u, %s",range, num_bits, str); + } 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;} + /* 13 Encoding the enumerated type */ guint32 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) diff --git a/epan/dissectors/packet-per.h b/epan/dissectors/packet-per.h index 1b89e9eeac..b4142e75d2 100644 --- a/epan/dissectors/packet-per.h +++ b/epan/dissectors/packet-per.h @@ -100,6 +100,8 @@ extern guint32 dissect_per_integer(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *ac extern guint32 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); +extern 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); + extern guint32 dissect_per_real(tvbuff_t *tvb, guint32 offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index, double *value); extern guint32 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); diff --git a/epan/dissectors/packet-x2ap.c b/epan/dissectors/packet-x2ap.c index 43d8e9887c..f48acbfd63 100644 --- a/epan/dissectors/packet-x2ap.c +++ b/epan/dissectors/packet-x2ap.c @@ -10,7 +10,7 @@ * Routines for dissecting Evolved Universal Terrestrial Radio Access Network (EUTRAN); * X2 Application Protocol (X2AP); * 3GPP TS 36.423 packet dissection - * Copyright 2007, Anders Broman <anders.broman@ericsson.com> + * Copyright 2007-2008, Anders Broman <anders.broman@ericsson.com> * * $Id$ * @@ -385,7 +385,7 @@ dissect_x2ap_Criticality(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_ static int dissect_x2ap_INTEGER_0_maxPrivateIEs(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, maxPrivateIEs, NULL, FALSE); + 0U, maxPrivateIEs, NULL, FALSE); return offset; } @@ -441,7 +441,7 @@ dissect_x2ap_ProcedureCode(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _ ProcedureCode = 0xFFFF; offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, 255U, &ProcedureCode, FALSE); + 0U, 255U, &ProcedureCode, FALSE); #line 54 "x2ap.cnf" if (check_col(actx->pinfo->cinfo, COL_INFO)) @@ -484,7 +484,7 @@ static const value_string x2ap_ProtocolIE_ID_vals[] = { static int dissect_x2ap_ProtocolIE_ID(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, maxProtocolIEs, &ProtocolIE_ID, FALSE); + 0U, maxProtocolIEs, &ProtocolIE_ID, FALSE); return offset; } @@ -636,8 +636,8 @@ dissect_x2ap_PrivateIE_Container(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t * static int dissect_x2ap_SAE_Bearer_BitRate(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { - offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, 4294967295U, NULL, FALSE); + offset = dissect_per_constrained_integer_64b(tvb, offset, actx, tree, hf_index, + 0U, 210000000000U, NULL, FALSE); return offset; } @@ -947,7 +947,7 @@ dissect_x2ap_DL_Forwarding(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _ static int dissect_x2ap_ENB_ID(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, 65535U, NULL, FALSE); + 0U, 65535U, NULL, FALSE); return offset; } @@ -1286,7 +1286,7 @@ dissect_x2ap_RRC_Context(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_ static int dissect_x2ap_INTEGER_1_256(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 1U, 256U, NULL, FALSE); + 1U, 256U, NULL, FALSE); return offset; } @@ -1485,7 +1485,7 @@ dissect_x2ap_UE_HistoryInformation(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t static int dissect_x2ap_UE_S1AP_ID(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, 4095U, NULL, FALSE); + 0U, 4095U, NULL, FALSE); return offset; } @@ -1495,7 +1495,7 @@ dissect_x2ap_UE_S1AP_ID(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, static int dissect_x2ap_UE_X2AP_ID(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) { offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index, - 0U, 4095U, NULL, FALSE); + 0U, 4095U, NULL, FALSE); return offset; } |