Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-umts_rlc.c
Line
Count
Source
1
/* packet-umts_rlc.c
2
 * Routines for UMTS RLC (Radio Link Control) v9.3.0 disassembly
3
 * http://www.3gpp.org/ftp/Specs/archive/25_series/25.322/
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/conversation.h>
15
#include <epan/exceptions.h>
16
#include <epan/expert.h>
17
#include <epan/packet.h>
18
#include <epan/prefs.h>
19
#include <epan/proto_data.h>
20
#include <epan/show_exception.h>
21
#include <epan/tfs.h>
22
#include <wsutil/array.h>
23
24
#include <wiretap/wtap.h>
25
26
/*
27
 * Optional include, for KASUMI support,
28
 * see header file for more information.
29
 * */
30
31
#include "packet-umts_fp.h"
32
#include "packet-umts_rlc.h"
33
#include "packet-rrc.h"
34
35
/* TODO:
36
 * - distinguish between startpoints and endpoints?
37
 * - use sub_num in fragment identification?
38
 */
39
40
void proto_register_rlc(void);
41
void proto_reg_handoff_rlc(void);
42
43
static int proto_umts_rlc;
44
45
static int proto_fp;
46
47
/* Preference to perform reassembly */
48
static bool global_rlc_perform_reassemby = true;
49
50
/* Preference to expect RLC headers without payloads */
51
static bool global_rlc_headers_expected;
52
53
/* Preference to expect ONLY ciphered data */
54
static bool global_rlc_ciphered;
55
56
/* Preference to ignore ciphering state reported from RRC */
57
/* This is important for captures with deciphered traffic AND the original security RRC messages present*/
58
static bool global_ignore_rrc_ciphering_indication;
59
60
/* Preference to try deciphering */
61
static bool global_rlc_try_decipher;
62
63
#ifdef HAVE_UMTS_KASUMI
64
static const char *global_rlc_kasumi_key;
65
#endif
66
67
/* LI size preference */
68
0
#define RLC_LI_UPPERLAYER 255 /* LI-size comes from rlc_info struct rather than preference */
69
static int global_rlc_li_size = RLC_LI_UPPERLAYER;
70
71
static const enum_val_t li_size_enumvals[] = {
72
    {"7", "7 bits", RLC_LI_7BITS},
73
    {"15", "15 bits", RLC_LI_15BITS},
74
    {"per_upper_layer", "Let upper layers decide", RLC_LI_UPPERLAYER},
75
    {NULL, NULL, -1}};
76
77
/* fields */
78
static int hf_rlc_seq;
79
static int hf_rlc_ext;
80
static int hf_rlc_pad;
81
static int hf_rlc_reassembled_data;
82
static int hf_rlc_frags;
83
static int hf_rlc_frag;
84
static int hf_rlc_duplicate_of;
85
static int hf_rlc_reassembled_in;
86
static int hf_rlc_he;
87
static int hf_rlc_dc;
88
static int hf_rlc_p;
89
static int hf_rlc_li;
90
static int hf_rlc_li_value;
91
static int hf_rlc_li_ext;
92
static int hf_rlc_li_data;
93
static int hf_rlc_data;
94
static int hf_rlc_ciphered_data;
95
static int hf_rlc_ciphered_lis_data;
96
static int hf_rlc_ctrl_type;
97
static int hf_rlc_r1;
98
static int hf_rlc_rsn;
99
static int hf_rlc_hfni;
100
static int hf_rlc_sufi;
101
static int hf_rlc_sufi_type;
102
static int hf_rlc_sufi_lsn;
103
static int hf_rlc_sufi_wsn;
104
static int hf_rlc_sufi_sn;
105
static int hf_rlc_sufi_l;
106
static int hf_rlc_sufi_fsn;
107
static int hf_rlc_sufi_len;
108
static int hf_rlc_sufi_bitmap;
109
static int hf_rlc_sufi_cw;
110
static int hf_rlc_sufi_n;
111
static int hf_rlc_sufi_sn_ack;
112
static int hf_rlc_sufi_sn_mrw;
113
static int hf_rlc_sufi_poll_sn;
114
static int hf_rlc_header_only;
115
static int hf_rlc_channel;
116
static int hf_rlc_channel_rbid;
117
static int hf_rlc_channel_dir;
118
static int hf_rlc_channel_ueid;
119
static int hf_rlc_sequence_number;
120
static int hf_rlc_length;
121
static int hf_rlc_bitmap_string;
122
123
/* subtrees */
124
static int ett_rlc;
125
static int ett_rlc_frag;
126
static int ett_rlc_fragments;
127
static int ett_rlc_sdu;
128
static int ett_rlc_sufi;
129
static int ett_rlc_bitmap;
130
static int ett_rlc_rlist;
131
static int ett_rlc_channel;
132
133
static expert_field ei_rlc_li_reserved;
134
static expert_field ei_rlc_he;
135
static expert_field ei_rlc_li_incorrect_mal;
136
static expert_field ei_rlc_sufi_cw;
137
static expert_field ei_rlc_kasumi_implementation_missing;
138
static expert_field ei_rlc_reassembly_unknown_error;
139
static expert_field ei_rlc_reassembly_lingering_endpoint;
140
static expert_field ei_rlc_sufi_len;
141
static expert_field ei_rlc_reassembly_fail_unfinished_sequence;
142
static expert_field ei_rlc_reassembly_fail_flag_set;
143
static expert_field ei_rlc_sufi_type;
144
static expert_field ei_rlc_reserved_bits_not_zero;
145
static expert_field ei_rlc_ctrl_type;
146
static expert_field ei_rlc_li_incorrect_warn;
147
static expert_field ei_rlc_li_too_many;
148
static expert_field ei_rlc_header_only;
149
static expert_field ei_rlc_ciphered_data;
150
static expert_field ei_rlc_no_per_frame_data;
151
static expert_field ei_rlc_incomplete_sequence;
152
static expert_field ei_rlc_unknown_udp_framing_tag;
153
static expert_field ei_rlc_missing_udp_framing_tag;
154
155
static dissector_handle_t ip_handle;
156
static dissector_handle_t rrc_handle;
157
static dissector_handle_t bmc_handle;
158
159
enum rlc_channel_type {
160
    RLC_PCCH,
161
    RLC_BCCH,
162
    RLC_UL_CCCH,
163
    RLC_DL_CCCH,
164
    RLC_UL_DCCH,
165
    RLC_DL_DCCH,
166
    RLC_PS_DTCH,
167
    RLC_DL_CTCH,
168
    RLC_UNKNOWN_CH
169
};
170
171
static const value_string rlc_dir_vals[] = {
172
    { P2P_DIR_UL, "Uplink" },
173
    { P2P_DIR_DL, "Downlink" },
174
    { 0, NULL }
175
};
176
177
static const true_false_string rlc_header_only_val = {
178
    "RLC PDU header only", "RLC PDU header and body present"
179
};
180
181
static const true_false_string rlc_ext_val = {
182
    "Next field is Length Indicator and E Bit", "Next field is data, piggybacked STATUS PDU or padding"
183
};
184
185
static const true_false_string rlc_dc_val = {
186
    "Data", "Control"
187
};
188
189
static const true_false_string rlc_p_val = {
190
    "Request a status report", "Status report not requested"
191
};
192
193
static const value_string rlc_he_vals[] = {
194
    { 0, "The succeeding octet contains data" },
195
    { 1, "The succeeding octet contains a length indicator and E bit" },
196
    { 2, "The succeeding octet contains data and the last octet of the PDU is the last octet of an SDU" },
197
    { 0, NULL }
198
};
199
200
0
#define RLC_STATUS      0x0
201
0
#define RLC_RESET       0x1
202
0
#define RLC_RESET_ACK   0x2
203
static const value_string rlc_ctrl_vals[] = {
204
    { RLC_STATUS,       "Status" },
205
    { RLC_RESET,        "Reset" },
206
    { RLC_RESET_ACK,    "Reset Ack" },
207
    { 0, NULL }
208
};
209
210
0
#define RLC_SUFI_NOMORE     0x0
211
0
#define RLC_SUFI_WINDOW     0x1
212
0
#define RLC_SUFI_ACK        0x2
213
0
#define RLC_SUFI_LIST       0x3
214
0
#define RLC_SUFI_BITMAP     0x4
215
0
#define RLC_SUFI_RLIST      0x5
216
0
#define RLC_SUFI_MRW        0x6
217
0
#define RLC_SUFI_MRW_ACK    0x7
218
0
#define RLC_SUFI_POLL       0x8
219
static const value_string rlc_sufi_vals[] = {
220
    { RLC_SUFI_NOMORE,  "No more data" },
221
    { RLC_SUFI_WINDOW,  "Window size" },
222
    { RLC_SUFI_ACK,     "Acknowledgement" },
223
    { RLC_SUFI_LIST,    "List" },
224
    { RLC_SUFI_BITMAP,  "Bitmap" },
225
    { RLC_SUFI_RLIST,   "Relative list" },
226
    { RLC_SUFI_MRW,     "Move receiving window" },
227
    { RLC_SUFI_MRW_ACK, "Move receiving window acknowledgement" },
228
    { RLC_SUFI_POLL,    "Poll" },
229
    { 0, NULL }
230
};
231
232
/* reassembly related data */
233
static GHashTable *fragment_table; /* table of not yet assembled fragments */
234
static GHashTable *endpoints; /* List of SDU-endpoints */
235
static GHashTable *reassembled_table; /* maps fragment -> complete sdu */
236
static GHashTable *sequence_table; /* channel -> seq */
237
static GHashTable *duplicate_table; /* duplicates */
238
239
/* identify an RLC channel, using one of two options:
240
 *  - via Radio Bearer ID and unique UE ID
241
 *  - via Radio Bearer ID and (VPI/VCI/CID) + Link ID
242
 */
243
struct rlc_channel {
244
    uint32_t         ueid;
245
    uint16_t         vpi;
246
    uint16_t         vci;
247
    uint8_t          cid;
248
    uint16_t         link;  /* link number */
249
    uint8_t          rbid;  /* radio bearer ID */
250
    uint8_t          dir;   /* direction */
251
    enum rlc_li_size li_size;
252
    enum rlc_mode    mode;
253
};
254
255
/* used for duplicate detection */
256
struct rlc_seq {
257
    nstime_t arrival;
258
    uint32_t frame_num;
259
    uint16_t seq;
260
    /* uint16_t oc; */     /* overflow counter, this is not used? */
261
};
262
263
struct rlc_seqlist {
264
    struct rlc_channel ch;
265
    GList *list;
266
    /* We will store one seqlist per channel so this is a good place to indicate
267
     *  whether or not this channel's reassembly has failed or not. */
268
    unsigned fail_packet; /* Equal to packet where fail flag was set or 0 otherwise. */
269
};
270
271
/* fragment representation */
272
struct rlc_frag {
273
    uint32_t            frame_num;
274
    struct rlc_channel  ch;
275
    uint16_t            seq;  /* RLC sequence number */
276
    uint16_t            li;   /* LI within current RLC frame */
277
    uint16_t            len;  /* length of fragment data */
278
    uint8_t            *data; /* store fragment data here */
279
280
    struct rlc_frag *next; /* next fragment */
281
};
282
283
struct rlc_sdu {
284
    tvbuff_t        *tvb;     /* contains reassembled tvb */
285
    uint16_t         len;     /* total length of reassembled SDU */
286
    uint16_t         fragcnt; /* number of fragments within this SDU */
287
    uint8_t         *data;    /* reassembled data buffer */
288
289
    struct rlc_frag *reassembled_in;
290
    struct rlc_frag *frags;   /* pointer to list of fragments */
291
    struct rlc_frag *last;    /* pointer to last fragment */
292
};
293
294
struct rlc_li {
295
    uint16_t    li;   /* original li */
296
    uint16_t    len;  /* length of this data fragment */
297
    uint8_t     ext;  /* extension bit value */
298
    proto_tree *tree; /* subtree for this LI */
299
};
300
301
/*** KASUMI related variables and structs ***/
302
typedef struct umts_kat_key{    /*Stores 128-bits KASUMI key*/
303
    uint64_t high;       /*64 MSB*/
304
    uint64_t low;    /*64 LSB*/
305
}kasumi_key;
306
307
308
/*Counter used as input for confidentiality algorithm*/
309
static uint32_t ps_counter[31][2] ;
310
static bool counter_init[31][2];
311
static uint32_t max_counter;
312
static GTree  * counter_map;    /*Saves the countervalues at first pass through, since they will be update*/
313
314
/* hashtable functions for fragment table
315
 * rlc_channel -> SDU
316
 */
317
static unsigned
318
rlc_channel_hash(const void *key)
319
0
{
320
0
    const struct rlc_channel *ch = (const struct rlc_channel *)key;
321
322
0
    if (ch->ueid)
323
0
        return ch->ueid | ch->rbid | ch->mode;
324
325
0
    return (ch->vci << 16) | (ch->link << 16) | ch->vpi | ch->vci;
326
0
}
327
328
static gboolean
329
rlc_channel_equal(const void *a, const void *b)
330
0
{
331
0
    const struct rlc_channel *x = (const struct rlc_channel *)a, *y = (const struct rlc_channel *)b;
332
333
0
    if (x->ueid || y->ueid)
334
0
        return x->ueid == y->ueid &&
335
0
            x->rbid == y->rbid &&
336
0
            x->mode == y->mode &&
337
0
            x->dir == y->dir ? true : false;
338
339
0
    return x->vpi == y->vpi &&
340
0
        x->vci == y->vci &&
341
0
        x->cid == y->cid &&
342
0
        x->rbid == y->rbid &&
343
0
        x->mode == y->mode &&
344
0
        x->dir == y->dir &&
345
0
        x->link == y->link ? true : false;
346
0
}
347
348
static int
349
rlc_channel_assign(struct rlc_channel *ch, enum rlc_mode mode, packet_info *pinfo, struct atm_phdr *atm)
350
0
{
351
0
    rlc_info        *rlcinf;
352
0
    fp_info         *fpinf;
353
354
0
    fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
355
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
356
0
    if (!fpinf || !rlcinf) return -1;
357
358
0
    if (rlcinf->ueid[fpinf->cur_tb]) {
359
0
        ch->ueid = rlcinf->ueid[fpinf->cur_tb];
360
0
        ch->vpi = ch->vci = ch->link = ch->cid = 0;
361
0
    } else {
362
0
        if (!atm) return -1;
363
0
        ch->ueid = 1;
364
0
        ch->vpi = atm->vpi;
365
0
        ch->vci = atm->vci;
366
0
        ch->cid = atm->aal2_cid;
367
0
        ch->link = pinfo->link_number;
368
0
    }
369
0
    ch->rbid = rlcinf->rbid[fpinf->cur_tb];
370
0
    ch->dir = pinfo->link_dir;
371
0
    ch->mode = mode;
372
0
    ch->li_size = rlcinf->li_size[fpinf->cur_tb];
373
374
0
    return 0;
375
0
}
376
377
static struct rlc_channel *
378
rlc_channel_create(enum rlc_mode mode, packet_info *pinfo, struct atm_phdr *atm)
379
0
{
380
0
    struct rlc_channel *ch;
381
0
    int rv;
382
383
0
    ch = g_new0(struct rlc_channel, 1);
384
0
    rv = rlc_channel_assign(ch, mode, pinfo, atm);
385
386
0
    if (rv != 0) {
387
        /* channel assignment failed */
388
0
        g_free(ch);
389
0
        ch = NULL;
390
0
        REPORT_DISSECTOR_BUG("Failed to assign channel");
391
0
    }
392
0
    return ch;
393
0
}
394
395
static void
396
rlc_channel_delete(void *data)
397
0
{
398
0
    g_free(data);
399
0
}
400
401
/* hashtable functions for reassembled table
402
 * fragment -> SDU
403
 */
404
static unsigned
405
rlc_frag_hash(const void *key)
406
0
{
407
0
    const struct rlc_frag *frag = (const struct rlc_frag *)key;
408
0
    return (frag->frame_num << 12) | frag->seq;
409
0
}
410
411
static gboolean
412
rlc_frag_equal(const void *a, const void *b)
413
0
{
414
0
    const struct rlc_frag *x = (const struct rlc_frag *)a;
415
0
    const struct rlc_frag *y = (const struct rlc_frag *)b;
416
417
0
    return rlc_channel_equal(&x->ch, &y->ch) &&
418
0
        x->seq == y->seq &&
419
0
        x->frame_num == y->frame_num &&
420
0
        x->li == y->li ? true : false;
421
0
}
422
423
static struct rlc_sdu *
424
rlc_sdu_create(void)
425
0
{
426
0
    struct rlc_sdu *sdu;
427
428
0
    sdu = wmem_new0(wmem_file_scope(), struct rlc_sdu);
429
0
    return sdu;
430
0
}
431
432
static void
433
rlc_frag_delete(void *data)
434
0
{
435
0
    struct rlc_frag *frag = (struct rlc_frag *)data;
436
437
0
    if (frag->data) {
438
0
        wmem_free(wmem_file_scope(), frag->data);
439
0
        frag->data = NULL;
440
0
    }
441
0
}
442
443
static void
444
rlc_sdu_frags_delete(void *data)
445
0
{
446
0
    struct rlc_sdu  *sdu = (struct rlc_sdu *)data;
447
0
    struct rlc_frag *frag;
448
449
0
    frag = sdu->frags;
450
0
    while (frag) {
451
0
        if (frag->data) {
452
0
            wmem_free(wmem_file_scope(), frag->data);
453
0
        }
454
0
        frag->data = NULL;
455
0
        frag = frag->next;
456
0
    }
457
0
}
458
459
static int
460
rlc_frag_assign(struct rlc_frag *frag, enum rlc_mode mode, packet_info *pinfo,
461
        uint16_t seq, uint16_t li, struct atm_phdr *atm)
462
0
{
463
0
    frag->frame_num = pinfo->num;
464
0
    frag->seq       = seq;
465
0
    frag->li        = li;
466
0
    frag->len       = 0;
467
0
    frag->data      = NULL;
468
0
    rlc_channel_assign(&frag->ch, mode, pinfo, atm);
469
470
0
    return 0;
471
0
}
472
473
static int
474
rlc_frag_assign_data(struct rlc_frag *frag, tvbuff_t *tvb,
475
             uint16_t offset, uint16_t length)
