epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-umts_mac.c
blob76150332366da3fe264c7d62cca12c5a3e2de565
1 /* packet-umts_mac.c
2 * Routines for UMTS MAC (3GPP TS 25.321) disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
13 #include <epan/packet.h>
14 #include <epan/conversation.h>
15 #include <epan/expert.h>
16 #include <epan/prefs.h>
17 #include <epan/proto_data.h>
19 #include "packet-rrc.h"
20 #include "packet-umts_fp.h"
21 #include "packet-umts_mac.h"
22 #include "packet-nbap.h"
24 void proto_register_umts_mac(void);
25 void proto_reg_handoff_umts_mac(void);
27 int proto_umts_mac;
28 extern int proto_fp;
29 extern int proto_umts_rlc;
31 /* dissector fields */
32 static int hf_mac_fach_fdd_tctf;
33 static int hf_mac_rach_fdd_tctf;
34 static int hf_mac_ct;
35 static int hf_mac_ueid_type;
36 static int hf_mac_crnti;
37 static int hf_mac_urnti;
38 static int hf_mac_resolved_urnti;
39 static int hf_mac_crnti_urnti_match_frame;
40 static int hf_mac_channel;
41 /* static int hf_mac_channel_str; */
43 static int hf_mac_lch_id;
44 static int hf_mac_macdflowd_id;
45 /* static int hf_mac_channel_hsdsch; */
46 static int hf_mac_trch_id;
48 /* static int hf_mac_edch_type2_subframe_header; */
49 /* static int hf_mac_edch_type2_descriptors; */
50 /* static int hf_mac_edch_type2_lchid; */
51 /* static int hf_mac_edch_type2_length; */
52 /* static int hf_mac_edch_type2_flag; */
53 static int hf_mac_edch_type2_tsn;
54 static int hf_mac_edch_type2_ss;
55 static int hf_mac_edch_type2_ss_interpretation;
56 static int hf_mac_edch_type2_sdu;
57 static int hf_mac_edch_type2_sdu_data;
58 static int hf_mac_is_fraglink;
59 static int hf_mac_is_reasmin;
61 /* subtrees */
62 static int ett_mac;
63 static int ett_mac_fach;
64 static int ett_mac_rach;
65 static int ett_mac_dch;
66 static int ett_mac_pch;
67 static int ett_mac_edch;
68 static int ett_mac_hsdsch;
69 static int ett_mac_edch_type2;
70 static int ett_mac_edch_type2_sdu;
71 static int ett_mac_resolved_urnti;
73 static expert_field ei_mac_cs_dtch_not_implemented;
74 static expert_field ei_mac_rach_tctf_unknown;
75 static expert_field ei_mac_unknown_content;
76 static expert_field ei_mac_per_frame_info_missing;
77 static expert_field ei_mac_fach_content_type_unknown;
78 static expert_field ei_mac_no_logical_channel;
79 static expert_field ei_mac_faked_logical_channel_id;
80 static expert_field ei_mac_macis_sdu_reassembled;
81 static expert_field ei_mac_macis_sdu_first;
82 static expert_field ei_mac_macis_sdu_middle;
83 static expert_field ei_mac_macis_sdu_last;
84 static expert_field ei_mac_macis_sdu_complete;
85 static expert_field ei_mac_reserved_c_t;
87 static dissector_handle_t rlc_pcch_handle;
88 static dissector_handle_t rlc_ccch_handle;
89 static dissector_handle_t rlc_ctch_handle;
90 static dissector_handle_t rlc_dcch_handle;
91 static dissector_handle_t rlc_ps_dtch_handle;
92 static dissector_handle_t rrc_handle;
94 /* MAC-is reassembly */
95 static unsigned MAX_TSN = 64;
96 static uint16_t mac_tsn_size = 6;
97 static int global_mac_tsn_size = MAC_TSN_6BITS;
98 int get_mac_tsn_size(void) { return global_mac_tsn_size; }
99 static const enum_val_t tsn_size_enumvals[] = {
100 {"6", "6 bits", MAC_TSN_6BITS},
101 {"14", "14 bits", MAC_TSN_14BITS},
102 {NULL, NULL, -1}};
103 enum mac_is_fragment_type {
104 MAC_IS_HEAD,
105 MAC_IS_MIDDLE,
106 MAC_IS_TAIL
108 typedef struct _mac_is_fragment {
109 uint8_t * data;
110 uint32_t length;
111 uint32_t frame_num;
112 uint16_t tsn;
113 uint8_t type;
114 struct _mac_is_fragment * next;
115 } mac_is_fragment;
116 typedef struct {
117 uint32_t frame_num; /* Where reassembly was done (depends on order of arrival). */
118 uint16_t tsn; /* TSN for the tail fragment. */
119 uint8_t * data;
120 uint32_t length;
121 mac_is_fragment * fragments;
122 } mac_is_sdu;
123 typedef struct {
124 mac_is_fragment * head;
125 mac_is_fragment * middle;
126 mac_is_fragment * tail;
127 } body_parts;
128 typedef struct {
129 uint8_t lchid; /* Logical Channel Identifier. */
130 unsigned ueid; /* User Equipment Identifier. */
131 } mac_is_channel;
132 static GHashTable * mac_is_sdus; /* channel -> (frag -> sdu) */
133 static GHashTable * mac_is_fragments; /* channel -> body_parts[] */
134 static gboolean mac_is_channel_equal(const void *a, const void *b)
136 const mac_is_channel *x = (const mac_is_channel *)a, *y = (const mac_is_channel *)b;
137 return x->lchid == y->lchid && x->ueid == y->ueid;
139 static unsigned mac_is_channel_hash(const void *key)
141 const mac_is_channel * ch = (const mac_is_channel *)key;
142 return (ch->ueid << 4) | ch->lchid;
145 static gboolean mac_is_fragment_equal(const void *a, const void *b)
147 const mac_is_fragment *x = (const mac_is_fragment *)a, *y = (const mac_is_fragment *)b;
148 return x->frame_num == y->frame_num && x->tsn == y->tsn && x->type == y->type;
150 static unsigned mac_is_fragment_hash(const void *key)
152 const mac_is_fragment *frag = (const mac_is_fragment *)key;
153 return (frag->frame_num << 2) | frag->type;
156 static const value_string rach_fdd_tctf_vals[] = {
157 { TCTF_CCCH_RACH_FDD , "CCCH over RACH (FDD)" },
158 { TCTF_DCCH_DTCH_RACH_FDD , "DCCH/DTCH over RACH (FDD)" },
159 { 0, NULL }};
161 static const value_string fach_fdd_tctf_vals[] = {
162 { TCTF_BCCH_FACH_FDD , "BCCH over FACH (FDD)" },
163 { TCTF_DCCH_DTCH_FACH_FDD , "DCCH/DTCH over FACH (FDD)" },
164 { TCTF_MTCH_FACH_FDD , "MTCH over FACH (FDD)" },
165 { TCTF_CCCH_FACH_FDD , "CCCH over FACH (FDD)" },
166 { TCTF_MCCH_FACH_FDD , "MCCH over FACH (FDD)" },
167 { TCTF_MSCH_FACH_FDD , "MSCH over FACH (FDD)" },
168 { TCTF_CTCH_FACH_FDD , "CTCH over FACH (FDD)" },
169 { 0, NULL }};
171 static const value_string ueid_type_vals[] = {
172 { MAC_UEID_TYPE_URNTI, "U-RNTI" },
173 { MAC_UEID_TYPE_CRNTI, "C-RNTI" },
174 { 0, NULL }};
176 static const value_string mac_logical_channel_vals[] = {
177 { MAC_PCCH, "PCCH" },
178 { MAC_CCCH, "CCCH" },
179 { MAC_CTCH, "CTCH" },
180 { MAC_DCCH, "DCCH" },
181 { MAC_DTCH, "DTCH" },
182 { MAC_BCCH, "BCCH" },
183 { MAC_MCCH, "MCCH" },
184 { MAC_MSCH, "MSCH" },
185 { MAC_MTCH, "MTCH" },
186 { MAC_N_A, "N/A" },
187 { 0, NULL }};
189 static uint8_t fach_fdd_tctf(uint8_t hdr, uint16_t *bit_offs)
191 uint8_t tctf;
192 /* first, test for valid 2-bit combinations */
193 tctf = hdr >> 6;
194 switch (tctf) {
195 case TCTF_BCCH_FACH_FDD:
196 case TCTF_DCCH_DTCH_FACH_FDD:
197 *bit_offs = 2;
198 return tctf;
200 /* 4-bit combinations */
201 tctf = hdr >> 4;
202 switch (tctf) {
203 case TCTF_MTCH_FACH_FDD:
204 *bit_offs = 4;
205 return tctf;
207 /* just return the 8-bit combination */
208 *bit_offs = 8;
209 tctf = hdr;
210 switch (tctf) {
211 case TCTF_CCCH_FACH_FDD:
212 case TCTF_MCCH_FACH_FDD:
213 case TCTF_MSCH_FACH_FDD:
214 case TCTF_CTCH_FACH_FDD:
215 return tctf;
216 default:
217 return tctf; /* TODO */
221 static uint16_t tree_add_common_dcch_dtch_fields(tvbuff_t *tvb, packet_info *pinfo _U_,
222 proto_tree *tree, uint16_t bitoffs, fp_info *fpinf, umts_mac_info *macinf, rlc_info *rlcinf)
224 uint8_t ueid_type;
225 conversation_t *p_conv;
226 umts_fp_conversation_info_t *umts_fp_conversation_info = NULL;
227 fp_rach_channel_info_t *fp_rach_channel_info = NULL;
228 fp_fach_channel_info_t *fp_fach_channel_info = NULL;
229 wmem_tree_t* channel_rnti_map = NULL;
230 uint16_t c_rnti;
231 fp_crnti_allocation_info_t *fp_crnti_allocation_info = NULL;
233 ueid_type = tvb_get_bits8(tvb, bitoffs, 2);
234 proto_tree_add_bits_item(tree, hf_mac_ueid_type, tvb, bitoffs, 2, ENC_BIG_ENDIAN);
235 bitoffs += 2;
236 if (ueid_type == MAC_UEID_TYPE_URNTI) {
237 proto_tree_add_bits_item(tree, hf_mac_urnti, tvb, bitoffs, 32, ENC_BIG_ENDIAN);
238 rlcinf->ueid[fpinf->cur_tb] = tvb_get_bits32(tvb, bitoffs, 32,ENC_BIG_ENDIAN);
239 bitoffs += 32;
240 } else if (ueid_type == MAC_UEID_TYPE_CRNTI) {
241 proto_tree_add_bits_item(tree, hf_mac_crnti, tvb, 4, 16, ENC_BIG_ENDIAN);
242 c_rnti = tvb_get_bits16(tvb, bitoffs, 16,ENC_BIG_ENDIAN);
243 p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
244 conversation_pt_to_conversation_type(pinfo->ptype),
245 pinfo->destport, pinfo->srcport, NO_ADDR_B);
246 if (p_conv != NULL) {
247 umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp);
249 /* Trying to resolve the U-RNTI for this C-RNTI based on the channel type*/
250 switch(fpinf->channel){
251 case CHANNEL_RACH_FDD:
252 /* In RACH: Get the channel's RNTIs map */
253 if (umts_fp_conversation_info) {
254 fp_rach_channel_info = (fp_rach_channel_info_t *)umts_fp_conversation_info->channel_specific_info;
255 if(fp_rach_channel_info) {
256 channel_rnti_map = fp_rach_channel_info->crnti_to_urnti_map;
259 break;
260 case CHANNEL_FACH_FDD:
261 /* In FACH: Get the channel's RNTIs map */
262 if (umts_fp_conversation_info) {
263 fp_fach_channel_info = (fp_fach_channel_info_t *)umts_fp_conversation_info->channel_specific_info;
264 if(fp_fach_channel_info) {
265 channel_rnti_map = fp_fach_channel_info->crnti_to_urnti_map;
268 break;
270 if(channel_rnti_map) {
271 fp_crnti_allocation_info = (fp_crnti_allocation_info_t *)wmem_tree_lookup32(channel_rnti_map, c_rnti);
273 /* If not found in the RACH/FACH channel's map, Look in the global RNTIs map */
274 if(fp_crnti_allocation_info == NULL) {
275 fp_crnti_allocation_info = (fp_crnti_allocation_info_t *)wmem_tree_lookup32(rrc_global_urnti_crnti_map, c_rnti);
276 if(fp_crnti_allocation_info != NULL) {
277 /* If found in the global map, check how many times it was retrieved (including this one) */
278 fp_crnti_allocation_info->global_retrieval_count++;
279 /* If seen 2 times (RACH + fast FACH) remove from global map */
280 if(fp_crnti_allocation_info->global_retrieval_count == 2) {
281 wmem_tree_remove32(rrc_global_urnti_crnti_map, c_rnti);
283 /* Also add to this channel's map for later retrieval */
284 if(channel_rnti_map) {
285 wmem_tree_insert32(channel_rnti_map, c_rnti, (void *)fp_crnti_allocation_info);
289 /* Choosing between resolved U-RNTI (if found) or the C-RNTI as UE-ID for RLC */
290 if(fp_crnti_allocation_info != NULL) {
291 /* Using U-RNTI */
292 rlcinf->ueid[fpinf->cur_tb] = fp_crnti_allocation_info->urnti;
293 /* Adding 'Resolved U-RNTI' related tree items*/
294 proto_item *temp;
295 proto_tree *resolved_urnti_tree;
296 temp = proto_tree_add_uint(tree, hf_mac_resolved_urnti, tvb, 0, 0, fp_crnti_allocation_info->urnti);
297 proto_item_set_generated(temp);
298 resolved_urnti_tree = proto_item_add_subtree(temp, ett_mac_resolved_urnti);
299 temp = proto_tree_add_uint(resolved_urnti_tree , hf_mac_crnti_urnti_match_frame, tvb, 0, 0, fp_crnti_allocation_info->alloc_frame_number);
300 proto_item_set_generated(temp);
302 else {
303 /* Using C-RNTI */
304 rlcinf->ueid[fpinf->cur_tb] = c_rnti;
306 bitoffs += 16;
309 if (macinf->ctmux[fpinf->cur_tb]) {
310 proto_item * temp;
311 if(rlcinf){
312 rlcinf->rbid[fpinf->cur_tb] = tvb_get_bits8(tvb, bitoffs, 4)+1;
314 proto_tree_add_bits_item(tree, hf_mac_ct, tvb, bitoffs, 4, ENC_BIG_ENDIAN);
315 bitoffs += 4;
316 if(rlcinf){
317 temp = proto_tree_add_uint(tree, hf_mac_lch_id, tvb, 0, 0, rlcinf->rbid[fpinf->cur_tb]);
318 proto_item_set_generated(temp);
321 return bitoffs;
324 static int dissect_mac_fdd_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
326 proto_tree *pch_tree = NULL;
327 proto_item *channel_type;
329 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
330 col_set_str(pinfo->cinfo, COL_INFO, "PCCH");
332 if (tree) {
333 proto_item *ti;
334 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
335 pch_tree = proto_item_add_subtree(ti, ett_mac_pch);
336 proto_item_append_text(ti, " (PCCH)");
337 channel_type = proto_tree_add_uint(pch_tree, hf_mac_channel, tvb, 0, 0, MAC_PCCH);
338 proto_item_set_generated(channel_type);
340 call_dissector_with_data(rlc_pcch_handle, tvb, pinfo, tree, data);
341 return tvb_captured_length(tvb);
344 static int dissect_mac_fdd_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
346 uint8_t tctf;
347 uint8_t chan;
348 uint16_t bitoffs = 0;
349 tvbuff_t *next_tvb;
350 proto_tree *rach_tree = NULL;
351 proto_item *channel_type;
352 umts_mac_info *macinf;
353 fp_info *fpinf;
354 rlc_info *rlcinf;
355 proto_item *ti = NULL;
356 uint8_t c_t;
357 /* RACH TCTF is always 2 bit */
358 tctf = tvb_get_bits8(tvb, 0, 2);
359 bitoffs += 2;
361 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
363 col_set_str(pinfo->cinfo, COL_INFO,
364 val_to_str_const(tctf, rach_fdd_tctf_vals, "Unknown TCTF"));
366 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
367 rach_tree = proto_item_add_subtree(ti, ett_mac_rach);
369 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
370 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
371 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
372 if (!macinf || !fpinf) {
373 proto_tree_add_expert(rach_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
374 return 1;
377 proto_tree_add_bits_item(rach_tree, hf_mac_rach_fdd_tctf, tvb, 0, 2, ENC_BIG_ENDIAN);
378 if (tctf == TCTF_DCCH_DTCH_RACH_FDD) {
379 macinf->ctmux[fpinf->cur_tb] = 1; /* DCCH/DTCH on RACH *always* has a C/T */
380 bitoffs = tree_add_common_dcch_dtch_fields(tvb, pinfo, rach_tree, bitoffs, fpinf, macinf, rlcinf);
383 chan = fpinf->cur_chan;
384 /* handoff to next dissector */
385 switch (tctf) {
386 case TCTF_CCCH_RACH_FDD:
387 proto_item_append_text(ti, " (CCCH)");
388 channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_CCCH);
389 proto_item_set_generated(channel_type);
390 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
391 add_new_data_source(pinfo, next_tvb, "Octet-Aligned CCCH Data");
392 call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
393 break;
394 case TCTF_DCCH_DTCH_RACH_FDD:
395 /*Set RLC Mode/MAC content based on the L-CHID derived from the C/T flag*/
396 c_t = tvb_get_bits8(tvb,bitoffs-4,4);
397 if (c_t == 15) {
398 /* reserved value, discard PDU */
399 expert_add_info(pinfo, NULL, &ei_mac_reserved_c_t);
400 break;
402 rlcinf->mode[chan] = lchId_rlc_map[c_t+1];
403 macinf->content[chan] = lchId_type_table[c_t+1];
404 rlcinf->rbid[chan] = c_t+1;
405 switch (macinf->content[chan]) {
406 case MAC_CONTENT_DCCH:
407 proto_item_append_text(ti, " (DCCH)");
408 channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
409 proto_item_set_generated(channel_type);
410 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
411 add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
412 call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
413 break;
414 case MAC_CONTENT_PS_DTCH:
415 proto_item_append_text(ti, " (PS DTCH)");
416 channel_type = proto_tree_add_uint(rach_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
417 proto_item_set_generated(channel_type);
418 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
419 add_new_data_source(pinfo, next_tvb, "Octet-Aligned DTCH Data");
420 call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
421 break;
422 case MAC_CONTENT_CS_DTCH:
423 proto_item_append_text(ti, " (CS DTCH)");
424 /* TODO */
425 break;
426 default:
427 proto_item_append_text(ti, " (Unknown RACH DCCH/DTCH Content)");
428 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown RACH DCCH/DTCH Content");
430 break;
431 default:
432 proto_item_append_text(ti, " (Unknown RACH TCTF)");
433 expert_add_info_format(pinfo, NULL, &ei_mac_rach_tctf_unknown, "Unknown RACH TCTF");
435 return tvb_captured_length(tvb);
438 static int dissect_mac_fdd_fach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
440 uint8_t hdr, tctf;
441 uint16_t bitoffs = 0;
442 uint16_t tctf_len, chan;
443 proto_tree *fach_tree = NULL;
444 proto_item *channel_type;
445 tvbuff_t *next_tvb;
446 umts_mac_info *macinf;
447 fp_info *fpinf;
448 rlc_info *rlcinf;
449 struct rrc_info *rrcinf;
450 proto_item *ti = NULL;
451 int c_t;
452 hdr = tvb_get_uint8(tvb, 0);
454 /* get target channel type field */
455 tctf = fach_fdd_tctf(hdr, &bitoffs);
456 tctf_len = bitoffs;
458 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
460 col_set_str(pinfo->cinfo, COL_INFO,
461 val_to_str_const(tctf, fach_fdd_tctf_vals, "Unknown TCTF"));
463 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
464 fach_tree = proto_item_add_subtree(ti, ett_mac_fach);
466 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
467 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
468 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
470 if (!macinf || !fpinf) {
471 proto_tree_add_expert(fach_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
472 return 1;
475 proto_tree_add_bits_item(fach_tree, hf_mac_fach_fdd_tctf, tvb, 0, tctf_len, ENC_BIG_ENDIAN);
476 if (tctf == TCTF_DCCH_DTCH_FACH_FDD) {
477 macinf->ctmux[fpinf->cur_tb] = 1; /* DCCH/DTCH on FACH *always* has a C/T */
478 bitoffs = tree_add_common_dcch_dtch_fields(tvb, pinfo, fach_tree, bitoffs, fpinf, macinf, rlcinf);
481 chan = fpinf->cur_chan;
482 switch (tctf) {
483 case TCTF_CCCH_FACH_FDD:
484 proto_item_append_text(ti, " (CCCH)");
485 channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_CCCH);
486 proto_item_set_generated(channel_type);
487 /* CCCH over FACH is always octet aligned */
488 next_tvb = tvb_new_subset_remaining(tvb, 1);
489 call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
490 break;
491 case TCTF_DCCH_DTCH_FACH_FDD:
493 /*Set RLC Mode based on the L-CHID derived from the C/T flag*/
494 c_t = tvb_get_bits8(tvb,bitoffs-4,4);
495 if (c_t == 15) {
496 /* reserved value, discard PDU */
497 expert_add_info(pinfo, NULL, &ei_mac_reserved_c_t);
498 break;
500 rlcinf->mode[fpinf->cur_tb] = lchId_rlc_map[c_t+1];
501 macinf->content[fpinf->cur_tb] = lchId_type_table[c_t+1];
502 switch (macinf->content[fpinf->cur_tb]) {
504 case MAC_CONTENT_DCCH:
505 proto_item_append_text(ti, " (DCCH)");
506 channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
507 proto_item_set_generated(channel_type);
508 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
509 add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
510 call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
511 break;
512 case MAC_CONTENT_PS_DTCH:
513 proto_item_append_text(ti, " (PS DTCH)");
514 channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
515 proto_item_set_generated(channel_type);
516 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[chan] - bitoffs);
517 add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
518 call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
519 break;
520 case MAC_CONTENT_CS_DTCH:
521 proto_item_append_text(ti, " (CS DTCH)");
522 expert_add_info(pinfo, NULL, &ei_mac_cs_dtch_not_implemented);
523 /* TODO */
524 break;
525 default:
526 proto_item_append_text(ti, " (Unknown FACH Content)");
527 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown FACH Content for this transportblock");
529 break;
530 case TCTF_CTCH_FACH_FDD:
531 proto_item_append_text(ti, " (CTCH)");
532 channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_CTCH);
533 proto_item_set_generated(channel_type);
534 /* CTCH over FACH is always octet aligned */
535 next_tvb = tvb_new_subset_remaining(tvb, 1);
536 call_dissector_with_data(rlc_ctch_handle, next_tvb, pinfo, tree, data);
537 break;
538 /* july 5: Added support for BCCH*/
539 case TCTF_BCCH_FACH_FDD:
540 proto_item_append_text(ti, " (BCCH)");
541 channel_type = proto_tree_add_uint(fach_tree, hf_mac_channel, tvb, 0, 0, MAC_BCCH);
542 proto_item_set_generated(channel_type);
544 /*We need to skip the first two bits (the TCTF bits), and since there is no MAC header, send rest to RRC*/
545 next_tvb= tvb_new_octet_aligned(tvb, 2, (tvb_reported_length(tvb)*8)-2);
546 add_new_data_source(pinfo, next_tvb, "Octet-Aligned BCCH Data");
548 /* In this case skip RLC and call RRC immediately subdissector */
549 rrcinf = (rrc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0);
550 if (!rrcinf) {
551 rrcinf = wmem_new0(wmem_file_scope(), struct rrc_info);
552 p_add_proto_data(wmem_file_scope(), pinfo, proto_rrc, 0, rrcinf);
554 rrcinf->msgtype[fpinf->cur_tb] = RRC_MESSAGE_TYPE_BCCH_FACH;
556 call_dissector_with_data(rrc_handle, next_tvb, pinfo, tree, data);
558 break;
559 case TCTF_MSCH_FACH_FDD:
560 case TCTF_MCCH_FACH_FDD:
561 case TCTF_MTCH_FACH_FDD:
562 expert_add_info(pinfo, NULL, &ei_mac_fach_content_type_unknown);
563 break;
564 default:
565 proto_item_append_text(ti, " (Unknown FACH Content)");
566 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, " Unknown FACH Content");
567 break;
569 return tvb_captured_length(tvb);
572 static int dissect_mac_fdd_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
574 uint16_t pos;
575 uint8_t bitoffs = 0;
576 umts_mac_info *macinf;
577 fp_info *fpinf;
578 rlc_info *rlcinf;
579 proto_tree *dch_tree = NULL;
580 proto_item *channel_type;
581 tvbuff_t *next_tvb;
582 proto_item *ti = NULL;
584 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
586 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
587 dch_tree = proto_item_add_subtree(ti, ett_mac_dch);
589 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
590 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
591 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
593 if (!macinf || !fpinf) {
594 proto_tree_add_expert(dch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
595 return 1;
597 pos = fpinf->cur_tb;
599 if (macinf->ctmux[pos]) {
600 if(rlcinf){
601 rlcinf->rbid[fpinf->cur_tb] = tvb_get_bits8(tvb, bitoffs, 4)+1;
603 /*Add CT flag to GUI*/
604 proto_tree_add_bits_item(dch_tree, hf_mac_ct, tvb, 0, 4, ENC_BIG_ENDIAN);
605 bitoffs = 4;
608 if (bitoffs) {
609 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, fpinf->chan_tf_size[pos] - bitoffs);
610 add_new_data_source(pinfo, next_tvb, "Octet-Aligned DCCH Data");
611 } else
612 next_tvb = tvb;
613 switch (macinf->content[pos]) {
614 case MAC_CONTENT_DCCH:
615 proto_item_append_text(ti, " (DCCH)");
617 /*Show logical channel id*/
618 channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
619 proto_item_set_generated(channel_type);
620 if(macinf->lchid[pos]!= 255){
622 if(macinf->fake_chid[pos]){
623 expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
625 }else{
626 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
629 channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
630 proto_item_set_generated(channel_type);
632 /*Transport channel printout*/
633 channel_type = proto_tree_add_uint(dch_tree, hf_mac_trch_id, tvb, 0, 0, macinf->trchid[pos]);
634 proto_item_set_generated(channel_type);
635 call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
636 break;
637 case MAC_CONTENT_PS_DTCH:
638 proto_item_append_text(ti, " (PS DTCH)");
639 /*Show logical channel id*/
640 channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
641 proto_item_set_generated(channel_type);
643 if(macinf->lchid[pos]== 255){
644 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
647 channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
648 proto_item_set_generated(channel_type);
649 call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
650 break;
651 case MAC_CONTENT_CS_DTCH:
652 proto_item_append_text(ti, " (CS DTCH)");
653 /*Show logical channel id*/
654 channel_type = proto_tree_add_uint(dch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
655 proto_item_set_generated(channel_type);
656 if(macinf->lchid[pos]!= 255){
657 if(macinf->fake_chid[pos]){
658 expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
660 }else{
661 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
664 channel_type = proto_tree_add_uint(dch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
665 proto_item_set_generated(channel_type);
667 /*Transport channel printout*/
668 channel_type = proto_tree_add_uint(dch_tree, hf_mac_trch_id, tvb, 0, 0, macinf->trchid[pos]);
669 proto_item_set_generated(channel_type);
671 break;
672 default:
673 proto_item_append_text(ti, " (Unknown DCH Content)");
674 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown DCH Content");
676 return tvb_captured_length(tvb);
679 static void init_frag(tvbuff_t * tvb, body_parts * bp, unsigned length, unsigned offset, uint32_t frame_num, uint16_t tsn, uint8_t type)
681 mac_is_fragment * frag = wmem_new(wmem_file_scope(), mac_is_fragment);
682 frag->type = type;
683 frag->length = length;
684 frag->data = (uint8_t *)wmem_alloc(wmem_file_scope(), length);
685 frag->frame_num = frame_num;
686 frag->tsn = tsn;
687 frag->next = NULL;
688 switch (type) {
689 case MAC_IS_HEAD:
690 DISSECTOR_ASSERT(bp->head == NULL);
691 bp->head = frag;
692 break;
693 case MAC_IS_MIDDLE:
694 DISSECTOR_ASSERT(bp->middle == NULL);
695 bp->middle = frag;
696 break;
697 case MAC_IS_TAIL:
698 DISSECTOR_ASSERT(bp->tail == NULL);
699 bp->tail = frag;
700 break;
702 tvb_memcpy(tvb, frag->data, offset, length);
705 static void mac_is_copy(mac_is_sdu * sdu, mac_is_fragment * frag, unsigned total_length, bool reverse)
707 DISSECTOR_ASSERT(sdu->length+frag->length <= total_length);
708 if (reverse) {
709 memcpy(sdu->data+total_length-frag->length-sdu->length, frag->data, frag->length);
710 } else {
711 memcpy(sdu->data+sdu->length, frag->data, frag->length);
713 sdu->length += frag->length;
714 wmem_free(wmem_file_scope(), frag->data);
718 * @param length Length of whole SDU, it will be verified.
720 static tvbuff_t * reassemble(tvbuff_t * tvb, body_parts ** body_parts_array, uint16_t head_tsn, unsigned length, mac_is_channel * ch, unsigned frame_num)
722 mac_is_sdu * sdu;
723 mac_is_fragment * f;
724 uint16_t i;
725 GHashTable * sdus;
727 /* Find frag->sdu hash table for this channel. */
728 sdus = (GHashTable *)g_hash_table_lookup(mac_is_sdus, ch);
729 /* If this is the first time we see this channel. */
730 if (sdus == NULL) {
731 mac_is_channel * channel;
732 sdus = g_hash_table_new(mac_is_fragment_hash, mac_is_fragment_equal);
733 channel = wmem_new(wmem_file_scope(), mac_is_channel);
734 *channel = *ch;
735 g_hash_table_insert(mac_is_sdus, channel, sdus);
738 sdu = wmem_new(wmem_file_scope(), mac_is_sdu);
739 sdu->length = 0;
740 sdu->data = (uint8_t *)wmem_alloc(wmem_file_scope(), length);
742 f = body_parts_array[head_tsn]->head; /* Start from head. */
743 g_hash_table_insert(sdus, f, sdu); /* Insert head->sdu mapping. */
744 body_parts_array[head_tsn]->head = NULL; /* Reset head. */
745 mac_is_copy(sdu, f, length, false); /* Copy head data into SDU. */
746 sdu->fragments = f; /* Set up fragments list to point at head. */
747 sdu->frame_num = frame_num; /* Frame number where reassembly is being done. */
749 for (i = (head_tsn+1)%MAX_TSN; body_parts_array[i]->middle != NULL; i = (i+1)%MAX_TSN)
751 f = f->next = body_parts_array[i]->middle; /* Iterate through. */
752 g_hash_table_insert(sdus, f, sdu); /* Insert middle->sdu mapping. */
753 body_parts_array[i]->middle = NULL; /* Reset. */
754 mac_is_copy(sdu, f, length, false); /* Copy middle data into SDU. */
756 DISSECTOR_ASSERT(body_parts_array[i]->tail != NULL);
758 f->next = body_parts_array[i]->tail;
759 g_hash_table_insert(sdus, f->next, sdu); /* Insert tail->sdu mapping. */
760 body_parts_array[i]->tail = NULL; /* Reset tail. */
761 sdu->tsn = i; /* Use TSN of tail as key for the SDU. */
762 mac_is_copy(sdu, f->next, length, false); /* Copy tail data into SDU. */
764 return tvb_new_child_real_data(tvb, sdu->data, sdu->length, sdu->length);
767 static mac_is_sdu * get_sdu(unsigned frame_num, uint16_t tsn, uint8_t type, mac_is_channel * ch)
769 mac_is_sdu * sdu = NULL;
770 GHashTable * sdus = NULL;
771 mac_is_fragment frag_lookup_key;
773 sdus = (GHashTable *)g_hash_table_lookup(mac_is_sdus, ch);
774 if (sdus) {
775 frag_lookup_key.frame_num = frame_num;
776 frag_lookup_key.tsn = tsn;
777 frag_lookup_key.type = type;
778 sdu = (mac_is_sdu *)g_hash_table_lookup(sdus, &frag_lookup_key);
779 return sdu;
781 return NULL;
784 static tvbuff_t * add_to_tree(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, mac_is_sdu * sdu, unsigned offset, uint16_t maclength, uint8_t type)
786 tvbuff_t * new_tvb = NULL;
788 if (sdu->frame_num == pinfo->num) {
789 mac_is_fragment * f = sdu->fragments;
790 unsigned counter = 0;
791 new_tvb = tvb_new_child_real_data(tvb, sdu->data, sdu->length, sdu->length);
792 add_new_data_source(pinfo, new_tvb, "Reassembled MAC-is SDU");
793 proto_tree_add_expert(tree, pinfo, &ei_mac_macis_sdu_reassembled, new_tvb, 0, -1);
795 while (f) {
796 proto_tree_add_uint_format_value(tree, hf_mac_is_fraglink, new_tvb,
797 counter, f->length, f->frame_num,
798 "%u, payload: %u-%u (%u bytes) (TSN: %u)",
799 f->frame_num, counter, counter+f->length-1, f->length,
800 f->tsn);
801 counter += f->length;
802 f = f->next;
804 return new_tvb;
805 } else {
806 new_tvb = tvb_new_subset_length_caplen(tvb, offset, maclength, -1);
807 switch (type) {
808 case MAC_IS_HEAD:
809 proto_tree_add_expert(tree, pinfo, &ei_mac_macis_sdu_first, new_tvb, 0, -1);
810 break;
811 case MAC_IS_MIDDLE:
812 proto_tree_add_expert(tree, pinfo, &ei_mac_macis_sdu_middle, new_tvb, 0, -1);
813 break;
814 case MAC_IS_TAIL:
815 proto_tree_add_expert(tree, pinfo, &ei_mac_macis_sdu_last, new_tvb, 0, -1);
816 break;
818 proto_tree_add_uint(tree, hf_mac_is_reasmin, new_tvb, 0, 0, sdu->frame_num);
819 return NULL; /* No data here. */
824 * If return value > 0 then tsn is changed to be tsn of head.
825 * @return return length of sequence tsn-1 to head.
827 static unsigned find_head(body_parts ** body_parts_array, uint16_t * tsn)
829 unsigned length = 0;
830 *tsn = (*tsn==0)? (uint16_t)(MAX_TSN-1) : (*tsn)-1;
831 for (; body_parts_array[*tsn]->middle != NULL; *tsn = (*tsn==0)?(uint16_t)(MAX_TSN-1):(*tsn)-1)
832 length += body_parts_array[*tsn]->middle->length;
833 if (body_parts_array[*tsn]->head != NULL)
834 return length+body_parts_array[*tsn]->head->length;
835 return 0;
839 * @return return length of sequence tsn+1 to tail.
841 static unsigned find_tail(body_parts ** body_parts_array, uint16_t tsn)
843 unsigned length = 0;
844 for (tsn = (tsn+1)%MAX_TSN; body_parts_array[tsn]->middle != NULL; tsn = (tsn+1)%MAX_TSN)
845 length += body_parts_array[tsn]->middle->length;
846 if (body_parts_array[tsn]->tail != NULL)
847 return length+body_parts_array[tsn]->tail->length;
848 return 0;
852 * @param ch Channel for which body parts are to be fetched.
853 * @return Array of body_part* for channel 'ch'.
855 static body_parts ** get_body_parts(mac_is_channel * ch)
857 body_parts ** bpa = (body_parts **)g_hash_table_lookup(mac_is_fragments, ch);
858 /* If there was no body_part* array for this channel, create one. */
859 if (bpa == NULL) {
860 mac_is_channel * channel;
861 uint16_t i;
862 bpa = wmem_alloc_array(wmem_file_scope(), body_parts*, MAX_TSN); /* Create new body_parts-pointer array */
863 for (i = 0; i < MAX_TSN; i++) {
864 bpa[i] = wmem_new0(wmem_file_scope(), body_parts); /* Fill it with body_parts. */
866 channel = wmem_new(wmem_file_scope(), mac_is_channel); /* Alloc new channel for use in hash table. */
867 *channel = *ch;
868 g_hash_table_insert(mac_is_fragments, channel, bpa);
870 return bpa;
873 static tvbuff_t * mac_is_add_fragment(tvbuff_t * tvb _U_, packet_info *pinfo, proto_tree * tree _U_, uint8_t lchid, unsigned ueid, int offset, uint8_t ss, uint16_t tsn, int sdu_no, uint8_t no_sdus, uint16_t maclength)
875 mac_is_channel ch; /* Channel for looking up in hash tables. */
876 ch.lchid = lchid;
877 ch.ueid = ueid;
879 /* If in first scan-through. */
880 if (!PINFO_FD_VISITED(pinfo)) {
881 /* Get body parts array for this channel. */
882 body_parts ** body_parts_array = get_body_parts(&ch);
883 /* Middle segment */
884 if (no_sdus == 1 && ss == 3) {
885 unsigned head_length, tail_length;
886 init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_MIDDLE);
887 tail_length = find_tail(body_parts_array, tsn);
888 if (tail_length > 0) {
889 head_length = find_head(body_parts_array, &tsn);
890 if (head_length > 0) {
891 /* tsn is now TSN of head */
892 return reassemble(tvb, body_parts_array, tsn, tail_length+head_length+maclength, &ch, pinfo->num);
895 /* XXX: haven't confirmed if case when middle segment comes last
896 * actually works or not. */
898 /* If first SDU is last segment of previous. A tail. */
899 else if (sdu_no == 0 && (ss & 1) == 1) {
900 unsigned length = maclength;
901 init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_TAIL);
902 length += find_head(body_parts_array, &tsn);
903 if (length > maclength) {
904 /* tsn is now TSN of head */
905 return reassemble(tvb, body_parts_array, tsn, length, &ch, pinfo->num);
908 /* If last SDU is first segment of next. A head. */
909 else if (sdu_no == no_sdus-1 && (ss & 2) == 2) {
910 unsigned length = maclength;
911 init_frag(tvb, body_parts_array[tsn], maclength, offset, pinfo->num, tsn, MAC_IS_HEAD);
912 length += find_tail(body_parts_array, tsn);
913 if (length > maclength) {
914 return reassemble(tvb, body_parts_array, tsn, length, &ch, pinfo->num);
916 /* If our SDU is not fragmented. */
917 } else {
918 DISSECTOR_ASSERT((sdu_no == 0) ? (ss&1) == 0 : ((sdu_no == no_sdus-1) ? (ss&2) == 0 : true));
919 return tvb_new_subset_length_caplen(tvb, offset, maclength, -1);
921 /* If clicking on a packet. */
922 } else {
923 tvbuff_t * new_tvb = NULL;
924 /* Middle segment */
925 if (no_sdus == 1 && ss == 3) {
926 mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_MIDDLE, &ch);
927 if (sdu) {
928 return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_MIDDLE);
931 /* If first SDU is last segment of previous. A tail. */
932 else if (sdu_no == 0 && (ss & 1) == 1) {
933 mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_TAIL, &ch);
934 if (sdu) {
935 return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_TAIL);
938 /* If last SDU is first segment of next. A head. */
939 else if (sdu_no == no_sdus-1 && (ss & 2) == 2) {
940 mac_is_sdu * sdu = get_sdu(pinfo->num, tsn, MAC_IS_HEAD, &ch);
941 if (sdu) {
942 return add_to_tree(tvb, pinfo, tree, sdu, offset, maclength, MAC_IS_HEAD);
944 } else {
945 new_tvb = tvb_new_subset_length_caplen(tvb, offset, maclength, -1);
946 proto_tree_add_expert(tree, pinfo, &ei_mac_macis_sdu_complete, new_tvb, 0, -1);
947 proto_tree_add_item(tree, hf_mac_edch_type2_sdu_data, new_tvb, 0, -1, ENC_NA);
948 return new_tvb;
951 return NULL;
954 static void ss_interpretation(tvbuff_t * tvb, proto_tree * tree, uint8_t ss, unsigned number_of_mac_is_sdus, unsigned offset)
956 switch (ss) {
957 case 0:
958 if (number_of_mac_is_sdus > 1) {
959 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
960 "The first MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The last MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU.");
961 } else {
962 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
963 "The MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU.");
965 break;
966 case 1:
967 if (number_of_mac_is_sdus > 1) {
968 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
969 "The last MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The first MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU.");
970 } else {
971 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
972 "The MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU.");
974 break;
975 case 2:
976 if (number_of_mac_is_sdus > 1) {
977 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
978 "The first MAC-is SDU of the MAC-is PDU is a complete MAC-d PDU or MAC-c PDU. The last MAC-is SDU of the MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
979 } else {
980 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
981 "The MAC-is SDU of the MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
983 break;
984 case 3:
985 if (number_of_mac_is_sdus > 1) {
986 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
987 "The first MAC-is SDU of the MAC-is PDU is the last segment of a MAC-d PDU or MAC-c PDU and the last MAC-is SDU of MAC-is PDU is the first segment of a MAC-d PDU or MAC-c PDU.");
988 } else {
989 proto_tree_add_uint_format_value(tree, hf_mac_edch_type2_ss_interpretation, tvb, offset, 1, ss,
990 "The MAC-is SDU is a middle segment of a MAC-d PDU or MAC-c PDU.");
992 break;
996 static void call_rlc(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, proto_item * ti, uint8_t lchid, void *data)
998 switch (lchId_type_table[lchid]) {
999 case MAC_CONTENT_DCCH:
1000 proto_item_append_text(ti, " (DCCH)");
1001 call_dissector_with_data(rlc_dcch_handle, tvb, pinfo, tree, data);
1002 break;
1003 case MAC_CONTENT_PS_DTCH:
1004 proto_item_append_text(ti, " (PS DTCH)");
1005 call_dissector_with_data(rlc_ps_dtch_handle, tvb, pinfo, tree, data);
1006 break;
1007 case MAC_CONTENT_CS_DTCH:
1008 proto_item_append_text(ti, " (CS DTCH)");
1009 /* TODO */
1010 break;
1011 default:
1012 proto_item_append_text(ti, " (Unknown EDCH Content)");
1013 expert_add_info_format(pinfo, ti, &ei_mac_unknown_content, "Unknown EDCH Content");
1014 break;
1019 * Dissect a MAC-is PDU.
1021 static int dissect_mac_fdd_edch_type2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1023 unsigned sdu_no, subframe_bytes = 0, offset = 0;
1024 uint8_t ss;
1025 uint16_t tsn;
1026 proto_item *pi, *temp;
1027 proto_tree *macis_pdu_tree, *macis_sdu_tree;
1028 umts_mac_is_info * mac_is_info = (umts_mac_is_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1029 rlc_info * rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1030 struct fp_info *p_fp_info = (struct fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1032 DISSECTOR_ASSERT(mac_is_info != NULL && rlcinf != NULL && p_fp_info != NULL);
1034 pi = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1035 macis_pdu_tree = proto_item_add_subtree(pi, ett_mac_edch_type2);
1037 /* SS */
1038 ss = (tvb_get_uint8(tvb, offset) & 0xc0) >> 6;
1039 proto_tree_add_item(macis_pdu_tree, hf_mac_edch_type2_ss, tvb, offset, 1, ENC_BIG_ENDIAN);
1041 ss_interpretation(tvb, macis_pdu_tree, ss, mac_is_info->number_of_mac_is_sdus, offset);
1043 /* TSN */
1044 tsn = tvb_get_bits8(tvb, offset*8+2, mac_tsn_size);
1045 proto_tree_add_bits_item(macis_pdu_tree, hf_mac_edch_type2_tsn, tvb, offset*8+2, mac_tsn_size, ENC_BIG_ENDIAN);
1047 offset += (2+mac_tsn_size)/8;
1049 /* MAC-is SDUs (i.e. MACd PDUs) */
1050 for (sdu_no=0; sdu_no < mac_is_info->number_of_mac_is_sdus; sdu_no++) {
1051 proto_item *ti;
1052 tvbuff_t * asm_tvb;
1053 uint8_t lchid = mac_is_info->lchid[sdu_no]+1;
1054 unsigned sdulength = mac_is_info->sdulength[sdu_no];
1056 ti = proto_tree_add_item(tree, hf_mac_edch_type2_sdu, tvb, offset, sdulength, ENC_NA);
1057 macis_sdu_tree = proto_item_add_subtree(ti, ett_mac_edch_type2_sdu);
1058 proto_item_append_text(ti, " (Logical channel=%u, Len=%u)", lchid, sdulength);
1059 temp = proto_tree_add_uint(ti, hf_mac_lch_id, tvb, 0, 0, lchid);
1060 proto_item_set_generated(temp);
1061 /*Set up information needed for MAC and lower layers*/
1062 rlcinf->mode[sdu_no] = lchId_rlc_map[lchid]; /* Set RLC mode by lchid to RLC_MODE map in nbap.h */
1063 rlcinf->ueid[sdu_no] = p_fp_info->com_context_id;
1064 rlcinf->rbid[sdu_no] = lchid;
1065 rlcinf->li_size[sdu_no] = RLC_LI_7BITS;
1066 rlcinf->ciphered[sdu_no] = false;
1067 rlcinf->deciphered[sdu_no] = false;
1069 asm_tvb = mac_is_add_fragment(tvb, pinfo, macis_sdu_tree, lchid, p_fp_info->com_context_id, offset, ss, tsn, sdu_no, mac_is_info->number_of_mac_is_sdus, sdulength);
1070 if (asm_tvb != NULL) {
1071 call_rlc(asm_tvb, pinfo, tree, ti, lchid, data);
1074 offset += sdulength;
1075 subframe_bytes += sdulength;
1078 proto_item_append_text(pi, "-is PDU (SS=%u, TSN=%u, %u bytes in %u SDU fragments)",
1079 ss, tsn, subframe_bytes, mac_is_info->number_of_mac_is_sdus);
1081 proto_item_set_len(pi, 1+subframe_bytes);
1082 /*total_bytes += subframe_bytes;*/
1083 return tvb_captured_length(tvb);
1086 static int dissect_mac_fdd_edch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1088 proto_tree *edch_tree = NULL;
1089 proto_item *channel_type;
1090 umts_mac_info *macinf;
1091 fp_info *fpinf;
1092 uint16_t pos;
1093 proto_item *ti = NULL;
1095 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1097 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1098 edch_tree = proto_item_add_subtree(ti, ett_mac_edch);
1100 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1102 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1103 if (!macinf|| !fpinf) {
1104 proto_tree_add_expert(edch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
1105 return 1;
1108 pos = fpinf->cur_tb;
1110 switch (macinf->content[pos]) {
1111 case MAC_CONTENT_DCCH:
1112 proto_item_append_text(ti, " (DCCH)");
1114 /*Show the logical channel id*/
1115 channel_type = proto_tree_add_uint(edch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1116 proto_item_set_generated(channel_type);
1118 channel_type = proto_tree_add_uint(edch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1119 proto_item_set_generated(channel_type);
1122 call_dissector_with_data(rlc_dcch_handle, tvb, pinfo, tree, data);
1123 break;
1124 case MAC_CONTENT_PS_DTCH:
1125 proto_item_append_text(ti, " (PS DTCH)");
1127 /*Show the logical channel id*/
1128 channel_type = proto_tree_add_uint(edch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1129 proto_item_set_generated(channel_type);
1131 channel_type = proto_tree_add_uint(edch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
1132 proto_item_set_generated(channel_type);
1134 call_dissector_with_data(rlc_ps_dtch_handle, tvb, pinfo, tree, data);
1135 break;
1136 case MAC_CONTENT_CS_DTCH:
1137 proto_item_append_text(ti, " (CS DTCH)");
1138 /* TODO */
1139 break;
1140 default:
1141 proto_item_append_text(ti, " (Unknown EDCH Content)");
1142 expert_add_info_format(pinfo, ti, &ei_mac_unknown_content, "Unknown EDCH Content");
1143 break;
1145 return tvb_captured_length(tvb);
1148 * Dissect hsdsch_common channel.
1150 * This will dissect hsdsch common channels, we handle this separately
1151 * since we might have to deal with MAC-ehs and or MAC-c headers
1152 * (in the MAC PDU).
1154 * @param tvb
1155 * @param pinfo
1156 * @param tree
1157 * @return Void.
1159 #if 0
1160 static void dissect_mac_fdd_hsdsch_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1162 proto_tree *hsdsch_tree = NULL;
1163 /*proto_item *channel_type;
1165 fp_info *fpinf;
1166 umts_mac_info *macinf;
1167 uint16_t pos;
1168 /* uint8_t bitoffs=0;
1169 tvbuff_t *next_tvb;
1171 proto_item *ti = NULL;
1173 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1175 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1176 hsdsch_tree = proto_item_add_subtree(ti, ett_mac_hsdsch);
1178 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1179 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac);
1181 if (!macinf) {
1182 proto_tree_add_expert(hsdsch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
1183 return;
1185 pos = fpinf->cur_tb;
1186 switch(macinf->content[pos]){
1187 /*In this case we don't have a MAC-c header 9.2.1.4*/
1189 #if 0
1190 case MAC_CONTENT_CCCH:
1192 break;
1193 case MAC_CONTENT_PCCH:
1195 break;
1197 case MAC_CONTENT_BCCH:
1199 break;
1200 #endif
1201 default:
1203 proto_item_append_text(ti, " (Unknown HSDSCH-Common Content)");
1204 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown HSDSCH-Common Content");
1205 break;
1209 #endif
1210 /* to avoid unnecessary re-alignment, the 4 bit padding prepended to the HSDSCH in FP type 1
1211 * are handled in the MAC layer
1212 * If the C/T field is present, 'bitoffs' will be 8 (4 bit padding and 4 bit C/T) and
1213 * no re-alignment is necessary
1214 * If no C/T is present, the whole payload will be left-shifted by 4 bit
1216 static int dissect_mac_fdd_hsdsch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1218 proto_tree *hsdsch_tree = NULL;
1219 proto_item *channel_type;
1220 fp_info *fpinf;
1221 umts_mac_info *macinf;
1222 uint16_t pos;
1223 uint8_t bitoffs=0;
1224 tvbuff_t *next_tvb;
1225 proto_item *ti = NULL;
1226 rlc_info * rlcinf;
1228 /*struct rrc_info *rrcinf = NULL;
1230 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC");
1232 ti = proto_tree_add_item(tree, proto_umts_mac, tvb, 0, -1, ENC_NA);
1233 hsdsch_tree = proto_item_add_subtree(ti, ett_mac_hsdsch);
1235 fpinf = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0);
1236 macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0);
1238 pos = fpinf->cur_tb;
1239 bitoffs = fpinf->hsdsch_entity == ehs ? 0 : 4; /*No MAC-d header for type 2*/
1241 if (!macinf) {
1242 proto_tree_add_expert(hsdsch_tree, pinfo, &ei_mac_per_frame_info_missing, tvb, 0, -1);
1243 return 1;
1245 if (macinf->ctmux[pos]) { /*The 4'st bits are padding*/
1246 proto_tree_add_bits_item(hsdsch_tree, hf_mac_ct, tvb, bitoffs, 4, ENC_BIG_ENDIAN);
1248 /*Sets the proper lchid, for later layers.*/
1249 macinf->lchid[pos] = tvb_get_bits8(tvb,bitoffs,4)+1;
1250 macinf->fake_chid[pos] = false;
1251 macinf->content[pos] = lchId_type_table[macinf->lchid[pos]]; /*Lookup MAC content*/
1253 rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0);
1254 rlcinf->rbid[pos] = macinf->lchid[pos];
1255 rlcinf->mode[pos] = lchId_rlc_map[macinf->lchid[pos]]; /*Look up RLC mode*/
1256 bitoffs += 4;
1259 if ((bitoffs % 8) == 0) {
1260 next_tvb = tvb_new_subset_remaining(tvb, bitoffs/8);
1261 } else {
1262 next_tvb = tvb_new_octet_aligned(tvb, bitoffs, macinf->pdu_len); /*Get rid of possible padding in at the end?*/
1263 add_new_data_source(pinfo, next_tvb, "Octet-Aligned HSDSCH Data");
1266 switch (macinf->content[pos]) {
1267 case MAC_CONTENT_CCCH:
1268 proto_item_append_text(ti, " (CCCH)");
1269 /*Set the logical channel id if it exists */
1270 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1271 proto_item_set_generated(channel_type);
1272 if(macinf->lchid[pos] != 255){
1273 if(macinf->fake_chid[pos]){
1274 expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1276 }else{
1277 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1279 /*Set the type of channel*/
1280 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1281 proto_item_set_generated(channel_type);
1283 /*Set the MACd-Flow ID*/
1284 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1285 proto_item_set_generated(channel_type);
1286 call_dissector_with_data(rlc_ccch_handle, next_tvb, pinfo, tree, data);
1287 break;
1288 case MAC_CONTENT_DCCH:
1289 proto_item_append_text(ti, " (DCCH)");
1290 /* channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel_hsdsch, tvb, 0, 0, MAC_DCCH);
1291 proto_item_set_generated(channel_type)*/
1292 /*Set the logical channel id if it exists */
1293 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1294 proto_item_set_generated(channel_type);
1295 if(macinf->lchid[pos] != 255){
1296 if(macinf->fake_chid[pos]){
1297 expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1299 }else{
1300 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1303 /*Set the type of channel*/
1304 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DCCH);
1306 proto_item_set_generated(channel_type);
1308 /*Set the MACd-Flow ID*/
1309 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1310 proto_item_set_generated(channel_type);
1311 call_dissector_with_data(rlc_dcch_handle, next_tvb, pinfo, tree, data);
1312 break;
1313 case MAC_CONTENT_PS_DTCH:
1314 proto_item_append_text(ti, " (PS DTCH)");
1316 /*Set the logical channel id if it exists */
1317 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_lch_id, tvb, 0, 0, macinf->lchid[pos]);
1318 proto_item_set_generated(channel_type);
1319 if(macinf->lchid[pos] != 255){
1320 if(macinf->fake_chid[pos]){
1321 expert_add_info(pinfo, channel_type, &ei_mac_faked_logical_channel_id);
1323 }else{
1324 expert_add_info(pinfo, channel_type, &ei_mac_no_logical_channel);
1327 /*Sets the channel type*/
1328 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_channel, tvb, 0, 0, MAC_DTCH);
1330 proto_item_set_generated(channel_type);
1332 /*Set the MACd-Flow ID*/
1333 channel_type = proto_tree_add_uint(hsdsch_tree, hf_mac_macdflowd_id, tvb, 0, 0, macinf->macdflow_id[pos]);
1334 proto_item_set_generated(channel_type);
1336 call_dissector_with_data(rlc_ps_dtch_handle, next_tvb, pinfo, tree, data);
1337 break;
1338 case MAC_CONTENT_CS_DTCH:
1339 proto_item_append_text(ti, " (CS DTCH)");
1340 break;
1341 default:
1342 proto_item_append_text(ti, " (Unknown HSDSCH Content)");
1343 expert_add_info_format(pinfo, NULL, &ei_mac_unknown_content, "Unknown HSDSCH Content");
1345 return tvb_captured_length(tvb);
1348 static void mac_is_sdus_hash_destroy(void *data)
1350 g_hash_table_destroy((GHashTable *)data);
1353 static void mac_init(void)
1355 mac_is_sdus = g_hash_table_new_full(mac_is_channel_hash, mac_is_channel_equal, NULL, mac_is_sdus_hash_destroy);
1356 mac_is_fragments = g_hash_table_new_full(mac_is_channel_hash, mac_is_channel_equal, NULL, NULL);
1357 if (global_mac_tsn_size == MAC_TSN_6BITS) {
1358 MAX_TSN = 64;
1359 mac_tsn_size = 6;
1360 } else {
1361 MAX_TSN = 16384;
1362 mac_tsn_size = 14;
1366 static void mac_cleanup(void)
1368 g_hash_table_destroy(mac_is_sdus);
1369 g_hash_table_destroy(mac_is_fragments);
1372 void
1373 proto_register_umts_mac(void)
1375 module_t *mac_module;
1376 static int *ett[] = {
1377 &ett_mac,
1378 &ett_mac_fach,
1379 &ett_mac_rach,
1380 &ett_mac_dch,
1381 &ett_mac_pch,
1382 &ett_mac_edch,
1383 &ett_mac_hsdsch,
1384 &ett_mac_edch_type2,
1385 &ett_mac_edch_type2_sdu,
1386 &ett_mac_resolved_urnti
1388 /** XX: Looks like some duplicate filter names ?? **/
1389 /** XX: May be OK: See doc/README.developer **/
1390 static hf_register_info hf[] = {
1391 { &hf_mac_rach_fdd_tctf,
1392 { "Target Channel Type Field", "mac.tctf",
1393 FT_UINT8, BASE_HEX, VALS(rach_fdd_tctf_vals), 0, NULL, HFILL }
1395 { &hf_mac_fach_fdd_tctf,
1396 { "Target Channel Type Field", "mac.tctf",
1397 FT_UINT8, BASE_HEX, VALS(fach_fdd_tctf_vals), 0, NULL, HFILL }
1399 { &hf_mac_ct,
1400 { "C/T", "mac.ct",
1401 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }
1403 { &hf_mac_ueid_type,
1404 { "UEID Type", "mac.ueid_type",
1405 FT_UINT8, BASE_DEC, VALS(ueid_type_vals), 0, NULL, HFILL }
1407 { &hf_mac_crnti,
1408 { "C-RNTI (UEID)", "mac.ueid",
1409 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
1411 { &hf_mac_urnti,
1412 { "U-RNTI (UEID)", "mac.ueid",
1413 FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
1415 { &hf_mac_resolved_urnti,
1416 { "Resolved U-RNTI", "mac.resolved_urnti",
1417 FT_UINT32, BASE_HEX, NULL, 0x0,
1418 "The U-RNTI of the UE which is using the C-RNTI seen in this frame",
1419 HFILL }
1421 { &hf_mac_crnti_urnti_match_frame,
1422 { "C-RNTI Allocation Frame", "mac.crnti_urnti_match_frame",
1423 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1424 "The frame number where the C-RNTI was allocated for the UE",
1425 HFILL }
1427 { &hf_mac_channel,
1428 { "Logical Channel Type", "mac.logical_channel",
1429 FT_UINT16, BASE_DEC, VALS(mac_logical_channel_vals), 0, NULL, HFILL }
1432 #if 0
1433 { &hf_mac_channel_str,
1434 { "Logical Channel", "mac.logical_channel",
1435 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1437 #endif
1438 #if 0
1439 { &hf_mac_channel_hsdsch,
1440 { "MACd-FlowID", "mac.macd_flowid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1442 #endif
1443 { &hf_mac_macdflowd_id,
1444 { "MACd-FlowID", "mac.macd_flowid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1446 { &hf_mac_lch_id,
1447 { "Logical Channel ID", "mac.logical_channel_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1449 { &hf_mac_trch_id,
1450 { "Transport Channel ID", "mac.transport_channel_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1452 #if 0
1453 { &hf_mac_edch_type2_descriptors,
1454 { "MAC-is Descriptors",
1455 "mac.edch.type2.descriptors", FT_STRING, BASE_NONE, NULL, 0x0,
1456 NULL, HFILL
1459 #endif
1460 #if 0
1461 { &hf_mac_edch_type2_lchid,
1462 { "LCH-ID",
1463 "mac.logical_channel_id", FT_UINT8, BASE_HEX, NULL, 0xf0,
1464 NULL, HFILL
1467 #endif
1468 #if 0
1469 { &hf_mac_edch_type2_length,
1470 { "Length",
1471 "mac.edch.type2.length", FT_UINT16, BASE_DEC, NULL, 0x0ffe,
1472 NULL, HFILL
1475 #endif
1476 #if 0
1477 { &hf_mac_edch_type2_flag,
1478 { "Flag",
1479 "mac.edch.type2.lchid", FT_UINT8, BASE_HEX, NULL, 0x01,
1480 "Indicates if another entry follows", HFILL
1483 #endif
1484 { &hf_mac_edch_type2_ss,
1485 { "SS",
1486 /* TODO: VALS */
1487 "mac.edch.type2.ss", FT_UINT8, BASE_HEX, NULL, 0xc0,
1488 "Segmentation Status", HFILL
1491 { &hf_mac_edch_type2_ss_interpretation,
1492 { "SS interpretation",
1493 "mac.edch.type2.ss_interpretation", FT_UINT8, BASE_HEX, NULL, 0x0,
1494 NULL, HFILL
1497 { &hf_mac_edch_type2_tsn,
1498 { "TSN",
1499 "mac.edch.type2.tsn", FT_UINT16, BASE_DEC, NULL, 0,
1500 "Transmission Sequence Number", HFILL
1503 { &hf_mac_edch_type2_sdu,
1504 { "MAC-is SDU",
1505 "mac.edch.type2.sdu", FT_NONE, BASE_NONE, NULL, 0x0,
1506 NULL, HFILL
1509 { &hf_mac_edch_type2_sdu_data,
1510 { "Data",
1511 "mac.edch.type2.sdu.data", FT_BYTES, BASE_NONE, NULL, 0x0,
1512 NULL, HFILL
1515 #if 0
1516 { &hf_mac_edch_type2_subframe_header,
1517 { "Subframe header",
1518 "mac.edch.type2.subframeheader", FT_STRING, BASE_NONE, NULL, 0x0,
1519 "EDCH Subframe header", HFILL
1522 #endif
1523 { &hf_mac_is_reasmin,
1524 { "Reassembled in frame", "mac.is.reasmin",
1525 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
1527 { &hf_mac_is_fraglink,
1528 { "Frame", "mac.is.fraglink",
1529 FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }
1533 static ei_register_info ei[] = {
1534 { &ei_mac_per_frame_info_missing, { "mac.per_frame_info_missing", PI_MALFORMED, PI_ERROR, "Cannot dissect MAC frame because per-frame info is missing", EXPFILL }},
1535 { &ei_mac_unknown_content, { "mac.unknown_content", PI_MALFORMED, PI_ERROR, "Unknown RACH DCCH/DTCH Content", EXPFILL }},
1536 { &ei_mac_rach_tctf_unknown, { "mac.rach_tctf.unknown", PI_MALFORMED, PI_ERROR, "Unknown RACH TCTF", EXPFILL }},
1537 { &ei_mac_cs_dtch_not_implemented, { "mac.cs_dtch.not_implemented", PI_DEBUG, PI_ERROR, "CS DTCH Is not implemented", EXPFILL }},
1538 { &ei_mac_fach_content_type_unknown, { "mac.fach_content_type.unknown", PI_UNDECODED, PI_WARN, "Unimplemented FACH Content type!", EXPFILL }},
1539 { &ei_mac_no_logical_channel, { "mac.no_logical_channel", PI_PROTOCOL, PI_WARN, "Frame is missing logical channel", EXPFILL }},
1540 { &ei_mac_faked_logical_channel_id, { "mac.faked_logical_channel_id", PI_PROTOCOL, PI_WARN, "This is a faked logical channel id!", EXPFILL }},
1541 { &ei_mac_macis_sdu_reassembled, { "mac.macis_sdu.reassembled", PI_REASSEMBLE, PI_CHAT, "Reassembled MAC-is SDU", EXPFILL }},
1542 { &ei_mac_macis_sdu_first, { "mac.macis_sdu.first", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is the first segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1543 { &ei_mac_macis_sdu_middle, { "mac.macis_sdu.middle", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is a middle segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1544 { &ei_mac_macis_sdu_last, { "mac.macis_sdu.last", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is the last segment of a MAC-d PDU or MAC-c PDU", EXPFILL }},
1545 { &ei_mac_macis_sdu_complete, { "mac.macis_sdu.complete", PI_REASSEMBLE, PI_CHAT, "This MAC-is SDU is a complete MAC-d PDU or MAC-c PDU", EXPFILL }},
1546 { &ei_mac_reserved_c_t, { "mac.reserved_ct", PI_PROTOCOL, PI_WARN, "C/T has a reserved value, PDU is discarded", EXPFILL }}
1549 expert_module_t* expert_umts_mac;
1551 proto_umts_mac = proto_register_protocol("MAC", "MAC", "mac");
1552 proto_register_field_array(proto_umts_mac, hf, array_length(hf));
1553 proto_register_subtree_array(ett, array_length(ett));
1554 expert_umts_mac = expert_register_protocol(proto_umts_mac);
1555 expert_register_field_array(expert_umts_mac, ei, array_length(ei));
1557 register_dissector("mac.fdd.rach", dissect_mac_fdd_rach, proto_umts_mac);
1558 register_dissector("mac.fdd.fach", dissect_mac_fdd_fach, proto_umts_mac);
1559 register_dissector("mac.fdd.pch", dissect_mac_fdd_pch, proto_umts_mac);
1560 register_dissector("mac.fdd.dch", dissect_mac_fdd_dch, proto_umts_mac);
1561 register_dissector("mac.fdd.edch", dissect_mac_fdd_edch, proto_umts_mac);
1562 register_dissector("mac.fdd.edch.type2", dissect_mac_fdd_edch_type2, proto_umts_mac);
1563 register_dissector("mac.fdd.hsdsch", dissect_mac_fdd_hsdsch, proto_umts_mac);
1565 register_init_routine(mac_init);
1566 register_cleanup_routine(mac_cleanup);
1568 /* Preferences */
1569 mac_module = prefs_register_protocol(proto_umts_mac, NULL);
1570 prefs_register_enum_preference(mac_module, "tsn_size", "TSN size",
1571 "TSN size in bits, either 6 or 14 bit",
1572 &global_mac_tsn_size, tsn_size_enumvals, false);
1575 void
1576 proto_reg_handoff_umts_mac(void)
1578 rlc_pcch_handle = find_dissector_add_dependency("rlc.pcch", proto_umts_mac);
1579 rlc_ccch_handle = find_dissector_add_dependency("rlc.ccch", proto_umts_mac);
1580 rlc_ctch_handle = find_dissector_add_dependency("rlc.ctch", proto_umts_mac);
1581 rlc_dcch_handle = find_dissector_add_dependency("rlc.dcch", proto_umts_mac);
1582 rlc_ps_dtch_handle = find_dissector_add_dependency("rlc.ps_dtch", proto_umts_mac);
1584 rrc_handle = find_dissector_add_dependency("rrc", proto_umts_mac);
1588 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1590 * Local variables:
1591 * c-basic-offset: 4
1592 * tab-width: 8
1593 * indent-tabs-mode: nil
1594 * End:
1596 * vi: set shiftwidth=4 tabstop=8 expandtab:
1597 * :indentSize=4:tabSize=8:noTabs=true: