Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-umts_mac.c
Line
Count
Source
1
/* packet-umts_mac.c
2
 * Routines for UMTS MAC (3GPP TS 25.321) disassembly
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include "config.h"
12
13
#include <epan/packet.h>
14
#include <epan/conversation.h>
15
#include <epan/expert.h>
16
#include <epan/prefs.h>
17
#include <epan/proto_data.h>
18
19
#include "packet-rrc.h"
20
#include "packet-umts_fp.h"
21
#include "packet-umts_mac.h"
22
#include "packet-nbap.h"
23
24
void proto_register_umts_mac(void);
25
void proto_reg_handoff_umts_mac(void);
26
27
static int proto_umts_mac;
28
static int proto_fp;
29
static int proto_umts_rlc;
30
31
/* dissector fields */
32
static int hf_mac_fach_fdd_tctf;
33
static int hf_mac_rach_fdd_tctf;
34
static int hf_mac_ct;
35
static int hf_mac_ueid_type;
36
static int hf_mac_crnti;
37
static int hf_mac_urnti;
38
static int hf_mac_resolved_urnti;
39
static int hf_mac_crnti_urnti_match_frame;
40
static int hf_mac_channel;
41
/* static int hf_mac_channel_str; */
42
43
static int hf_mac_lch_id;
44
static int hf_mac_macdflowd_id;
45
/* static int hf_mac_channel_hsdsch; */
46
static int hf_mac_trch_id;
47
48
/* static int hf_mac_edch_type2_subframe_header; */
49
/* static int hf_mac_edch_type2_descriptors; */
50
/* static int hf_mac_edch_type2_lchid; */
51
/* static int hf_mac_edch_type2_length; */
52
/* static int hf_mac_edch_type2_flag; */
53
static int hf_mac_edch_type2_tsn;
54
static int hf_mac_edch_type2_ss;
55
static int hf_mac_edch_type2_ss_interpretation;
56
static int hf_mac_edch_type2_sdu;
57
static int hf_mac_edch_type2_sdu_data;
58
static int hf_mac_is_fraglink;
59
static int hf_mac_is_reasmin;
60
61
/* subtrees */
62
static int ett_mac;
63
static int ett_mac_fach;
64
static int ett_mac_rach;
65
static int ett_mac_dch;
66
static int ett_mac_pch;
67
static int ett_mac_edch;
68
static int ett_mac_hsdsch;
69
static int ett_mac_edch_type2;
70
static int ett_mac_edch_type2_sdu;
71
static int ett_mac_resolved_urnti;
72
73
static expert_field ei_mac_cs_dtch_not_implemented;
74
static expert_field ei_mac_rach_tctf_unknown;
75
static expert_field ei_mac_unknown_content;
76
static expert_field ei_mac_per_frame_info_missing;
77
static expert_field ei_mac_fach_content_type_unknown;
78
static expert_field ei_mac_no_logical_channel;
79
static expert_field ei_mac_faked_logical_channel_id;
80
static expert_field ei_mac_macis_sdu_reassembled;
81
static expert_field ei_mac_macis_sdu_first;
82
static expert_field ei_mac_macis_sdu_middle;
83
static expert_field ei_mac_macis_sdu_last;
84
static expert_field ei_mac_macis_sdu_complete;
85
static expert_field ei_mac_reserved_c_t;
86
87
static dissector_handle_t rlc_pcch_handle;
88
static dissector_handle_t rlc_ccch_handle;
89
static dissector_handle_t rlc_ctch_handle;
90
static dissector_handle_t rlc_dcch_handle;
91
static dissector_handle_t rlc_ps_dtch_handle;
92
static dissector_handle_t rrc_handle;
93
94
/* MAC-is reassembly */
95
static size_t MAX_TSN = 64;
96
static uint16_t mac_tsn_size = 6;
97
static int global_mac_tsn_size = MAC_TSN_6BITS;
98
0
int get_mac_tsn_size(void) { return global_mac_tsn_size; }
99
static const enum_val_t tsn_size_enumvals[] = {
100
    {"6",  "6 bits",  MAC_TSN_6BITS},
101
    {"14", "14 bits", MAC_TSN_14BITS},
102
    {NULL, NULL, -1}};
103
enum mac_is_fragment_type {
104
    MAC_IS_HEAD,
105
    MAC_IS_MIDDLE,
106
    MAC_IS_TAIL
107
};
108
typedef struct _mac_is_fragment {
109
    uint8_t * data;
110
    uint32_t length;
111
    uint32_t frame_num;
112
    uint16_t tsn;
113
    uint8_t type;
114
    struct _mac_is_fragment * next;
115
} mac_is_fragment;
116
typedef struct {
117
    uint32_t frame_num; /* Where reassembly was done (depends on order of arrival). */
118
    uint16_t tsn; /* TSN for the tail fragment. */
119
    uint8_t * data;
120
    uint32_t length;
121
    mac_is_fragment * fragments;
122
} mac_is_sdu;
123
typedef struct {
124
    mac_is_fragment * head;
125
    mac_is_fragment * middle;
126
    mac_is_fragment * tail;
127
} body_parts;
128
typedef struct {
129
    uint8_t lchid; /* Logical Channel Identifier. */
130
    unsigned ueid; /* User Equipment Identifier. */
131
} mac_is_channel;
132
static GHashTable * mac_is_sdus; /* channel -> (frag -> sdu) */
133
static GHashTable * mac_is_fragments; /* channel -> body_parts[] */
134
static gboolean mac_is_channel_equal(const void *a, const void *b)
135
0
{
136
0
    const mac_is_channel *x = (const mac_is_channel *)a, *y = (const mac_is_channel *)b;
137
0
    return x->lchid == y->lchid && x->ueid == y->ueid;
138
0
}
139
static unsigned mac_is_channel_hash(const void *key)
140
0
{
141
0
    const mac_is_channel * ch = (const mac_is_channel *)key;
142
0
    return (ch->ueid << 4)  | ch->lchid;
143
0
}
144
145
static gboolean mac_is_fragment_equal(const void *a, const void *b)
146
0
{
147
0
    const mac_is_fragment *x = (const mac_is_fragment *)a, *y = (const mac_is_fragment *)b;
148
0
    return x->frame_num == y->frame_num && x->tsn == y->tsn && x->type == y->type;
149
0
}
150
static unsigned mac_is_fragment_hash(const void *key)
151
0
{
152
0
    const mac_is_fragment *frag = (const mac_is_fragment *)key;
153
0
    return (frag->frame_num << 2) | frag->type;
154
0
}
155
156
static const value_string rach_fdd_tctf_vals[] = {
157
    { TCTF_CCCH_RACH_FDD      , "CCCH over RACH (FDD)" },
158
    { TCTF_DCCH_DTCH_RACH_FDD , "DCCH/DTCH over RACH (FDD)" },
159
    { 0, NULL }};
160
161
static const value_string fach_fdd_tctf_vals[] = {
162
    { TCTF_BCCH_FACH_FDD      , "BCCH over FACH (FDD)" },
163
    { TCTF_DCCH_DTCH_FACH_FDD , "DCCH/DTCH over FACH (FDD)" },
164
    { TCTF_MTCH_FACH_FDD      , "MTCH over FACH (FDD)" },
165
    { TCTF_CCCH_FACH_FDD      , "CCCH over FACH (FDD)" },
166
    { TCTF_MCCH_FACH_FDD      , "MCCH over FACH (FDD)" },
167
    { TCTF_MSCH_FACH_FDD      , "MSCH over FACH (FDD)" },
168
    { TCTF_CTCH_FACH_FDD      , "CTCH over FACH (FDD)" },
169
    { 0, NULL }};
170
171
static const value_string ueid_type_vals[] = {
172
    { MAC_UEID_TYPE_URNTI,  "U-RNTI" },
173
    { MAC_UEID_TYPE_CRNTI,  "C-RNTI" },
174
    { 0, NULL }};
175
176
static const value_string mac_logical_channel_vals[] = {
177
    { MAC_PCCH, "PCCH" },
178
    { MAC_CCCH, "CCCH" },
179
    { MAC_CTCH, "CTCH" },
180
    { MAC_DCCH, "DCCH" },
181
    { MAC_DTCH, "DTCH" },
182
    { MAC_BCCH, "BCCH" },
183
    { MAC_MCCH, "MCCH" },
184
    { MAC_MSCH, "MSCH" },
185
    { MAC_MTCH, "MTCH" },
186
    { MAC_N_A, "N/A" },
187
    { 0, NULL }};
188
189
static uint8_t fach_fdd_tctf(uint8_t hdr, uint16_t *bit_offs)
190
0
{
191
0
    uint8_t tctf;
192
    /* first, test for valid 2-bit combinations */
193
0
    tctf = hdr >> 6;
194
0
    switch (tctf) {
195
0
        case TCTF_BCCH_FACH_FDD:
196
0
        case TCTF_DCCH_DTCH_FACH_FDD:
197
0
            *bit_offs = 2;
198
0
            return tctf;
199
0
    }
200
    /* 4-bit combinations */
201
0
    tctf = hdr >> 4;
202
0
    switch (tctf) {
203
0
        case TCTF_MTCH_FACH_FDD:
204
0
            *bit_offs = 4;
205
0
            return tctf;
206
0
    }
207
    /* just return the 8-bit combination */
208
0
    *bit_offs = 8;
209
0
    tctf = hdr;
210
0
    switch (tctf) {
211
0
        case TCTF_CCCH_FACH_FDD:
212
0
        case TCTF_MCCH_FACH_FDD:
213
0
        case TCTF_MSCH_FACH_FDD:
214
0
        case TCTF_CTCH_FACH_FDD:
215
0
            return tctf;
216
0
        default:
217
0
            return tctf; /* TODO */
218
0
    }
219
0
}
220
221
static uint16_t tree_add_common_dcch_dtch_fields(tvbuff_t *tvb, packet_info *pinfo _U_,
222
    proto_tree *tree, uint16_t bitoffs, fp_info *fpinf, umts_mac_info *macinf, rlc_info  *rlcinf)