476
0
{
477
0
    frag->len  = length;
478
0
    frag->data = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, offset, length);
479
0
    return 0;
480
0
}
481
482
static struct rlc_frag *
483
rlc_frag_create(tvbuff_t *tvb, enum rlc_mode mode, packet_info *pinfo,
484
        uint16_t offset, uint16_t length, uint16_t seq, uint16_t li,
485
        struct atm_phdr *atm)
486
0
{
487
0
    struct rlc_frag *frag;
488
489
0
    frag = wmem_new0(wmem_file_scope(), struct rlc_frag);
490
0
    rlc_frag_assign(frag, mode, pinfo, seq, li, atm);
491
0
    rlc_frag_assign_data(frag, tvb, offset, length);
492
493
0
    return frag;
494
0
}
495
496
static int
497
rlc_cmp_seq(const void *a, const void *b)
498
0
{
499
0
    const struct rlc_seq *_a = (const struct rlc_seq *)a, *_b = (const struct rlc_seq *)b;
500
501
0
    return  _a->seq < _b->seq ? -1 :
502
0
            _a->seq > _b->seq ?  1 :
503
0
            0;
504
0
}
505
506
static int moduloCompare(uint16_t a, uint16_t b, uint16_t modulus)
507
0
{
508
0
    int ret;
509
0
    a = a % modulus;
510
0
    b = b % modulus;
511
512
0
    if( a <= b ){
513
0
        ret = a - b;
514
0
    } else {
515
0
        ret = a - (b + modulus);
516
0
    }
517
0
    if( ret == (1 - modulus) ){
518
0
        ret = 1;
519
0
    }
520
0
    return ret;
521
0
}
522
523
static uint16_t getChannelSNModulus(struct rlc_channel * ch_lookup)
524
0
{
525
0
    if( RLC_UM == ch_lookup->mode){ /*FIXME: This is a very heuristic way to determine SN bitwidth. */
526
0
        return 128;
527
0
    } else {
528
0
        return 4096;
529
0
    }
530
0
}
531
532
/* "Value destroy" function called each time an entry is removed
533
 *  from the sequence_table hash.
534
 * It frees the GList pointed to by the entry.
535
 */
536
static void
537
free_rlc_seqlist_data(void *data)
538
0
{
539
0
    struct rlc_seqlist *list = (struct rlc_seqlist *)data;
540
0
    if (list->list != NULL) {
541
0
        g_list_free(list->list);
542
0
        list->list = NULL;   /* for good measure */
543
0
    }
544
0
}
545
546
/** Utility functions used for various comparisons/cleanups in tree **/
547
static int
548
0
rlc_simple_key_cmp(const void *b_ptr, const void *a_ptr, void *ignore _U_){
549
0
    if( GPOINTER_TO_INT(a_ptr) > GPOINTER_TO_INT(b_ptr) ){
550
0
        return  -1;
551
0
    }
552
0
    return GPOINTER_TO_INT(a_ptr) < GPOINTER_TO_INT(b_ptr);
553
0
}
554
555
static void
556
fragment_table_init(void)
557
14
{
558
14
    int i;
559
14
    fragment_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, NULL);
560
14
    endpoints = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, free_rlc_seqlist_data);
561
14
    reassembled_table = g_hash_table_new_full(rlc_frag_hash, rlc_frag_equal,
562
14
        rlc_frag_delete, rlc_sdu_frags_delete);
563
14
    sequence_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal,
564
14
        NULL, free_rlc_seqlist_data);
565
14
    duplicate_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
566
567
    /*Reset and or clear deciphering variables*/
568
14
    counter_map = g_tree_new_full(rlc_simple_key_cmp,NULL,NULL,rlc_channel_delete);
569
448
    for(i = 0; i< 31; i++ ){
570
434
        ps_counter[i][0] = 0;
571
434
        ps_counter[i][1] = 0;
572
434
        counter_init[i][0] = 0;
573
434
        counter_init[i][1] = 0;
574
434
    }
575
14
    max_counter = 0;
576
14
}
577
578
static void
579
fragment_table_cleanup(void)
580
0
{
581
0
    g_tree_destroy(counter_map);
582
0
    g_hash_table_destroy(fragment_table);
583
0
    g_hash_table_destroy(endpoints);
584
0
    g_hash_table_destroy(reassembled_table);
585
0
    g_hash_table_destroy(sequence_table);
586
0
    g_hash_table_destroy(duplicate_table);
587
0
}
588
589
/* add the list of fragments for this sdu to 'tree' */
590
static void
591
tree_add_fragment_list(struct rlc_sdu *sdu, tvbuff_t *tvb,packet_info *pinfo, proto_tree *tree)
592
0
{
593
0
    proto_item      *ti;
594
0
    proto_tree      *frag_tree;
595
0
    uint16_t         offset;
596
0
    struct rlc_frag *sdufrag;
597
598
0
    ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, -1, ENC_NA);
599
0
    proto_item_set_generated(ti);
600
0
    frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
601
0
    proto_item_append_text(ti, " (%u bytes, %u fragments) ",
602
0
        sdu->len, sdu->fragcnt);
603
0
    sdufrag = sdu->frags;
604
0
    offset = 0;
605
0
    while (sdufrag) {
606
0
        if (sdufrag->len > 0) {
607
0
            proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
608
0
                sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: %u-%u (%u bytes) (Seq: %u)",
609
0
                sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
610
0
        } else {
611
0
            proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
612
0
                sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: none (0 bytes) (Seq: %u)",
613
0
                sdufrag->frame_num, sdufrag->seq);
614
0
        }
615
616
0
        mark_frame_as_depended_upon(pinfo->fd, sdufrag->frame_num);
617
618
0
        offset += sdufrag->len;
619
0
        sdufrag = sdufrag->next;
620
0
    }
621
0
    ti = proto_tree_add_item(ti, hf_rlc_reassembled_data, tvb, 0, -1, ENC_NA);
622
0
    proto_item_set_generated(ti);
623
0
}
624
625
/* add the list of fragments for this sdu to 'tree' */
626
static void
627
tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
628
0
{
629
0
    proto_item      *ti;
630
0
    proto_tree      *frag_tree;
631
0
    uint16_t         offset;
632
0
    struct rlc_frag *sdufrag;
633
634
0
    ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, ENC_NA);
635
0
    proto_item_set_generated(ti);
636
0
    frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
637
0
    proto_item_append_text(ti, " (%u bytes, %u fragments) ",
638
0
        sdu->len, sdu->fragcnt);
639
0
    sdufrag = sdu->frags;
640
0
    offset = 0;
641
0
    while (sdufrag) {
642
0
        proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0,
643
0
            0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
644
0
            sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
645
0
        offset += sdufrag->len;
646
0
        sdufrag = sdufrag->next;
647
0
    }
648
0
}
649
650
/* Add the same description to too the two given proto_items */
651
static void
652
add_description(proto_item *li_ti, proto_item *length_ti,
653
                const char *format, ...)  G_GNUC_PRINTF(3, 4);
654
static void
655
add_description(proto_item *li_ti, proto_item *length_ti,
656
                const char *format, ...)
657
0
{
658
0
#define MAX_INFO_BUFFER 256
659
0
    static char info_buffer[MAX_INFO_BUFFER];
660
661
0
    va_list ap;
662
663
0
    va_start(ap, format);
664
0
    vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
665
0
    va_end(ap);
666
667
0
    proto_item_append_text(li_ti, " (%s)", info_buffer);
668
0
    proto_item_append_text(length_ti, " (%s)", info_buffer);
669
0
}
670
671
/* add information for an LI to 'tree' */
672
static proto_tree *
673
tree_add_li(enum rlc_mode mode, struct rlc_li *li, uint8_t li_idx, uint32_t hdr_offs,
674
        bool li_is_on_2_bytes, tvbuff_t *tvb, proto_tree *tree)
675
0
{
676
0
    proto_item *root_ti, *ti;
677
0
    proto_tree *li_tree;
678
0
    uint32_t    li_offs;
679
0
    uint64_t    length;
680
681
0
    if (!tree) return NULL;
682
683
0
    if (li_is_on_2_bytes) {
684
0
        li_offs = hdr_offs + li_idx*2;
685
0
        root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 2, ENC_NA);
686
0
        li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
687
0
        ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 15, &length, ENC_BIG_ENDIAN);
688
689
0
        switch (li->li) {
690
0
            case 0x0000:
691
0
                add_description(root_ti, ti, "The previous RLC PDU was exactly filled with the last segment of an RLC SDU and there is no LI that indicates the end of the RLC SDU in the previous RLC PDU");
692
0
                break;
693
0
            case 0x7ffa:
694
0
                if (mode == RLC_UM) {
695
0
                    add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the second last octet in this RLC PDU is the last octet of the same RLC SDU. The remaining octet in the RLC PDU is ignored");
696
0
                } else {
697
0
                    add_description(root_ti, ti, "Reserved");
698
0
                }
699
0
                break;
700
0
            case 0x7ffb:
701
0
                add_description(root_ti, ti, "The second last octet in the previous RLC PDU is the last octet of an RLC SDU and there is no LI to indicate the end of SDU. The remaining octet in the previous RLC PDU is ignored");
702
0
                break;
703
0
            case 0x7ffc:
704
0
                if (mode == RLC_UM) {
705
0
                    add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
706
0
                } else {
707
0
                    add_description(root_ti, ti, "Reserved");
708
0
                }
709
0
                break;
710
0
            case 0x7ffd:
711
0
                if (mode == RLC_UM) {
712
0
                    add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the last octet in this RLC PDU is the last octet of the same RLC SDU");
713
0
                } else {
714
0
                    add_description(root_ti, ti, "Reserved");
715
0
                }
716
0
                break;
717
0
            case 0x7ffe:
718
0
                if (mode == RLC_UM) {
719
0
                    add_description(root_ti, ti, "The RLC PDU contains a segment of an SDU but neither the first octet nor the last octet of this SDU");
720
0
                } else {
721
0
                    add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
722
0
                }
723
0
                break;
724
0
            case 0x7fff:
725
0
                add_description(root_ti, ti, "The rest of the RLC PDU is padding");
726
0
                break;
727
728
0
            default:
729
0
                add_description(root_ti, ti, "length=%u", (uint16_t)length);
730
0
                break;
731
0
        }
732
0
        proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+15, 1, ENC_BIG_ENDIAN);
733
0
    } else {
734
0
        li_offs = hdr_offs + li_idx;
735
0
        root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 1, ENC_NA);
736
0
        li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
737
0
        ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 7, &length, ENC_BIG_ENDIAN);
738
0
        switch (li->li) {
739
0
            case 0x00:
740
0
                add_description(root_ti, ti, "The previous RLC PDU was exactly filled with the last segment of an RLC SDU and there is no LI that indicates the end of the RLC SDU in the previous RLC PDU");
741
0
                break;
742
0
            case 0x7c:
743
0
                if (mode == RLC_UM) {
744
0
                    add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
745
0
                } else {
746
0
                    add_description(root_ti, ti, "Reserved");
747
0
                }
748
0
                break;
749
0
            case 0x7d:
750
0
                if (mode == RLC_UM) {
751
0
                    add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the last octet in this RLC PDU is the last octet of the same RLC SDU");
752
0
                } else {
753
0
                    add_description(root_ti, ti, "Reserved");
754
0
                }
755
0
                break;
756
0
            case 0x7e:
757
0
                if (mode == RLC_UM) {
758
0
                    add_description(root_ti, ti, "The RLC PDU contains a segment of an SDU but neither the first octet nor the last octet of this SDU");
759
0
                } else {
760
0
                    add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
761
0
                }
762
0
                break;
763
0
            case 0x7f:
764
0
                add_description(root_ti, ti, "The rest of the RLC PDU is padding");
765
0
                break;
766
767
0
            default:
768
0
                add_description(root_ti, ti, "length=%u", (uint16_t)length);
769
0
                break;
770
0
        }
771
0
        proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+7, 1, ENC_BIG_ENDIAN);
772
0
    }
773
774
0
    if (li->len > 0) {
775
0
        if (li->li > tvb_reported_length_remaining(tvb, hdr_offs)) return li_tree;
776
0
        if (li->len > li->li) return li_tree;
777
0
        ti = proto_tree_add_item(li_tree, hf_rlc_li_data, tvb, hdr_offs + li->li - li->len, li->len, ENC_NA);
778
0
        proto_item_set_hidden(ti);
779
0
    }
780
781
0
    return li_tree;
782
0
}
783
784
/* add a fragment to an SDU */
785
static int
786
rlc_sdu_add_fragment(enum rlc_mode mode, struct rlc_sdu *sdu, struct rlc_frag *frag)
787
0
{
788
0
    struct rlc_frag *tmp;
789
790
0
    if (!sdu->frags) {
791
        /* insert as first element */
792
0
        sdu->frags = frag;
793
0
        sdu->last = frag;
794
0
        sdu->fragcnt++;
795
0
        sdu->len += frag->len;
796
0
        return 0;
797
0
    }
798
0
    switch (mode) {
799
0
        case RLC_UM:
800
            /* insert as last element */
801
0
            sdu->last->next = frag;
802
0
            frag->next = NULL;
803
0
            sdu->last = frag;
804
0
            sdu->len += frag->len;
805
0
            break;
806
0
        case RLC_AM:
807
            /* insert ordered */
808
0
            tmp = sdu->frags;
809
810
            /* If receiving exotic border line sequence, e.g. 4094, 4095, 0, 1 */
811
0
            if (frag->seq+2048 < tmp->seq) {
812
0
                while (tmp->next && frag->seq+2048 < tmp->seq)
813
0
                    tmp = tmp->next;
814
0
                if (tmp->next == NULL) {
815
0
                    tmp->next = frag;
816
0
                    sdu->last = frag;
817
0
                } else {
818
0
                    while (tmp->next && tmp->next->seq < frag->seq)
819
0
                        tmp = tmp->next;
820
0
                    frag->next = tmp->next;
821
0
                    tmp->next = frag;
822
0
                    if (frag->next == NULL) sdu->last = frag;
823
0
                }
824
0
            } else { /* Receiving ordinary sequence */
825
0
                if (frag->seq < tmp->seq) {
826
                    /* insert as first element */
827
0
                    frag->next = tmp;
828
0
                    sdu->frags = frag;
829
0
                } else {
830
0
                    while (tmp->next && tmp->next->seq < frag->seq)
831
0
                        tmp = tmp->next;
832
0
                    frag->next = tmp->next;
833
0
                    tmp->next = frag;
834
0
                    if (frag->next == NULL) sdu->last = frag;
835
0
                }
836
0
            }
837
0
            sdu->len += frag->len;
838
0
            break;
839
0
        default:
840
0
            return -2;
841
0
    }
842
0
    sdu->fragcnt++;
843
0
    return 0;
844
0
}
845
846
static void
847
reassemble_data(struct rlc_channel *ch, struct rlc_sdu *sdu, struct rlc_frag *frag)
848
0
{
849
0
    struct rlc_frag *temp;
850
0
    uint16_t         offs = 0;
851
852
0
    if (!sdu || !ch || !sdu->frags) return;
853
854
0
    if (sdu->data) return; /* already assembled */
855
856
0
    if (frag)
857
0
        sdu->reassembled_in = frag;
858
0
    else
859
0
        sdu->reassembled_in = sdu->last;
860
861
0
    sdu->data = (uint8_t *)wmem_alloc(wmem_file_scope(), sdu->len);
862
0
    temp = sdu->frags;
863
0
    while (temp && ((offs + temp->len) <= sdu->len)) {
864
0
        if (temp->data) {
865
0
            memcpy(sdu->data + offs, temp->data, temp->len);
866
0
            wmem_free(wmem_file_scope(), temp->data);
867
0
        }
868
0
        temp->data = NULL;
869
        /* mark this fragment in reassembled table */
870
0
        g_hash_table_insert(reassembled_table, temp, sdu);
871
872
0
        offs += temp->len;
873
0
        temp = temp->next;
874
0
    }
875
0
}
876
877
#define RLC_ADD_FRAGMENT_FAIL_PRINT 0
878
#define RLC_ADD_FRAGMENT_DEBUG_PRINT 0
879
#if RLC_ADD_FRAGMENT_DEBUG_PRINT
880
static void
881
printends(GList * list)
882
{
883
    if (list == NULL)
884
        return;
885
    g_print("-> length: %d\n[", g_list_length(list));
886
    while (list)
887
    {
888
        g_print("%d ", GPOINTER_TO_INT(list->data));
889
        list = list->next;
890
    }
891
    g_print("]\n");
892
}
893
#endif
894
895
static struct rlc_frag **
896
get_frags(packet_info * pinfo, struct rlc_channel * ch_lookup, struct atm_phdr *atm)
897
0
{
898
0
    void *value = NULL;
899
0
    struct rlc_frag ** frags = NULL;
900
    /* Look for already created frags table */
901
0
    if (g_hash_table_lookup_extended(fragment_table, ch_lookup, NULL, &value)) {
902
0
        frags = (struct rlc_frag **)value;
903
0
    } else if (pinfo != NULL) {
904
0
        struct rlc_channel *ch;
905
0
        ch = rlc_channel_create(ch_lookup->mode, pinfo, atm);
906
0
        frags = (struct rlc_frag **)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_frag *) * 4096);
907
0
        g_hash_table_insert(fragment_table, ch, frags);
908
0
    } else {
909
0
        return NULL;
910
0
    }
911
0
    return frags;
