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