223
0
{
224
0
    uint8_t ueid_type;
225
0
    conversation_t   *p_conv;
226
0
    umts_fp_conversation_info_t *umts_fp_conversation_info = NULL;
227
0
    fp_rach_channel_info_t *fp_rach_channel_info = NULL;
228
0
    fp_fach_channel_info_t *fp_fach_channel_info = NULL;
229
0
    wmem_tree_t* channel_rnti_map = NULL;
230
0
    uint16_t c_rnti;
231
0
    fp_crnti_allocation_info_t *fp_crnti_allocation_info = NULL;
232
233
0
    ueid_type = tvb_get_bits8(tvb, bitoffs, 2);
234
0
    proto_tree_add_bits_item(tree, hf_mac_ueid_type, tvb, bitoffs, 2, ENC_BIG_ENDIAN);
235
0
    bitoffs += 2;
236
0
    if (ueid_type == MAC_UEID_TYPE_URNTI) {
237
0
        proto_tree_add_bits_item(tree, hf_mac_urnti, tvb, bitoffs, 32, ENC_BIG_ENDIAN);
238
0
        rlcinf->ueid[fpinf->cur_tb] = tvb_get_bits32(tvb, bitoffs, 32,ENC_BIG_ENDIAN);
239
0
        bitoffs += 32;
240
0
    } else if (ueid_type == MAC_UEID_TYPE_CRNTI) {
241
0
        proto_tree_add_bits_item(tree, hf_mac_crnti, tvb, 4, 16, ENC_BIG_ENDIAN);
242
0
        c_rnti = tvb_get_bits16(tvb, bitoffs, 16,ENC_BIG_ENDIAN);
243
0
        p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
244
0
                        conversation_pt_to_conversation_type(pinfo->ptype),
245
0
                        pinfo->destport, pinfo->srcport, NO_ADDR_B);
246
0
        if (p_conv != NULL) {
247
0
            umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp);
248
0
        }
249
        /* Trying to resolve the U-RNTI for this C-RNTI based on the channel type*/
250
0
        switch(fpinf->channel){
251
0
            case CHANNEL_RACH_FDD:
252
                /* In RACH: Get the channel's RNTIs map */
253
0
                if (umts_fp_conversation_info) {
254
0
                    fp_rach_channel_info = (fp_rach_channel_info_t *)umts_fp_conversation_info->channel_specific_info;
255
0
                    if(fp_rach_channel_info) {
256
0
                        channel_rnti_map = fp_rach_channel_info->crnti_to_urnti_map;
257
0
                    }
258
0
                }
259
0
                break;
260
0
            case CHANNEL_FACH_FDD:
261
                /* In FACH: Get the channel's RNTIs map */
262
0
                if (umts_fp_conversation_info) {
263
0
                    fp_fach_channel_info = (fp_fach_channel_info_t *)umts_fp_conversation_info->channel_specific_info;
264
0
                    if(fp_fach_channel_info) {
265
0
                        channel_rnti_map = fp_fach_channel_info->crnti_to_urnti_map;
266
0
                    }
267
0
                }
268
0
                break;
269
0
        }
270
0
        if(channel_rnti_map) {
271
0
            fp_crnti_allocation_info = (fp_crnti_allocation_info_t *)wmem_tree_lookup32(channel_rnti_map, c_rnti);
272
0
        }
273
        /* If not found in the RACH/FACH channel's map, Look in the global RNTIs map */
274
0
        if(fp_crnti_allocation_info == NULL) {
275
0
            fp_crnti_allocation_info = (fp_crnti_allocation_info_t *)wmem_tree_lookup32(rrc_global_urnti_crnti_map, c_rnti);
276
0
            if(fp_crnti_allocation_info != NULL) {
277
                /* If found in the global map, check how many times it was retrieved (including this one) */
278
0
                fp_crnti_allocation_info->global_retrieval_count++;
279
                /* If seen 2 times (RACH + fast FACH) remove from global map */
280
0
                if(fp_crnti_allocation_info->global_retrieval_count == 2) {
281
0
                    wmem_tree_remove32(rrc_global_urnti_crnti_map, c_rnti);
282
0
                }
283
                /* Also add to this channel's map for later retrieval */
284
0
                if(channel_rnti_map) {
285
0
                    wmem_tree_insert32(channel_rnti_map, c_rnti, (void *)fp_crnti_allocation_info);
286
0
                }
287
0
            }
288
0
        }
289
        /* Choosing between resolved U-RNTI (if found) or the C-RNTI as UE-ID for RLC */
290
0
        if(fp_crnti_allocation_info != NULL) {
291
            /* Using U-RNTI */
292
0
            rlcinf->ueid[fpinf->cur_tb] = fp_crnti_allocation_info->urnti;
293
            /* Adding 'Resolved U-RNTI' related tree items*/
294
0
            proto_item *temp;
295
0
            proto_tree *resolved_urnti_tree;
296
0
            temp = proto_tree_add_uint(tree, hf_mac_resolved_urnti, tvb, 0, 0, fp_crnti_allocation_info->urnti);
297
0
            proto_item_set_generated(temp);
298
0
            resolved_urnti_tree = proto_item_add_subtree(temp, ett_mac_resolved_urnti);
299
0
            temp = proto_tree_add_uint(resolved_urnti_tree , hf_mac_crnti_urnti_match_frame, tvb, 0, 0, fp_crnti_allocation_info->alloc_frame_number);
300
0
            proto_item_set_generated(temp);
301
0
        }
302
0
        else {
303
            /* Using C-RNTI */
304
0
            rlcinf->ueid[fpinf->cur_tb] = c_rnti;
305
0
        }
306
0
        bitoffs += 16;
307
0
    }
308
309
0
    if (macinf->ctmux[fpinf->cur_tb]) {
310
0
        proto_item * temp;
311
0
        if(rlcinf){
312
0
            rlcinf->rbid[fpinf->cur_tb] = tvb_get_bits8(tvb, bitoffs, 4)+1;
313
0
        }
314
0
        proto_tree_add_bits_item(tree, hf_mac_ct, tvb, bitoffs, 4, ENC_BIG_ENDIAN);
315
0
        bitoffs += 4;
316
0
        if(rlcinf){
317
0
            temp = proto_tree_add_uint(tree, hf_mac_lch_id, tvb, 0, 0, rlcinf->rbid[fpinf->cur_tb]);
318
0
            proto_item_set_generated(temp);
319
0
        }
320
0
    }
321
0
    return bitoffs;