912
0
}
913
static struct rlc_seqlist *
914
get_endlist(packet_info * pinfo, struct rlc_channel * ch_lookup, struct atm_phdr *atm)
915
0
{
916
0
    void *value = NULL;
917
0
    struct rlc_seqlist * endlist = NULL;
918
    /* If there already exists a frag table for this channel use that one. */
919
0
    if (g_hash_table_lookup_extended(endpoints, ch_lookup, NULL, &value)) {
920
0
        endlist = (struct rlc_seqlist *)value;
921
0
    } else if (pinfo != NULL) { /* Else create a new one. */
922
0
        struct rlc_channel * ch;
923
924
0
        endlist = wmem_new(wmem_file_scope(), struct rlc_seqlist);
925
0
        ch = rlc_channel_create(ch_lookup->mode, pinfo, atm);
926
0
        endlist->fail_packet = 0;
927
0
        endlist->list = NULL;
928
0
        endlist->list = g_list_prepend(endlist->list, GINT_TO_POINTER(-1));
929
0
        g_hash_table_insert(endpoints, ch, endlist);
930
0
    } else {
931
0
        return NULL;
932
0
    }
933
0
    return endlist;
934
0
}
935
936
static void
937
reassemble_sequence(struct rlc_frag ** frags, struct rlc_seqlist * endlist,
938
                    struct rlc_channel * ch_lookup, uint16_t start, uint16_t end)
939
0
{
940
0
    GList * element = NULL;
941
0
    struct rlc_sdu * sdu = rlc_sdu_create();
942
943
0
    uint16_t snmod = getChannelSNModulus(ch_lookup);
944
945
    /* Insert fragments into SDU. */
946
0
    for (; moduloCompare(start,end,snmod ) <= 0; start = (start+1)%snmod)
947
0
    {
948
0
        struct rlc_frag * tempfrag = NULL;
949
0
        tempfrag = frags[start]->next;
950
0
        frags[start]->next = NULL;
951
0
        rlc_sdu_add_fragment(ch_lookup->mode, sdu, frags[start]);
952
0
        frags[start] = tempfrag;
953
0
    }
954
955
    /* Remove first endpoint. */
956
0
    element = g_list_first(endlist->list);
957
0
    if (element) {
958
0
        endlist->list = g_list_delete_link(endlist->list, element);
959
0
        if (frags[end] != NULL) {
960
0
            if (endlist->list) {
961
0
                endlist->list->data = GINT_TO_POINTER((GPOINTER_TO_INT(endlist->list->data) - 1 + snmod) % snmod);
962
0
            }
963
0
        }
964
0
    }
965
0
    reassemble_data(ch_lookup, sdu, NULL);
966
0
}
967
968
/* Reset the specified channel's reassembly data, useful for when a sequence
969
 * resets on transport channel swap. */
970
/* TODO: not currently called */
971
void
972
rlc_reset_channel(enum rlc_mode mode, uint8_t rbid, uint8_t dir, uint32_t ueid,
973
                  struct atm_phdr *atm)
974
0
{
975
0
    struct rlc_frag ** frags = NULL;
976
0
    struct rlc_seqlist * endlist = NULL;
977
0
    struct rlc_channel ch_lookup;
978
0
    unsigned i;
979
980
0
    ch_lookup.mode = mode;
981
0
    ch_lookup.rbid = rbid;
982
0
    ch_lookup.dir = dir;
983
0
    ch_lookup.ueid = ueid;
984
0
    frags = get_frags(NULL, &ch_lookup, atm);
985
0
    endlist = get_endlist(NULL, &ch_lookup, atm);
986
0
    if (endlist) {
987
0
        endlist->fail_packet = 0;
988
0
        g_list_free(endlist->list);
989
0
        endlist->list = NULL;
990
0
    }
991
992
0
    if (frags) {
993
0
        for (i = 0; i < 4096; i++) {
994
0
            frags[i] = NULL;
995
0
        }
996
0
    }
997
0
}
998
999
/* add a new fragment to an SDU
1000
 * if length == 0, just finalize the specified SDU
1001
 */
1002
static struct rlc_frag *
1003
add_fragment(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
1004
         proto_tree *tree, uint16_t offset, uint16_t seq, uint16_t num_li,
1005
         uint16_t len, bool final, struct atm_phdr *atm)
1006
0
{
1007
0
    struct rlc_channel  ch_lookup;
1008
0
    struct rlc_frag     frag_lookup, *frag = NULL;
1009
0
    void               *orig_key = NULL, *value = NULL;
1010
0
    struct rlc_sdu     *sdu = NULL;
1011
0
    struct rlc_frag ** frags = NULL;
1012
0
    struct rlc_seqlist * endlist = NULL;
1013
0
    GList * element = NULL;
1014
0
    int snmod;
1015
1016
0
    if (rlc_channel_assign(&ch_lookup, mode, pinfo, atm) == -1) {
1017
0
        return NULL;
1018
0
    }
1019
0
    rlc_frag_assign(&frag_lookup, mode, pinfo, seq, num_li, atm);
1020
    #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1021
        g_print("packet: %d, channel (%d %d %d) seq: %u, num_li: %u, offset: %u, \n", pinfo->num, ch_lookup.dir, ch_lookup.rbid, ch_lookup.ueid, seq, num_li, offset);
1022
    #endif
1023
1024
0
    snmod = getChannelSNModulus(&ch_lookup);
1025
1026
    /* look for an already assembled SDU */
1027
0
    if (g_hash_table_lookup_extended(reassembled_table, &frag_lookup, &orig_key, &value)) {
1028
        /* this fragment is already reassembled somewhere */
1029
0
        frag = (struct rlc_frag *)orig_key;
1030
0
        sdu = (struct rlc_sdu *)value;
1031
0
        if (tree) {
1032
            /* mark the fragment, if reassembly happened somewhere else */
1033
0
            if (frag->seq != sdu->reassembled_in->seq ||
1034
0
                frag->li != sdu->reassembled_in->li)
1035
0
                proto_tree_add_uint(tree, hf_rlc_reassembled_in, tvb, 0, 0,
1036
0
                    sdu->reassembled_in->frame_num);
1037
0
        }
1038
0
        return frag;
1039
0
    }
1040
1041
0
    frags = get_frags(pinfo, &ch_lookup, atm);
1042
0
    endlist = get_endlist(pinfo, &ch_lookup, atm);
1043
1044
    /* If already done reassembly */
1045
0
    if (PINFO_FD_VISITED(pinfo)) {
1046
0
        if (tree && len > 0) {
1047
0
            if (endlist->list && endlist->list->next) {
1048
0
                int16_t start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1049
0
                int16_t end = GPOINTER_TO_INT(endlist->list->next->data);
1050
0
                int16_t missing = start;
1051
0
                bool wecanreasmmore = true;
1052
1053
0
                for (; moduloCompare(missing,end,snmod ) <= 0; missing = (missing+1)%snmod)
1054
0
                {
1055
0
                    if (frags[missing] == NULL) {
1056
0
                        wecanreasmmore = false;
1057
0
                        break;
1058
0
                    }
1059
0
                }
1060
1061
0
                if (wecanreasmmore) {
1062
0
                    reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1063
0
                } else {
1064
0
                    if (end >= 0 && end < snmod && frags[end]) {
1065
0
                        proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1066
0
                                        "Did not perform reassembly because of unfinished sequence (%d->%d [packet %u]), could not find %d.", start, end, frags[end]->frame_num, missing);
1067
0
                    } else {
1068
0
                        proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1069
0
                                        "Did not perform reassembly because of unfinished sequence (%d->%d [could not determine packet]), could not find %d.", start, end, missing);
1070
0
                    }
1071
0
                }
1072
0
            } else if (endlist->list) {
1073
0
                if (endlist->fail_packet != 0 && endlist->fail_packet <= pinfo->num) {
1074
0
                    proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_flag_set, tvb, 0, 0, "Did not perform reassembly because fail flag was set in packet %u.", endlist->fail_packet);
1075
0
                } else {
1076
0
                    int16_t end = GPOINTER_TO_INT(endlist->list->data);
1077
0
                    if (end >= 0 && end < snmod && frags[end]) {
1078
0
                        proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [packet %d]).", end, frags[end]->frame_num);
1079
0
                    } else {
1080
0
                        proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [could not determine packet]).", end);
1081
0
                    }
1082
0
                }
1083
0
            } else {
1084
0
                expert_add_info(pinfo, NULL, &ei_rlc_reassembly_unknown_error);
1085
0
            }
1086
0
        }
1087
0
        return NULL; /* If already done reassembly and no SDU found, too bad */
1088
0
    }
1089
1090
0
    if (endlist->fail_packet != 0) { /* don't continue after sh*t has hit the fan */
1091
0
        return NULL;
1092
0
    }
1093
1094
0
    frag = rlc_frag_create(tvb, mode, pinfo, offset, len, seq, num_li, atm);
1095
1096
    /* If frags[seq] is not NULL then we must have data from several PDUs in the
1097
     * same RLC packet (using Length Indicators) or something has gone terribly
1098
     * wrong. */
1099
0
    if (frags[seq] != NULL) {
1100
0
        if (num_li > 0) {
1101
0
            struct rlc_frag * tempfrag = frags[seq];
1102
0
            while (tempfrag->next != NULL)
1103
0
                tempfrag = tempfrag->next;
1104
0
            tempfrag->next = frag;
1105
0
        } else { /* This should never happen */
1106
0
            endlist->fail_packet = pinfo->num;
1107
0
            return NULL;
1108
0
        }
1109
0
    } else {
1110
0
        frags[seq] = frag;
1111
0
    }
1112
1113
    /* It is also possible that frags[seq] is NULL even though we do have data
1114
     * from several PDUs in the same RLC packet. This is if the reassembly is
1115
     * not lagging behind at all because of perfectly ordered sequences. */
1116
0
    if (endlist->list && num_li != 0) {
1117
0
        int16_t first = GPOINTER_TO_INT(endlist->list->data);
1118
0
        if (seq == first) {
1119
0
            endlist->list->data = GINT_TO_POINTER(first-1);
1120
0
        }
1121
0
    }
1122
1123
    /* If this is an endpoint */
1124
0
    if (final) {
1125
0
        endlist->list = g_list_append(endlist->list, GINT_TO_POINTER((int)seq));
1126
0
    }
1127
1128
    #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1129
    printends(endlist->list);
1130
    #endif
1131
1132
    /* Try to reassemble SDU. */
1133
0
    if (endlist->list && endlist->list->next) {
1134
0
        int16_t start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1135
0
        int16_t end = GPOINTER_TO_INT(endlist->list->next->data);
1136
0
        if (frags[end] == NULL) {
1137
#if RLC_ADD_FRAGMENT_FAIL_PRINT
1138
            proto_tree_add_debug_text(tree, "frag[end] is null, this is probably because end was a startpoint but because of some error ended up being treated as an endpoint, setting fail flag, start %d, end %d, packet %u\n", start, end, pinfo->num);
1139
#endif
1140
0
            endlist->fail_packet = pinfo->num;
1141
0
            return NULL;
1142
0
        }
1143
1144
        /* If our endpoint is a LI=0 with no data. */
1145
0
        if (start == end && frags[start]->len == 0) {
1146
0
            element = g_list_first(endlist->list);
1147
0
            if (element) {
1148
0
                endlist->list = g_list_delete_link(endlist->list, element);
1149
0
            }
1150
0
            frags[start] = frags[start]->next;
1151
1152
            /* If frags[start] is not NULL now, then that means that there was
1153
             * another fragment with the same seq number because of LI. If we
1154
             * don't decrease the endpoint by 1 then that fragment will be
1155
             * skipped and all hell will break lose. */
1156
0
            if (frags[start] != NULL) {
1157
0
                endlist->list->data = GINT_TO_POINTER(start-1);
1158
0
            }
1159
            /* NOTE: frags[start] is wmem_alloc'ed and will remain until file closes, we would want to free it here maybe. */
1160
0
            return NULL;
1161
0
        }
1162
1163
        #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1164
        g_print("start: %d, end: %d\n",start, end);
1165
        #endif
1166
1167
0
        for (;  moduloCompare(start,end,snmod ) < 0; start = (start+1)%snmod)
1168
0
        {
1169
0
            if (frags[start] == NULL) {
1170
0
                if (MIN((start-seq+snmod)%snmod, (seq-start+snmod)%snmod) >= snmod/4) {
1171
#if RLC_ADD_FRAGMENT_FAIL_PRINT
1172
                    proto_tree_add_debug_text(tree,
1173
"Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1174
too far away from an unfinished sequence (%u->%u). The missing sequence number \
1175
is %u. The most recently complete sequence ended in packet %u.", pinfo->num, seq, 0, end, start, 0);
1176
#endif
1177
0
                    endlist->fail_packet = pinfo->num; /* If it has gone too far, give up */
1178
0
                    return NULL;
1179
0
                }
1180
0
                return frag;
1181
0
            }
1182
0
        }
1183
0
        start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1184
0
        reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1185
0
    } else if (endlist->list) {
1186
0
        int16_t first = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1187
        /* If the distance between the oldest stored endpoint in endlist and
1188
         * this endpoint is too large, set fail flag. */
1189
0
        if (MIN((first-seq+snmod)%snmod, (seq-first+snmod)%snmod) >= snmod/4) {
1190
#if RLC_ADD_FRAGMENT_FAIL_PRINT
1191
            proto_tree_add_debug_text(tree,
1192
"Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1193
too far away from an unfinished sequence with start %u and without end.", pinfo->num, seq, first);
1194
#endif
1195
0
            endlist->fail_packet = pinfo->num; /* Give up if things have gone too far. */
1196
0
            return NULL;
1197
0
        }
1198
0
    }
1199
1200
0
    return frag;
1201
0
}
1202
1203
/* is_data is used to identify rlc data parts that are not identified by an LI, but are at the end of
1204
 * the RLC frame
1205
 * these can be valid reassembly points, but only if the LI of the *next* relevant RLC frame is
1206
 * set to '0' (this is indicated in the reassembled SDU
1207
 */
1208
static tvbuff_t *
1209
get_reassembled_data(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
1210
             proto_tree *tree, uint16_t seq, uint16_t num_li,
1211
             struct atm_phdr *atm)
1212
0
{
1213
0
    void            *orig_frag, *orig_sdu;
1214
0
    struct rlc_sdu  *sdu;
1215
0
    struct rlc_frag  lookup, *frag;
1216
1217
0
    rlc_frag_assign(&lookup, mode, pinfo, seq, num_li, atm);
1218
1219
0
    if (!g_hash_table_lookup_extended(reassembled_table, &lookup,
1220
0
        &orig_frag, &orig_sdu))
1221
0
        return NULL;
1222
1223
0
    sdu = (struct rlc_sdu *)orig_sdu;
1224
0
    if (!sdu || !sdu->data)
1225
0
        return NULL;
1226
1227
    /* TODO */
1228
#if 0
1229
    if (!rlc_frag_equal(&lookup, sdu->reassembled_in)) return NULL;
1230
#endif
1231
1232
0
    frag = sdu->frags;
1233
0
    while (frag->next) {
1234
0
        if (frag->next->seq - frag->seq > 1) {
1235
0
            proto_tree_add_expert(tree, pinfo, &ei_rlc_incomplete_sequence, tvb, 0, 0);
1236
0
            tree_add_fragment_list_incomplete(sdu, tvb, tree);
1237
0
            return NULL;
1238
0
        }
1239
0
        frag = frag->next;
1240
0
    }
1241
1242
0
    sdu->tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->len, sdu->len);
1243
0
    add_new_data_source(pinfo, sdu->tvb, "Reassembled RLC Message");
1244
1245
    /* reassembly happened here, so create the fragment list */
1246
0
    if (tree && sdu->fragcnt > 1)
1247
0
        tree_add_fragment_list(sdu, sdu->tvb, pinfo, tree);
1248
1249
0
    return sdu->tvb;
1250
0
}
1251
1252
0
#define RLC_RETRANSMISSION_TIMEOUT 5 /* in seconds */
1253
static bool
1254
rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, uint16_t seq,
1255
         uint32_t *original, struct atm_phdr *atm)
1256
0
{
1257
0
    GList              *element;
1258
0
    struct rlc_seqlist  lookup, *list;
1259
0
    struct rlc_seq      seq_item, *seq_new;
1260
0
    uint16_t snmod;
1261
0
    nstime_t delta;
1262
0
    bool is_duplicate,is_unseen;
1263
1264
0
    if (rlc_channel_assign(&lookup.ch, mode, pinfo, atm) == -1)
1265
0
        return false;
1266
0
    list = (struct rlc_seqlist *)g_hash_table_lookup(sequence_table, &lookup.ch);
1267
0
    if (!list) {
1268
        /* we see this channel for the first time */
1269
0
        list = (struct rlc_seqlist *)wmem_alloc0(wmem_file_scope(), sizeof(*list));
1270
0
        rlc_channel_assign(&list->ch, mode, pinfo, atm);
1271
0
        g_hash_table_insert(sequence_table, &list->ch, list);
1272
0
    }
1273
0
    seq_item.seq = seq;
1274
0
    seq_item.frame_num = pinfo->num;
1275
1276
    /* When seq is 12 bit (in RLC protocol), it will wrap around after 4096. */
1277
    /* Window size is at most 4095 so we remove packets further away than that */
1278
0
    element = g_list_first(list->list);
1279
0
    snmod = getChannelSNModulus(&lookup.ch);
1280
0
    if (element) {
1281
0
        seq_new = (struct rlc_seq *)element->data;
1282
        /* Add SN modulus because %-operation for negative values in C is not equal to mathematical modulus */
1283
0
        if (MIN((seq_new->seq-seq+snmod)%snmod, (seq-seq_new->seq+snmod)%snmod) >= snmod/4) {
1284
0
            list->list = g_list_remove_link(list->list, element);
1285
0
        }
1286
0
    }
1287
1288
0
    is_duplicate = false;
1289
0
    is_unseen = true;
1290
0
    element = g_list_find_custom(list->list, &seq_item, rlc_cmp_seq);
1291
0
    while(element) {
1292
        /* Check if this is a different frame (by comparing frame numbers) which arrived less than */
1293
        /* RLC_RETRANSMISSION_TIMEOUT seconds ago */
1294
0
        seq_new = (struct rlc_seq *)element->data;
1295
0
        if (seq_new->frame_num < seq_item.frame_num) {
1296
0
            nstime_delta(&delta, &pinfo->abs_ts, &seq_new->arrival);
1297
0
            if (delta.secs < RLC_RETRANSMISSION_TIMEOUT) {
1298
                /* This is a duplicate. */
1299
0
                if (original) {
1300
                    /* Save the frame number where our sequence number was previously seen */
1301
0
                    *original = seq_new->frame_num;
1302
0
                }
1303
0
                is_duplicate = true;
1304
0
            }
1305
0
        }
1306
0
        else if (seq_new->frame_num == seq_item.frame_num) {
1307
            /* Check if our frame is already in the list and this is a secondary check.*/
1308
            /* in this case raise a flag so the frame isn't entered more than once to the list */
1309
0
            is_unseen = false;
1310
0
        }
1311
0
        element = g_list_find_custom(element->next, &seq_item, rlc_cmp_seq);
1312
0
    }
1313
0
    if(is_unseen) {
1314
        /* Add to list for the first time this frame is checked */
1315
0
        seq_item.arrival = pinfo->abs_ts; /* Initialize first to please Coverity */
1316
0
        seq_new = wmem_new0(wmem_file_scope(), struct rlc_seq);
1317
0
        *seq_new = seq_item;
1318
0
        list->list = g_list_append(list->list, seq_new); /* insert in order of arrival */
1319
0
    }
1320
0
    return is_duplicate;
1321
0
}
1322
1323
static void
1324
rlc_call_subdissector(enum rlc_channel_type channel, tvbuff_t *tvb,
1325
              packet_info *pinfo, proto_tree *tree)
