2 * Routines for UMTS RLC (Radio Link Control) v9.3.0 disassembly
3 * http://www.3gpp.org/ftp/Specs/archive/25_series/25.322/
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/conversation.h>
16 #include <epan/expert.h>
17 #include <epan/prefs.h>
18 #include <epan/proto_data.h>
20 #include <wiretap/wtap.h>
23 * Optional include, for KASUMI support,
24 * see header file for more information.
27 #include "packet-umts_fp.h"
28 #include "packet-umts_rlc.h"
29 #include "packet-rrc.h"
32 * - distinguish between startpoints and endpoints?
33 * - use sub_num in fragment identification?
36 void proto_register_rlc(void);
37 void proto_reg_handoff_rlc(void);
39 int proto_umts_rlc = -1;
43 /* Preference to perform reassembly */
44 static gboolean global_rlc_perform_reassemby = TRUE;
46 /* Preference to expect RLC headers without payloads */
47 static gboolean global_rlc_headers_expected = FALSE;
49 /* Preference to expect ONLY ciphered data */
50 static gboolean global_rlc_ciphered = FALSE;
52 /* Preference to ignore ciphering state reported from RRC */
53 /* This is important for captures with deciphered traffic AND the original security RRC messages present*/
54 static gboolean global_ignore_rrc_ciphering_indication = FALSE;
56 /* Preference to try deciphering */
57 static gboolean global_rlc_try_decipher = FALSE;
59 #ifdef HAVE_UMTS_KASUMI
60 static const char *global_rlc_kasumi_key = NULL;
63 /* LI size preference */
64 #define RLC_LI_UPPERLAYER 255 /* LI-size comes from rlc_info struct rather than preference */
65 static gint global_rlc_li_size = RLC_LI_UPPERLAYER;
67 static const enum_val_t li_size_enumvals[] = {
68 {"7 bits", "7 bits", RLC_LI_7BITS},
69 {"15 bits", "15 bits", RLC_LI_15BITS},
70 {"Let upper layers decide", "Let upper layers decide", RLC_LI_UPPERLAYER},
74 static int hf_rlc_seq = -1;
75 static int hf_rlc_ext = -1;
76 static int hf_rlc_pad = -1;
77 static int hf_rlc_frags = -1;
78 static int hf_rlc_frag = -1;
79 static int hf_rlc_duplicate_of = -1;
80 static int hf_rlc_reassembled_in = -1;
81 static int hf_rlc_he = -1;
82 static int hf_rlc_dc = -1;
83 static int hf_rlc_p = -1;
84 static int hf_rlc_li = -1;
85 static int hf_rlc_li_value = -1;
86 static int hf_rlc_li_ext = -1;
87 static int hf_rlc_li_data = -1;
88 static int hf_rlc_data = -1;
89 static int hf_rlc_ciphered_data = -1;
90 static int hf_rlc_ciphered_lis_data = -1;
91 static int hf_rlc_ctrl_type = -1;
92 static int hf_rlc_r1 = -1;
93 static int hf_rlc_rsn = -1;
94 static int hf_rlc_hfni = -1;
95 static int hf_rlc_sufi = -1;
96 static int hf_rlc_sufi_type = -1;
97 static int hf_rlc_sufi_lsn = -1;
98 static int hf_rlc_sufi_wsn = -1;
99 static int hf_rlc_sufi_sn = -1;
100 static int hf_rlc_sufi_l = -1;
101 static int hf_rlc_sufi_fsn = -1;
102 static int hf_rlc_sufi_len = -1;
103 static int hf_rlc_sufi_bitmap = -1;
104 static int hf_rlc_sufi_cw = -1;
105 static int hf_rlc_sufi_n = -1;
106 static int hf_rlc_sufi_sn_ack = -1;
107 static int hf_rlc_sufi_sn_mrw = -1;
108 static int hf_rlc_sufi_poll_sn = -1;
109 static int hf_rlc_header_only = -1;
110 static int hf_rlc_channel = -1;
111 static int hf_rlc_channel_rbid = -1;
112 static int hf_rlc_channel_dir = -1;
113 static int hf_rlc_channel_ueid = -1;
114 static int hf_rlc_sequence_number = -1;
115 static int hf_rlc_length = -1;
116 static int hf_rlc_bitmap_string = -1;
119 static int ett_rlc = -1;
120 static int ett_rlc_frag = -1;
121 static int ett_rlc_fragments = -1;
122 static int ett_rlc_sdu = -1;
123 static int ett_rlc_sufi = -1;
124 static int ett_rlc_bitmap = -1;
125 static int ett_rlc_rlist = -1;
126 static int ett_rlc_channel = -1;
128 static expert_field ei_rlc_li_reserved = EI_INIT;
129 static expert_field ei_rlc_he = EI_INIT;
130 static expert_field ei_rlc_li_incorrect_mal = EI_INIT;
131 static expert_field ei_rlc_sufi_cw = EI_INIT;
132 static expert_field ei_rlc_kasumi_implementation_missing = EI_INIT;
133 static expert_field ei_rlc_reassembly_unknown_error = EI_INIT;
134 static expert_field ei_rlc_reassembly_lingering_endpoint = EI_INIT;
135 static expert_field ei_rlc_sufi_len = EI_INIT;
136 static expert_field ei_rlc_reassembly_fail_unfinished_sequence = EI_INIT;
137 static expert_field ei_rlc_reassembly_fail_flag_set = EI_INIT;
138 static expert_field ei_rlc_sufi_type = EI_INIT;
139 static expert_field ei_rlc_reserved_bits_not_zero = EI_INIT;
140 static expert_field ei_rlc_ctrl_type = EI_INIT;
141 static expert_field ei_rlc_li_incorrect_warn = EI_INIT;
142 static expert_field ei_rlc_li_too_many = EI_INIT;
143 static expert_field ei_rlc_header_only = EI_INIT;
144 static expert_field ei_rlc_ciphered_data = EI_INIT;
145 static expert_field ei_rlc_no_per_frame_data = EI_INIT;
146 static expert_field ei_rlc_incomplete_sequence = EI_INIT;
147 static expert_field ei_rlc_unknown_udp_framing_tag = EI_INIT;
148 static expert_field ei_rlc_missing_udp_framing_tag = EI_INIT;
150 static dissector_handle_t ip_handle;
151 static dissector_handle_t rrc_handle;
152 static dissector_handle_t bmc_handle;
154 enum rlc_channel_type {
166 static const value_string rlc_dir_vals[] = {
167 { P2P_DIR_UL, "Uplink" },
168 { P2P_DIR_DL, "Downlink" },
172 static const true_false_string rlc_header_only_val = {
173 "RLC PDU header only", "RLC PDU header and body present"
176 static const true_false_string rlc_ext_val = {
177 "Next field is Length Indicator and E Bit", "Next field is data, piggybacked STATUS PDU or padding"
180 static const true_false_string rlc_dc_val = {
184 static const true_false_string rlc_p_val = {
185 "Request a status report", "Status report not requested"
188 static const value_string rlc_he_vals[] = {
189 { 0, "The succeeding octet contains data" },
190 { 1, "The succeeding octet contains a length indicator and E bit" },
191 { 2, "The succeeding octet contains data and the last octet of the PDU is the last octet of an SDU" },
195 #define RLC_STATUS 0x0
196 #define RLC_RESET 0x1
197 #define RLC_RESET_ACK 0x2
198 static const value_string rlc_ctrl_vals[] = {
199 { RLC_STATUS, "Status" },
200 { RLC_RESET, "Reset" },
201 { RLC_RESET_ACK, "Reset Ack" },
205 #define RLC_SUFI_NOMORE 0x0
206 #define RLC_SUFI_WINDOW 0x1
207 #define RLC_SUFI_ACK 0x2
208 #define RLC_SUFI_LIST 0x3
209 #define RLC_SUFI_BITMAP 0x4
210 #define RLC_SUFI_RLIST 0x5
211 #define RLC_SUFI_MRW 0x6
212 #define RLC_SUFI_MRW_ACK 0x7
213 #define RLC_SUFI_POLL 0x8
214 static const value_string rlc_sufi_vals[] = {
215 { RLC_SUFI_NOMORE, "No more data" },
216 { RLC_SUFI_WINDOW, "Window size" },
217 { RLC_SUFI_ACK, "Acknowledgement" },
218 { RLC_SUFI_LIST, "List" },
219 { RLC_SUFI_BITMAP, "Bitmap" },
220 { RLC_SUFI_RLIST, "Relative list" },
221 { RLC_SUFI_MRW, "Move receiving window" },
222 { RLC_SUFI_MRW_ACK, "Move receiving window acknowledgement" },
223 { RLC_SUFI_POLL, "Poll" },
227 /* reassembly related data */
228 static GHashTable *fragment_table = NULL; /* table of not yet assembled fragments */
229 static GHashTable *endpoints = NULL; /* List of SDU-endpoints */
230 static GHashTable *reassembled_table = NULL; /* maps fragment -> complete sdu */
231 static GHashTable *sequence_table = NULL; /* channel -> seq */
232 static GHashTable *duplicate_table = NULL; /* duplicates */
234 /* identify an RLC channel, using one of two options:
235 * - via Radio Bearer ID and unique UE ID
236 * - via Radio Bearer ID and (VPI/VCI/CID) + Link ID
243 guint16 link; /* link number */
244 guint8 rbid; /* radio bearer ID */
245 guint8 dir; /* direction */
246 enum rlc_li_size li_size;
250 /* used for duplicate detection */
255 guint16 oc; /* overflow counter, this is not used? */
259 struct rlc_channel ch;
261 /* We will store one seqlist per channel so this is a good place to indicate
262 * whether or not this channel's reassembly has failed or not. */
263 guint fail_packet; /* Equal to packet where fail flag was set or 0 otherwise. */
266 /* fragment representation */
269 struct rlc_channel ch;
270 guint16 seq; /* RLC sequence number */
271 guint16 li; /* LI within current RLC frame */
272 guint16 len; /* length of fragment data */
273 guint8 *data; /* store fragment data here */
275 struct rlc_frag *next; /* next fragment */
279 tvbuff_t *tvb; /* contains reassembled tvb */
280 guint16 len; /* total length of reassembled SDU */
281 guint16 fragcnt; /* number of fragments within this SDU */
282 guint8 *data; /* reassembled data buffer */
284 struct rlc_frag *reassembled_in;
285 struct rlc_frag *frags; /* pointer to list of fragments */
286 struct rlc_frag *last; /* pointer to last fragment */
290 guint16 li; /* original li */
291 guint16 len; /* length of this data fragment */
292 guint8 ext; /* extension bit value */
293 proto_tree *tree; /* subtree for this LI */
296 /*** KASUMI related variables and structs ***/
297 typedef struct umts_kat_key{ /*Stores 128-bits KASUMI key*/
298 guint64 high; /*64 MSB*/
299 guint64 low; /*64 LSB*/
303 /*Counter used as input for confidentiality algorithm*/
304 static guint32 ps_counter[31][2] ;
305 static gboolean counter_init[31][2];
306 static guint32 max_counter = 0;
307 static GTree * counter_map; /*Saves the countervalues at first pass through, since they will be update*/
309 /* hashtable functions for fragment table
313 rlc_channel_hash(gconstpointer key)
315 const struct rlc_channel *ch = (const struct rlc_channel *)key;
318 return ch->ueid | ch->rbid | ch->mode;
320 return (ch->vci << 16) | (ch->link << 16) | ch->vpi | ch->vci;
324 rlc_channel_equal(gconstpointer a, gconstpointer b)
326 const struct rlc_channel *x = (const struct rlc_channel *)a, *y = (const struct rlc_channel *)b;
328 if (x->ueid || y->ueid)
329 return x->ueid == y->ueid &&
330 x->rbid == y->rbid &&
331 x->mode == y->mode &&
332 x->dir == y->dir ? TRUE : FALSE;
334 return x->vpi == y->vpi &&
337 x->rbid == y->rbid &&
338 x->mode == y->mode &&
340 x->link == y->link ? TRUE : FALSE;
344 rlc_channel_assign(struct rlc_channel *ch, enum rlc_mode mode, packet_info *pinfo, struct atm_phdr *atm)
349 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
350 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
351 if (!fpinf || !rlcinf) return -1;
353 if (rlcinf->ueid[fpinf->cur_tb]) {
354 ch->ueid = rlcinf->ueid[fpinf->cur_tb];
355 ch->vpi = ch->vci = ch->link = ch->cid = 0;
361 ch->cid = atm->aal2_cid;
362 ch->link = pinfo->link_number;
364 ch->rbid = rlcinf->rbid[fpinf->cur_tb];
365 ch->dir = pinfo->link_dir;
367 ch->li_size = rlcinf->li_size[fpinf->cur_tb];
372 static struct rlc_channel *
373 rlc_channel_create(enum rlc_mode mode, packet_info *pinfo, struct atm_phdr *atm)
375 struct rlc_channel *ch;
378 ch = (struct rlc_channel *)g_malloc0(sizeof(struct rlc_channel));
379 rv = rlc_channel_assign(ch, mode, pinfo, atm);
382 /* channel assignment failed */
385 REPORT_DISSECTOR_BUG("Failed to assign channel");
391 rlc_channel_delete(gpointer data)
396 /* hashtable functions for reassembled table
400 rlc_frag_hash(gconstpointer key)
402 const struct rlc_frag *frag = (const struct rlc_frag *)key;
403 return (frag->frame_num << 12) | frag->seq;
407 rlc_frag_equal(gconstpointer a, gconstpointer b)
409 const struct rlc_frag *x = (const struct rlc_frag *)a;
410 const struct rlc_frag *y = (const struct rlc_frag *)b;
412 return rlc_channel_equal(&x->ch, &y->ch) &&
414 x->frame_num == y->frame_num &&
415 x->li == y->li ? TRUE : FALSE;
418 static struct rlc_sdu *
423 sdu = (struct rlc_sdu *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_sdu));
428 rlc_frag_delete(gpointer data)
430 struct rlc_frag *frag = (struct rlc_frag *)data;
439 rlc_sdu_frags_delete(gpointer data)
441 struct rlc_sdu *sdu = (struct rlc_sdu *)data;
442 struct rlc_frag *frag;
455 rlc_frag_assign(struct rlc_frag *frag, enum rlc_mode mode, packet_info *pinfo,
456 guint16 seq, guint16 li, struct atm_phdr *atm)
458 frag->frame_num = pinfo->num;
463 rlc_channel_assign(&frag->ch, mode, pinfo, atm);
469 rlc_frag_assign_data(struct rlc_frag *frag, tvbuff_t *tvb,
470 guint16 offset, guint16 length)
473 frag->data = (guint8 *)g_malloc(length);
474 tvb_memcpy(tvb, frag->data, offset, length);
478 static struct rlc_frag *
479 rlc_frag_create(tvbuff_t *tvb, enum rlc_mode mode, packet_info *pinfo,
480 guint16 offset, guint16 length, guint16 seq, guint16 li,
481 struct atm_phdr *atm)
483 struct rlc_frag *frag;
485 frag = (struct rlc_frag *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_frag));
486 rlc_frag_assign(frag, mode, pinfo, seq, li, atm);
487 rlc_frag_assign_data(frag, tvb, offset, length);
493 rlc_cmp_seq(gconstpointer a, gconstpointer b)
495 const struct rlc_seq *_a = (const struct rlc_seq *)a, *_b = (const struct rlc_seq *)b;
497 return _a->seq < _b->seq ? -1 :
498 _a->seq > _b->seq ? 1 :
502 static int moduloCompare(guint16 a, guint16 b, guint16 modulus)
511 ret = a - (b + modulus);
513 if( ret == (1 - modulus) ){
519 static guint16 getChannelSNModulus(struct rlc_channel * ch_lookup)
521 if( RLC_UM == ch_lookup->mode){ /*FIXME: This is a very heuristic way to determine SN bitwidth. */
528 /* "Value destroy" function called each time an entry is removed
529 * from the sequence_table hash.
530 * It frees the GList pointed to by the entry.
533 free_sequence_table_entry_data(gpointer data)
535 struct rlc_seqlist *list = (struct rlc_seqlist *)data;
536 if (list->list != NULL) {
537 g_list_free(list->list);
538 list->list = NULL; /* for good measure */
542 /** Utility functions used for various comparisons/cleanups in tree **/
544 rlc_simple_key_cmp(gconstpointer b_ptr, gconstpointer a_ptr, gpointer ignore _U_){
545 if( GPOINTER_TO_INT(a_ptr) > GPOINTER_TO_INT(b_ptr) ){
548 return GPOINTER_TO_INT(a_ptr) < GPOINTER_TO_INT(b_ptr);
552 fragment_table_init(void)
555 fragment_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, NULL);
556 endpoints = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal, rlc_channel_delete, NULL);
557 reassembled_table = g_hash_table_new_full(rlc_frag_hash, rlc_frag_equal,
558 rlc_frag_delete, rlc_sdu_frags_delete);
559 sequence_table = g_hash_table_new_full(rlc_channel_hash, rlc_channel_equal,
560 NULL, free_sequence_table_entry_data);
561 duplicate_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
563 /*Reset and or clear deciphering variables*/
564 counter_map = g_tree_new_full(rlc_simple_key_cmp,NULL,NULL,rlc_channel_delete);
565 for(i = 0; i< 31; i++ ){
566 ps_counter[i][0] = 0;
567 ps_counter[i][1] = 0;
568 counter_init[i][0] = 0;
569 counter_init[i][1] = 0;
575 fragment_table_cleanup(void)
577 g_tree_destroy(counter_map);
578 g_hash_table_destroy(fragment_table);
579 g_hash_table_destroy(endpoints);
580 g_hash_table_destroy(reassembled_table);
581 g_hash_table_destroy(sequence_table);
582 g_hash_table_destroy(duplicate_table);
585 /* add the list of fragments for this sdu to 'tree' */
587 tree_add_fragment_list(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
590 proto_tree *frag_tree;
592 struct rlc_frag *sdufrag;
594 ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, -1, ENC_NA);
595 frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
596 proto_item_append_text(ti, " (%u bytes, %u fragments): ",
597 sdu->len, sdu->fragcnt);
598 sdufrag = sdu->frags;
601 if (sdufrag->len > 0) {
602 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
603 sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: %u-%u (%u bytes) (Seq: %u)",
604 sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
606 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, offset,
607 sdufrag->len, sdufrag->frame_num, "Frame: %u, payload: none (0 bytes) (Seq: %u)",
608 sdufrag->frame_num, sdufrag->seq);
610 offset += sdufrag->len;
611 sdufrag = sdufrag->next;
615 /* add the list of fragments for this sdu to 'tree' */
617 tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
620 proto_tree *frag_tree;
622 struct rlc_frag *sdufrag;
624 ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, ENC_NA);
625 frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
626 proto_item_append_text(ti, " (%u bytes, %u fragments): ",
627 sdu->len, sdu->fragcnt);
628 sdufrag = sdu->frags;
631 proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0,
632 0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
633 sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
634 offset += sdufrag->len;
635 sdufrag = sdufrag->next;
639 /* Add the same description to too the two given proto_items */
641 add_description(proto_item *li_ti, proto_item *length_ti,
642 const char *format, ...)
644 #define MAX_INFO_BUFFER 256
645 static char info_buffer[MAX_INFO_BUFFER];
649 va_start(ap, format);
650 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
653 proto_item_append_text(li_ti, " (%s)", info_buffer);
654 proto_item_append_text(length_ti, " (%s)", info_buffer);
657 /* add information for an LI to 'tree' */
659 tree_add_li(enum rlc_mode mode, struct rlc_li *li, guint8 li_idx, guint32 hdr_offs,
660 gboolean li_is_on_2_bytes, tvbuff_t *tvb, proto_tree *tree)
662 proto_item *root_ti, *ti;
667 if (!tree) return NULL;
669 if (li_is_on_2_bytes) {
670 li_offs = hdr_offs + li_idx*2;
671 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 2, ENC_NA);
672 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
673 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 15, &length, ENC_BIG_ENDIAN);
677 add_description(root_ti, ti, "The previous RLC PDU was exactly filled with the last segment of an RLC SDU and there is no LI that indicates the end of the RLC SDU in the previous RLC PDU");
680 if (mode == RLC_UM) {
681 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the second last octet in this RLC PDU is the last octet of the same RLC SDU. The remaining octet in the RLC PDU is ignored");
683 add_description(root_ti, ti, "Reserved");
687 add_description(root_ti, ti, "The second last octet in the previous RLC PDU is the last octet of an RLC SDU and there is no LI to indicate the end of SDU. The remaining octet in the previous RLC PDU is ignored");
690 if (mode == RLC_UM) {
691 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
693 add_description(root_ti, ti, "Reserved");
697 if (mode == RLC_UM) {
698 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the last octet in this RLC PDU is the last octet of the same RLC SDU");
700 add_description(root_ti, ti, "Reserved");
704 if (mode == RLC_UM) {
705 add_description(root_ti, ti, "The RLC PDU contains a segment of an SDU but neither the first octet nor the last octet of this SDU");
707 add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
711 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
715 add_description(root_ti, ti, "length=%u", (guint16)length);
718 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+15, 1, ENC_BIG_ENDIAN);
720 li_offs = hdr_offs + li_idx;
721 root_ti = proto_tree_add_item(tree, hf_rlc_li, tvb, li_offs, 1, ENC_NA);
722 li_tree = proto_item_add_subtree(root_ti, ett_rlc_frag);
723 ti = proto_tree_add_bits_ret_val(li_tree, hf_rlc_li_value, tvb, li_offs*8, 7, &length, ENC_BIG_ENDIAN);
726 add_description(root_ti, ti, "The previous RLC PDU was exactly filled with the last segment of an RLC SDU and there is no LI that indicates the end of the RLC SDU in the previous RLC PDU");
729 if (mode == RLC_UM) {
730 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU");
732 add_description(root_ti, ti, "Reserved");
736 if (mode == RLC_UM) {
737 add_description(root_ti, ti, "The first data octet in this RLC PDU is the first octet of an RLC SDU and the last octet in this RLC PDU is the last octet of the same RLC SDU");
739 add_description(root_ti, ti, "Reserved");
743 if (mode == RLC_UM) {
744 add_description(root_ti, ti, "The RLC PDU contains a segment of an SDU but neither the first octet nor the last octet of this SDU");
746 add_description(root_ti, ti, "The rest of the RLC PDU includes a piggybacked STATUS PDU");
750 add_description(root_ti, ti, "The rest of the RLC PDU is padding");
754 add_description(root_ti, ti, "length=%u", (guint16)length);
757 proto_tree_add_bits_item(li_tree, hf_rlc_li_ext, tvb, li_offs*8+7, 1, ENC_BIG_ENDIAN);
761 if (li->li > tvb_reported_length_remaining(tvb, hdr_offs)) return li_tree;
762 if (li->len > li->li) return li_tree;
763 ti = proto_tree_add_item(li_tree, hf_rlc_li_data, tvb, hdr_offs + li->li - li->len, li->len, ENC_NA);
764 PROTO_ITEM_SET_HIDDEN(ti);
770 /* add a fragment to an SDU */
772 rlc_sdu_add_fragment(enum rlc_mode mode, struct rlc_sdu *sdu, struct rlc_frag *frag)
774 struct rlc_frag *tmp;
777 /* insert as first element */
781 sdu->len += frag->len;
786 /* insert as last element */
787 sdu->last->next = frag;
790 sdu->len += frag->len;
796 /* If receiving exotic border line sequence, e.g. 4094, 4095, 0, 1 */
797 if (frag->seq+2048 < tmp->seq) {
798 while (tmp->next && frag->seq+2048 < tmp->seq)
800 if (tmp->next == NULL) {
804 while (tmp->next && tmp->next->seq < frag->seq)
806 frag->next = tmp->next;
808 if (frag->next == NULL) sdu->last = frag;
810 } else { /* Receiving ordinary sequence */
811 if (frag->seq < tmp->seq) {
812 /* insert as first element */
816 while (tmp->next && tmp->next->seq < frag->seq)
818 frag->next = tmp->next;
820 if (frag->next == NULL) sdu->last = frag;
823 sdu->len += frag->len;
833 reassemble_data(struct rlc_channel *ch, struct rlc_sdu *sdu, struct rlc_frag *frag)
835 struct rlc_frag *temp;
838 if (!sdu || !ch || !sdu->frags) return;
840 if (sdu->data) return; /* already assembled */
843 sdu->reassembled_in = frag;
845 sdu->reassembled_in = sdu->last;
847 sdu->data = (guint8 *)wmem_alloc(wmem_file_scope(), sdu->len);
849 while (temp && ((offs + temp->len) <= sdu->len)) {
850 memcpy(sdu->data + offs, temp->data, temp->len);
853 /* mark this fragment in reassembled table */
854 g_hash_table_insert(reassembled_table, temp, sdu);
861 #define RLC_ADD_FRAGMENT_FAIL_PRINT 0
862 #define RLC_ADD_FRAGMENT_DEBUG_PRINT 0
863 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
865 printends(GList * list)
869 g_print("-> length: %d\n[", g_list_length(list));
872 g_print("%d ", GPOINTER_TO_INT(list->data));
879 static struct rlc_frag **
880 get_frags(packet_info * pinfo, struct rlc_channel * ch_lookup, struct atm_phdr *atm)
882 gpointer value = NULL;
883 struct rlc_frag ** frags = NULL;
884 /* Look for already created frags table */
885 if (g_hash_table_lookup_extended(fragment_table, ch_lookup, NULL, &value)) {
886 frags = (struct rlc_frag **)value;
887 } else if (pinfo != NULL) {
888 struct rlc_channel *ch;
889 ch = rlc_channel_create(ch_lookup->mode, pinfo, atm);
890 frags = (struct rlc_frag **)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_frag *) * 4096);
891 g_hash_table_insert(fragment_table, ch, frags);
897 static struct rlc_seqlist *
898 get_endlist(packet_info * pinfo, struct rlc_channel * ch_lookup, struct atm_phdr *atm)
900 gpointer value = NULL;
901 struct rlc_seqlist * endlist = NULL;
902 /* If there already exists a frag table for this channel use that one. */
903 if (g_hash_table_lookup_extended(endpoints, ch_lookup, NULL, &value)) {
904 endlist = (struct rlc_seqlist *)value;
905 } else if (pinfo != NULL) { /* Else create a new one. */
906 struct rlc_channel * ch;
908 endlist = wmem_new(wmem_file_scope(), struct rlc_seqlist);
909 ch = rlc_channel_create(ch_lookup->mode, pinfo, atm);
910 endlist->fail_packet = 0;
911 endlist->list = NULL;
912 endlist->list = g_list_prepend(endlist->list, GINT_TO_POINTER(-1));
913 g_hash_table_insert(endpoints, ch, endlist);
921 reassemble_sequence(struct rlc_frag ** frags, struct rlc_seqlist * endlist,
922 struct rlc_channel * ch_lookup, guint16 start, guint16 end)
924 GList * element = NULL;
925 struct rlc_sdu * sdu = rlc_sdu_create();
927 guint16 snmod = getChannelSNModulus(ch_lookup);
929 /* Insert fragments into SDU. */
930 for (; moduloCompare(start,end,snmod ) <= 0; start = (start+1)%snmod)
932 struct rlc_frag * tempfrag = NULL;
933 tempfrag = frags[start]->next;
934 frags[start]->next = NULL;
935 rlc_sdu_add_fragment(ch_lookup->mode, sdu, frags[start]);
936 frags[start] = tempfrag;
939 /* Remove first endpoint. */
940 element = g_list_first(endlist->list);
942 endlist->list = g_list_remove_link(endlist->list, element);
943 if (frags[end] != NULL) {
945 endlist->list->data = GINT_TO_POINTER((GPOINTER_TO_INT(endlist->list->data) - 1 + snmod) % snmod);
949 reassemble_data(ch_lookup, sdu, NULL);
952 /* Reset the specified channel's reassembly data, useful for when a sequence
953 * resets on transport channel swap. */
955 rlc_reset_channel(enum rlc_mode mode, guint8 rbid, guint8 dir, guint32 ueid,
956 struct atm_phdr *atm)
958 struct rlc_frag ** frags = NULL;
959 struct rlc_seqlist * endlist = NULL;
960 struct rlc_channel ch_lookup;
963 ch_lookup.mode = mode;
964 ch_lookup.rbid = rbid;
966 ch_lookup.ueid = ueid;
967 frags = get_frags(NULL, &ch_lookup, atm);
968 endlist = get_endlist(NULL, &ch_lookup, atm);
969 DISSECTOR_ASSERT(frags && endlist);
971 endlist->fail_packet = 0;
972 g_list_free(endlist->list);
973 endlist->list = NULL;
975 for (i = 0; i < 4096; i++) {
980 /* add a new fragment to an SDU
981 * if length == 0, just finalize the specified SDU
983 static struct rlc_frag *
984 add_fragment(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
985 proto_tree *tree, guint16 offset, guint16 seq, guint16 num_li,
986 guint16 len, gboolean final, struct atm_phdr *atm)
988 struct rlc_channel ch_lookup;
989 struct rlc_frag frag_lookup, *frag = NULL;
990 gpointer orig_key = NULL, value = NULL;
991 struct rlc_sdu *sdu = NULL;
992 struct rlc_frag ** frags = NULL;
993 struct rlc_seqlist * endlist = NULL;
994 GList * element = NULL;
997 if (rlc_channel_assign(&ch_lookup, mode, pinfo, atm) == -1) {
1000 rlc_frag_assign(&frag_lookup, mode, pinfo, seq, num_li, atm);
1001 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1002 g_print("packet: %d, channel (%d %d %d) seq: %u, num_li: %u, offset: %u, \n", pinfo->num, ch_lookup.dir, ch_lookup.rbid, ch_lookup.ueid, seq, num_li, offset);
1005 snmod = getChannelSNModulus(&ch_lookup);
1007 /* look for an already assembled SDU */
1008 if (g_hash_table_lookup_extended(reassembled_table, &frag_lookup, &orig_key, &value)) {
1009 /* this fragment is already reassembled somewhere */
1010 frag = (struct rlc_frag *)orig_key;
1011 sdu = (struct rlc_sdu *)value;
1013 /* mark the fragment, if reassembly happened somewhere else */
1014 if (frag->seq != sdu->reassembled_in->seq ||
1015 frag->li != sdu->reassembled_in->li)
1016 proto_tree_add_uint(tree, hf_rlc_reassembled_in, tvb, 0, 0,
1017 sdu->reassembled_in->frame_num);
1022 frags = get_frags(pinfo, &ch_lookup, atm);
1023 endlist = get_endlist(pinfo, &ch_lookup, atm);
1025 /* If already done reassembly */
1026 if (pinfo->fd->flags.visited) {
1027 if (tree && len > 0) {
1028 if (endlist->list && endlist->list->next) {
1029 gint16 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1030 gint16 end = GPOINTER_TO_INT(endlist->list->next->data);
1031 gint16 missing = start;
1032 gboolean wecanreasmmore = TRUE;
1034 for (; moduloCompare(missing,end,snmod ) <= 0; missing = (missing+1)%snmod)
1036 if (frags[missing] == NULL) {
1037 wecanreasmmore = FALSE;
1042 if (wecanreasmmore) {
1043 reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1045 if (end >= 0 && end < snmod && frags[end]) {
1046 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1047 "Did not perform reassembly because of unfinished sequence (%d->%d [packet %u]), could not find %d.", start, end, frags[end]->frame_num, missing);
1049 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_unfinished_sequence, tvb, 0, 0,
1050 "Did not perform reassembly because of unfinished sequence (%d->%d [could not determine packet]), could not find %d.", start, end, missing);
1053 } else if (endlist->list) {
1054 if (endlist->fail_packet != 0 && endlist->fail_packet <= pinfo->num) {
1055 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_fail_flag_set, tvb, 0, 0, "Did not perform reassembly because fail flag was set in packet %u.", endlist->fail_packet);
1057 gint16 end = GPOINTER_TO_INT(endlist->list->data);
1058 if (end >= 0 && end < snmod && frags[end]) {
1059 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [packet %d]).", end, frags[end]->frame_num);
1061 proto_tree_add_expert_format(tree, pinfo, &ei_rlc_reassembly_lingering_endpoint, tvb, 0, 0, "Did not perform reassembly because of unfinished sequence, found lingering endpoint (%d [could not determine packet]).", end);
1065 expert_add_info(pinfo, NULL, &ei_rlc_reassembly_unknown_error);
1068 return NULL; /* If already done reassembly and no SDU found, too bad */
1071 if (endlist->fail_packet != 0) { /* don't continue after sh*t has hit the fan */
1075 frag = rlc_frag_create(tvb, mode, pinfo, offset, len, seq, num_li, atm);
1077 /* If frags[seq] is not NULL then we must have data from several PDUs in the
1078 * same RLC packet (using Length Indicators) or something has gone terribly
1080 if (frags[seq] != NULL) {
1082 struct rlc_frag * tempfrag = frags[seq];
1083 while (tempfrag->next != NULL)
1084 tempfrag = tempfrag->next;
1085 tempfrag->next = frag;
1086 } else { /* This should never happen */
1087 endlist->fail_packet = pinfo->num;
1094 /* It is also possible that frags[seq] is NULL even though we do have data
1095 * from several PDUs in the same RLC packet. This is if the reassembly is
1096 * not lagging behind at all because of perfectly ordered sequences. */
1097 if (endlist->list && num_li != 0) {
1098 gint16 first = GPOINTER_TO_INT(endlist->list->data);
1100 endlist->list->data = GINT_TO_POINTER(first-1);
1104 /* If this is an endpoint */
1106 endlist->list = g_list_append(endlist->list, GINT_TO_POINTER((gint)seq));
1109 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1110 printends(endlist->list);
1113 /* Try to reassemble SDU. */
1114 if (endlist->list && endlist->list->next) {
1115 gint16 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1116 gint16 end = GPOINTER_TO_INT(endlist->list->next->data);
1117 if (frags[end] == NULL) {
1118 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1119 proto_tree_add_debug_text(tree, "frag[end] is null, this is probably because end was a startpoint but because of some error ended up being treated as an endpoint, setting fail flag, start %d, end %d, packet %u\n", start, end, pinfo->num);
1121 endlist->fail_packet = pinfo->num;
1125 /* If our endpoint is a LI=0 with no data. */
1126 if (start == end && frags[start]->len == 0) {
1127 element = g_list_first(endlist->list);
1129 endlist->list = g_list_remove_link(endlist->list, element);
1131 frags[start] = frags[start]->next;
1133 /* If frags[start] is not NULL now, then that means that there was
1134 * another fragment with the same seq number because of LI. If we
1135 * don't decrease the endpoint by 1 then that fragment will be
1136 * skipped and all hell will break lose. */
1137 if (frags[start] != NULL) {
1138 endlist->list->data = GINT_TO_POINTER(start-1);
1140 /* NOTE: frags[start] is wmem_alloc'ed and will remain until file closes, we would want to free it here maybe. */
1144 #if RLC_ADD_FRAGMENT_DEBUG_PRINT
1145 g_print("start: %d, end: %d\n",start, end);
1148 for (; moduloCompare(start,end,snmod ) < 0; start = (start+1)%snmod)
1150 if (frags[start] == NULL) {
1151 if (MIN((start-seq+snmod)%snmod, (seq-start+snmod)%snmod) >= snmod/4) {
1152 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1153 proto_tree_add_debug_text(tree,
1154 "Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1155 too far away from an unfinished sequence (%u->%u). The missing sequence number \
1156 is %u. The most recently complete sequence ended in packet %u.", pinfo->num, seq, 0, end, start, 0);
1158 endlist->fail_packet = pinfo->num; /* If it has gone too far, give up */
1164 start = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1165 reassemble_sequence(frags, endlist, &ch_lookup, start, end);
1166 } else if (endlist->list) {
1167 gint16 first = (GPOINTER_TO_INT(endlist->list->data) + 1) % snmod;
1168 /* If the distance between the oldest stored endpoint in endlist and
1169 * this endpoint is too large, set fail flag. */
1170 if (MIN((first-seq+snmod)%snmod, (seq-first+snmod)%snmod) >= snmod/4) {
1171 #if RLC_ADD_FRAGMENT_FAIL_PRINT
1172 proto_tree_add_debug_text(tree,
1173 "Packet %u. Setting fail flag because RLC fragment with sequence number %u was \
1174 too far away from an unfinished sequence with start %u and without end.", pinfo->num, seq, first);
1176 endlist->fail_packet = pinfo->num; /* Give up if things have gone too far. */
1184 /* is_data is used to identify rlc data parts that are not identified by an LI, but are at the end of
1186 * these can be valid reassembly points, but only if the LI of the *next* relevant RLC frame is
1187 * set to '0' (this is indicated in the reassembled SDU
1190 get_reassembled_data(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo,
1191 proto_tree *tree, guint16 seq, guint16 num_li,
1192 struct atm_phdr *atm)
1194 gpointer orig_frag, orig_sdu;
1195 struct rlc_sdu *sdu;
1196 struct rlc_frag lookup, *frag;
1198 rlc_frag_assign(&lookup, mode, pinfo, seq, num_li, atm);
1200 if (!g_hash_table_lookup_extended(reassembled_table, &lookup,
1201 &orig_frag, &orig_sdu))
1204 sdu = (struct rlc_sdu *)orig_sdu;
1205 if (!sdu || !sdu->data)
1210 if (!rlc_frag_equal(&lookup, sdu->reassembled_in)) return NULL;
1214 while (frag->next) {
1215 if (frag->next->seq - frag->seq > 1) {
1216 proto_tree_add_expert(tree, pinfo, &ei_rlc_incomplete_sequence, tvb, 0, 0);
1217 tree_add_fragment_list_incomplete(sdu, tvb, tree);
1223 sdu->tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->len, sdu->len);
1224 add_new_data_source(pinfo, sdu->tvb, "Reassembled RLC Message");
1226 /* reassembly happened here, so create the fragment list */
1227 if (tree && sdu->fragcnt > 1)
1228 tree_add_fragment_list(sdu, sdu->tvb, tree);
1233 #define RLC_RETRANSMISSION_TIMEOUT 5 /* in seconds */
1235 rlc_is_duplicate(enum rlc_mode mode, packet_info *pinfo, guint16 seq,
1236 guint32 *original, struct atm_phdr *atm)
1239 struct rlc_seqlist lookup, *list;
1240 struct rlc_seq seq_item, *seq_new;
1243 gboolean is_duplicate,is_unseen;
1245 if (rlc_channel_assign(&lookup.ch, mode, pinfo, atm) == -1)
1247 list = (struct rlc_seqlist *)g_hash_table_lookup(sequence_table, &lookup.ch);
1249 /* we see this channel for the first time */
1250 list = (struct rlc_seqlist *)wmem_alloc0(wmem_file_scope(), sizeof(*list));
1251 rlc_channel_assign(&list->ch, mode, pinfo, atm);
1252 g_hash_table_insert(sequence_table, &list->ch, list);
1255 seq_item.frame_num = pinfo->num;
1257 /* When seq is 12 bit (in RLC protocol), it will wrap around after 4096. */
1258 /* Window size is at most 4095 so we remove packets further away than that */
1259 element = g_list_first(list->list);
1260 snmod = getChannelSNModulus(&lookup.ch);
1262 seq_new = (struct rlc_seq *)element->data;
1263 /* Add SN modulus because %-operation for negative values in C is not equal to mathematical modulus */
1264 if (MIN((seq_new->seq-seq+snmod)%snmod, (seq-seq_new->seq+snmod)%snmod) >= snmod/4) {
1265 list->list = g_list_remove_link(list->list, element);
1269 is_duplicate = FALSE;
1271 element = g_list_find_custom(list->list, &seq_item, rlc_cmp_seq);
1273 /* Check if this is a different frame (by comparing frame numbers) which arrived less than */
1274 /* RLC_RETRANSMISSION_TIMEOUT seconds ago */
1275 seq_new = (struct rlc_seq *)element->data;
1276 if (seq_new->frame_num < seq_item.frame_num) {
1277 nstime_delta(&delta, &pinfo->abs_ts, &seq_new->arrival);
1278 if (delta.secs < RLC_RETRANSMISSION_TIMEOUT) {
1279 /* This is a duplicate. */
1281 /* Save the frame number where our sequence number was previously seen */
1282 *original = seq_new->frame_num;
1284 is_duplicate = TRUE;
1287 else if (seq_new->frame_num == seq_item.frame_num) {
1288 /* Check if our frame is already in the list and this is a secondary check.*/
1289 /* in this case raise a flag so the frame isn't entered more than once to the list */
1292 element = g_list_find_custom(element->next, &seq_item, rlc_cmp_seq);
1295 /* Add to list for the first time this frame is checked */
1296 seq_new = (struct rlc_seq *)wmem_alloc0(wmem_file_scope(), sizeof(struct rlc_seq));
1297 *seq_new = seq_item;
1298 seq_new->arrival = pinfo->abs_ts;
1299 list->list = g_list_append(list->list, seq_new); /* insert in order of arrival */
1301 return is_duplicate;
1305 rlc_call_subdissector(enum rlc_channel_type channel, tvbuff_t *tvb,
1306 packet_info *pinfo, proto_tree *tree)
1308 enum rrc_message_type msgtype;
1311 msgtype = RRC_MESSAGE_TYPE_UL_CCCH;
1314 msgtype = RRC_MESSAGE_TYPE_DL_CCCH;
1317 msgtype = RRC_MESSAGE_TYPE_INVALID;
1318 call_dissector(bmc_handle, tvb, pinfo, tree);
1319 /* once the packet has been dissected, protect it from further changes using a 'fence' in the INFO column */
1320 col_append_str(pinfo->cinfo, COL_INFO," ");
1321 col_set_fence(pinfo->cinfo, COL_INFO);
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 using a 'fence' in the INFO column */
1340 col_append_str(pinfo->cinfo, COL_INFO," ");
1341 col_set_fence(pinfo->cinfo, COL_INFO);
1344 return; /* stop dissecting */
1346 if (msgtype != RRC_MESSAGE_TYPE_INVALID) {
1347 struct rrc_info *rrcinf;
1349 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1350 rrcinf = (rrc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0);
1352 rrcinf = (rrc_info *)wmem_alloc0(wmem_file_scope(), sizeof(struct rrc_info));
1353 p_add_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0, rrcinf);
1355 rrcinf->msgtype[fpinf->cur_tb] = msgtype;
1356 call_dissector(rrc_handle, tvb, pinfo, tree);
1357 /* once the packet has been dissected, protect it from further changes using a 'fence' in the INFO column */
1358 col_append_str(pinfo->cinfo, COL_INFO," ");
1359 col_set_fence(pinfo->cinfo, COL_INFO);
1364 add_channel_info(packet_info * pinfo, proto_tree * tree, fp_info * fpinf, rlc_info * rlcinf)
1367 proto_tree * channel_tree ;
1369 item = proto_tree_add_item(tree, hf_rlc_channel, NULL, 0, 0, ENC_NA);
1370 channel_tree = proto_item_add_subtree(item, ett_rlc_channel);
1371 proto_item_append_text(item, " (rbid: %u, dir: %s, uid: 0x%08x)", rlcinf->rbid[fpinf->cur_tb],
1372 val_to_str_const(pinfo->link_dir, rlc_dir_vals, "Unknown"), rlcinf->ueid[fpinf->cur_tb]);
1373 PROTO_ITEM_SET_GENERATED(item);
1374 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_rbid, NULL, 0, 0, rlcinf->rbid[fpinf->cur_tb]);
1375 PROTO_ITEM_SET_GENERATED(item);
1376 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_dir, NULL, 0, 0, pinfo->link_dir);
1377 PROTO_ITEM_SET_GENERATED(item);
1378 item = proto_tree_add_uint(channel_tree, hf_rlc_channel_ueid, NULL, 0, 0, rlcinf->ueid[fpinf->cur_tb]);
1379 PROTO_ITEM_SET_GENERATED(item);
1383 #ifdef HAVE_UMTS_KASUMI
1385 translate_hex_key(gchar * char_key){
1389 key_in = wmem_alloc0(wmem_packet_scope(), sizeof(guint8)*16);
1390 j= (int)(strlen(char_key)/2)-1;
1391 /*Translate "hex-string" into a byte aligned block */
1392 for(i = (int)strlen(char_key); i> 0; i-=2 ){
1393 key_in[j] = ( (guint8) (strtol( &char_key[i-2], NULL, 16 ) ));
1394 char_key[i-2] = '\0';
1402 /** @brief Deciphers a given tvb
1404 * Note that the actual KASUMI implementation needs to be placed into
1405 * epan/crypt/kasumi.* by "end users" since due to patents the actual implementation
1406 * cannot be distributed openly at the moment.
1408 * Refer to 3GPP TS 35.201 and 3GPP TS 35.202 for further information.
1410 * @param tvb The ciphered data.
1411 * @param pinfo Packet info.
1412 * @param counter the COUNTER value input
1413 * @param rbid the radiobear id
1414 * @param dir Direction of the link
1415 * @param header_size Size of the unciphered header
1416 * @return tvb Returns a deciphered tvb
1419 #ifndef HAVE_UMTS_KASUMI
1420 rlc_decipher_tvb(tvbuff_t *tvb _U_, packet_info *pinfo, guint32 counter _U_,
1421 guint8 rbid _U_, gboolean dir _U_, guint8 header_size _U_) {
1422 /*Check if we have a KASUMI implementation*/
1423 expert_add_info(pinfo, NULL, &ei_rlc_kasumi_implementation_missing);
1426 rlc_decipher_tvb(tvbuff_t *tvb, packet_info *pinfo, guint32 counter, guint8 rbid, gboolean dir, guint8 header_size) {
1427 guint8* out=NULL,*key_in = NULL;
1430 /*Fix the key into a byte block*/
1431 /*TODO: This should be done in a preferences callback function*/
1432 out = wmem_alloc0(wmem_packet_scope(), strlen(global_rlc_kasumi_key)+1);
1433 memcpy(out,global_rlc_kasumi_key,strlen(global_rlc_kasumi_key)); /*Copy from prefrence const pointer*/
1434 key_in = translate_hex_key(out); /*Translation*/
1436 /*Location for decrypted data & original RLC header*/
1437 out = tvb_memdup(pinfo->pool, tvb, 0, tvb_captured_length(tvb));
1439 /*Call f8 confidentiality function, note that rbid is zero indexed*/
1440 f8( key_in, counter, rbid-1, dir, &out[header_size], (tvb_captured_length(tvb)-header_size)*8 );
1443 t = tvb_new_real_data(out,tvb_captured_length(tvb), tvb_reported_length(tvb));
1444 add_new_data_source(pinfo, t, "Deciphered RLC");
1446 #endif /* HAVE_UMTS_KASUMI */
1449 /** @brief Checks if an RLC packet is ciphered, according to information reported from the RRC layer
1451 * @param pinfo Packet info.
1452 * @param fpinf FP info
1453 * @param rlcinf RLC info
1454 * @param seq Sequence number of the RLC packet
1455 * @return gboolean Returns TRUE if the packet is ciphered and false otherwise
1458 is_ciphered_according_to_rrc(packet_info *pinfo, fp_info *fpinf, rlc_info *rlcinf ,guint16 seq) {
1461 rrc_ciphering_info *ciphering_info;
1464 guint32 security_mode_frame_num;
1465 gint32 ciphering_begin_seq;
1467 if(global_ignore_rrc_ciphering_indication) {
1471 cur_tb = fpinf->cur_tb;
1472 ueid = rlcinf->ueid[cur_tb];
1473 ciphering_info = (rrc_ciphering_info *)g_tree_lookup(rrc_ciph_info_tree, GINT_TO_POINTER((gint)ueid));
1474 if(ciphering_info != NULL) {
1475 rbid = rlcinf->rbid[cur_tb];
1476 direction = fpinf->is_uplink ? P2P_DIR_UL : P2P_DIR_DL;
1477 security_mode_frame_num = ciphering_info->setup_frame[direction];
1478 ciphering_begin_seq = ciphering_info->seq_no[rbid][direction];
1479 /* Making sure the rrc security message's frame number makes sense */
1480 if( security_mode_frame_num > 0 && security_mode_frame_num <= pinfo->num) {
1481 /* Making sure the sequence number where ciphering starts makes sense */
1482 /* TODO: This check is incorrect if the sequence numbers wrap around */
1483 if(ciphering_begin_seq >= 0 && ciphering_begin_seq <= seq){
1492 * @param key is created with GINT_TO_POINTER
1493 * @param value is a pointer to a guint32
1494 * @param data is a pointer to a guint32
1497 iter_same(gpointer key, gpointer value, gpointer data) {
1498 /*If true we found the correct frame*/
1499 if ((guint32)GPOINTER_TO_INT(key) > *(guint32*)data){
1500 *((guint32*)data) = *((guint32*)value);
1503 *((guint32*)data) = (guint32)GPOINTER_TO_INT(key);
1509 * Used for looking up and old ciphering counter value in the counter_map tree.
1510 * @param key is created with GINT_TO_POINTER
1511 * @param value is pointer to an array of 2 guint32s
1512 * @param data is a pointer to an array of 3 guint32s
1515 rlc_find_old_counter(gpointer key, gpointer value, gpointer data) {
1517 /*If true we found the correct frame*/
1518 if( (guint32)GPOINTER_TO_INT(key) >= ((guint32 *)data)[0] ){
1521 /*Overwrite the data since the previous one wasn't correct*/
1522 ((guint32*)data)[1] = ((guint32*)value)[0];
1523 ((guint32*)data)[2] = ((guint32*)value)[1];
1529 rlc_decipher(tvbuff_t *tvb, packet_info * pinfo, proto_tree * tree, fp_info * fpinf,
1530 rlc_info * rlcinf, guint16 seq, enum rlc_mode mode)
1532 rrc_ciphering_info *ciphering_info;
1533 guint8 indx, header_size, hfn_shift;
1536 int ciphered_data_hf;
1538 indx = fpinf->is_uplink ? P2P_DIR_UL : P2P_DIR_DL;
1539 pos = fpinf->cur_tb;
1540 if (mode ==RLC_UM) {
1548 /*Ciphering info singled in RRC by securitymodecommands */
1549 ciphering_info = (rrc_ciphering_info *)g_tree_lookup(rrc_ciph_info_tree, GINT_TO_POINTER((gint)rlcinf->ueid[fpinf->cur_tb]));
1551 /*TODO: This doesn't really work for all packets..*/
1552 /*Check if we have ciphering info and that this frame is ciphered*/
1553 if(ciphering_info!=NULL && ( (ciphering_info->setup_frame[indx] > 0 && ciphering_info->setup_frame[indx] < pinfo->num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] == -1) ||
1554 (ciphering_info->setup_frame[indx] < pinfo->num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] >= 0 && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] <= seq) )){
1558 /*Check if this counter has been initialized*/
1559 if(!counter_init[rlcinf->rbid[pos]][indx] ){
1560 guint32 frame_num = pinfo->num;
1562 /*Initializes counter*/
1563 counter_init[rlcinf->rbid[pos]][0] = TRUE;
1564 counter_init[rlcinf->rbid[pos]][1] = TRUE;
1565 /*Find appropriate start value*/
1566 g_tree_foreach(ciphering_info->start_ps, (GTraverseFunc)iter_same, &frame_num);
1568 /*Set COUNTER value accordingly as specified by 6.4.8 in 3GPP TS 33.102 */
1569 if(max_counter +2 > frame_num && ciphering_info->seq_no[rlcinf->rbid[pos]][indx] == -1){
1570 ps_counter[rlcinf->rbid[pos]][0] = (max_counter+2) << hfn_shift;
1571 ps_counter[rlcinf->rbid[pos]][1] = (max_counter+2) << hfn_shift;
1573 ps_counter[rlcinf->rbid[pos]][0] = frame_num << hfn_shift;
1574 ps_counter[rlcinf->rbid[pos]][1] = frame_num << hfn_shift;
1578 /*Preserve counter value for next dissection round*/
1580 ciph = (guint32 *)g_malloc(sizeof(guint32)*2);
1581 ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1582 ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1583 g_tree_insert(counter_map, GINT_TO_POINTER((gint)pinfo->num), ciph);
1587 /*Update the maximal COUNTER value seen so far*/
1588 max_counter = MAX(max_counter,((ps_counter[rlcinf->rbid[pos]][indx]) | seq) >> hfn_shift);
1590 /*XXX: Since RBID in umts isn't configured properly..*/
1591 if(rlcinf->rbid[pos] == 9 ){
1593 guint32 frame_num[3];
1594 /*Set frame num we will be "searching" around*/
1595 frame_num[0] = pinfo->num;
1596 /*Find the correct counter value*/
1597 g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1598 t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),16,!fpinf->is_uplink,header_size);
1600 t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),16,!fpinf->is_uplink,header_size);
1604 /*We need to find the original counter value for second dissection pass*/
1605 guint32 frame_num[3];
1606 frame_num[0] = pinfo->num;
1607 g_tree_foreach(counter_map, (GTraverseFunc)rlc_find_old_counter, &frame_num[0]);
1608 t = rlc_decipher_tvb(tvb, pinfo, (frame_num[indx+1] | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1610 t = rlc_decipher_tvb(tvb, pinfo, ((ps_counter[rlcinf->rbid[pos]][indx]) | seq),rlcinf->rbid[pos],!fpinf->is_uplink,header_size);
1613 /*Update the hyperframe number*/
1616 ps_counter[rlcinf->rbid[pos]][indx] += 1 << hfn_shift;
1618 if(!tree){/*Preserve counter for second packet analysis run*/
1620 ciph = (guint32 *)g_malloc(sizeof(guint32)*2);
1621 ciph[0] = ps_counter[rlcinf->rbid[pos]][0];
1622 ciph[1] = ps_counter[rlcinf->rbid[pos]][1];
1623 g_tree_insert(counter_map, GINT_TO_POINTER((gint)pinfo->num+1), ciph);
1627 /*Unable to decipher the packet*/
1629 /* Choosing the right field text ("LIs & Data" or just "Data") based on extension bit / header extension */
1630 ext = tvb_get_guint8(tvb, header_size - 1) & 0x01;
1631 ciphered_data_hf = (ext == 1) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
1632 /* Adding ciphered payload field to tree */
1633 proto_tree_add_item(tree, ciphered_data_hf, tvb, header_size, -1, ENC_NA);
1634 proto_tree_add_expert(tree, pinfo, &ei_rlc_ciphered_data, tvb, header_size, -1);
1635 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1639 col_append_str(pinfo->cinfo, COL_INFO, "[Deciphered Data]");
1641 /*TODO: Old tvb should be freed here?*/
1647 dissect_rlc_tm(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1648 proto_tree *top_level, proto_tree *tree)
1653 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1654 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1657 if (fpinf && rlcinf) {
1658 /* Add "channel" information, very useful for debugging. */
1659 add_channel_info(pinfo, tree, fpinf, rlcinf);
1661 proto_tree_add_item(tree, hf_rlc_data, tvb, 0, -1, ENC_NA);
1663 rlc_call_subdissector(channel, tvb, pinfo, top_level);
1668 rlc_um_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo, proto_tree *tree,
1669 proto_tree *top_level, enum rlc_channel_type channel, guint16 seq,
1670 struct rlc_li *li, guint16 num_li, gboolean li_is_on_2_bytes,
1671 struct atm_phdr *atm)
1674 gboolean dissected = FALSE;
1676 tvbuff_t *next_tvb = NULL;
1678 /* perform reassembly now */
1679 for (i = 0; i < num_li; i++) {
1680 if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
1681 /* padding, must be last LI */
1683 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, tvb_captured_length_remaining(tvb, offs), ENC_NA);
1685 offs += tvb_captured_length_remaining(tvb, offs);
1686 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7c)) || (li[i].li == 0x7ffc)) {
1687 /* a new SDU starts here, mark this seq as the first PDU. */
1688 struct rlc_channel ch_lookup;
1689 struct rlc_seqlist * endlist = NULL;
1690 if( -1 != rlc_channel_assign(&ch_lookup, RLC_UM, pinfo, atm ) ){
1691 endlist = get_endlist(pinfo, &ch_lookup, atm);
1692 endlist->list->data = GINT_TO_POINTER((gint)seq);
1693 endlist->fail_packet=0;
1696 } else if (li[i].li == 0x7ffa) {
1697 /* the first data octet in this RLC PDU is the first octet of an RLC SDU
1698 and the second last octet in this RLC PDU is the last octet of the same RLC SDU */
1699 length = tvb_reported_length_remaining(tvb, offs);
1702 if (tree && length) {
1703 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, length, ENC_NA);
1705 if (global_rlc_perform_reassemby) {
1706 add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, length, TRUE, atm);
1707 next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i, atm);
1712 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, 1, ENC_NA);
1716 if (tree && li[i].len) {
1717 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
1719 if (global_rlc_perform_reassemby) {
1720 add_fragment(RLC_UM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE, atm);
1721 next_tvb = get_reassembled_data(RLC_UM, tvb, pinfo, tree, seq, i, atm);
1726 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
1732 /* is there data left? */
1733 if (tvb_reported_length_remaining(tvb, offs) > 0) {
1735 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
1737 if (global_rlc_perform_reassemby) {
1738 /* add remaining data as fragment */
1739 add_fragment(RLC_UM, tvb, pinfo, tree, offs, seq, i, tvb_captured_length_remaining(tvb, offs), FALSE, atm);
1740 if (dissected == FALSE)
1741 col_set_str(pinfo->cinfo, COL_INFO, "[RLC UM Fragment]");
1744 if (dissected == FALSE)
1745 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] SN=%u", seq);
1747 if (channel == RLC_UNKNOWN_CH)
1748 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Data] SN=%u", seq);
1752 rlc_decode_li(enum rlc_mode mode, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1753 struct rlc_li *li, guint8 max_li, gboolean li_on_2_bytes)
1755 guint32 hdr_len, offs = 0, li_offs;
1756 guint8 ext, num_li = 0;
1757 guint16 next_bytes, prev_li = 0;
1758 proto_item *malformed;
1770 case RLC_UNKNOWN_MODE:
1775 /* calculate header length */
1776 ext = tvb_get_guint8(tvb, hdr_len++) & 0x01;
1778 next_bytes = li_on_2_bytes ? tvb_get_ntohs(tvb, hdr_len) : tvb_get_guint8(tvb, hdr_len);
1779 ext = next_bytes & 0x01;
1780 hdr_len += li_on_2_bytes ? 2 : 1;
1782 total_len = tvb_captured_length_remaining(tvb, hdr_len);
1784 /* do actual evaluation of LIs */
1785 ext = tvb_get_guint8(tvb, offs++) & 0x01;
1788 if (li_on_2_bytes) {
1789 next_bytes = tvb_get_ntohs(tvb, offs);
1792 next_bytes = tvb_get_guint8(tvb, offs++);
1794 ext = next_bytes & 0x01;
1795 li[num_li].ext = ext;
1796 li[num_li].li = next_bytes >> 1;
1798 if (li_on_2_bytes) {
1799 switch (li[num_li].li) {
1800 case 0x0000: /* previous segment was the last one */
1801 case 0x7ffb: /* previous PDU contains last segment of SDU (minus last byte) */
1802 case 0x7ffe: /* contains piggybacked STATUS in AM or segment in UM */
1803 case 0x7fff: /* padding */
1806 case 0x7ffa: /* contains exactly one SDU (minus last byte), UM only */
1807 case 0x7ffc: /* start of a new SDU, UM only */
1808 case 0x7ffd: /* contains exactly one SDU, UM only */
1810 if (mode == RLC_UM) {
1815 /* add malformed LI for investigation */
1816 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1817 expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1818 return -1; /* just give up on this */
1820 /* since the LI is an offset (from the end of the header), it
1821 * may not be larger than the total remaining length and no
1822 * LI may be smaller than its preceding one
1824 if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1825 || (li[num_li].li < prev_li)) {
1826 /* add malformed LI for investigation */
1828 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1829 expert_add_info(pinfo, malformed, &ei_rlc_li_incorrect_warn);
1830 return -1; /* just give up on this */
1832 li[num_li].len = li[num_li].li - prev_li;
1833 prev_li = li[num_li].li;
1836 switch (li[num_li].li) {
1837 case 0x00: /* previous segment was the last one */
1838 case 0x7e: /* contains piggybacked STATUS in AM or segment in UM */
1839 case 0x7f: /* padding */
1842 case 0x7c: /* start of a new SDU, UM only */
1843 case 0x7d: /* contains exactly one SDU, UM only */
1845 if (mode == RLC_UM) {
1850 /* add malformed LI for investigation */
1851 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1852 expert_add_info(pinfo, malformed, &ei_rlc_li_reserved);
1853 return -1; /* just give up on this */
1855 /* since the LI is an offset (from the end of the header), it
1856 * may not be larger than the total remaining length and no
1857 * LI may be smaller than its preceding one
1859 li[num_li].len = li[num_li].li - prev_li;
1860 if (((li[num_li].li > total_len) && !global_rlc_headers_expected)
1861 || (li[num_li].li < prev_li)) {
1862 /* add malformed LI for investigation */
1864 malformed = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1865 expert_add_info_format(pinfo, malformed, &ei_rlc_li_incorrect_mal, "Incorrect LI value 0x%x", li[num_li].li);
1866 return -1; /* just give up on this */
1868 prev_li = li[num_li].li;
1871 li[num_li].tree = tree_add_li(mode, &li[num_li], num_li, li_offs, li_on_2_bytes, tvb, tree);
1874 if (num_li >= max_li) {
1875 /* OK, so this is not really a malformed packet, but for now,
1876 * we will treat it as such, so that it is marked in some way */
1877 expert_add_info(pinfo, li[num_li-1].tree, &ei_rlc_li_too_many);
1885 dissect_rlc_um(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
1886 proto_tree *top_level, proto_tree *tree, struct atm_phdr *atm)
1889 struct rlc_li li[MAX_LI];
1895 guint8 next_byte, offs = 0;
1896 gint16 cur_tb, num_li = 0;
1897 gboolean is_truncated, li_is_on_2_bytes;
1898 proto_item *truncated_ti;
1899 gboolean ciphered_according_to_rrc = FALSE;
1900 gboolean ciphered_flag = FALSE;
1901 gboolean deciphered_flag = FALSE;
1902 int ciphered_data_hf;
1905 next_byte = tvb_get_guint8(tvb, offs++);
1906 seq = next_byte >> 1;
1908 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1909 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1912 if (fpinf && rlcinf) {
1913 /* Add "channel" information, very useful for debugging. */
1914 add_channel_info(pinfo, tree, fpinf, rlcinf);
1916 /* show sequence number and extension bit */
1917 proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 0, 7, ENC_BIG_ENDIAN);
1918 proto_tree_add_bits_item(tree, hf_rlc_ext, tvb, 7, 1, ENC_BIG_ENDIAN);
1921 if (!fpinf || !rlcinf) {
1922 proto_tree_add_expert(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0, -1);
1926 cur_tb = fpinf->cur_tb;
1927 ciphered_according_to_rrc = is_ciphered_according_to_rrc(pinfo, fpinf, rlcinf, (guint16)seq);
1928 ciphered_flag = rlcinf->ciphered[cur_tb];
1929 deciphered_flag = rlcinf->deciphered[cur_tb];
1930 if (((ciphered_according_to_rrc || ciphered_flag) && !deciphered_flag) || global_rlc_ciphered) {
1931 if(global_rlc_try_decipher){
1932 rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_UM);
1934 /* Choosing the right field text ("LIs & Data" or just "Data") based on extension bit */
1935 ext = tvb_get_guint8(tvb, 0) & 0x01;
1936 ciphered_data_hf = (ext == 1) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
1937 /* Adding ciphered payload field to tree */
1938 proto_tree_add_item(tree, ciphered_data_hf, tvb, offs, -1, ENC_NA);
1939 proto_tree_add_expert(tree, pinfo, &ei_rlc_ciphered_data, tvb, offs, -1);
1940 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
1945 if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
1946 if (rlcinf->li_size[cur_tb] == RLC_LI_VARIABLE) {
1947 li_is_on_2_bytes = (tvb_reported_length(tvb) > 125) ? TRUE : FALSE;
1949 li_is_on_2_bytes = (rlcinf->li_size[cur_tb] == RLC_LI_15BITS) ? TRUE : FALSE;
1951 } else { /* Override rlcinf configuration with preference. */
1952 li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? TRUE : FALSE;
1957 num_li = rlc_decode_li(RLC_UM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
1958 if (num_li == -1) return; /* something went wrong */
1959 offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
1961 if (global_rlc_headers_expected) {
1962 /* There might not be any data, if only header was logged */
1963 is_truncated = (tvb_captured_length_remaining(tvb, offs) == 0);
1964 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
1967 PROTO_ITEM_SET_GENERATED(truncated_ti);
1968 expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
1971 PROTO_ITEM_SET_HIDDEN(truncated_ti);
1975 /* do not detect duplicates or reassemble, if prefiltering is done */
1976 if (pinfo->num == 0) return;
1977 /* check for duplicates */
1978 if (rlc_is_duplicate(RLC_UM, pinfo, seq, &orig_num, atm) == TRUE) {
1979 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC UM Fragment] [Duplicate] SN=%u", seq);
1980 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, orig_num);
1983 rlc_um_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, li, num_li, li_is_on_2_bytes, atm);
1987 dissect_rlc_status(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint8 offset)
1989 guint8 sufi_type, bits;
1990 guint64 len, sn, wsn, lsn, l;
1991 guint16 value, previous_sn;
1992 gboolean isErrorBurstInd;
1993 gint bit_offset, previous_bit_offset;
1995 proto_tree *sufi_tree, *bitmap_tree, *rlist_tree;
1996 proto_item *sufi_item, *ti;
1997 #define BUFF_SIZE 41
2000 guint8 sufi_start_offset;
2001 gboolean seen_last = FALSE;
2002 guint16 number_of_bitmap_entries = 0;
2004 bit_offset = offset*8 + 4; /* first SUFI type is always 4 bit shifted */
2006 while (!seen_last && tvb_reported_length_remaining(tvb, bit_offset/8) > 0) {
2008 sufi_type = tvb_get_bits8(tvb, bit_offset, 4);
2009 sufi_start_offset = bit_offset/8;
2010 sufi_item = proto_tree_add_item(tree, hf_rlc_sufi, tvb, sufi_start_offset, 0, ENC_NA);
2011 sufi_tree = proto_item_add_subtree(sufi_item, ett_rlc_sufi);
2012 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_type, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2013 proto_item_append_text(sufi_item, " (%s)", val_to_str_const(sufi_type, rlc_sufi_vals, "Unknown"));
2015 switch (sufi_type) {
2016 case RLC_SUFI_NOMORE:
2020 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_lsn, tvb, bit_offset, 12, &lsn, ENC_BIG_ENDIAN);
2021 col_append_fstr(pinfo->cinfo, COL_INFO, " LSN=%u", (guint16)lsn);
2022 proto_item_append_text(sufi_item, " LSN=%u", (guint16)lsn);
2026 case RLC_SUFI_WINDOW:
2027 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_wsn, tvb, bit_offset, 12, &wsn, ENC_BIG_ENDIAN);
2028 col_append_fstr(pinfo->cinfo, COL_INFO, " WSN=%u", (guint16)wsn);
2032 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2033 col_append_fstr(pinfo->cinfo, COL_INFO, " LIST(%u) - ", (guint8)len);
2037 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2038 proto_item_append_text(ti, " (AMD PDU not correctly received)");
2040 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_l, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
2042 proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)",
2043 (unsigned)(sn+l)&0xfff);
2044 col_append_fstr(pinfo->cinfo, COL_INFO, "%u-%u ", (guint16)sn, (unsigned)(sn+l)&0xfff);
2047 col_append_fstr(pinfo->cinfo, COL_INFO, "%u ", (guint16)sn);
2053 expert_add_info(pinfo, tree, &ei_rlc_sufi_len);
2056 case RLC_SUFI_BITMAP:
2057 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2059 len++; /* bitmap is len + 1 */
2060 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2062 proto_tree_add_item(sufi_tree, hf_rlc_sufi_bitmap, tvb, bit_offset/8, (gint)len, ENC_NA);
2063 bitmap_tree = proto_tree_add_subtree(sufi_tree, tvb, bit_offset/8, (gint)len, ett_rlc_bitmap, &ti, "Decoded bitmap:");
2064 col_append_str(pinfo->cinfo, COL_INFO, " BITMAP=(");
2066 buff = (gchar *)wmem_alloc(wmem_packet_scope(), BUFF_SIZE);
2067 for (i=0; i<len; i++) {
2068 bits = tvb_get_bits8(tvb, bit_offset, 8);
2069 for (l=0, j=0; l<8; l++) {
2070 if ((bits << l) & 0x80) {
2071 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%4u,", (unsigned)(sn+(8*i)+l)&0xfff);
2072 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", (unsigned)(sn+(8*i)+l)&0xfff);
2073 number_of_bitmap_entries++;
2075 j += g_snprintf(&buff[j], BUFF_SIZE-j, " ,");
2078 proto_tree_add_string_format(bitmap_tree, hf_rlc_bitmap_string, tvb, bit_offset/8, 1, buff, "%s", buff);
2081 proto_item_append_text(ti, " (%u SNs)", number_of_bitmap_entries);
2082 col_append_str(pinfo->cinfo, COL_INFO, " )");
2084 case RLC_SUFI_RLIST:
2085 previous_bit_offset = bit_offset;
2086 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2088 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_fsn, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2090 proto_item_append_text(sufi_item, " (%u codewords)", (guint16)len);
2092 for (i=0; i<len; i++) {
2093 ti = proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_cw, tvb, bit_offset, 4, &l, ENC_BIG_ENDIAN);
2095 proto_item_append_text(ti, " (Error burst indication)");
2100 if (len && (((cw[len-1] & 0x01) == 0) || (cw[len-1] == 0x01))) {
2101 expert_add_info(pinfo, tree, &ei_rlc_sufi_cw);
2103 rlist_tree = proto_tree_add_subtree(sufi_tree, tvb, previous_bit_offset/8, (bit_offset-previous_bit_offset)/8, ett_rlc_rlist, NULL, "Decoded list:");
2104 proto_tree_add_uint_format_value(rlist_tree, hf_rlc_sequence_number, tvb, (previous_bit_offset+4)/8, 12/8, (guint32)sn, "%u (AMD PDU not correctly received)", (unsigned)sn);
2105 col_append_fstr(pinfo->cinfo, COL_INFO, " RLIST=(%u", (unsigned)sn);
2107 for (i=0, isErrorBurstInd=FALSE, j=0, previous_sn=(guint16)sn, value=0; i<len; i++) {
2108 if (cw[i] == 0x01) {
2109 isErrorBurstInd = TRUE;
2111 value |= (cw[i] >> 1) << j;
2114 if (isErrorBurstInd) {
2115 previous_sn = (previous_sn + value) & 0xfff;
2116 ti = proto_tree_add_uint(rlist_tree, hf_rlc_length, tvb, (previous_bit_offset+16+4*i)/8, 1, value);
2118 proto_item_append_text(ti, " (all consecutive AMD PDUs up to SN %u not correctly received)", previous_sn);
2119 col_append_fstr(pinfo->cinfo, COL_INFO, " ->%u", previous_sn);
2121 isErrorBurstInd = FALSE;
2123 value = (value + previous_sn) & 0xfff;
2124 proto_tree_add_uint_format_value(rlist_tree, hf_rlc_sequence_number, tvb, (previous_bit_offset+16+4*i)/8, 1, value, "%u (AMD PDU not correctly received)",value);
2125 col_append_fstr(pinfo->cinfo, COL_INFO, " %u", value);
2126 previous_sn = value;
2132 col_append_str(pinfo->cinfo, COL_INFO, ")");
2135 case RLC_SUFI_MRW_ACK:
2136 col_append_str(pinfo->cinfo, COL_INFO, " MRW-ACK");
2137 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2139 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_ack, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2141 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
2144 col_append_str(pinfo->cinfo, COL_INFO, " MRW");
2145 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_len, tvb, bit_offset, 4, &len, ENC_BIG_ENDIAN);
2149 proto_tree_add_bits_ret_val(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, &sn, ENC_BIG_ENDIAN);
2150 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u", (guint16)sn);
2155 /* only one SN_MRW field is present */
2156 ti = proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_sn_mrw, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2157 proto_item_append_text(ti, " (RLC SDU to be discarded in the Receiver extends above the configured transmission window in the Sender)");
2160 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_n, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
2164 proto_tree_add_bits_item(sufi_tree, hf_rlc_sufi_poll_sn, tvb, bit_offset, 12, ENC_BIG_ENDIAN);
2169 expert_add_info(pinfo, tree, &ei_rlc_sufi_type);
2170 return; /* invalid value, ignore the rest */
2173 /* Set extent of SUFI root */
2174 proto_item_set_len(sufi_item, ((bit_offset+7)/8) - sufi_start_offset);
2179 dissect_rlc_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2181 guint8 type, next_byte;
2186 next_byte = tvb_get_guint8(tvb, 0);
2187 type = (next_byte >> 4) & 0x07;
2189 ti = proto_tree_add_bits_item(tree, hf_rlc_ctrl_type, tvb, 1, 3, ENC_BIG_ENDIAN);
2192 dissect_rlc_status(tvb, pinfo, tree, 0);
2196 col_append_str(pinfo->cinfo, COL_INFO, (type == RLC_RESET) ? " RESET" : " RESET-ACK");
2197 proto_tree_add_bits_ret_val(tree, hf_rlc_rsn, tvb, 4, 1, &rsn, ENC_BIG_ENDIAN);
2198 proto_tree_add_bits_ret_val(tree, hf_rlc_r1, tvb, 5, 3, &r1, ENC_BIG_ENDIAN);
2200 expert_add_info(pinfo, ti, &ei_rlc_reserved_bits_not_zero);
2203 proto_tree_add_bits_ret_val(tree, hf_rlc_hfni, tvb, 8, 20, &hfn, ENC_BIG_ENDIAN);
2204 col_append_fstr(pinfo->cinfo, COL_INFO, " RSN=%u HFN=%u", (guint16)rsn, (guint32)hfn);
2207 expert_add_info_format(pinfo, ti, &ei_rlc_ctrl_type, "Invalid RLC AM control type %u", type);
2208 return; /* invalid */
2213 rlc_am_reassemble(tvbuff_t *tvb, guint8 offs, packet_info *pinfo,
2214 proto_tree *tree, proto_tree *top_level,
2215 enum rlc_channel_type channel, guint16 seq, gboolean poll_set, struct rlc_li *li,
2216 guint16 num_li, gboolean final, gboolean li_is_on_2_bytes,
2217 struct atm_phdr *atm)
2220 gboolean piggyback = FALSE, dissected = FALSE;
2221 tvbuff_t *next_tvb = NULL;
2223 struct rlc_channel ch_lookup;
2224 struct rlc_seqlist * endlist = NULL;
2225 if( 0 == seq ){ /* assuming that a new RRC Connection is established when 0==seq. */
2226 if( -1 != rlc_channel_assign(&ch_lookup, RLC_AM, pinfo, atm ) ){
2227 endlist = get_endlist(pinfo, &ch_lookup, atm);
2228 endlist->list->data = GINT_TO_POINTER( -1);
2232 /* perform reassembly now */
2233 for (i = 0; i < num_li; i++) {
2234 if ((!li_is_on_2_bytes && (li[i].li == 0x7e)) || (li[i].li == 0x7ffe)) {
2235 /* piggybacked status */
2237 } else if ((!li_is_on_2_bytes && (li[i].li == 0x7f)) || (li[i].li == 0x7fff)) {
2238 /* padding, must be last LI */
2239 if (tvb_reported_length_remaining(tvb, offs) > 0) {
2241 proto_tree_add_item(tree, hf_rlc_pad, tvb, offs, -1, ENC_NA);
2244 /* Insert empty RLC frag so RLC doesn't miss this seq number. */
2245 add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, 0, TRUE, atm);
2248 offs += tvb_captured_length_remaining(tvb, offs);
2251 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, li[i].len, ENC_NA);
2253 if (global_rlc_perform_reassemby) {
2254 add_fragment(RLC_AM, tvb, pinfo, li[i].tree, offs, seq, i, li[i].len, TRUE, atm);
2255 next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i, atm);
2260 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2267 dissect_rlc_status(tvb, pinfo, tree, offs);
2269 if (tvb_reported_length_remaining(tvb, offs) > 0) {
2270 /* we have remaining data, which we need to mark in the tree */
2272 proto_tree_add_item(tree, hf_rlc_data, tvb, offs, -1, ENC_NA);
2274 if (global_rlc_perform_reassemby) {
2275 add_fragment(RLC_AM, tvb, pinfo, tree, offs, seq, i,
2276 tvb_captured_length_remaining(tvb,offs), final, atm);
2278 next_tvb = get_reassembled_data(RLC_AM, tvb, pinfo, tree, seq, i, atm);
2284 rlc_call_subdissector(channel, next_tvb, pinfo, top_level);
2288 if (dissected == FALSE)
2289 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] SN=%u %s",
2290 seq, poll_set ? "(P)" : "");
2292 if (channel == RLC_UNKNOWN_CH)
2293 col_append_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Data] SN=%u %s",
2294 seq, poll_set ? "(P)" : "");
2298 dissect_rlc_am(enum rlc_channel_type channel, tvbuff_t *tvb, packet_info *pinfo,
2299 proto_tree *top_level, proto_tree *tree, struct atm_phdr *atm)
2302 struct rlc_li li[MAX_LI];
2306 guint8 next_byte, offs = 0;
2307 guint32 orig_num = 0;
2311 gboolean is_truncated, li_is_on_2_bytes;
2312 proto_item *truncated_ti, *ti;
2314 gboolean ciphered_according_to_rrc = FALSE;
2315 gboolean ciphered_flag = FALSE;
2316 gboolean deciphered_flag = FALSE;
2317 int ciphered_data_hf;
2319 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2320 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2322 next_byte = tvb_get_guint8(tvb, offs++);
2323 dc = next_byte >> 7;
2325 if (fpinf && rlcinf) {
2326 /* Add "channel" information, very useful for debugging. */
2327 add_channel_info(pinfo, tree, fpinf, rlcinf);
2329 proto_tree_add_bits_item(tree, hf_rlc_dc, tvb, 0, 1, ENC_BIG_ENDIAN);
2332 col_set_str(pinfo->cinfo, COL_INFO, "[RLC Control Frame]");
2333 dissect_rlc_control(tvb, pinfo, tree);
2337 seq = next_byte & 0x7f;
2339 next_byte = tvb_get_guint8(tvb, offs++);
2340 seq |= (next_byte >> 3);
2342 ext = next_byte & 0x03;
2343 /* show header fields */
2344 proto_tree_add_bits_item(tree, hf_rlc_seq, tvb, 1, 12, ENC_BIG_ENDIAN);
2345 proto_tree_add_bits_ret_val(tree, hf_rlc_p, tvb, 13, 1, &polling, ENC_BIG_ENDIAN);
2346 ti = proto_tree_add_bits_item(tree, hf_rlc_he, tvb, 14, 2, ENC_BIG_ENDIAN);
2348 /* header extension may only be 00, 01 or 10 */
2350 expert_add_info(pinfo, ti, &ei_rlc_he);
2354 if (!fpinf || !rlcinf) {
2355 proto_tree_add_expert(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0, -1);
2359 cur_tb = fpinf->cur_tb;
2361 * WARNING DECIPHERING IS HIGHLY EXPERIMENTAL!!!
2363 ciphered_according_to_rrc = is_ciphered_according_to_rrc(pinfo, fpinf, rlcinf, (guint16)seq);
2364 ciphered_flag = rlcinf->ciphered[cur_tb];
2365 deciphered_flag = rlcinf->deciphered[cur_tb];
2366 if (((ciphered_according_to_rrc || ciphered_flag) && !deciphered_flag) || global_rlc_ciphered) {
2367 if(global_rlc_try_decipher){
2368 rlc_decipher(tvb, pinfo, tree, fpinf, rlcinf, seq, RLC_AM);
2370 /* Choosing the right field text ("LIs & Data" or just "Data") based on header extension field */
2371 ciphered_data_hf = (ext == 0x01) ? hf_rlc_ciphered_lis_data : hf_rlc_ciphered_data;
2372 /* Adding ciphered payload field to tree */
2373 proto_tree_add_item(tree, ciphered_data_hf, tvb, offs, -1, ENC_NA);
2374 proto_tree_add_expert(tree, pinfo, &ei_rlc_ciphered_data, tvb, offs, -1);
2375 col_append_str(pinfo->cinfo, COL_INFO, "[Ciphered Data]");
2380 if (global_rlc_li_size == RLC_LI_UPPERLAYER) {
2381 if (rlcinf->li_size[cur_tb] == RLC_LI_VARIABLE) {
2382 li_is_on_2_bytes = (tvb_reported_length(tvb) > 126) ? TRUE : FALSE;
2384 li_is_on_2_bytes = (rlcinf->li_size[cur_tb] == RLC_LI_15BITS) ? TRUE : FALSE;
2386 } else { /* Override rlcinf configuration with preference. */
2387 li_is_on_2_bytes = (global_rlc_li_size == RLC_LI_15BITS) ? TRUE : FALSE;
2390 num_li = rlc_decode_li(RLC_AM, tvb, pinfo, tree, li, MAX_LI, li_is_on_2_bytes);
2391 if (num_li == -1) return; /* something went wrong */
2392 offs += ((li_is_on_2_bytes) ? 2 : 1) * num_li;
2393 if (global_rlc_headers_expected) {
2394 /* There might not be any data, if only header was logged */
2395 is_truncated = (tvb_captured_length_remaining(tvb, offs) == 0);
2396 truncated_ti = proto_tree_add_boolean(tree, hf_rlc_header_only, tvb, 0, 0,
2399 PROTO_ITEM_SET_GENERATED(truncated_ti);
2400 expert_add_info(pinfo, truncated_ti, &ei_rlc_header_only);
2403 PROTO_ITEM_SET_HIDDEN(truncated_ti);
2407 /* do not detect duplicates or reassemble, if prefiltering is done */
2408 if (pinfo->num == 0) return;
2409 /* check for duplicates, but not if already visited */
2410 if (pinfo->fd->flags.visited == FALSE && rlc_is_duplicate(RLC_AM, pinfo, seq, &orig_num, atm) == TRUE) {
2411 g_hash_table_insert(duplicate_table, GUINT_TO_POINTER(pinfo->num), GUINT_TO_POINTER(orig_num));
2413 } else if (pinfo->fd->flags.visited == TRUE && tree) {
2414 gpointer value = g_hash_table_lookup(duplicate_table, GUINT_TO_POINTER(pinfo->num));
2415 if (value != NULL) {
2416 col_add_fstr(pinfo->cinfo, COL_INFO, "[RLC AM Fragment] [Duplicate] SN=%u %s", seq, (polling != 0) ? "(P)" : "");
2417 proto_tree_add_uint(tree, hf_rlc_duplicate_of, tvb, 0, 0, GPOINTER_TO_UINT(value));
2422 rlc_am_reassemble(tvb, offs, pinfo, tree, top_level, channel, seq, polling != 0,
2423 li, num_li, ext == 2, li_is_on_2_bytes, atm);
2426 /* dissect entry functions */
2428 dissect_rlc_pcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2430 proto_tree *subtree = NULL;
2432 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2433 col_clear(pinfo->cinfo, COL_INFO);
2435 /* PCCH is always RLC TM */
2438 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2439 subtree = proto_item_add_subtree(ti, ett_rlc);
2440 proto_item_append_text(ti, " TM (PCCH)");
2442 dissect_rlc_tm(RLC_PCCH, tvb, pinfo, tree, subtree);
2443 return tvb_captured_length(tvb);
2447 dissect_rlc_bcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2450 proto_item *ti = NULL;
2451 proto_tree *subtree = NULL;
2453 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2454 col_clear(pinfo->cinfo, COL_INFO);
2456 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2457 if (!fpi) return 0; /* dissection failure */
2460 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2461 subtree = proto_item_add_subtree(ti, ett_rlc);
2463 proto_item_append_text(ti, " TM (BCCH)");
2464 dissect_rlc_tm(RLC_BCCH, tvb, pinfo, tree, subtree);
2465 return tvb_captured_length(tvb);
2469 dissect_rlc_ccch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2472 proto_item *ti = NULL;
2473 proto_tree *subtree = NULL;
2474 struct atm_phdr *atm = (struct atm_phdr *)data;
2476 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2477 col_clear(pinfo->cinfo, COL_INFO);
2479 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2480 if (!fpi) return 0; /* dissection failure */
2483 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2484 subtree = proto_item_add_subtree(ti, ett_rlc);
2487 if (fpi->is_uplink) {
2488 /* UL CCCH is always RLC TM */
2489 proto_item_append_text(ti, " TM (CCCH)");
2490 dissect_rlc_tm(RLC_UL_CCCH, tvb, pinfo, tree, subtree);
2492 /* DL CCCH is always UM */
2493 proto_item_append_text(ti, " UM (CCCH)");
2494 dissect_rlc_um(RLC_DL_CCCH, tvb, pinfo, tree, subtree, atm);
2496 return tvb_captured_length(tvb);
2500 dissect_rlc_ctch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2503 proto_item *ti = NULL;
2504 proto_tree *subtree = NULL;
2505 struct atm_phdr *atm = (struct atm_phdr *)data;
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 if (!fpi) return 0; /* dissection failure */
2514 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2515 subtree = proto_item_add_subtree(ti, ett_rlc);
2518 /* CTCH is always UM */
2519 proto_item_append_text(ti, " UM (CTCH)");
2520 dissect_rlc_um(RLC_DL_CTCH, tvb, pinfo, tree, subtree, atm);
2521 return tvb_captured_length(tvb);
2525 dissect_rlc_dcch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2527 proto_item *ti = NULL;
2528 proto_tree *subtree = NULL;
2531 enum rlc_channel_type channel;
2532 struct atm_phdr *atm = (struct atm_phdr *)data;
2534 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2535 col_clear(pinfo->cinfo, COL_INFO);
2537 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2538 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2541 proto_tree_add_expert(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0, -1);
2546 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2547 subtree = proto_item_add_subtree(ti, ett_rlc);
2550 channel = fpi->is_uplink ? RLC_UL_DCCH : RLC_DL_DCCH;
2552 switch (rlci->mode[fpi->cur_tb]) {
2554 proto_item_append_text(ti, " UM (DCCH)");
2555 dissect_rlc_um(channel, tvb, pinfo, tree, subtree, atm);
2558 proto_item_append_text(ti, " AM (DCCH)");
2559 dissect_rlc_am(channel, tvb, pinfo, tree, subtree, atm);
2562 return tvb_captured_length(tvb);
2566 dissect_rlc_ps_dtch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2568 proto_item *ti = NULL;
2569 proto_tree *subtree = NULL;
2572 struct atm_phdr *atm = (struct atm_phdr *)data;
2574 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2575 col_clear(pinfo->cinfo, COL_INFO);
2577 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2578 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2580 if (!fpi || !rlci) {
2581 proto_tree_add_expert(tree, pinfo, &ei_rlc_no_per_frame_data, tvb, 0, -1);
2586 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2587 subtree = proto_item_add_subtree(ti, ett_rlc);
2590 switch (rlci->mode[fpi->cur_tb]) {
2592 proto_item_append_text(ti, " UM (PS DTCH)");
2593 dissect_rlc_um(RLC_PS_DTCH, tvb, pinfo, tree, subtree, atm);
2596 proto_item_append_text(ti, " AM (PS DTCH)");
2597 dissect_rlc_am(RLC_PS_DTCH, tvb, pinfo, tree, subtree, atm);
2600 proto_item_append_text(ti, " TM (PS DTCH)");
2601 dissect_rlc_tm(RLC_PS_DTCH, tvb, pinfo, tree, subtree);
2604 return tvb_captured_length(tvb);
2608 dissect_rlc_dch_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2610 proto_item *ti = NULL;
2611 proto_tree *subtree = NULL;
2614 struct atm_phdr *atm = (struct atm_phdr *)data;
2616 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2617 col_clear(pinfo->cinfo, COL_INFO);
2619 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2620 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2622 if (!fpi || !rlci) return 0;
2625 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2626 subtree = proto_item_add_subtree(ti, ett_rlc);
2629 switch (rlci->mode[fpi->cur_tb]) {
2631 proto_item_append_text(ti, " UM (Unknown)");
2632 dissect_rlc_um(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree, atm);
2635 proto_item_append_text(ti, " AM (Unknown)");
2636 dissect_rlc_am(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree, atm);
2639 proto_item_append_text(ti, " TM (Unknown)");
2640 dissect_rlc_tm(RLC_UNKNOWN_CH, tvb, pinfo, tree, subtree);
2643 return tvb_captured_length(tvb);
2647 report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
2648 tvbuff_t *tvb, gint start, gint length)
2651 proto_tree *subtree;
2653 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2654 col_clear(pinfo->cinfo, COL_INFO);
2655 ti = proto_tree_add_item(tree, proto_umts_rlc, tvb, 0, -1, ENC_NA);
2656 subtree = proto_item_add_subtree(ti, ett_rlc);
2657 proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
2660 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
2662 dissect_rlc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2669 guint channelType = UMTS_CHANNEL_TYPE_UNSPECIFIED;
2670 gboolean fpInfoAlreadySet = FALSE;
2671 gboolean rlcInfoAlreadySet = FALSE;
2672 gboolean channelTypePresent = FALSE;
2673 gboolean rlcModePresent = FALSE;
2674 proto_item *ti = NULL;
2675 proto_tree *subtree = NULL;
2676 struct atm_phdr *atm = (struct atm_phdr *)data;
2678 /* Do this again on re-dissection to re-discover offset of actual PDU */
2680 /* Needs to be at least as long as:
2681 - the signature string
2682 - conditional header bytes
2684 - at least one byte of RLC PDU payload */
2685 if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(RLC_START_STRING)+2+2)) {
2689 /* OK, compare with signature string */
2690 if (tvb_strneql(tvb, offset, RLC_START_STRING, (gint)strlen(RLC_START_STRING)) != 0) {
2693 offset += (gint)strlen(RLC_START_STRING);
2695 /* If redissecting, use previous info struct (if available) */
2696 fpi = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
2698 /* Allocate new info struct for this frame */
2699 fpi = (fp_info *)wmem_alloc0(wmem_file_scope(), sizeof(fp_info));
2701 fpInfoAlreadySet = TRUE;
2703 rlci = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
2705 /* Allocate new info struct for this frame */
2706 rlci = (rlc_info *)wmem_alloc0(wmem_file_scope(), sizeof(rlc_info));
2708 rlcInfoAlreadySet = TRUE;
2711 /* Setting non-zero UE-ID for RLC reassembly to work, might be
2712 * overriden if the optional URNTI tag is present */
2713 rlci->ueid[fpi->cur_tb] = 1;
2715 /* Read conditional/optional fields */
2716 while (tag != RLC_PAYLOAD_TAG) {
2717 /* Process next tag */
2718 tag = tvb_get_guint8(tvb, offset++);
2720 case RLC_CHANNEL_TYPE_TAG:
2721 channelType = tvb_get_guint8(tvb, offset);
2723 channelTypePresent = TRUE;
2726 rlci->mode[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
2728 rlcModePresent = TRUE;
2730 case RLC_DIRECTION_TAG:
2731 if (tvb_get_guint8(tvb, offset) == DIRECTION_UPLINK) {
2732 fpi->is_uplink = TRUE;
2733 pinfo->link_dir = P2P_DIR_UL;
2735 fpi->is_uplink = FALSE;
2736 pinfo->link_dir = P2P_DIR_DL;
2741 rlci->ueid[fpi->cur_tb] = tvb_get_ntohl(tvb, offset);
2744 case RLC_RADIO_BEARER_ID_TAG:
2745 rlci->rbid[fpi->cur_tb] = tvb_get_guint8(tvb, offset);
2748 case RLC_LI_SIZE_TAG:
2749 rlci->li_size[fpi->cur_tb] = (enum rlc_li_size) tvb_get_guint8(tvb, offset);
2752 case RLC_PAYLOAD_TAG:
2753 /* Have reached data, so get out of loop */
2756 /* It must be a recognised tag */
2757 report_heur_error(tree, pinfo, &ei_rlc_unknown_udp_framing_tag, tvb, offset-1, 1);
2762 if ((channelTypePresent == FALSE) && (rlcModePresent == FALSE)) {
2763 /* Conditional fields are missing */
2764 report_heur_error(tree, pinfo, &ei_rlc_missing_udp_framing_tag, tvb, 0, offset);
2768 /* Store info in packet if needed */
2769 if (!fpInfoAlreadySet) {
2770 p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, fpi);
2772 if (!rlcInfoAlreadySet) {
2773 p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlci);
2776 /**************************************/
2777 /* OK, now dissect as RLC */
2779 /* Create tvb that starts at actual RLC PDU */
2780 rlc_tvb = tvb_new_subset_remaining(tvb, offset);
2781 switch (channelType) {
2782 case UMTS_CHANNEL_TYPE_UNSPECIFIED:
2783 /* Call relevant dissector according to RLC mode */
2784 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC");
2785 col_clear(pinfo->cinfo, COL_INFO);
2788 ti = proto_tree_add_item(tree, proto_umts_rlc, rlc_tvb, 0, -1, ENC_NA);
2789 subtree = proto_item_add_subtree(ti, ett_rlc);
2792 if (rlci->mode[fpi->cur_tb] == RLC_AM) {
2793 proto_item_append_text(ti, " AM");
2794 dissect_rlc_am(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree, atm);
2795 } else if (rlci->mode[fpi->cur_tb] == RLC_UM) {
2796 proto_item_append_text(ti, " UM");
2797 dissect_rlc_um(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree, atm);
2799 proto_item_append_text(ti, " TM");
2800 dissect_rlc_tm(RLC_UNKNOWN_CH, rlc_tvb, pinfo, tree, subtree);
2803 case UMTS_CHANNEL_TYPE_PCCH:
2804 dissect_rlc_pcch(rlc_tvb, pinfo, tree, data);
2806 case UMTS_CHANNEL_TYPE_CCCH:
2807 dissect_rlc_ccch(rlc_tvb, pinfo, tree, data);
2809 case UMTS_CHANNEL_TYPE_DCCH:
2810 dissect_rlc_dcch(rlc_tvb, pinfo, tree, data);
2812 case UMTS_CHANNEL_TYPE_PS_DTCH:
2813 dissect_rlc_ps_dtch(rlc_tvb, pinfo, tree, data);
2815 case UMTS_CHANNEL_TYPE_CTCH:
2816 dissect_rlc_ctch(rlc_tvb, pinfo, tree, data);
2818 case UMTS_CHANNEL_TYPE_BCCH:
2819 dissect_rlc_bcch(rlc_tvb, pinfo, tree, data);
2822 /* Unknown channel type */
2830 proto_register_rlc(void)
2832 module_t *rlc_module;
2833 expert_module_t* expert_rlc;
2834 static hf_register_info hf[] = {
2836 { "D/C Bit", "rlc.dc",
2837 FT_BOOLEAN, BASE_NONE, TFS(&rlc_dc_val), 0, NULL, HFILL }
2839 { &hf_rlc_ctrl_type,
2840 { "Control PDU Type", "rlc.ctrl_pdu_type",
2841 FT_UINT8, BASE_DEC, VALS(rlc_ctrl_vals), 0, "PDU Type", HFILL }
2844 { "Reserved 1", "rlc.r1",
2845 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2848 { "Reset Sequence Number", "rlc.rsn",
2849 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2852 { "Hyper Frame Number Indicator", "rlc.hfni",
2853 FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL }
2856 { "Sequence Number", "rlc.seq",
2857 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2860 { "Extension Bit", "rlc.ext",
2861 FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2864 { "Header Extension Type", "rlc.he",
2865 FT_UINT8, BASE_DEC, VALS(rlc_he_vals), 0, NULL, HFILL }
2868 { "Polling Bit", "rlc.p",
2869 FT_BOOLEAN, BASE_NONE, TFS(&rlc_p_val), 0, NULL, HFILL }
2872 { "Padding", "rlc.padding",
2873 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2876 { "Reassembled Fragments", "rlc.fragments",
2877 FT_NONE, BASE_NONE, NULL, 0, "Fragments", HFILL }
2880 { "RLC Fragment", "rlc.fragment",
2881 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2883 { &hf_rlc_duplicate_of,
2884 { "Duplicate of", "rlc.duplicate_of",
2885 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2887 { &hf_rlc_reassembled_in,
2888 { "Reassembled Message in frame", "rlc.reassembled_in",
2889 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
2892 { "Data", "rlc.data",
2893 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2895 { &hf_rlc_ciphered_data,
2896 { "Ciphered Data", "rlc.ciphered_data",
2897 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2899 { &hf_rlc_ciphered_lis_data,
2900 { "Ciphered LIs & Data", "rlc.ciphered_data",
2901 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2903 /* LI information */
2906 FT_NONE, BASE_NONE, NULL, 0, "Length Indicator", HFILL }
2909 { "LI value", "rlc.li.value",
2910 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2913 { "LI extension bit", "rlc.li.ext",
2914 FT_BOOLEAN, BASE_NONE, TFS(&rlc_ext_val), 0, NULL, HFILL }
2917 { "LI Data", "rlc.li.data",
2918 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2920 /* SUFI information */
2922 { "SUFI", "rlc.sufi",
2923 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2925 { &hf_rlc_sufi_type,
2926 { "SUFI Type", "rlc.sufi.type",
2927 FT_UINT8, BASE_DEC, VALS(rlc_sufi_vals), 0, NULL, HFILL }
2930 { "Last Sequence Number", "rlc.sufi.lsn",
2931 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2934 { "Window Size Number", "rlc.sufi.wsn",
2935 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2938 { "Sequence Number", "rlc.sufi.sn",
2939 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2942 { "Length", "rlc.sufi.l",
2943 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2946 { "Length", "rlc.sufi.len",
2947 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2950 { "First Sequence Number", "rlc.sufi.fsn",
2951 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2953 { &hf_rlc_sufi_bitmap,
2954 { "Bitmap", "rlc.sufi.bitmap",
2955 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }
2958 { "Codeword", "rlc.sufi.cw",
2959 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2962 { "Nlength", "rlc.sufi.n",
2963 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2965 { &hf_rlc_sufi_sn_ack,
2966 { "SN ACK", "rlc.sufi.sn_ack",
2967 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2969 { &hf_rlc_sufi_sn_mrw,
2970 { "SN MRW", "rlc.sufi.sn_mrw",
2971 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2973 { &hf_rlc_sufi_poll_sn,
2974 { "Poll SN", "rlc.sufi.poll_sn",
2975 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }
2977 /* Other information */
2978 { &hf_rlc_header_only,
2979 { "RLC PDU header only", "rlc.header_only",
2980 FT_BOOLEAN, BASE_NONE, TFS(&rlc_header_only_val), 0 ,NULL, HFILL }
2983 { "Channel", "rlc.channel",
2984 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }
2986 { &hf_rlc_channel_rbid,
2987 { "Radio Bearer ID", "rlc.channel.rbid",
2988 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }
2990 { &hf_rlc_channel_dir,
2991 { "Direction", "rlc.channel.dir",
2992 FT_UINT8, BASE_DEC, VALS(rlc_dir_vals), 0, NULL, HFILL }
2994 { &hf_rlc_channel_ueid,
2995 { "User Equipment ID", "rlc.channel.ueid",
2996 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }
2998 { &hf_rlc_sequence_number,
2999 { "Sequence Number", "rlc.sequence_number",
3000 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
3003 { "Length", "rlc.length",
3004 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }
3006 { &hf_rlc_bitmap_string,
3007 { "Bitmap string", "rlc.bitmap_string",
3008 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
3012 static gint *ett[] = {
3022 static ei_register_info ei[] = {
3023 { &ei_rlc_reassembly_fail_unfinished_sequence, { "rlc.reassembly.fail.unfinished_sequence", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because of previous unfinished sequence.", EXPFILL }},
3024 { &ei_rlc_reassembly_fail_flag_set, { "rlc.reassembly.fail.flag_set", PI_REASSEMBLE, PI_ERROR, "Did not perform reassembly because fail flag was set previously.", EXPFILL }},
3025 { &ei_rlc_reassembly_lingering_endpoint, { "rlc.lingering_endpoint", PI_REASSEMBLE, PI_ERROR, "Lingering endpoint.", EXPFILL }},
3026 { &ei_rlc_reassembly_unknown_error, { "rlc.reassembly.unknown_error", PI_REASSEMBLE, PI_ERROR, "Unknown error.", EXPFILL }},
3027 { &ei_rlc_kasumi_implementation_missing, { "rlc.kasumi_implementation_missing", PI_UNDECODED, PI_WARN, "Unable to decipher packet since KASUMI implementation is missing.", EXPFILL }},
3028 { &ei_rlc_li_reserved, { "rlc.li.reserved", PI_PROTOCOL, PI_WARN, "Uses reserved LI", EXPFILL }},
3029 { &ei_rlc_li_incorrect_warn, { "rlc.li.incorrect", PI_PROTOCOL, PI_WARN, "Incorrect LI value", EXPFILL }},
3030 { &ei_rlc_li_incorrect_mal, { "rlc.li.incorrect", PI_MALFORMED, PI_ERROR, "Incorrect LI value 0x%x", EXPFILL }},
3031 { &ei_rlc_li_too_many, { "rlc.li.too_many", PI_MALFORMED, PI_ERROR, "Too many LI entries", EXPFILL }},
3032 { &ei_rlc_header_only, { "rlc.header_only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
3033 { &ei_rlc_sufi_len, { "rlc.sufi.len.invalid", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
3034 { &ei_rlc_sufi_cw, { "rlc.sufi.cw.invalid", PI_PROTOCOL, PI_WARN, "Invalid last codeword", EXPFILL }},
3035 { &ei_rlc_sufi_type, { "rlc.sufi.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid SUFI type", EXPFILL }},
3036 { &ei_rlc_reserved_bits_not_zero, { "rlc.reserved_bits_not_zero", PI_PROTOCOL, PI_WARN, "reserved bits not zero", EXPFILL }},
3037 { &ei_rlc_ctrl_type, { "rlc.ctrl_pdu_type.invalid", PI_PROTOCOL, PI_WARN, "Invalid RLC AM control type", EXPFILL }},
3038 { &ei_rlc_he, { "rlc.he.invalid", PI_PROTOCOL, PI_WARN, "Incorrect HE value", EXPFILL }},
3039 { &ei_rlc_ciphered_data, { "rlc.ciphered_data", PI_UNDECODED, PI_WARN, "Cannot dissect RLC frame because it is ciphered", EXPFILL }},
3040 { &ei_rlc_no_per_frame_data, { "rlc.no_per_frame_data", PI_PROTOCOL, PI_WARN, "Can't dissect RLC frame because no per-frame info was attached!", EXPFILL }},
3041 { &ei_rlc_incomplete_sequence, { "rlc.incomplete_sequence", PI_MALFORMED, PI_ERROR, "Error: Incomplete sequence", EXPFILL }},
3042 { &ei_rlc_unknown_udp_framing_tag, { "rlc.unknown_udp_framing_tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3043 { &ei_rlc_missing_udp_framing_tag, { "rlc.missing_udp_framing_tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3046 proto_umts_rlc = proto_register_protocol("Radio Link Control", "RLC", "rlc");
3047 register_dissector("rlc.bcch", dissect_rlc_bcch, proto_umts_rlc);
3048 register_dissector("rlc.pcch", dissect_rlc_pcch, proto_umts_rlc);
3049 register_dissector("rlc.ccch", dissect_rlc_ccch, proto_umts_rlc);
3050 register_dissector("rlc.ctch", dissect_rlc_ctch, proto_umts_rlc);
3051 register_dissector("rlc.dcch", dissect_rlc_dcch, proto_umts_rlc);
3052 register_dissector("rlc.ps_dtch", dissect_rlc_ps_dtch, proto_umts_rlc);
3053 register_dissector("rlc.dch_unknown", dissect_rlc_dch_unknown, proto_umts_rlc);
3055 proto_register_field_array(proto_umts_rlc, hf, array_length(hf));
3056 proto_register_subtree_array(ett, array_length(ett));
3057 expert_rlc = expert_register_protocol(proto_umts_rlc);
3058 expert_register_field_array(expert_rlc, ei, array_length(ei));
3061 rlc_module = prefs_register_protocol(proto_umts_rlc, NULL);
3063 prefs_register_obsolete_preference(rlc_module, "heuristic_rlc_over_udp");
3065 prefs_register_bool_preference(rlc_module, "perform_reassembly",
3066 "Try to reassemble SDUs",
3067 "When enabled, try to reassemble SDUs from the various PDUs received",
3068 &global_rlc_perform_reassemby);
3070 prefs_register_bool_preference(rlc_module, "header_only_mode",
3071 "May see RLC headers only",
3072 "When enabled, if data is not present, don't report as an error, but instead "
3073 "add expert info to indicate that headers were omitted",
3074 &global_rlc_headers_expected);
3076 prefs_register_bool_preference(rlc_module, "ignore_rrc_cipher_indication",
3077 "Ignore ciphering indication from higher layers",
3078 "When enabled, RLC will ignore sequence numbers reported in 'Security Mode Command'/'Security Mode Complete' (RRC) messages when checking if frames are ciphered",
3079 &global_ignore_rrc_ciphering_indication);
3081 prefs_register_bool_preference(rlc_module, "ciphered_data",
3082 "All data is ciphered",
3083 "When enabled, RLC will assume all payloads in RLC frames are ciphered",
3084 &global_rlc_ciphered);
3086 #ifdef HAVE_UMTS_KASUMI
3087 prefs_register_bool_preference(rlc_module, "try_decipher",
3088 "Try to decipher data",
3089 "When enabled, RLC will try to decipher data. (Experimental)",
3090 &global_rlc_try_decipher);
3092 prefs_register_string_preference(rlc_module, "kasumi_key",
3093 "KASUMI key", "Key for kasumi 32 characters long hex-string", &global_rlc_kasumi_key);
3095 /* If Wireshark isn't compiled with KASUMI we still want to register the above preferences
3096 * We are doing so for two reasons:
3097 * 1. To inform the user about the disabled preferences (using static text preference)
3098 * 2. To prevent errors when Wireshark reads a preferences file which includes records for these preferences
3100 prefs_register_static_text_preference(rlc_module, "try_decipher",
3101 "Data deciphering is disabled", "Wireshark was compiled without the KASUMI decryption algorithm");
3103 prefs_register_obsolete_preference(rlc_module, "kasumi_key");
3104 #endif /* HAVE_UMTS_KASUMI */
3106 prefs_register_enum_preference(rlc_module, "li_size",
3108 "LI size in bits, either 7 or 15 bit",
3109 &global_rlc_li_size, li_size_enumvals, FALSE);
3111 register_init_routine(fragment_table_init);
3112 register_cleanup_routine(fragment_table_cleanup);
3116 proto_reg_handoff_rlc(void)
3118 rrc_handle = find_dissector_add_dependency("rrc", proto_umts_rlc);
3119 ip_handle = find_dissector_add_dependency("ip", proto_umts_rlc);
3120 bmc_handle = find_dissector_add_dependency("bmc", proto_umts_rlc);
3121 /* Add as a heuristic UDP dissector */
3122 heur_dissector_add("udp", dissect_rlc_heur, "RLC over UDP", "rlc_udp", proto_umts_rlc, HEURISTIC_DISABLE);
3131 * indent-tabs-mode: nil
3134 * ex: set shiftwidth=4 tabstop=8 expandtab:
3135 * :indentSize=4:tabSize=8:noTabs=true: