Fix a typo
[obnox/wireshark/wip.git] / epan / dissectors / packet-rlc.c
1 /* Routines for UMTS RLC (Radio Link Control) disassembly
2  * http://www.3gpp.org/ftp/Specs/archive/25_series/25.322/
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30
31 #include <glib.h>
32
33 #include <epan/packet.h>
34 #include <epan/asn1.h>
35 #include <epan/expert.h>
36 #include <epan/prefs.h>
37 #include "packet-umts_fp.h"
38 #include "packet-umts_mac.h"
39 #include "packet-rlc.h"
40 #include "packet-rrc.h"
41
42 /* TODO:
43  *      - AM SEQ wrap case
44  *      - UM/AM 'real' reordering (final packet must appear in-order right now)
45  *      - use sub_num in fragment identification?
46  */
47
48 #define DEBUG_FRAME(number, msg) {if (pinfo->fd->num == number) printf("%u: %s\n", number, msg);}
49
50 int proto_rlc = -1;
51
52 extern int proto_fp;
53 extern int proto_malformed;
54
55 /* Preference to perform reassembly */
56 static gboolean global_rlc_perform_reassemby = TRUE;
57
58 /* Preference to expect RLC headers without payloads */
59 static gboolean global_rlc_headers_expected = FALSE;
60
61 /* Heuristic dissection */
62 static gboolean global_rlc_heur = FALSE;
63
64 /* fields */
65 static int hf_rlc_seq = -1;
66 static int hf_rlc_ext = -1;
67 static int hf_rlc_pad = -1;
68 static int hf_rlc_frags = -1;
69 static int hf_rlc_frag = -1;
70 static int hf_rlc_duplicate_of = -1;
71 static int hf_rlc_reassembled_in = -1;
72 static int hf_rlc_he = -1;
73 static int hf_rlc_dc = -1;
74 static int hf_rlc_p = -1;
75 static int hf_rlc_li = -1;
76 static int hf_rlc_li_value = -1;
77 static int hf_rlc_li_ext = -1;
78 static int hf_rlc_li_data = -1;
79 static int hf_rlc_data = -1;
80 static int hf_rlc_ctrl_type = -1;
81 static int hf_rlc_r1 = -1;
82 static int hf_rlc_rsn = -1;
83 static int hf_rlc_hfni = -1;
84 static int hf_rlc_sufi = -1;
85 static int hf_rlc_sufi_type = -1;
86 static int hf_rlc_sufi_lsn = -1;
87 static int hf_rlc_sufi_wsn = -1;
88 static int hf_rlc_sufi_sn = -1;
89 static int hf_rlc_sufi_l = -1;
90 static int hf_rlc_sufi_fsn = -1;
91 static int hf_rlc_sufi_len = -1;
92 static int hf_rlc_sufi_bitmap = -1;
93 static int hf_rlc_sufi_cw = -1;
94 static int hf_rlc_sufi_n = -1;
95 static int hf_rlc_sufi_sn_ack = -1;
96 static int hf_rlc_sufi_sn_mrw = -1;
97 static int hf_rlc_sufi_poll_sn = -1;
98 static int hf_rlc_header_only = -1;
99
100 /* subtrees */
101 static int ett_rlc = -1;
102 static int ett_rlc_frag = -1;
103 static int ett_rlc_fragments = -1;
104 static int ett_rlc_sdu = -1;
105 static int ett_rlc_sufi = -1;
106 static int ett_rlc_bitmap = -1;
107 static int ett_rlc_rlist = -1;
108
109 static dissector_handle_t ip_handle;
110 static dissector_handle_t rrc_handle;
111 static dissector_handle_t bmc_handle;
112
113 enum rlc_channel_type {
114         RLC_PCCH,
115         RLC_UL_CCCH,
116         RLC_DL_CCCH,
117         RLC_UL_DCCH,
118         RLC_DL_DCCH,
119         RLC_PS_DTCH,
120         RLC_DL_CTCH,
121         RLC_UNKNOWN_CH
122 };
123
124 static const true_false_string rlc_header_only_val = {
125         "RLC PDU header only", "RLC PDU header and body present"
126 };
127
128
129 static const true_false_string rlc_ext_val = {
130         "Next field is Length Indicator and E Bit", "Next field is data, piggybacked STATUS PDU or padding"
131 };
132
133 static const true_false_string rlc_dc_val = {
134         "Data", "Control"
135 };
136
137 static const true_false_string rlc_p_val = {
138         "Request a status report", "Status report not requested"
139 };
140
141 static const value_string rlc_he_vals[] = {
142         { 0, "The succeeding octet contains data" },
143         { 1, "The succeeding octet contains a length indicator and E bit" },
144         { 2, "The succeeding octet contains data and the last octet of the PDU is the last octet of an SDU" },
145         { 0, NULL }
146 };
147
148 #define RLC_STATUS              0x0
149 #define RLC_RESET               0x1
150 #define RLC_RESET_ACK   0x2
151 static const value_string rlc_ctrl_vals[] = {
152         { RLC_STATUS,           "Status" },
153         { RLC_RESET,            "Reset" },
154         { RLC_RESET_ACK,        "Reset Ack" },
155         { 0, NULL }
156 };
157
158 #define RLC_SUFI_NOMORE         0x0
159 #define RLC_SUFI_WINDOW         0x1
160 #define RLC_SUFI_ACK            0x2
161 #define RLC_SUFI_LIST           0x3
162 #define RLC_SUFI_BITMAP         0x4
163 #define RLC_SUFI_RLIST          0x5
164 #define RLC_SUFI_MRW            0x6
165 #define RLC_SUFI_MRW_ACK        0x7
166 #define RLC_SUFI_POLL       0x8
167 static const value_string rlc_sufi_vals[] = {
168         { RLC_SUFI_NOMORE,      "No more data" },
169         { RLC_SUFI_WINDOW,      "Window size" },
170         { RLC_SUFI_ACK,         "Acknowledgement" },
171         { RLC_SUFI_LIST,        "List" },
172         { RLC_SUFI_BITMAP,      "Bitmap" },
173         { RLC_SUFI_RLIST,       "Relative list" },
174         { RLC_SUFI_MRW,         "Move receiving window" },
175         { RLC_SUFI_MRW_ACK,     "Move receiving window acknowledgement" },
176         { RLC_SUFI_POLL,        "Poll" },
177         { 0, NULL }
178 };
179
180 /* reassembly related data */
181 static GHashTable *fragment_table = NULL;       /* maps rlc_channel -> fragmented sdu */
182 static GHashTable *reassembled_table = NULL;    /* maps fragment -> complete sdu */
183 static GHashTable *sequence_table = NULL;       /* channel -> seq */
184
185 /* identify an RLC channel, using one of two options:
186  *  - via Radio Bearer ID and U-RNTI
187  *  - via Radio Bearer ID and (VPI/VCI/CID) + Link ID
188  */
189 struct rlc_channel {
190         guint32 urnti;
191         guint16 vpi;
192         guint16 vci;
193         guint8 cid;
194         guint16 link; /* link number */
195         guint8 rbid; /* radio bearer ID */
196         guint8 dir; /* direction */
197         enum rlc_li_size li_size;
198         enum rlc_mode mode;
199 };
200
201 /* used for duplicate detection */
202 struct rlc_seq {
203         guint32 frame_num;
204         nstime_t arrival;
205         guint16 seq;
206         guint16 oc; /* overflow counter */
207 };
208
209 struct rlc_seqlist {
210         struct rlc_channel ch;
211
212         GList *list;
213 };
214
215 /* fragment representation */
216 struct rlc_frag {
217         guint32 frame_num;
218         struct rlc_channel ch;
219         guint16 seq; /* RLC sequence number */
220         guint16 li; /* LI within current RLC frame */
221         guint16 len; /* length of fragment data */
222         guint8 *data; /* store fragment data here */
223
224         struct rlc_frag *next; /* next fragment */
225 };
226
227 struct rlc_sdu {
228         tvbuff_t *tvb; /* contains reassembled tvb */
229         guint16 len; /* total length of reassembled SDU */
230         guint16 fragcnt; /* number of fragments within this SDU */
231         guint8 *data; /* reassembled data buffer */
232
233         struct rlc_frag *reassembled_in;
234         struct rlc_frag *frags; /* pointer to list of fragments */
235         struct rlc_frag *last; /* pointer to last fragment */
236 };
237
238 struct rlc_li {
239         guint16 li; /* original li */
240         guint16 len; /* length of this data fragment */
241         guint8 ext; /* extension bit value */
242
243         proto_tree *tree; /* subtree for this LI */
244 };
245
246 /* hashtable functions for fragment table
247  * rlc_channel -> SDU
248  */
249 static guint
250 rlc_channel_hash(gconstpointer key)
251 {
252         const struct rlc_channel *ch = key;
253
254         if (ch->urnti)
255                 return ch->urnti | ch->rbid | ch->mode;
256
257         return (ch->vci << 16) | (ch->link << 16) | ch->vpi | ch->vci;
258 }
259
260 static gboolean
261 rlc_channel_equal(gconstpointer a, gconstpointer b)
262 {
263         const struct rlc_channel *x = a, *y = b;
264
265         if (x->urnti || y->urnti)
266                 return x->urnti == y->urnti &&
267                         x->rbid == y->rbid &&
268                         x->mode == y->mode &&
269                         x->dir == y->dir ? TRUE : FALSE;
270
271         return x->vpi == y->vpi &&
272                 x->vci == y->vci &&
273                 x->cid == y->cid &&
274                 x->rbid == y->rbid &&
275                 x->mode == y->mode &&
276                 x->dir == y->dir &&
277                 x->link == y->link ? TRUE : FALSE;
278 }
279
280 static int
281 rlc_channel_assign(struct rlc_channel *ch, enum rlc_mode mode, packet_info *pinfo)
282 {
283         struct atm_phdr *atm;
284         rlc_info *rlcinf;
285         fp_info *fpinf;
286
287         atm = &pinfo->pseudo_header->atm;
288         fpinf = p_get_proto_data(pinfo->fd, proto_fp);
289         rlcinf = p_get_proto_data(pinfo->fd, proto_rlc);
290         if (!fpinf || !rlcinf || !atm) return -1;
291
292         if (rlcinf->urnti[fpinf->cur_tb]) {
293                 ch->urnti = rlcinf->urnti[fpinf->cur_tb];
294                 ch->vpi = ch->vci = ch->link = ch->cid = 0;
295         } else {
296                 ch->urnti = 0;
297                 ch->vpi = atm->vpi;
298                 ch->vci = atm->vci;
299                 ch->cid = atm->aal2_cid;
300                 ch->link = pinfo->link_number;
301         }
302         ch->rbid = rlcinf->rbid[fpinf->cur_tb];
303         ch->dir = pinfo->p2p_dir;
304         ch->mode = mode;
305         ch->li_size = rlcinf->li_size[fpinf->cur_tb];
306
307         return 0;
308 }
309
310 static struct rlc_channel *
311 rlc_channel_create(enum rlc_mode mode, packet_info *pinfo)
312 {
313         struct rlc_channel *ch;
314         int rv;
315
316         ch = g_malloc0(sizeof(struct rlc_channel));
317         rv = rlc_channel_assign(ch, mode, pinfo);
318
319         if (rv != 0) {
320                 /* channel assignment failed */
321                 g_free(ch);
322                 ch = NULL;
323         }
324         return ch;
325 }
326
327 static void
328 rlc_channel_delete(gpointer data)
329 {
330         g_free(data);
331 }
332
333 /* hashtable functions for reassembled table
334  * fragment -> SDU
335  */
336 static guint
337 rlc_frag_hash(gconstpointer key)
338 {
339         const struct rlc_frag *frag = key;
340         return rlc_channel_hash(&frag->ch) | frag->li | frag->seq;
341 }
342
343 static gboolean
344 rlc_frag_equal(gconstpointer a, gconstpointer b)
345 {
346         const struct rlc_frag *x = a, *y = b;
347
348         return rlc_channel_equal(&x->ch, &y->ch) &&
349                 x->seq == y->seq &&
350                 x->frame_num == y->frame_num &&
351                 x->li == y->li ? TRUE : FALSE;
352 }
353
354
355 static struct rlc_sdu *
356 rlc_sdu_create(void)
357 {
358         struct rlc_sdu *sdu;
359         sdu = se_alloc0(sizeof(struct rlc_sdu));
360         return sdu;
361 }
362
363 static void
364 rlc_frag_delete(gpointer data)
365 {
366         struct rlc_frag *frag = data;
367         if (frag->data) {
368                 g_free(frag->data);
369                 frag->data = NULL;
370         }
371 }
372
373 static void
374 rlc_sdu_frags_delete(gpointer data)
375 {
376         struct rlc_sdu *sdu = data;
377         struct rlc_frag *frag;
378
379         frag = sdu->frags;
380         while (frag) {
381                 if (frag->data) {
382                         g_free(frag->data);
383                 }
384                 frag->data = NULL;
385                 frag = frag->next;
386         }
387 }
388
389 static int
390 rlc_frag_assign(struct rlc_frag *frag, enum rlc_mode mode, packet_info *pinfo,
391                 guint16 seq, guint16 li)
392 {
393         frag->frame_num = pinfo->fd->num;
394         frag->seq = seq;
395         frag->li = li;
396         frag->len = 0;
397         frag->data = NULL;
398         rlc_channel_assign(&frag->ch, mode, pinfo);
399
400         return 0;
401 }
402
403 static int
404 rlc_frag_assign_data(struct rlc_frag *frag, tvbuff_t *tvb,
405                      guint16 offset, guint16 length)
406 {
407         frag->len = length;
408         frag->data = g_malloc(length);
409         tvb_memcpy(tvb, frag->data, offset, length);
410         return 0;
411 }
412
413 static struct rlc_frag *
414 rlc_frag_create(tvbuff_t *tvb, enum rlc_mode mode, packet_info *pinfo,
415                 guint16 offset, guint16 length, guint16 seq, guint16 li)
416 {
417         struct rlc_frag *frag;
418         frag = se_alloc0(sizeof(struct rlc_frag));
419         rlc_frag_assign(frag, mode, pinfo, seq, li);
420         rlc_frag_assign_data(frag, tvb, offset, length);
421
422         return frag;
423 }
424
425 static int
426 rlc_cmp_seq(gconstpointer a, gconstpointer b)
427 {
428         const struct rlc_seq *_a = a, *_b = b;
429
430         return  _a->seq < _b->seq ? -1 :
431                         _a->seq > _b->seq ?  1 :
432                         0;
433 }
434
435 /* callback function to use for g_hash_table_foreach_remove()
436  * always return TRUE (=always delete the entry)
437  * this is required for backwards compatibility
438  * with older versions of glib which do not have
439  * a g_hash_table_remove_all() (because of this,
440  * hashtables are emptied using g_hash_table_foreach_remove()
441  * in conjunction with this funcion)
442  */
443 static gboolean
444 free_table_entry(gpointer key _U_, gpointer value _U_, gpointer user_data _U_)
445 {
446         return TRUE;
447 }
448
449 /* "Value destroy" function called each time an entry is removed
450  *  from the sequence_table hash.
451  * It frees the GList pointed to by the entry.
452  */
453 static void
454 free_sequence_table_entry_data(gpointer data)
455 {
456         struct rlc_seqlist *list = data;
457         if (list->list != NULL) {
458                 g_list_free(list->list);
459                 list->list = NULL;   /* for good measure */
460         }
461 }
462
463 static void
464 fragment_table_init(void)
465 {
466         if (fragment_table) {
467                 g_hash_table_foreach_remove(fragment_table, free_table_entry, NULL);
468                 g_hash_table_destroy(fragment_table);
469         }
470         if (reassembled_table) {
471                 g_hash_table_foreach_remove(reassembled_table, free_table_entry, NULL);
472                 g_hash_table_destroy(reassembled_table);
473         }
474         if (sequence_table) {
475                 /* Note: "value destroy" function will be called for each removed hash table entry */
476                 g_hash_table_foreach_remove(sequence_table, free_table_entry, NULL);
477                 g_hash_table_destroy(sequence_table);
478         }
479         fragment_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal,
480                 rlc_channel_delete, rlc_sdu_frags_delete);
481         reassembled_table = g_hash_table_new_full(rlc_frag_hash, rlc_frag_equal,
482                 rlc_frag_delete, rlc_sdu_frags_delete);
483         sequence_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal,
484                 NULL, free_sequence_table_entry_data);
485 }
486
487 /* add the list of fragments for this sdu to 'tree' */
488 static void
489 tree_add_fragment_list(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
490 {
491         proto_item *ti;
492         proto_tree *frag_tree;
493         guint16 offset;
494         struct rlc_frag *sdufrag;
495         ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, -1, ENC_NA);
496         frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
497         proto_item_append_text(ti, " (%u bytes, %u fragments): ",
498                 sdu->len, sdu->fragcnt);
499         sdufrag = sdu->frags;
500         offset = 0;
501         while (sdufrag) {
502                 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
503                         sdufrag->len, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
504                         sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
505                 offset += sdufrag->len;
506                 sdufrag = sdufrag->next;
507         }
508 }
509
510 /* add the list of fragments for this sdu to 'tree' */
511 static void
512 tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
513 {
514         proto_item *ti;
515         proto_tree *frag_tree;
516         guint16 offset;
517         struct rlc_frag *sdufrag;
518         ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, ENC_NA);
519         frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
520         proto_item_append_text(ti, " (%u bytes, %u fragments): ",
521                 sdu->len, sdu->fragcnt);
522         sdufrag = sdu->frags;
523         offset = 0;
524         while (sdufrag) {
525                 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0,
526                         0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
527                         sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
528                 offset += sdufrag->len;
529                 sdufrag = sdufrag->next;
530         }
531 }
532
533 /* Add the same description to too the two given proto_items */
534 static void add_description(proto_item *li_ti, proto_item *length_ti,
535                                      const char *format, ...)
536 {
537     #define MAX_INFO_BUFFER 256
538     static char info_buffer[MAX_INFO_BUFFER];
539
540     va_list ap;
541
542     va_start(ap, format);
543     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
544     va_end(ap);
545
546     proto_item_append_text(li_ti, " (%s)", info_buffer);
547     proto_item_append_text(length_ti, " (%s)", info_buffer);
548 }
549
550 /* add information for an LI to 'tree' */
551 static proto_tree *
552 tree_add_li(enum rlc_mode mode, struct rlc_li *li, guint8 li_idx, guint8 hdr_offs,
553             gboolean li_is_on_2_bytes, tvbuff_t *tvb, proto_tree *tree)
554 {
555         proto_item *root_ti, *ti;
556         proto_tree *li_tree;
557         guint8 li_offs;
558         guint64 length;
559
560         if (!tree) return NULL;
561
562         if (li_is_on_2_bytes) {
563                 li_offs = hdr_offs + li_idx*2;
564                 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 2, ENC_NA);
565                 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
566                 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 15, &length, ENC_BIG_ENDIAN);
567
568                 switch (li->li) {
569                         case 0x0000:
570                                 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");
571                                 break;
572                         case 0x7ffa:
573                                 if (mode == RLC_UM) {
574                                         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");
575                                 } else {
576                                         add_description(root_ti, ti, "Reserved");
577                                 }
578                                 break;
579                         case 0x7ffb:
580                                 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");
581                                 break;
582                         case 0x7ffc:
583                                 if (mode == RLC_UM) {
584                                         add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
585                                 } else {
586                                         add_description(root_ti, ti, "Reserved");
587                                 }
588                                 break;
589                         case 0x7ffd:
590                                 if (mode == RLC_UM) {
591                                         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");
592                                 } else {
593                                         add_description(root_ti, ti, "Reserved");
594                                 }
595                                 break;
596                         case 0x7ffe:
597                                 if (mode == RLC_UM) {
598                                         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");
599                                 } else {
600                                         add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
601                                 }
602                                 break;
603                         case 0x7fff:
604                                 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
605                                 break;
606
607                         default:
608                                 add_description(root_ti, ti, "length=%u", (guint16)length);
609                                 break;
610                 }
611                 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+15, 1, ENC_BIG_ENDIAN);
612         } else {
613                 li_offs = hdr_offs + li_idx;
614                 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 1, ENC_NA);
615                 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
616                 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 7, &length, ENC_BIG_ENDIAN);
617                 switch (li->li) {
618                         case 0x00:
619                                 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");
620                                 break;
621                         case 0x7c:
622                                 if (mode == RLC_UM) {
623                                         add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
624                                 } else {
625                                         add_description(root_ti, ti, "Reserved");
626                                 }
627                                 break;
628                         case 0x7d:
629                                 if (mode == RLC_UM) {
630                                         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");
631                                 } else {
632                                         add_description(root_ti, ti, "Reserved");
633                                 }
634                                 break;
635                         case 0x7e:
636                                 if (mode == RLC_UM) {
637                                         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");
638                                 } else {
639                                         add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
640                                 }
641                                 break;
642                         case 0x7f:
643                                 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
644                                 break;
645
646                         default:
647                                 add_description(root_ti, ti, "length=%u", (guint16)length);
648                                 break;
649                 }
650                 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+7, 1, ENC_BIG_ENDIAN);
651         }
652
653         if (li->len > 0) {
654                 if (li->li > tvb_length_remaining(tvb, hdr_offs)) return li_tree;
655                 if (li->len > li->li) return li_tree;
656                 ti = proto_tree_add_item(li_tree, hf_rlc_li_data, tvb, hdr_offs + li->li - li->len, li->len, ENC_NA);
657                 PROTO_ITEM_SET_HIDDEN(ti);
658         }
659
660         return li_tree;
661 }
662
663 /* add a fragment to an SDU */
664 static int
665 rlc_sdu_add_fragment(enum rlc_mode mode, struct rlc_sdu *sdu, struct rlc_frag *frag)
666 {
667         struct rlc_frag *tmp;
668
669         if (!sdu->frags) {
670                 /* insert as first element */
671                 sdu->frags = frag;
672                 sdu->last = frag;
673                 sdu->fragcnt++;
674                 sdu->len += frag->len;
675                 return 0;
676         }
677         switch (mode) {
678                 case RLC_UM:
679                         /* insert as last element */
680                         sdu->last->next = frag;
681                         frag->next = NULL;
682                         sdu->last = frag;
683                         sdu->len += frag->len;
684                         break;
685                 case RLC_AM:
686                         /* insert ordered */
687                         tmp = sdu->frags;
688                         if (frag->seq < tmp->seq) {
689                                 /* insert as first element */
690                                 frag->next = tmp;
691                                 sdu->frags = frag;
692                         } else {
693                                 while (tmp->next && tmp->next->seq < frag->seq)
694                                         tmp = tmp->next;
695                                 frag->next = tmp->next;
696                                 tmp->next = frag;
697                                 if (frag->next == NULL) sdu->last = frag;
698                         }
699                         sdu->len += frag->len;
700                         break;
701                 default:
702                         return -2;
703         }
704         sdu->fragcnt++;
705         return 0;
706 }
707
708 static void
709 reassemble_message(struct rlc_channel *ch, struct rlc_sdu *sdu, struct rlc_frag *frag)
710 {
711         struct rlc_frag *temp;
712         guint16 offs = 0;
713
714         if (!sdu || !ch || !sdu->frags) return;
715
716         if (sdu->data) return; /* already assembled */
717
718         if (frag)
719                 sdu->reassembled_in = frag;
720         else
721                 sdu->reassembled_in = sdu->last;
722
723         sdu->data = se_alloc(sdu->len);
724
725         temp = sdu->frags;
726         while (temp) {
727                 memcpy(sdu->data + offs, temp->data, temp->len);
728                 /* mark this fragment in reassembled table */
729                 g_hash_table_insert(reassembled_table, temp, sdu);
730
731                 offs += temp->len;
732                 temp = temp->next;
733         }
734         g_hash_table_remove(fragment_table, ch);
735 }
736
737 /* add a new fragment to an SDU
738  * if length == 0, just finalize the specified SDU
739  */
740 static struct rlc_frag *
741 add_fragment(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
742              proto_tree *tree, guint16 offset, guint16 seq, guint16 num_li,
743              guint16 len, gboolean final)
744 {
745         struct rlc_channel ch_lookup;
746         struct rlc_frag frag_lookup, *frag = NULL, *tmp;
747         gpointer orig_frag, orig_sdu;
748         struct rlc_sdu *sdu;
749
750         rlc_channel_assign(&ch_lookup, mode, pinfo);
751         rlc_frag_assign(&frag_lookup, mode, pinfo, seq, num_li);
752
753         /* look for an already assembled SDU */
754         if (g_hash_table_lookup_extended(reassembled_table, &frag_lookup,
755             &orig_frag, &orig_sdu)) {
756                 /* this fragment is already reassembled somewhere */
757                 frag = orig_frag;
758                 sdu = orig_sdu;
759                 if (tree) {
760                         /* mark the fragment, if reassembly happened somewhere else */
761                         if (frag->seq != sdu->reassembled_in->seq ||
762                                 frag->li != sdu->reassembled_in->li)
763                                 proto_tree_add_uint(tree, hf_rlc_reassembled_in, tvb, 0, 0,
764                                         sdu->reassembled_in->frame_num);
765                 }
766                 return frag;
767         }
768
769         /* if not already reassembled, search for a fragment entry */
770         sdu = g_hash_table_lookup(fragment_table, &ch_lookup);
771
772         if (final && len == 0) {
773                 /* just finish this SDU */
774                 if (sdu) {
775                         frag = rlc_frag_create(tvb, mode, pinfo, offset, len, seq, num_li);
776                         rlc_sdu_add_fragment(mode, sdu, frag);
777                         reassemble_message(&ch_lookup, sdu, frag);
778                 }
779                 return NULL;
780         }
781         /* create the SDU entry, if it does not already exist */
782         if (!sdu) {
783                 /* this the first observed fragment of an SDU */
784                 struct rlc_channel *ch;
785                 ch = rlc_channel_create(mode, pinfo);
786                 sdu = rlc_sdu_create();
787                 g_hash_table_insert(fragment_table, ch, sdu);
788         }
789
790         /* check whether we have seen this fragment already */
791         tmp = sdu->frags;
792         while (tmp) {
793                 if (rlc_frag_equal(&frag_lookup, tmp) == TRUE)
794                         return tmp;
795                 tmp = tmp->next;
796         }
797         frag = rlc_frag_create(tvb, mode, pinfo, offset, len, seq, num_li);
798         rlc_sdu_add_fragment(mode, sdu, frag);
799         if (final) {
800                 reassemble_message(&ch_lookup, sdu, frag);
801         }
802         return frag;
803 }
804
805 /* is_data is used to identify rlc data parts that are not identified by an LI, but are at the end of
806  * the RLC frame
807  * these can be valid reassembly points, but only if the LI of the *next* relevant RLC frame is
808  * set to '0' (this is indicated in the reassembled SDU
809  */
810 static tvbuff_t *
811 get_reassembled_data(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
812                      proto_tree *tree, guint16 seq, guint16 num_li)
813 {
814         gpointer orig_frag, orig_sdu;
815         struct rlc_sdu *sdu;
816         struct rlc_frag lookup, *frag;
817
818         rlc_frag_assign(&lookup, mode, pinfo, seq, num_li);
819
820         if (!g_hash_table_lookup_extended(reassembled_table, &lookup,
821             &orig_frag, &orig_sdu))
822                 return NULL;
823
824         frag = orig_frag;
825         sdu = orig_sdu;
826         if (!sdu || !sdu->data)
827                 return NULL;
828
829         /* TODO */
830 #if 0
831         if (!rlc_frag_equal(&lookup, sdu->reassembled_in)) return NULL;
832 #endif
833
834         if (tree) {
835                 frag = sdu->frags;
836                 while (frag->next) {
837                         if (frag->next->seq - frag->seq > 1) {
838                                 proto_item *pi = proto_tree_add_text(tree, tvb, 0, 0,
839                                         "Error: Incomplete sequence");
840                                 PROTO_ITEM_SET_GENERATED(pi);
841                                 tree_add_fragment_list_incomplete(sdu, tvb, tree);
842                                 return NULL;
843                         }
844                         frag = frag->next;
845                 }
846         }
847         sdu->tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->len, sdu->len);
848         add_new_data_source(pinfo, sdu->tvb, "Reassembled RLC Message");
849
850         /* reassembly happened here, so create the fragment list */
851         if (tree)
852                 tree_add_fragment_list(sdu, sdu->tvb, tree);
853
854         return sdu->tvb;
855 }
856
857 #define RLC_RETRANSMISSION_TIMEOUT 5 /* in seconds */
858 static gboolean
859 rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, guint16 seq,
860                  guint32 *original)
861 {
862         GList *element;
863         struct rlc_seqlist lookup, *list;
864         struct rlc_seq seq_item, *seq_new;
865
866         rlc_channel_assign(&lookup.ch, mode, pinfo);
867         list = g_hash_table_lookup(sequence_table, &lookup.ch);
868         if (!list) {
869                 /* we see this channel for the first time */
870                 list = se_alloc0(sizeof(*list));
871                 rlc_channel_assign(&list->ch, mode, pinfo);
872                 g_hash_table_insert(sequence_table, &list->ch, list);
873         }
874         seq_item.seq = seq;
875         seq_item.frame_num = pinfo->fd->num;
876
877         element = g_list_find_custom(list->list, &seq_item, rlc_cmp_seq);
878         if (element) {
879                 seq_new = element->data;
880                 if (seq_new->frame_num != seq_item.frame_num) {
881                         nstime_t delta;
882                         nstime_delta(&delta, &pinfo->fd->abs_ts, &seq_new->arrival);
883                         if (delta.secs < RLC_RETRANSMISSION_TIMEOUT) {
884                                 if (original)
885                                         *original = seq_new->frame_num;
886                                 return TRUE;
887                         }
888                         return FALSE;
889                 }
890                 return FALSE; /* we revisit the seq that was already seen */
891         }
892         seq_new = se_alloc0(sizeof(struct rlc_seq));
893         *seq_new = seq_item;
894         seq_new->arrival = pinfo->fd->abs_ts;
895         list->list = g_list_insert_sorted(list->list, seq_new, rlc_cmp_seq);
896         return FALSE;
897 }
898
899 static void
900 rlc_call_subdissector(enum rlc_channel_type channel, tvbuff_t *tvb,
901                       packet_info *pinfo, proto_tree *tree)
902 {
903         enum rrc_message_type msgtype;
904
905         switch (channel) {
906                 case RLC_UL_CCCH:
907                         msgtype = RRC_MESSAGE_TYPE_UL_CCCH;
908                         break;
909                 case RLC_DL_CCCH:
910                         msgtype = RRC_MESSAGE_TYPE_DL_CCCH;
911                         break;
912                 case RLC_DL_CTCH:
913                         msgtype = RRC_MESSAGE_TYPE_INVALID;
914                         call_dissector(bmc_handle, tvb, pinfo, tree);
915                         break;
916                 case RLC_UL_DCCH:
917                         msgtype = RRC_MESSAGE_TYPE_UL_DCCH;
918                         break;
919                 case RLC_DL_DCCH:
920                         msgtype = RRC_MESSAGE_TYPE_DL_DCCH;
921                         break;
922                 case RLC_PCCH:
923                         msgtype = RRC_MESSAGE_TYPE_PCCH;
924                         break;
925                 case RLC_PS_DTCH:
926                         msgtype = RRC_MESSAGE_TYPE_INVALID;
927                         /* assume transparent PDCP for now */
928                         call_dissector(ip_handle, tvb, pinfo, tree);
929                         break;
930                 default:
931                         return; /* abort */
932         }
933         if (msgtype != RRC_MESSAGE_TYPE_INVALID) {
934                 struct rrc_info *rrcinf;
935                 fp_info *fpinf;
936                 fpinf = p_get_proto_data(pinfo->fd, proto_fp);
937                 rrcinf = p_get_proto_data(pinfo->fd, proto_rrc);
938                 if (!rrcinf) {
939                         rrcinf = se_alloc0(sizeof(struct rrc_info));
940                         p_add_proto_data(pinfo->fd, proto_rrc, rrcinf);
941                 }
942                 rrcinf->msgtype[fpinf->cur_tb] = msgtype;
943                 call_dissector(rrc_handle, tvb, pinfo, tree);
944                 /* once the packet has been dissected, protect it from further changes */
945                 col_set_writable(pinfo->cinfo, FALSE);
946         }
947 }
948
949 static void
950 dissect_rlc_tm(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
951                proto_tree *top_level, proto_tree *tree)
952 {
953         if (tree) {
954                 proto_tree_add_item(tree, hf_rlc_data, tvb, 0, -1, ENC_NA);
955         }
956         rlc_call_subdissector(channel, tvb, pinfo, top_level);
957 }
958
959
960 static void
961 rlc_um_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo, proto_tree *tree,
962                   proto_tree *top_level, enum rlc_channel_type channel, guint16 seq,
963                   struct rlc_li *li, guint16 num_li, gboolean li_is_on_2_bytes)
964 {
965         guint8 i;
966         gboolean dissected = FALSE;
967         gint length;
968         tvbuff_t *next_tvb = NULL;
969         /* perform reassembly now */
970         for (i = 0; i < num_li; i++) {
971                 if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
972                         /* padding, must be last LI */
973                         if (tree) {
974                                 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, -1, ENC_NA);
975                         }
976                         offs += tvb_length_remaining(tvb, offs);
977                 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7c)) || (li[i].li == 0x7ffc)) {
978                         /* a new SDU starts here, nothing to do */
979                 } else if (li[i].li == 0x7ffa) {
980                         /* the first data octet in this RLC PDU is the first octet of an RLC SDU
981                            and the second last octet in this RLC PDU is the last octet of the same RLC SDU */
982                         length = tvb_length_remaining(tvb, offs);
983                         if (length > 1) {
984                                 length--;
985                                 if (tree && length) {
986                                         proto_tree_add_item(tree, hf_rlc_data, tvb, offs, length, ENC_NA);
987                                 }
988                                 if (global_rlc_perform_reassemby) {
989                                         add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, length, TRUE);
990                                         next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, li[i].tree, seq, i);
991                                 }
992                                 offs += length;
993                         }
994                         if (tree) {
995                                 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, 1, ENC_NA);
996                         }
997                         offs += 1;
998                 } else {
999                         if (tree && li[i].len) {
1000                                 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
1001                         }
1002                         if (global_rlc_perform_reassemby) {
1003                                 add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE);
1004                                 next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, li[i].tree, seq, i);
1005                         }
1006                 }
1007                 if (next_tvb) {
1008                         dissected = TRUE;
1009                         rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1010                         next_tvb = NULL;
1011                 }
1012                 offs += li[i].len;
1013         }
1014
1015         /* is there data left? */
1016         if (tvb_length_remaining(tvb, offs) > 0) {
1017                 if (tree) {
1018                         proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
1019                 }
1020                 if (global_rlc_perform_reassemby) {
1021                         /* add remaining data as fragment */
1022                         add_fragment(RLC_UM, tvb, pinfo, tree, offs, seq, i, tvb_length_remaining(tvb, offs), FALSE);
1023                         if (dissected == FALSE)
1024                                 col_set_str(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]");
1025                 }
1026         }
1027         if (dissected == FALSE)
1028                 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]  SN=%u", seq);
1029         else
1030                 if (channel == RLC_UNKNOWN_CH)
1031                         col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Data]  SN=%u", seq);
1032 }
1033
1034 static gint16
1035 rlc_decode_li(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1036               struct rlc_li *li, guint8 max_li, gboolean li_on_2_bytes)
1037 {
1038         guint8 ext, hdr_len, offs = 0, num_li = 0, li_offs;
1039         guint16 next_bytes, prev_li = 0;
1040         proto_item *malformed;
1041         guint16 total_len;
1042
1043         switch (mode) {
1044                 case RLC_AM: offs = 1; break;
1045                 case RLC_UM: offs = 0; break;
1046                 case RLC_TM: return -1;
1047         }
1048         hdr_len = offs;
1049         /* calculate header length */
1050         ext = tvb_get_guint8(tvb, hdr_len++) & 0x01;
1051         while (ext) {
1052                 next_bytes = li_on_2_bytes ? tvb_get_ntohs(tvb, hdr_len) : tvb_get_guint8(tvb, hdr_len);
1053                 ext = next_bytes & 0x01;
1054                 hdr_len += li_on_2_bytes ? 2 : 1;
1055         }
1056         total_len = tvb_length_remaining(tvb, hdr_len);
1057
1058         /* do actual evaluation of LIs */
1059         ext = tvb_get_guint8(tvb, offs++) & 0x01;
1060         li_offs = offs;
1061         while (ext) {
1062                 if (li_on_2_bytes) {
1063                         next_bytes = tvb_get_ntohs(tvb, offs);
1064                         offs += 2;
1065                 } else {
1066                         next_bytes = tvb_get_guint8(tvb, offs++);
1067                 }
1068                 ext = next_bytes & 0x01;
1069                 li[num_li].ext = ext;
1070                 li[num_li].li = next_bytes >> 1;
1071
1072                 if (li_on_2_bytes) {
1073                         switch (li[num_li].li) {
1074                                 case 0x0000: /* previous segment was the last one */
1075                                 case 0x7ffb: /* previous PDU contains last segment of SDU (minus last byte) */
1076                                 case 0x7ffe: /* contains piggybacked STATUS in AM or segment in UM */
1077                                 case 0x7fff: /* padding */
1078                                         li[num_li].len = 0;
1079                                         break;
1080                                 case 0x7ffa: /* contains exactly one SDU (minus last byte), UM only */
1081                                 case 0x7ffc: /* start of a new SDU, UM only */
1082                                 case 0x7ffd: /* contains exactly one SDU, UM only */
1083                                         if (mode == RLC_UM) {
1084                                                 /* valid for UM */
1085                                                 li[num_li].len = 0;
1086                                                 break;
1087                                         }
1088                                         /*invalid for AM */
1089                                         /* add malformed LI for investigation */
1090                                         tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1091                                         malformed = proto_tree_add_protocol_format(tree,
1092                                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1093                                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1094                                                 "Malformed Packet (Uses reserved LI)");
1095                                         col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1096                                         return -1; /* just give up on this */
1097                                 default:
1098                                         /* since the LI is an offset (from the end of the header), it
1099                                         * may not be larger than the total remaining length and no
1100                                         * LI may be smaller than its preceding one
1101                                         */
1102                                         if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1103                                                 || (li[num_li].li < prev_li)) {
1104                                                 /* add malformed LI for investigation */
1105                                                 tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1106                                                 malformed = proto_tree_add_protocol_format(tree,
1107                                                         proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1108                                                 expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1109                                                         "Malformed Packet (incorrect LI value)");
1110                                                 col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1111                                                 return -1; /* just give up on this */
1112                                         }
1113                                         li[num_li].len = li[num_li].li - prev_li;
1114                                         prev_li = li[num_li].li;
1115                         }
1116                 } else {
1117                         switch (li[num_li].li) {
1118                                 case 0x00: /* previous segment was the last one */
1119                                 case 0x7e: /* contains piggybacked STATUS in AM or segment in UM */
1120                                 case 0x7f: /* padding */
1121                                         li[num_li].len = 0;
1122                                         break;
1123                                 case 0x7c: /* start of a new SDU, UM only */
1124                                 case 0x7d: /* contains exactly one SDU, UM only */
1125                                         if (mode == RLC_UM) {
1126                                                 /* valid for UM */
1127                                                 li[num_li].len = 0;
1128                                                 break;
1129                                         }
1130                                         /*invalid for AM */
1131                                         /* add malformed LI for investigation */
1132                                         tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1133                                         malformed = proto_tree_add_protocol_format(tree,
1134                                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1135                                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1136                                                 "Malformed Packet (Uses reserved LI)");
1137                                         col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1138                                         return -1; /* just give up on this */
1139                                 default:
1140                                         /* since the LI is an offset (from the end of the header), it
1141                                         * may not be larger than the total remaining length and no
1142                                         * LI may be smaller than its preceding one
1143                                         */
1144                                         if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1145                                                 || (li[num_li].li < prev_li)) {
1146                                                 /* add malformed LI for investigation */
1147                                                 tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1148                                                 malformed = proto_tree_add_protocol_format(tree,
1149                                                         proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1150                                                 expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1151                                                         "Malformed Packet (incorrect LI value 0x%x)",li[num_li].li);
1152                                                 col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1153                                                 return -1; /* just give up on this */
1154                                         }
1155                                         li[num_li].len = li[num_li].li - prev_li;
1156                                         prev_li = li[num_li].li;
1157                         }
1158                 }
1159                 li[num_li].tree = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1160                 num_li++;
1161
1162                 if (num_li > max_li) {
1163                         /* OK, so this is not really a malformed packet, but for now,
1164                         * we will treat it as such, so that it is marked in some way */
1165                         malformed = proto_tree_add_protocol_format(tree,
1166                                 proto_malformed, tvb, 0, 0, "[Dissector Problem: %s]", pinfo->current_proto);
1167                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1168                                 "Too many LI entries");
1169                         return -1;
1170                 }
1171         }
1172         return num_li;
1173 }
1174
1175 static void
1176 dissect_rlc_um(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1177                proto_tree *top_level, proto_tree *tree)
1178 {
1179 #define MAX_LI 16
1180         struct rlc_li li[MAX_LI];
1181         fp_info *fpinf;
1182         rlc_info *rlcinf;
1183         guint32 orig_num;
1184         guint8 seq;
1185         guint8 next_byte, offs = 0;
1186         gint16 pos, num_li = 0;
1187         gboolean is_truncated, li_is_on_2_bytes;
1188         proto_item *truncated_ti;
1189
1190         next_byte = tvb_get_guint8(tvb, offs++);
1191         seq = next_byte >> 1;
1192
1193         /* show sequence number and extension bit */
1194         if (tree) {
1195                 proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 0, 7, ENC_BIG_ENDIAN);
1196                 proto_tree_add_bits_item(tree, hf_rlc_ext, tvb, 7, 1, ENC_BIG_ENDIAN);
1197         }
1198
1199         fpinf = p_get_proto_data(pinfo->fd, proto_fp);
1200         rlcinf = p_get_proto_data(pinfo->fd, proto_rlc);
1201         if (!fpinf || !rlcinf) {
1202                 proto_tree_add_text(tree, tvb, 0, -1,
1203                         "Cannot dissect RLC frame because per-frame info is missing");
1204                 return;
1205         }
1206         pos = fpinf->cur_tb;
1207         if (rlcinf->ciphered[pos] == TRUE && rlcinf->deciphered[pos] == FALSE) {
1208                 proto_tree_add_text(tree, tvb, 0, -1,
1209                         "Cannot dissect RLC frame because it is ciphered");
1210                 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1211                 return;
1212         }
1213
1214         if (rlcinf->li_size[pos] == RLC_LI_VARIABLE) {
1215                 li_is_on_2_bytes = (tvb_length(tvb) > 125) ? TRUE : FALSE;
1216         } else {
1217                 li_is_on_2_bytes = (rlcinf->li_size[pos] == RLC_LI_15BITS) ? TRUE : FALSE;
1218         }
1219
1220         num_li = rlc_decode_li(RLC_UM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
1221         if (num_li == -1) return; /* something went wrong */
1222         offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
1223
1224         if (global_rlc_headers_expected) {
1225                 /* There might not be any data, if only headerwas logged */
1226                 is_truncated = (tvb_length_remaining(tvb, offs) == 0);
1227                 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
1228                                                       is_truncated);
1229                 if (is_truncated) {
1230                         PROTO_ITEM_SET_GENERATED(truncated_ti);
1231                         expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1232                                                "RLC PDU SDUs have been omitted");
1233                         return;
1234                 } else {
1235                         PROTO_ITEM_SET_HIDDEN(truncated_ti);
1236                 }
1237         }
1238
1239         /* do not detect duplicates or reassemble, if prefiltering is done */
1240         if (pinfo->fd->num == 0) return;
1241         /* check for duplicates */
1242         if (rlc_is_duplicate(RLC_UM, pinfo, seq, &orig_num) == TRUE) {
1243                 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] [Duplicate]  SN=%u", seq);
1244                 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, orig_num);
1245                 return;
1246         }
1247         rlc_um_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, li, num_li, li_is_on_2_bytes);
1248 }
1249
1250 static void
1251 dissect_rlc_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint8 offset)
1252 {
1253         guint8 sufi_type, bits;
1254         guint64 len, sn, wsn, lsn, l;
1255         guint16 value, previous_sn;
1256         gboolean isErrorBurstInd;
1257         gint bit_offset, previous_bit_offset;
1258         guint i, j;
1259         proto_tree *sufi_tree, *bitmap_tree, *rlist_tree;
1260         proto_item *sufi_item, *malformed, *ti;
1261         #define BUFF_SIZE 41
1262         gchar *buff = NULL;
1263         guint8 cw[15];
1264         guint8 sufi_start_offset;
1265         gboolean seen_last = FALSE;
1266         guint16 number_of_bitmap_entries = 0;
1267
1268         bit_offset = offset*8 + 4; /* first SUFI type is always 4 bit shifted */
1269
1270         while (!seen_last && tvb_length_remaining(tvb, bit_offset/8) > 0) {
1271                 /* SUFI */
1272                 sufi_type = tvb_get_bits8(tvb, bit_offset, 4);
1273                 sufi_start_offset = bit_offset/8;
1274                 sufi_item = proto_tree_add_item(tree, hf_rlc_sufi, tvb, sufi_start_offset, 0, ENC_NA);
1275                 sufi_tree = proto_item_add_subtree(sufi_item, ett_rlc_sufi);
1276                 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_type, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
1277                 proto_item_append_text(sufi_item, " (%s)", val_to_str_const(sufi_type, rlc_sufi_vals, "Unknown"));
1278                 bit_offset += 4;
1279                 switch (sufi_type) {
1280                         case RLC_SUFI_NOMORE:
1281                                 seen_last = TRUE;
1282                                 break;
1283                         case RLC_SUFI_ACK:
1284                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_lsn, tvb, bit_offset, 12, &lsn, ENC_BIG_ENDIAN);
1285                                 col_append_fstr(pinfo->cinfo, COL_INFO, " LSN=%u", (guint16)lsn);
1286                                 proto_item_append_text(sufi_item, " LSN=%u", (guint16)lsn);
1287                                 bit_offset += 12;
1288                                 seen_last = TRUE;
1289                                 break;
1290                         case RLC_SUFI_WINDOW:
1291                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_wsn, tvb, bit_offset, 12, &wsn, ENC_BIG_ENDIAN);
1292                                 col_append_fstr(pinfo->cinfo, COL_INFO, " WSN=%u", (guint16)wsn);
1293                                 bit_offset += 12;
1294                                 break;
1295                         case RLC_SUFI_LIST:
1296                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
1297                                 col_append_fstr(pinfo->cinfo, COL_INFO,  " LIST(%u) - ", (guint8)len);
1298                                 bit_offset += 4;
1299                                 if (len) {
1300                                         while (len) {
1301                                                 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1302                                                 proto_item_append_text(ti, " (AMD PDU not correctly received)");
1303                                                 bit_offset += 12;
1304                                                 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_l, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
1305                                                 if (l) {
1306                                                         proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)",
1307                                                                                (unsigned)(sn+l)&0xfff);
1308                                                         col_append_fstr(pinfo->cinfo, COL_INFO,  "%u-%u ", (guint16)sn, (unsigned)(sn+l)&0xfff);
1309                                                 }
1310                                                 else {
1311                                                         col_append_fstr(pinfo->cinfo, COL_INFO,  "%u ", (guint16)sn);
1312                                                 }
1313                                                 bit_offset += 4;
1314                                                 len--;
1315                                         }
1316                                 } else {
1317                                         malformed = proto_tree_add_protocol_format(tree,
1318                                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1319                                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1320                                                 "Malformed Packet (invalid length)");
1321                                         col_append_str(pinfo->cinfo, COL_INFO, " [Malformed Packet]");
1322                                 }
1323                                 break;
1324                         case RLC_SUFI_BITMAP:
1325                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
1326                                 bit_offset += 4;
1327                                 len++; /* bitmap is len + 1 */
1328                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1329                                 bit_offset += 12;
1330                                 proto_tree_add_item(sufi_tree, hf_rlc_sufi_bitmap, tvb, bit_offset/8, (gint)len, ENC_NA);
1331                                 ti = proto_tree_add_text(sufi_tree, tvb, bit_offset/8, (gint)len, "Decoded bitmap:");
1332                                 col_append_str(pinfo->cinfo, COL_INFO, " BITMAP=(");
1333
1334                                 bitmap_tree = proto_item_add_subtree(ti, ett_rlc_bitmap);
1335                                 buff = ep_alloc(BUFF_SIZE);
1336                                 for (i=0; i<len; i++) {
1337                                         bits = tvb_get_bits8(tvb, bit_offset, 8);
1338                                         for (l=0, j=0; l<8; l++) {
1339                                                 if ((bits << l) & 0x80) {
1340                                                         j += g_snprintf(&buff[j], BUFF_SIZE-j, "%04u,", (unsigned)(sn+(8*i)+l)&0xfff);
1341                                                         col_append_fstr(pinfo->cinfo, COL_INFO, " %u", (unsigned)(sn+(8*i)+l)&0xfff);
1342                                                         number_of_bitmap_entries++;
1343                                                 } else {
1344                                                         j += g_snprintf(&buff[j], BUFF_SIZE-j, "    ,");
1345                                                 }
1346                                         }
1347                                         proto_tree_add_text(bitmap_tree, tvb, bit_offset/8, 1, "%s", buff);
1348                                         bit_offset += 8;
1349                                 }
1350                                 proto_item_append_text(ti, " (%u SNs)", number_of_bitmap_entries);
1351                                 col_append_str(pinfo->cinfo, COL_INFO, " )");
1352                                 break;
1353                         case RLC_SUFI_RLIST:
1354                                 previous_bit_offset = bit_offset;
1355                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
1356                                 bit_offset += 4;
1357                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1358                                 bit_offset += 12;
1359                                 proto_item_append_text(sufi_item, " (%u codewords)", (guint16)len);
1360
1361                                 for (i=0; i<len; i++) {
1362                                         ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_cw, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
1363                                         if (l == 0x01) {
1364                                                 proto_item_append_text(ti, " (Error burst indication)");
1365                                         }
1366                                         bit_offset += 4;
1367                                         cw[i] = (guint8)l;
1368                                 }
1369                                 if (len && (((cw[len-1] & 0x01) == 0) || (cw[len-1] == 0x01))) {
1370                                         malformed = proto_tree_add_protocol_format(tree,
1371                                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1372                                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1373                                                 "Malformed Packet (invalid last codeword)");
1374                                         col_append_str(pinfo->cinfo, COL_INFO, " [Malformed Packet]");
1375                                 } else {
1376                                         ti = proto_tree_add_text(sufi_tree, tvb, previous_bit_offset/8, (bit_offset-previous_bit_offset)/8, "Decoded list:");
1377                                         rlist_tree = proto_item_add_subtree(ti, ett_rlc_rlist);
1378                                         proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+4)/8, 12/8,
1379                                                             "Sequence Number = %u (AMD PDU not correctly received)",(unsigned)sn);
1380                                         col_append_fstr(pinfo->cinfo, COL_INFO, " RLIST=(%u", (unsigned)sn);
1381
1382                                         for (i=0, isErrorBurstInd=FALSE, j=0, previous_sn=(guint16)sn, value=0; i<len; i++) {
1383                                                 if (cw[i] == 0x01) {
1384                                                         isErrorBurstInd = TRUE;
1385                                                 } else {
1386                                                         value |= (cw[i] >> 1) << j;
1387                                                         j += 3;
1388                                                         if (cw[i] & 0x01) {
1389                                                                 if (isErrorBurstInd) {
1390                                                                         previous_sn = (previous_sn + value) & 0xfff;
1391                                                                         ti = proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+16+4*i)/8, 1, "Length: %u", value);
1392                                                                         if (value) {
1393                                                                                 proto_item_append_text(ti, "  (all consecutive AMD PDUs up to SN %u not correctly received)", previous_sn);
1394                                                                                 col_append_fstr(pinfo->cinfo, COL_INFO, " ->%u", previous_sn);
1395                                                                         }
1396                                                                         isErrorBurstInd = FALSE;
1397                                                                 } else {
1398                                                                         value = (value + previous_sn) & 0xfff;
1399                                                                         proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+16+4*i)/8, 1, "Sequence Number = %u (AMD PDU not correctly received)",value);
1400                                                                         col_append_fstr(pinfo->cinfo, COL_INFO, " %u", value);
1401                                                                         previous_sn = value;
1402                                                                 }
1403                                                                 value = j = 0;
1404                                                         }
1405                                                 }
1406                                         }
1407                                         col_append_str(pinfo->cinfo, COL_INFO, ")");
1408                                 }
1409                                 break;
1410                         case RLC_SUFI_MRW_ACK:
1411                                 col_append_str(pinfo->cinfo, COL_INFO, " MRW-ACK");
1412                                 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
1413                                 bit_offset += 4;
1414                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_ack, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1415                                 bit_offset += 12;
1416                                 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
1417                                 break;
1418                         case RLC_SUFI_MRW:
1419                                 col_append_str(pinfo->cinfo, COL_INFO, " MRW");
1420                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
1421                                 bit_offset += 4;
1422                                 if (len) {
1423                                         while (len) {
1424                                                 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1425                                                 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
1426                                                 bit_offset += 12;
1427                                                 len--;
1428                                         }
1429                                 } else {
1430                                         /* only one SN_MRW field is present */
1431                                         ti = proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
1432                                         proto_item_append_text(ti, " (RLC SDU to be discarded in the Receiver extends above the configured transmission window in the Sender)");
1433                                         bit_offset += 12;
1434                                 }
1435                                 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
1436                                 bit_offset += 4;
1437                                 break;
1438                         case RLC_SUFI_POLL:
1439                                 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_poll_sn, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
1440                                 bit_offset += 12;
1441                                 break;
1442
1443                         default:
1444                                 malformed = proto_tree_add_protocol_format(tree,
1445                                         proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1446                                 expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1447                                         "Malformed Packet (invalid SUFI type)");
1448                                 col_append_str(pinfo->cinfo, COL_INFO, " [Malformed Packet]");
1449                                 return; /* invalid value, ignore the rest */
1450                 }
1451
1452                 /* Set extent of SUFI root */
1453                 proto_item_set_len(sufi_item, ((bit_offset+7)/8) - sufi_start_offset);
1454         }
1455 }
1456
1457 static void
1458 dissect_rlc_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1459 {
1460         guint8 type, next_byte;
1461         proto_item *malformed;
1462         guint64 r1;
1463         guint64 rsn, hfn;
1464
1465         next_byte = tvb_get_guint8(tvb, 0);
1466         type = (next_byte >> 4) & 0x07;
1467
1468         proto_tree_add_bits_item(tree, hf_rlc_ctrl_type, tvb, 1, 3, ENC_BIG_ENDIAN);
1469         switch (type) {
1470                 case RLC_STATUS:
1471                         dissect_rlc_status(tvb, pinfo, tree, 0);
1472                         break;
1473                 case RLC_RESET:
1474                 case RLC_RESET_ACK:
1475                         col_append_str(pinfo->cinfo, COL_INFO, (type == RLC_RESET) ? " RESET" : " RESET-ACK");
1476                         proto_tree_add_bits_ret_val(tree, hf_rlc_rsn, tvb, 4, 1, &rsn, ENC_BIG_ENDIAN);
1477                         proto_tree_add_bits_ret_val(tree, hf_rlc_r1, tvb, 5, 3, &r1, ENC_BIG_ENDIAN);
1478                         if (r1) {
1479                                 proto_item *malformed;
1480                                 malformed = proto_tree_add_protocol_format(tree,
1481                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1482                                 expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1483                                         "Malformed Packet (reserved bits not zero)");
1484                                 col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1485                                 return;
1486                         }
1487                         proto_tree_add_bits_ret_val(tree, hf_rlc_hfni, tvb, 8, 20, &hfn, ENC_BIG_ENDIAN);
1488                         col_append_fstr(pinfo->cinfo, COL_INFO, " RSN=%u HFN=%u", (guint16)rsn, (guint32)hfn);
1489                         break;
1490                 default:
1491                         malformed = proto_tree_add_protocol_format(tree,
1492                                 proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1493                         expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1494                                 "Malformed Packet (invalid RLC AM control type %u)", type);
1495                         col_append_str(pinfo->cinfo, COL_INFO, " [Malformed Packet]");
1496                         return; /* invalid */
1497         }
1498 }
1499
1500 static void
1501 rlc_am_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo,
1502                   proto_tree *tree, proto_tree *top_level,
1503                   enum rlc_channel_type channel, guint16 seq, gboolean poll_set, struct rlc_li *li,
1504                   guint16 num_li, gboolean final, gboolean li_is_on_2_bytes)
1505 {
1506         guint8 i;
1507         gboolean piggyback = FALSE, dissected = FALSE;
1508         tvbuff_t *next_tvb = NULL;
1509         /* perform reassembly now */
1510         for (i = 0; i < num_li; i++) {
1511                 if ((!li_is_on_2_bytes && (li[i].li == 0x7e)) || (li[i].li == 0x7ffe)) {
1512                         /* piggybacked status */
1513                         piggyback = TRUE;
1514                 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
1515                         /* padding, must be last LI */
1516                         if (tree && tvb_length_remaining(tvb, offs) > 0) {
1517                                 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, -1, ENC_NA);
1518                         }
1519                         offs += tvb_length_remaining(tvb, offs);
1520                 } else {
1521                         if (tree && li[i].len) {
1522                                 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
1523                         }
1524                         if (global_rlc_perform_reassemby) {
1525                                 add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE);
1526                                 next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, li[i].tree, seq, i);
1527                         }
1528                 }
1529                 if (next_tvb) {
1530                         dissected = TRUE;
1531                         rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1532                         next_tvb = NULL;
1533                 }
1534                 offs += li[i].len;
1535         }
1536
1537         if (piggyback) {
1538                 dissect_rlc_status(tvb, pinfo, tree, offs);
1539         } else {
1540                 if (tvb_length_remaining(tvb, offs) > 0) {
1541                         /* we have remaining data, which we need to mark in the tree */
1542                         if (tree) {
1543                                 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
1544                         }
1545                         if (global_rlc_perform_reassemby) {
1546                                 add_fragment(RLC_AM, tvb, pinfo, tree, offs, seq, i,
1547                                         tvb_length_remaining(tvb,offs), final);
1548                                 if (final) {
1549                                         next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, NULL, seq, i);
1550                                 }
1551                         }
1552                 }
1553                 if (next_tvb) {
1554                         dissected = TRUE;
1555                         rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1556                         next_tvb = NULL;
1557                 }
1558         }
1559         if (dissected == FALSE)
1560                 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment]  SN=%u %s",
1561                              seq, poll_set ? "(P)" : "");
1562         else
1563                 if (channel == RLC_UNKNOWN_CH)
1564                         col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Data]  SN=%u %s",
1565                                      seq, poll_set ? "(P)" : "");
1566 }
1567
1568 static void
1569 dissect_rlc_am(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1570                proto_tree *top_level, proto_tree *tree)
1571 {
1572 #define MAX_LI 16
1573         struct rlc_li li[MAX_LI];
1574         fp_info *fpinf;
1575         rlc_info *rlcinf;
1576         guint8 ext, dc;
1577         guint8 next_byte, offs = 0;
1578         guint32 orig_num = 0;
1579         gint16 num_li = 0, seq, pos;
1580         gboolean is_truncated, li_is_on_2_bytes;
1581         proto_item *truncated_ti;
1582         guint64 polling;
1583
1584         next_byte = tvb_get_guint8(tvb, offs++);
1585         dc = next_byte >> 7;
1586         if (tree)
1587                 proto_tree_add_bits_item(tree, hf_rlc_dc, tvb, 0, 1, ENC_BIG_ENDIAN);
1588         if (dc == 0) {
1589                 col_set_str(pinfo->cinfo, COL_INFO, "[RLC Control Frame]");
1590                 dissect_rlc_control(tvb, pinfo, tree);
1591                 return;
1592         }
1593
1594         seq = next_byte & 0x7f;
1595         seq <<= 5;
1596         next_byte = tvb_get_guint8(tvb, offs++);
1597         seq |= (next_byte >> 3);
1598
1599         ext = next_byte & 0x03;
1600         /* show header fields */
1601         proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 1, 12, ENC_BIG_ENDIAN);
1602         proto_tree_add_bits_ret_val(tree, hf_rlc_p, tvb, 13, 1, &polling, ENC_BIG_ENDIAN);
1603         proto_tree_add_bits_item(tree, hf_rlc_he, tvb, 14, 2, ENC_BIG_ENDIAN);
1604
1605         /* header extension may only be 00, 01 or 10 */
1606         if (ext > 2) {
1607                 proto_item *malformed;
1608                 malformed = proto_tree_add_protocol_format(tree,
1609                         proto_malformed, tvb, 0, 0, "[Malformed Packet: %s]", pinfo->current_proto);
1610                 expert_add_info_format(pinfo, malformed, PI_MALFORMED, PI_ERROR,
1611                         "Malformed Packet (incorrect HE value)");
1612                 col_append_str(pinfo->cinfo, COL_INFO, "[Malformed Packet]");
1613                 return;
1614         }
1615
1616         fpinf = p_get_proto_data(pinfo->fd, proto_fp);
1617         rlcinf = p_get_proto_data(pinfo->fd, proto_rlc);
1618         if (!fpinf || !rlcinf) {
1619                 proto_tree_add_text(tree, tvb, 0, -1,
1620                         "Cannot dissect RLC frame because per-frame info is missing");
1621                 return;
1622         }
1623         pos = fpinf->cur_tb;
1624         if (rlcinf->ciphered[pos] == TRUE && rlcinf->deciphered[pos] == FALSE) {
1625                 proto_tree_add_text(tree, tvb, 0, -1,
1626                 "Cannot dissect RLC frame because it is ciphered");
1627                 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1628                 return;
1629         }
1630
1631         if (rlcinf->li_size[pos] == RLC_LI_VARIABLE) {
1632                 li_is_on_2_bytes = (tvb_length(tvb) > 126) ? TRUE : FALSE;
1633         } else {
1634                 li_is_on_2_bytes = (rlcinf->li_size[pos] == RLC_LI_15BITS) ? TRUE : FALSE;
1635         }
1636
1637         num_li = rlc_decode_li(RLC_AM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
1638         if (num_li == -1) return; /* something went wrong */
1639         offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
1640
1641         if (global_rlc_headers_expected) {
1642                 /* There might not be any data, if only header was logged */
1643                 is_truncated = (tvb_length_remaining(tvb, offs) == 0);
1644                 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
1645                                                       is_truncated);
1646                 if (is_truncated) {
1647                         PROTO_ITEM_SET_GENERATED(truncated_ti);
1648                         expert_add_info_format(pinfo, truncated_ti, PI_SEQUENCE, PI_NOTE,
1649                                                "RLC PDU SDUs have been omitted");
1650                         return;
1651                 } else {
1652                         PROTO_ITEM_SET_HIDDEN(truncated_ti);
1653                 }
1654         }
1655
1656         /* do not detect duplicates or reassemble, if prefiltering is done */
1657         if (pinfo->fd->num == 0) return;
1658         /* check for duplicates */
1659         if (rlc_is_duplicate(RLC_AM, pinfo, seq, &orig_num) == TRUE) {
1660                 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] [Duplicate]  SN=%u %s",
1661                              seq, (polling != 0) ? "(P)" : "");
1662                 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, orig_num);
1663                 return;
1664         }
1665         rlc_am_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, polling != 0,
1666                           li, num_li, ext == 2, li_is_on_2_bytes);
1667 }
1668
1669 /* dissect entry functions */
1670 static void
1671 dissect_rlc_pcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1672 {
1673         proto_tree *subtree = NULL;
1674         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1675         col_clear(pinfo->cinfo, COL_INFO);
1676
1677         /* PCCH is always RLC TM */
1678         if (tree) {
1679                 proto_item *ti;
1680                 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1681                 subtree = proto_item_add_subtree(ti, ett_rlc);
1682                 proto_item_append_text(ti, " TM (PCCH)");
1683         }
1684         dissect_rlc_tm(RLC_PCCH, tvb, pinfo, tree, subtree);
1685 }
1686
1687 static void
1688 dissect_rlc_ccch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1689 {
1690         fp_info *fpi;
1691         proto_item *ti = NULL;
1692         proto_tree *subtree = NULL;
1693
1694         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1695         col_clear(pinfo->cinfo, COL_INFO);
1696
1697         fpi = p_get_proto_data(pinfo->fd, proto_fp);
1698         if (!fpi) return; /* dissection failure */
1699
1700         if (tree) {
1701                 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1702                 subtree = proto_item_add_subtree(ti, ett_rlc);
1703         }
1704
1705         if (fpi->is_uplink) {
1706                 /* UL CCCH is always RLC TM */
1707                 proto_item_append_text(ti, " TM (CCCH)");
1708                 dissect_rlc_tm(RLC_UL_CCCH, tvb, pinfo, tree, subtree);
1709         } else {
1710                 /* DL CCCH is always UM */
1711                 proto_item_append_text(ti, " UM (CCCH)");
1712                 dissect_rlc_um(RLC_DL_CCCH, tvb, pinfo, tree, subtree);
1713         }
1714 }
1715
1716 static void
1717 dissect_rlc_ctch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1718 {
1719     fp_info *fpi;
1720     proto_item *ti = NULL;
1721     proto_tree *subtree = NULL;
1722
1723
1724         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1725     col_clear(pinfo->cinfo, COL_INFO);
1726
1727     fpi = p_get_proto_data(pinfo->fd, proto_fp);
1728     if (!fpi) return; /* dissection failure */
1729
1730     if (tree) {
1731         ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1732         subtree = proto_item_add_subtree(ti, ett_rlc);
1733     }
1734
1735     /* CTCH is always UM */
1736     proto_item_append_text(ti, " UM (CTCH)");
1737     dissect_rlc_um(RLC_DL_CTCH, tvb, pinfo, tree, subtree);
1738 }
1739
1740 static void
1741 dissect_rlc_dcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1742 {
1743         proto_item *ti = NULL;
1744         proto_tree *subtree = NULL;
1745         fp_info *fpi;
1746         rlc_info *rlci;
1747         enum rlc_channel_type channel;
1748
1749         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1750         col_clear(pinfo->cinfo, COL_INFO);
1751
1752         fpi = p_get_proto_data(pinfo->fd, proto_fp);
1753         rlci = p_get_proto_data(pinfo->fd, proto_rlc);
1754
1755         if (!fpi || !rlci){
1756         ti = proto_tree_add_text(tree, tvb, 0, -1,
1757                                 "Can't dissect RLC frame because no per-frame info was attached!");
1758         PROTO_ITEM_SET_GENERATED(ti);
1759                 return;
1760         }
1761
1762         if (tree) {
1763                 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1764                 subtree = proto_item_add_subtree(ti, ett_rlc);
1765         }
1766
1767         channel = fpi->is_uplink ? RLC_UL_DCCH : RLC_DL_DCCH;
1768
1769         switch (rlci->mode[fpi->cur_tb]) {
1770                 case RLC_UM:
1771                         proto_item_append_text(ti, " UM (DCCH)");
1772                         dissect_rlc_um(channel, tvb, pinfo, tree, subtree);
1773                         break;
1774                 case RLC_AM:
1775                         proto_item_append_text(ti, " AM (DCCH)");
1776                         dissect_rlc_am(channel, tvb, pinfo, tree, subtree);
1777                         break;
1778         }
1779 }
1780
1781 static void
1782 dissect_rlc_ps_dtch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1783 {
1784         proto_item *ti = NULL;
1785         proto_tree *subtree = NULL;
1786         fp_info *fpi;
1787         rlc_info *rlci;
1788
1789         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1790         col_clear(pinfo->cinfo, COL_INFO);
1791
1792         fpi = p_get_proto_data(pinfo->fd, proto_fp);
1793         rlci = p_get_proto_data(pinfo->fd, proto_rlc);
1794
1795         if (!fpi || !rlci) return;
1796
1797         if (tree) {
1798                 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1799                 subtree = proto_item_add_subtree(ti, ett_rlc);
1800         }
1801
1802         switch (rlci->mode[fpi->cur_tb]) {
1803                 case RLC_UM:
1804                         proto_item_append_text(ti, " UM (PS DTCH)");
1805                         dissect_rlc_um(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
1806                         break;
1807                 case RLC_AM:
1808                         proto_item_append_text(ti, " AM (PS DTCH)");
1809                         dissect_rlc_am(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
1810                         break;
1811                 case RLC_TM:
1812                         proto_item_append_text(ti, " TM (PS DTCH)");
1813                         dissect_rlc_tm(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
1814                         break;
1815         }
1816 }
1817
1818 static void
1819 dissect_rlc_dch_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1820 {
1821         proto_item *ti = NULL;
1822         proto_tree *subtree = NULL;
1823         fp_info *fpi;
1824         rlc_info *rlci;
1825
1826         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1827         col_clear(pinfo->cinfo, COL_INFO);
1828
1829         fpi = p_get_proto_data(pinfo->fd, proto_fp);
1830         rlci = p_get_proto_data(pinfo->fd, proto_rlc);
1831
1832         if (!fpi || !rlci) return;
1833
1834         if (tree) {
1835                 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
1836                 subtree = proto_item_add_subtree(ti, ett_rlc);
1837         }
1838
1839         switch (rlci->mode[fpi->cur_tb]) {
1840                 case RLC_UM:
1841                         proto_item_append_text(ti, " UM (Unknown)");
1842                         dissect_rlc_um(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
1843                         break;
1844                 case RLC_AM:
1845                         proto_item_append_text(ti, " AM (Unknown)");
1846                         dissect_rlc_am(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
1847                         break;
1848                 case RLC_TM:
1849                         proto_item_append_text(ti, " TM (Unknown)");
1850                         dissect_rlc_tm(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
1851                         break;
1852         }
1853 }
1854
1855
1856 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
1857 static gboolean
1858 dissect_rlc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1859 {
1860         gint                 offset = 0;
1861         fp_info              *fpi;
1862         rlc_info             *rlci;
1863         tvbuff_t             *rlc_tvb;
1864         guint8               tag = 0;
1865         guint                channelType = UMTS_CHANNEL_TYPE_UNSPECIFIED;
1866         gboolean             fpInfoAlreadySet = FALSE;
1867         gboolean             rlcInfoAlreadySet = FALSE;
1868         gboolean             channelTypePresent = FALSE;
1869         gboolean             rlcModePresent = FALSE;
1870         proto_item           *ti = NULL;
1871         proto_tree           *subtree = NULL;
1872
1873         /* This is a heuristic dissector, which means we get all the UDP
1874          * traffic not sent to a known dissector and not claimed by
1875          * a heuristic dissector called before us!
1876          */
1877         if (!global_rlc_heur) {
1878                 return FALSE;
1879         }
1880
1881         /* Do this again on re-dissection to re-discover offset of actual PDU */
1882
1883         /* Needs to be at least as long as:
1884            - the signature string
1885            - conditional header bytes
1886            - tag for data
1887            - at least one byte of RLC PDU payload */
1888         if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(RLC_START_STRING)+2+2)) {
1889                 return FALSE;
1890         }
1891
1892         /* OK, compare with signature string */
1893         if (tvb_strneql(tvb, offset, RLC_START_STRING, (gint)strlen(RLC_START_STRING)) != 0) {
1894                 return FALSE;
1895         }
1896         offset += (gint)strlen(RLC_START_STRING);
1897
1898         /* If redissecting, use previous info struct (if available) */
1899         fpi = p_get_proto_data(pinfo->fd, proto_fp);
1900         if (fpi == NULL) {
1901                 /* Allocate new info struct for this frame */
1902                 fpi = se_alloc0(sizeof(fp_info));
1903         } else {
1904                 fpInfoAlreadySet = TRUE;
1905         }
1906         rlci = p_get_proto_data(pinfo->fd, proto_rlc);
1907         if (rlci == NULL) {
1908                 /* Allocate new info struct for this frame */
1909                 rlci = se_alloc0(sizeof(rlc_info));
1910         } else {
1911                 rlcInfoAlreadySet = TRUE;
1912         }
1913
1914         /* Read conditional/optional fields */
1915         while (tag != RLC_PAYLOAD_TAG) {
1916                 /* Process next tag */
1917                 tag = tvb_get_guint8(tvb, offset++);
1918                 switch (tag) {
1919                         case RLC_CHANNEL_TYPE_TAG:
1920                                 channelType = tvb_get_guint8(tvb, offset);
1921                                 offset++;
1922                                 channelTypePresent = TRUE;
1923                                 break;
1924                         case RLC_MODE_TAG:
1925                                 rlci->mode[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
1926                                 offset++;
1927                                 rlcModePresent = TRUE;
1928                                 break;
1929                         case RLC_DIRECTION_TAG:
1930                                 fpi->is_uplink = (tvb_get_guint8(tvb, offset) == DIRECTION_UPLINK) ? TRUE : FALSE;
1931                                 offset++;
1932                                 break;
1933                         case RLC_URNTI_TAG:
1934                                 rlci->urnti[fpi->cur_tb] = tvb_get_ntohl(tvb, offset);
1935                                 offset += 4;
1936                                 break;
1937                         case RLC_RADIO_BEARER_ID_TAG:
1938                                 rlci->rbid[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
1939                                 offset++;
1940                                 break;
1941                         case RLC_LI_SIZE_TAG:
1942                                 rlci->li_size[fpi->cur_tb] = (enum rlc_li_size) tvb_get_guint8(tvb, offset);
1943                                 offset++;
1944                                 break;
1945                         case RLC_PAYLOAD_TAG:
1946                                 /* Have reached data, so get out of loop */
1947                                 continue;
1948                         default:
1949                                 /* It must be a recognised tag */
1950                                 return FALSE;
1951                 }
1952         }
1953
1954         if ((channelTypePresent == FALSE) && (rlcModePresent == FALSE)) {
1955                 /* Conditional fields are missing */
1956                 return FALSE;
1957         }
1958
1959         /* Store info in packet if needed */
1960         if (!fpInfoAlreadySet) {
1961                 p_add_proto_data(pinfo->fd, proto_fp, fpi);
1962         }
1963         if (!rlcInfoAlreadySet) {
1964                 p_add_proto_data(pinfo->fd, proto_rlc, rlci);
1965         }
1966
1967     /**************************************/
1968     /* OK, now dissect as RLC             */
1969
1970     /* Create tvb that starts at actual RLC PDU */
1971     rlc_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
1972         switch (channelType) {
1973                 case UMTS_CHANNEL_TYPE_UNSPECIFIED:
1974                         /* Call relevant dissector according to RLC mode */
1975                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
1976                         col_clear(pinfo->cinfo, COL_INFO);
1977
1978                         if (tree) {
1979                                 ti = proto_tree_add_item(tree, proto_rlc, rlc_tvb, 0, -1, ENC_NA);
1980                                 subtree = proto_item_add_subtree(ti, ett_rlc);
1981                         }
1982
1983                         if (rlci->mode[fpi->cur_tb] == RLC_AM) {
1984                                 proto_item_append_text(ti, " AM");
1985                                 dissect_rlc_am(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
1986                         } else if (rlci->mode[fpi->cur_tb] == RLC_UM) {
1987                                 proto_item_append_text(ti, " UM");
1988                                 dissect_rlc_um(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
1989                         } else {
1990                                 proto_item_append_text(ti, " TM");
1991                                 dissect_rlc_tm(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
1992                         }
1993                         break;
1994                 case UMTS_CHANNEL_TYPE_PCCH:
1995                         dissect_rlc_pcch(rlc_tvb, pinfo, tree);
1996                         break;
1997                 case UMTS_CHANNEL_TYPE_CCCH:
1998                         dissect_rlc_ccch(rlc_tvb, pinfo, tree);
1999                         break;
2000                 case UMTS_CHANNEL_TYPE_DCCH:
2001                         dissect_rlc_dcch(rlc_tvb, pinfo, tree);
2002                         break;
2003                 case UMTS_CHANNEL_TYPE_PS_DTCH:
2004                         dissect_rlc_ps_dtch(rlc_tvb, pinfo, tree);
2005                         break;
2006                 case UMTS_CHANNEL_TYPE_CTCH:
2007                         dissect_rlc_ctch(rlc_tvb, pinfo, tree);
2008                         break;
2009
2010                 default:
2011                         /* Unknown channel type */
2012                         return FALSE;
2013         }
2014
2015     return TRUE;
2016 }
2017
2018 void
2019 proto_register_rlc(void)
2020 {
2021         module_t *rlc_module;
2022
2023         static hf_register_info hf[] = {
2024                 { &hf_rlc_dc, { "D/C Bit", "rlc.dc", FT_BOOLEAN, 8, TFS(&rlc_dc_val), 0, NULL, HFILL } },
2025                 { &hf_rlc_ctrl_type, { "Control PDU Type", "rlc.ctrl_pdu_type", FT_UINT8, BASE_DEC, VALS(rlc_ctrl_vals), 0, "PDU Type", HFILL } },
2026                 { &hf_rlc_r1, { "Reserved 1", "rlc.r1", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2027                 { &hf_rlc_rsn, { "Reset Sequence Number", "rlc.rsn", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2028                 { &hf_rlc_hfni, { "Hyper Frame Number Indicator", "rlc.hfni", FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL } },
2029                 { &hf_rlc_seq, { "Sequence Number", "rlc.seq", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2030                 { &hf_rlc_ext, { "Extension Bit", "rlc.ext", FT_BOOLEAN, BASE_DEC, TFS(&rlc_ext_val), 0, NULL, HFILL } },
2031                 { &hf_rlc_he, { "Header Extension Type", "rlc.he", FT_UINT8, BASE_DEC, VALS(rlc_he_vals), 0, NULL, HFILL } },
2032                 { &hf_rlc_p, { "Polling Bit", "rlc.p", FT_BOOLEAN, 8, TFS(&rlc_p_val), 0, NULL, HFILL } },
2033                 { &hf_rlc_pad, { "Padding", "rlc.padding", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
2034                 { &hf_rlc_frags, { "Reassembled Fragments", "rlc.fragments", FT_NONE, BASE_NONE, NULL, 0, "Fragments", HFILL } },
2035                 { &hf_rlc_frag, { "RLC Fragment", "rlc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2036                 { &hf_rlc_duplicate_of, { "Duplicate of", "rlc.duplicate_of", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2037                 { &hf_rlc_reassembled_in, { "Reassembled Message in frame", "rlc.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL } },
2038                 { &hf_rlc_data, { "Data", "rlc.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
2039                 /* LI information */
2040                 { &hf_rlc_li, { "LI", "rlc.li", FT_NONE, BASE_NONE, NULL, 0, "Length Indicator", HFILL } },
2041                 { &hf_rlc_li_value, { "LI value", "rlc.li.value", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2042                 { &hf_rlc_li_ext, { "LI extension bit", "rlc.li.ext", FT_BOOLEAN, BASE_DEC, TFS(&rlc_ext_val), 0, NULL, HFILL } },
2043                 { &hf_rlc_li_data, { "LI Data", "rlc.li.data", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
2044                 /* SUFI information */
2045                 { &hf_rlc_sufi, { "SUFI", "rlc.sufi", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
2046                 { &hf_rlc_sufi_type, { "SUFI Type", "rlc.sufi.type", FT_UINT8, BASE_DEC, VALS(rlc_sufi_vals), 0, NULL, HFILL } },
2047                 { &hf_rlc_sufi_lsn, { "Last Sequence Number", "rlc.sufi.lsn", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2048                 { &hf_rlc_sufi_wsn, { "Window Size Number", "rlc.sufi.wsn", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2049                 { &hf_rlc_sufi_sn, { "Sequence Number", "rlc.sufi.sn", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2050                 { &hf_rlc_sufi_l, { "Length", "rlc.sufi.l", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2051                 { &hf_rlc_sufi_len, { "Length", "rlc.sufi.len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2052                 { &hf_rlc_sufi_fsn, { "First Sequence Number", "rlc.sufi.fsn", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2053                 { &hf_rlc_sufi_bitmap, { "Bitmap", "rlc.sufi.bitmap", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
2054                 { &hf_rlc_sufi_cw, { "Codeword", "rlc.sufi.cw", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2055                 { &hf_rlc_sufi_n, { "Nlength", "rlc.sufi.n", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2056                 { &hf_rlc_sufi_sn_ack, { "SN ACK", "rlc.sufi.sn_ack", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2057                 { &hf_rlc_sufi_sn_mrw, { "SN MRW", "rlc.sufi.sn_mrw", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2058                 { &hf_rlc_sufi_poll_sn, { "Poll SN", "rlc.sufi.poll_sn", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
2059                 /* Other information */
2060                 { &hf_rlc_header_only, { "RLC PDU header only", "rlc.header_only", FT_BOOLEAN, BASE_DEC, TFS(&rlc_header_only_val), 0 ,NULL, HFILL } },
2061         };
2062         static gint *ett[] = {
2063                 &ett_rlc,
2064                 &ett_rlc_frag,
2065                 &ett_rlc_fragments,
2066                 &ett_rlc_sdu,
2067                 &ett_rlc_sufi,
2068                 &ett_rlc_bitmap,
2069                 &ett_rlc_rlist
2070         };
2071         proto_rlc = proto_register_protocol("Radio Link Control", "RLC", "rlc");
2072         register_dissector("rlc.pcch", dissect_rlc_pcch, proto_rlc);
2073         register_dissector("rlc.ccch", dissect_rlc_ccch, proto_rlc);
2074         register_dissector("rlc.ctch", dissect_rlc_ctch, proto_rlc);
2075         register_dissector("rlc.dcch", dissect_rlc_dcch, proto_rlc);
2076         register_dissector("rlc.ps_dtch", dissect_rlc_ps_dtch, proto_rlc);
2077         register_dissector("rlc.dch_unknown", dissect_rlc_dch_unknown, proto_rlc);
2078
2079         proto_register_field_array(proto_rlc, hf, array_length(hf));
2080         proto_register_subtree_array(ett, array_length(ett));
2081
2082         /* Preferences */
2083         rlc_module = prefs_register_protocol(proto_rlc, NULL);
2084
2085         prefs_register_bool_preference(rlc_module, "heuristic_rlc_over_udp",
2086                 "Try Heuristic RLC over UDP framing",
2087                 "When enabled, use heuristic dissector to find RLC frames sent with "
2088                 "UDP framing",
2089                 &global_rlc_heur);
2090
2091         prefs_register_bool_preference(rlc_module, "perform_reassembly",
2092                 "Try to reassemble SDUs",
2093                 "When enabled, try to reassemble SDUs from the various PDUs received",
2094                 &global_rlc_perform_reassemby);
2095
2096         prefs_register_bool_preference(rlc_module, "header_only_mode",
2097                 "May see RLC headers only",
2098                 "When enabled, if data is not present, don't report as an error, but instead "
2099                 "add expert info to indicate that headers were omitted",
2100                 &global_rlc_headers_expected);
2101
2102         register_init_routine(fragment_table_init);
2103 }
2104
2105 void
2106 proto_reg_handoff_rlc(void)
2107 {
2108         rrc_handle = find_dissector("rrc");
2109         ip_handle = find_dissector("ip");
2110         bmc_handle = find_dissector("bmc");
2111         /* Add as a heuristic UDP dissector */
2112         heur_dissector_add("udp", dissect_rlc_heur, proto_rlc);
2113 }