1326
0
{
1327
0
    bool is_rrc_payload = true;
1328
0
    volatile dissector_handle_t next_dissector = NULL;
1329
0
    enum rrc_message_type msgtype;
1330
1331
0
    switch (channel) {
1332
0
        case RLC_UL_CCCH:
1333
0
            msgtype = RRC_MESSAGE_TYPE_UL_CCCH;
1334
0
            break;
1335
0
        case RLC_DL_CCCH:
1336
0
            msgtype = RRC_MESSAGE_TYPE_DL_CCCH;
1337
0
            break;
1338
0
        case RLC_DL_CTCH:
1339
            /* Payload of DL CTCH is BMC*/
1340
0
            is_rrc_payload = false;
1341
0
            msgtype = RRC_MESSAGE_TYPE_INVALID;
1342
0
            next_dissector = bmc_handle;
1343
0
            break;
1344
0
        case RLC_UL_DCCH:
1345
0
            msgtype = RRC_MESSAGE_TYPE_UL_DCCH;
1346
0
            break;
1347
0
        case RLC_DL_DCCH:
1348
0
            msgtype = RRC_MESSAGE_TYPE_DL_DCCH;
1349
0
            break;
1350
0
        case RLC_PCCH:
1351
0
            msgtype = RRC_MESSAGE_TYPE_PCCH;
1352
0
            break;
1353
0
        case RLC_BCCH:
1354
0
            msgtype = RRC_MESSAGE_TYPE_BCCH_FACH;
1355
0
            break;
1356
0
        case RLC_PS_DTCH:
1357
            /* Payload of PS DTCH is PDCP or just IP*/
1358
0
            is_rrc_payload = false;
1359
0
            msgtype = RRC_MESSAGE_TYPE_INVALID;
1360
            /* assume transparent PDCP for now */
1361
0
            next_dissector = ip_handle;
1362
0
            break;
1363
0
        default:
1364
0
            return; /* stop dissecting */
1365
0
    }
1366
1367
0
    if (is_rrc_payload && msgtype != RRC_MESSAGE_TYPE_INVALID) {
1368
        /* Passing the RRC sub type in the 'rrc_info' struct */
1369
0
        struct rrc_info *rrcinf;
1370
0
        fp_info *fpinf;
1371
0
        fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1372
0
        rrcinf = (rrc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0);
1373
0
        if (!rrcinf) {
1374
0
            rrcinf = (rrc_info *)wmem_alloc0(wmem_file_scope(), sizeof(struct rrc_info));
1375
0
            p_add_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0, rrcinf);
1376
0
        }
1377
0
        rrcinf->msgtype[fpinf->cur_tb] = msgtype;
1378
0
        next_dissector = rrc_handle;
1379
0
    }
1380
1381
0
    if(next_dissector != NULL) {
1382
0
        TRY {
1383
0
            call_dissector(next_dissector, tvb, pinfo, tree);
1384
0
        }
1385
0
        CATCH_NONFATAL_ERRORS {
1386
            /*
1387
             * Sub dissector threw an exception
1388
             * Show the exception and continue dissecting other SDUs.
1389
             */
1390
0
            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1391
0
        }
1392
0
        ENDTRY;
1393
        /* once the packet has been dissected, protect it from further changes using a 'fence' in the INFO column */
1394
0
        col_append_str(pinfo->cinfo, COL_INFO," ");
1395
0
        col_set_fence(pinfo->cinfo, COL_INFO);
1396
0
    }
1397
0
}
1398
1399
static void
1400
add_channel_info(packet_info * pinfo, proto_tree * tree, fp_info * fpinf, rlc_info * rlcinf)
1401
0
{
1402
0
    proto_item * item;
1403
0
    proto_tree * channel_tree ;
1404
1405
0
    item = proto_tree_add_item(tree, hf_rlc_channel, NULL, 0, 0, ENC_NA);
1406
0
    channel_tree = proto_item_add_subtree(item, ett_rlc_channel);
1407
0
    proto_item_append_text(item, " (rbid: %u, dir: %s, uid: 0x%08x)", rlcinf->rbid[fpinf->cur_tb],
1408
0
                           val_to_str_const(pinfo->link_dir, rlc_dir_vals, "Unknown"), rlcinf->ueid[fpinf->cur_tb]);
1409
0
    proto_item_set_generated(item);
1410
0
    item = proto_tree_add_uint(channel_tree, hf_rlc_channel_rbid, NULL, 0, 0, rlcinf->rbid[fpinf->cur_tb]);
1411
0
    proto_item_set_generated(item);
1412
0
    item = proto_tree_add_uint(channel_tree, hf_rlc_channel_dir, NULL, 0, 0, pinfo->link_dir);
1413
0
    proto_item_set_generated(item);
1414
0
    item = proto_tree_add_uint(channel_tree, hf_rlc_channel_ueid, NULL, 0, 0, rlcinf->ueid[fpinf->cur_tb]);
1415
0
    proto_item_set_generated(item);
1416
1417
0
}
1418
1419
#ifdef HAVE_UMTS_KASUMI
1420
static uint8_t *
1421
translate_hex_key(char * char_key){
1422
    int i,j;
1423
    uint8_t * key_in;
1424
1425
    key_in = wmem_alloc0(pinfo->pool, sizeof(uint8_t)*16);
1426
    j= (int)(strlen(char_key)/2)-1;
1427
    /*Translate "hex-string" into a byte aligned block */
1428
    for(i = (unsigned)strlen(char_key); i> 0; i-=2 ){
1429
        key_in[j] =  ( (uint8_t)  (strtol( &char_key[i-2], NULL, 16 ) ));
1430
        char_key[i-2] = '\0';
1431
        j--;
1432
    }
1433
    return key_in;
1434
1435
}
1436
#endif
1437
1438
/** @brief Deciphers a given tvb
1439
 *
1440
 * Note that the actual KASUMI implementation needs to be placed into
1441
 * epan/crypt/kasumi.* by "end users" since due to patents the actual implementation
1442
 * cannot be distributed openly at the moment.
1443
 *
1444
 * Refer to 3GPP TS 35.201 and 3GPP TS 35.202 for further information.
1445
 *
1446
 *  @param tvb The ciphered data.
1447
 *  @param  pinfo Packet info.
1448
 *  @param counter the COUNTER value input
1449
 *  @param rbid the radiobear id
1450
 *  @param dir Direction of the link
1451
 *  @param header_size Size of the unciphered header
1452
 *  @return tvb Returns a deciphered tvb
1453
 */
1454
static tvbuff_t *
1455
#ifndef HAVE_UMTS_KASUMI
1456
rlc_decipher_tvb(tvbuff_t *tvb _U_, packet_info *pinfo, uint32_t counter _U_,
1457
0
                 uint8_t rbid _U_, bool dir _U_, uint8_t header_size _U_) {
1458
    /*Check if we have a KASUMI implementation*/
1459
0
    expert_add_info(pinfo, NULL, &ei_rlc_kasumi_implementation_missing);
1460
0
    return NULL;
1461
#else
1462
rlc_decipher_tvb(tvbuff_t *tvb, packet_info *pinfo, uint32_t counter, uint8_t rbid, bool dir, uint8_t header_size) {
1463
    uint8_t* out=NULL,*key_in = NULL;
1464
    tvbuff_t *t;
1465
1466
    /*Fix the key into a byte block*/
1467
    /*TODO: This should be done in a preferences callback function*/
1468
    out = wmem_alloc0(pinfo->pool, strlen(global_rlc_kasumi_key)+1);
1469
    memcpy(out,global_rlc_kasumi_key,strlen(global_rlc_kasumi_key));    /*Copy from preference const pointer*/
1470
    key_in = translate_hex_key(out);    /*Translation*/
1471
1472
    /*Location for decrypted data & original RLC header*/
1473
    out = tvb_memdup(pinfo->pool, tvb, 0, tvb_captured_length(tvb));
1474
1475
    /*Call f8 confidentiality function, note that rbid is zero indexed*/
1476
    f8( key_in, counter, rbid-1, dir, &out[header_size], (tvb_captured_length(tvb)-header_size)*8 );
1477
1478
    /*Create new tvb.*/
1479
    t = tvb_new_real_data(out,tvb_captured_length(tvb), tvb_reported_length(tvb));
1480
    add_new_data_source(pinfo, t, "Deciphered RLC");
1481
    return t;
1482
#endif /* HAVE_UMTS_KASUMI */
1483
0
}
1484
1485
/** @brief Checks if an RLC packet is ciphered, according to information reported from the RRC layer
1486
 *
1487
 *  @param pinfo Packet info.
1488
 *  @param fpinf FP info
1489
 *  @param rlcinf RLC info
1490
 *  @param seq Sequence number of the RLC packet
1491
 *  @return bool Returns true if the packet is ciphered and false otherwise
1492
 */
1493
static bool
1494
0
is_ciphered_according_to_rrc(packet_info *pinfo, fp_info *fpinf, rlc_info *rlcinf ,uint16_t seq) {
1495
0
    int16_t             cur_tb;
1496
0
    uint32_t            ueid;
1497
0
    rrc_ciphering_info *ciphering_info;
1498
0
    uint8_t             rbid;
1499
0
    uint8_t             direction;
1500
0
    uint32_t            security_mode_frame_num;
1501
0
    int32_t             ciphering_begin_seq;
1502
1503
0
    if(global_ignore_rrc_ciphering_indication) {
1504
0
        return false;
1505
0
    }
1506
1507
0
    cur_tb = fpinf->cur_tb;
1508
0
    ueid = rlcinf->ueid[cur_tb];
1509
0
    ciphering_info =  (rrc_ciphering_info *)g_tree_lookup(rrc_ciph_info_tree, GINT_TO_POINTER((int)ueid));
1510
0
    if(ciphering_info != NULL) {
1511
0
        rbid = rlcinf->rbid[cur_tb];
1512
0
        direction = fpinf->is_uplink ? P2P_DIR_UL : P2P_DIR_DL;
1513
0
        security_mode_frame_num = ciphering_info->setup_frame[direction];
1514
0
        ciphering_begin_seq = ciphering_info->seq_no[rbid][direction];
1515
        /* Making sure the rrc security message's frame number makes sense */
1516
0
        if( security_mode_frame_num > 0 && security_mode_frame_num <= pinfo->num) {
1517
            /* Making sure the sequence number where ciphering starts makes sense */
1518
            /* TODO: This check is incorrect if the sequence numbers wrap around */
1519
0
            if(ciphering_begin_seq >= 0 && ciphering_begin_seq <= seq){
1520
        /* Finally, make sure the encryption algorithm isn't set to UEA0 (no ciphering)*/
1521
0
                return ciphering_info->ciphering_algorithm != 0;
1522
0
            }
1523
0
        }
1524
0
    }
1525
0
    return false;
1526
0
}
1527
1528
/*
1529
 * @param key is created with GINT_TO_POINTER
1530
 * @param value is a pointer to a uint32_t
1531
 * @param data is a pointer to a uint32_t
1532
 */
1533
static gboolean
1534
0
iter_same(void *key, void *value, void *data) {
1535
    /*If true we found the correct frame*/
1536
0
    if ((uint32_t)GPOINTER_TO_INT(key) > *(uint32_t*)data){
1537
0
        *((uint32_t*)data) = *((uint32_t*)value);
1538
0
        return TRUE;
1539
0
    }
1540
0
    *((uint32_t*)data) = (uint32_t)GPOINTER_TO_INT(key);
1541
1542
0
    return TRUE;
1543
0
}
1544
1545
/**
1546
 * Used for looking up and old ciphering counter value in the counter_map tree.
1547
 * @param key is created with GINT_TO_POINTER
1548
 * @param value is pointer to an array of 2 uint32_t
1549
 * @param data is a pointer to an array of 3 uint32_t
1550
 */
1551
static gboolean
1552
0
rlc_find_old_counter(void *key, void *value, void *data) {
1553
1554
    /*If true we found the correct frame*/
1555
0
    if( (uint32_t)GPOINTER_TO_INT(key) >= ((uint32_t *)data)[0] ){
1556
0
        return TRUE;
1557
0
    }
1558
    /*Overwrite the data since the previous one wasn't correct*/
1559
0
    ((uint32_t*)data)[1] = ((uint32_t*)value)[0];
1560
0
    ((uint32_t*)data)[2] = ((uint32_t*)value)[1];
1561
1562
0
    return FALSE;
1563
0
}
1564
1565
static void
1566
rlc_decipher(tvbuff_t *tvb, packet_info * pinfo, proto_tree * tree, fp_info * fpinf,
1567
             rlc_info * rlcinf, uint16_t seq, enum rlc_mode mode)
1568
0
{
1569
0
    rrc_ciphering_info *ciphering_info;
1570
0
    uint8_t indx, header_size, hfn_shift;
1571
0
    int16_t pos;
1572
0
    uint8_t ext;
1573
0
    int ciphered_data_hf;
1574
1575
0
    indx = fpinf->is_uplink ? P2P_DIR_UL : P2P_DIR_DL;
1576
0
    pos = fpinf->cur_tb;
1577
0
    if (mode ==RLC_UM) {
1578
0
        header_size = 1;
1579
0
        hfn_shift = 7;
1580
0
    } else {
1581
0
        header_size = 2;
1582
0
        hfn_shift = 12;
1583
0
    }
1584
1585
    /*Ciphering info singled in RRC by securitymodecommands */
1586
0
    ciphering_info =  (rrc_ciphering_info *)g_tree_lookup(rrc_ciph_info_tree, GINT_TO_POINTER((int)rlcinf->ueid[fpinf->cur_tb]));
1587
1588
    /*TODO: This doesn't really work for all packets..*/
1589
    /*Check if we have ciphering info and that this frame is ciphered*/
1590
0
    if(ciphering_info!=NULL && ( (ciphering_info->setup_frame[indx] > 0 && ciphering_info->setup_frame[indx] < pinfo->num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] == -1)  ||
1591
0
                     (ciphering_info->setup_frame[indx] < pinfo->num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] >= 0  && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] <= seq) )){
1592
1593
0
        tvbuff_t *t;
1594
1595
        /*Check if this counter has been initialized*/
1596
0
        if(!counter_init[rlcinf->rbid[pos]][indx] ){
1597
0
            uint32_t frame_num = pinfo->num;
1598
1599
            /*Initializes counter*/
1600
0
            counter_init[rlcinf->rbid[pos]][0] = true;
1601
0
            counter_init[rlcinf->rbid[pos]][1] = true;
1602
            /*Find appropriate start value*/
1603
0
            g_tree_foreach(ciphering_info->start_ps, (GTraverseFunc)iter_same, &frame_num);
1604
1605
            /*Set COUNTER value accordingly as specified by 6.4.8 in 3GPP TS 33.102 */
1606
0
            if(max_counter +2 > frame_num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] == -1){
1607
0
                ps_counter[rlcinf->rbid[pos]][0] = (max_counter+2) << hfn_shift;
1608
0
                ps_counter[rlcinf->rbid[pos]][1] = (max_counter+2) << hfn_shift;
1609
0
            }else{
1610
0
                ps_counter[rlcinf->rbid[pos]][0] = frame_num << hfn_shift;
1611
0
                ps_counter[rlcinf->rbid[pos]][1] = frame_num << hfn_shift;
1612
0
            }
1613
1614
0
            if(!tree){
1615
                /*Preserve counter value for next dissection round*/
1616
0
                uint32_t * ciph;
1617
0
                ciph = g_new(uint32_t, 2);
1618
0
                ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1619
0
                ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1620
0
                g_tree_insert(counter_map, GINT_TO_POINTER((int)pinfo->num), ciph);
1621
0
            }
1622
1623
0
        }
1624
        /*Update the maximal COUNTER value seen so far*/
1625
0
        max_counter = MAX(max_counter,((ps_counter[rlcinf->rbid[pos]][indx]) | seq) >> hfn_shift);
1626
1627
    /*XXX: Since RBID in umts isn't configured properly..*/
1628
0
        if(rlcinf->rbid[pos] == 9 ){
1629
0
            if(tree){
1630
0
                uint32_t frame_num[3];
1631
                /*Set frame num we will be "searching" around*/
1632
0
                frame_num[0] = pinfo->num;
1633
                /*Find the correct counter value*/
1634
0
                g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1635
0
                t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),16,!fpinf->is_uplink,header_size);
1636
0
            }else{
1637
0
                t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),16,!fpinf->is_uplink,header_size);
1638
0
            }
1639
0
        }else{
1640
0
            if(tree){
1641
                /*We need to find the original counter value for second dissection pass*/
1642
0
                uint32_t frame_num[3];
1643
0
                frame_num[0] = pinfo->num;
1644
0
                g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1645
0
                t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1646
0
            }else
1647
0
                t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1648
0
        }
1649
1650
        /*Update the hyperframe number*/
1651
0
        if(seq == 4095){
1652
1653
0
            ps_counter[rlcinf->rbid[pos]][indx] += 1 << hfn_shift;
1654
1655
0
            if(!tree){/*Preserve counter for second packet analysis run*/
1656
0
                uint32_t * ciph;
1657
0
                ciph = g_new(uint32_t, 2);
1658
0
                ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1659
0
                ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1660
0
                g_tree_insert(counter_map, GINT_TO_POINTER((int)pinfo->num+1), ciph);
1661
0
            }
1662
0
        }
