1 /* Routines for UMTS RLC (Radio Link Control) v9.3.0 disassembly
2 * http://www.3gpp.org/ftp/Specs/archive/25_series/25.322/
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/wmem/wmem.h>
30 #include <epan/conversation.h>
31 #include <epan/asn1.h>
32 #include <epan/expert.h>
33 #include <epan/prefs.h>
34 #include <wiretap/wtap.h>
37 * Optional include, for KASUMI support,
38 * see header file for more information.
40 #include <epan/crypt/kasumi.h>
42 #include "packet-umts_fp.h"
43 #include "packet-umts_mac.h"
44 #include "packet-rlc.h"
45 #include "packet-rrc.h"
48 * - distinguish between startpoints and endpoints?
49 * - use sub_num in fragment identification?
52 #define DEBUG_FRAME(number, msg) {if (pinfo->fd->num == number) printf("%u: %s\n", number, msg);}
54 #define ROL16(a,b) (guint16)((a<<b)|(a>>(16-b)))
56 void proto_register_rlc(void);
57 void proto_reg_handoff_rlc(void);
63 /* Preference to perform reassembly */
64 static gboolean global_rlc_perform_reassemby = TRUE;
66 /* Preference to expect RLC headers without payloads */
67 static gboolean global_rlc_headers_expected = FALSE;
70 /* Heuristic dissection */
71 static gboolean global_rlc_heur = FALSE;
73 /* Preference to expect ciphered data */
74 static gboolean global_rlc_ciphered = FALSE;
76 /* Preference to try deciphering */
77 static gboolean global_rlc_try_decipher = FALSE;
79 #ifdef HAVE_UMTS_KASUMI
80 static const char *global_rlc_kasumi_key = NULL;
83 /* LI size preference */
84 #define RLC_LI_UPPERLAYER 255 /* LI-size comes from rlc_info struct rather than preference */
85 static gint global_rlc_li_size = RLC_LI_UPPERLAYER;
87 static const enum_val_t li_size_enumvals[] = {
88 {"7 bits", "7 bits", RLC_LI_7BITS},
89 {"15 bits", "15 bits", RLC_LI_15BITS},
90 {"Let upper layers decide", "Let upper layers decide", RLC_LI_UPPERLAYER},
94 static int hf_rlc_seq = -1;
95 static int hf_rlc_ext = -1;
96 static int hf_rlc_pad = -1;
97 static int hf_rlc_frags = -1;
98 static int hf_rlc_frag = -1;
99 static int hf_rlc_duplicate_of = -1;
100 static int hf_rlc_reassembled_in = -1;
101 static int hf_rlc_he = -1;
102 static int hf_rlc_dc = -1;
103 static int hf_rlc_p = -1;
104 static int hf_rlc_li = -1;
105 static int hf_rlc_li_value = -1;
106 static int hf_rlc_li_ext = -1;
107 static int hf_rlc_li_data = -1;
108 static int hf_rlc_data = -1;
109 static int hf_rlc_ctrl_type = -1;
110 static int hf_rlc_r1 = -1;
111 static int hf_rlc_rsn = -1;
112 static int hf_rlc_hfni = -1;
113 static int hf_rlc_sufi = -1;
114 static int hf_rlc_sufi_type = -1;
115 static int hf_rlc_sufi_lsn = -1;
116 static int hf_rlc_sufi_wsn = -1;
117 static int hf_rlc_sufi_sn = -1;
118 static int hf_rlc_sufi_l = -1;
119 static int hf_rlc_sufi_fsn = -1;
120 static int hf_rlc_sufi_len = -1;
121 static int hf_rlc_sufi_bitmap = -1;
122 static int hf_rlc_sufi_cw = -1;
123 static int hf_rlc_sufi_n = -1;
124 static int hf_rlc_sufi_sn_ack = -1;
125 static int hf_rlc_sufi_sn_mrw = -1;
126 static int hf_rlc_sufi_poll_sn = -1;
127 static int hf_rlc_header_only = -1;
128 static int hf_rlc_channel = -1;
129 static int hf_rlc_channel_rbid = -1;
130 static int hf_rlc_channel_dir = -1;
131 static int hf_rlc_channel_ueid = -1;
134 static int ett_rlc = -1;
135 static int ett_rlc_frag = -1;
136 static int ett_rlc_fragments = -1;
137 static int ett_rlc_sdu = -1;
138 static int ett_rlc_sufi = -1;
139 static int ett_rlc_bitmap = -1;
140 static int ett_rlc_rlist = -1;
141 static int ett_rlc_channel = -1;
143 static expert_field ei_rlc_li_reserved = EI_INIT;
144 static expert_field ei_rlc_he = EI_INIT;
145 static expert_field ei_rlc_li_incorrect_mal = EI_INIT;
146 static expert_field ei_rlc_sufi_cw = EI_INIT;
147 static expert_field ei_rlc_kasumi_implementation_missing = EI_INIT;
148 static expert_field ei_rlc_reassembly_unknown_error = EI_INIT;
149 static expert_field ei_rlc_reassembly_lingering_endpoint = EI_INIT;
150 static expert_field ei_rlc_sufi_len = EI_INIT;
151 static expert_field ei_rlc_reassembly_fail_unfinished_sequence = EI_INIT;
152 static expert_field ei_rlc_reassembly_fail_flag_set = EI_INIT;
153 static expert_field ei_rlc_sufi_type = EI_INIT;
154 static expert_field ei_rlc_reserved_bits_not_zero = EI_INIT;
155 static expert_field ei_rlc_ctrl_type = EI_INIT;
156 static expert_field ei_rlc_li_incorrect_warn = EI_INIT;
157 static expert_field ei_rlc_li_too_many = EI_INIT;
158 static expert_field ei_rlc_header_only = EI_INIT;
160 static dissector_handle_t ip_handle;
161 static dissector_handle_t rrc_handle;
162 static dissector_handle_t bmc_handle;
164 enum rlc_channel_type {
176 static const value_string rlc_dir_vals[] = {
177 { P2P_DIR_UL, "Uplink" },
178 { P2P_DIR_DL, "Downlink" },
182 static const true_false_string rlc_header_only_val = {
183 "RLC PDU header only", "RLC PDU header and body present"
186 static const true_false_string rlc_ext_val = {
187 "Next field is Length Indicator and E Bit", "Next field is data, piggybacked STATUS PDU or padding"
190 static const true_false_string rlc_dc_val = {
194 static const true_false_string rlc_p_val = {
195 "Request a status report", "Status report not requested"
198 static const value_string rlc_he_vals[] = {
199 { 0, "The succeeding octet contains data" },
200 { 1, "The succeeding octet contains a length indicator and E bit" },
201 { 2, "The succeeding octet contains data and the last octet of the PDU is the last octet of an SDU" },
205 #define RLC_STATUS 0x0
206 #define RLC_RESET 0x1
207 #define RLC_RESET_ACK 0x2
208 static const value_string rlc_ctrl_vals[] = {
209 { RLC_STATUS, "Status" },
210 { RLC_RESET, "Reset" },
211 { RLC_RESET_ACK, "Reset Ack" },
215 #define RLC_SUFI_NOMORE 0x0
216 #define RLC_SUFI_WINDOW 0x1
217 #define RLC_SUFI_ACK 0x2
218 #define RLC_SUFI_LIST 0x3
219 #define RLC_SUFI_BITMAP 0x4
220 #define RLC_SUFI_RLIST 0x5
221 #define RLC_SUFI_MRW 0x6
222 #define RLC_SUFI_MRW_ACK 0x7
223 #define RLC_SUFI_POLL 0x8
224 static const value_string rlc_sufi_vals[] = {
225 { RLC_SUFI_NOMORE, "No more data" },
226 { RLC_SUFI_WINDOW, "Window size" },
227 { RLC_SUFI_ACK, "Acknowledgement" },
228 { RLC_SUFI_LIST, "List" },
229 { RLC_SUFI_BITMAP, "Bitmap" },
230 { RLC_SUFI_RLIST, "Relative list" },
231 { RLC_SUFI_MRW, "Move receiving window" },
232 { RLC_SUFI_MRW_ACK, "Move receiving window acknowledgement" },
233 { RLC_SUFI_POLL, "Poll" },
237 /* reassembly related data */
238 static GHashTable *fragment_table = NULL; /* table of not yet assembled fragments */
239 static GHashTable *endpoints = NULL; /* List of SDU-endpoints */
240 static GHashTable *reassembled_table = NULL; /* maps fragment -> complete sdu */
241 static GHashTable *sequence_table = NULL; /* channel -> seq */
242 static GHashTable *duplicate_table = NULL; /* duplicates */
244 /* identify an RLC channel, using one of two options:
245 * - via Radio Bearer ID and U-RNTI
246 * - via Radio Bearer ID and (VPI/VCI/CID) + Link ID
253 guint16 link; /* link number */
254 guint8 rbid; /* radio bearer ID */
255 guint8 dir; /* direction */
256 enum rlc_li_size li_size;
260 /* used for duplicate detection */
265 guint16 oc; /* overflow counter, this is not used? */
269 struct rlc_channel ch;
271 /* We will store one seqlist per channel so this is a good place to indicate
272 * whether or not this channel's reassembly has failed or not. */
273 guint fail_packet; /* Equal to packet where fail flag was set or 0 otherwise. */
276 /* fragment representation */
279 struct rlc_channel ch;
280 guint16 seq; /* RLC sequence number */
281 guint16 li; /* LI within current RLC frame */
282 guint16 len; /* length of fragment data */
283 guint8 *data; /* store fragment data here */
285 struct rlc_frag *next; /* next fragment */
289 tvbuff_t *tvb; /* contains reassembled tvb */
290 guint16 len; /* total length of reassembled SDU */
291 guint16 fragcnt; /* number of fragments within this SDU */
292 guint8 *data; /* reassembled data buffer */
294 struct rlc_frag *reassembled_in;
295 struct rlc_frag *frags; /* pointer to list of fragments */
296 struct rlc_frag *last; /* pointer to last fragment */
300 guint16 li; /* original li */
301 guint16 len; /* length of this data fragment */
302 guint8 ext; /* extension bit value */
303 proto_tree *tree; /* subtree for this LI */
306 /*** KASUMI related variables and structs ***/
307 typedef struct umts_kat_key{ /*Stores 128-bits KASUMI key*/
308 guint64 high; /*64 MSB*/
309 guint64 low; /*64 LSB*/
313 /*Counter used as input for confidentiality algorithm*/
314 static guint32 ps_counter[31][2] ;
315 static gboolean counter_init[31][2];
316 static guint32 max_counter = 0;
317 static GTree * counter_map; /*Saves the countervalues at first pass through, since they will be update*/
319 /* hashtable functions for fragment table
323 rlc_channel_hash(gconstpointer key)
325 const struct rlc_channel *ch = (const struct rlc_channel *)key;
328 return ch->urnti | ch->rbid | ch->mode;
330 return (ch->vci << 16) | (ch->link << 16) | ch->vpi | ch->vci;
334 rlc_channel_equal(gconstpointer a, gconstpointer b)
336 const struct rlc_channel *x = (const struct rlc_channel *)a, *y = (const struct rlc_channel *)b;
338 if (x->urnti || y->urnti)
339 return x->urnti == y->urnti &&
340 x->rbid == y->rbid &&
341 x->mode == y->mode &&
342 x->dir == y->dir ? TRUE : FALSE;
344 return x->vpi == y->vpi &&
347 x->rbid == y->rbid &&
348 x->mode == y->mode &&
350 x->link == y->link ? TRUE : FALSE;
354 rlc_channel_assign(struct rlc_channel *ch, enum rlc_mode mode, packet_info *pinfo)
356 struct atm_phdr *atm;
360 atm = &pinfo->pseudo_header->atm;
361 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
362 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
363 if (!fpinf || !rlcinf) return -1;
365 if (rlcinf->urnti[fpinf->cur_tb]) {
366 ch->urnti = rlcinf->urnti[fpinf->cur_tb];
367 ch->vpi = ch->vci = ch->link = ch->cid = 0;
373 ch->cid = atm->aal2_cid;
374 ch->link = pinfo->link_number;
376 ch->rbid = rlcinf->rbid[fpinf->cur_tb];
377 ch->dir = pinfo->p2p_dir;
379 ch->li_size = rlcinf->li_size[fpinf->cur_tb];
384 static struct rlc_channel *
385 rlc_channel_create(enum rlc_mode mode, packet_info *pinfo)
387 struct rlc_channel *ch;
390 ch = (struct rlc_channel *)g_malloc0(sizeof(struct rlc_channel));
391 rv = rlc_channel_assign(ch, mode, pinfo);
394 /* channel assignment failed */
397 REPORT_DISSECTOR_BUG("Failed to assign channel");
403 rlc_channel_delete(gpointer data)
408 /* hashtable functions for reassembled table
412 rlc_frag_hash(gconstpointer key)
414 const struct rlc_frag *frag = (const struct rlc_frag *)key;
415 return (frag->frame_num << 12) | frag->seq;
419 rlc_frag_equal(gconstpointer a, gconstpointer b)
421 const struct rlc_frag *x = (const struct rlc_frag *)a;
422 const struct rlc_frag *y = (const struct rlc_frag *)b;
424 return rlc_channel_equal(&x->ch, &y->ch) &&
426 x->frame_num == y->frame_num &&
427 x->li == y->li ? TRUE : FALSE;
430 static struct rlc_sdu *
435 sdu = (struct rlc_sdu *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_sdu));
440 rlc_frag_delete(gpointer data)
442 struct rlc_frag *frag = (struct rlc_frag *)data;
451 rlc_sdu_frags_delete(gpointer data)
453 struct rlc_sdu *sdu = (struct rlc_sdu *)data;
454 struct rlc_frag *frag;
467 rlc_frag_assign(struct rlc_frag *frag, enum rlc_mode mode, packet_info *pinfo,
468 guint16 seq, guint16 li)
470 frag->frame_num = pinfo->fd->num;
475 rlc_channel_assign(&frag->ch, mode, pinfo);
481 rlc_frag_assign_data(struct rlc_frag *frag, tvbuff_t *tvb,
482 guint16 offset, guint16 length)
485 frag->data = (guint8 *)g_malloc(length);
486 tvb_memcpy(tvb, frag->data, offset, length);
490 static struct rlc_frag *
491 rlc_frag_create(tvbuff_t *tvb, enum rlc_mode mode, packet_info *pinfo,
492 guint16 offset, guint16 length, guint16 seq, guint16 li)
494 struct rlc_frag *frag;
496 frag = (struct rlc_frag *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_frag));
497 rlc_frag_assign(frag, mode, pinfo, seq, li);
498 rlc_frag_assign_data(frag, tvb, offset, length);
504 rlc_cmp_seq(gconstpointer a, gconstpointer b)
506 const struct rlc_seq *_a = (const struct rlc_seq *)a, *_b = (const struct rlc_seq *)b;
508 return _a->seq < _b->seq ? -1 :
509 _a->seq > _b->seq ? 1 :
513 static int moduloCompare(guint16 a, guint16 b, guint16 modulus)
522 ret = a - (b + modulus);
524 if( ret == (1 - modulus) ){
530 static guint16 getChannelSNModulus(struct rlc_channel * ch_lookup)
532 if( RLC_UM == ch_lookup->mode){ /*FIXME: This is a very heuristic way to detemine SN bitwidth. */
539 /* "Value destroy" function called each time an entry is removed
540 * from the sequence_table hash.
541 * It frees the GList pointed to by the entry.
544 free_sequence_table_entry_data(gpointer data)
546 struct rlc_seqlist *list = (struct rlc_seqlist *)data;
547 if (list->list != NULL) {
548 g_list_free(list->list);
549 list->list = NULL; /* for good measure */
553 /** Utility functions used for various comparions/cleanups in tree **/
555 rlc_simple_key_cmp(gconstpointer b_ptr, gconstpointer a_ptr, gpointer ignore _U_){
556 if( GPOINTER_TO_INT(a_ptr) > GPOINTER_TO_INT(b_ptr) ){
559 return GPOINTER_TO_INT(a_ptr) < GPOINTER_TO_INT(b_ptr);
563 fragment_table_init(void)
566 if (fragment_table) {
567 g_hash_table_destroy(fragment_table);
570 g_hash_table_destroy(endpoints);
572 if (reassembled_table) {
573 g_hash_table_destroy(reassembled_table);
575 if (sequence_table) {
576 g_hash_table_destroy(sequence_table);
578 if (duplicate_table) {
579 g_hash_table_destroy(duplicate_table);
582 g_tree_destroy(counter_map);
584 fragment_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, NULL);
585 endpoints = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, NULL);
586 reassembled_table = g_hash_table_new_full(rlc_frag_hash, rlc_frag_equal,
587 rlc_frag_delete, rlc_sdu_frags_delete);
588 sequence_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal,
589 NULL, free_sequence_table_entry_data);
590 duplicate_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
592 /*Reset and or clear deciphering variables*/
593 counter_map = g_tree_new_full(rlc_simple_key_cmp,NULL,NULL,rlc_channel_delete);
594 for(i = 0; i< 31; i++ ){
595 ps_counter[i][0] = 0;
596 ps_counter[i][1] = 0;
597 counter_init[i][0] = 0;
598 counter_init[i][1] = 0;
603 /* add the list of fragments for this sdu to 'tree' */
605 tree_add_fragment_list(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
608 proto_tree *frag_tree;
610 struct rlc_frag *sdufrag;
612 ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, -1, ENC_NA);
613 frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
614 proto_item_append_text(ti, " (%u bytes, %u fragments): ",
615 sdu->len, sdu->fragcnt);
616 sdufrag = sdu->frags;
619 if (sdufrag->len > 0) {
620 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
621 sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: %u-%u (%u bytes) (Seq: %u)",
622 sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
624 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
625 sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: none (0 bytes) (Seq: %u)",
626 sdufrag->frame_num, sdufrag->seq);
628 offset += sdufrag->len;
629 sdufrag = sdufrag->next;
633 /* add the list of fragments for this sdu to 'tree' */
635 tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
638 proto_tree *frag_tree;
640 struct rlc_frag *sdufrag;
642 ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, ENC_NA);
643 frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
644 proto_item_append_text(ti, " (%u bytes, %u fragments): ",
645 sdu->len, sdu->fragcnt);
646 sdufrag = sdu->frags;
649 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0,
650 0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
651 sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
652 offset += sdufrag->len;
653 sdufrag = sdufrag->next;
657 /* Add the same description to too the two given proto_items */
659 add_description(proto_item *li_ti, proto_item *length_ti,
660 const char *format, ...)
662 #define MAX_INFO_BUFFER 256
663 static char info_buffer[MAX_INFO_BUFFER];
667 va_start(ap, format);
668 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
671 proto_item_append_text(li_ti, " (%s)", info_buffer);
672 proto_item_append_text(length_ti, " (%s)", info_buffer);
675 /* add information for an LI to 'tree' */
677 tree_add_li(enum rlc_mode mode, struct rlc_li *li, guint8 li_idx, guint8 hdr_offs,
678 gboolean li_is_on_2_bytes, tvbuff_t *tvb, proto_tree *tree)
680 proto_item *root_ti, *ti;
685 if (!tree) return NULL;
687 if (li_is_on_2_bytes) {
688 li_offs = hdr_offs + li_idx*2;
689 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 2, ENC_NA);
690 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
691 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 15, &length, ENC_BIG_ENDIAN);
695 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");
698 if (mode == RLC_UM) {
699 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");
701 add_description(root_ti, ti, "Reserved");
705 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");
708 if (mode == RLC_UM) {
709 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
711 add_description(root_ti, ti, "Reserved");
715 if (mode == RLC_UM) {
716 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");
718 add_description(root_ti, ti, "Reserved");
722 if (mode == RLC_UM) {
723 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");
725 add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
729 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
733 add_description(root_ti, ti, "length=%u", (guint16)length);
736 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+15, 1, ENC_BIG_ENDIAN);
738 li_offs = hdr_offs + li_idx;
739 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 1, ENC_NA);
740 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
741 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 7, &length, ENC_BIG_ENDIAN);
744 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");
747 if (mode == RLC_UM) {
748 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
750 add_description(root_ti, ti, "Reserved");
754 if (mode == RLC_UM) {
755 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");
757 add_description(root_ti, ti, "Reserved");
761 if (mode == RLC_UM) {
762 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");
764 add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
768 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
772 add_description(root_ti, ti, "length=%u", (guint16)length);
775 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+7, 1, ENC_BIG_ENDIAN);
779 if (li->li > tvb_length_remaining(tvb, hdr_offs)) return li_tree;
780 if (li->len > li->li) return li_tree;
781 ti = proto_tree_add_item(li_tree, hf_rlc_li_data, tvb, hdr_offs + li->li - li->len, li->len, ENC_NA);
782 PROTO_ITEM_SET_HIDDEN(ti);
788 /* add a fragment to an SDU */
790 rlc_sdu_add_fragment(enum rlc_mode mode, struct rlc_sdu *sdu, struct rlc_frag *frag)
792 struct rlc_frag *tmp;
795 /* insert as first element */
799 sdu->len += frag->len;
804 /* insert as last element */
805 sdu->last->next = frag;
808 sdu->len += frag->len;
814 /* If receiving exotic border line sequence, e.g. 4094, 4095, 0, 1 */
815 if (frag->seq+2048 < tmp->seq) {
816 while (tmp->next && frag->seq+2048 < tmp->seq)
818 if (tmp->next == NULL) {
822 while (tmp->next && tmp->next->seq < frag->seq)
824 frag->next = tmp->next;
826 if (frag->next == NULL) sdu->last = frag;
828 } else { /* Receiving ordinary sequence */
829 if (frag->seq < tmp->seq) {
830 /* insert as first element */
834 while (tmp->next && tmp->next->seq < frag->seq)
836 frag->next = tmp->next;
838 if (frag->next == NULL) sdu->last = frag;
841 sdu->len += frag->len;
851 reassemble_data(struct rlc_channel *ch, struct rlc_sdu *sdu, struct rlc_frag *frag)
853 struct rlc_frag *temp;
856 if (!sdu || !ch || !sdu->frags) return;
858 if (sdu->data) return; /* already assembled */
861 sdu->reassembled_in = frag;
863 sdu->reassembled_in = sdu->last;
865 sdu->data = (guint8 *)wmem_alloc(wmem_file_scope(), sdu->len);
867 while (temp && ((offs + temp->len) <= sdu->len)) {
868 memcpy(sdu->data + offs, temp->data, temp->len);
871 /* mark this fragment in reassembled table */
872 g_hash_table_insert(reassembled_table, temp, sdu);
879 #define RLC_ADD_FRAGMENT_FAIL_PRINT 0
880 #define RLC_ADD_FRAGMENT_DEBUG_PRINT 0
881 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
883 printends(GList * list)
887 g_print("-> length: %d\n[", g_list_length(list));
890 g_print("%d ", GPOINTER_TO_INT(list->data));
897 static struct rlc_frag **
898 get_frags(packet_info * pinfo, struct rlc_channel * ch_lookup)
900 gpointer value = NULL;
901 struct rlc_frag ** frags = NULL;
902 /* Look for already created frags table */
903 if (g_hash_table_lookup_extended(fragment_table, ch_lookup, NULL, &value)) {
904 frags = (struct rlc_frag **)value;
905 } else if (pinfo != NULL) {
906 struct rlc_channel *ch;
907 ch = rlc_channel_create(ch_lookup->mode, pinfo);
908 frags = (struct rlc_frag **)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_frag *) * 4096);
909 g_hash_table_insert(fragment_table, ch, frags);
915 static struct rlc_seqlist *
916 get_endlist(packet_info * pinfo, struct rlc_channel * ch_lookup)
918 gpointer value = NULL;
919 struct rlc_seqlist * endlist = NULL;
920 /* If there already exists a frag table for this channel use that one. */
921 if (g_hash_table_lookup_extended(endpoints, ch_lookup, NULL, &value)) {
922 endlist = (struct rlc_seqlist *)value;
923 } else if (pinfo != NULL) { /* Else create a new one. */
924 struct rlc_channel * ch;
926 endlist = wmem_new(wmem_file_scope(), struct rlc_seqlist);
927 ch = rlc_channel_create(ch_lookup->mode, pinfo);
928 endlist->fail_packet = 0;
929 endlist->list = NULL;
930 endlist->list = g_list_prepend(endlist->list, GINT_TO_POINTER(-1));
931 g_hash_table_insert(endpoints, ch, endlist);
939 reassemble_sequence(struct rlc_frag ** frags, struct rlc_seqlist * endlist,
940 struct rlc_channel * ch_lookup, guint16 start, guint16 end)
942 GList * element = NULL;
943 struct rlc_sdu * sdu = rlc_sdu_create();
945 guint16 snmod = getChannelSNModulus(ch_lookup);
947 /* Insert fragments into SDU. */
948 for (; moduloCompare(start,end,snmod ) <= 0; start = (start+1)%snmod)
950 struct rlc_frag * tempfrag = NULL;
951 tempfrag = frags[start]->next;
952 frags[start]->next = NULL;
953 rlc_sdu_add_fragment(ch_lookup->mode, sdu, frags[start]);
954 frags[start] = tempfrag;
957 /* Remove first endpoint. */
958 element = g_list_first(endlist->list);
960 endlist->list = g_list_remove_link(endlist->list, element);
961 if (frags[end] != NULL) {
963 endlist->list->data = GINT_TO_POINTER((GPOINTER_TO_INT(endlist->list->data) - 1 + snmod) % snmod);
967 reassemble_data(ch_lookup, sdu, NULL);
970 /* Reset the specified channel's reassembly data, useful for when a sequence
971 * resets on transport channel swap. */
973 rlc_reset_channel(enum rlc_mode mode, guint8 rbid, guint8 dir, guint32 urnti)
975 struct rlc_frag ** frags = NULL;
976 struct rlc_seqlist * endlist = NULL;
977 struct rlc_channel ch_lookup;
980 ch_lookup.mode = mode;
981 ch_lookup.rbid = rbid;
983 ch_lookup.urnti = urnti;
984 frags = get_frags(NULL, &ch_lookup);
985 endlist = get_endlist(NULL, &ch_lookup);
986 DISSECTOR_ASSERT(frags && endlist);
988 endlist->fail_packet = 0;
989 g_list_free(endlist->list);
990 endlist->list = NULL;
992 for (i = 0; i < 4096; i++) {
997 /* add a new fragment to an SDU
998 * if length == 0, just finalize the specified SDU
1000 static struct rlc_frag *
1001 add_fragment(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
1002 proto_tree *tree, guint16 offset, guint16 seq, guint16 num_li,
1003 guint16 len, gboolean final)
1005 struct rlc_channel ch_lookup;
1006 struct rlc_frag frag_lookup, *frag = NULL;
1007 gpointer orig_key = NULL, value = NULL;
1008 struct rlc_sdu *sdu = NULL;
1009 struct rlc_frag ** frags = NULL;
1010 struct rlc_seqlist * endlist = NULL;
1011 GList * element = NULL;
1014 if (rlc_channel_assign(&ch_lookup, mode, pinfo) == -1) {
1017 rlc_frag_assign(&frag_lookup, mode, pinfo, seq, num_li);
1018 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1019 g_print("packet: %d, channel (%d %d %d) seq: %u, num_li: %u, offset: %u, \n", pinfo->fd->num, ch_lookup.dir, ch_lookup.rbid, ch_lookup.urnti, seq, num_li, offset);
1022 snmod = getChannelSNModulus(&ch_lookup);
1024 /* look for an already assembled SDU */
1025 if (g_hash_table_lookup_extended(reassembled_table, &frag_lookup, &orig_key, &value)) {
1026 /* this fragment is already reassembled somewhere */
1027 frag = (struct rlc_frag *)orig_key;
1028 sdu = (struct rlc_sdu *)value;
1030 /* mark the fragment, if reassembly happened somewhere else */
1031 if (frag->seq != sdu->reassembled_in->seq ||
1032 frag->li != sdu->reassembled_in->li)
1033 proto_tree_add_uint(tree, hf_rlc_reassembled_in, tvb, 0, 0,
1034 sdu->reassembled_in->frame_num);
1039 frags = get_frags(pinfo, &ch_lookup);
1040 endlist = get_endlist(pinfo, &ch_lookup);
1042 /* If already done reassembly */
1043 if (pinfo->fd->flags.visited) {
1044 if (tree && len > 0) {
1045 if (endlist->list && endlist->list->next) {
1046 gint16 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1047 gint16 end = GPOINTER_TO_INT(endlist->list->next->data);
1048 gint16 missing = start;
1049 gboolean wecanreasmmore = TRUE;
1051 for (; moduloCompare(missing,end,snmod ) <= 0; missing = (missing+1)%snmod)
1053 if (frags[missing] == NULL) {
1054 wecanreasmmore = FALSE;
1059 if (wecanreasmmore) {
1060 reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1062 if (end >= 0 && end < snmod && frags[end]) {
1063 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1064 "Did not perform reassembly because of unfinished sequence (%d->%d [packet %u]), could not find %d.", start, end, frags[end]->frame_num, missing);
1066 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1067 "Did not perform reassembly because of unfinished sequence (%d->%d [could not determine packet]), could not find %d.", start, end, missing);
1070 } else if (endlist->list) {
1071 if (endlist->fail_packet != 0 && endlist->fail_packet <= pinfo->fd->num) {
1072 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_flag_set, tvb, 0, 0, "Did not perform reassembly because fail flag was set in packet %u.", endlist->fail_packet);
1074 gint16 end = GPOINTER_TO_INT(endlist->list->data);
1075 if (end >= 0 && end < snmod && frags[end]) {
1076 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [packet %d]).", end, frags[end]->frame_num);
1078 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [could not determine packet]).", end);
1082 expert_add_info(pinfo, NULL, &ei_rlc_reassembly_unknown_error);
1085 return NULL; /* If already done reassembly and no SDU found, too bad */
1088 if (endlist->fail_packet != 0) { /* don't continue after sh*t has hit the fan */
1092 frag = rlc_frag_create(tvb, mode, pinfo, offset, len, seq, num_li);
1094 /* If frags[seq] is not NULL then we must have data from several PDUs in the
1095 * same RLC packet (using Length Indicators) or something has gone terribly
1097 if (frags[seq] != NULL) {
1099 struct rlc_frag * tempfrag = frags[seq];
1100 while (tempfrag->next != NULL)
1101 tempfrag = tempfrag->next;
1102 tempfrag->next = frag;
1103 } else { /* This should never happen */
1104 endlist->fail_packet = pinfo->fd->num;
1111 /* It is also possible that frags[seq] is NULL even though we do have data
1112 * from several PDUs in the same RLC packet. This is if the reassembly is
1113 * not lagging behind at all because of perfectly ordered sequences. */
1114 if (endlist->list && num_li != 0) {
1115 gint16 first = GPOINTER_TO_INT(endlist->list->data);
1117 endlist->list->data = GINT_TO_POINTER(first-1);
1121 /* If this is an endpoint */
1123 endlist->list = g_list_append(endlist->list, GINT_TO_POINTER((gint)seq));
1126 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1127 printends(endlist->list);
1130 /* Try to reassemble SDU. */
1131 if (endlist->list && endlist->list->next) {
1132 gint16 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1133 gint16 end = GPOINTER_TO_INT(endlist->list->next->data);
1134 if (frags[end] == NULL) {
1135 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1136 g_warning("frag[end] is null, this is probably because end was a startpoint but because of some error ended up being treated as an endpoint, setting fail flag, start %d, end %d, packet %u\n", start, end, pinfo->fd->num);
1138 endlist->fail_packet = pinfo->fd->num;
1142 /* If our endpoint is a LI=0 with no data. */
1143 if (start == end && frags[start]->len == 0) {
1144 element = g_list_first(endlist->list);
1146 endlist->list = g_list_remove_link(endlist->list, element);
1148 frags[start] = frags[start]->next;
1150 /* If frags[start] is not NULL now, then that means that there was
1151 * another fragment with the same seq number because of LI. If we
1152 * don't decrease the endpoint by 1 then that fragment will be
1153 * skipped and all hell will break lose. */
1154 if (frags[start] != NULL) {
1155 endlist->list->data = GINT_TO_POINTER(start-1);
1157 /* NOTE: frags[start] is wmem_alloced and will remain until file closes, we would want to free it here maybe. */
1161 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1162 g_print("start: %d, end: %d\n",start, end);
1165 for (; moduloCompare(start,end,snmod ) < 0; start = (start+1)%snmod)
1167 if (frags[start] == NULL) {
1168 if (MIN((start-seq+snmod)%snmod, (seq-start+snmod)%snmod) >= snmod/4) {
1169 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1171 "Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1172 too far away from an unfinished sequence (%u->%u). The missing sequence number \
1173 is %u. The most recently complete sequence ended in packet %u.", pinfo->fd->num, seq, 0, end, start, 0);
1175 endlist->fail_packet = pinfo->fd->num; /* If it has gone too far, give up */
1181 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1182 reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1183 } else if (endlist->list) {
1184 gint16 first = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1185 /* If the distance between the oldest stored endpoint in endlist and
1186 * this endpoint is too large, set fail flag. */
1187 if (MIN((first-seq+snmod)%snmod, (seq-first+snmod)%snmod) >= snmod/4) {
1188 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1190 "Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1191 too far away from an unfinished sequence with start %u and without end.", pinfo->fd->num, seq, first);
1193 endlist->fail_packet = pinfo->fd->num; /* Give up if things have gone too far. */
1201 /* is_data is used to identify rlc data parts that are not identified by an LI, but are at the end of
1203 * these can be valid reassembly points, but only if the LI of the *next* relevant RLC frame is
1204 * set to '0' (this is indicated in the reassembled SDU
1207 get_reassembled_data(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
1208 proto_tree *tree, guint16 seq, guint16 num_li)
1210 gpointer orig_frag, orig_sdu;
1211 struct rlc_sdu *sdu;
1212 struct rlc_frag lookup, *frag;
1214 rlc_frag_assign(&lookup, mode, pinfo, seq, num_li);
1216 if (!g_hash_table_lookup_extended(reassembled_table, &lookup,
1217 &orig_frag, &orig_sdu))
1220 sdu = (struct rlc_sdu *)orig_sdu;
1221 if (!sdu || !sdu->data)
1226 if (!rlc_frag_equal(&lookup, sdu->reassembled_in)) return NULL;
1231 while (frag->next) {
1232 if (frag->next->seq - frag->seq > 1) {
1233 proto_item *pi = proto_tree_add_text(tree, tvb, 0, 0,
1234 "Error: Incomplete sequence");
1235 PROTO_ITEM_SET_GENERATED(pi);
1236 tree_add_fragment_list_incomplete(sdu, tvb, tree);
1242 sdu->tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->len, sdu->len);
1243 add_new_data_source(pinfo, sdu->tvb, "Reassembled RLC Message");
1245 /* reassembly happened here, so create the fragment list */
1246 if (tree && sdu->fragcnt > 1)
1247 tree_add_fragment_list(sdu, sdu->tvb, tree);
1252 #define RLC_RETRANSMISSION_TIMEOUT 5 /* in seconds */
1254 rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, guint16 seq,
1258 struct rlc_seqlist lookup, *list;
1259 struct rlc_seq seq_item, *seq_new;
1262 rlc_channel_assign(&lookup.ch, mode, pinfo);
1263 list = (struct rlc_seqlist *)g_hash_table_lookup(sequence_table, &lookup.ch);
1265 /* we see this channel for the first time */
1266 list = (struct rlc_seqlist *)wmem_alloc0(wmem_file_scope(), sizeof(*list));
1267 rlc_channel_assign(&list->ch, mode, pinfo);
1268 g_hash_table_insert(sequence_table, &list->ch, list);
1271 seq_item.frame_num = pinfo->fd->num;
1273 /* When seq is 12 bit (in RLC protocol), it will wrap around after 4096. */
1274 /* Window size is at most 4095 so we remove packets further away than that */
1275 element = g_list_first(list->list);
1276 snmod = getChannelSNModulus(&lookup.ch);
1278 seq_new = (struct rlc_seq *)element->data;
1279 /* Add SN modulus because %-operation for negative values in C is not equal to mathematical modulus */
1280 if (MIN((seq_new->seq-seq+snmod)%snmod, (seq-seq_new->seq+snmod)%snmod) >= snmod/4) {
1281 list->list = g_list_remove_link(list->list, element);
1285 element = g_list_find_custom(list->list, &seq_item, rlc_cmp_seq);
1287 seq_new = (struct rlc_seq *)element->data;
1288 if (seq_new->frame_num != seq_item.frame_num) {
1290 nstime_delta(&delta, &pinfo->fd->abs_ts, &seq_new->arrival);
1291 if (delta.secs < RLC_RETRANSMISSION_TIMEOUT) {
1293 *original = seq_new->frame_num;
1298 return FALSE; /* we revisit the seq that was already seen */
1300 seq_new = (struct rlc_seq *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_seq));
1301 *seq_new = seq_item;
1302 seq_new->arrival = pinfo->fd->abs_ts;
1303 list->list = g_list_append(list->list, seq_new); /* insert in order of arrival */
1308 rlc_call_subdissector(enum rlc_channel_type channel, tvbuff_t *tvb,
1309 packet_info *pinfo, proto_tree *tree)
1311 enum rrc_message_type msgtype;
1314 msgtype = RRC_MESSAGE_TYPE_UL_CCCH;
1317 msgtype = RRC_MESSAGE_TYPE_DL_CCCH;
1320 msgtype = RRC_MESSAGE_TYPE_INVALID;
1321 call_dissector(bmc_handle, tvb, pinfo, tree);
1324 msgtype = RRC_MESSAGE_TYPE_UL_DCCH;
1327 msgtype = RRC_MESSAGE_TYPE_DL_DCCH;
1330 msgtype = RRC_MESSAGE_TYPE_PCCH;
1333 msgtype = RRC_MESSAGE_TYPE_BCCH_FACH;
1336 msgtype = RRC_MESSAGE_TYPE_INVALID;
1337 /* assume transparent PDCP for now */
1338 call_dissector(ip_handle, tvb, pinfo, tree);
1339 /* once the packet has been dissected, protect it from further changes */
1340 col_set_writable(pinfo->cinfo, FALSE);
1343 return; /* stop dissecting */
1345 if (msgtype != RRC_MESSAGE_TYPE_INVALID) {
1346 struct rrc_info *rrcinf;
1348 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1349 rrcinf = (rrc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0);
1351 rrcinf = (rrc_info *)wmem_alloc0(wmem_file_scope(), sizeof(struct rrc_info));
1352 p_add_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0, rrcinf);
1354 rrcinf->msgtype[fpinf->cur_tb] = msgtype;
1355 call_dissector(rrc_handle, tvb, pinfo, tree);
1356 /* once the packet has been dissected, protect it from further changes */
1357 col_set_writable(pinfo->cinfo, FALSE);
1362 add_channel_info(packet_info * pinfo, proto_tree * tree, fp_info * fpinf, rlc_info * rlcinf)
1365 proto_tree * channel_tree ;
1367 item = proto_tree_add_item(tree, hf_rlc_channel, NULL, 0, 0, ENC_NA);
1368 channel_tree = proto_item_add_subtree(item, ett_rlc_channel);
1369 proto_item_append_text(item, " (rbid: %u, dir: %s, uid: %u)", rlcinf->rbid[fpinf->cur_tb],
1370 val_to_str_const(pinfo->p2p_dir, rlc_dir_vals, "Unknown"), rlcinf->urnti[fpinf->cur_tb]);
1371 PROTO_ITEM_SET_GENERATED(item);
1372 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_rbid, NULL, 0, 0, rlcinf->rbid[fpinf->cur_tb]);
1373 PROTO_ITEM_SET_GENERATED(item);
1374 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_dir, NULL, 0, 0, pinfo->p2p_dir);
1375 PROTO_ITEM_SET_GENERATED(item);
1376 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_ueid, NULL, 0, 0, rlcinf->urnti[fpinf->cur_tb]);
1377 PROTO_ITEM_SET_GENERATED(item);
1381 #ifdef HAVE_UMTS_KASUMI
1383 translate_hex_key(gchar * char_key){
1387 key_in = g_malloc0(sizeof(guint8)*16);
1388 j= (int)(strlen(char_key)/2)-1;
1389 /*Translate "hex-string" into a byte aligned block */
1390 for(i = (int)strlen(char_key); i> 0; i-=2 ){
1391 key_in[j] = ( (guint8) (strtol( &char_key[i-2], NULL, 16 ) ));
1392 char_key[i-2] = '\0';
1400 /** @brief Deciphers a given tvb
1402 * Note that the actual KASUMI implementation needs to be placed into
1403 * epan/crypt/kasumi.* by "end users" since due to patents the acutal implementation
1404 * cannot be distributed openly at the moment.
1406 * Refer to 3GPP TS 35.201 and 3GPP TS 35.202 for further information.
1408 * @param tvb The ciphered data.
1409 * @param pinfo Packet info.
1410 * @param counter the COUNTER value input
1411 * @param rbid the radiobear id
1412 * @param dir Direction of the link
1413 * @param header_size Size of the unciphered header
1414 * @return tvb Returns a deciphered tvb
1417 #ifndef HAVE_UMTS_KASUMI
1418 rlc_decipher_tvb(tvbuff_t *tvb _U_, packet_info *pinfo, guint32 counter _U_,
1419 guint8 rbid _U_, gboolean dir _U_, guint8 header_size _U_) {
1420 /*Check if we have a KASUMI implementation*/
1421 expert_add_info(pinfo, NULL, &ei_rlc_kasumi_implementation_missing);
1424 rlc_decipher_tvb(tvbuff_t *tvb, packet_info *pinfo, guint32 counter, guint8 rbid, gboolean dir, guint8 header_size) {
1426 guint8* out=NULL,*key_in = NULL;
1429 /*Fix the key into a byte block*/
1430 /*TODO: This should be done in a preferences callback function*/
1431 out = wmem_alloc0(wmem_packet_scope(), strlen(global_rlc_kasumi_key)+1);
1432 memcpy(out,global_rlc_kasumi_key,strlen(global_rlc_kasumi_key)); /*Copy from prefrence const pointer*/
1433 key_in = translate_hex_key(out); /*Translation*/
1435 /*Location for decrypted data*/
1436 out = g_malloc( tvb_length(tvb) );
1438 /*Build data input but dont send the header*/
1439 for(i = 0; i< tvb_length(tvb)-header_size; i++ ){
1440 out[i+header_size] = tvb_get_guint8(tvb, header_size+i);
1442 /*Call KASUMI confidentiality function, note that rbid is zero indxed*/
1443 f8( key_in, counter, rbid-1, dir, &out[header_size], (tvb_length(tvb)-header_size)*8 );
1445 /*Restore header in tvb*/
1446 for (i = 0; i < header_size; i++) {
1447 out[i] = tvb_get_guint8(tvb, i);
1451 t = tvb_new_real_data(out,tvb_length(tvb), tvb_reported_length(tvb));
1452 /*add_new_data_source(pinfo, tvb, "Data enciphered");*/
1453 add_new_data_source(pinfo, t, "Deciphered data");
1455 #endif /* HAVE_UMTS_KASUMI */
1459 * @param key is created with GINT_TO_POINTER
1460 * @param value is a pointer to a guint32
1461 * @param data is a pointer to a guint32
1464 iter_same(gpointer key, gpointer value, gpointer data) {
1465 /*If true we found the correct frame*/
1466 if ((guint32)GPOINTER_TO_INT(key) > *(guint32*)data){
1467 *((guint32*)data) = *((guint32*)value);
1470 *((guint32*)data) = (guint32)GPOINTER_TO_INT(key);
1476 * Used for looking up and old ciphering counter value in the counter_map tree.
1477 * @param key is created with GINT_TO_POINTER
1478 * @param value is pointer to an array of 2 guint32s
1479 * @param data is a pointer to an array of 3 guint32s
1482 rlc_find_old_counter(gpointer key, gpointer value, gpointer data) {
1484 /*If true we found the correct frame*/
1485 if( (guint32)GPOINTER_TO_INT(key) >= ((guint32 *)data)[0] ){
1488 /*Overwrite the data since the previous one wasn't correct*/
1489 ((guint32*)data)[1] = ((guint32*)value)[0];
1490 ((guint32*)data)[2] = ((guint32*)value)[1];
1496 rlc_decipher(tvbuff_t *tvb, packet_info * pinfo, proto_tree * tree, fp_info * fpinf,
1497 rlc_info * rlcinf, guint16 seq, enum rlc_mode mode)
1499 rrc_ciphering_info * c_inf;
1500 guint8 indx, header_size, hfn_shift;
1503 indx = fpinf->is_uplink ? 1 : 0;
1504 pos = fpinf->cur_tb;
1505 if (mode ==RLC_UM) {
1513 /*Ciphering info singled in RRC by securitymodecommands */
1514 c_inf = (rrc_ciphering_info *)g_tree_lookup(rrc_ciph_inf, GINT_TO_POINTER((gint)fpinf->com_context_id));
1516 /*TODO: This doesnt really work for all packets..*/
1517 /*Check if we have ciphering info and that this frame is ciphered*/
1518 if(c_inf!=NULL && ( (c_inf->setup_frame > 0 && c_inf->setup_frame < pinfo->fd->num && c_inf->seq_no[rlcinf->rbid[pos]][indx] == -1) ||
1519 (c_inf->setup_frame < pinfo->fd->num && c_inf->seq_no[rlcinf->rbid[pos]][indx] >= 0 && c_inf->seq_no[rlcinf->rbid[pos]][indx] <= seq) )){
1523 /*Check if this counter has been initialized*/
1524 if(!counter_init[rlcinf->rbid[pos]][indx] ){
1525 guint32 frame_num = pinfo->fd->num;
1527 /*Initializes counter*/
1528 counter_init[rlcinf->rbid[pos]][0] = TRUE;
1529 counter_init[rlcinf->rbid[pos]][1] = TRUE;
1530 /*Find apropriate start value*/
1531 g_tree_foreach(c_inf->start_ps, (GTraverseFunc)iter_same, &frame_num);
1533 /*Set COUNTER value accordingly as specified by 6.4.8 in 3GPP TS 33.102 */
1534 if(max_counter +2 > frame_num && c_inf->seq_no[rlcinf->rbid[pos]][indx] == -1){
1535 ps_counter[rlcinf->rbid[pos]][0] = (max_counter+2) << hfn_shift;
1536 ps_counter[rlcinf->rbid[pos]][1] = (max_counter+2) << hfn_shift;
1538 ps_counter[rlcinf->rbid[pos]][0] = frame_num << hfn_shift;
1539 ps_counter[rlcinf->rbid[pos]][1] = frame_num << hfn_shift;
1543 /*Preserve counter value for next dissection round*/
1545 ciph = (guint32 *)g_malloc(sizeof(guint32)*2);
1546 ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1547 ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1548 g_tree_insert(counter_map, GINT_TO_POINTER((gint)pinfo->fd->num), ciph);
1552 /*Update the maximal COUNTER value seen so far*/
1553 max_counter = MAX(max_counter,((ps_counter[rlcinf->rbid[pos]][indx]) | seq) >> hfn_shift);
1555 /*XXX:Since RBID in umts isnt configured properly..*/
1556 if(rlcinf->rbid[pos] == 9 ){
1558 guint32 frame_num[3];
1559 /*Set frame num we will be "searching" around*/
1560 frame_num[0] = pinfo->fd->num;
1561 /*Find the correct counter value*/
1562 g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1563 t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),16,!fpinf->is_uplink,header_size);
1565 t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),16,!fpinf->is_uplink,header_size);
1569 /*We need to find the original counter value for second dissection pass*/
1570 guint32 frame_num[3];
1571 frame_num[0] = pinfo->fd->num;
1572 g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1573 t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1575 t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1578 /*Update the hyperframe number*/
1581 ps_counter[rlcinf->rbid[pos]][indx] += 1 << hfn_shift;
1583 if(!tree){/*Preserve counter for second packet analysis run*/
1585 ciph = (guint32 *)g_malloc(sizeof(guint32)*2);
1586 ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1587 ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1588 g_tree_insert(counter_map, GINT_TO_POINTER((gint)pinfo->fd->num+1), ciph);
1592 /*Unable to decipher the packet*/
1594 proto_tree_add_text(tree, tvb, 0, -1,
1595 "Cannot dissect RLC frame because it is ciphered");
1596 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1600 col_append_str(pinfo->cinfo, COL_INFO, "[Deciphered Data]");
1602 /*TODO: Old tvb should be freed here?*/
1608 dissect_rlc_tm(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1609 proto_tree *top_level, proto_tree *tree)
1614 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1615 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
1618 if (fpinf && rlcinf) {
1619 /* Add "channel" information, very useful for debugging. */
1620 add_channel_info(pinfo, tree, fpinf, rlcinf);
1622 proto_tree_add_item(tree, hf_rlc_data, tvb, 0, -1, ENC_NA);
1624 rlc_call_subdissector(channel, tvb, pinfo, top_level);
1629 rlc_um_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo, proto_tree *tree,
1630 proto_tree *top_level, enum rlc_channel_type channel, guint16 seq,
1631 struct rlc_li *li, guint16 num_li, gboolean li_is_on_2_bytes)
1634 gboolean dissected = FALSE;
1636 tvbuff_t *next_tvb = NULL;
1638 /* perform reassembly now */
1639 for (i = 0; i < num_li; i++) {
1640 if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
1641 /* padding, must be last LI */
1643 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, tvb_length_remaining(tvb, offs), ENC_NA);
1645 offs += tvb_length_remaining(tvb, offs);
1646 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7c)) || (li[i].li == 0x7ffc)) {
1647 /* a new SDU starts here, mark this seq as the first PDU. */
1648 struct rlc_channel ch_lookup;
1649 struct rlc_seqlist * endlist = NULL;
1650 if( -1 != rlc_channel_assign(&ch_lookup, RLC_UM, pinfo ) ){
1651 endlist = get_endlist(pinfo, &ch_lookup);
1652 endlist->list->data = GINT_TO_POINTER((gint)seq);
1653 endlist->fail_packet=0;
1656 } else if (li[i].li == 0x7ffa) {
1657 /* the first data octet in this RLC PDU is the first octet of an RLC SDU
1658 and the second last octet in this RLC PDU is the last octet of the same RLC SDU */
1659 length = tvb_length_remaining(tvb, offs);
1662 if (tree && length) {
1663 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, length, ENC_NA);
1665 if (global_rlc_perform_reassemby) {
1666 add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, length, TRUE);
1667 next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i);
1672 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, 1, ENC_NA);
1676 if (tree && li[i].len) {
1677 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
1679 if (global_rlc_perform_reassemby) {
1680 add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE);
1681 next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i);
1686 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1692 /* is there data left? */
1693 if (tvb_length_remaining(tvb, offs) > 0) {
1695 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
1697 if (global_rlc_perform_reassemby) {
1698 /* add remaining data as fragment */
1699 add_fragment(RLC_UM, tvb, pinfo, tree, offs, seq, i, tvb_length_remaining(tvb, offs), FALSE);
1700 if (dissected == FALSE)
1701 col_set_str(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]");
1704 if (dissected == FALSE)
1705 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] SN=%u", seq);
1707 if (channel == RLC_UNKNOWN_CH)
1708 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Data] SN=%u", seq);
1712 rlc_decode_li(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1713 struct rlc_li *li, guint8 max_li, gboolean li_on_2_bytes)
1715 guint8 ext, hdr_len, offs = 0, num_li = 0, li_offs;
1716 guint16 next_bytes, prev_li = 0;
1717 proto_item *malformed;
1729 case RLC_UNKNOWN_MODE:
1734 /* calculate header length */
1735 ext = tvb_get_guint8(tvb, hdr_len++) & 0x01;
1737 next_bytes = li_on_2_bytes ? tvb_get_ntohs(tvb, hdr_len) : tvb_get_guint8(tvb, hdr_len);
1738 ext = next_bytes & 0x01;
1739 hdr_len += li_on_2_bytes ? 2 : 1;
1741 total_len = tvb_length_remaining(tvb, hdr_len);
1743 /* do actual evaluation of LIs */
1744 ext = tvb_get_guint8(tvb, offs++) & 0x01;
1747 if (li_on_2_bytes) {
1748 next_bytes = tvb_get_ntohs(tvb, offs);
1751 next_bytes = tvb_get_guint8(tvb, offs++);
1753 ext = next_bytes & 0x01;
1754 li[num_li].ext = ext;
1755 li[num_li].li = next_bytes >> 1;
1757 if (li_on_2_bytes) {
1758 switch (li[num_li].li) {
1759 case 0x0000: /* previous segment was the last one */
1760 case 0x7ffb: /* previous PDU contains last segment of SDU (minus last byte) */
1761 case 0x7ffe: /* contains piggybacked STATUS in AM or segment in UM */
1762 case 0x7fff: /* padding */
1765 case 0x7ffa: /* contains exactly one SDU (minus last byte), UM only */
1766 case 0x7ffc: /* start of a new SDU, UM only */
1767 case 0x7ffd: /* contains exactly one SDU, UM only */
1768 if (mode == RLC_UM) {
1774 /* add malformed LI for investigation */
1775 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1776 expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1777 return -1; /* just give up on this */
1779 /* since the LI is an offset (from the end of the header), it
1780 * may not be larger than the total remaining length and no
1781 * LI may be smaller than its preceding one
1783 if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1784 || (li[num_li].li < prev_li)) {
1785 /* add malformed LI for investigation */
1786 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1787 expert_add_info(pinfo, malformed, &ei_rlc_li_incorrect_warn);
1788 return -1; /* just give up on this */
1790 li[num_li].len = li[num_li].li - prev_li;
1791 prev_li = li[num_li].li;
1794 switch (li[num_li].li) {
1795 case 0x00: /* previous segment was the last one */
1796 case 0x7e: /* contains piggybacked STATUS in AM or segment in UM */
1797 case 0x7f: /* padding */
1800 case 0x7c: /* start of a new SDU, UM only */
1801 case 0x7d: /* contains exactly one SDU, UM only */
1802 if (mode == RLC_UM) {
1808 /* add malformed LI for investigation */
1809 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1810 expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1811 return -1; /* just give up on this */
1813 /* since the LI is an offset (from the end of the header), it
1814 * may not be larger than the total remaining length and no
1815 * LI may be smaller than its preceding one
1817 li[num_li].len = li[num_li].li - prev_li;
1818 if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1819 || (li[num_li].li < prev_li)) {
1820 /* add malformed LI for investigation */
1821 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1822 expert_add_info_format(pinfo, malformed, &ei_rlc_li_incorrect_mal, "Incorrect LI value 0x%x", li[num_li].li);
1823 return -1; /* just give up on this */
1825 prev_li = li[num_li].li;
1828 li[num_li].tree = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1831 if (num_li > max_li) {
1832 /* OK, so this is not really a malformed packet, but for now,
1833 * we will treat it as such, so that it is marked in some way */
1834 expert_add_info(pinfo, li[num_li-1].tree, &ei_rlc_li_too_many);
1842 dissect_rlc_um(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1843 proto_tree *top_level, proto_tree *tree)
1846 struct rlc_li li[MAX_LI];
1851 guint8 next_byte, offs = 0;
1852 gint16 pos, num_li = 0;
1853 gboolean is_truncated, li_is_on_2_bytes;
1854 proto_item *truncated_ti;
1856 next_byte = tvb_get_guint8(tvb, offs++);
1857 seq = next_byte >> 1;
1859 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1860 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
1863 if (fpinf && rlcinf) {
1864 /* Add "channel" information, very useful for debugging. */
1865 add_channel_info(pinfo, tree, fpinf, rlcinf);
1867 /* show sequence number and extension bit */
1868 proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 0, 7, ENC_BIG_ENDIAN);
1869 proto_tree_add_bits_item(tree, hf_rlc_ext, tvb, 7, 1, ENC_BIG_ENDIAN);
1872 if (!fpinf || !rlcinf) {
1873 proto_tree_add_text(tree, tvb, 0, -1,
1874 "Cannot dissect RLC frame because per-frame info is missing");
1878 pos = fpinf->cur_tb;
1880 if ((rlcinf->ciphered[pos] == TRUE && rlcinf->deciphered[pos] == FALSE) || global_rlc_ciphered) {
1881 if(global_rlc_try_decipher){
1882 rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_UM);
1884 proto_tree_add_text(tree, tvb, 0, -1,
1885 "Cannot dissect RLC frame because it is ciphered");
1886 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1891 if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
1892 if (rlcinf->li_size[pos] == RLC_LI_VARIABLE) {
1893 li_is_on_2_bytes = (tvb_length(tvb) > 125) ? TRUE : FALSE;
1895 li_is_on_2_bytes = (rlcinf->li_size[pos] == RLC_LI_15BITS) ? TRUE : FALSE;
1897 } else { /* Override rlcinf configuration with preference. */
1898 li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? TRUE : FALSE;
1903 num_li = rlc_decode_li(RLC_UM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
1904 if (num_li == -1) return; /* something went wrong */
1905 offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
1907 if (global_rlc_headers_expected) {
1908 /* There might not be any data, if only header was logged */
1909 is_truncated = (tvb_length_remaining(tvb, offs) == 0);
1910 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
1913 PROTO_ITEM_SET_GENERATED(truncated_ti);
1914 expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
1917 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1921 /* do not detect duplicates or reassemble, if prefiltering is done */
1922 if (pinfo->fd->num == 0) return;
1923 /* check for duplicates */
1924 if (rlc_is_duplicate(RLC_UM, pinfo, seq, &orig_num) == TRUE) {
1925 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] [Duplicate] SN=%u", seq);
1926 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, orig_num);
1929 rlc_um_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, li, num_li, li_is_on_2_bytes);
1933 dissect_rlc_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint8 offset)
1935 guint8 sufi_type, bits;
1936 guint64 len, sn, wsn, lsn, l;
1937 guint16 value, previous_sn;
1938 gboolean isErrorBurstInd;
1939 gint bit_offset, previous_bit_offset;
1941 proto_tree *sufi_tree, *bitmap_tree, *rlist_tree;
1942 proto_item *sufi_item, *ti;
1943 #define BUFF_SIZE 41
1946 guint8 sufi_start_offset;
1947 gboolean seen_last = FALSE;
1948 guint16 number_of_bitmap_entries = 0;
1950 bit_offset = offset*8 + 4; /* first SUFI type is always 4 bit shifted */
1952 while (!seen_last && tvb_length_remaining(tvb, bit_offset/8) > 0) {
1954 sufi_type = tvb_get_bits8(tvb, bit_offset, 4);
1955 sufi_start_offset = bit_offset/8;
1956 sufi_item = proto_tree_add_item(tree, hf_rlc_sufi, tvb, sufi_start_offset, 0, ENC_NA);
1957 sufi_tree = proto_item_add_subtree(sufi_item, ett_rlc_sufi);
1958 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_type, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
1959 proto_item_append_text(sufi_item, " (%s)", val_to_str_const(sufi_type, rlc_sufi_vals, "Unknown"));
1961 switch (sufi_type) {
1962 case RLC_SUFI_NOMORE:
1966 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_lsn, tvb, bit_offset, 12, &lsn, ENC_BIG_ENDIAN);
1967 col_append_fstr(pinfo->cinfo, COL_INFO, " LSN=%u", (guint16)lsn);
1968 proto_item_append_text(sufi_item, " LSN=%u", (guint16)lsn);
1972 case RLC_SUFI_WINDOW:
1973 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_wsn, tvb, bit_offset, 12, &wsn, ENC_BIG_ENDIAN);
1974 col_append_fstr(pinfo->cinfo, COL_INFO, " WSN=%u", (guint16)wsn);
1978 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
1979 col_append_fstr(pinfo->cinfo, COL_INFO, " LIST(%u) - ", (guint8)len);
1983 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
1984 proto_item_append_text(ti, " (AMD PDU not correctly received)");
1986 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_l, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
1988 proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)",
1989 (unsigned)(sn+l)&0xfff);
1990 col_append_fstr(pinfo->cinfo, COL_INFO, "%u-%u ", (guint16)sn, (unsigned)(sn+l)&0xfff);
1993 col_append_fstr(pinfo->cinfo, COL_INFO, "%u ", (guint16)sn);
1999 expert_add_info(pinfo, tree, &ei_rlc_sufi_len);
2002 case RLC_SUFI_BITMAP:
2003 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2005 len++; /* bitmap is len + 1 */
2006 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2008 proto_tree_add_item(sufi_tree, hf_rlc_sufi_bitmap, tvb, bit_offset/8, (gint)len, ENC_NA);
2009 ti = proto_tree_add_text(sufi_tree, tvb, bit_offset/8, (gint)len, "Decoded bitmap:");
2010 col_append_str(pinfo->cinfo, COL_INFO, " BITMAP=(");
2012 bitmap_tree = proto_item_add_subtree(ti, ett_rlc_bitmap);
2013 buff = (gchar *)wmem_alloc(wmem_packet_scope(), BUFF_SIZE);
2014 for (i=0; i<len; i++) {
2015 bits = tvb_get_bits8(tvb, bit_offset, 8);
2016 for (l=0, j=0; l<8; l++) {
2017 if ((bits << l) & 0x80) {
2018 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%4u,", (unsigned)(sn+(8*i)+l)&0xfff);
2019 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", (unsigned)(sn+(8*i)+l)&0xfff);
2020 number_of_bitmap_entries++;
2022 j += g_snprintf(&buff[j], BUFF_SIZE-j, " ,");
2025 proto_tree_add_text(bitmap_tree, tvb, bit_offset/8, 1, "%s", buff);
2028 proto_item_append_text(ti, " (%u SNs)", number_of_bitmap_entries);
2029 col_append_str(pinfo->cinfo, COL_INFO, " )");
2031 case RLC_SUFI_RLIST:
2032 previous_bit_offset = bit_offset;
2033 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2035 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2037 proto_item_append_text(sufi_item, " (%u codewords)", (guint16)len);
2039 for (i=0; i<len; i++) {
2040 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_cw, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
2042 proto_item_append_text(ti, " (Error burst indication)");
2047 if (len && (((cw[len-1] & 0x01) == 0) || (cw[len-1] == 0x01))) {
2048 expert_add_info(pinfo, tree, &ei_rlc_sufi_cw);
2050 ti = proto_tree_add_text(sufi_tree, tvb, previous_bit_offset/8, (bit_offset-previous_bit_offset)/8, "Decoded list:");
2051 rlist_tree = proto_item_add_subtree(ti, ett_rlc_rlist);
2052 proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+4)/8, 12/8,
2053 "Sequence Number = %u (AMD PDU not correctly received)",(unsigned)sn);
2054 col_append_fstr(pinfo->cinfo, COL_INFO, " RLIST=(%u", (unsigned)sn);
2056 for (i=0, isErrorBurstInd=FALSE, j=0, previous_sn=(guint16)sn, value=0; i<len; i++) {
2057 if (cw[i] == 0x01) {
2058 isErrorBurstInd = TRUE;
2060 value |= (cw[i] >> 1) << j;
2063 if (isErrorBurstInd) {
2064 previous_sn = (previous_sn + value) & 0xfff;
2065 ti = proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+16+4*i)/8, 1, "Length: %u", value);
2067 proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)", previous_sn);
2068 col_append_fstr(pinfo->cinfo, COL_INFO, " ->%u", previous_sn);
2070 isErrorBurstInd = FALSE;
2072 value = (value + previous_sn) & 0xfff;
2073 proto_tree_add_text(rlist_tree, tvb, (previous_bit_offset+16+4*i)/8, 1, "Sequence Number = %u (AMD PDU not correctly received)",value);
2074 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", value);
2075 previous_sn = value;
2081 col_append_str(pinfo->cinfo, COL_INFO, ")");
2084 case RLC_SUFI_MRW_ACK:
2085 col_append_str(pinfo->cinfo, COL_INFO, " MRW-ACK");
2086 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2088 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_ack, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2090 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
2093 col_append_str(pinfo->cinfo, COL_INFO, " MRW");
2094 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2098 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2099 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
2104 /* only one SN_MRW field is present */
2105 ti = proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2106 proto_item_append_text(ti, " (RLC SDU to be discarded in the Receiver extends above the configured transmission window in the Sender)");
2109 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2113 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_poll_sn, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2118 expert_add_info(pinfo, tree, &ei_rlc_sufi_type);
2119 return; /* invalid value, ignore the rest */
2122 /* Set extent of SUFI root */
2123 proto_item_set_len(sufi_item, ((bit_offset+7)/8) - sufi_start_offset);
2128 dissect_rlc_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2130 guint8 type, next_byte;
2135 next_byte = tvb_get_guint8(tvb, 0);
2136 type = (next_byte >> 4) & 0x07;
2138 ti = proto_tree_add_bits_item(tree, hf_rlc_ctrl_type, tvb, 1, 3, ENC_BIG_ENDIAN);
2141 dissect_rlc_status(tvb, pinfo, tree, 0);
2145 col_append_str(pinfo->cinfo, COL_INFO, (type == RLC_RESET) ? " RESET" : " RESET-ACK");
2146 proto_tree_add_bits_ret_val(tree, hf_rlc_rsn, tvb, 4, 1, &rsn, ENC_BIG_ENDIAN);
2147 proto_tree_add_bits_ret_val(tree, hf_rlc_r1, tvb, 5, 3, &r1, ENC_BIG_ENDIAN);
2149 expert_add_info(pinfo, ti, &ei_rlc_reserved_bits_not_zero);
2152 proto_tree_add_bits_ret_val(tree, hf_rlc_hfni, tvb, 8, 20, &hfn, ENC_BIG_ENDIAN);
2153 col_append_fstr(pinfo->cinfo, COL_INFO, " RSN=%u HFN=%u", (guint16)rsn, (guint32)hfn);
2156 expert_add_info(pinfo, ti, &ei_rlc_ctrl_type);
2157 return; /* invalid */
2162 rlc_am_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo,
2163 proto_tree *tree, proto_tree *top_level,
2164 enum rlc_channel_type channel, guint16 seq, gboolean poll_set, struct rlc_li *li,
2165 guint16 num_li, gboolean final, gboolean li_is_on_2_bytes)
2168 gboolean piggyback = FALSE, dissected = FALSE;
2169 tvbuff_t *next_tvb = NULL;
2171 struct rlc_channel ch_lookup;
2172 struct rlc_seqlist * endlist = NULL;
2173 if( 0 == seq ){ /* assuming that a new RRC Connection is established when 0==seq. */
2174 if( -1 != rlc_channel_assign(&ch_lookup, RLC_AM, pinfo ) ){
2175 endlist = get_endlist(pinfo, &ch_lookup);
2176 endlist->list->data = GINT_TO_POINTER( -1);
2180 /* perform reassembly now */
2181 for (i = 0; i < num_li; i++) {
2182 if ((!li_is_on_2_bytes && (li[i].li == 0x7e)) || (li[i].li == 0x7ffe)) {
2183 /* piggybacked status */
2185 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
2186 /* padding, must be last LI */
2187 if (tvb_length_remaining(tvb, offs) > 0) {
2189 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, -1, ENC_NA);
2192 /* Insert empty RLC frag so RLC doesn't miss this seq number. */
2193 add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, 0, TRUE);
2196 offs += tvb_length_remaining(tvb, offs);
2199 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
2201 if (global_rlc_perform_reassemby) {
2202 add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE);
2203 next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i);
2208 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2215 dissect_rlc_status(tvb, pinfo, tree, offs);
2217 if (tvb_length_remaining(tvb, offs) > 0) {
2218 /* we have remaining data, which we need to mark in the tree */
2220 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
2222 if (global_rlc_perform_reassemby) {
2223 add_fragment(RLC_AM, tvb, pinfo, tree, offs, seq, i,
2224 tvb_length_remaining(tvb,offs), final);
2226 next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i);
2232 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2236 if (dissected == FALSE)
2237 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] SN=%u %s",
2238 seq, poll_set ? "(P)" : "");
2240 if (channel == RLC_UNKNOWN_CH)
2241 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Data] SN=%u %s",
2242 seq, poll_set ? "(P)" : "");
2246 dissect_rlc_am(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
2247 proto_tree *top_level, proto_tree *tree)
2250 struct rlc_li li[MAX_LI];
2254 guint8 next_byte, offs = 0;
2255 guint32 orig_num = 0;
2256 gint16 num_li = 0, pos;
2258 gboolean is_truncated, li_is_on_2_bytes;
2259 proto_item *truncated_ti, *ti;
2262 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2263 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2265 next_byte = tvb_get_guint8(tvb, offs++);
2266 dc = next_byte >> 7;
2268 if (fpinf && rlcinf) {
2269 /* Add "channel" information, very useful for debugging. */
2270 add_channel_info(pinfo, tree, fpinf, rlcinf);
2272 proto_tree_add_bits_item(tree, hf_rlc_dc, tvb, 0, 1, ENC_BIG_ENDIAN);
2275 col_set_str(pinfo->cinfo, COL_INFO, "[RLC Control Frame]");
2276 dissect_rlc_control(tvb, pinfo, tree);
2280 seq = next_byte & 0x7f;
2282 next_byte = tvb_get_guint8(tvb, offs++);
2283 seq |= (next_byte >> 3);
2285 ext = next_byte & 0x03;
2286 /* show header fields */
2287 proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 1, 12, ENC_BIG_ENDIAN);
2288 proto_tree_add_bits_ret_val(tree, hf_rlc_p, tvb, 13, 1, &polling, ENC_BIG_ENDIAN);
2289 ti = proto_tree_add_bits_item(tree, hf_rlc_he, tvb, 14, 2, ENC_BIG_ENDIAN);
2291 /* header extension may only be 00, 01 or 10 */
2293 expert_add_info(pinfo, ti, &ei_rlc_he);
2297 if (!fpinf || !rlcinf) {
2298 proto_tree_add_text(tree, tvb, 0, -1,
2299 "Cannot dissect RLC frame because per-frame info is missing");
2303 pos = fpinf->cur_tb;
2306 * WARNING DECIPHERING IS HIGHLY EXPERIMENTAL!!!
2308 if (((rlcinf->ciphered[pos] == TRUE && rlcinf->deciphered[pos] == FALSE) || global_rlc_ciphered)) {
2309 if(global_rlc_try_decipher){
2310 rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_AM);
2312 proto_tree_add_text(tree, tvb, 0, -1,
2313 "Cannot dissect RLC frame because it is ciphered");
2314 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
2319 if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
2320 if (rlcinf->li_size[pos] == RLC_LI_VARIABLE) {
2321 li_is_on_2_bytes = (tvb_length(tvb) > 126) ? TRUE : FALSE;
2323 li_is_on_2_bytes = (rlcinf->li_size[pos] == RLC_LI_15BITS) ? TRUE : FALSE;
2325 } else { /* Override rlcinf configuration with preference. */
2326 li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? TRUE : FALSE;
2329 num_li = rlc_decode_li(RLC_AM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
2330 if (num_li == -1) return; /* something went wrong */
2331 offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
2332 if (global_rlc_headers_expected) {
2333 /* There might not be any data, if only header was logged */
2334 is_truncated = (tvb_length_remaining(tvb, offs) == 0);
2335 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
2338 PROTO_ITEM_SET_GENERATED(truncated_ti);
2339 expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
2342 PROTO_ITEM_SET_HIDDEN(truncated_ti);
2346 /* do not detect duplicates or reassemble, if prefiltering is done */
2347 if (pinfo->fd->num == 0) return;
2348 /* check for duplicates, but not if already visited */
2349 if (pinfo->fd->flags.visited == FALSE && rlc_is_duplicate(RLC_AM, pinfo, seq, &orig_num) == TRUE) {
2350 g_hash_table_insert(duplicate_table, GUINT_TO_POINTER(pinfo->fd->num), GUINT_TO_POINTER(orig_num));
2352 } else if (pinfo->fd->flags.visited == TRUE && tree) {
2353 gpointer value = g_hash_table_lookup(duplicate_table, GUINT_TO_POINTER(pinfo->fd->num));
2354 if (value != NULL) {
2355 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] [Duplicate] SN=%u %s", seq, (polling != 0) ? "(P)" : "");
2356 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, GPOINTER_TO_UINT(value));
2361 rlc_am_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, polling != 0,
2362 li, num_li, ext == 2, li_is_on_2_bytes);
2365 /* dissect entry functions */
2367 dissect_rlc_pcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2369 proto_tree *subtree = NULL;
2371 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2372 col_clear(pinfo->cinfo, COL_INFO);
2374 /* PCCH is always RLC TM */
2377 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2378 subtree = proto_item_add_subtree(ti, ett_rlc);
2379 proto_item_append_text(ti, " TM (PCCH)");
2381 dissect_rlc_tm(RLC_PCCH, tvb, pinfo, tree, subtree);
2385 dissect_rlc_bcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2388 proto_item *ti = NULL;
2389 proto_tree *subtree = NULL;
2391 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2392 col_clear(pinfo->cinfo, COL_INFO);
2394 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2395 if (!fpi) return; /* dissection failure */
2398 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2399 subtree = proto_item_add_subtree(ti, ett_rlc);
2401 proto_item_append_text(ti, " TM (BCCH)");
2402 dissect_rlc_tm(RLC_BCCH, tvb, pinfo, tree, subtree);
2406 dissect_rlc_ccch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2409 proto_item *ti = NULL;
2410 proto_tree *subtree = NULL;
2412 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2413 col_clear(pinfo->cinfo, COL_INFO);
2415 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2416 if (!fpi) return; /* dissection failure */
2419 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2420 subtree = proto_item_add_subtree(ti, ett_rlc);
2423 if (fpi->is_uplink) {
2424 /* UL CCCH is always RLC TM */
2425 proto_item_append_text(ti, " TM (CCCH)");
2426 dissect_rlc_tm(RLC_UL_CCCH, tvb, pinfo, tree, subtree);
2428 /* DL CCCH is always UM */
2429 proto_item_append_text(ti, " UM (CCCH)");
2430 dissect_rlc_um(RLC_DL_CCCH, tvb, pinfo, tree, subtree);
2435 dissect_rlc_ctch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2438 proto_item *ti = NULL;
2439 proto_tree *subtree = NULL;
2442 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2443 col_clear(pinfo->cinfo, COL_INFO);
2445 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2446 if (!fpi) return; /* dissection failure */
2449 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2450 subtree = proto_item_add_subtree(ti, ett_rlc);
2453 /* CTCH is always UM */
2454 proto_item_append_text(ti, " UM (CTCH)");
2455 dissect_rlc_um(RLC_DL_CTCH, tvb, pinfo, tree, subtree);
2459 dissect_rlc_dcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2461 proto_item *ti = NULL;
2462 proto_tree *subtree = NULL;
2465 enum rlc_channel_type channel;
2467 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2468 col_clear(pinfo->cinfo, COL_INFO);
2470 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2471 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2474 ti = proto_tree_add_text(tree, tvb, 0, -1,
2475 "Can't dissect RLC frame because no per-frame info was attached!");
2476 PROTO_ITEM_SET_GENERATED(ti);
2481 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2482 subtree = proto_item_add_subtree(ti, ett_rlc);
2485 channel = fpi->is_uplink ? RLC_UL_DCCH : RLC_DL_DCCH;
2487 switch (rlci->mode[fpi->cur_tb]) {
2489 proto_item_append_text(ti, " UM (DCCH)");
2490 dissect_rlc_um(channel, tvb, pinfo, tree, subtree);
2493 proto_item_append_text(ti, " AM (DCCH)");
2494 dissect_rlc_am(channel, tvb, pinfo, tree, subtree);
2500 dissect_rlc_ps_dtch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2502 proto_item *ti = NULL;
2503 proto_tree *subtree = NULL;
2507 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2508 col_clear(pinfo->cinfo, COL_INFO);
2510 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2511 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2513 if (!fpi || !rlci) {
2514 ti = proto_tree_add_text(tree, tvb, 0, -1,
2515 "Can't dissect RLC frame because no per-frame info was attached!");
2516 PROTO_ITEM_SET_GENERATED(ti);
2521 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2522 subtree = proto_item_add_subtree(ti, ett_rlc);
2525 switch (rlci->mode[fpi->cur_tb]) {
2527 proto_item_append_text(ti, " UM (PS DTCH)");
2528 dissect_rlc_um(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
2531 proto_item_append_text(ti, " AM (PS DTCH)");
2532 dissect_rlc_am(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
2535 proto_item_append_text(ti, " TM (PS DTCH)");
2536 dissect_rlc_tm(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
2542 dissect_rlc_dch_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2544 proto_item *ti = NULL;
2545 proto_tree *subtree = NULL;
2549 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2550 col_clear(pinfo->cinfo, COL_INFO);
2552 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2553 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2555 if (!fpi || !rlci) return;
2558 ti = proto_tree_add_item(tree, proto_rlc, tvb, 0, -1, ENC_NA);
2559 subtree = proto_item_add_subtree(ti, ett_rlc);
2562 switch (rlci->mode[fpi->cur_tb]) {
2564 proto_item_append_text(ti, " UM (Unknown)");
2565 dissect_rlc_um(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
2568 proto_item_append_text(ti, " AM (Unknown)");
2569 dissect_rlc_am(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
2572 proto_item_append_text(ti, " TM (Unknown)");
2573 dissect_rlc_tm(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
2579 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
2581 dissect_rlc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2588 guint channelType = UMTS_CHANNEL_TYPE_UNSPECIFIED;
2589 gboolean fpInfoAlreadySet = FALSE;
2590 gboolean rlcInfoAlreadySet = FALSE;
2591 gboolean channelTypePresent = FALSE;
2592 gboolean rlcModePresent = FALSE;
2593 proto_item *ti = NULL;
2594 proto_tree *subtree = NULL;
2596 /* This is a heuristic dissector, which means we get all the UDP
2597 * traffic not sent to a known dissector and not claimed by
2598 * a heuristic dissector called before us!
2600 if (!global_rlc_heur) {
2604 /* Do this again on re-dissection to re-discover offset of actual PDU */
2606 /* Needs to be at least as long as:
2607 - the signature string
2608 - conditional header bytes
2610 - at least one byte of RLC PDU payload */
2611 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(RLC_START_STRING)+2+2)) {
2615 /* OK, compare with signature string */
2616 if (tvb_strneql(tvb, offset, RLC_START_STRING, (gint)strlen(RLC_START_STRING)) != 0) {
2619 offset += (gint)strlen(RLC_START_STRING);
2621 /* If redissecting, use previous info struct (if available) */
2622 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2624 /* Allocate new info struct for this frame */
2625 fpi = (fp_info *)wmem_alloc0(wmem_file_scope(), sizeof(fp_info));
2627 fpInfoAlreadySet = TRUE;
2629 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2631 /* Allocate new info struct for this frame */
2632 rlci = (rlc_info *)wmem_alloc0(wmem_file_scope(), sizeof(rlc_info));
2634 rlcInfoAlreadySet = TRUE;
2637 /* Read conditional/optional fields */
2638 while (tag != RLC_PAYLOAD_TAG) {
2639 /* Process next tag */
2640 tag = tvb_get_guint8(tvb, offset++);
2642 case RLC_CHANNEL_TYPE_TAG:
2643 channelType = tvb_get_guint8(tvb, offset);
2645 channelTypePresent = TRUE;
2648 rlci->mode[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
2650 rlcModePresent = TRUE;
2652 case RLC_DIRECTION_TAG:
2653 if (tvb_get_guint8(tvb, offset) == DIRECTION_UPLINK) {
2654 fpi->is_uplink = TRUE;
2655 pinfo->p2p_dir = P2P_DIR_UL;
2657 fpi->is_uplink = FALSE;
2658 pinfo->p2p_dir = P2P_DIR_DL;
2663 rlci->urnti[fpi->cur_tb] = tvb_get_ntohl(tvb, offset);
2666 case RLC_RADIO_BEARER_ID_TAG:
2667 rlci->rbid[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
2670 case RLC_LI_SIZE_TAG:
2671 rlci->li_size[fpi->cur_tb] = (enum rlc_li_size) tvb_get_guint8(tvb, offset);
2674 case RLC_PAYLOAD_TAG:
2675 /* Have reached data, so get out of loop */
2678 /* It must be a recognised tag */
2683 if ((channelTypePresent == FALSE) && (rlcModePresent == FALSE)) {
2684 /* Conditional fields are missing */
2688 /* Store info in packet if needed */
2689 if (!fpInfoAlreadySet) {
2690 p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, fpi);
2692 if (!rlcInfoAlreadySet) {
2693 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0, rlci);
2696 /**************************************/
2697 /* OK, now dissect as RLC */
2699 /* Create tvb that starts at actual RLC PDU */
2700 rlc_tvb = tvb_new_subset_remaining(tvb, offset);
2701 switch (channelType) {
2702 case UMTS_CHANNEL_TYPE_UNSPECIFIED:
2703 /* Call relevant dissector according to RLC mode */
2704 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2705 col_clear(pinfo->cinfo, COL_INFO);
2708 ti = proto_tree_add_item(tree, proto_rlc, rlc_tvb, 0, -1, ENC_NA);
2709 subtree = proto_item_add_subtree(ti, ett_rlc);
2712 if (rlci->mode[fpi->cur_tb] == RLC_AM) {
2713 proto_item_append_text(ti, " AM");
2714 dissect_rlc_am(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
2715 } else if (rlci->mode[fpi->cur_tb] == RLC_UM) {
2716 proto_item_append_text(ti, " UM");
2717 dissect_rlc_um(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
2719 proto_item_append_text(ti, " TM");
2720 dissect_rlc_tm(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
2723 case UMTS_CHANNEL_TYPE_PCCH:
2724 dissect_rlc_pcch(rlc_tvb, pinfo, tree);
2726 case UMTS_CHANNEL_TYPE_CCCH:
2727 dissect_rlc_ccch(rlc_tvb, pinfo, tree);
2729 case UMTS_CHANNEL_TYPE_DCCH:
2730 dissect_rlc_dcch(rlc_tvb, pinfo, tree);
2732 case UMTS_CHANNEL_TYPE_PS_DTCH:
2733 dissect_rlc_ps_dtch(rlc_tvb, pinfo, tree);
2735 case UMTS_CHANNEL_TYPE_CTCH:
2736 dissect_rlc_ctch(rlc_tvb, pinfo, tree);
2738 case UMTS_CHANNEL_TYPE_BCCH:
2739 dissect_rlc_bcch(rlc_tvb, pinfo, tree);
2742 /* Unknown channel type */
2750 rlc_is_ciphered(packet_info * pinfo){
2755 return global_rlc_ciphered;
2758 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2759 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc, 0);
2761 return ((rlcinf && fpinf && (rlcinf->ciphered[fpinf->cur_tb] == TRUE) && (rlcinf->deciphered[fpinf->cur_tb] == FALSE))
2762 || global_rlc_ciphered);
2766 proto_register_rlc(void)
2768 module_t *rlc_module;
2769 expert_module_t* expert_rlc;
2770 static hf_register_info hf[] = {
2772 { "D/C Bit", "rlc.dc",
2773 FT_BOOLEAN, BASE_NONE, TFS(&rlc_dc_val), 0, NULL, HFILL }
2775 { &hf_rlc_ctrl_type,
2776 { "Control PDU Type", "rlc.ctrl_pdu_type",
2777 FT_UINT8, BASE_DEC, VALS(rlc_ctrl_vals), 0, "PDU Type", HFILL }
2780 { "Reserved 1", "rlc.r1",
2781 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2784 { "Reset Sequence Number", "rlc.rsn",
2785 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2788 { "Hyper Frame Number Indicator", "rlc.hfni",
2789 FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL }
2792 { "Sequence Number", "rlc.seq",
2793 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2796 { "Extension Bit", "rlc.ext",
2797 FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2800 { "Header Extension Type", "rlc.he",
2801 FT_UINT8, BASE_DEC, VALS(rlc_he_vals), 0, NULL, HFILL }
2804 { "Polling Bit", "rlc.p",
2805 FT_BOOLEAN, BASE_NONE, TFS(&rlc_p_val), 0, NULL, HFILL }
2808 { "Padding", "rlc.padding",
2809 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2812 { "Reassembled Fragments", "rlc.fragments",
2813 FT_NONE, BASE_NONE, NULL, 0, "Fragments", HFILL }
2816 { "RLC Fragment", "rlc.fragment",
2817 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2819 { &hf_rlc_duplicate_of,
2820 { "Duplicate of", "rlc.duplicate_of",
2821 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2823 { &hf_rlc_reassembled_in,
2824 { "Reassembled Message in frame", "rlc.reassembled_in",
2825 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2828 { "Data", "rlc.data",
2829 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2831 /* LI information */
2834 FT_NONE, BASE_NONE, NULL, 0, "Length Indicator", HFILL }
2837 { "LI value", "rlc.li.value",
2838 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2841 { "LI extension bit", "rlc.li.ext",
2842 FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2845 { "LI Data", "rlc.li.data",
2846 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2848 /* SUFI information */
2850 { "SUFI", "rlc.sufi",
2851 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2853 { &hf_rlc_sufi_type,
2854 { "SUFI Type", "rlc.sufi.type",
2855 FT_UINT8, BASE_DEC, VALS(rlc_sufi_vals), 0, NULL, HFILL }
2858 { "Last Sequence Number", "rlc.sufi.lsn",
2859 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2862 { "Window Size Number", "rlc.sufi.wsn",
2863 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2866 { "Sequence Number", "rlc.sufi.sn",
2867 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2870 { "Length", "rlc.sufi.l",
2871 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2874 { "Length", "rlc.sufi.len",
2875 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2878 { "First Sequence Number", "rlc.sufi.fsn",
2879 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2881 { &hf_rlc_sufi_bitmap,
2882 { "Bitmap", "rlc.sufi.bitmap",
2883 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2886 { "Codeword", "rlc.sufi.cw",
2887 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2890 { "Nlength", "rlc.sufi.n",
2891 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2893 { &hf_rlc_sufi_sn_ack,
2894 { "SN ACK", "rlc.sufi.sn_ack",
2895 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2897 { &hf_rlc_sufi_sn_mrw,
2898 { "SN MRW", "rlc.sufi.sn_mrw",
2899 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2901 { &hf_rlc_sufi_poll_sn,
2902 { "Poll SN", "rlc.sufi.poll_sn",
2903 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2905 /* Other information */
2906 { &hf_rlc_header_only,
2907 { "RLC PDU header only", "rlc.header_only",
2908 FT_BOOLEAN, BASE_NONE, TFS(&rlc_header_only_val), 0 ,NULL, HFILL }
2911 { "Channel", "rlc.channel",
2912 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2914 { &hf_rlc_channel_rbid,
2915 { "Radio Bearer ID", "rlc.channel.rbid",
2916 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2918 { &hf_rlc_channel_dir,
2919 { "Direction", "rlc.channel.dir",
2920 FT_UINT8, BASE_DEC, VALS(rlc_dir_vals), 0, NULL, HFILL }
2922 { &hf_rlc_channel_ueid,
2923 { "User Equipment ID", "rlc.channel.ueid",
2924 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
2927 static gint *ett[] = {
2937 static ei_register_info ei[] = {
2938 { &ei_rlc_reassembly_fail_unfinished_sequence, { "rlc.reassembly.fail.unfinished_sequence", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because of previous unfinished sequence.", EXPFILL }},
2939 { &ei_rlc_reassembly_fail_flag_set, { "rlc.reassembly.fail.flag_set", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because fail flag was set previously.", EXPFILL }},
2940 { &ei_rlc_reassembly_lingering_endpoint, { "rlc.lingering_endpoint", PI_REASSEMBLE, PI_ERROR, "Lingering endpoint.", EXPFILL }},
2941 { &ei_rlc_reassembly_unknown_error, { "rlc.reassembly.unknown_error", PI_REASSEMBLE, PI_ERROR, "Unknown error.", EXPFILL }},
2942 { &ei_rlc_kasumi_implementation_missing, { "rlc.kasumi_implementation_missing", PI_UNDECODED, PI_WARN, "Unable to decipher packet since KASUMI implementation is missing.", EXPFILL }},
2943 { &ei_rlc_li_reserved, { "rlc.li.reserved", PI_PROTOCOL, PI_WARN, "Uses reserved LI", EXPFILL }},
2944 { &ei_rlc_li_incorrect_warn, { "rlc.li.incorrect", PI_PROTOCOL, PI_WARN, "Incorrect LI value", EXPFILL }},
2945 { &ei_rlc_li_incorrect_mal, { "rlc.li.incorrect", PI_MALFORMED, PI_ERROR, "Incorrect LI value 0x%x", EXPFILL }},
2946 { &ei_rlc_li_too_many, { "rlc.li.too_many", PI_MALFORMED, PI_ERROR, "Too many LI entries", EXPFILL }},
2947 { &ei_rlc_header_only, { "rlc.header_only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
2948 { &ei_rlc_sufi_len, { "rlc.sufi.len.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
2949 { &ei_rlc_sufi_cw, { "rlc.sufi.cw.invalid", PI_PROTOCOL, PI_WARN, "Invalid last codeword", EXPFILL }},
2950 { &ei_rlc_sufi_type, { "rlc.sufi.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid SUFI type", EXPFILL }},
2951 { &ei_rlc_reserved_bits_not_zero, { "rlc.reserved_bits_not_zero", PI_PROTOCOL, PI_WARN, "reserved bits not zero", EXPFILL }},
2952 { &ei_rlc_ctrl_type, { "rlc.ctrl_pdu_type.invalid", PI_PROTOCOL, PI_WARN, "Invalid RLC AM control type %u", EXPFILL }},
2953 { &ei_rlc_he, { "rlc.he.invalid", PI_PROTOCOL, PI_WARN, "Incorrect HE value", EXPFILL }},
2956 proto_rlc = proto_register_protocol("Radio Link Control", "RLC", "rlc");
2957 register_dissector("rlc.bcch", dissect_rlc_bcch, proto_rlc);
2958 register_dissector("rlc.pcch", dissect_rlc_pcch, proto_rlc);
2959 register_dissector("rlc.ccch", dissect_rlc_ccch, proto_rlc);
2960 register_dissector("rlc.ctch", dissect_rlc_ctch, proto_rlc);
2961 register_dissector("rlc.dcch", dissect_rlc_dcch, proto_rlc);
2962 register_dissector("rlc.ps_dtch", dissect_rlc_ps_dtch, proto_rlc);
2963 register_dissector("rlc.dch_unknown", dissect_rlc_dch_unknown, proto_rlc);
2965 proto_register_field_array(proto_rlc, hf, array_length(hf));
2966 proto_register_subtree_array(ett, array_length(ett));
2967 expert_rlc = expert_register_protocol(proto_rlc);
2968 expert_register_field_array(expert_rlc, ei, array_length(ei));
2971 rlc_module = prefs_register_protocol(proto_rlc, NULL);
2973 prefs_register_bool_preference(rlc_module, "heuristic_rlc_over_udp",
2974 "Try Heuristic RLC over UDP framing",
2975 "When enabled, use heuristic dissector to find RLC frames sent with "
2979 prefs_register_bool_preference(rlc_module, "perform_reassembly",
2980 "Try to reassemble SDUs",
2981 "When enabled, try to reassemble SDUs from the various PDUs received",
2982 &global_rlc_perform_reassemby);
2984 prefs_register_bool_preference(rlc_module, "header_only_mode",
2985 "May see RLC headers only",
2986 "When enabled, if data is not present, don't report as an error, but instead "
2987 "add expert info to indicate that headers were omitted",
2988 &global_rlc_headers_expected);
2990 prefs_register_bool_preference(rlc_module, "ciphered_data",
2992 "When enabled, rlc will assume all data is ciphered",
2993 &global_rlc_ciphered);
2995 prefs_register_bool_preference(rlc_module, "try_decipher",
2996 "Try to Decipher data",
2997 "When enabled, rlc will try to decipher data. (Experimental)",
2998 &global_rlc_try_decipher);
3000 prefs_register_enum_preference(rlc_module, "li_size",
3002 "LI size in bits, either 7 or 15 bit",
3003 &global_rlc_li_size, li_size_enumvals, FALSE);
3005 #ifdef HAVE_UMTS_KASUMI
3006 prefs_register_string_preference(rlc_module, "kasumi_key",
3007 "KASUMI key", "Key for kasumi 32 characters long hex-string", &global_rlc_kasumi_key);
3008 #endif /* HAVE_UMTS_KASUMI */
3010 register_init_routine(fragment_table_init);
3014 proto_reg_handoff_rlc(void)
3016 rrc_handle = find_dissector("rrc");
3017 ip_handle = find_dissector("ip");
3018 bmc_handle = find_dissector("bmc");
3019 /* Add as a heuristic UDP dissector */
3020 heur_dissector_add("udp", dissect_rlc_heur, proto_rlc);
3029 * indent-tabs-mode: nil
3032 * ex: set shiftwidth=4 tabstop=8 expandtab:
3033 * :indentSize=4:tabSize=8:noTabs=true: