diff options
-rw-r--r-- | asn1/x2ap/X2AP-IEs.asn | 4 | ||||
-rw-r--r-- | asn1/x2ap/packet-x2ap-template.c | 2 | ||||
-rw-r--r-- | asn1/x2ap/x2ap.cnf | 3 | ||||
-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 | ||||
-rw-r--r-- | epan/libwireshark.def | 1 |
7 files changed, 265 insertions, 14 deletions
diff --git a/asn1/x2ap/X2AP-IEs.asn b/asn1/x2ap/X2AP-IEs.asn index f9998b6a5b..8f7e455fb4 100644 --- a/asn1/x2ap/X2AP-IEs.asn +++ b/asn1/x2ap/X2AP-IEs.asn @@ -294,9 +294,7 @@ RRC-Context ::= OCTET STRING -- S ---SAE-Bearer-BitRate ::= INTEGER (0..210000000000) --- NOTE THIS needs changes in packet-per.c I think !!!! -SAE-Bearer-BitRate ::= INTEGER (0..4294967295) +SAE-Bearer-BitRate ::= INTEGER (0..210000000000) SAE-BearerLevel-QoS-Parameters ::= SEQUENCE { label INTEGER (1..256), diff --git a/asn1/x2ap/packet-x2ap-template.c b/asn1/x2ap/packet-x2ap-template.c index fe0803ec30..ae9715c969 100644 --- a/asn1/x2ap/packet-x2ap-template.c +++ b/asn1/x2ap/packet-x2ap-template.c @@ -2,7 +2,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$ * diff --git a/asn1/x2ap/x2ap.cnf b/asn1/x2ap/x2ap.cnf index 8d8348d3ad..3140831ab7 100644 --- a/asn1/x2ap/x2ap.cnf +++ b/asn1/x2ap/x2ap.cnf @@ -73,6 +73,9 @@ ProtocolIE-ContainerPairList #.TYPE_ATTR #.END +# Handle 64 bit constraint +#.FN_PARS SAE-Bearer-BitRate FN_VARIANT = _64b + #.ASSIGN_VALUE_TO_TYPE # X2AP does not have constants assigned to types, they are pure INTEGER # ProcedureCode 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; } diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 0fd22c7342..ebd82de497 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -199,6 +199,7 @@ dissect_per_choice dissect_per_constrained_sequence_of dissect_per_constrained_set_of dissect_per_constrained_integer +dissect_per_constrained_integer_64b dissect_per_enumerated dissect_per_external_type dissect_per_GeneralString |