1663
1664
        /*Unable to decipher the packet*/
1665
0
        if(t == NULL){
1666
            /* Choosing the right field text ("LIs & Data" or just "Data") based on extension bit / header extension */
1667
0
            ext = tvb_get_uint8(tvb, header_size - 1) & 0x01;
1668
0
            ciphered_data_hf = (ext == 1) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
1669
            /* Adding ciphered payload field to tree */
1670
0
            proto_tree_add_item(tree, ciphered_data_hf, tvb, header_size, -1, ENC_NA);
1671
0
            proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_ciphered_data, tvb, header_size);
1672
0
            col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1673
0
            return;
1674
1675
0
        }else{
1676
0
            col_append_str(pinfo->cinfo, COL_INFO, "[Deciphered Data]");
1677
1678
            /*TODO: Old tvb should be freed here?*/
1679
0
        }
1680
0
    }
1681
0
}
1682
1683
static void
1684
dissect_rlc_tm(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1685
           proto_tree *top_level, proto_tree *tree)
1686
0
{
1687
0
    fp_info       *fpinf;
1688
0
    rlc_info      *rlcinf;
1689
1690
0
    fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1691
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1692
1693
0
    if (tree) {
1694
0
        if (fpinf && rlcinf) {
1695
            /* Add "channel" information, very useful for debugging. */
1696
0
            add_channel_info(pinfo, tree, fpinf, rlcinf);
1697
0
        }
1698
0
        proto_tree_add_item(tree, hf_rlc_data, tvb, 0, -1, ENC_NA);
1699
0
    }
1700
0
    rlc_call_subdissector(channel, tvb, pinfo, top_level);
1701
0
}
1702
1703
1704
static void
1705
rlc_um_reassemble(tvbuff_t *tvb, uint16_t offs, packet_info *pinfo, proto_tree *tree,
1706
          proto_tree *top_level, enum rlc_channel_type channel, uint16_t seq,
1707
          struct rlc_li *li, uint16_t num_li, bool li_is_on_2_bytes,
1708
          struct atm_phdr *atm)
1709
0
{
1710
0
    uint16_t  i;
1711
0
    bool      dissected = false;
1712
0
    int       length;
1713
0
    tvbuff_t *next_tvb  = NULL;
1714
1715
    /* perform reassembly now */
1716
0
    for (i = 0; i < num_li; i++) {
1717
0
        if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
1718
            /* padding, must be last LI */
1719
0
            if (tree) {
1720
0
                proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, tvb_captured_length_remaining(tvb, offs), ENC_NA);
1721
0
            }
1722
0
            offs += tvb_captured_length_remaining(tvb, offs);
1723
0
        } else if ((!li_is_on_2_bytes && (li[i].li == 0x7c)) || (li[i].li == 0x7ffc)) {
1724
            /* a new SDU starts here, mark this seq as the first PDU. */
1725
0
            struct rlc_channel  ch_lookup;
1726
0
            struct rlc_seqlist * endlist = NULL;
1727
0
            if( -1 != rlc_channel_assign(&ch_lookup, RLC_UM, pinfo, atm ) ){
1728
0
                endlist = get_endlist(pinfo, &ch_lookup, atm);
1729
0
                endlist->list->data = GINT_TO_POINTER((int)seq);
1730
0
                endlist->fail_packet=0;
1731
0
            }
1732
1733
0
        } else if (li[i].li == 0x7ffa) {
1734
            /* the first data octet in this RLC PDU is the first octet of an RLC SDU
1735
               and the second last octet in this RLC PDU is the last octet of the same RLC SDU */
1736
0
            length = tvb_reported_length_remaining(tvb, offs);
1737
0
            if (length > 1) {
1738
0
                length--;
1739
0
                if (tree && length) {
1740
0
                    proto_tree_add_item(tree, hf_rlc_data, tvb, offs, length, ENC_NA);
1741
0
                }
1742
0
                if (global_rlc_perform_reassemby) {
1743
0
                    add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, length, true, atm);
1744
0
                    next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i, atm);
1745
0
                }
1746
0
                offs += length;
1747
0
            }
1748
0
            if (tree) {
1749
0
                proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, 1, ENC_NA);
1750
0
            }
1751
0
            offs += 1;
1752
0
        } else {
1753
0
            if (tree && li[i].len) {
1754
0
                proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
1755
0
            }
1756
0
            if (global_rlc_perform_reassemby) {
1757
0
                add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, true, atm);
1758
0
                next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i, atm);
1759
0
            }
1760
0
        }
1761
0
        if (next_tvb) {
1762
0
            dissected = true;
1763
0
            rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1764
0
            next_tvb = NULL;
1765
0
        }
1766
0
        offs += li[i].len;
1767
0
    }
1768
1769
    /* is there data left? */
1770
0
    if (tvb_reported_length_remaining(tvb, offs) > 0) {
1771
0
        if (tree) {
1772
0
            proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
1773
0
        }
1774
0
        if (global_rlc_perform_reassemby) {
1775
            /* add remaining data as fragment */
1776
0
            add_fragment(RLC_UM, tvb, pinfo, tree, offs, seq, i, tvb_captured_length_remaining(tvb, offs), false, atm);
1777
0
            if (dissected == false)
1778
0
                col_set_str(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]");
1779
0
        }
1780
0
    }
1781
0
    if (dissected == false)
1782
0
        col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]  SN=%u", seq);
1783
0
    else
1784
0
        if (channel == RLC_UNKNOWN_CH)
1785
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Data]  SN=%u", seq);
1786
0
}
1787
1788
static int16_t
1789
rlc_decode_li(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1790
          struct rlc_li *li, uint8_t max_li, bool li_on_2_bytes)
1791
0
{
1792
0
    uint32_t    hdr_len, offs = 0, li_offs;
1793
0
    uint8_t     ext, num_li = 0;
1794
0
    uint16_t    next_bytes, prev_li = 0;
1795
0
    proto_item *malformed;
1796
0
    uint16_t    total_len;
1797
1798
0
    switch (mode) {
1799
0
        case RLC_AM:
1800
0
            offs = 1;
1801
0
            break;
1802
0
        case RLC_UM:
1803
0
            offs = 0;
1804
0
            break;
1805
0
        case RLC_TM:
1806
            /* fall through */
1807
0
        case RLC_UNKNOWN_MODE:
1808
0
        default:
1809
0
            return -1;
1810
0
    }
1811
0
    hdr_len = offs;
1812
    /* calculate header length */
1813
0
    ext = tvb_get_uint8(tvb, hdr_len++) & 0x01;
1814
0
    while (ext) {
1815
0
        next_bytes = li_on_2_bytes ? tvb_get_ntohs(tvb, hdr_len) : tvb_get_uint8(tvb, hdr_len);
1816
0
        ext = next_bytes & 0x01;
1817
0
        hdr_len += li_on_2_bytes ? 2 : 1;
1818
0
    }
1819
0
    total_len = tvb_captured_length_remaining(tvb, hdr_len);
1820
1821
    /* do actual evaluation of LIs */
1822
0
    ext = tvb_get_uint8(tvb, offs++) & 0x01;
1823
0
    li_offs = offs;
1824
0
    while (ext) {
1825
0
        if (li_on_2_bytes) {
1826
0
            next_bytes = tvb_get_ntohs(tvb, offs);
1827
0
            offs += 2;
1828
0
        } else {
1829
0
            next_bytes = tvb_get_uint8(tvb, offs++);
1830
0
        }
1831
0
        ext = next_bytes & 0x01;
1832
0
        li[num_li].ext = ext;
1833
0
        li[num_li].li = next_bytes >> 1;
1834
1835
0
        if (li_on_2_bytes) {
1836
0
            switch (li[num_li].li) {
1837
0
                case 0x0000: /* previous segment was the last one */
1838
0
                case 0x7ffb: /* previous PDU contains last segment of SDU (minus last byte) */
1839
0
                case 0x7ffe: /* contains piggybacked STATUS in AM or segment in UM */
1840
0
                case 0x7fff: /* padding */
1841
0
                    li[num_li].len = 0;
1842
0
                    break;
1843
0
                case 0x7ffa: /* contains exactly one SDU (minus last byte), UM only */
1844
0
                case 0x7ffc: /* start of a new SDU, UM only */
1845
0
                case 0x7ffd: /* contains exactly one SDU, UM only */
1846
0
                    li[num_li].len = 0;
1847
0
                    if (mode == RLC_UM) {
1848
                        /* valid for UM */
1849
0
                        break;
1850
0
                    }
1851
                    /*invalid for AM */
1852
                    /* add malformed LI for investigation */
1853
0
                    malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1854
0
                    expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1855
0
                    return -1; /* just give up on this */
1856
0
                default:
1857
                    /* since the LI is an offset (from the end of the header), it
1858
                    * may not be larger than the total remaining length and no
1859
                    * LI may be smaller than its preceding one
1860
                    */
1861
0
                    if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1862
0
                        || (li[num_li].li < prev_li)) {
1863
                        /* add malformed LI for investigation */
1864
0
                        li[num_li].len = 0;
1865
0
                        malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1866
0
                        expert_add_info(pinfo, malformed, &ei_rlc_li_incorrect_warn);
1867
0
                        return -1; /* just give up on this */
1868
0
                    }
1869
0
                    li[num_li].len = li[num_li].li - prev_li;
1870
0
                    prev_li = li[num_li].li;
1871
0
            }
1872
0
        } else {
1873
0
            switch (li[num_li].li) {
1874
0
                case 0x00: /* previous segment was the last one */
1875
0
                case 0x7e: /* contains piggybacked STATUS in AM or segment in UM */
1876
0
                case 0x7f: /* padding */
1877
0
                    li[num_li].len = 0;
1878
0
                    break;
1879
0
                case 0x7c: /* start of a new SDU, UM only */
1880
0
                case 0x7d: /* contains exactly one SDU, UM only */
1881
0
                    li[num_li].len = 0;
1882
0
                    if (mode == RLC_UM) {
1883
                        /* valid for UM */
1884
0
                        break;
1885
0
                    }
1886
                    /*invalid for AM */
1887
                    /* add malformed LI for investigation */
1888
0
                    malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1889
0
                    expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1890
0
                    return -1; /* just give up on this */
1891
0
                default:
1892
                    /* since the LI is an offset (from the end of the header), it
1893
                    * may not be larger than the total remaining length and no
1894
                    * LI may be smaller than its preceding one
1895
                    */
1896
0
                    li[num_li].len = li[num_li].li - prev_li;
1897
0
                    if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1898
0
                        || (li[num_li].li < prev_li)) {
1899
                        /* add malformed LI for investigation */
1900
0
                        li[num_li].len = 0;
1901
0
                        malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1902
0
                        expert_add_info_format(pinfo, malformed, &ei_rlc_li_incorrect_mal, "Incorrect LI value 0x%x", li[num_li].li);
1903
0
                        return -1; /* just give up on this */
1904
0
                    }
1905
0
                    prev_li = li[num_li].li;
1906
0
            }
1907
0
        }
1908
0
        li[num_li].tree = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1909
0
        num_li++;
1910
1911
0
        if (num_li >= max_li) {
1912
            /* OK, so this is not really a malformed packet, but for now,
1913
            * we will treat it as such, so that it is marked in some way */
1914
0
            expert_add_info(pinfo, li[num_li-1].tree, &ei_rlc_li_too_many);
1915
0
            return -1;
1916
0
        }
1917
0
    }
1918
0
    return num_li;
1919
0
}
1920
1921
static void
1922
dissect_rlc_um(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1923
           proto_tree *top_level, proto_tree *tree, struct atm_phdr *atm)
1924
0
{
1925
0
#define MAX_LI 16
1926
0
    struct rlc_li  li[MAX_LI];
1927
0
    fp_info       *fpinf;
1928
0
    rlc_info      *rlcinf;
1929
0
    uint32_t       orig_num;
1930
0
    uint8_t        seq;
1931
0
    uint8_t        ext;
1932
0
    uint8_t        next_byte;
1933
0
    uint16_t       offs = 0;
1934
0
    int16_t        cur_tb, num_li  = 0;
1935
0
    bool           is_truncated, li_is_on_2_bytes;
1936
0
    proto_item    *truncated_ti;
1937
0
    bool           ciphered_according_to_rrc = false;
1938
0
    bool           ciphered_flag = false;
1939
0
    bool           deciphered_flag = false;
1940
0
    int            ciphered_data_hf;
1941
1942
1943
0
    next_byte = tvb_get_uint8(tvb, offs++);
1944
0
    seq = next_byte >> 1;
1945
1946
0
    fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1947
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1948
1949
0
    if (tree) {
1950
0
        if (fpinf && rlcinf) {
1951
            /* Add "channel" information, very useful for debugging. */
1952
0
            add_channel_info(pinfo, tree, fpinf, rlcinf);
1953
0
        }
1954
        /* show sequence number and extension bit */
1955
0
        proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 0, 7, ENC_BIG_ENDIAN);
1956
0
        proto_tree_add_bits_item(tree, hf_rlc_ext, tvb, 7, 1, ENC_BIG_ENDIAN);
1957
0
    }
1958
1959
0
    if (!fpinf || !rlcinf) {
1960
0
        proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0);
1961
0
        return;
1962
0
    }
1963
1964
0
    cur_tb = fpinf->cur_tb;
1965
0
    ciphered_according_to_rrc = is_ciphered_according_to_rrc(pinfo, fpinf, rlcinf, (uint16_t)seq);
1966
0
    ciphered_flag = rlcinf->ciphered[cur_tb];
1967
0
    deciphered_flag = rlcinf->deciphered[cur_tb];
1968
0
    if (((ciphered_according_to_rrc || ciphered_flag) && !deciphered_flag) || global_rlc_ciphered) {
1969
0
        if(global_rlc_try_decipher){
1970
0
            rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_UM);
1971
0
        }else{
1972
            /* Choosing the right field text ("LIs & Data" or just "Data") based on extension bit */
1973
0
            ext = tvb_get_uint8(tvb, 0) & 0x01;
1974
0
            ciphered_data_hf = (ext == 1) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
1975
            /* Adding ciphered payload field to tree */
1976
0
            proto_tree_add_item(tree, ciphered_data_hf, tvb, offs, -1, ENC_NA);
1977
0
            proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_ciphered_data, tvb, offs);
1978
0
            col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1979
0
            return;
1980
0
        }
1981
0
    }
1982
1983
0
    if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
1984
0
        if (rlcinf->li_size[cur_tb] == RLC_LI_VARIABLE) {
1985
0
            li_is_on_2_bytes = (tvb_reported_length(tvb) > 125) ? true : false;
1986
0
        } else {
1987
0
            li_is_on_2_bytes = (rlcinf->li_size[cur_tb] == RLC_LI_15BITS) ? true : false;
1988
0
        }
1989
0
    } else { /* Override rlcinf configuration with preference. */
1990
0
        li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? true : false;
1991
0
    }
1992
1993
1994
1995
0
    num_li = rlc_decode_li(RLC_UM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
1996
0
    if (num_li == -1) return; /* something went wrong */
1997
0
    offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
1998
1999
0
    if (global_rlc_headers_expected) {
2000
        /* There might not be any data, if only header was logged */
2001
0
        is_truncated = (tvb_captured_length_remaining(tvb, offs) == 0);
2002
0
        truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
2003
0
                                              is_truncated);
2004
0
        if (is_truncated) {
2005
0
            proto_item_set_generated(truncated_ti);
2006
0
            expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
2007
0
            return;
2008
0
        } else {
2009
0
            proto_item_set_hidden(truncated_ti);
2010
0
        }
2011
0
    }
2012
2013
    /* do not detect duplicates or reassemble, if prefiltering is done */
2014
0
    if (pinfo->num == 0) return;
2015
    /* check for duplicates */
2016
0
    if (rlc_is_duplicate(RLC_UM, pinfo, seq, &orig_num, atm) == true) {
2017
0
        col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] [Duplicate]  SN=%u", seq);
2018
0
        proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, orig_num);
2019
0
        return;
2020
0
    }
2021
0
    rlc_um_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, li, num_li, li_is_on_2_bytes, atm);
2022
0
}
2023
2024
static void
2025
dissect_rlc_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, uint16_t offset)
2026
0
{
2027
0
    uint8_t     sufi_type, bits;
2028
0
    uint64_t    len, sn, wsn, lsn, l;
2029
0
    uint16_t    value, previous_sn;
2030
0
    bool        isErrorBurstInd;
2031
0
    int         bit_offset, previous_bit_offset;
2032
0
    unsigned    i, j;
2033
0
    proto_tree *sufi_tree, *bitmap_tree, *rlist_tree;
2034
0
    proto_item *sufi_item, *ti;
2035
0
    #define BUFF_SIZE 41
2036
0
    char       *buff                     = NULL;
2037
0
    uint8_t     cw[15];
2038
0
    uint8_t     sufi_start_offset;
2039
0
    bool        seen_last                = false;
2040
0
    uint16_t    number_of_bitmap_entries = 0;
2041
2042
0
    bit_offset = offset*8 + 4; /* first SUFI type is always 4 bit shifted */
2043
2044
0
    while (!seen_last && tvb_reported_length_remaining(tvb, bit_offset/8) > 0) {
2045
        /* SUFI */
2046
0
        sufi_type = tvb_get_bits8(tvb, bit_offset, 4);
2047
0
        sufi_start_offset = bit_offset/8;
2048
0
        sufi_item = proto_tree_add_item(tree, hf_rlc_sufi, tvb, sufi_start_offset, 0, ENC_NA);
2049
0
        sufi_tree = proto_item_add_subtree(sufi_item, ett_rlc_sufi);
2050
0
        proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_type, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2051
0
        proto_item_append_text(sufi_item, " (%s)", val_to_str_const(sufi_type, rlc_sufi_vals, "Unknown"));
2052
0
        bit_offset += 4;
2053
0
        switch (sufi_type) {
2054
0
            case RLC_SUFI_NOMORE:
2055
0
                seen_last = true;
2056
0
                break;
2057
0
            case RLC_SUFI_ACK:
2058
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_lsn, tvb, bit_offset, 12, &lsn, ENC_BIG_ENDIAN);
2059
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " LSN=%u", (uint16_t)lsn);
2060
0
                proto_item_append_text(sufi_item, " LSN=%u", (uint16_t)lsn);
2061
0
                bit_offset += 12;
2062
0
                seen_last = true;
2063
0
                break;
2064
0
            case RLC_SUFI_WINDOW:
2065
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_wsn, tvb, bit_offset, 12, &wsn, ENC_BIG_ENDIAN);
2066
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " WSN=%u", (uint16_t)wsn);
2067
0
                bit_offset += 12;
