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