From Pascal Quantin:
authorjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 5 Oct 2008 09:30:24 +0000 (09:30 +0000)
committerjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 5 Oct 2008 09:30:24 +0000 (09:30 +0000)
The attached patch fix several bugs in the decoding function to display the
Cell Channel Description (44.018 chapter 10.5.2.1b) and the Frequency List
(44.018 chapter 10.5.2.13) information elements content.
Without this patch the ARFCNs displayed are completely wrong.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@26354 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dissectors/packet-gsm_a_rr.c

index a22ec3df0463e04cc72932ababb1013b5e085bba..c368cfbbfa66f64bee5356c55e76757992e6fd4c 100644 (file)
@@ -628,13 +628,13 @@ gint ett_gsm_rr_elem[NUM_GSM_RR_ELEM];
 
 #define ARFCN_MAX 1024 /* total number of ARFCNs defined */
 
-static void display_channel_list(guint8 *list, tvbuff_t *tvb, proto_tree *tree)
+static void display_channel_list(guint8 *list, tvbuff_t *tvb, proto_tree *tree, guint32 offset)
 {
        int arfcn;
        proto_item *ti=NULL;
 
-       ti = proto_tree_add_text(tree, tvb, 0, 16, "List of ARFCNs =");
-       for (arfcn=0; arfcn<=ARFCN_MAX; arfcn++) {
+       ti = proto_tree_add_text(tree, tvb, 0, offset, "List of ARFCNs =");
+       for (arfcn=0; arfcn<ARFCN_MAX; arfcn++) {
                if (list[arfcn])
                        proto_item_append_text(ti, " %d", arfcn);
        }
@@ -671,15 +671,15 @@ static int f_k(int k, int *w, int range)
        return n%1024;
 }
 
-static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int range)
+static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, int range)
 {
-       int offset=0, f0, arfcn_orig, bits, w[64], wsize, i, wi;
+       int curr_offset=offset, f0, arfcn_orig, bits, w[64], wsize, i, wi;
        int octet, nwi=1, jwi=0, wbits, imax, iused, arfcn;
        guint8 list[1024];
 
        memset((void*)list,0,sizeof(list));
 
-       octet = tvb_get_guint8(tvb, offset++);
+       octet = tvb_get_guint8(tvb, curr_offset++);
        if (range==1024) {
                f0 = (octet>>2)&1;
                if (f0)
@@ -691,8 +691,8 @@ static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int ra
        }
        else {
                arfcn_orig = (octet&1);
-               arfcn_orig = (arfcn_orig << 8) + tvb_get_guint8(tvb, offset++);
-               octet = tvb_get_guint8(tvb, offset++);
+               arfcn_orig = (arfcn_orig << 8) + tvb_get_guint8(tvb, curr_offset++);
+               octet = tvb_get_guint8(tvb, curr_offset++);
                arfcn_orig = (arfcn_orig << 1) + (octet>>7);
                list[arfcn_orig] = 1;
                bits = 7;
@@ -707,9 +707,9 @@ static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int ra
                        break;
                case 128:
                        wsize=7;
-                       imax = 29;
+                       imax = 28;
                        break;
-       default:
+               default:
                        wsize=0;
                        imax = 0;
                        DISSECTOR_ASSERT_NOT_REACHED();
@@ -722,7 +722,7 @@ static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int ra
                wi = octet & ~(0xff<<bits);      /* mask "bits" low bits to start wi from existing octet */
                wbits = bits;
                if (wsize>wbits) {                        /* need to extract more bits from the next octet */
-                       octet = tvb_get_guint8(tvb, offset++);
+                       octet = tvb_get_guint8(tvb, curr_offset++);
                        wi = (wi << 8) + octet;
                        bits = 8;
                        wbits += 8;
@@ -736,7 +736,7 @@ static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int ra
                        bits = 0;
 
                w[i] = wi;
-               if (w[i]==0) {
+               if ((w[i]==0) || ((curr_offset-offset)>len)) {
                        iused = i - 1;
                        break;    /* all remaining elements must also be zero */
                }
@@ -753,13 +753,13 @@ static void dissect_channel_list_n_range(tvbuff_t *tvb, proto_tree *tree, int ra
                list[arfcn] = 1;
        }
 
-       display_channel_list(list, tvb, tree);
+       display_channel_list(list, tvb, tree, offset);
 
        return;
 }
 
 static guint8
-dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_)
+dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
 {
        guint32 curr_offset;
        guint8  oct,bit,byte;
@@ -776,10 +776,10 @@ dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U
        if ((oct & 0xc0) == 0x00)
        {
                /* bit map 0 */
-               item = proto_tree_add_text(tree,tvb, curr_offset, 16, "List of ARFCNs =");
+               item = proto_tree_add_text(tree,tvb, curr_offset, len, "List of ARFCNs =");
                bit = 4;
                arfcn = 125;
-               for (byte = 0;byte <= 15;byte++)
+               for (byte = 0;byte <= len-1;byte++)
                {
                        oct = tvb_get_guint8(tvb, curr_offset);
                        while (bit-- != 0)
@@ -787,45 +787,45 @@ dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U
                                arfcn--;
                                if (((oct >> bit) & 1) == 1)
                                {
-                                       proto_item_append_text(item," %4d",arfcn);
+                                       proto_item_append_text(item," %d",arfcn);
                                }
                        }
                        bit = 8;
                        curr_offset++;
                }
        }
-       else if ((oct & 0xf8) == 0x80)
+       else if ((oct & 0xc8) == 0x80)
        {
                /* 1024 range */
-               dissect_channel_list_n_range(tvb, tree, 1024);
-               curr_offset = curr_offset + 16;
+               dissect_channel_list_n_range(tvb, tree, curr_offset, len, 1024);
+               curr_offset = curr_offset + len;
        }
-       else if ((oct & 0xfe) == 0x88)
+       else if ((oct & 0xce) == 0x88)
        {
                /* 512 range */
-               dissect_channel_list_n_range(tvb, tree, 512);
-               curr_offset = curr_offset + 16;
+               dissect_channel_list_n_range(tvb, tree, curr_offset, len, 512);
+               curr_offset = curr_offset + len;
        }
-       else if ((oct & 0xfe) == 0x8a)
+       else if ((oct & 0xce) == 0x8a)
        {
                /* 256 range */
-               dissect_channel_list_n_range(tvb, tree, 256);
-               curr_offset = curr_offset + 16;
+               dissect_channel_list_n_range(tvb, tree, curr_offset, len, 256);
+               curr_offset = curr_offset + len;
        }
-       else if ((oct & 0xfe) == 0x8c)
+       else if ((oct & 0xce) == 0x8c)
        {
                /* 128 range */
-               dissect_channel_list_n_range(tvb, tree, 128);
-               curr_offset = curr_offset + 16;
+               dissect_channel_list_n_range(tvb, tree, curr_offset, len, 128);
+               curr_offset = curr_offset + len;
        }
-       else if ((oct & 0xfe) == 0x8e)
+       else if ((oct & 0xce) == 0x8e)
        {
                /* variable bit map */
                arfcn = ((oct & 0x01) << 9) | (tvb_get_guint8(tvb, curr_offset+1) << 1) | ((tvb_get_guint8(tvb, curr_offset + 2) & 0x80) >> 7);
-               item = proto_tree_add_text(tree,tvb, curr_offset, 16,"List of ARFCNs = %d",arfcn);
+               item = proto_tree_add_text(tree,tvb,curr_offset,len,"List of ARFCNs = %d",arfcn);
                curr_offset = curr_offset + 2;
                bit = 7;
-               for (byte = 0;byte <= 13;byte++)
+               for (byte = 0;byte <= len-3;byte++)
                {
                        oct = tvb_get_guint8(tvb, curr_offset);
                        while (bit-- != 0)
@@ -833,7 +833,7 @@ dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U
                                arfcn++;
                                if (((oct >> bit) & 1) == 1)
                                {
-                                       proto_item_append_text(item," %4d",arfcn);
+                                       proto_item_append_text(item," %d",arfcn);
                                }
                        }
                        bit = 8;
@@ -845,9 +845,9 @@ dissect_arfcn_list(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U
 }
 
 guint8
-de_rr_cell_ch_dsc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+de_rr_cell_ch_dsc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_)
 {
-       return dissect_arfcn_list(tvb, tree, offset, len, add_string, string_len);
+       return dissect_arfcn_list(tvb, tree, offset, 16, add_string, string_len);
 }
 /*
  * [3] 10.5.2.1c BA List Pref
@@ -2080,7 +2080,7 @@ static const value_string gsm_a_rr_ext_ind_vals[] = {
        { 0,    NULL }
 };
 static guint8
-de_rr_neigh_cell_desc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+de_rr_neigh_cell_desc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_)
 {
        guint32 curr_offset;
 
@@ -2089,14 +2089,14 @@ de_rr_neigh_cell_desc(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len
        proto_tree_add_item(tree, hf_gsm_a_rr_ext_ind, tvb, curr_offset, 1, FALSE);
        proto_tree_add_item(tree, hf_gsm_a_rr_ba_ind, tvb, curr_offset, 1, FALSE);
 
-       return dissect_arfcn_list(tvb, tree, offset, len, add_string, string_len);
+       return dissect_arfcn_list(tvb, tree, offset, 16, add_string, string_len);
 }
 
  /*
  * [3] 10.5.2.22a Neighbour Cell Description 2
  */
 static guint8
-de_rr_neigh_cell_desc2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len, gchar *add_string _U_, int string_len _U_)
+de_rr_neigh_cell_desc2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len _U_, gchar *add_string _U_, int string_len _U_)
 {
        guint32 curr_offset;
 
@@ -2106,7 +2106,7 @@ de_rr_neigh_cell_desc2(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint le
        proto_tree_add_item(tree, hf_gsm_a_rr_ext_ind, tvb, curr_offset, 1, FALSE);
        proto_tree_add_item(tree, hf_gsm_a_rr_ba_ind, tvb, curr_offset, 1, FALSE);
 
-       return dissect_arfcn_list(tvb, tree, offset, len, add_string, string_len);
+       return dissect_arfcn_list(tvb, tree, offset, 16, add_string, string_len);
 }
 
 /*
@@ -3127,7 +3127,7 @@ dtap_rr_ass_cmd(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint len)
        ELEM_OPT_TLV(0x05, GSM_A_PDU_TYPE_RR, DE_RR_FREQ_LIST, " - Frequency List, after time");
 
        /* 62 Cell Channel Description  10.5.2.1b       O TV 17 */
-       ELEM_OPT_TLV(0x62, GSM_A_PDU_TYPE_RR, DE_RR_CELL_CH_DSC, "");
+       ELEM_OPT_TV(0x62, GSM_A_PDU_TYPE_RR, DE_RR_CELL_CH_DSC, "");
 
        /* 10 Multislot Allocation              10.5.2.21b      C TLV 3-12 */
        ELEM_OPT_TLV(0x10,GSM_A_PDU_TYPE_RR, DE_RR_MULT_ALL, " - Description of the multislot configuration");