2068
0
                break;
2069
0
            case RLC_SUFI_LIST:
2070
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2071
0
                col_append_fstr(pinfo->cinfo, COL_INFO,  " LIST(%u) - ", (uint8_t)len);
2072
0
                bit_offset += 4;
2073
0
                if (len) {
2074
0
                    while (len) {
2075
0
                        ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2076
0
                        proto_item_append_text(ti, " (AMD PDU not correctly received)");
2077
0
                        bit_offset += 12;
2078
0
                        ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_l, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
2079
0
                        if (l) {
2080
0
                            proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)",
2081
0
                                                   (unsigned)(sn+l)&0xfff);
2082
0
                            col_append_fstr(pinfo->cinfo, COL_INFO,  "%u-%u ", (uint16_t)sn, (unsigned)(sn+l)&0xfff);
2083
0
                        }
2084
0
                        else {
2085
0
                            col_append_fstr(pinfo->cinfo, COL_INFO,  "%u ", (uint16_t)sn);
2086
0
                        }
2087
0
                        bit_offset += 4;
2088
0
                        len--;
2089
0
                    }
2090
0
                } else {
2091
0
                    expert_add_info(pinfo, tree, &ei_rlc_sufi_len);
2092
0
                }
2093
0
                break;
2094
0
            case RLC_SUFI_BITMAP:
2095
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2096
0
                bit_offset += 4;
2097
0
                len++; /* bitmap is len + 1 */
2098
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2099
0
                bit_offset += 12;
2100
0
                proto_tree_add_item(sufi_tree, hf_rlc_sufi_bitmap, tvb, bit_offset/8, (int)len, ENC_NA);
2101
0
                bitmap_tree = proto_tree_add_subtree(sufi_tree, tvb, bit_offset/8, (int)len, ett_rlc_bitmap, &ti, "Decoded bitmap:");
2102
0
                col_append_str(pinfo->cinfo, COL_INFO, " BITMAP=(");
2103
2104
0
                buff = (char *)wmem_alloc(pinfo->pool, BUFF_SIZE);
2105
0
                for (i=0; i<len; i++) {
2106
0
                    bits = tvb_get_bits8(tvb, bit_offset, 8);
2107
0
                    for (l=0, j=0; l<8; l++) {
2108
0
                        if ((bits << l) & 0x80) {
2109
0
                            j += snprintf(&buff[j], BUFF_SIZE-j, "%4u,", (unsigned)(sn+(8*i)+l)&0xfff);
2110
0
                            col_append_fstr(pinfo->cinfo, COL_INFO, " %u", (unsigned)(sn+(8*i)+l)&0xfff);
2111
0
                            number_of_bitmap_entries++;
2112
0
                        } else {
2113
0
                            j += snprintf(&buff[j], BUFF_SIZE-j, "    ,");
2114
0
                        }
2115
0
                    }
2116
0
                    proto_tree_add_string_format(bitmap_tree, hf_rlc_bitmap_string, tvb, bit_offset/8, 1, buff, "%s", buff);
2117
0
                    bit_offset += 8;
2118
0
                }
2119
0
                proto_item_append_text(ti, " (%u SNs)", number_of_bitmap_entries);
2120
0
                col_append_str(pinfo->cinfo, COL_INFO, " )");
2121
0
                break;
2122
0
            case RLC_SUFI_RLIST:
2123
0
                previous_bit_offset = bit_offset;
2124
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2125
0
                bit_offset += 4;
2126
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2127
0
                bit_offset += 12;
2128
0
                proto_item_append_text(sufi_item, " (%u codewords)", (uint16_t)len);
2129
2130
0
                for (i=0; i<len; i++) {
2131
0
                    ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_cw, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
2132
0
                    if (l == 0x01) {
2133
0
                        proto_item_append_text(ti, " (Error burst indication)");
2134
0
                    }
2135
0
                    bit_offset += 4;
2136
0
                    cw[i] = (uint8_t)l;
2137
0
                }
2138
0
                if (len && (((cw[len-1] & 0x01) == 0) || (cw[len-1] == 0x01))) {
2139
0
                    expert_add_info(pinfo, tree, &ei_rlc_sufi_cw);
2140
0
                } else {
2141
0
                    rlist_tree = proto_tree_add_subtree(sufi_tree, tvb, previous_bit_offset/8, (bit_offset-previous_bit_offset)/8, ett_rlc_rlist, NULL, "Decoded list:");
2142
0
                    proto_tree_add_uint_format_value(rlist_tree, hf_rlc_sequence_number, tvb, (previous_bit_offset+4)/8, 12/8, (uint32_t)sn, "%u (AMD PDU not correctly received)", (unsigned)sn);
2143
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " RLIST=(%u", (unsigned)sn);
2144
2145
0
                    for (i=0, isErrorBurstInd=false, j=0, previous_sn=(uint16_t)sn, value=0; i<len; i++) {
2146
0
                        if (cw[i] == 0x01) {
2147
0
                            isErrorBurstInd = true;
2148
0
                        } else {
2149
0
                            value |= (cw[i] >> 1) << j;
2150
0
                            j += 3;
2151
0
                            if (cw[i] & 0x01) {
2152
0
                                if (isErrorBurstInd) {
2153
0
                                    previous_sn = (previous_sn + value) & 0xfff;
2154
0
                                    ti = proto_tree_add_uint(rlist_tree, hf_rlc_length, tvb, (previous_bit_offset+16+4*i)/8, 1, value);
2155
0
                                    if (value) {
2156
0
                                        proto_item_append_text(ti, "  (all consecutive AMD PDUs up to SN %u not correctly received)", previous_sn);
2157
0
                                        col_append_fstr(pinfo->cinfo, COL_INFO, " ->%u", previous_sn);
2158
0
                                    }
2159
0
                                    isErrorBurstInd = false;
2160
0
                                } else {
2161
0
                                    value = (value + previous_sn) & 0xfff;
2162
0
                                    proto_tree_add_uint_format_value(rlist_tree, hf_rlc_sequence_number, tvb, (previous_bit_offset+16+4*i)/8, 1, value, "%u (AMD PDU not correctly received)",value);
2163
0
                                    col_append_fstr(pinfo->cinfo, COL_INFO, " %u", value);
2164
0
                                    previous_sn = value;
2165
0
                                }
2166
0
                                value = j = 0;
2167
0
                            }
2168
0
                        }
2169
0
                    }
2170
0
                    col_append_str(pinfo->cinfo, COL_INFO, ")");
2171
0
                }
2172
0
                break;
2173
0
            case RLC_SUFI_MRW_ACK:
2174
0
                col_append_str(pinfo->cinfo, COL_INFO, " MRW-ACK");
2175
0
                proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2176
0
                bit_offset += 4;
2177
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_ack, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2178
0
                bit_offset += 12;
2179
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (uint16_t)sn);
2180
0
                break;
2181
0
            case RLC_SUFI_MRW:
2182
0
                col_append_str(pinfo->cinfo, COL_INFO, " MRW");
2183
0
                proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2184
0
                bit_offset += 4;
2185
0
                if (len) {
2186
0
                    while (len) {
2187
0
                        proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2188
0
                        col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (uint16_t)sn);
2189
0
                        bit_offset += 12;
2190
0
                        len--;
2191
0
                    }
2192
0
                } else {
2193
                    /* only one SN_MRW field is present */
2194
0
                    ti = proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2195
0
                    proto_item_append_text(ti, " (RLC SDU to be discarded in the Receiver extends above the configured transmission window in the Sender)");
2196
0
                    bit_offset += 12;
2197
0
                }
2198
0
                proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2199
0
                bit_offset += 4;
2200
0
                break;
2201
0
            case RLC_SUFI_POLL:
2202
0
                proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_poll_sn, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2203
0
                bit_offset += 12;
2204
0
                break;
2205
2206
0
            default:
2207
0
                expert_add_info(pinfo, tree, &ei_rlc_sufi_type);
2208
0
                return; /* invalid value, ignore the rest */
2209
0
        }
2210
2211
        /* Set extent of SUFI root */
2212
0
        proto_item_set_len(sufi_item, ((bit_offset+7)/8) - sufi_start_offset);
2213
0
    }
2214
0
}
2215
2216
static void
2217
dissect_rlc_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2218
0
{
2219
0
    uint8_t     type, next_byte;
2220
0
    proto_item *ti;
2221
0
    uint64_t    r1;
2222
0
    uint64_t    rsn, hfn;
2223
2224
0
    next_byte = tvb_get_uint8(tvb, 0);
2225
0
    type = (next_byte >> 4) & 0x07;
2226
2227
0
    ti = proto_tree_add_bits_item(tree, hf_rlc_ctrl_type, tvb, 1, 3, ENC_BIG_ENDIAN);
2228
0
    switch (type) {
2229
0
        case RLC_STATUS:
2230
0
            dissect_rlc_status(tvb, pinfo, tree, 0);
2231
0
            break;
2232
0
        case RLC_RESET:
2233
0
        case RLC_RESET_ACK:
2234
0
            col_append_str(pinfo->cinfo, COL_INFO, (type == RLC_RESET) ? " RESET" : " RESET-ACK");
2235
0
            proto_tree_add_bits_ret_val(tree, hf_rlc_rsn, tvb, 4, 1, &rsn, ENC_BIG_ENDIAN);
2236
0
            proto_tree_add_bits_ret_val(tree, hf_rlc_r1, tvb, 5, 3, &r1, ENC_BIG_ENDIAN);
2237
0
            if (r1) {
2238
0
                expert_add_info(pinfo, ti, &ei_rlc_reserved_bits_not_zero);
2239
0
                return;
2240
0
            }
2241
0
            proto_tree_add_bits_ret_val(tree, hf_rlc_hfni, tvb, 8, 20, &hfn, ENC_BIG_ENDIAN);
2242
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " RSN=%u HFN=%u", (uint16_t)rsn, (uint32_t)hfn);
2243
0
            break;
2244
0
        default:
2245
0
            expert_add_info_format(pinfo, ti, &ei_rlc_ctrl_type, "Invalid RLC AM control type %u", type);
2246
0
            return; /* invalid */
2247
0
    }
2248
0
}
2249
2250
static void
2251
rlc_am_reassemble(tvbuff_t *tvb, uint16_t offs, packet_info *pinfo,
2252
          proto_tree *tree, proto_tree *top_level,
2253
          enum rlc_channel_type channel, uint16_t seq, bool poll_set, struct rlc_li *li,
2254
          uint16_t num_li, bool final, bool li_is_on_2_bytes,
2255
          struct atm_phdr *atm)
2256
0
{
2257
0
    uint16_t  i;
2258
0
    bool      piggyback = false, dissected = false;
2259
0
    tvbuff_t *next_tvb  = NULL;
2260
2261
0
    struct rlc_channel  ch_lookup;
2262
0
    struct rlc_seqlist * endlist = NULL;
2263
0
    if( 0 == seq ){ /* assuming that a new RRC Connection is established when 0==seq.  */
2264
0
        if( -1 != rlc_channel_assign(&ch_lookup, RLC_AM, pinfo, atm ) ){
2265
0
            endlist = get_endlist(pinfo, &ch_lookup, atm);
2266
0
            endlist->list->data = GINT_TO_POINTER( -1);
2267
0
        }
2268
0
    }
2269
2270
    /* perform reassembly now */
2271
0
    for (i = 0; i < num_li; i++) {
2272
0
        if ((!li_is_on_2_bytes && (li[i].li == 0x7e)) || (li[i].li == 0x7ffe)) {
2273
            /* piggybacked status */
2274
0
            piggyback = true;
2275
0
        } else if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
2276
            /* padding, must be last LI */
2277
0
            if (tvb_reported_length_remaining(tvb, offs) > 0) {
2278
0
                if (tree) {
2279
0
                    proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, -1, ENC_NA);
2280
0
                }
2281
0
                if (i == 0) {
2282
                    /* Insert empty RLC frag so RLC doesn't miss this seq number. */
2283
0
                    add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, 0, true, atm);
2284
0
                }
2285
0
            }
2286
0
            offs += tvb_captured_length_remaining(tvb, offs);
2287
0
        } else {
2288
0
            if (tree) {
2289
0
                proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
2290
0
            }
2291
0
            if (global_rlc_perform_reassemby) {
2292
0
                add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, true, atm);
2293
0
                next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i, atm);
2294
0
            }
2295
0
        }
2296
0
        if (next_tvb) {
2297
0
            dissected = true;
2298
0
            rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2299
0
            next_tvb = NULL;
2300
0
        }
2301
0
        offs += li[i].len;
2302
0
    }
2303
2304
0
    if (piggyback) {
2305
0
        dissect_rlc_status(tvb, pinfo, tree, offs);
2306
0
    } else {
2307
0
        if (tvb_reported_length_remaining(tvb, offs) > 0) {
2308
            /* we have remaining data, which we need to mark in the tree */
2309
0
            if (tree) {
2310
0
                proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
2311
0
            }
2312
0
            if (global_rlc_perform_reassemby) {
2313
0
                add_fragment(RLC_AM, tvb, pinfo, tree, offs, seq, i,
2314
0
                    tvb_captured_length_remaining(tvb,offs), final, atm);
2315
0
                if (final) {
2316
0
                    next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i, atm);
2317
0
                }
2318
0
            }
2319
0
        }
2320
0
        if (next_tvb) {
2321
0
            dissected = true;
2322
0
            rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2323
0
            next_tvb = NULL;
2324
0
        }
2325
0
    }
2326
0
    if (dissected == false)
2327
0
        col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment]  SN=%u %s",
2328
0
                     seq, poll_set ? "(P)" : "");
2329
0
    else
2330
0
        if (channel == RLC_UNKNOWN_CH)
2331
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Data]  SN=%u %s",
2332
0
                         seq, poll_set ? "(P)" : "");
2333
0
}
2334
2335
static void
2336
dissect_rlc_am(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
2337
           proto_tree *top_level, proto_tree *tree, struct atm_phdr *atm)
2338
0
{
2339
0
#define MAX_LI 16
2340
0
    struct rlc_li  li[MAX_LI];
2341
0
    fp_info       *fpinf;
2342
0
    rlc_info      *rlcinf;
2343
0
    uint8_t        ext, dc;
2344
0
    uint8_t        next_byte;
2345
0
    uint32_t       orig_num        = 0;
2346
0
    int16_t        num_li          = 0;
2347
0
    int16_t        cur_tb;
2348
0
    uint16_t       seq, offs       = 0;
2349
0
    bool           is_truncated, li_is_on_2_bytes;
2350
0
    proto_item    *truncated_ti, *ti;
2351
0
    uint64_t       polling;
2352
0
    bool           ciphered_according_to_rrc = false;
2353
0
    bool           ciphered_flag = false;
2354
0
    bool           deciphered_flag = false;
2355
0
    int            ciphered_data_hf;
2356
2357
0
    fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2358
0
    rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2359
2360
0
    next_byte = tvb_get_uint8(tvb, offs++);
2361
0
    dc = next_byte >> 7;
2362
0
    if (tree) {
2363
0
        if (fpinf && rlcinf) {
2364
            /* Add "channel" information, very useful for debugging. */
2365
0
            add_channel_info(pinfo, tree, fpinf, rlcinf);
2366
0
        }
2367
0
        proto_tree_add_bits_item(tree, hf_rlc_dc, tvb, 0, 1, ENC_BIG_ENDIAN);
2368
0
    }
2369
0
    if (dc == 0) {
2370
0
        col_set_str(pinfo->cinfo, COL_INFO, "[RLC Control Frame]");
2371
0
        dissect_rlc_control(tvb, pinfo, tree);
2372
0
        return;
2373
0
    }
2374
2375
0
    seq = next_byte & 0x7f;
2376
0
    seq <<= 5;
2377
0
    next_byte = tvb_get_uint8(tvb, offs++);
2378
0
    seq |= (next_byte >> 3);
2379
2380
0
    ext = next_byte & 0x03;
2381
    /* show header fields */
2382
0
    proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 1, 12, ENC_BIG_ENDIAN);
2383
0
    proto_tree_add_bits_ret_val(tree, hf_rlc_p, tvb, 13, 1, &polling, ENC_BIG_ENDIAN);
2384
0
    ti = proto_tree_add_bits_item(tree, hf_rlc_he, tvb, 14, 2, ENC_BIG_ENDIAN);
2385
2386
    /* header extension may only be 00, 01 or 10 */
2387
0
    if (ext > 2) {
2388
0
        expert_add_info(pinfo, ti, &ei_rlc_he);
2389
0
        return;
2390
0
    }
2391
2392
0
    if (!fpinf || !rlcinf) {
2393
0
        proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0);
2394
0
        return;
2395
0
    }
2396
2397
0
    cur_tb = fpinf->cur_tb;
2398
    /**
2399
     * WARNING DECIPHERING IS HIGHLY EXPERIMENTAL!!!
2400
     * */
2401
0
    ciphered_according_to_rrc = is_ciphered_according_to_rrc(pinfo, fpinf, rlcinf, (uint16_t)seq);
2402
0
    ciphered_flag = rlcinf->ciphered[cur_tb];
2403
0
    deciphered_flag = rlcinf->deciphered[cur_tb];
2404
0
    if (((ciphered_according_to_rrc || ciphered_flag) && !deciphered_flag) || global_rlc_ciphered) {
2405
0
        if(global_rlc_try_decipher){
2406
0
            rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_AM);
2407
0
        }else{
2408
            /* Choosing the right field text ("LIs & Data" or just "Data") based on header extension field */
2409
0
            ciphered_data_hf = (ext == 0x01) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
2410
            /* Adding ciphered payload field to tree */
2411
0
            proto_tree_add_item(tree, ciphered_data_hf, tvb, offs, -1, ENC_NA);
2412
0
            proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_ciphered_data, tvb, offs);
