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