322
0
}
323
324
static int dissect_mac_fdd_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
325
0
{
326
0
    proto_tree *pch_tree = NULL;
327
0
    proto_item *channel_type;
328
329
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
330
0
    col_set_str(pinfo->cinfo, COL_INFO, "PCCH");
331
332
0
    if (tree) {
333
0
        proto_item *ti;
334
0
        ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
335
0
        pch_tree = proto_item_add_subtree(ti, ett_mac_pch);
336
0
        proto_item_append_text(ti, " (PCCH)");
337
0
        channel_type = proto_tree_add_uint(pch_tree, hf_mac_channel, tvb, 0, 0, MAC_PCCH);
338
0
        proto_item_set_generated(channel_type);
339
0
    }
340
0
    call_dissector_with_data(rlc_pcch_handle, tvb, pinfo, tree, data);
341
0
    return tvb_captured_length(tvb);
342
0
}
343
344
static int dissect_mac_fdd_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
345
0
{
346
0
    uint8_t        tctf;
347
0
    uint8_t        chan;
348
0
    uint16_t       bitoffs   = 0;
349
0
    tvbuff_t      *next_tvb;
350
0
    proto_tree    *rach_tree = NULL;
351
0
    proto_item    *channel_type;
352
0
    umts_mac_info *macinf;
353
0
    fp_info       *fpinf;
354
0
    rlc_info      *rlcinf;
355
0
    proto_item    *ti        = NULL;
356
0
    uint8_t        c_t;
357
    /* RACH TCTF is always 2 bit */
358
0
    tctf = tvb_get_bits8(tvb, 0, 2);
359
0
    bitoffs += 2;
360
361
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
362
363
0
    col_set_str(pinfo->cinfo, COL_INFO,
364
0
        val_to_str_const(tctf, rach_fdd_tctf_vals, "Unknown TCTF"));
365
366
0
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
367
0
    rach_tree = proto_item_add_subtree(ti, ett_mac_rach);
368
369
0
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
370
0
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
371
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
372
0
    if (!macinf || !fpinf) {
373
0
        proto_tree_add_expert_remaining(rach_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
374
0
        return 1;
375
0
    }
376
377
0
    proto_tree_add_bits_item(rach_tree, hf_mac_rach_fdd_tctf, tvb, 0, 2, ENC_BIG_ENDIAN);
378
0
    if (tctf == TCTF_DCCH_DTCH_RACH_FDD) {
379
0
        macinf->ctmux[fpinf->cur_tb] = 1; /* DCCH/DTCH on RACH *always* has a C/T */
380
0
        bitoffs = tree_add_common_dcch_dtch_fields(tvb, pinfo, rach_tree, bitoffs, fpinf, macinf, rlcinf);
381
0
    }
382
383
0
    chan = fpinf->cur_chan;
384
    /* handoff to next dissector */
385
0
    switch (tctf) {
386
0
        case TCTF_CCCH_RACH_FDD:
387
0
            proto_item_append_text(ti, " (CCCH)");
388
0
            channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_CCCH);
389
0
            proto_item_set_generated(channel_type);
390
0
            next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
391
0
            add_new_data_source(pinfo, next_tvb, "Octet-Aligned CCCH Data");
392
0
            call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
393
0
            break;
394
0
        case TCTF_DCCH_DTCH_RACH_FDD:
395
            /*Set RLC Mode/MAC content based on the L-CHID derived from the C/T flag*/
396
0
            c_t = tvb_get_bits8(tvb,bitoffs-4,4);
397
0
            if (c_t == 15) {
398
                /* reserved value, discard PDU */
399
0
                expert_add_info(pinfo, NULL, &ei_mac_reserved_c_t);
400
0
                break;
401
0
            }
402
0
            rlcinf->mode[chan] = lchId_rlc_map[c_t+1];
403
0
            macinf->content[chan] = lchId_type_table[c_t+1];
404
0
            rlcinf->rbid[chan] = c_t+1;
405
0
            switch (macinf->content[chan]) {
406
0
                case MAC_CONTENT_DCCH:
407
0
                    proto_item_append_text(ti, " (DCCH)");
408
0
                    channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
409
0
                    proto_item_set_generated(channel_type);
410
0
                    next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
411
0
                    add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
412
0
                    call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
413
0
                    break;
414
0
                case MAC_CONTENT_PS_DTCH:
415
0
                    proto_item_append_text(ti, " (PS DTCH)");
416
0
                    channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
417
0
                    proto_item_set_generated(channel_type);
418
0
                    next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
419
0
                    add_new_data_source(pinfo, next_tvb, "Octet-Aligned DTCH Data");
420
0
                    call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
421
0
                    break;
422
0
                case MAC_CONTENT_CS_DTCH:
423
0
                    proto_item_append_text(ti, " (CS DTCH)");
424
                    /* TODO */
425
0
                    break;
426
0
                default:
427
0
                    proto_item_append_text(ti, " (Unknown RACH DCCH/DTCH Content)");
428
0
                    expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown RACH DCCH/DTCH Content");
429
0
            }
430
0
            break;
431
0
        default:
432
0
            proto_item_append_text(ti, " (Unknown RACH TCTF)");
433
0
            expert_add_info(pinfo, NULL, &ei_mac_rach_tctf_unknown);
434
0
    }
435
0
    return tvb_captured_length(tvb);
436
0
}
437
438
static int dissect_mac_fdd_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
439
0
{
440
0
    uint8_t        hdr, tctf;
441
0
    uint16_t       bitoffs   = 0;
442
0
    uint16_t       tctf_len, chan;
443
0
    proto_tree    *fach_tree = NULL;
444
0
    proto_item    *channel_type;
445
0
    tvbuff_t *next_tvb;
446
0
    umts_mac_info *macinf;
447
0
    fp_info       *fpinf;
448
0
    rlc_info      *rlcinf;
449
0
    struct rrc_info *rrcinf;
450
0
    proto_item    *ti        = NULL;
451
0
    int c_t;
452
0
    hdr = tvb_get_uint8(tvb, 0);
453
454
    /* get target channel type field */
455
0
    tctf = fach_fdd_tctf(hdr, &bitoffs);
456
0
    tctf_len = bitoffs;
457
458
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
459
460
0
    col_set_str(pinfo->cinfo, COL_INFO,
461
0
        val_to_str_const(tctf, fach_fdd_tctf_vals, "Unknown TCTF"));
462
463
0
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
464
0
    fach_tree = proto_item_add_subtree(ti, ett_mac_fach);
465
466
0
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
467
0
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
468
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
469
470
0
    if (!macinf || !fpinf) {
471
0
        proto_tree_add_expert_remaining(fach_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
472
0
        return 1;
473
0
    }
474
475
0
    proto_tree_add_bits_item(fach_tree, hf_mac_fach_fdd_tctf, tvb, 0, tctf_len, ENC_BIG_ENDIAN);
476
0
    if (tctf == TCTF_DCCH_DTCH_FACH_FDD) {
477
0
        macinf->ctmux[fpinf->cur_tb] = 1; /* DCCH/DTCH on FACH *always* has a C/T */
478
0
        bitoffs = tree_add_common_dcch_dtch_fields(tvb, pinfo, fach_tree, bitoffs, fpinf, macinf, rlcinf);
479
0
    }
480
481
0
    chan = fpinf->cur_chan;
482
0
    switch (tctf) {
483
0
        case TCTF_CCCH_FACH_FDD:
484
0
            proto_item_append_text(ti, " (CCCH)");
485
0
            channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_CCCH);
486
0
            proto_item_set_generated(channel_type);
487
            /* CCCH over FACH is always octet aligned */
488
0
            next_tvb = tvb_new_subset_remaining(tvb, 1);
489
0
            call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
490
0
            break;
491
0
        case TCTF_DCCH_DTCH_FACH_FDD:
492
493
            /*Set RLC Mode based on the L-CHID derived from the C/T flag*/
494
0
            c_t = tvb_get_bits8(tvb,bitoffs-4,4);
495
0
            if (c_t == 15) {
496
                /* reserved value, discard PDU */
497
0
                expert_add_info(pinfo, NULL, &ei_mac_reserved_c_t);
498
0
                break;
499
0
            }
500
0
            rlcinf->mode[fpinf->cur_tb] = lchId_rlc_map[c_t+1];
501
0
            macinf->content[fpinf->cur_tb] = lchId_type_table[c_t+1];
502
0
            switch (macinf->content[fpinf->cur_tb]) {
503
504
0
                case MAC_CONTENT_DCCH:
505
0
                    proto_item_append_text(ti, " (DCCH)");
506
0
                    channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
507
0
                    proto_item_set_generated(channel_type);
508
0
                    next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
509
0
                    add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
510
0
                    call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
511
0
                    break;
512
0
                case MAC_CONTENT_PS_DTCH:
513
0
                    proto_item_append_text(ti, " (PS DTCH)");
514
0
                    channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
515
0
                    proto_item_set_generated(channel_type);
516
0
                    next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
517
0
                    add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
518
0
                    call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
519
0
                    break;
520
0
                case MAC_CONTENT_CS_DTCH:
521
0
                    proto_item_append_text(ti, " (CS DTCH)");
522
0
                    expert_add_info(pinfo, NULL, &ei_mac_cs_dtch_not_implemented);
523
                    /* TODO */
524
0
                    break;
525
0
                default:
526
0
                    proto_item_append_text(ti, " (Unknown FACH Content)");
527
0
                    expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown FACH Content for this transportblock");
528
0
            }
529
0
            break;
530
0
        case TCTF_CTCH_FACH_FDD:
531
0
            proto_item_append_text(ti, " (CTCH)");
532
0
            channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_CTCH);
533
0
            proto_item_set_generated(channel_type);
534
            /* CTCH over FACH is always octet aligned */
535
0
            next_tvb = tvb_new_subset_remaining(tvb, 1);
536
0
            call_dissector_with_data(rlc_ctch_handle, next_tvb, pinfo, tree, data);
537
0
            break;
538
        /* july 5: Added support for BCCH*/
539
0
        case TCTF_BCCH_FACH_FDD:
540
0
            proto_item_append_text(ti, " (BCCH)");
541
0
            channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_BCCH);
542
0
            proto_item_set_generated(channel_type);
543
544
            /*We need to skip the first two bits (the TCTF bits), and since there is no MAC header, send rest to RRC*/
545
0
            next_tvb= tvb_new_octet_aligned(tvb, 2, (tvb_reported_length(tvb)*8)-2);
546
0
            add_new_data_source(pinfo, next_tvb, "Octet-Aligned BCCH Data");
547
548
            /* In this case skip RLC and call RRC immediately subdissector */
549
0
            rrcinf = (rrc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0);
550
0
            if (!rrcinf) {
551
0
                rrcinf = wmem_new0(wmem_file_scope(), struct rrc_info);
552
0
                p_add_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0, rrcinf);
553
0
            }
554
0
            rrcinf->msgtype[fpinf->cur_tb] = RRC_MESSAGE_TYPE_BCCH_FACH;
555
556
0
            call_dissector_with_data(rrc_handle, next_tvb, pinfo, tree, data);
557
558
0
            break;
559
0
        case TCTF_MSCH_FACH_FDD:
560
0
        case TCTF_MCCH_FACH_FDD:
561
0
        case TCTF_MTCH_FACH_FDD:
562
0
            expert_add_info(pinfo, NULL, &ei_mac_fach_content_type_unknown);
563
0
            break;
564
0
        default:
565
0
            proto_item_append_text(ti, " (Unknown FACH Content)");
566
0
            expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, " Unknown FACH Content");
567
0
            break;
568
0
    }
569
0
    return tvb_captured_length(tvb);