2413
0
            col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
2414
0
            return;
2415
0
        }
2416
0
    }
2417
2418
0
    if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
2419
0
        if (rlcinf->li_size[cur_tb] == RLC_LI_VARIABLE) {
2420
0
            li_is_on_2_bytes = (tvb_reported_length(tvb) > 126) ? true : false;
2421
0
        } else {
2422
0
            li_is_on_2_bytes = (rlcinf->li_size[cur_tb] == RLC_LI_15BITS) ? true : false;
2423
0
        }
2424
0
    } else { /* Override rlcinf configuration with preference. */
2425
0
        li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? true : false;
2426
0
    }
2427
2428
0
    num_li = rlc_decode_li(RLC_AM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
2429
0
    if (num_li == -1) return; /* something went wrong */
2430
0
    offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
2431
0
    if (global_rlc_headers_expected) {
2432
        /* There might not be any data, if only header was logged */
2433
0
        is_truncated = (tvb_captured_length_remaining(tvb, offs) == 0);
2434
0
        truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
2435
0
                                              is_truncated);
2436
0
        if (is_truncated) {
2437
0
            proto_item_set_generated(truncated_ti);
2438
0
            expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
2439
0
            return;
2440
0
        } else {
2441
0
            proto_item_set_hidden(truncated_ti);
2442
0
        }
2443
0
    }
2444
2445
    /* do not detect duplicates or reassemble, if prefiltering is done */
2446
0
    if (pinfo->num == 0) return;
2447
    /* check for duplicates, but not if already visited */
2448
0
    if (!PINFO_FD_VISITED(pinfo) && rlc_is_duplicate(RLC_AM, pinfo, seq, &orig_num, atm) == true) {
2449
0
        g_hash_table_insert(duplicate_table, GUINT_TO_POINTER(pinfo->num), GUINT_TO_POINTER(orig_num));
2450
0
        return;
2451
0
    } else if (PINFO_FD_VISITED(pinfo) && tree) {
2452
0
        void *value = g_hash_table_lookup(duplicate_table, GUINT_TO_POINTER(pinfo->num));
2453
0
        if (value != NULL) {
2454
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] [Duplicate]  SN=%u %s", seq, (polling != 0) ? "(P)" : "");
2455
0
            proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, GPOINTER_TO_UINT(value));
2456
0
            return;
2457
0
        }
2458
0
    }
2459
2460
0
    rlc_am_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, polling != 0,
2461
0
                      li, num_li, ext == 2, li_is_on_2_bytes, atm);
2462
0
}
2463
2464
/* dissect entry functions */
2465
static int
2466
dissect_rlc_pcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2467
0
{
2468
0
    proto_tree *subtree = NULL;
2469
2470
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2471
0
    col_clear(pinfo->cinfo, COL_INFO);
2472
2473
    /* PCCH is always RLC TM */
2474
0
    if (tree) {
2475
0
        proto_item *ti;
2476
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2477
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2478
0
        proto_item_append_text(ti, " TM (PCCH)");
2479
0
    }
2480
0
    dissect_rlc_tm(RLC_PCCH, tvb, pinfo, tree, subtree);
2481
0
    return tvb_captured_length(tvb);
2482
0
}
2483
2484
static int
2485
dissect_rlc_bcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2486
0
{
2487
0
    fp_info    *fpi;
2488
0
    proto_item *ti      = NULL;
2489
0
    proto_tree *subtree = NULL;
2490
2491
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2492
0
    col_clear(pinfo->cinfo, COL_INFO);
2493
2494
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2495
0
    if (!fpi) return 0; /* dissection failure */
2496
2497
0
    if (tree) {
2498
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2499
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2500
0
    }
2501
0
    proto_item_append_text(ti, " TM (BCCH)");
2502
0
    dissect_rlc_tm(RLC_BCCH, tvb, pinfo, tree, subtree);
2503
0
    return tvb_captured_length(tvb);
2504
0
}
2505
2506
static int
2507
dissect_rlc_ccch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2508
0
{
2509
0
    fp_info    *fpi;
2510
0
    proto_item *ti      = NULL;
2511
0
    proto_tree *subtree = NULL;
2512
0
    struct atm_phdr *atm = (struct atm_phdr *)data;
2513
2514
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2515
0
    col_clear(pinfo->cinfo, COL_INFO);
2516
2517
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2518
0
    if (!fpi) return 0; /* dissection failure */
2519
2520
0
    if (tree) {
2521
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2522
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2523
0
    }
2524
2525
0
    if (fpi->is_uplink) {
2526
        /* UL CCCH is always RLC TM */
2527
0
        proto_item_append_text(ti, " TM (CCCH)");
2528
0
        dissect_rlc_tm(RLC_UL_CCCH, tvb, pinfo, tree, subtree);
2529
0
    } else {
2530
        /* DL CCCH is always UM */
2531
0
        proto_item_append_text(ti, " UM (CCCH)");
2532
0
        dissect_rlc_um(RLC_DL_CCCH, tvb, pinfo, tree, subtree, atm);
2533
0
    }
2534
0
    return tvb_captured_length(tvb);
2535
0
}
2536
2537
static int
2538
dissect_rlc_ctch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void  *data)
2539
0
{
2540
0
    fp_info    *fpi;
2541
0
    proto_item *ti      = NULL;
2542
0
    proto_tree *subtree = NULL;
2543
0
    struct atm_phdr *atm = (struct atm_phdr *)data;
2544
2545
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2546
0
    col_clear(pinfo->cinfo, COL_INFO);
2547
2548
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2549
0
    if (!fpi) return 0; /* dissection failure */
2550
2551
0
    if (tree) {
2552
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2553
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2554
0
    }
2555
2556
    /* CTCH is always UM */
2557
0
    proto_item_append_text(ti, " UM (CTCH)");
2558
0
    dissect_rlc_um(RLC_DL_CTCH, tvb, pinfo, tree, subtree, atm);
2559
0
    return tvb_captured_length(tvb);
2560
0
}
2561
2562
static int
2563
dissect_rlc_dcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2564
0
{
2565
0
    proto_item            *ti      = NULL;
2566
0
    proto_tree            *subtree = NULL;
2567
0
    fp_info               *fpi;
2568
0
    rlc_info              *rlci;
2569
0
    enum rlc_channel_type  channel;
2570
0
    struct atm_phdr       *atm = (struct atm_phdr *)data;
2571
2572
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2573
0
    col_clear(pinfo->cinfo, COL_INFO);
2574
2575
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2576
0
    rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2577
2578
0
    if (!fpi || !rlci){
2579
0
        proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0);
2580
0
        return 1;
2581
0
    }
2582
2583
0
    if (tree) {
2584
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2585
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2586
0
    }
2587
2588
0
    channel = fpi->is_uplink ? RLC_UL_DCCH : RLC_DL_DCCH;
2589
2590
0
    switch (rlci->mode[fpi->cur_tb]) {
2591
0
        case RLC_UM:
2592
0
            proto_item_append_text(ti, " UM (DCCH)");
2593
0
            dissect_rlc_um(channel, tvb, pinfo, tree, subtree, atm);
2594
0
            break;
2595
0
        case RLC_AM:
2596
0
            proto_item_append_text(ti, " AM (DCCH)");
2597
0
            dissect_rlc_am(channel, tvb, pinfo, tree, subtree, atm);
2598
0
            break;
2599
0
    }
2600
0
    return tvb_captured_length(tvb);
2601
0
}
2602
2603
static int
2604
dissect_rlc_ps_dtch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2605
0
{
2606
0
    proto_item *ti      = NULL;
2607
0
    proto_tree *subtree = NULL;
2608
0
    fp_info    *fpi;
2609
0
    rlc_info   *rlci;
2610
0
    struct atm_phdr *atm = (struct atm_phdr *)data;
2611
2612
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2613
0
    col_clear(pinfo->cinfo, COL_INFO);
2614
2615
0
    fpi  = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2616
0
    rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2617
2618
0
    if (!fpi || !rlci) {
2619
0
        proto_tree_add_expert_remaining(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0);
2620
0
        return 1;
2621
0
    }
2622
2623
0
    if (tree) {
2624
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2625
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2626
0
    }
2627
2628
0
    switch (rlci->mode[fpi->cur_tb]) {
2629
0
        case RLC_UM:
2630
0
            proto_item_append_text(ti, " UM (PS DTCH)");
2631
0
            dissect_rlc_um(RLC_PS_DTCH, tvb, pinfo, tree, subtree, atm);
2632
0
            break;
2633
0
        case RLC_AM:
2634
0
            proto_item_append_text(ti, " AM (PS DTCH)");
2635
0
            dissect_rlc_am(RLC_PS_DTCH, tvb, pinfo, tree, subtree, atm);
2636
0
            break;
2637
0
        case RLC_TM:
2638
0
            proto_item_append_text(ti, " TM (PS DTCH)");
2639
0
            dissect_rlc_tm(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
2640
0
            break;
2641
0
    }
2642
0
    return tvb_captured_length(tvb);
2643
0
}
2644
2645
static int
2646
dissect_rlc_dch_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2647
0
{
2648
0
    proto_item *ti      = NULL;
2649
0
    proto_tree *subtree = NULL;
2650
0
    fp_info    *fpi;
2651
0
    rlc_info   *rlci;
2652
0
    struct atm_phdr *atm = (struct atm_phdr *)data;
2653
2654
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2655
0
    col_clear(pinfo->cinfo, COL_INFO);
2656
2657
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2658
0
    rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2659
2660
0
    if (!fpi || !rlci) return 0;
2661
2662
0
    if (tree) {
2663
0
        ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2664
0
        subtree = proto_item_add_subtree(ti, ett_rlc);
2665
0
    }
2666
2667
0
    switch (rlci->mode[fpi->cur_tb]) {
2668
0
        case RLC_UM:
2669
0
            proto_item_append_text(ti, " UM (Unknown)");
2670
0
            dissect_rlc_um(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree, atm);
2671
0
            break;
2672
0
        case RLC_AM:
2673
0
            proto_item_append_text(ti, " AM (Unknown)");
2674
0
            dissect_rlc_am(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree, atm);
2675
0
            break;
2676
0
        case RLC_TM:
2677
0
            proto_item_append_text(ti, " TM (Unknown)");
2678
0
            dissect_rlc_tm(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
2679
0
            break;
2680
0
    }
2681
0
    return tvb_captured_length(tvb);
2682
0
}
2683
2684
static void
2685
report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
2686
                  tvbuff_t *tvb, unsigned start, unsigned length)
2687
0
{
2688
0
    proto_item *ti;
2689
0
    proto_tree *subtree;
2690
2691
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2692
0
    col_clear(pinfo->cinfo, COL_INFO);
2693
0
    ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2694
0
    subtree = proto_item_add_subtree(ti, ett_rlc);
2695
0
    proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
2696
0
}
2697
2698
/* Heuristic dissector looks for supported framing protocol (see wiki page)  */
2699
static bool
2700
dissect_rlc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2701
0
{
2702
0
    unsigned    offset             = 0;
2703
0
    fp_info    *fpi;
2704
0
    rlc_info   *rlci;
2705
0
    tvbuff_t   *rlc_tvb;
2706
0
    uint8_t     tag                = 0;
2707
0
    unsigned    channelType        = UMTS_CHANNEL_TYPE_UNSPECIFIED;
2708
0
    bool        fpInfoAlreadySet   = false;
2709
0
    bool        rlcInfoAlreadySet  = false;
2710
0
    bool        channelTypePresent = false;
2711
0
    bool        rlcModePresent     = false;
2712
0
    proto_item *ti                 = NULL;
2713
0
    proto_tree *subtree            = NULL;
2714
0
    struct atm_phdr *atm           = (struct atm_phdr *)data;
2715
2716
    /* Do this again on re-dissection to re-discover offset of actual PDU */
2717
2718
    /* Needs to be at least as long as:
2719
       - the signature string
2720
       - conditional header bytes
2721
       - tag for data
2722
       - at least one byte of RLC PDU payload */
2723
0
    if (tvb_captured_length_remaining(tvb, offset) < (unsigned)(strlen(RLC_START_STRING)+2+2)) {
2724
0
        return false;
2725
0
    }
2726
2727
    /* OK, compare with signature string */
2728
0
    if (tvb_strneql(tvb, offset, RLC_START_STRING, (unsigned)strlen(RLC_START_STRING)) != 0) {
2729
0
        return false;
2730
0
    }
2731
0
    offset += (unsigned)strlen(RLC_START_STRING);
2732
2733
    /* If redissecting, use previous info struct (if available) */
2734
0
    fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2735
0
    if (fpi == NULL) {
2736
        /* Allocate new info struct for this frame */
2737
0
        fpi = wmem_new0(wmem_file_scope(), fp_info);
2738
0
    } else {
2739
0
        fpInfoAlreadySet = true;
2740
0
    }
2741
0
    rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2742
0
    if (rlci == NULL) {
2743
        /* Allocate new info struct for this frame */
2744
0
        rlci = wmem_new0(wmem_file_scope(), rlc_info);
2745
0
    } else {
2746
0
        rlcInfoAlreadySet = true;
2747
0
    }
2748
2749
    /* Setting non-zero UE-ID for RLC reassembly to work, might be
2750
     * overriden if the optional URNTI tag is present */
2751
0
    rlci->ueid[fpi->cur_tb] = 1;
2752
2753
    /* Read conditional/optional fields */
2754
0
    while (tag != RLC_PAYLOAD_TAG) {
2755
        /* Process next tag */
2756
0
        tag = tvb_get_uint8(tvb, offset++);
2757
0
        switch (tag) {
2758
0
            case RLC_CHANNEL_TYPE_TAG:
2759
0
                channelType = tvb_get_uint8(tvb, offset);
2760
0
                offset++;
2761
0
                channelTypePresent = true;
2762
0
                break;
2763
0
            case RLC_MODE_TAG:
2764
0
                rlci->mode[fpi->cur_tb] = tvb_get_uint8(tvb, offset);
2765
0
                offset++;
2766
0
                rlcModePresent = true;
2767
0
                break;
2768
0
            case RLC_DIRECTION_TAG:
2769
0
                if (tvb_get_uint8(tvb, offset) == DIRECTION_UPLINK) {
2770
0
                    fpi->is_uplink = true;
2771
0
                    pinfo->link_dir = P2P_DIR_UL;
2772
0
                } else {
2773
0
                    fpi->is_uplink = false;
2774
0
                    pinfo->link_dir = P2P_DIR_DL;
2775
0
                }
2776
0
                offset++;
2777
0
                break;
2778
0
            case RLC_URNTI_TAG:
2779
0
                rlci->ueid[fpi->cur_tb] = tvb_get_ntohl(tvb, offset);
2780
0
                offset += 4;
2781
0
                break;
2782
0
            case RLC_RADIO_BEARER_ID_TAG:
2783
0
                rlci->rbid[fpi->cur_tb] = tvb_get_uint8(tvb, offset);
2784
0
                offset++;
2785
0
                break;
2786
0
            case RLC_LI_SIZE_TAG:
2787
0
                rlci->li_size[fpi->cur_tb] = (enum rlc_li_size) tvb_get_uint8(tvb, offset);
2788
0
                offset++;
2789
0
                break;
2790
0
            case RLC_PAYLOAD_TAG:
2791
                /* Have reached data, so get out of loop */
2792
0
                continue;
2793
0
            default:
2794
                /* It must be a recognised tag */
2795
0
                report_heur_error(tree, pinfo, &ei_rlc_unknown_udp_framing_tag, tvb, offset-1, 1);
2796
0
                return true;
2797
0
        }
2798
0
    }
2799
2800
0
    if ((channelTypePresent == false) && (rlcModePresent == false)) {
2801
        /* Conditional fields are missing */
2802
0
        report_heur_error(tree, pinfo, &ei_rlc_missing_udp_framing_tag, tvb, 0, offset);
2803
0
        return true;
2804
0
    }
2805
2806
    /* Store info in packet if needed */
2807
0
    if (!fpInfoAlreadySet) {
2808
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, fpi);
2809
0
    }
2810
0
    if (!rlcInfoAlreadySet) {
2811
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlci);
2812
0
    }
2813
2814
    /**************************************/
2815
    /* OK, now dissect as RLC             */
2816
2817
    /* Create tvb that starts at actual RLC PDU */
2818
0
    rlc_tvb = tvb_new_subset_remaining(tvb, offset);