570
0
}
571
572
static int dissect_mac_fdd_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
573
0
{
574
0
    uint16_t       pos;
575
0
    uint8_t        bitoffs  = 0;
576
0
    umts_mac_info *macinf;
577
0
    fp_info       *fpinf;
578
0
    rlc_info      *rlcinf;
579
0
    proto_tree    *dch_tree = NULL;
580
0
    proto_item    *channel_type;
581
0
    tvbuff_t      *next_tvb;
582
0
    proto_item    *ti       = NULL;
583
584
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
585
586
0
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
587
0
    dch_tree = proto_item_add_subtree(ti, ett_mac_dch);
588
589
0
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
590
0
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
591
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
592
593
0
    if (!macinf || !fpinf) {
594
0
        proto_tree_add_expert_remaining(dch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
595
0
        return 1;
596
0
    }
597
0
    pos = fpinf->cur_tb;
598
599
0
    if (macinf->ctmux[pos]) {
600
0
        if(rlcinf){
601
0
            rlcinf->rbid[fpinf->cur_tb] = tvb_get_bits8(tvb, bitoffs, 4)+1;
602
0
        }
603
        /*Add CT flag to GUI*/
604
0
        proto_tree_add_bits_item(dch_tree, hf_mac_ct, tvb, 0, 4, ENC_BIG_ENDIAN);
605
0
        bitoffs = 4;
606
0
    }
607
608
0
    if (bitoffs) {
609
0
        next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[pos] - bitoffs);
610
0
        add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
611
0
    } else
612
0
        next_tvb = tvb;
613
0
    switch (macinf->content[pos]) {
614
0
        case MAC_CONTENT_DCCH:
615
0
            proto_item_append_text(ti, " (DCCH)");
616
617
            /*Show logical channel id*/
618
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
619
0
            proto_item_set_generated(channel_type);
620
0
            if(macinf->lchid[pos]!= 255){
621
622
0
                if(macinf->fake_chid[pos]){
623
0
                    expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
624
0
                }
625
0
            }else{
626
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
627
0
            }
628
629
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
630
0
            proto_item_set_generated(channel_type);
631
632
            /*Transport channel printout*/
633
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_trch_id, tvb, 0, 0, macinf->trchid[pos]);
634
0
            proto_item_set_generated(channel_type);
635
0
            call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
636
0
            break;
637
0
        case MAC_CONTENT_PS_DTCH:
638
0
            proto_item_append_text(ti, " (PS DTCH)");
639
             /*Show logical channel id*/
640
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
641
0
            proto_item_set_generated(channel_type);
642
643
0
            if(macinf->lchid[pos]== 255){
644
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
645
0
            }
646
647
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
648
0
            proto_item_set_generated(channel_type);
649
0
            call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
650
0
            break;
651
0
        case MAC_CONTENT_CS_DTCH:
652
0
            proto_item_append_text(ti, " (CS DTCH)");
653
            /*Show logical channel id*/
654
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
655
0
            proto_item_set_generated(channel_type);
656
0
            if(macinf->lchid[pos]!= 255){
657
0
                if(macinf->fake_chid[pos]){
658
0
                    expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
659
0
                }
660
0
            }else{
661
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
662
0
            }
663
664
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
665
0
            proto_item_set_generated(channel_type);
666
667
            /*Transport channel printout*/
668
0
            channel_type = proto_tree_add_uint(dch_tree, hf_mac_trch_id, tvb, 0, 0, macinf->trchid[pos]);
669
0
            proto_item_set_generated(channel_type);
670
671
0
            break;
672
0
        default:
673
0
            proto_item_append_text(ti, " (Unknown DCH Content)");
674
0
            expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown DCH Content");
675
0
    }
676
0
    return tvb_captured_length(tvb);
677
0
}
678
679
static void init_frag(tvbuff_t * tvb, body_parts * bp, unsigned length, unsigned offset, uint32_t frame_num, uint16_t tsn, uint8_t type)
680
0
{
681
0
    mac_is_fragment * frag = wmem_new(wmem_file_scope(), mac_is_fragment);
682
0
    frag->type = type;
683
0
    frag->length = length;
684
0
    frag->data = (uint8_t *)wmem_alloc(wmem_file_scope(), length);
685
0
    frag->frame_num = frame_num;
686
0
    frag->tsn = tsn;
687
0
    frag->next = NULL;
688
0
    switch (type) {
689
0
        case MAC_IS_HEAD:
690
0
            DISSECTOR_ASSERT(bp->head == NULL);
691
0
            bp->head = frag;
692
0
            break;
693
0
        case MAC_IS_MIDDLE:
694
0
            DISSECTOR_ASSERT(bp->middle == NULL);
695
0
            bp->middle = frag;
696
0
            break;
697
0
        case MAC_IS_TAIL:
698
0
            DISSECTOR_ASSERT(bp->tail == NULL);
699
0
            bp->tail = frag;
700
0
            break;
701
0
    }
702
0
    tvb_memcpy(tvb, frag->data, offset, length);
703
0
}
704
705
static void mac_is_copy(mac_is_sdu * sdu, mac_is_fragment * frag, unsigned total_length, bool reverse)
706
0
{
707
0
    DISSECTOR_ASSERT(sdu->length+frag->length <= total_length);
708
0
    if (reverse) {
709
0
        memcpy(sdu->data+total_length-frag->length-sdu->length, frag->data, frag->length);
710
0
    } else {
711
0
        memcpy(sdu->data+sdu->length, frag->data, frag->length);
712
0
    }
713
0
    sdu->length += frag->length;
714
0
    wmem_free(wmem_file_scope(), frag->data);
715
0
}
716
717
/*
718
 * @param length Length of whole SDU, it will be verified.
719
 */
720
static tvbuff_t * reassemble(tvbuff_t * tvb, body_parts ** body_parts_array, uint16_t head_tsn, unsigned length, mac_is_channel * ch, unsigned frame_num)
721
0
{
722
0
    mac_is_sdu * sdu;
723
0
    mac_is_fragment * f;
724
0
    uint16_t i;
725
0
    GHashTable * sdus;
726
727
    /* Find frag->sdu hash table for this channel. */
728
0
    sdus = (GHashTable *)g_hash_table_lookup(mac_is_sdus, ch);
729
    /* If this is the first time we see this channel. */
730
0
    if (sdus == NULL) {
731
0
        mac_is_channel * channel;
732
0
        sdus = g_hash_table_new(mac_is_fragment_hash, mac_is_fragment_equal);
733
0
        channel = wmem_new(wmem_file_scope(), mac_is_channel);
734
0
        *channel = *ch;
735
0
        g_hash_table_insert(mac_is_sdus, channel, sdus);
736
0
    }
737
738
0
    sdu = wmem_new(wmem_file_scope(), mac_is_sdu);
739
0
    sdu->length = 0;
740
0
    sdu->data = (uint8_t *)wmem_alloc(wmem_file_scope(), length);
741
742
0
    f = body_parts_array[head_tsn]->head; /* Start from head. */
743
0
    g_hash_table_insert(sdus, f, sdu); /* Insert head->sdu mapping. */
744
0
    body_parts_array[head_tsn]->head = NULL; /* Reset head. */
745
0
    mac_is_copy(sdu, f, length, false); /* Copy head data into SDU. */
746
0
    sdu->fragments = f; /* Set up fragments list to point at head. */
747
0
    sdu->frame_num = frame_num; /* Frame number where reassembly is being done. */
748
749
0
    for (i = (head_tsn+1)%MAX_TSN; body_parts_array[i]->middle != NULL; i = (i+1)%MAX_TSN)
750
0
    {
751
0
        f = f->next = body_parts_array[i]->middle; /* Iterate through. */
752
0
        g_hash_table_insert(sdus, f, sdu); /* Insert middle->sdu mapping. */
753
0
        body_parts_array[i]->middle = NULL; /* Reset. */
754
0
        mac_is_copy(sdu, f, length, false); /* Copy middle data into SDU. */
755
0
    }
756
0
    DISSECTOR_ASSERT(body_parts_array[i]->tail != NULL);
757
758
0
    f->next = body_parts_array[i]->tail;
759
0
    g_hash_table_insert(sdus, f->next, sdu); /* Insert tail->sdu mapping. */
760
0
    body_parts_array[i]->tail = NULL; /* Reset tail. */
761
0
    sdu->tsn = i; /* Use TSN of tail as key for the SDU. */
762
0
    mac_is_copy(sdu, f->next, length, false); /* Copy tail data into SDU. */
763
764
0
    return tvb_new_child_real_data(tvb, sdu->data, sdu->length, sdu->length);
765
0
}
766
767
static mac_is_sdu * get_sdu(unsigned frame_num, uint16_t tsn, uint8_t type, mac_is_channel * ch)
768
0
{
769
0
    mac_is_sdu * sdu = NULL;
770
0
    GHashTable * sdus = NULL;
771
0
    mac_is_fragment frag_lookup_key;
772
773
0
    sdus = (GHashTable *)g_hash_table_lookup(mac_is_sdus, ch);
774
0
    if (sdus) {
775
0
        frag_lookup_key.frame_num = frame_num;
776
0
        frag_lookup_key.tsn = tsn;
777
0
        frag_lookup_key.type = type;
778
0
        sdu = (mac_is_sdu *)g_hash_table_lookup(sdus, &frag_lookup_key);
779
0
        return sdu;
780
0
    }
781
0
    return NULL;
782
0
}
783
784
static tvbuff_t * add_to_tree(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, mac_is_sdu * sdu, unsigned offset, uint16_t maclength, uint8_t type)
785
0
{
786
0
    tvbuff_t * new_tvb = NULL;
787
788
0
    if (sdu->frame_num == pinfo->num) {
789
0
        mac_is_fragment * f = sdu->fragments;
790
0
        unsigned counter = 0;
791
0
        new_tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->length, sdu->length);
792
0
        add_new_data_source(pinfo, new_tvb, "Reassembled MAC-is SDU");
793
0
        proto_tree_add_expert_remaining(tree, pinfo, &ei_mac_macis_sdu_reassembled, new_tvb, 0);
794
795
0
        while (f) {
796
0
            proto_tree_add_uint_format_value(tree, hf_mac_is_fraglink, new_tvb,
797
0
                    counter, f->length, f->frame_num,
798
0
                    "%u, payload: %u-%u (%u bytes) (TSN: %u)",
799
0
                    f->frame_num, counter, counter+f->length-1, f->length,
800
0
                    f->tsn);
801
0
            counter += f->length;
802
0
            f = f->next;
803
0
        }
804
0
        return new_tvb;
805
0
    } else {
806
0
        new_tvb = tvb_new_subset_length(tvb, offset, maclength);
807
0
        switch (type) {
808
0
            case MAC_IS_HEAD:
809
0
                proto_tree_add_expert_remaining(tree, pinfo, &ei_mac_macis_sdu_first, new_tvb, 0);
810
0
                break;
811
0
            case MAC_IS_MIDDLE:
812
0
                proto_tree_add_expert_remaining(tree, pinfo, &ei_mac_macis_sdu_middle, new_tvb, 0);
813
0
                break;
814
0
            case MAC_IS_TAIL:
815
0
                proto_tree_add_expert_remaining(tree, pinfo, &ei_mac_macis_sdu_last, new_tvb, 0);
816
0
                break;
817
0
        }
818
0
        proto_tree_add_uint(tree, hf_mac_is_reasmin, new_tvb, 0, 0, sdu->frame_num);
819
0
        return NULL; /* No data here. */
820
0
    }
821
0
}
822
823
/*
824
 * If return value > 0 then tsn is changed to be tsn of head.
825
 * @return return length of sequence tsn-1 to head.
826
 */
827
static unsigned find_head(body_parts ** body_parts_array, uint16_t * tsn)
828
0
{
829
0
    unsigned length = 0;
830
0
    *tsn = (*tsn==0)? (uint16_t)(MAX_TSN-1) : (*tsn)-1;
831
0
    for (; body_parts_array[*tsn]->middle != NULL; *tsn = (*tsn==0)?(uint16_t)(MAX_TSN-1):(*tsn)-1)
832
0
        length += body_parts_array[*tsn]->middle->length;
833
0
    if (body_parts_array[*tsn]->head != NULL)
834
0
        return length+body_parts_array[*tsn]->head->length;
835
0
    return 0;
836
0
}
837
838
/*
839
 * @return return length of sequence tsn+1 to tail.
840
 */
841
static unsigned find_tail(body_parts ** body_parts_array, uint16_t tsn)
842
0
{
843
0
    unsigned length = 0;
844
0
    for (tsn = (tsn+1)%MAX_TSN; body_parts_array[tsn]->middle != NULL; tsn = (tsn+1)%MAX_TSN)
845
0
        length += body_parts_array[tsn]->middle->length;
846
0
    if (body_parts_array[tsn]->tail != NULL)
847
0
        return length+body_parts_array[tsn]->tail->length;
848
0
    return 0;
849
0
}
850
851
/*
852
 * @param ch Channel for which body parts are to be fetched.
853
 * @return Array of body_part* for channel 'ch'.
854
 */
855
static body_parts ** get_body_parts(mac_is_channel * ch)
856
0
{
857
0
    body_parts ** bpa = (body_parts **)g_hash_table_lookup(mac_is_fragments, ch);
858
    /* If there was no body_part* array for this channel, create one. */
859
0
    if (bpa == NULL) {
860
0
        mac_is_channel * channel;
861
0
        bpa = wmem_alloc_array(wmem_file_scope(), body_parts*, MAX_TSN); /* Create new body_parts-pointer array */
862
0
        for (size_t i = 0; i < MAX_TSN; i++) {
863
0
            bpa[i] = wmem_new0(wmem_file_scope(), body_parts); /* Fill it with body_parts. */
864
0
        }
865
0
        channel = wmem_new(wmem_file_scope(), mac_is_channel); /* Alloc new channel for use in hash table. */
866
0
        *channel = *ch;
867
0
        g_hash_table_insert(mac_is_fragments, channel, bpa);
868
0
    }
869
0
    return bpa;
870
0
}
871
872
static tvbuff_t * mac_is_add_fragment(tvbuff_t * tvb _U_, packet_info *pinfo, proto_tree * tree _U_, uint8_t lchid, unsigned ueid, int offset, uint8_t ss, uint16_t tsn, int sdu_no, uint8_t no_sdus, uint16_t maclength)
873
0
{
874
0
    mac_is_channel ch; /* Channel for looking up in hash tables. */
875
0
    ch.lchid = lchid;
876
0
    ch.ueid = ueid;
877
878
    /* If in first scan-through. */
879
0
    if (!PINFO_FD_VISITED(pinfo)) {
880
        /* Get body parts array for this channel. */
881
0
        body_parts ** body_parts_array = get_body_parts(&ch);
882
        /* Middle segment */
883
0
        if (no_sdus == 1 && ss == 3) {
884
0
            unsigned head_length, tail_length;
885
0
            init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_MIDDLE);
886
0
            tail_length = find_tail(body_parts_array, tsn);
887
0
            if (tail_length > 0) {
888
0
                head_length = find_head(body_parts_array, &tsn);
889
0
                if (head_length > 0) {
890
                    /* tsn is now TSN of head */
891
0
                    return reassemble(tvb, body_parts_array, tsn, tail_length+head_length+maclength, &ch, pinfo->num);
892
0
                }
893
0
            }
894
            /* XXX: haven't confirmed if case when middle segment comes last
895
             * actually works or not. */
896
0
        }
897
        /* If first SDU is last segment of previous. A tail. */
898
0
        else if (sdu_no == 0 && (ss & 1) == 1) {
899
0
            unsigned length = maclength;
900
0
            init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_TAIL);
901
0
            length += find_head(body_parts_array, &tsn);
902
0
            if (length > maclength) {
903
                /* tsn is now TSN of head */
904
0
                return reassemble(tvb, body_parts_array, tsn, length, &ch, pinfo->num);
905
0
            }
906
0
        }
907
        /* If last SDU is first segment of next. A head. */
908
0
        else if (sdu_no == no_sdus-1 && (ss & 2) == 2) {
909
0
            unsigned length = maclength;
910
0
            init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_HEAD);
911
0
            length += find_tail(body_parts_array, tsn);
912
0
            if (length > maclength) {
913
0
                return reassemble(tvb, body_parts_array, tsn, length, &ch, pinfo->num);
914
0
            }
915
        /* If our SDU is not fragmented. */
916
0
        } else {
917
0
            DISSECTOR_ASSERT((sdu_no == 0) ? (ss&1) == 0 : ((sdu_no == no_sdus-1) ? (ss&2) == 0 : true));
918
0
            return tvb_new_subset_length(tvb, offset, maclength);
919
0
        }
920
    /* If clicking on a packet. */
921
0
    } else {
922
0
        tvbuff_t * new_tvb = NULL;
923
        /* Middle segment */
924
0
        if (no_sdus == 1 && ss == 3) {
925
0
            mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_MIDDLE, &ch);
926
0
            if (sdu) {
927
0
                return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_MIDDLE);
928
0
            }
929
0
        }
930
        /* If first SDU is last segment of previous. A tail. */
931
0
        else if (sdu_no == 0 && (ss & 1) == 1) {
932
0
            mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_TAIL, &ch);
933
0
            if (sdu) {
934
0
                return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_TAIL);
935
0
            }
936
0
        }
937
        /* If last SDU is first segment of next. A head. */
938
0
        else if (sdu_no == no_sdus-1 && (ss & 2) == 2) {
939
0
            mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_HEAD, &ch);
940
0
            if (sdu) {
941
0
                return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_HEAD);
942
0
            }
943
0
        } else {
944
0
            new_tvb = tvb_new_subset_length(tvb, offset, maclength);
945
0
            proto_tree_add_expert_remaining(tree, pinfo, &ei_mac_macis_sdu_complete, new_tvb, 0);
946
0
            proto_tree_add_item(tree, hf_mac_edch_type2_sdu_data, new_tvb, 0, -1, ENC_NA);
947
0
            return new_tvb;
948
0
        }
949
0
    }
950
0
    return NULL;
951
0
}
952
953
static void ss_interpretation(tvbuff_t * tvb, proto_tree * tree, uint8_t ss, unsigned number_of_mac_is_sdus, unsigned offset)
954
0
{
955
0
    switch (ss) {
956
0
        case 0:
957
0
            if (number_of_mac_is_sdus > 1) {
958
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
959
0
                    "The first MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The last MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU.");
960
0
            } else {
961
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
962
0
                    "The MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU.");
963
0
            }
964
0
            break;
965
0
        case 1:
966
0
            if (number_of_mac_is_sdus > 1) {
967
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
968
0
                    "The last MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The first MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU.");
969
0
            } else {
970
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
971
0
                    "The MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU.");
972
0
            }
973
0
            break;
974
0
        case 2:
975
0
            if (number_of_mac_is_sdus > 1) {
976
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
977
0
                    "The first MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The last MAC-is SDU of the MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
978
0
            } else {
979
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
980
0
                    "The MAC-is SDU of the MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
981
0
            }
982
0
            break;
983
0
        case 3:
984
0
            if (number_of_mac_is_sdus > 1) {
985
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
986
0
                    "The first MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU and the last MAC-is SDU of MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
987
0
            } else {
988
0
                proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
989
0
                    "The MAC-is SDU is a middle segment of a MAC-d PDU or MAC-c PDU.");
990
0
            }
991
0
            break;
992
0
    }
993
0
}
994
995
static void call_rlc(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, proto_item * ti, uint8_t lchid, void *data)
996
0
{
997
0
    switch (lchId_type_table[lchid]) {
998
0
        case MAC_CONTENT_DCCH:
999
0
            proto_item_append_text(ti, " (DCCH)");
1000
0
            call_dissector_with_data(rlc_dcch_handle, tvb, pinfo, tree, data);
1001
0
            break;
1002
0
        case MAC_CONTENT_PS_DTCH:
1003
0
            proto_item_append_text(ti, " (PS DTCH)");
1004
0
            call_dissector_with_data(rlc_ps_dtch_handle, tvb, pinfo, tree, data);
1005
0
            break;
1006
0
        case MAC_CONTENT_CS_DTCH:
1007
0
            proto_item_append_text(ti, " (CS DTCH)");
1008
            /* TODO */
1009
0
            break;
1010
0
        default:
1011
0
            proto_item_append_text(ti, " (Unknown EDCH Content)");
1012
0
            expert_add_info_format(pinfo, ti, &ei_mac_unknown_content, "Unknown EDCH Content");
1013
0
            break;
1014
0
    }
1015
0
}
1016
1017
/*
1018
 * Dissect a MAC-is PDU.
1019
 */