2819
0
    switch (channelType) {
2820
0
        case UMTS_CHANNEL_TYPE_UNSPECIFIED:
2821
            /* Call relevant dissector according to RLC mode */
2822
0
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2823
0
            col_clear(pinfo->cinfo, COL_INFO);
2824
2825
0
            if (tree) {
2826
0
                ti = proto_tree_add_item(tree, proto_umts_rlc, rlc_tvb, 0, -1, ENC_NA);
2827
0
                subtree = proto_item_add_subtree(ti, ett_rlc);
2828
0
            }
2829
2830
0
            if (rlci->mode[fpi->cur_tb] == RLC_AM) {
2831
0
                proto_item_append_text(ti, " AM");
2832
0
                dissect_rlc_am(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree, atm);
2833
0
            } else if (rlci->mode[fpi->cur_tb] == RLC_UM) {
2834
0
                proto_item_append_text(ti, " UM");
2835
0
                dissect_rlc_um(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree, atm);
2836
0
            } else {
2837
0
                proto_item_append_text(ti, " TM");
2838
0
                dissect_rlc_tm(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
2839
0
            }
2840
0
            break;
2841
0
        case UMTS_CHANNEL_TYPE_PCCH:
2842
0
            dissect_rlc_pcch(rlc_tvb, pinfo, tree, data);
2843
0
            break;
2844
0
        case UMTS_CHANNEL_TYPE_CCCH:
2845
0
            dissect_rlc_ccch(rlc_tvb, pinfo, tree, data);
2846
0
            break;
2847
0
        case UMTS_CHANNEL_TYPE_DCCH:
2848
0
            dissect_rlc_dcch(rlc_tvb, pinfo, tree, data);
2849
0
            break;
2850
0
        case UMTS_CHANNEL_TYPE_PS_DTCH:
2851
0
            dissect_rlc_ps_dtch(rlc_tvb, pinfo, tree, data);
2852
0
            break;
2853
0
        case UMTS_CHANNEL_TYPE_CTCH:
2854
0
            dissect_rlc_ctch(rlc_tvb, pinfo, tree, data);
2855
0
            break;
2856
0
        case UMTS_CHANNEL_TYPE_BCCH:
2857
0
            dissect_rlc_bcch(rlc_tvb, pinfo, tree, data);
2858
0
            break;
2859
0
        default:
2860
            /* Unknown channel type */
2861
0
            return false;
2862
0
    }
2863
2864
0
    return true;
2865
0
}
2866
2867
void
2868
proto_register_rlc(void)
2869
14
{
2870
14
    module_t *rlc_module;
2871
14
    expert_module_t* expert_rlc;
2872
14
    static hf_register_info hf[] = {
2873
14
        { &hf_rlc_dc,
2874
14
          { "D/C Bit", "rlc.dc",
2875
14
            FT_BOOLEAN, BASE_NONE, TFS(&rlc_dc_val), 0, NULL, HFILL }
2876
14
        },
2877
14
        { &hf_rlc_ctrl_type,
2878
14
          { "Control PDU Type", "rlc.ctrl_pdu_type",
2879
14
            FT_UINT8, BASE_DEC, VALS(rlc_ctrl_vals), 0, NULL, HFILL }
2880
14
        },
2881
14
        { &hf_rlc_r1,
2882
14
          { "Reserved 1", "rlc.r1",
2883
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2884
14
        },
2885
14
        { &hf_rlc_rsn,
2886
14
          { "Reset Sequence Number", "rlc.rsn",
2887
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2888
14
        },
2889
14
        { &hf_rlc_hfni,
2890
14
          { "Hyper Frame Number Indicator", "rlc.hfni",
2891
14
            FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL }
2892
14
        },
2893
14
        { &hf_rlc_seq,
2894
14
          { "Sequence Number", "rlc.seq",
2895
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2896
14
        },
2897
14
        { &hf_rlc_ext,
2898
14
          { "Extension Bit", "rlc.ext",
2899
14
            FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2900
14
        },
2901
14
        { &hf_rlc_he,
2902
14
          { "Header Extension Type", "rlc.he",
2903
14
            FT_UINT8, BASE_DEC, VALS(rlc_he_vals), 0, NULL, HFILL }
2904
14
        },
2905
14
        { &hf_rlc_p,
2906
14
          { "Polling Bit", "rlc.p",
2907
14
            FT_BOOLEAN, BASE_NONE, TFS(&rlc_p_val), 0, NULL, HFILL }
2908
14
        },
2909
14
        { &hf_rlc_pad,
2910
14
          { "Padding", "rlc.padding",
2911
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2912
14
        },
2913
14
        { &hf_rlc_reassembled_data,
2914
14
          { "Reassembled RLC Data", "rlc.reassembled_data",
2915
14
            FT_BYTES, BASE_NONE, NULL, 0, "The reassembled payload", HFILL }
2916
14
        },
2917
14
        { &hf_rlc_frags,
2918
14
          { "Reassembled Fragments", "rlc.fragments",
2919
14
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2920
14
        },
2921
14
        { &hf_rlc_frag,
2922
14
          { "RLC Fragment", "rlc.fragment",
2923
14
            FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2924
14
        },
2925
14
        { &hf_rlc_duplicate_of,
2926
14
          { "Duplicate of", "rlc.duplicate_of",
2927
14
            FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2928
14
        },
2929
14
        { &hf_rlc_reassembled_in,
2930
14
          { "Reassembled Message in frame", "rlc.reassembled_in",
2931
14
            FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2932
14
        },
2933
14
        { &hf_rlc_data,
2934
14
          { "Data", "rlc.data",
2935
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2936
14
        },
2937
14
        { &hf_rlc_ciphered_data,
2938
14
          { "Ciphered Data", "rlc.ciphered_data",
2939
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2940
14
        },
2941
14
        { &hf_rlc_ciphered_lis_data,
2942
14
          { "Ciphered LIs & Data", "rlc.ciphered_data",
2943
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2944
14
        },
2945
        /* LI information */
2946
14
        { &hf_rlc_li,
2947
14
          { "LI", "rlc.li",
2948
14
            FT_NONE, BASE_NONE, NULL, 0, "Length Indicator", HFILL }
2949
14
        },
2950
14
        { &hf_rlc_li_value,
2951
14
          { "LI value", "rlc.li.value",
2952
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2953
14
        },
2954
14
        { &hf_rlc_li_ext,
2955
14
          { "LI extension bit", "rlc.li.ext",
2956
14
            FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2957
14
        },
2958
14
        { &hf_rlc_li_data,
2959
14
          { "LI Data", "rlc.li.data",
2960
14
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2961
14
        },
2962
        /* SUFI information */
2963
14
        { &hf_rlc_sufi,
2964
14
          { "SUFI", "rlc.sufi",
2965
14
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2966
14
        },
2967
14
        { &hf_rlc_sufi_type,
2968
14
          { "SUFI Type", "rlc.sufi.type",
2969
14
            FT_UINT8, BASE_DEC, VALS(rlc_sufi_vals), 0, NULL, HFILL }
2970
14
        },
2971
14
        { &hf_rlc_sufi_lsn,
2972
14
          { "Last Sequence Number", "rlc.sufi.lsn",
2973
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2974
14
        },
2975
14
        { &hf_rlc_sufi_wsn,
2976
14
          { "Window Size Number", "rlc.sufi.wsn",
2977
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2978
14
        },
2979
14
        { &hf_rlc_sufi_sn,
2980
14
          { "Sequence Number", "rlc.sufi.sn",
2981
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2982
14
        },
2983
14
        { &hf_rlc_sufi_l,
2984
14
          { "Length", "rlc.sufi.l",
2985
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2986
14
        },
2987
14
        { &hf_rlc_sufi_len,
2988
14
          { "Length", "rlc.sufi.len",
2989
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2990
14
        },
2991
14
        { &hf_rlc_sufi_fsn,
2992
14
          { "First Sequence Number", "rlc.sufi.fsn",
2993
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2994
14
        },
2995
14
        { &hf_rlc_sufi_bitmap,
2996
14
          { "Bitmap", "rlc.sufi.bitmap",
2997
14
            FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2998
14
        },
2999
14
        { &hf_rlc_sufi_cw,
3000
14
          { "Codeword", "rlc.sufi.cw",
3001
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
3002
14
        },
3003
14
        { &hf_rlc_sufi_n,
3004
14
          { "Nlength", "rlc.sufi.n",
3005
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
3006
14
        },
3007
14
        { &hf_rlc_sufi_sn_ack,
3008
14
          { "SN ACK", "rlc.sufi.sn_ack",
3009
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
3010
14
        },
3011
14
        { &hf_rlc_sufi_sn_mrw,
3012
14
          { "SN MRW", "rlc.sufi.sn_mrw",
3013
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
3014
14
        },
3015
14
        { &hf_rlc_sufi_poll_sn,
3016
14
          { "Poll SN", "rlc.sufi.poll_sn",
3017
14
            FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
3018
14
        },
3019
        /* Other information */
3020
14
        { &hf_rlc_header_only,
3021
14
          { "RLC PDU header only", "rlc.header_only",
3022
14
            FT_BOOLEAN, BASE_NONE, TFS(&rlc_header_only_val), 0 ,NULL, HFILL }
3023
14
        },
3024
14
        { &hf_rlc_channel,
3025
14
          { "Channel", "rlc.channel",
3026
14
            FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
3027
14
        },
3028
14
        { &hf_rlc_channel_rbid,
3029
14
          { "Radio Bearer ID", "rlc.channel.rbid",
3030
14
            FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
3031
14
        },
3032
14
        { &hf_rlc_channel_dir,
3033
14
          { "Direction", "rlc.channel.dir",
3034
14
            FT_UINT8, BASE_DEC, VALS(rlc_dir_vals), 0, NULL, HFILL }
3035
14
        },
3036
14
        { &hf_rlc_channel_ueid,
3037
14
          { "User Equipment ID", "rlc.channel.ueid",
3038
14
            FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
3039
14
        },
3040
14
        { &hf_rlc_sequence_number,
3041
14
          { "Sequence Number", "rlc.sequence_number",
3042
14
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
3043
14
        },
3044
14
        { &hf_rlc_length,
3045
14
          { "Length", "rlc.length",
3046
14
            FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
3047
14
        },
3048
14
        { &hf_rlc_bitmap_string,
3049
14
          { "Bitmap string", "rlc.bitmap_string",
3050
14
            FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
3051
14
        },
3052
14
    };
3053
3054
14
    static int *ett[] = {
3055
14
        &ett_rlc,
3056
14
        &ett_rlc_frag,
3057
14
        &ett_rlc_fragments,
3058
14
        &ett_rlc_sdu,
3059
14
        &ett_rlc_sufi,
3060
14
        &ett_rlc_bitmap,
3061
14
        &ett_rlc_rlist,
3062
14
        &ett_rlc_channel
3063
14
    };
3064
14
    static ei_register_info ei[] = {
3065
14
        { &ei_rlc_reassembly_fail_unfinished_sequence, { "rlc.reassembly.fail.unfinished_sequence", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because of previous unfinished sequence.", EXPFILL }},
3066
14
        { &ei_rlc_reassembly_fail_flag_set, { "rlc.reassembly.fail.flag_set", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because fail flag was set previously.", EXPFILL }},
3067
14
        { &ei_rlc_reassembly_lingering_endpoint, { "rlc.lingering_endpoint", PI_REASSEMBLE, PI_ERROR, "Lingering endpoint.", EXPFILL }},
3068
14
        { &ei_rlc_reassembly_unknown_error, { "rlc.reassembly.unknown_error", PI_REASSEMBLE, PI_ERROR, "Unknown error.", EXPFILL }},
3069
14
        { &ei_rlc_kasumi_implementation_missing, { "rlc.kasumi_implementation_missing", PI_UNDECODED, PI_WARN, "Unable to decipher packet since KASUMI implementation is missing.", EXPFILL }},
3070
14
        { &ei_rlc_li_reserved, { "rlc.li.reserved", PI_PROTOCOL, PI_WARN, "Uses reserved LI", EXPFILL }},
3071
14
        { &ei_rlc_li_incorrect_warn, { "rlc.li.incorrect", PI_PROTOCOL, PI_WARN, "Incorrect LI value", EXPFILL }},
3072
14
        { &ei_rlc_li_incorrect_mal, { "rlc.li.incorrect_mal", PI_MALFORMED, PI_ERROR, "Incorrect LI value", EXPFILL }},
3073
14
        { &ei_rlc_li_too_many, { "rlc.li.too_many", PI_MALFORMED, PI_ERROR, "Too many LI entries", EXPFILL }},
3074
14
        { &ei_rlc_header_only, { "rlc.header_only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
3075
14
        { &ei_rlc_sufi_len, { "rlc.sufi.len.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
3076
14
        { &ei_rlc_sufi_cw, { "rlc.sufi.cw.invalid", PI_PROTOCOL, PI_WARN, "Invalid last codeword", EXPFILL }},
3077
14
        { &ei_rlc_sufi_type, { "rlc.sufi.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid SUFI type", EXPFILL }},
3078
14
        { &ei_rlc_reserved_bits_not_zero, { "rlc.reserved_bits_not_zero", PI_PROTOCOL, PI_WARN, "reserved bits not zero", EXPFILL }},
3079
14
        { &ei_rlc_ctrl_type, { "rlc.ctrl_pdu_type.invalid", PI_PROTOCOL, PI_WARN, "Invalid RLC AM control type", EXPFILL }},
3080
14
        { &ei_rlc_he, { "rlc.he.invalid", PI_PROTOCOL, PI_WARN, "Incorrect HE value", EXPFILL }},
3081
14
        { &ei_rlc_ciphered_data, { "rlc.ciphered", PI_UNDECODED, PI_WARN, "Cannot dissect RLC frame because it is ciphered", EXPFILL }},
3082
14
        { &ei_rlc_no_per_frame_data, { "rlc.no_per_frame_data", PI_PROTOCOL, PI_WARN, "Can't dissect RLC frame because no per-frame info was attached!", EXPFILL }},
3083
14
        { &ei_rlc_incomplete_sequence, { "rlc.incomplete_sequence", PI_MALFORMED, PI_ERROR, "Error: Incomplete sequence", EXPFILL }},
3084
14
        { &ei_rlc_unknown_udp_framing_tag, { "rlc.unknown_udp_framing_tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3085
14
        { &ei_rlc_missing_udp_framing_tag, { "rlc.missing_udp_framing_tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3086
14
    };
3087
3088
14
    proto_umts_rlc = proto_register_protocol("Radio Link Control", "RLC", "rlc");
3089
14
    register_dissector("rlc.bcch",        dissect_rlc_bcch,        proto_umts_rlc);
3090
14
    register_dissector("rlc.pcch",        dissect_rlc_pcch,        proto_umts_rlc);
3091
14
    register_dissector("rlc.ccch",        dissect_rlc_ccch,        proto_umts_rlc);
3092
14
    register_dissector("rlc.ctch",        dissect_rlc_ctch,        proto_umts_rlc);
3093
14
    register_dissector("rlc.dcch",        dissect_rlc_dcch,        proto_umts_rlc);
3094
14
    register_dissector("rlc.ps_dtch",     dissect_rlc_ps_dtch,     proto_umts_rlc);
3095
14
    register_dissector("rlc.dch_unknown", dissect_rlc_dch_unknown, proto_umts_rlc);
3096
3097
14
    proto_register_field_array(proto_umts_rlc, hf, array_length(hf));
3098
14
    proto_register_subtree_array(ett, array_length(ett));
3099
14
    expert_rlc = expert_register_protocol(proto_umts_rlc);
3100
14
    expert_register_field_array(expert_rlc, ei, array_length(ei));
3101
3102
    /* Preferences */
3103
14
    rlc_module = prefs_register_protocol(proto_umts_rlc, NULL);
3104
3105
14
    prefs_register_obsolete_preference(rlc_module, "heuristic_rlc_over_udp");
3106
3107
14
    prefs_register_bool_preference(rlc_module, "perform_reassembly",
3108
14
        "Try to reassemble SDUs",
3109
14
        "When enabled, try to reassemble SDUs from the various PDUs received",
3110
14
        &global_rlc_perform_reassemby);
3111
3112
14
    prefs_register_bool_preference(rlc_module, "header_only_mode",
3113
14
        "May see RLC headers only",
3114
14
        "When enabled, if data is not present, don't report as an error, but instead "
3115
14
        "add expert info to indicate that headers were omitted",
3116
14
        &global_rlc_headers_expected);
3117
3118
14
    prefs_register_bool_preference(rlc_module, "ignore_rrc_cipher_indication",
3119
14
        "Ignore ciphering indication from higher layers",
3120
14
        "When enabled, RLC will ignore sequence numbers reported in 'Security Mode Command'/'Security Mode Complete' (RRC) messages when checking if frames are ciphered",
3121
14
        &global_ignore_rrc_ciphering_indication);
3122
3123
14
    prefs_register_bool_preference(rlc_module, "ciphered_data",
3124
14
        "All data is ciphered",
3125
14
        "When enabled, RLC will assume all payloads in RLC frames are ciphered",
3126
14
        &global_rlc_ciphered);
3127
3128
#ifdef HAVE_UMTS_KASUMI
3129
    prefs_register_bool_preference(rlc_module, "try_decipher",
3130
        "Try to decipher data",
3131
        "When enabled, RLC will try to decipher data. (Experimental)",
3132
        &global_rlc_try_decipher);
3133
3134
    prefs_register_string_preference(rlc_module, "kasumi_key",
3135
        "KASUMI key", "Key for kasumi 32 characters long hex-string", &global_rlc_kasumi_key);
3136
#else
3137
    /* If Wireshark isn't compiled with KASUMI we still want to register the above preferences
3138
     * We are doing so for two reasons:
3139
     * 1. To inform the user about the disabled preferences (using static text preference)
3140
     * 2. To prevent errors when Wireshark reads a preferences file which includes records for these preferences
3141
     */
3142
14
    prefs_register_static_text_preference(rlc_module, "try_decipher",
3143
14
        "Data deciphering is disabled", "Wireshark was compiled without the KASUMI decryption algorithm");
3144
3145
14
    prefs_register_obsolete_preference(rlc_module, "kasumi_key");
3146
14
#endif /* HAVE_UMTS_KASUMI */
3147
3148
14
    prefs_register_enum_preference(rlc_module, "li_size",
3149
14
        "LI size",
3150
14
        "LI size in bits, either 7 or 15 bit",
3151
14
        &global_rlc_li_size, li_size_enumvals, false);
3152
3153
14
    register_init_routine(fragment_table_init);
3154
14
    register_cleanup_routine(fragment_table_cleanup);
3155
14
}
3156
3157
void
3158
proto_reg_handoff_rlc(void)
3159
14
{
3160
14
    proto_fp = proto_get_id_by_filter_name("fp");
3161
3162
14
    rrc_handle = find_dissector_add_dependency("rrc", proto_umts_rlc);
3163
14
    ip_handle  = find_dissector_add_dependency("ip", proto_umts_rlc);
3164
14
    bmc_handle = find_dissector_add_dependency("bmc", proto_umts_rlc);
3165
    /* Add as a heuristic UDP dissector */
3166
14
    heur_dissector_add("udp", dissect_rlc_heur, "RLC over UDP", "rlc_udp", proto_umts_rlc, HEURISTIC_DISABLE);
3167
14
}
3168
3169
/*
3170
 * Editor modelines
3171
 *
3172
 * Local Variables:
3173
 * c-basic-offset: 4
3174
 * tab-width: 8
3175
 * indent-tabs-mode: nil
3176
 * End:
3177
 *
3178
 * ex: set shiftwidth=4 tabstop=8 expandtab:
3179
 * :indentSize=4:tabSize=8:noTabs=true:
3180
 */