1020
static int dissect_mac_fdd_edch_type2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1021
0
{
1022
0
    unsigned sdu_no, subframe_bytes = 0, offset = 0;
1023
0
    uint8_t ss;
1024
0
    uint16_t tsn;
1025
0
    proto_item *pi, *temp;
1026
0
    proto_tree *macis_pdu_tree, *macis_sdu_tree;
1027
0
    umts_mac_is_info * mac_is_info = (umts_mac_is_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1028
0
    rlc_info * rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1029
0
    struct fp_info *p_fp_info = (struct fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1030
1031
0
    DISSECTOR_ASSERT(mac_is_info != NULL && rlcinf != NULL && p_fp_info != NULL);
1032
1033
0
    pi = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1034
0
    macis_pdu_tree = proto_item_add_subtree(pi, ett_mac_edch_type2);
1035
1036
    /* SS */
1037
0
    ss = (tvb_get_uint8(tvb, offset) & 0xc0) >> 6;
1038
0
    proto_tree_add_item(macis_pdu_tree, hf_mac_edch_type2_ss, tvb, offset, 1, ENC_BIG_ENDIAN);
1039
1040
0
    ss_interpretation(tvb, macis_pdu_tree, ss, mac_is_info->number_of_mac_is_sdus, offset);
1041
1042
    /* TSN */
1043
0
    tsn = tvb_get_bits8(tvb, offset*8+2, mac_tsn_size);
1044
0
    proto_tree_add_bits_item(macis_pdu_tree, hf_mac_edch_type2_tsn, tvb, offset*8+2, mac_tsn_size, ENC_BIG_ENDIAN);
1045
1046
0
    offset += (2+mac_tsn_size)/8;
1047
1048
    /* MAC-is SDUs (i.e. MACd PDUs) */
1049
0
    for (sdu_no=0; sdu_no < mac_is_info->number_of_mac_is_sdus; sdu_no++) {
1050
0
        proto_item *ti;
1051
0
        tvbuff_t * asm_tvb;
1052
0
        uint8_t lchid = mac_is_info->lchid[sdu_no]+1;
1053
0
        unsigned sdulength = mac_is_info->sdulength[sdu_no];
1054
1055
0
        ti = proto_tree_add_item(tree, hf_mac_edch_type2_sdu, tvb, offset, sdulength, ENC_NA);
1056
0
        macis_sdu_tree = proto_item_add_subtree(ti, ett_mac_edch_type2_sdu);
1057
0
        proto_item_append_text(ti, " (Logical channel=%u, Len=%u)", lchid, sdulength);
1058
0
        temp = proto_tree_add_uint(ti, hf_mac_lch_id, tvb, 0, 0, lchid);
1059
0
        proto_item_set_generated(temp);
1060
        /*Set up information needed for MAC and lower layers*/
1061
0
        rlcinf->mode[sdu_no] = lchId_rlc_map[lchid]; /* Set RLC mode by lchid to RLC_MODE map in nbap.h */
1062
0
        rlcinf->ueid[sdu_no] = p_fp_info->com_context_id;
1063
0
        rlcinf->rbid[sdu_no] = lchid;
1064
0
        rlcinf->li_size[sdu_no] = RLC_LI_7BITS;
1065
0
        rlcinf->ciphered[sdu_no] = false;
1066
0
        rlcinf->deciphered[sdu_no] = false;
1067
1068
0
        asm_tvb = mac_is_add_fragment(tvb, pinfo, macis_sdu_tree, lchid, p_fp_info->com_context_id, offset, ss, tsn, sdu_no, mac_is_info->number_of_mac_is_sdus, sdulength);
1069
0
        if (asm_tvb != NULL) {
1070
0
            call_rlc(asm_tvb, pinfo, tree, ti, lchid, data);
1071
0
        }
1072
1073
0
        offset += sdulength;
1074
0
        subframe_bytes += sdulength;
1075
0
    }
1076
1077
0
    proto_item_append_text(pi, "-is PDU (SS=%u, TSN=%u, %u bytes in %u SDU fragments)",
1078
0
                           ss, tsn, subframe_bytes, mac_is_info->number_of_mac_is_sdus);
1079
1080
0
    proto_item_set_len(pi, 1+subframe_bytes);
1081
    /*total_bytes += subframe_bytes;*/
1082
0
    return tvb_captured_length(tvb);
1083
0
}
1084
1085
static int dissect_mac_fdd_edch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1086
0
{
1087
0
    proto_tree    *edch_tree = NULL;
1088
0
    proto_item    *channel_type;
1089
0
    umts_mac_info *macinf;
1090
0
    fp_info       *fpinf;
1091
0
    uint16_t       pos;
1092
0
    proto_item    *ti        = NULL;
1093
1094
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1095
1096
0
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1097
0
    edch_tree = proto_item_add_subtree(ti, ett_mac_edch);
1098
1099
0
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1100
1101
0
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1102
0
    if (!macinf|| !fpinf) {
1103
0
        proto_tree_add_expert_remaining(edch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
1104
0
        return 1;
1105
0
    }
1106
1107
0
    pos = fpinf->cur_tb;
1108
1109
0
    switch (macinf->content[pos]) {
1110
0
        case MAC_CONTENT_DCCH:
1111
0
            proto_item_append_text(ti, " (DCCH)");
1112
1113
            /*Show the logical channel id*/
1114
0
            channel_type = proto_tree_add_uint(edch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1115
0
            proto_item_set_generated(channel_type);
1116
1117
0
            channel_type = proto_tree_add_uint(edch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1118
0
            proto_item_set_generated(channel_type);
1119
1120
1121
0
            call_dissector_with_data(rlc_dcch_handle, tvb, pinfo, tree, data);
1122
0
            break;
1123
0
        case MAC_CONTENT_PS_DTCH:
1124
0
            proto_item_append_text(ti, " (PS DTCH)");
1125
1126
            /*Show the logical channel id*/
1127
0
            channel_type = proto_tree_add_uint(edch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1128
0
            proto_item_set_generated(channel_type);
1129
1130
0
            channel_type = proto_tree_add_uint(edch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
1131
0
            proto_item_set_generated(channel_type);
1132
1133
0
            call_dissector_with_data(rlc_ps_dtch_handle, tvb, pinfo, tree, data);
1134
0
            break;
1135
0
        case MAC_CONTENT_CS_DTCH:
1136
0
            proto_item_append_text(ti, " (CS DTCH)");
1137
            /* TODO */
1138
0
            break;
1139
0
        default:
1140
0
            proto_item_append_text(ti, " (Unknown EDCH Content)");
1141
0
            expert_add_info_format(pinfo, ti, &ei_mac_unknown_content, "Unknown EDCH Content");
1142
0
            break;
1143
0
    }
1144
0
    return tvb_captured_length(tvb);
1145
0
}
1146
/**
1147
* Dissect hsdsch_common channel.
1148
*
1149
* This will dissect hsdsch common channels, we handle this separately
1150
* since we might have to deal with MAC-ehs and or MAC-c headers
1151
* (in the MAC PDU).
1152
*
1153
* @param tvb
1154
* @param pinfo
1155
* @param tree
1156
* @return Void.
1157
*/
1158
#if 0
1159
static void dissect_mac_fdd_hsdsch_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1160
{
1161
    proto_tree    *hsdsch_tree = NULL;
1162
    /*proto_item    *channel_type;
1163
    */
1164
    fp_info       *fpinf;
1165
    umts_mac_info *macinf;
1166
    uint16_t       pos;
1167
  /*  uint8_t        bitoffs=0;
1168
    tvbuff_t      *next_tvb;
1169
    */
1170
    proto_item    *ti  = NULL;
1171
1172
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1173
1174
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1175
    hsdsch_tree = proto_item_add_subtree(ti, ett_mac_hsdsch);
1176
1177
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1178
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac);
1179
1180
    if (!macinf) {
1181
        proto_tree_add_expert_remaining(hsdsch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
1182
        return;
1183
    }
1184
    pos = fpinf->cur_tb;
1185
    switch(macinf->content[pos]){
1186
        /*In this case we don't have a MAC-c header 9.2.1.4*/
1187
1188
#if 0
1189
        case MAC_CONTENT_CCCH:
1190
1191
            break;
1192
        case MAC_CONTENT_PCCH:
1193
1194
            break;
1195
1196
        case MAC_CONTENT_BCCH:
1197
1198
            break;
1199
#endif
1200
        default:
1201
1202
            proto_item_append_text(ti, " (Unknown HSDSCH-Common Content)");
1203
            expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown HSDSCH-Common Content");
1204
            break;
1205
    }
1206
1207
}
1208
#endif
1209
/* to avoid unnecessary re-alignment, the 4 bit padding prepended to the HSDSCH in FP type 1
1210
 * are handled in the MAC layer
1211
 * If the C/T field is present, 'bitoffs' will be 8 (4 bit padding and 4 bit C/T) and
1212
 * no re-alignment is necessary
1213
 * If no C/T is present, the whole payload will be left-shifted by 4 bit
1214
 */
1215
static int dissect_mac_fdd_hsdsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1216
0
{
1217
0
    proto_tree    *hsdsch_tree = NULL;
1218
0
    proto_item    *channel_type;
1219
0
    fp_info       *fpinf;
1220
0
    umts_mac_info *macinf;
1221
0
    uint16_t       pos;
1222
0
    uint8_t        bitoffs=0;
1223
0
    tvbuff_t      *next_tvb;
1224
0
    proto_item    *ti          = NULL;
1225
0
    rlc_info * rlcinf;
1226
1227
    /*struct rrc_info  *rrcinf = NULL;
1228
    */
1229
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1230
1231
0
    ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1232
0
    hsdsch_tree = proto_item_add_subtree(ti, ett_mac_hsdsch);
1233
1234
0
    fpinf  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1235
0
    macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1236
1237
0
    pos = fpinf->cur_tb;
1238
0
    bitoffs = fpinf->hsdsch_entity == ehs ? 0 : 4;   /*No MAC-d header for type 2*/
1239
1240
0
    if (!macinf) {
1241
0
        proto_tree_add_expert_remaining(hsdsch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0);
1242
0
        return 1;
1243
0
    }
1244
0
    if (macinf->ctmux[pos]) {   /*The 4'st bits are padding*/
1245
0
        proto_tree_add_bits_item(hsdsch_tree, hf_mac_ct, tvb, bitoffs, 4, ENC_BIG_ENDIAN);
1246
1247
        /*Sets the proper lchid, for later layers.*/
1248
0
        macinf->lchid[pos] = tvb_get_bits8(tvb,bitoffs,4)+1;
1249
0
        macinf->fake_chid[pos] = false;
1250
0
        macinf->content[pos] = lchId_type_table[macinf->lchid[pos]];    /*Lookup MAC content*/
1251
1252
0
        rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1253
0
        rlcinf->rbid[pos] = macinf->lchid[pos];
1254
0
        rlcinf->mode[pos] =  lchId_rlc_map[macinf->lchid[pos]]; /*Look up RLC mode*/
1255
0
        bitoffs += 4;
1256
0
    }
1257
1258
0
    if ((bitoffs % 8) == 0) {
1259
0
        next_tvb = tvb_new_subset_remaining(tvb, bitoffs/8);
1260
0
    } else {
1261
0
        next_tvb = tvb_new_octet_aligned(tvb, bitoffs, macinf->pdu_len);    /*Get rid of possible padding in at the end?*/
1262
0
        add_new_data_source(pinfo, next_tvb, "Octet-Aligned HSDSCH Data");
1263
0
    }
1264
1265
0
    switch (macinf->content[pos]) {
1266
0
        case MAC_CONTENT_CCCH:
1267
0
            proto_item_append_text(ti, " (CCCH)");
1268
            /*Set the logical channel id if it exists */
1269
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1270
0
            proto_item_set_generated(channel_type);
1271
0
            if(macinf->lchid[pos] != 255){
1272
0
                if(macinf->fake_chid[pos]){
1273
0
                    expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1274
0
                }
1275
0
            }else{
1276
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1277
0
            }
1278
            /*Set the type of channel*/
1279
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1280
0
            proto_item_set_generated(channel_type);
1281
1282
            /*Set the MACd-Flow ID*/
1283
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1284
0
            proto_item_set_generated(channel_type);
1285
0
            call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
1286
0
            break;
1287
0
        case MAC_CONTENT_DCCH:
1288
0
            proto_item_append_text(ti, " (DCCH)");
1289
          /*  channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel_hsdsch, tvb, 0, 0, MAC_DCCH);
1290
            proto_item_set_generated(channel_type)*/
1291
            /*Set the logical channel id if it exists */
1292
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1293
0
            proto_item_set_generated(channel_type);
1294
0
            if(macinf->lchid[pos] != 255){
1295
0
                if(macinf->fake_chid[pos]){
1296
0
                    expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1297
0
                }
1298
0
            }else{
1299
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1300
0
            }
1301
1302
            /*Set the type of channel*/
1303
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1304
1305
0
            proto_item_set_generated(channel_type);
1306
1307
            /*Set the MACd-Flow ID*/
1308
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1309
0
            proto_item_set_generated(channel_type);
1310
0
            call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
1311
0
            break;
1312
0
        case MAC_CONTENT_PS_DTCH:
1313
0
            proto_item_append_text(ti, " (PS DTCH)");
1314
1315
            /*Set the logical channel id if it exists */
1316
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1317
0
            proto_item_set_generated(channel_type);
1318
0
            if(macinf->lchid[pos] != 255){
1319
0
                if(macinf->fake_chid[pos]){
1320
0
                    expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1321
0
                }
1322
0
            }else{
1323
0
                expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1324
0
            }
1325
1326
            /*Sets the channel type*/
1327
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
1328
1329
0
            proto_item_set_generated(channel_type);
1330
1331
            /*Set the MACd-Flow ID*/
1332
0
            channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1333
0
            proto_item_set_generated(channel_type);
1334
1335
0
            call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
1336
0
            break;
1337
0
        case MAC_CONTENT_CS_DTCH:
1338
0
            proto_item_append_text(ti, " (CS DTCH)");
1339
0
            break;
1340
0
        default:
1341
0
            proto_item_append_text(ti, " (Unknown HSDSCH Content)");
1342
0
           expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown HSDSCH Content");
1343
0
    }
1344
0
    return tvb_captured_length(tvb);
1345
0
}
1346
1347
static void mac_is_sdus_hash_destroy(void *data)
1348
0
{
1349
0
    g_hash_table_destroy((GHashTable *)data);
1350
0
}
1351
1352
static void mac_init(void)
1353
16
{
1354
16
    mac_is_sdus = g_hash_table_new_full(mac_is_channel_hash, mac_is_channel_equal, NULL, mac_is_sdus_hash_destroy);
1355
16
    mac_is_fragments = g_hash_table_new_full(mac_is_channel_hash, mac_is_channel_equal, NULL, NULL);
1356
16
    if (global_mac_tsn_size == MAC_TSN_6BITS) {
1357
16
        MAX_TSN = 64;
1358
16
        mac_tsn_size = 6;
1359
16
    } else {
1360
0
        MAX_TSN = 16384;
1361
0
        mac_tsn_size = 14;
1362
0
    }
1363
16
}
1364
1365
static void mac_cleanup(void)
1366
0
{
1367
0
    g_hash_table_destroy(mac_is_sdus);
1368
0
    g_hash_table_destroy(mac_is_fragments);
1369
0
}
1370
1371
void
1372
proto_register_umts_mac(void)
1373
16
{
1374
16
    module_t *mac_module;
1375
16
    static int *ett[] = {
1376
16
        &ett_mac,
1377
16
        &ett_mac_fach,
1378
16
        &ett_mac_rach,
1379
16
        &ett_mac_dch,
1380
16
        &ett_mac_pch,
1381
16
        &ett_mac_edch,
1382
16
        &ett_mac_hsdsch,
1383
16
        &ett_mac_edch_type2,
1384
16
        &ett_mac_edch_type2_sdu,
1385
16
        &ett_mac_resolved_urnti
1386
16
    };
1387
    /** XX: Looks like some duplicate filter names ?? **/
1388
    /** XX: May be OK: See doc/README.developer       **/
1389
16
    static hf_register_info hf[] = {
1390
16
        { &hf_mac_rach_fdd_tctf,
1391
16
          { "Target Channel Type Field", "mac.tctf",
1392
16
            FT_UINT8, BASE_HEX, VALS(rach_fdd_tctf_vals), 0, NULL, HFILL }
1393
16
        },
1394
16
        { &hf_mac_fach_fdd_tctf,
1395
16
          { "Target Channel Type Field", "mac.tctf",
1396
16
            FT_UINT8, BASE_HEX, VALS(fach_fdd_tctf_vals), 0, NULL, HFILL }
1397
16
        },
1398
16
        { &hf_mac_ct,
1399
16
          { "C/T", "mac.ct",
1400
16
            FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
1401
16
        },
1402
16
        { &hf_mac_ueid_type,
1403
16
          { "UEID Type", "mac.ueid_type",
1404
16
            FT_UINT8, BASE_DEC, VALS(ueid_type_vals), 0, NULL, HFILL }
1405
16
        },
1406
16
        { &hf_mac_crnti,
1407
16
          { "C-RNTI (UEID)", "mac.ueid",
1408
16
            FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
1409
16
        },
1410
16
        { &hf_mac_urnti,
1411
16
          { "U-RNTI (UEID)", "mac.ueid",
1412
16
            FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
1413
16
        },
1414
16
        { &hf_mac_resolved_urnti,
1415
16
          { "Resolved U-RNTI", "mac.resolved_urnti",
1416
16
            FT_UINT32, BASE_HEX, NULL, 0x0,
1417
16
            "The U-RNTI of the UE which is using the C-RNTI seen in this frame",
1418
16
            HFILL }
1419
16
        },
1420
16
        { &hf_mac_crnti_urnti_match_frame,
1421
16
          { "C-RNTI Allocation Frame", "mac.crnti_urnti_match_frame",
1422
16
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1423
16
            "The frame number where the C-RNTI was allocated for the UE",
1424
16
            HFILL }
1425
16
        },
1426
16
        { &hf_mac_channel,
1427
16
          { "Logical Channel Type", "mac.logical_channel",
1428
16
            FT_UINT16, BASE_DEC, VALS(mac_logical_channel_vals), 0, NULL, HFILL }
1429
16
        },
1430
1431
#if 0
1432
         { &hf_mac_channel_str,
1433
          { "Logical Channel", "mac.logical_channel",
1434
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1435
        },
1436
#endif
1437
#if 0
1438
        { &hf_mac_channel_hsdsch,
1439
            { "MACd-FlowID", "mac.macd_flowid", FT_UINT16, BASE_DEC, NULL, 0x0,  NULL, HFILL }
1440
        },
1441
#endif
1442
16
        { &hf_mac_macdflowd_id,
1443
16
            { "MACd-FlowID", "mac.macd_flowid", FT_UINT16, BASE_DEC, NULL, 0x0,  NULL, HFILL }
1444
16
        },
1445
16
         { &hf_mac_lch_id,
1446
16
            { "Logical Channel ID", "mac.logical_channel_id", FT_UINT16, BASE_DEC, NULL, 0x0,  NULL, HFILL }
1447
16
        },
1448
16
        { &hf_mac_trch_id,
1449
16
            { "Transport Channel ID", "mac.transport_channel_id", FT_UINT16, BASE_DEC, NULL, 0x0,  NULL, HFILL }
1450
16
        },
1451
#if 0
1452
        { &hf_mac_edch_type2_descriptors,
1453
          { "MAC-is Descriptors",
1454
            "mac.edch.type2.descriptors", FT_STRING, BASE_NONE, NULL, 0x0,
1455
            NULL, HFILL
1456
          }
1457
        },
1458
#endif
1459
#if 0
1460
        { &hf_mac_edch_type2_lchid,
1461
          { "LCH-ID",
1462
            "mac.logical_channel_id", FT_UINT8, BASE_HEX, NULL, 0xf0,
1463
            NULL, HFILL
1464
          }
1465
        },
1466
#endif
1467
#if 0
1468
        { &hf_mac_edch_type2_length,
1469
          { "Length",
1470
            "mac.edch.type2.length", FT_UINT16, BASE_DEC, NULL, 0x0ffe,
1471
            NULL, HFILL
1472
          }
1473
        },
1474
#endif
1475
#if 0
1476
        { &hf_mac_edch_type2_flag,
1477
          { "Flag",
1478
            "mac.edch.type2.lchid", FT_UINT8, BASE_HEX, NULL, 0x01,
1479
            "Indicates if another entry follows", HFILL
1480
          }
1481
        },
1482
#endif
1483
16
        { &hf_mac_edch_type2_ss,
1484
16
          { "SS",
1485
            /* TODO: VALS */
1486
16
            "mac.edch.type2.ss", FT_UINT8, BASE_HEX, NULL, 0xc0,
1487
16
            "Segmentation Status", HFILL
1488
16
          }
1489
16
        },
1490
16
        { &hf_mac_edch_type2_ss_interpretation,
1491
16
          { "SS interpretation",
1492
16
            "mac.edch.type2.ss_interpretation", FT_UINT8, BASE_HEX, NULL, 0x0,
1493
16
            NULL, HFILL
1494
16
          }
1495
16
        },
1496
16
        { &hf_mac_edch_type2_tsn,
1497
16
          { "TSN",
1498
16
            "mac.edch.type2.tsn", FT_UINT16, BASE_DEC, NULL, 0,
1499
16
            "Transmission Sequence Number", HFILL
1500
16
          }
1501
16
        },
1502
16
        { &hf_mac_edch_type2_sdu,
1503
16
          { "MAC-is SDU",
1504
16
            "mac.edch.type2.sdu", FT_NONE, BASE_NONE, NULL, 0x0,
1505
16
            NULL, HFILL
1506
16
          }
1507
16
        },
1508
16
        { &hf_mac_edch_type2_sdu_data,
1509
16
          { "Data",
1510
16
            "mac.edch.type2.sdu.data", FT_BYTES, BASE_NONE, NULL, 0x0,
1511
16
            NULL, HFILL
1512
16
          }
1513
16
        },
1514
#if 0
1515
        { &hf_mac_edch_type2_subframe_header,
1516
          { "Subframe header",
1517
            "mac.edch.type2.subframeheader", FT_STRING, BASE_NONE, NULL, 0x0,
1518
            "EDCH Subframe header", HFILL
1519
          }
1520
        },
1521
#endif
1522
16
        { &hf_mac_is_reasmin,
1523
16
          { "Reassembled in frame", "mac.is.reasmin",
1524
16
            FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
1525
16
        },
1526
16
        { &hf_mac_is_fraglink,
1527
16
          { "Frame", "mac.is.fraglink",
1528
16
            FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
1529
16
        }
1530
16
    };
1531
1532
16
    static ei_register_info ei[] = {
1533
16
        { &ei_mac_per_frame_info_missing, { "mac.per_frame_info_missing", PI_MALFORMED, PI_ERROR, "Cannot dissect MAC frame because per-frame info is missing", EXPFILL }},
1534
16
        { &ei_mac_unknown_content, { "mac.unknown_content", PI_MALFORMED, PI_ERROR, "Unknown RACH DCCH/DTCH Content", EXPFILL }},
1535
16
        { &ei_mac_rach_tctf_unknown, { "mac.rach_tctf.unknown", PI_MALFORMED, PI_ERROR, "Unknown RACH TCTF", EXPFILL }},
1536
16
        { &ei_mac_cs_dtch_not_implemented, { "mac.cs_dtch.not_implemented", PI_DEBUG, PI_ERROR, "CS DTCH Is not implemented", EXPFILL }},
1537
16
        { &ei_mac_fach_content_type_unknown, { "mac.fach_content_type.unknown", PI_UNDECODED, PI_WARN, "Unimplemented FACH Content type!", EXPFILL }},
1538
16
        { &ei_mac_no_logical_channel, { "mac.no_logical_channel", PI_PROTOCOL, PI_WARN, "Frame is missing logical channel", EXPFILL }},
1539
16
        { &ei_mac_faked_logical_channel_id, { "mac.faked_logical_channel_id", PI_PROTOCOL, PI_WARN, "This is a faked logical channel id!", EXPFILL }},
1540
16
        { &ei_mac_macis_sdu_reassembled, { "mac.macis_sdu.reassembled", PI_REASSEMBLE, PI_CHAT, "Reassembled MAC-is SDU", EXPFILL }},
1541
16
        { &ei_mac_macis_sdu_first, { "mac.macis_sdu.first", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is the first segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1542
16
        { &ei_mac_macis_sdu_middle, { "mac.macis_sdu.middle", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is a middle segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1543
16
        { &ei_mac_macis_sdu_last, { "mac.macis_sdu.last", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is the last segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1544
16
        { &ei_mac_macis_sdu_complete, { "mac.macis_sdu.complete", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is a complete MAC-d PDU or MAC-c PDU", EXPFILL }},
1545
16
        { &ei_mac_reserved_c_t, { "mac.reserved_ct", PI_PROTOCOL, PI_WARN, "C/T has a reserved value, PDU is discarded", EXPFILL }}
1546
16
    };
1547
1548
16
    expert_module_t* expert_umts_mac;
1549
1550
16
    proto_umts_mac = proto_register_protocol("MAC", "MAC", "mac");
1551
16
    proto_register_field_array(proto_umts_mac, hf, array_length(hf));
1552
16
    proto_register_subtree_array(ett, array_length(ett));
1553
16
    expert_umts_mac = expert_register_protocol(proto_umts_mac);
1554
16
    expert_register_field_array(expert_umts_mac, ei, array_length(ei));
1555
1556
16
    register_dissector("mac.fdd.rach", dissect_mac_fdd_rach, proto_umts_mac);
1557
16
    register_dissector("mac.fdd.fach", dissect_mac_fdd_fach, proto_umts_mac);
1558
16
    register_dissector("mac.fdd.pch", dissect_mac_fdd_pch, proto_umts_mac);
1559
16
    register_dissector("mac.fdd.dch", dissect_mac_fdd_dch, proto_umts_mac);
1560
16
    register_dissector("mac.fdd.edch", dissect_mac_fdd_edch, proto_umts_mac);
1561
16
    register_dissector("mac.fdd.edch.type2", dissect_mac_fdd_edch_type2, proto_umts_mac);
1562
16
    register_dissector("mac.fdd.hsdsch", dissect_mac_fdd_hsdsch, proto_umts_mac);
1563
1564
16
    register_init_routine(mac_init);
1565
16
    register_cleanup_routine(mac_cleanup);
1566
1567
    /* Preferences */
1568
16
    mac_module = prefs_register_protocol(proto_umts_mac, NULL);
1569
16
    prefs_register_enum_preference(mac_module, "tsn_size", "TSN size",
1570
16
            "TSN size in bits, either 6 or 14 bit",
1571
16
            &global_mac_tsn_size, tsn_size_enumvals, false);
1572
16
}
1573
1574
void
1575
proto_reg_handoff_umts_mac(void)
1576
16
{
1577
16
    proto_fp = proto_get_id_by_filter_name("fp");
1578
16
    proto_umts_rlc = proto_get_id_by_filter_name("rlc");
1579
1580
16
    rlc_pcch_handle    = find_dissector_add_dependency("rlc.pcch", proto_umts_mac);
1581
16
    rlc_ccch_handle    = find_dissector_add_dependency("rlc.ccch", proto_umts_mac);
1582
16
    rlc_ctch_handle    = find_dissector_add_dependency("rlc.ctch", proto_umts_mac);
1583
16
    rlc_dcch_handle    = find_dissector_add_dependency("rlc.dcch", proto_umts_mac);
1584
16
    rlc_ps_dtch_handle = find_dissector_add_dependency("rlc.ps_dtch", proto_umts_mac);
1585
1586
16
    rrc_handle = find_dissector_add_dependency("rrc", proto_umts_mac);
1587
16
}
1588
1589
/*
1590
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1591
 *
1592
 * Local variables:
1593
 * c-basic-offset: 4
1594
 * tab-width: 8
1595
 * indent-tabs-mode: nil
1596
 * End:
1597
 *
1598
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1599
 * :indentSize=4:tabSize=8:noTabs=true:
1600
 */