Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-pdcp-lte.c
1 /* Routines for LTE PDCP/ROHC
2  *
3  * Martin Mathieson
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/expert.h>
35 #include <epan/addr_resolv.h>
36
37 #include "packet-pdcp-lte.h"
38
39 /* Described in:
40  * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
41  *                Packet Data Convergence Protocol (PDCP) specification
42  *
43  * RFC 3095       RObust Header Compression (ROHC):
44  *                Framework and four profiles: RTP, UDP, ESP, and uncompressed
45  */
46
47
48 /* TODO:
49    - Complete ROHC support for RTP and extend to other profiles (including ROHCv2)
50    - Support for deciphering
51    - Verify MAC authentication bytes
52 */
53
54
55 /* Initialize the protocol and registered fields. */
56 int proto_pdcp_lte = -1;
57
58 extern int proto_rlc_lte;
59
60 /* Configuration (info known outside of PDU) */
61 static int hf_pdcp_lte_configuration = -1;
62 static int hf_pdcp_lte_direction = -1;
63 static int hf_pdcp_lte_ueid = -1;
64 static int hf_pdcp_lte_channel_type = -1;
65 static int hf_pdcp_lte_channel_id = -1;
66 static int hf_pdcp_lte_rohc = -1;
67 static int hf_pdcp_lte_rohc_compression = -1;
68 static int hf_pdcp_lte_rohc_mode = -1;
69 static int hf_pdcp_lte_rohc_rnd = -1;
70 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
71 static int hf_pdcp_lte_rohc_profile = -1;
72 static int hf_pdcp_lte_no_header_pdu = -1;
73 static int hf_pdcp_lte_plane = -1;
74 static int hf_pdcp_lte_seqnum_length = -1;
75 static int hf_pdcp_lte_cid_inclusion_info = -1;
76 static int hf_pdcp_lte_large_cid_present = -1;
77
78 /* PDCP header fields */
79 static int hf_pdcp_lte_seq_num_5 = -1;
80 static int hf_pdcp_lte_seq_num_7 = -1;
81 static int hf_pdcp_lte_reserved3 = -1;
82 static int hf_pdcp_lte_seq_num_12 = -1;
83 static int hf_pdcp_lte_signalling_data = -1;
84 static int hf_pdcp_lte_mac = -1;
85 static int hf_pdcp_lte_data_control = -1;
86 static int hf_pdcp_lte_user_plane_data = -1;
87 static int hf_pdcp_lte_control_pdu_type = -1;
88 static int hf_pdcp_lte_fms = -1;
89 static int hf_pdcp_lte_bitmap = -1;
90 static int hf_pdcp_lte_bitmap_not_received = -1;
91
92 /* Robust Header Compression Fields */
93 static int hf_pdcp_lte_rohc_padding = -1;
94 static int hf_pdcp_lte_rohc_r_0_crc = -1;
95 static int hf_pdcp_lte_rohc_feedback = -1;
96
97 static int hf_pdcp_lte_rohc_type0_t = -1;
98 static int hf_pdcp_lte_rohc_type1_t = -1;
99 static int hf_pdcp_lte_rohc_type2_t = -1;
100
101 static int hf_pdcp_lte_rohc_d = -1;
102 static int hf_pdcp_lte_rohc_ir_crc = -1;
103
104 static int hf_pdcp_lte_rohc_static_ipv4 = -1;
105 static int hf_pdcp_lte_rohc_ip_version = -1;
106 static int hf_pdcp_lte_rohc_ip_protocol = -1;
107 static int hf_pdcp_lte_rohc_ip_src = -1;
108 static int hf_pdcp_lte_rohc_ip_dst = -1;
109
110 static int hf_pdcp_lte_rohc_static_udp = -1;
111 static int hf_pdcp_lte_rohc_static_udp_src_port = -1;
112 static int hf_pdcp_lte_rohc_static_udp_dst_port = -1;
113
114 static int hf_pdcp_lte_rohc_static_rtp = -1;
115 static int hf_pdcp_lte_rohc_static_rtp_ssrc = -1;
116
117 static int hf_pdcp_lte_rohc_dynamic_ipv4 = -1;
118 static int hf_pdcp_lte_rohc_dynamic_ipv4_tos = -1;
119 static int hf_pdcp_lte_rohc_dynamic_ipv4_ttl = -1;
120 static int hf_pdcp_lte_rohc_dynamic_ipv4_id = -1;
121 static int hf_pdcp_lte_rohc_dynamic_ipv4_df = -1;
122 static int hf_pdcp_lte_rohc_dynamic_ipv4_rnd = -1;
123 static int hf_pdcp_lte_rohc_dynamic_ipv4_nbo = -1;
124
125 static int hf_pdcp_lte_rohc_dynamic_udp = -1;
126 static int hf_pdcp_lte_rohc_dynamic_udp_checksum = -1;
127 static int hf_pdcp_lte_rohc_dynamic_udp_seqnum = -1;
128
129 static int hf_pdcp_lte_rohc_dynamic_rtp = -1;
130 static int hf_pdcp_lte_rohc_dynamic_rtp_rx = -1;
131 static int hf_pdcp_lte_rohc_dynamic_rtp_cc = -1;
132 static int hf_pdcp_lte_rohc_dynamic_rtp_seqnum = -1;
133 static int hf_pdcp_lte_rohc_dynamic_rtp_timestamp = -1;
134 static int hf_pdcp_lte_rohc_dynamic_rtp_reserved3 = -1;
135 static int hf_pdcp_lte_rohc_dynamic_rtp_x = -1;
136 static int hf_pdcp_lte_rohc_dynamic_rtp_mode = -1;
137 static int hf_pdcp_lte_rohc_dynamic_rtp_tis = -1;
138 static int hf_pdcp_lte_rohc_dynamic_rtp_tss = -1;
139 static int hf_pdcp_lte_rohc_dynamic_rtp_ts_stride = -1;
140
141 static int hf_pdcp_lte_rohc_ts = -1;
142 static int hf_pdcp_lte_rohc_m = -1;
143 static int hf_pdcp_lte_rohc_uor2_sn = -1;
144 static int hf_pdcp_lte_rohc_uor2_x = -1;
145
146 static int hf_pdcp_lte_rohc_add_cid = -1;
147 static int hf_pdcp_lte_rohc_large_cid = -1;
148
149 static int hf_pdcp_lte_rohc_uo0_sn = -1;
150 static int hf_pdcp_lte_rohc_uo0_crc = -1;
151
152 static int hf_pdcp_lte_rohc_r0_sn = -1;
153 static int hf_pdcp_lte_rohc_r0_crc_sn = -1;
154 static int hf_pdcp_lte_rohc_r0_crc_crc = -1;
155
156 static int hf_pdcp_lte_rohc_feedback_code = -1;
157 static int hf_pdcp_lte_rohc_feedback_size = -1;
158 static int hf_pdcp_lte_rohc_feedback_feedback1 = -1;
159 static int hf_pdcp_lte_rohc_feedback_feedback2 = -1;
160 static int hf_pdcp_lte_rohc_feedback_ack_type = -1;
161 static int hf_pdcp_lte_rohc_feedback_mode = -1;
162 static int hf_pdcp_lte_rohc_feedback_sn = -1;
163 static int hf_pdcp_lte_rohc_feedback_option = -1;
164 static int hf_pdcp_lte_rohc_feedback_length = -1;
165 static int hf_pdcp_lte_rohc_feedback_crc = -1;
166 static int hf_pdcp_lte_rohc_feedback_option_sn = -1;
167 static int hf_pdcp_lte_rohc_feedback_option_clock = -1;
168
169 static int hf_pdcp_lte_rohc_ip_id = -1;
170 static int hf_pdcp_lte_rohc_udp_checksum = -1;
171 static int hf_pdcp_lte_rohc_payload = -1;
172
173 /* Sequence Analysis */
174 static int hf_pdcp_lte_sequence_analysis = -1;
175 static int hf_pdcp_lte_sequence_analysis_ok = -1;
176 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
177 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
178
179 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
180 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
181
182
183
184
185 /* Protocol subtree. */
186 static int ett_pdcp = -1;
187 static int ett_pdcp_configuration = -1;
188 static int ett_pdcp_packet = -1;
189 static int ett_pdcp_lte_sequence_analysis = -1;
190 static int ett_pdcp_rohc = -1;
191 static int ett_pdcp_rohc_static_ipv4 = -1;
192 static int ett_pdcp_rohc_static_udp = -1;
193 static int ett_pdcp_rohc_static_rtp = -1;
194 static int ett_pdcp_rohc_dynamic_ipv4 = -1;
195 static int ett_pdcp_rohc_dynamic_udp = -1;
196 static int ett_pdcp_rohc_dynamic_rtp = -1;
197 static int ett_pdcp_rohc_report_bitmap = -1;
198
199
200 static const value_string direction_vals[] =
201 {
202     { DIRECTION_UPLINK,      "Uplink"},
203     { DIRECTION_DOWNLINK,    "Downlink"},
204     { 0, NULL }
205 };
206
207
208 static const value_string pdcp_plane_vals[] = {
209     { SIGNALING_PLANE,    "Signalling" },
210     { USER_PLANE,         "User" },
211     { 0,   NULL }
212 };
213
214 static const value_string logical_channel_vals[] = {
215     { Channel_DCCH,  "DCCH"},
216     { Channel_BCCH,  "BCCH"},
217     { Channel_CCCH,  "CCCH"},
218     { Channel_PCCH,  "PCCH"},
219     { 0,             NULL}
220 };
221
222 static const value_string rohc_mode_vals[] = {
223     { UNIDIRECTIONAL,            "Unidirectional" },
224     { OPTIMISTIC_BIDIRECTIONAL,  "Optimistic Bidirectional" },
225     { RELIABLE_BIDIRECTIONAL,    "Reliable Bidirectional" },
226     { 0,   NULL }
227 };
228
229
230 /* Values taken from:
231    http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
232 static const value_string rohc_profile_vals[] = {
233          { 0x0000,   "ROHC uncompressed" },      /* [RFC5795] */
234          { 0x0001,   "ROHC RTP" },               /* [RFC3095] */
235          { 0x0101,   "ROHCv2 RTP" },             /* [RFC5225] */
236          { 0x0002,   "ROHC UDP" },               /* [RFC3095] */
237          { 0x0102,   "ROHCv2 UDP" },             /* [RFC5225] */
238          { 0x0003,   "ROHC ESP" },               /* [RFC3095] */
239          { 0x0103,   "ROHCv2 ESP" },             /* [RFC5225] */
240          { 0x0004,   "ROHC IP" },                /* [RFC3843] */
241          { 0x0104,   "ROHCv2 IP" },              /* [RFC5225] */
242          { 0x0005,   "ROHC LLA" },               /* [RFC4362] */
243          { 0x0105,   "ROHC LLA with R-mode" },   /* [RFC3408] */
244          { 0x0006,   "ROHC TCP" },               /* [RFC4996] */
245          { 0x0007,   "ROHC RTP/UDP-Lite" },      /* [RFC4019] */
246          { 0x0107,   "ROHCv2 RTP/UDP-Lite" },    /* [RFC5225] */
247          { 0x0008,   "ROHC UDP-Lite" },          /* [RFC4019] */
248          { 0x0108,   "ROHCv2 UDP-Lite" },        /* [RFC5225] */
249          { 0,   NULL }
250 };
251
252 static const value_string pdu_type_vals[] = {
253     { 0,   "Control PDU" },
254     { 1,   "Data PDU" },
255     { 0,   NULL }
256 };
257
258 static const value_string feedback_ack_vals[] = {
259     { 0,   "ACK" },
260     { 1,   "NACK" },
261     { 2,   "STATIC-NACK" },
262     { 0,   NULL }
263 };
264
265 static const value_string feedback_option_vals[] = {
266     { 1,   "CRC" },
267     { 2,   "REJECT" },
268     { 3,   "SN-Not-Valid" },
269     { 4,   "SN" },
270     { 5,   "Clock" },
271     { 6,   "Jitter" },
272     { 7,   "Loss" },
273     { 0,   NULL }
274 };
275
276 static const value_string control_pdu_type_vals[] = {
277     { 0,   "PDCP Status report" },
278     { 1,   "Header Compression Feedback Information" },
279     { 0,   NULL }
280 };
281
282 static const value_string t_vals[] = {
283     { 0,   "ID message format" },
284     { 1,   "TS message format" },
285     { 0,   NULL }
286 };
287
288 static const value_string ip_protocol_vals[] = {
289     { 6,   "TCP" },
290     { 17,  "UDP" },
291     { 0,   NULL }
292 };
293
294
295 static dissector_handle_t ip_handle;
296 static dissector_handle_t ipv6_handle;
297 static dissector_handle_t data_handle;
298
299 /* Preference variables */
300 static gboolean global_pdcp_show_feedback_option_tag_length = FALSE;
301 static gboolean global_pdcp_dissect_user_plane_as_ip = FALSE;
302 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = FALSE;
303 static gboolean global_pdcp_check_sequence_numbers = FALSE;
304 static gboolean global_pdcp_dissect_rohc = FALSE;
305
306
307 /**************************************************/
308 /* Sequence number analysis                       */
309
310 /* Channel key */
311 typedef struct
312 {
313     guint16            ueId;
314     LogicalChannelType channelType;
315     guint16            channelId;
316     guint8             direction;
317 } pdcp_channel_hash_key;
318
319 /* Channel state */
320 typedef struct
321 {
322     guint16  previousSequenceNumber;
323     guint32  previousFrameNum;
324 } pdcp_channel_status;
325
326 /* The sequence analysis channel hash table.
327    Maps key -> status */
328 static GHashTable *pdcp_sequence_analysis_channel_hash = NULL;
329
330 /* Equal keys */
331 static gint pdcp_channel_equal(gconstpointer v, gconstpointer v2)
332 {
333     const pdcp_channel_hash_key* val1 = v;
334     const pdcp_channel_hash_key* val2 = v2;
335
336     /* All fields must match */
337     return (memcmp(val1, val2, sizeof(pdcp_channel_hash_key)) == 0);
338 }
339
340 /* Compute a hash value for a given key. */
341 static guint pdcp_channel_hash_func(gconstpointer v)
342 {
343     const pdcp_channel_hash_key* val1 = v;
344
345     /* TODO: use multipliers */
346     return val1->ueId + val1->channelType + val1->channelId + val1->direction;
347 }
348
349 /* Hash table functions for frame reports */
350
351 /* TODO: copied from packet-rlc-lte.c.  extern, or add to lib? */
352 /* Equal keys */
353 static gint pdcp_frame_equal(gconstpointer v, gconstpointer v2)
354 {
355     return (v == v2);
356 }
357
358 /* Compute a hash value for a given key. */
359 static guint pdcp_frame_hash_func(gconstpointer v)
360 {
361     return GPOINTER_TO_UINT(v);
362 }
363
364
365 /* Info to attach to frame when first read, recording what to show about sequence */
366 typedef struct
367 {
368     gboolean  sequenceExpectedCorrect;
369     guint16   sequenceExpected;
370     guint32   previousFrameNum;
371
372     guint16   firstSN;
373     guint16   lastSN;
374
375     enum { SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing} state;
376 } pdcp_sequence_report_in_frame;
377
378 /* The sequence analysis frame report hash table instance itself   */
379 static GHashTable *pdcp_lte_frame_sequence_analysis_report_hash = NULL;
380
381
382 /* Add to the tree values associated with sequence analysis for this frame */
383 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
384                                    pdcp_lte_info *p_pdcp_lte_info,
385                                    guint16   sequenceNumber,
386                                    packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
387 {
388     proto_tree *seqnum_tree;
389     proto_item *seqnum_ti;
390     proto_item *ti;
391
392     /* Create subtree */
393     seqnum_ti = proto_tree_add_string_format(tree,
394                                              hf_pdcp_lte_sequence_analysis,
395                                              tvb, 0, 0,
396                                              "", "Sequence Analysis");
397     seqnum_tree = proto_item_add_subtree(seqnum_ti,
398                                          ett_pdcp_lte_sequence_analysis);
399     PROTO_ITEM_SET_GENERATED(seqnum_ti);
400
401
402     /* Previous channel frame */
403     if (p->previousFrameNum != 0) {
404         proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
405                             tvb, 0, 0, p->previousFrameNum);
406     }
407
408     /* Expected sequence number */
409     ti = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
410                             tvb, 0, 0, p->sequenceExpected);
411     PROTO_ITEM_SET_GENERATED(ti);
412
413     /* Make sure we have recognised SN length */
414     switch (p_pdcp_lte_info->seqnum_length) {
415         case PDCP_SN_LENGTH_5_BITS:
416         case PDCP_SN_LENGTH_7_BITS:
417         case PDCP_SN_LENGTH_12_BITS:
418             break;
419         default:
420             DISSECTOR_ASSERT_NOT_REACHED();
421             break;
422     }
423
424     switch (p->state) {
425         case SN_OK:
426             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
427                                         tvb, 0, 0, TRUE);
428             PROTO_ITEM_SET_GENERATED(ti);
429             proto_item_append_text(seqnum_ti, " - OK");
430             break;
431
432         case SN_Missing:
433             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
434                                         tvb, 0, 0, FALSE);
435             PROTO_ITEM_SET_GENERATED(ti);
436             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
437                                         tvb, 0, 0, TRUE);
438             PROTO_ITEM_SET_GENERATED(ti);
439             if (p->lastSN != p->firstSN) {
440                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
441                                        "PDCP SNs (%u to %u) missing for %s on UE %u",
442                                        p->firstSN, p->lastSN,
443                                        val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
444                                        p_pdcp_lte_info->ueid);
445                 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
446                                        p->firstSN, p->lastSN);
447             }
448             else {
449                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
450                                        "PDCP SN (%u) missing for %s on UE %u",
451                                        p->firstSN,
452                                        val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
453                                        p_pdcp_lte_info->ueid);
454                 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
455                                        p->firstSN);
456             }
457             break;
458
459         case SN_Repeated:
460             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
461                                         tvb, 0, 0, FALSE);
462             PROTO_ITEM_SET_GENERATED(ti);
463             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
464                                         tvb, 0, 0, TRUE);
465             PROTO_ITEM_SET_GENERATED(ti);
466             expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
467                                    "PDCP SN (%u) repeated for %s for UE %u",
468                                    p->firstSN,
469                                    val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
470                                    p_pdcp_lte_info->ueid);
471             proto_item_append_text(seqnum_ti, "- SN %u Repeated",
472                                    p->firstSN);
473             break;
474
475         default:
476             /* Incorrect sequence number */
477             expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
478                                    "Wrong Sequence Number for %s on UE %u - got %u, expected %u",
479                                    val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
480                                    p_pdcp_lte_info->ueid, sequenceNumber, p->sequenceExpected);
481             break;
482     }
483 }
484
485
486 /* Update the channel status and set report for this frame */
487 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
488                                      pdcp_lte_info *p_pdcp_lte_info,
489                                      guint16 sequenceNumber,
490                                      proto_tree *tree)
491 {
492     pdcp_channel_hash_key          channel_key;
493     pdcp_channel_hash_key          *p_channel_key;
494     pdcp_channel_status            *p_channel_status;
495     pdcp_sequence_report_in_frame  *p_report_in_frame = NULL;
496     gboolean               createdChannel = FALSE;
497     guint16                expectedSequenceNumber = 0;
498     guint16                snLimit = 0;
499
500     /* If find stat_report_in_frame already, use that and get out */
501     if (pinfo->fd->flags.visited) {
502         p_report_in_frame = (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_frame_sequence_analysis_report_hash,
503                                                                                 &pinfo->fd->num);
504         if (p_report_in_frame != NULL) {
505             addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
506                                    sequenceNumber,
507                                    pinfo, tree, tvb);
508             return;
509         }
510         else {
511             /* Give up - we must have tried already... */
512             return;
513         }
514     }
515
516
517     /**************************************************/
518     /* Create or find an entry for this channel state */
519     memset(&channel_key, 0, sizeof(channel_key));
520     channel_key.ueId = p_pdcp_lte_info->ueid;
521     channel_key.channelType = p_pdcp_lte_info->channelType;
522     channel_key.channelId = p_pdcp_lte_info->channelId;
523     channel_key.direction = p_pdcp_lte_info->direction;
524
525     /* Do the table lookup */
526     p_channel_status = (pdcp_channel_status*)g_hash_table_lookup(pdcp_sequence_analysis_channel_hash, &channel_key);
527
528     /* Create table entry if necessary */
529     if (p_channel_status == NULL) {
530         createdChannel = TRUE;
531
532         /* Allocate a new value and duplicate key contents */
533         p_channel_status = se_alloc0(sizeof(pdcp_channel_status));
534         p_channel_key = se_memdup(&channel_key, sizeof(pdcp_channel_hash_key));
535
536         /* Add entry */
537         g_hash_table_insert(pdcp_sequence_analysis_channel_hash, p_channel_key, p_channel_status);
538     }
539
540     /* Create space for frame state_report */
541     p_report_in_frame = se_alloc(sizeof(pdcp_sequence_report_in_frame));
542
543     switch (p_pdcp_lte_info->seqnum_length) {
544         case PDCP_SN_LENGTH_5_BITS:
545             snLimit = 32;
546             break;
547         case PDCP_SN_LENGTH_7_BITS:
548             snLimit = 128;
549             break;
550         case PDCP_SN_LENGTH_12_BITS:
551             snLimit = 4096;
552             break;
553         default:
554             DISSECTOR_ASSERT_NOT_REACHED();
555             break;
556     }
557
558     /* Work out expected sequence number */
559     if (!createdChannel) {
560         expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
561     }
562
563     /* Set report for this frame */
564     /* For PDCP, sequence number is always expectedSequence number */
565     p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
566
567     /* For wrong sequence number... */
568     if (!p_report_in_frame->sequenceExpectedCorrect) {
569
570         /* Frames are not missing if we get an earlier sequence number again */
571         if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
572             p_report_in_frame->state = SN_Missing;
573             p_report_in_frame->firstSN = expectedSequenceNumber;
574             p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
575
576             p_report_in_frame->sequenceExpected = expectedSequenceNumber;
577             p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
578
579             /* Update channel status to remember *this* frame */
580             p_channel_status->previousFrameNum = pinfo->fd->num;
581             p_channel_status->previousSequenceNumber = sequenceNumber;
582         }
583         else {
584             /* An SN has been repeated */
585             p_report_in_frame->state = SN_Repeated;
586             p_report_in_frame->firstSN = sequenceNumber;
587
588             p_report_in_frame->sequenceExpected = expectedSequenceNumber;
589             p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
590         }
591     }
592     else {
593         /* SN was OK */
594         p_report_in_frame->state = SN_OK;
595         p_report_in_frame->sequenceExpected = expectedSequenceNumber;
596         p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
597
598         /* Update channel status to remember *this* frame */
599         p_channel_status->previousFrameNum = pinfo->fd->num;
600         p_channel_status->previousSequenceNumber = sequenceNumber;
601     }
602
603     /* Associate with this frame number */
604     g_hash_table_insert(pdcp_lte_frame_sequence_analysis_report_hash, &pinfo->fd->num, p_report_in_frame);
605
606     /* Add state report for this frame into tree */
607     addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
608                            pinfo, tree, tvb);
609 }
610
611
612 /* Write the given formatted text to:
613    - the info column
614    - the top-level RLC PDU item */
615 static void write_pdu_label_and_info(proto_item *pdu_ti,
616                                      packet_info *pinfo, const char *format, ...)
617 {
618     #define MAX_INFO_BUFFER 256
619     static char info_buffer[MAX_INFO_BUFFER];
620
621     va_list ap;
622
623     va_start(ap, format);
624     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
625     va_end(ap);
626
627     /* Add to indicated places */
628     col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
629     proto_item_append_text(pdu_ti, "%s", info_buffer);
630 }
631
632
633
634 /***************************************************************/
635
636
637 /* Dissect a Large-CID field.
638    Return following offset */
639 static int dissect_large_cid(proto_tree *tree,
640                              tvbuff_t *tvb,
641                              int offset)
642 {
643     guint8 first_octet = tvb_get_guint8(tvb, offset);
644
645     if ((first_octet & 0x80) == 0) {
646         /* One byte */
647         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 1,
648                             first_octet);
649         return offset+1;
650     }
651     else {
652         /* Two bytes */
653         guint16 bytes = tvb_get_ntohs(tvb, offset) & 0x7fff;
654         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 2,
655                             bytes);
656         return offset+2;
657     }
658
659 }
660
661 static int dissect_pdcp_dynamic_chain(proto_tree *tree,
662                                       proto_item *root_item _U_,
663                                       tvbuff_t *tvb,
664                                       int offset,
665                                       struct pdcp_lte_info *p_pdcp_info,
666                                       packet_info *pinfo)
667 {
668     /* IPv4 dynamic */
669     if (p_pdcp_info->rohc_ip_version == 4) {
670         proto_tree *dynamic_ipv4_tree;
671         proto_item *root_ti;
672         int tree_start_offset = offset;
673         guint8 tos, ttl, id, rnd, nbo;
674
675         /* Create dynamic IPv4 subtree */
676         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_ipv4, tvb, offset, -1, ENC_NA);
677         dynamic_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_ipv4);
678
679         /* ToS */
680         tos = tvb_get_guint8(tvb, offset);
681         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_tos, tvb, offset, 1, FALSE);
682         offset++;
683
684         /* TTL */
685         ttl = tvb_get_guint8(tvb, offset);
686         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_ttl, tvb, offset, 1, FALSE);
687         offset++;
688
689         /* IP-ID */
690         id = tvb_get_guint8(tvb, offset);
691         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_id, tvb, offset, 1, FALSE);
692         offset++;
693
694         /* IP flags */
695         rnd = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
696         nbo = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
697         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_df, tvb, offset, 1, FALSE);
698         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_rnd, tvb, offset, 1, FALSE);
699         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_nbo, tvb, offset, 1, FALSE);
700
701         /* TODO: general extension header list... */
702         offset += 3;
703
704         /* Set proper length for subtree */
705         proto_item_set_len(root_ti, offset-tree_start_offset);
706
707         /* Add summary to root item */
708         proto_item_append_text(root_ti, " (ToS=%u, TTL=%u, ID=%u, RND=%u, NBO=%u)",
709                                tos, ttl, id, rnd, nbo);
710     }
711
712     /* UDP dynamic */
713     if ((p_pdcp_info->profile == 1) ||
714         (p_pdcp_info->profile == 2)) {
715
716         proto_tree *dynamic_udp_tree;
717         proto_item *root_ti;
718         unsigned short checksum;
719
720         /* Create dynamic UDP subtree */
721         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_udp, tvb, offset, 2, ENC_NA);
722         dynamic_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_udp);
723
724         /* 16-bit checksum */
725         checksum = tvb_get_ntohs(tvb, offset);
726         proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_checksum, tvb, offset, 2, FALSE);
727         offset +=2;
728
729         if (p_pdcp_info->profile == 2) {
730             guint16 seqnum;
731
732             seqnum = tvb_get_ntohs(tvb, offset);
733             proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_seqnum, tvb, offset, 2, FALSE);
734             offset +=2;
735
736             /* Add summary to root item */
737             proto_item_append_text(root_ti, " (checksum = %04x, seqnum = %u)", checksum, seqnum);
738         }
739         else {
740             /* Add summary to root item */
741             proto_item_append_text(root_ti, " (checksum = %04x)", checksum);
742         }
743     }
744
745     /* RTP dynamic */
746     if (p_pdcp_info->profile == 1) {
747         proto_tree *dynamic_rtp_tree;
748         proto_item *root_ti;
749         int tree_start_offset = offset;
750         guint8     rx;
751         /*guint8     contributing_csrcs;*/
752         guint16    sequence_number;
753         guint32    timestamp;
754         guint8     tis=0, tss=0;
755         guint64    ts_stride=0;
756
757         /* Create dynamic RTP subtree */
758         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_rtp, tvb, offset, -1, ENC_NA);
759         dynamic_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_rtp);
760
761         /* TODO: */
762         /* V | P | RX | CC */
763         rx = tvb_get_guint8(tvb, offset) & 0x10;
764         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_rx, tvb, offset, 1, FALSE);
765         /*contributing_csrcs = tvb_get_guint8(tvb, offset) & 0x0f;*/
766         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_cc, tvb, offset, 1, FALSE);
767         offset += 1;
768
769         /* TODO: */
770         /* M | PT */
771         offset += 1;
772
773         /* Sequence number */
774         sequence_number = tvb_get_ntohs(tvb, offset);
775         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_seqnum, tvb, offset, 2, FALSE);
776         offset += 2;
777
778         /* Timestamp (4 octets) */
779         timestamp = tvb_get_ntohl(tvb, offset);
780         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_timestamp, tvb, offset, 4, FALSE);
781         offset += 4;
782
783         /* TODO: CSRC list */
784         /*offset += (4 * contributing_csrcs); */
785         offset++;
786
787         /* TODO: Reserved | X | Mode | TIS | TIS */
788         if (rx) {
789             guint8 this_byte = tvb_get_guint8(tvb, offset);
790             proto_item *reserved_ti = proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
791                                                           tvb, offset, 1, FALSE);
792
793             /* Check reserved bits are 0 */
794             if ((this_byte & 0xe0) != 0) {
795                 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
796                                        "Reserved bits have value 0x%x - should be 0x0",
797                                        (this_byte & 0xe0));
798             }
799             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_x, tvb, offset, 1, FALSE);
800             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_mode, tvb, offset, 1, FALSE);
801             tss = (this_byte & 0x02);
802             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tss, tvb, offset, 1, FALSE);
803             tis = (this_byte & 0x01);
804             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tis, tvb, offset, 1, FALSE);
805             offset++;
806         }
807
808         /* TODO: the length of these fields can be learned by looked at the leading bits, see
809            RFC 3095, "4.5.6.  Self-describing variable-length values" */
810         /* TODO: TS-Stride (1-4 bytes) */
811         if (tis) {
812             /* Assume encoded in two bytes for now... */
813             proto_tree_add_bits_ret_val(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
814                                         tvb, offset*8 + 2, 14, &ts_stride, FALSE);
815             offset += 2;
816         }
817
818         /* TODO: Time-stride (1-4 bytes) */
819         if (tss) {
820         }
821
822         /* Set proper length for subtree */
823         proto_item_set_len(root_ti, offset-tree_start_offset);
824
825         /* Add summary to root item */
826         proto_item_append_text(root_ti, " (seqnum = %u, timestamp = %u)",
827                                sequence_number, timestamp);
828     }
829
830     return offset;
831 }
832
833
834
835 static int dissect_pdcp_irdyn_packet(proto_tree *tree,
836                                      proto_item *root_item,
837                                      tvbuff_t *tvb,
838                                      int offset,
839                                      struct pdcp_lte_info *p_pdcp_info,
840                                      packet_info *pinfo)
841 {
842     col_append_str(pinfo->cinfo, COL_INFO, " IRDYN");
843     proto_item_append_text(root_item, " (IRDYN)");
844
845     /* Large CID */
846     if (p_pdcp_info->large_cid_present) {
847         offset = dissect_large_cid(tree, tvb, offset);
848     }
849
850     /* Profile */
851     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
852     offset++;
853
854     /* 8-bit CRC */
855     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
856     offset++;
857
858     /* Dissect dynamic chain */
859     offset = dissect_pdcp_dynamic_chain(tree,
860                                         root_item,
861                                         tvb,
862                                         offset,
863                                         p_pdcp_info,
864                                         pinfo);
865     return offset;
866 }
867
868
869 static int dissect_pdcp_ir_packet(proto_tree *tree,
870                                   proto_item *root_item,
871                                   tvbuff_t *tvb,
872                                   int offset,
873                                   struct pdcp_lte_info *p_pdcp_info,
874                                   packet_info *pinfo)
875 {
876     unsigned char dynamic_chain_present;
877
878     col_append_str(pinfo->cinfo, COL_INFO, " IR");
879     proto_item_append_text(root_item, " (IR)");
880
881     /* Is dynamic chain present? */
882     dynamic_chain_present = tvb_get_guint8(tvb, offset) & 0x1;
883     proto_tree_add_item(tree, hf_pdcp_lte_rohc_d, tvb, offset, 1, FALSE);
884     offset++;
885
886     /* Large CID */
887     if (p_pdcp_info->large_cid_present) {
888         offset = dissect_large_cid(tree, tvb, offset);
889     }
890
891     /* Profile */
892     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
893     offset++;
894
895     /* 8-bit CRC */
896     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
897     offset++;
898
899     /* IPv4 static part */
900     if (p_pdcp_info->rohc_ip_version == 4) {
901         proto_tree *static_ipv4_tree;
902         proto_item *root_ti;
903         int tree_start_offset = offset;
904         guint8  protocol;
905         guint32 source, dest;
906
907         /* Create static IPv4 subtree */
908         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_ipv4, tvb, offset, -1, ENC_NA);
909         static_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_ipv4);
910
911         /* IP version (must be 4) */
912         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_version, tvb, offset, 1, FALSE);
913         offset++;
914
915         /* Protocol */
916         protocol = tvb_get_guint8(tvb, offset);
917         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_protocol, tvb, offset, 1, FALSE);
918         offset++;
919
920         /* Source address */
921         source = tvb_get_ipv4(tvb, offset);
922         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_src, tvb, offset, 4, FALSE);
923         offset += 4;
924
925         /* Dest address */
926         dest = tvb_get_ipv4(tvb, offset);
927         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_dst, tvb, offset, 4, FALSE);
928         offset += 4;
929
930         /* Set proper length for subtree */
931         proto_item_set_len(root_ti, offset-tree_start_offset);
932
933         /* Add summary to root item */
934         proto_item_append_text(root_ti, " (prot=%s: %s -> %s)",
935                                val_to_str_const(protocol, ip_protocol_vals, "Unknown"),
936                                (char*)get_hostname(source),
937                                (char*)get_hostname(dest));
938     }
939
940     /* UDP static part. TODO: also check protocol from last part!? */
941     if ((p_pdcp_info->profile == 1) ||
942         (p_pdcp_info->profile == 2)) {
943
944         proto_tree *static_udp_tree;
945         proto_item *root_ti;
946         int tree_start_offset = offset;
947         unsigned short source_port, dest_port;
948
949         /* Create static UDP subtree */
950         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_udp, tvb, offset, -1, ENC_NA);
951         static_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_udp);
952
953         /* Source port */
954         source_port = tvb_get_ntohs(tvb, offset);
955         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
956         offset += 2;
957
958         /* Dest port */
959         dest_port = tvb_get_ntohs(tvb, offset);
960         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
961         offset += 2;
962
963         /* Set proper length for subtree */
964         proto_item_set_len(root_ti, offset-tree_start_offset);
965
966         /* Add summary to root item */
967         proto_item_append_text(root_ti, " (%u -> %u)", source_port, dest_port);
968     }
969
970     /* RTP static */
971     if (p_pdcp_info->profile == 1) {
972         proto_tree *static_rtp_tree;
973         proto_item *root_ti;
974         guint32    ssrc;
975
976         /* Create static RTP subtree */
977         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_rtp, tvb, offset, 4, ENC_NA);
978         static_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_rtp);
979
980         /* SSRC */
981         ssrc = tvb_get_ntohl(tvb, offset);
982         proto_tree_add_item(static_rtp_tree, hf_pdcp_lte_rohc_static_rtp_ssrc, tvb, offset, 4, FALSE);
983         offset += 4;
984
985         /* Add summary to root item */
986         proto_item_append_text(root_ti, " (SSRC=%u)", ssrc);
987     }
988
989
990     /* Dynamic chain */
991     if (dynamic_chain_present) {
992         offset = dissect_pdcp_dynamic_chain(tree,
993                                             root_item,
994                                             tvb,
995                                             offset,
996                                             p_pdcp_info,
997                                             pinfo);
998     }
999
1000     return offset;
1001 }
1002
1003
1004
1005 static int dissect_pdcp_feedback_feedback1(proto_tree *tree,
1006                                            proto_item *item,
1007                                            tvbuff_t *tvb,
1008                                            int offset,
1009                                            struct pdcp_lte_info *p_pdcp_info _U_,
1010                                            packet_info *pinfo)
1011 {
1012     guint8 sn;
1013
1014     proto_item_append_text(item, " (type 1)");
1015
1016     /* TODO: profile-specific */
1017     sn = tvb_get_guint8(tvb, offset);
1018     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback1, tvb, offset, 1, FALSE);
1019     offset++;
1020
1021     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1022
1023     return offset;
1024 }
1025
1026 /* Includes Large-CID, if present */
1027 static int dissect_pdcp_feedback_feedback2(proto_tree *tree,
1028                                            proto_item *item,
1029                                            tvbuff_t *tvb,
1030                                            int offset,
1031                                            int size,
1032                                            struct pdcp_lte_info *p_pdcp_info,
1033                                            packet_info *pinfo)
1034 {
1035     proto_item *ti;
1036     guint8  ack_type;
1037     guint8  mode;
1038     guint8  first_octet;
1039     guint16 sn;
1040     const char * full_mode_name;
1041     int size_remaining;
1042
1043     proto_item_append_text(item, " (type 2)");
1044
1045     /* Large CID */
1046     if (p_pdcp_info->large_cid_present) {
1047         offset = dissect_large_cid(tree, tvb, offset);
1048     }
1049
1050     /* Feedback2 hidden filter */
1051     ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback2, tvb, offset, -1, ENC_NA);
1052     PROTO_ITEM_SET_HIDDEN(ti);
1053
1054     /* Ack-type */
1055     first_octet = tvb_get_guint8(tvb, offset);
1056     ack_type = (first_octet & 0xc0) >> 6;
1057     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_ack_type, tvb, offset, 1, FALSE);
1058
1059     /* TODO: expert info on NACK? */
1060
1061     /* Mode */
1062     mode = (first_octet & 0x30) >> 4;
1063     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_mode, tvb, offset, 1, FALSE);
1064
1065     /* Show ACK-TYPE(Mode) in info column */
1066     full_mode_name = val_to_str_const(mode, rohc_mode_vals, "Error");
1067
1068     col_append_fstr(pinfo->cinfo, COL_INFO, " %s(%c)",
1069                     val_to_str_const(ack_type, feedback_ack_vals, "Unknown"),
1070                     full_mode_name[0]);
1071
1072     /* 11 bits of SN */
1073     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_sn, tvb, offset, 2, FALSE);
1074     sn = tvb_get_ntohs(tvb, offset) & 0x7ff;
1075     offset += 2;
1076
1077     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1078
1079     /* Loop over any remaining feedback options */
1080     size_remaining = size - 2;
1081
1082     while (tvb_length_remaining(tvb, offset) > 0) {
1083         guint8 option = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
1084         guint8 length = tvb_get_guint8(tvb, offset) & 0x0f;
1085         guint8 one_byte_value;
1086
1087         /* Preference setting controls showing option and lengths */
1088         if (global_pdcp_show_feedback_option_tag_length) {
1089             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option, tvb, offset, 1, FALSE);
1090             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_length, tvb, offset, 1, FALSE);
1091         }
1092         offset++;
1093         size_remaining--;
1094
1095         /* TODO: switch including missing option types */
1096         switch (option) {
1097             case 1:
1098                 /* CRC */
1099                 one_byte_value = tvb_get_guint8(tvb, offset);
1100                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_crc, tvb, offset, 1, FALSE);
1101                 col_append_fstr(pinfo->cinfo, COL_INFO, " CRC=%u ", one_byte_value);
1102                 break;
1103             case 2:
1104                 /* REJECT: TODO */
1105                 break;
1106             case 3:
1107                 /* SN-Not-Valid: TODO */
1108                 break;
1109             case 4:
1110                 /* SN */
1111                 one_byte_value = tvb_get_guint8(tvb, offset);
1112                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_sn, tvb, offset, 1, FALSE);
1113                 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u ", one_byte_value);
1114                 break;
1115             case 5:
1116                 /* Clock */
1117                 one_byte_value = tvb_get_guint8(tvb, offset);
1118                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_clock, tvb, offset, 1, FALSE);
1119                 col_append_fstr(pinfo->cinfo, COL_INFO, " Clock=%u ", one_byte_value);
1120                 break;
1121             case 6:
1122                 /* Jitter: TODO */
1123                 break;
1124             case 7:
1125                 /* Loss: TODO */
1126                 break;
1127
1128             default:
1129                 /* TODO: unhandled option */
1130                 break;
1131         }
1132
1133         /* Skip length */
1134         offset += length;
1135         size_remaining -= length;
1136     }
1137
1138     return offset;
1139 }
1140
1141
1142 /* Dissect a feedback packet.
1143    Return following offset */
1144 static int dissect_pdcp_feedback_packet(proto_tree *tree,
1145                                         proto_item *root_item,
1146                                         tvbuff_t *tvb,
1147                                         int offset,
1148                                         struct pdcp_lte_info *p_pdcp_info,
1149                                         packet_info *pinfo)
1150 {
1151     guint8 code;
1152     guint8 size;
1153     proto_item *ti;
1154     proto_item *feedback_ti;
1155     proto_tree *feedback_tree;
1156
1157     col_append_str(pinfo->cinfo, COL_INFO, " Feedback");
1158     proto_item_append_text(root_item, " (Feedback)");
1159
1160     /* Create feedback tree root */
1161     feedback_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback, tvb, offset, -1, ENC_NA);
1162     feedback_tree = proto_item_add_subtree(feedback_ti, ett_pdcp_packet);
1163
1164     /* Code */
1165     code = tvb_get_guint8(tvb, offset) & 0x07;
1166     ti = proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_code, tvb, offset, 1, FALSE);
1167     offset++;
1168
1169     /* Optional length field */
1170     if (code != 0) {
1171         proto_item_append_text(ti, " (length of feedback data)");
1172         size = code;
1173     }
1174     else {
1175         proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_size, tvb, offset, 1, FALSE);
1176         size = tvb_get_guint8(tvb, offset);
1177         offset++;
1178     }
1179
1180     /* Work out feedback type */
1181     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
1182          !p_pdcp_info->large_cid_present) {
1183
1184         /* Small CID */
1185         if (size == 1) {
1186             offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
1187         }
1188         else if ((size > 1) && ((tvb_get_guint8(tvb, offset) & 0xc0) == 0xc0)) {
1189             /* Add-CID here! */
1190             proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
1191             offset++;
1192
1193             if (size == 2) {
1194                 offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
1195             }
1196             else {
1197                 offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1198             }
1199         }
1200         else {
1201             offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1202         }
1203     }
1204     else {
1205         offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1206     }
1207
1208     return offset;
1209 }
1210
1211
1212 /* Dissect R-0 packet.
1213    Return following offset */
1214 static int dissect_pdcp_r_0_packet(proto_tree *tree,
1215                                    proto_item *root_item,
1216                                    tvbuff_t *tvb,
1217                                    int offset,
1218                                    struct pdcp_lte_info *p_pdcp_info,
1219                                    packet_info *pinfo)
1220 {
1221     guint8 sn;
1222
1223     col_append_str(pinfo->cinfo, COL_INFO, " R-0");
1224     proto_item_append_text(root_item, " (R-0)");
1225
1226     /* 6 bits of sn */
1227     sn = tvb_get_guint8(tvb, offset) & 0x3f;
1228     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_sn, tvb, offset, 1, FALSE);
1229     offset++;
1230
1231     /* Large CID */
1232     if (p_pdcp_info->large_cid_present) {
1233         offset = dissect_large_cid(tree, tvb, offset);
1234     }
1235
1236     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1237
1238     return offset;
1239 }
1240
1241
1242 /* Dissect R-0-CRC packet.
1243    Return following offset */
1244 static int dissect_pdcp_r_0_crc_packet(proto_tree *tree,
1245                                        proto_item *root_item,
1246                                        tvbuff_t *tvb,
1247                                        int offset,
1248                                        struct pdcp_lte_info *p_pdcp_info,
1249                                        packet_info *pinfo)
1250 {
1251     guint8 sn;
1252
1253     col_append_str(pinfo->cinfo, COL_INFO, " R-0-CRC");
1254     proto_item_append_text(root_item, " (R-0-CRC)");
1255
1256     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r_0_crc, tvb, offset, -1, ENC_NA);
1257
1258     /* 7 bits of sn */
1259     /* TODO: wrong!  Large-cid may be in-between!!!! */
1260     sn = tvb_get_guint8(tvb, offset) & 0x3f;
1261     offset++;
1262
1263     /* Large CID */
1264     if (p_pdcp_info->large_cid_present) {
1265         offset = dissect_large_cid(tree, tvb, offset);
1266     }
1267
1268     /* Conclude SN */
1269     sn = (sn << 1) + ((tvb_get_guint8(tvb, offset) & 0x80) >> 7);
1270     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_r0_crc_sn, tvb, offset, 1, sn);
1271
1272     /* 7 bit CRC */
1273     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_crc_crc, tvb, offset, 1, FALSE);
1274     offset++;
1275
1276     /* Show SN in info column */
1277     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1278
1279     return offset;
1280 }
1281
1282
1283 /* Dissect UO-0-CRC packet.
1284    Return following offset */
1285 static int dissect_pdcp_uo_0_packet(proto_tree *tree,
1286                                     proto_item *root_item,
1287                                     tvbuff_t *tvb,
1288                                     int offset,
1289                                     struct pdcp_lte_info *p_pdcp_info,
1290                                     packet_info *pinfo)
1291 {
1292     guint8 sn;
1293
1294     col_append_str(pinfo->cinfo, COL_INFO, " U0-0");
1295     proto_item_append_text(root_item, " (UO-0)");
1296
1297     /* SN */
1298     sn = (tvb_get_guint8(tvb, offset) & 0x78) >> 3;
1299     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_sn, tvb, offset, 1, FALSE);
1300
1301     /* CRC (3 bits) */
1302     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_crc, tvb, offset, 1, FALSE);
1303
1304     offset++;
1305
1306     /* Large CID */
1307     if (p_pdcp_info->large_cid_present) {
1308         offset = dissect_large_cid(tree, tvb, offset);
1309     }
1310
1311     /* Show SN in info column */
1312     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1313
1314     return offset;
1315 }
1316
1317
1318 /* Dissect R-1 packet.
1319    Return following offset */
1320 static int  dissect_pdcp_r_1_packet(proto_tree *tree,
1321                                     proto_item *root_item,
1322                                     tvbuff_t *tvb,
1323                                     int offset,
1324                                     struct pdcp_lte_info *p_pdcp_info,
1325                                     packet_info *pinfo)
1326 {
1327     col_append_str(pinfo->cinfo, COL_INFO, " R-1");
1328     proto_item_append_text(root_item, " (R-1)");
1329
1330     /* TODO: octet before large-cid */
1331     offset++;
1332
1333     /* Large CID */
1334     if (p_pdcp_info->large_cid_present) {
1335         offset = dissect_large_cid(tree, tvb, offset);
1336     }
1337
1338     if (p_pdcp_info->profile == 1) {
1339         /* TODO: */
1340     }
1341     else if (p_pdcp_info->profile == 2) {
1342         /* TODO: */
1343     }
1344
1345     return offset;
1346 }
1347
1348
1349 /* Dissect R-1-TS or R-1-ID packet.
1350    Return following offset */
1351 static int  dissect_pdcp_r_1_ts_or_id_packet(proto_tree *tree,
1352                                              proto_item *root_item,
1353                                              tvbuff_t *tvb,
1354                                              int offset,
1355                                              struct pdcp_lte_info *p_pdcp_info,
1356                                              packet_info *pinfo)
1357 {
1358     unsigned char T;
1359
1360     /* TODO: octet before large-cid */
1361     offset++;
1362
1363     /* Large CID */
1364     if (p_pdcp_info->large_cid_present) {
1365         offset = dissect_large_cid(tree, tvb, offset);
1366     }
1367
1368     /* T determines frame type */
1369     T = tvb_get_guint8(tvb, ++offset) >> 7;
1370     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type1_t, tvb, offset, 1, FALSE);
1371     if (T) {
1372         col_append_str(pinfo->cinfo, COL_INFO, " R-1-TS");
1373         proto_item_append_text(root_item, " (R-1-TS)");
1374     }
1375     else {
1376         col_append_str(pinfo->cinfo, COL_INFO, " R-1-ID");
1377         proto_item_append_text(root_item, " (R-1-ID)");
1378     }
1379
1380     if (p_pdcp_info->profile == 1) {
1381         /* TODO: */
1382     }
1383     else if (p_pdcp_info->profile == 2) {
1384         /* TODO: */
1385     }
1386
1387     return offset;
1388 }
1389
1390
1391 /* Dissect UO-1 packet.
1392    Return following offset */
1393 static int  dissect_pdcp_uo_1_packet(proto_tree *tree,
1394                                      proto_item *root_item,
1395                                      tvbuff_t *tvb,
1396                                      int offset,
1397                                      struct pdcp_lte_info *p_pdcp_info,
1398                                      packet_info *pinfo)
1399 {
1400     col_append_str(pinfo->cinfo, COL_INFO, " UO-1");
1401     proto_item_append_text(root_item, " (UO-1)");
1402
1403     /* TODO: octet before large-cid */
1404     offset++;
1405
1406     /* Large CID */
1407     if (p_pdcp_info->large_cid_present) {
1408         offset = dissect_large_cid(tree, tvb, offset);
1409     }
1410
1411     if (p_pdcp_info->profile == 1) {
1412         /* TODO: */
1413     }
1414     else if (p_pdcp_info->profile == 2) {
1415         /* TODO: */
1416     }
1417
1418     return offset;
1419 }
1420
1421
1422 /* Dissect UO-1-TS or UO-1-ID packet.
1423    Return following offset */
1424 static int  dissect_pdcp_uo_1_ts_or_id_packet(proto_tree *tree,
1425                                               proto_item *root_item,
1426                                               tvbuff_t *tvb,
1427                                               int offset,
1428                                               struct pdcp_lte_info *p_pdcp_info,
1429                                               packet_info *pinfo)
1430 {
1431     unsigned char T;
1432
1433     /* TODO: octet before large-cid */
1434     offset++;
1435
1436     /* Large CID */
1437     if (p_pdcp_info->large_cid_present) {
1438         offset = dissect_large_cid(tree, tvb, offset);
1439     }
1440
1441     /* T determines frame type */
1442     T = tvb_get_guint8(tvb, ++offset) >> 5;
1443     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type0_t, tvb, offset, 1, FALSE);
1444     if (T) {
1445         col_append_str(pinfo->cinfo, COL_INFO, " UO-1-TS");
1446         proto_item_append_text(root_item, " (UO-1-TS)");
1447     }
1448     else {
1449         col_append_str(pinfo->cinfo, COL_INFO, " UO-1-ID");
1450         proto_item_append_text(root_item, " (UO-1-ID)");
1451     }
1452
1453     if (p_pdcp_info->profile == 1) {
1454         /* TODO: */
1455     }
1456     else if (p_pdcp_info->profile == 2) {
1457         /* TODO: */
1458     }
1459
1460     return offset;
1461 }
1462
1463
1464
1465
1466
1467 /* Dissect UOR-2 packet.
1468    Return following offset */
1469 static int  dissect_pdcp_uor_2_packet(proto_tree *tree,
1470                                       proto_item *root_item,
1471                                       tvbuff_t *tvb,
1472                                       int offset,
1473                                       struct pdcp_lte_info *p_pdcp_info,
1474                                       packet_info *pinfo)
1475 {
1476     guint8 ts;
1477
1478     col_append_str(pinfo->cinfo, COL_INFO, " U0R-2");
1479     proto_item_append_text(root_item, " (UOR-2)");
1480
1481     /* TS straddles CID */
1482     ts = tvb_get_guint8(tvb, offset) & 0x1f;
1483     offset++;
1484
1485     /* Large CID */
1486     if (p_pdcp_info->large_cid_present) {
1487         offset = dissect_large_cid(tree, tvb, offset);
1488     }
1489
1490     /* Last bit of TS is here */
1491     ts = (ts << 1) | (tvb_get_guint8(tvb, offset) >> 7);
1492     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1493
1494     if (p_pdcp_info->profile == 1) {
1495         /* M */
1496         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, FALSE);
1497
1498         /* SN (6 bits) */
1499         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_sn, tvb, offset, 1, FALSE);
1500         offset++;
1501
1502         /* X (one bit) */
1503         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_x, tvb, offset, 1, FALSE);
1504
1505         /* TODO: CRC */
1506         offset++;
1507     }
1508     else if (p_pdcp_info->profile == 2) {
1509         /* TODO: */
1510         offset += 2;
1511     }
1512
1513     return offset;
1514 }
1515
1516
1517 /* Dissect UOR-2-TS or UOR-2-ID packet.
1518    Return following offset */
1519 static int  dissect_pdcp_uor_2_ts_or_id_packet(proto_tree *tree,
1520                                                proto_item *root_item,
1521                                                tvbuff_t *tvb,
1522                                                int offset,
1523                                                struct pdcp_lte_info *p_pdcp_info,
1524                                                packet_info *pinfo)
1525 {
1526     unsigned char T;
1527
1528     /* TODO: octet before large-cid.
1529        TODO: can't decode this until we know what T is,
1530              but T is after large-cid... */
1531     offset++;
1532
1533     /* T determines frame type */
1534     T = tvb_get_guint8(tvb, offset) >> 7;
1535     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type2_t, tvb, offset, 1, FALSE);
1536
1537     if (T) {
1538         col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-TS");
1539         proto_item_append_text(root_item, " (UOR-2-TS)");
1540     }
1541     else {
1542         col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-ID");
1543         proto_item_append_text(root_item, " (UOR-2-ID)");
1544     }
1545
1546
1547     if (T) {
1548         /* UOR-2-TS format */
1549
1550         /* TS */
1551         guint8 ts = tvb_get_guint8(tvb, offset) & 0x1f;
1552         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1553         offset++;
1554
1555         /* Large CID */
1556         if (p_pdcp_info->large_cid_present) {
1557             offset = dissect_large_cid(tree, tvb, offset);
1558         }
1559
1560         /* m */
1561         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, ts);
1562
1563         /* TODO: */
1564     }
1565     else {
1566         /* TODO: UOR-2-ID format */
1567
1568         /* IP-ID */
1569
1570         /* Large CID */
1571         if (p_pdcp_info->large_cid_present) {
1572             offset = dissect_large_cid(tree, tvb, offset);
1573         }
1574
1575         /* TODO: */
1576     }
1577
1578     if (p_pdcp_info->profile == 1) {
1579         /* TODO: */
1580     }
1581     else if (p_pdcp_info->profile == 2) {
1582         /* TODO: */
1583     }
1584
1585     return offset;
1586 }
1587
1588
1589
1590
1591 /* Show in the tree the config info attached to this frame, as generated fields */
1592 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1593                              pdcp_lte_info *p_pdcp_info)
1594 {
1595     proto_item *ti;
1596     proto_tree *configuration_tree;
1597     proto_item *configuration_ti = proto_tree_add_item(tree,
1598                                                        hf_pdcp_lte_configuration,
1599                                                        tvb, 0, 0, FALSE);
1600     configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1601
1602     /* Direction */
1603     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1604                              p_pdcp_info->direction);
1605     PROTO_ITEM_SET_GENERATED(ti);
1606
1607     /* Plane */
1608     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1609                              p_pdcp_info->plane);
1610     PROTO_ITEM_SET_GENERATED(ti);
1611
1612     /* UEId */
1613     if (p_pdcp_info->ueid != 0) {
1614         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
1615                                  p_pdcp_info->ueid);
1616         PROTO_ITEM_SET_GENERATED(ti);
1617     }
1618
1619     /* Channel type */
1620     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
1621                              p_pdcp_info->channelType);
1622     PROTO_ITEM_SET_GENERATED(ti);
1623     if (p_pdcp_info->channelId != 0) {
1624         /* Channel type */
1625         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
1626                                  p_pdcp_info->channelId);
1627         PROTO_ITEM_SET_GENERATED(ti);
1628     }
1629
1630
1631     /* User-plane-specific fields */
1632     if (p_pdcp_info->plane == USER_PLANE) {
1633
1634         /* No Header PDU */
1635         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1636                                  p_pdcp_info->no_header_pdu);
1637         PROTO_ITEM_SET_GENERATED(ti);
1638
1639         if (!p_pdcp_info->no_header_pdu) {
1640
1641             /* Seqnum length */
1642             ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1643                                      p_pdcp_info->seqnum_length);
1644             PROTO_ITEM_SET_GENERATED(ti);
1645         }
1646     }
1647
1648     /* ROHC compression */
1649     ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1650                                 p_pdcp_info->rohc_compression);
1651     PROTO_ITEM_SET_GENERATED(ti);
1652
1653     /* ROHC-specific settings */
1654     if (p_pdcp_info->rohc_compression) {
1655
1656         /* Show ROHC mode */
1657         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1658                                  p_pdcp_info->mode);
1659         PROTO_ITEM_SET_GENERATED(ti);
1660
1661         /* Show RND */
1662         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1663                                  p_pdcp_info->rnd);
1664         PROTO_ITEM_SET_GENERATED(ti);
1665
1666         /* UDP Checksum */
1667         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1668                                  p_pdcp_info->udp_checkum_present);
1669         PROTO_ITEM_SET_GENERATED(ti);
1670
1671         /* ROHC profile */
1672         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1673                                  p_pdcp_info->profile);
1674         PROTO_ITEM_SET_GENERATED(ti);
1675
1676         /* CID Inclusion Info */
1677         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1678                                  p_pdcp_info->cid_inclusion_info);
1679         PROTO_ITEM_SET_GENERATED(ti);
1680
1681         /* Large CID */
1682         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1683                                  p_pdcp_info->large_cid_present);
1684         PROTO_ITEM_SET_GENERATED(ti);
1685     }
1686
1687     /* Append summary to configuration root */
1688     proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1689                            val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1690                            val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1691
1692     if (p_pdcp_info->rohc_compression) {
1693         const char *mode = val_to_str_const(p_pdcp_info->mode, rohc_mode_vals, "Error");
1694         proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1695                                mode[0],
1696                                val_to_str_const(p_pdcp_info->profile, rohc_profile_vals, "Unknown"));
1697     }
1698     proto_item_append_text(configuration_ti, ")");
1699     PROTO_ITEM_SET_GENERATED(configuration_ti);
1700
1701     /* Show plane in info column */
1702     col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1703                     val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1704
1705 }
1706
1707
1708 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1709 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info  *p_pdcp_info)
1710 {
1711     dissector_handle_t rrc_handle = 0;
1712
1713     switch (p_pdcp_info->channelType)
1714     {
1715         case Channel_CCCH:
1716             if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1717                 rrc_handle = find_dissector("lte_rrc.ul_ccch");
1718             }
1719             else {
1720                 rrc_handle = find_dissector("lte_rrc.dl_ccch");
1721             }
1722             break;
1723         case Channel_PCCH:
1724             rrc_handle = find_dissector("lte-rrc.pcch");
1725             break;
1726         case Channel_BCCH:
1727             switch (p_pdcp_info->BCCHTransport) {
1728                 case BCH_TRANSPORT:
1729                     rrc_handle = find_dissector("lte_rrc.bcch_bch");
1730                     break;
1731                 case DLSCH_TRANSPORT:
1732                     rrc_handle = find_dissector("lte_rrc.bcch_dl_sch");
1733                     break;
1734             }
1735             break;
1736         case Channel_DCCH:
1737             if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1738                 rrc_handle = find_dissector("lte_rrc.ul_dcch");
1739             }
1740             else {
1741                 rrc_handle = find_dissector("lte_rrc.dl_dcch");
1742             }
1743             break;
1744
1745
1746         default:
1747             break;
1748     }
1749
1750     return rrc_handle;
1751 }
1752
1753
1754 /* Forwad declarations */
1755 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1756
1757 /* Heuristic dissection */
1758 static gboolean global_pdcp_lte_heur = FALSE;
1759
1760 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
1761 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1762                                      proto_tree *tree)
1763 {
1764     gint                 offset = 0;
1765     struct pdcp_lte_info *p_pdcp_lte_info;
1766     tvbuff_t             *pdcp_tvb;
1767     guint8               tag = 0;
1768     gboolean             infoAlreadySet = FALSE;
1769     gboolean             seqnumLengthTagPresent = FALSE;
1770
1771     /* This is a heuristic dissector, which means we get all the UDP
1772      * traffic not sent to a known dissector and not claimed by
1773      * a heuristic dissector called before us!
1774      */
1775
1776     if (!global_pdcp_lte_heur) {
1777         return FALSE;
1778     }
1779
1780     /* Do this again on re-dissection to re-discover offset of actual PDU */
1781
1782     /* Needs to be at least as long as:
1783        - the signature string
1784        - fixed header bytes
1785        - tag for data
1786        - at least one byte of PDCP PDU payload */
1787     if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(PDCP_LTE_START_STRING)+3+2)) {
1788         return FALSE;
1789     }
1790
1791     /* OK, compare with signature string */
1792     if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1793         return FALSE;
1794     }
1795     offset += (gint)strlen(PDCP_LTE_START_STRING);
1796
1797
1798     /* If redissecting, use previous info struct (if available) */
1799     p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1800     if (p_pdcp_lte_info == NULL) {
1801         /* Allocate new info struct for this frame */
1802         p_pdcp_lte_info = se_alloc0(sizeof(struct pdcp_lte_info));
1803         infoAlreadySet = FALSE;
1804     }
1805     else {
1806         infoAlreadySet = TRUE;
1807     }
1808
1809
1810     /* Read fixed fields */
1811     p_pdcp_lte_info->no_header_pdu = tvb_get_guint8(tvb, offset++);
1812     p_pdcp_lte_info->plane = tvb_get_guint8(tvb, offset++);
1813     p_pdcp_lte_info->rohc_compression = tvb_get_guint8(tvb, offset++);
1814
1815     /* Read optional fields */
1816     while (tag != PDCP_LTE_PAYLOAD_TAG) {
1817         /* Process next tag */
1818         tag = tvb_get_guint8(tvb, offset++);
1819         switch (tag) {
1820             case PDCP_LTE_SEQNUM_LENGTH_TAG:
1821                 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1822                 offset++;
1823                 seqnumLengthTagPresent = TRUE;
1824                 break;
1825             case PDCP_LTE_DIRECTION_TAG:
1826                 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1827                 offset++;
1828                 break;
1829             case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1830                 p_pdcp_lte_info->channelType = tvb_get_guint8(tvb, offset);
1831                 offset++;
1832                 break;
1833             case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1834                 p_pdcp_lte_info->BCCHTransport = tvb_get_guint8(tvb, offset);
1835                 offset++;
1836                 break;
1837             case PDCP_LTE_ROHC_IP_VERSION_TAG:
1838                 p_pdcp_lte_info->rohc_ip_version = tvb_get_ntohs(tvb, offset);
1839                 offset += 2;
1840                 break;
1841             case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1842                 p_pdcp_lte_info->cid_inclusion_info = tvb_get_guint8(tvb, offset);
1843                 offset++;
1844                 break;
1845             case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1846                 p_pdcp_lte_info->large_cid_present = tvb_get_guint8(tvb, offset);
1847                 offset++;
1848                 break;
1849             case PDCP_LTE_ROHC_MODE_TAG:
1850                 p_pdcp_lte_info->mode = tvb_get_guint8(tvb, offset);
1851                 offset++;
1852                 break;
1853             case PDCP_LTE_ROHC_RND_TAG:
1854                 p_pdcp_lte_info->rnd = tvb_get_guint8(tvb, offset);
1855                 offset++;
1856                 break;
1857             case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1858                 p_pdcp_lte_info->udp_checkum_present = tvb_get_guint8(tvb, offset);
1859                 offset++;
1860                 break;
1861             case PDCP_LTE_ROHC_PROFILE_TAG:
1862                 p_pdcp_lte_info->profile = tvb_get_ntohs(tvb, offset);
1863                 offset += 2;
1864                 break;
1865
1866             case PDCP_LTE_PAYLOAD_TAG:
1867                 /* Have reached data, so get out of loop */
1868                 continue;
1869
1870             default:
1871                 /* It must be a recognised tag */
1872                 return FALSE;
1873         }
1874     }
1875
1876     if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1877         /* Conditional field is not present */
1878         return FALSE;
1879     }
1880
1881     if (!infoAlreadySet) {
1882         /* Store info in packet */
1883         p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
1884     }
1885
1886     /**************************************/
1887     /* OK, now dissect as PDCP LTE        */
1888
1889     /* Create tvb that starts at actual PDCP PDU */
1890     pdcp_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
1891     dissect_pdcp_lte(pdcp_tvb, pinfo, tree);
1892     return TRUE;
1893 }
1894
1895
1896 /******************************/
1897 /* Main dissection function.  */
1898 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1899 {
1900     const char         *mode;
1901     proto_tree         *pdcp_tree = NULL;
1902     proto_item         *root_ti = NULL;
1903     proto_tree         *rohc_tree = NULL;
1904     proto_item         *rohc_ti = NULL;
1905     gint               offset = 0;
1906     gint               rohc_offset;
1907     struct pdcp_lte_info  *p_pdcp_info;
1908     guint8             base_header_byte;
1909     gboolean           udp_checksum_needed = TRUE;
1910     gboolean           ip_id_needed = TRUE;
1911
1912     /* Append this protocol name rather than replace. */
1913     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1914
1915     /* Create pdcp tree. */
1916     if (tree) {
1917         root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, FALSE);
1918         pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1919     }
1920
1921
1922     /* Look for attached packet info! */
1923     p_pdcp_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1924     /* Can't dissect anything without it... */
1925     if (p_pdcp_info == NULL) {
1926         return;
1927     }
1928
1929
1930     /* Set mode string */
1931     mode = val_to_str_const(p_pdcp_info->mode, rohc_mode_vals, "Error");
1932
1933     /* Show configuration (attached packet) info in tree */
1934     if (pdcp_tree) {
1935         show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1936     }
1937
1938     /* Show ROHC mode */
1939     if (p_pdcp_info->rohc_compression) {
1940         col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1941     }
1942
1943
1944     /* Handle PDCP header (if present) */
1945     if (!p_pdcp_info->no_header_pdu) {
1946
1947         /* TODO: shouldn't need to initialise this one!! */
1948         guint16  seqnum = 0;
1949         gboolean seqnum_set = FALSE;
1950
1951         /*****************************/
1952         /* Signalling plane messages */
1953         if (p_pdcp_info->plane == SIGNALING_PLANE) {
1954             guint32 mac;
1955             guint32 data_length;
1956
1957             /* 5-bit sequence number */
1958             seqnum = tvb_get_guint8(tvb, offset) & 0x1f;
1959             seqnum_set = TRUE;
1960             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, FALSE);
1961             write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
1962             offset++;
1963
1964             /* RRC data is all but last 4 bytes.
1965                Call lte-rrc dissector (according to direction and channel type) */
1966             if (global_pdcp_dissect_signalling_plane_as_rrc) {
1967                 /* Get appropriate dissector handle */
1968                 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1969
1970                 if (rrc_handle != 0) {
1971                     /* Call RRC dissector if have one */
1972                     tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
1973                                                            tvb_length_remaining(tvb, offset) - 4,
1974                                                            tvb_length_remaining(tvb, offset) - 4);
1975                     call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
1976                 }
1977                 else {
1978                      /* Just show data */
1979                         proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1980                                             tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1981                 }
1982             }
1983             else {
1984                 /* Just show as unparsed data */
1985                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1986                                     tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1987             }
1988
1989             data_length = tvb_length_remaining(tvb, offset) - 4;
1990             offset += data_length;
1991
1992             /* Last 4 bytes are MAC */
1993             mac = tvb_get_ntohl(tvb, offset);
1994             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, tvb, offset, 4, FALSE);
1995             offset += 4;
1996
1997             col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
1998                             mac, data_length);
1999
2000         }
2001         else if (p_pdcp_info->plane == USER_PLANE) {
2002
2003             /**********************************/
2004             /* User-plane messages            */
2005             gboolean pdu_type = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2006
2007             /* Data/Control flag */
2008             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, FALSE);
2009
2010             if (pdu_type == 1) {
2011                 /*****************************/
2012                 /* Use-plane Data            */
2013
2014                 /* Number of sequence number bits depends upon config */
2015                 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_7_BITS) {
2016                     seqnum = tvb_get_guint8(tvb, offset) & 0x7f;
2017                     seqnum_set = TRUE;
2018                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, FALSE);
2019                     offset++;
2020                 }
2021                 else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2022                     proto_item *ti;
2023                     guint8 reserved_value;
2024
2025                     /* 3 reserved bits */
2026                     ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, FALSE);
2027                     reserved_value = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
2028
2029                     /* Complain if not 0 */
2030                     if (reserved_value != 0) {
2031                         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2032                                                "Reserved bits have value 0x%x - should be 0x0",
2033                                                reserved_value);
2034                     }
2035
2036                     /* 12-bit sequence number */
2037                     seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
2038                     seqnum_set = TRUE;
2039                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, FALSE);
2040                     offset += 2;
2041                 }
2042                 else {
2043                     /* Not a recognised data format!!!!! */
2044                     return;
2045                 }
2046
2047                 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
2048             }
2049             else {
2050                 /*******************************/
2051                 /* User-plane Control messages */
2052                 guint8 control_pdu_type = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
2053                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, FALSE);
2054
2055                 switch (control_pdu_type) {
2056                     case 0:    /* PDCP status report */
2057                         {
2058                             guint16 fms;
2059                             guint   not_received = 0;
2060                             guint   sn;
2061                             proto_tree *bitmap_tree;
2062                             proto_item *bitmap_ti = NULL;
2063
2064                             /* First-Missing-Sequence SN */
2065                             fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
2066                             sn = (fms + 1) % 4096;
2067                             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
2068                                                 offset, 2, FALSE);
2069                             offset += 2;
2070
2071                             /* Bitmap tree */
2072                             if (tvb_length_remaining(tvb, offset) > 0) {
2073                                 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
2074                                                                 offset, -1, FALSE);
2075                                 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_rohc_report_bitmap);
2076
2077
2078                                 /* For each byte... */
2079                                 for ( ; tvb_length_remaining(tvb, offset); offset++) {
2080                                     guint bit_offset = 0;
2081                                     /* .. look for error (0) in each bit */
2082                                     for ( ; bit_offset < 8; bit_offset++) {
2083                                         if ((tvb_get_guint8(tvb, offset) >> (7-bit_offset) & 0x1) == 0) {
2084                                             proto_tree_add_boolean_format_value(bitmap_tree, hf_pdcp_lte_bitmap_not_received, tvb, offset, 1, TRUE,
2085                                                                                 " (SN=%u)", sn);
2086                                             not_received++;
2087                                         }
2088                                         sn = (sn + 1) % 4096;
2089                                     }
2090                                 }
2091                             }
2092
2093                             if (bitmap_ti != NULL) {
2094                                 proto_item_append_text(bitmap_ti, " (not-received=%u)", not_received);
2095                             }
2096                             write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
2097                                                     fms, not_received);
2098                         }
2099                         return;
2100
2101                     case 1:     /* ROHC Feedback */
2102                         offset++;
2103                         break;  /* Drop-through to dissect feedback */
2104
2105                     default:    /* Reserved */
2106                         return;
2107                 }
2108             }
2109         }
2110         else {
2111             /* Invalid plane setting...! */
2112             write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
2113                                      p_pdcp_info->plane);
2114             return;
2115         }
2116
2117         /* For now, only do sequence analysis if RLC wasn't present in the frame */
2118         /* This can be fixed once RLC does re-assembly... */
2119         if (global_pdcp_check_sequence_numbers && seqnum_set &&
2120              (p_get_proto_data(pinfo->fd, proto_rlc_lte) == NULL)) {
2121
2122             checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
2123                                      (guint16)seqnum, pdcp_tree);
2124         }
2125
2126     }
2127     else {
2128         /* Show that its a no-header PDU */
2129         write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
2130     }
2131
2132
2133     /* If not compressed with ROHC, show as user-plane data */
2134     if (!p_pdcp_info->rohc_compression) {
2135         if (tvb_length_remaining(tvb, offset) > 0) {
2136             if (p_pdcp_info->plane == USER_PLANE) {
2137                 if (global_pdcp_dissect_user_plane_as_ip) {
2138                     tvbuff_t *payload_tvb = tvb_new_subset_remaining(tvb, offset);
2139                     switch (tvb_get_guint8(tvb, offset) & 0xf0) {
2140                         case 0x40:
2141                             call_dissector_only(ip_handle, payload_tvb, pinfo, pdcp_tree);
2142                             break;
2143                         case 0x60:
2144                             call_dissector_only(ipv6_handle, payload_tvb, pinfo, pdcp_tree);
2145                             break;
2146                         default:
2147                             call_dissector_only(data_handle, payload_tvb, pinfo, pdcp_tree);
2148                             break;
2149                     }
2150                 }
2151                 else {
2152                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, tvb, offset, -1, ENC_NA);
2153                 }
2154             }
2155             else {
2156                 if (global_pdcp_dissect_signalling_plane_as_rrc) {
2157                     /* Get appropriate dissector handle */
2158                     dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
2159
2160                     if (rrc_handle != 0) {
2161                         /* Call RRC dissector if have one */
2162                         tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
2163                                                                tvb_length_remaining(tvb, offset),
2164                                                                tvb_length_remaining(tvb, offset));
2165                         call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
2166                     }
2167                     else {
2168                          /* Just show data */
2169                          proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
2170                                              tvb_length_remaining(tvb, offset), ENC_NA);
2171                     }
2172                 }
2173                 else {
2174                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset, -1, ENC_NA);
2175                 }
2176             }
2177
2178             write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
2179                                      tvb_length_remaining(tvb, offset));
2180         }
2181         return;
2182     }
2183
2184
2185     /***************************/
2186     /* ROHC packets            */
2187     /***************************/
2188
2189     col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2190                     val_to_str_const(p_pdcp_info->profile, rohc_profile_vals, "Unknown"));
2191
2192     /* Only attempt ROHC if configured to */
2193     if (!global_pdcp_dissect_rohc) {
2194         return;
2195     }
2196
2197     /* Create pdcp tree. */
2198     if (pdcp_tree) {
2199         rohc_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_rohc, tvb, offset, -1, ENC_NA);
2200         rohc_tree = proto_item_add_subtree(rohc_ti, ett_pdcp_rohc);
2201     }
2202
2203     rohc_offset = offset;
2204
2205     /* Skip any leading padding octets (11100000) */
2206     while (tvb_get_guint8(tvb, offset) == 0xe0) {
2207         offset++;
2208     }
2209     if (offset > rohc_offset) {
2210         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_padding, tvb, rohc_offset,
2211                             offset-rohc_offset, ENC_NA);
2212     }
2213
2214     /* Add-CID octet */
2215     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
2216         !p_pdcp_info->large_cid_present)
2217     {
2218         if (((tvb_get_guint8(tvb, offset) >> 4) & 0x0f) == 0x0e) {
2219             proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
2220             offset++;
2221         }
2222         else {
2223             /* Assume CID value of 0 if field absent */
2224             proto_item *ti = proto_tree_add_uint(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 0, 0);
2225             PROTO_ITEM_SET_GENERATED(ti);
2226         }
2227     }
2228
2229     /* Now look at first octet of base header and identify packet type */
2230     base_header_byte = tvb_get_guint8(tvb, offset);
2231
2232     /* IR (1111110) */
2233     if ((base_header_byte & 0xfe) == 0xfc) {
2234         offset = dissect_pdcp_ir_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2235         udp_checksum_needed = FALSE;
2236         ip_id_needed = FALSE;
2237     }
2238
2239     /* IRDYN (11111000) */
2240     else if (base_header_byte == 0xf8) {
2241         offset = dissect_pdcp_irdyn_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2242         udp_checksum_needed = FALSE;
2243         ip_id_needed = FALSE;
2244     }
2245
2246     /* Feedback (begins with 11110) */
2247     else if (((base_header_byte & 0xf8) >> 3) == 0x1e) {
2248         offset = dissect_pdcp_feedback_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2249         return;
2250     }
2251
2252     /* Packet type 0 (0) */
2253     else if ((base_header_byte & 0x80) == 0) {
2254
2255         /* TODO: decide type based upon:
2256            - mode
2257            - 2nd bit
2258            - length remaining (taking into account large-cid) */
2259
2260         /* R-0 begins with 00 */
2261         if (((base_header_byte & 0xc0) == 0) &&
2262              (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
2263
2264             offset = dissect_pdcp_r_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2265         }
2266
2267         /* R-0-CRC begins with 01 */
2268         else if ((((base_header_byte & 0x40) >> 6) == 1) &&
2269                   (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
2270
2271             offset = dissect_pdcp_r_0_crc_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2272         }
2273
2274         else {
2275             offset = dissect_pdcp_uo_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2276         }
2277     }
2278
2279     /* Packet type 1 (10) */
2280     else if (((base_header_byte & 0xc0) >> 6) == 2) {
2281
2282         switch (p_pdcp_info->mode) {
2283
2284             case RELIABLE_BIDIRECTIONAL:
2285                  /* R-1 if !(ipv4 && rand) */
2286                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
2287                       (!p_pdcp_info->rnd))) {
2288                     offset = dissect_pdcp_r_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2289                     return;
2290                  }
2291                 else {
2292                     /* Whether its R-1-ID or R-1-TS depends upon T bit */
2293                     dissect_pdcp_r_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2294                     return;
2295                 }
2296                 break;
2297
2298             case UNIDIRECTIONAL:
2299             case OPTIMISTIC_BIDIRECTIONAL:
2300                  /* UO-1 if !(ipv4 && rand) */
2301                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
2302                       (!p_pdcp_info->rnd))) {
2303
2304                     dissect_pdcp_uo_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2305                  } else {
2306                     /* Whether its UO-1-ID or UO-1-TS depends upon T bit */
2307                     dissect_pdcp_uo_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2308                  }
2309
2310                 return;
2311
2312         }
2313     }
2314
2315     /* Packet type 2 (110) */
2316     else if (((base_header_byte & 0xe0) >> 5) == 6) {
2317
2318         /* UOR-2 if !(ipv4 && rand) */
2319         if (!((p_pdcp_info->rohc_ip_version == 4) &&
2320               (!p_pdcp_info->rnd))) {
2321
2322             dissect_pdcp_uor_2_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2323         }
2324         else {
2325             /* Whether its UOR-2-ID or UOR-2-TS depends upon T bit */
2326             dissect_pdcp_uor_2_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2327             return;
2328         }
2329     }
2330
2331     /* Segment (1111111) */
2332     else if ((base_header_byte & 0xfe) == 0xfe) {
2333         /* TODO: */
2334         return;
2335     }
2336
2337
2338     /* Fields beyond base header */
2339
2340     /* These 2 fields not present for IR, IR-DYN frames */
2341
2342     /* IP-ID */
2343     if (p_pdcp_info->rnd && ip_id_needed) {
2344         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_ip_id, tvb, offset, 2, FALSE);
2345         offset += 2;
2346     }
2347
2348     /* UDP Checksum */
2349     if (p_pdcp_info->udp_checkum_present && udp_checksum_needed) {
2350         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_udp_checksum, tvb, offset, 2, FALSE);
2351         offset += 2;
2352     }
2353
2354     /* Payload */
2355     if (tvb_reported_length_remaining(tvb, offset) > 0) {
2356         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_payload, tvb, offset, -1, ENC_NA);
2357     }
2358 }
2359
2360
2361 /* Initializes the hash table and the mem_chunk area each time a new
2362  * file is loaded or re-loaded in wireshark */
2363 static void
2364 pdcp_lte_init_protocol(void)
2365 {
2366     /* Destroy any existing hashes. */
2367     if (pdcp_sequence_analysis_channel_hash) {
2368         g_hash_table_destroy(pdcp_sequence_analysis_channel_hash);
2369     }
2370     if (pdcp_lte_frame_sequence_analysis_report_hash) {
2371         g_hash_table_destroy(pdcp_lte_frame_sequence_analysis_report_hash);
2372     }
2373
2374
2375     /* Now create them over */
2376     pdcp_sequence_analysis_channel_hash = g_hash_table_new(pdcp_channel_hash_func, pdcp_channel_equal);
2377     pdcp_lte_frame_sequence_analysis_report_hash = g_hash_table_new(pdcp_frame_hash_func, pdcp_frame_equal);
2378 }
2379
2380
2381
2382 void proto_register_pdcp(void)
2383 {
2384     static hf_register_info hf[] =
2385     {
2386         { &hf_pdcp_lte_configuration,
2387             { "Configuration",
2388               "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2389               "Configuration info passed into dissector", HFILL
2390             }
2391         },
2392
2393         { &hf_pdcp_lte_rohc_compression,
2394             { "ROHC Compression",
2395               "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2396               NULL, HFILL
2397             }
2398         },
2399         { &hf_pdcp_lte_rohc_mode,
2400             { "ROHC Mode",
2401               "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2402               NULL, HFILL
2403             }
2404         },
2405         { &hf_pdcp_lte_rohc_rnd,
2406             { "RND",  /* TODO: true/false vals? */
2407               "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
2408               "RND of outer ip header", HFILL
2409             }
2410         },
2411         { &hf_pdcp_lte_rohc_udp_checksum_present,
2412             { "UDP Checksum",  /* TODO: true/false vals? */
2413               "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2414               "UDP Checksum present", HFILL
2415             }
2416         },
2417         { &hf_pdcp_lte_direction,
2418             { "Direction",
2419               "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2420               "Direction of message", HFILL
2421             }
2422         },
2423         { &hf_pdcp_lte_ueid,
2424             { "UE",
2425               "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2426               "UE Identifier", HFILL
2427             }
2428         },
2429         { &hf_pdcp_lte_channel_type,
2430             { "Channel type",
2431               "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
2432               NULL, HFILL
2433             }
2434         },
2435         { &hf_pdcp_lte_channel_id,
2436             { "Channel Id",
2437               "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
2438               NULL, HFILL
2439             }
2440         },
2441         { &hf_pdcp_lte_rohc_profile,
2442             { "ROHC profile",
2443               "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2444               "ROHC Mode", HFILL
2445             }
2446         },
2447         { &hf_pdcp_lte_no_header_pdu,
2448             { "No Header PDU",
2449               "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
2450               NULL, HFILL
2451             }
2452         },
2453         { &hf_pdcp_lte_plane,
2454             { "Plane",
2455               "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2456               NULL, HFILL
2457             }
2458         },
2459         { &hf_pdcp_lte_seqnum_length,
2460             { "Seqnum length",
2461               "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2462               "Sequence Number Length", HFILL
2463             }
2464         },
2465
2466
2467         { &hf_pdcp_lte_cid_inclusion_info,
2468             { "CID Inclusion Info",
2469               "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
2470               NULL, HFILL
2471             }
2472         },
2473         { &hf_pdcp_lte_large_cid_present,
2474             { "Large CID Present",
2475               "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2476               NULL, HFILL
2477             }
2478         },
2479
2480         { &hf_pdcp_lte_seq_num_5,
2481             { "Seq Num",
2482               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
2483               "PDCP Seq num", HFILL
2484             }
2485         },
2486         { &hf_pdcp_lte_seq_num_7,
2487             { "Seq Num",
2488               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
2489               "PDCP Seq num", HFILL
2490             }
2491         },
2492         { &hf_pdcp_lte_reserved3,
2493             { "Reserved",
2494               "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2495               "3 reserved bits", HFILL
2496             }
2497         },
2498         { &hf_pdcp_lte_seq_num_12,
2499             { "Seq Num",
2500               "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2501               "PDCP Seq num", HFILL
2502             }
2503         },
2504         { &hf_pdcp_lte_signalling_data,
2505             { "Signalling Data",
2506               "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2507               NULL, HFILL
2508             }
2509         },
2510         { &hf_pdcp_lte_mac,
2511             { "MAC",
2512               "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
2513               NULL, HFILL
2514             }
2515         },
2516         { &hf_pdcp_lte_data_control,
2517             { "PDU Type",
2518               "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
2519               NULL, HFILL
2520             }
2521         },
2522         { &hf_pdcp_lte_user_plane_data,
2523             { "User-Plane Data",
2524               "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2525               NULL, HFILL
2526             }
2527         },
2528         { &hf_pdcp_lte_control_pdu_type,
2529             { "Control PDU Type",
2530               "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2531               NULL, HFILL
2532             }
2533         },
2534         { &hf_pdcp_lte_fms,
2535             { "First Missing Sequence Number",
2536               "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2537               "First Missing PDCP Sequence Number", HFILL
2538             }
2539         },
2540         { &hf_pdcp_lte_bitmap,
2541             { "Bitmap",
2542               "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2543               "Status report bitmap (0=error, 1=OK)", HFILL
2544             }
2545         },
2546         { &hf_pdcp_lte_bitmap_not_received,
2547             { "Not Received",
2548               "pdcp-lte.bitmap.error", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2549               "Status report PDU error", HFILL
2550             }
2551         },
2552
2553
2554         { &hf_pdcp_lte_sequence_analysis,
2555             { "Sequence Analysis",
2556               "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2557               NULL, HFILL
2558             }
2559         },
2560         { &hf_pdcp_lte_sequence_analysis_ok,
2561             { "OK",
2562               "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2563               NULL, HFILL
2564             }
2565         },
2566         { &hf_pdcp_lte_sequence_analysis_previous_frame,
2567             { "Previous frame for channel",
2568               "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2569               NULL, HFILL
2570             }
2571         },
2572         { &hf_pdcp_lte_sequence_analysis_expected_sn,
2573             { "Expected SN",
2574               "pdcp-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2575               NULL, HFILL
2576             }
2577         },
2578         { &hf_pdcp_lte_sequence_analysis_skipped,
2579             { "Skipped frames",
2580               "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2581               NULL, HFILL
2582             }
2583         },
2584         { &hf_pdcp_lte_sequence_analysis_repeated,
2585             { "Repeated frame",
2586               "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2587               NULL, HFILL
2588             }
2589         },
2590
2591         { &hf_pdcp_lte_rohc,
2592             { "ROHC Message",
2593               "pdcp-lte.rohc", FT_NONE, BASE_NONE, NULL, 0,
2594               NULL, HFILL
2595             }
2596         },
2597
2598         { &hf_pdcp_lte_rohc_padding,
2599             { "Padding",
2600               "pdcp-lte.rohc.padding", FT_NONE, BASE_NONE, NULL, 0,
2601               "ROHC Padding", HFILL
2602             }
2603         },
2604         { &hf_pdcp_lte_rohc_r_0_crc,
2605             { "R-0-CRC Packet",
2606               "pdcp-lte.r-0-crc", FT_NONE, BASE_NONE, NULL, 0,
2607               NULL, HFILL
2608             }
2609         },
2610         { &hf_pdcp_lte_rohc_feedback,
2611             { "Feedback",
2612               "pdcp-lte.rohc.feedback", FT_NONE, BASE_NONE, NULL, 0,
2613               "Feedback Packet", HFILL
2614             }
2615         },
2616         { &hf_pdcp_lte_rohc_type0_t,
2617             { "T",
2618               "pdcp-lte.rohc.t0.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x20,
2619               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2620             }
2621         },
2622         { &hf_pdcp_lte_rohc_type1_t,
2623             { "T",
2624               "pdcp-lte.rohc.t1.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2625               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2626             }
2627         },
2628         { &hf_pdcp_lte_rohc_type2_t,
2629             { "T",
2630               "pdcp-lte.rohc.t2.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2631               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2632             }
2633         },
2634         { &hf_pdcp_lte_rohc_d,
2635             { "D",
2636               "pdcp-lte.rohc.d", FT_UINT8, BASE_HEX, NULL, 0x01,
2637               "Indicates whether Dynamic chain is present", HFILL
2638             }
2639         },
2640         { &hf_pdcp_lte_rohc_ir_crc,
2641             { "CRC",
2642               "pdcp-lte.rohc.ir.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
2643               "8-bit CRC", HFILL
2644             }
2645         },
2646
2647         { &hf_pdcp_lte_rohc_static_ipv4,
2648             { "Static IPv4 chain",
2649               "pdcp-lte.rohc.static.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2650               NULL, HFILL
2651             }
2652         },
2653         { &hf_pdcp_lte_rohc_ip_version,
2654             { "IP Version",
2655               "pdcp-lte.rohc.ip-version", FT_UINT8, BASE_HEX, NULL, 0xf0,
2656               NULL, HFILL
2657             }
2658         },
2659         /* TODO: create/use value_string */
2660         { &hf_pdcp_lte_rohc_ip_protocol,
2661             { "IP Protocol",
2662               "pdcp-lte.rohc.ip-protocol", FT_UINT8, BASE_DEC, VALS(ip_protocol_vals), 0x0,
2663               NULL, HFILL
2664             }
2665         },
2666         { &hf_pdcp_lte_rohc_ip_src,
2667             { "IP Source address",
2668               "pdcp-lte.rohc.ip-src", FT_IPv4, BASE_NONE, NULL, 0x0,
2669               NULL, HFILL
2670             }
2671         },
2672         { &hf_pdcp_lte_rohc_ip_dst,
2673             { "IP Destination address",
2674               "pdcp-lte.rohc.ip-dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2675               NULL, HFILL
2676             }
2677         },
2678
2679         { &hf_pdcp_lte_rohc_static_udp,
2680             { "Static UDP chain",
2681               "pdcp-lte.rohc.static.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2682               NULL, HFILL
2683             }
2684         },
2685         { &hf_pdcp_lte_rohc_static_udp_src_port,
2686             { "Static UDP source port",
2687               "pdcp-lte.rohc.static.udp.src-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2688               NULL, HFILL
2689             }
2690         },
2691         { &hf_pdcp_lte_rohc_static_udp_dst_port,
2692             { "Static UDP destination port",
2693               "pdcp-lte.rohc.static.udp.dst-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2694               NULL, HFILL
2695             }
2696         },
2697         { &hf_pdcp_lte_rohc_static_rtp,
2698             { "Static RTP chain",
2699               "pdcp-lte.rohc.static.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2700               NULL, HFILL
2701             }
2702         },
2703         { &hf_pdcp_lte_rohc_static_rtp_ssrc,
2704             { "SSRC",
2705               "pdcp-lte.rohc.static.rtp.ssrc", FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2706               "Static RTP chain SSRC", HFILL
2707             }
2708         },
2709
2710         { &hf_pdcp_lte_rohc_dynamic_ipv4,
2711             { "Dynamic IPv4 chain",
2712               "pdcp-lte.rohc.dynamic.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2713               NULL, HFILL
2714             }
2715         },
2716         { &hf_pdcp_lte_rohc_dynamic_ipv4_tos,
2717             { "ToS",
2718               "pdcp-lte.rohc.ip.tos", FT_UINT8, BASE_HEX, NULL, 0x0,
2719               "IP Type of Service", HFILL
2720             }
2721         },
2722         { &hf_pdcp_lte_rohc_dynamic_ipv4_ttl,
2723             { "TTL",
2724               "pdcp-lte.rohc.ip.ttl", FT_UINT8, BASE_HEX, NULL, 0x0,
2725               "IP Time To Live", HFILL
2726             }
2727         },
2728         { &hf_pdcp_lte_rohc_dynamic_ipv4_id,
2729             { "IP-ID",
2730               "pdcp-lte.rohc.ip.id", FT_UINT8, BASE_HEX, NULL, 0x0,
2731               "IP ID", HFILL
2732             }
2733         },
2734         { &hf_pdcp_lte_rohc_dynamic_ipv4_df,
2735             { "Don't Fragment",
2736               "pdcp-lte.rohc.ip.df", FT_UINT8, BASE_HEX, NULL, 0x80,
2737               "IP Don't Fragment flag", HFILL
2738             }
2739         },
2740         { &hf_pdcp_lte_rohc_dynamic_ipv4_rnd,
2741             { "Random IP-ID field",
2742               "pdcp-lte.rohc.ip.rnd", FT_UINT8, BASE_HEX, NULL, 0x40,
2743               NULL, HFILL
2744             }
2745         },
2746         { &hf_pdcp_lte_rohc_dynamic_ipv4_nbo,
2747             { "Network Byte Order IP-ID field",
2748               "pdcp-lte.rohc.ip.nbo", FT_UINT8, BASE_HEX, NULL, 0x20,
2749               NULL, HFILL
2750             }
2751         },
2752         { &hf_pdcp_lte_rohc_dynamic_udp,
2753             { "Dynamic UDP chain",
2754               "pdcp-lte.rohc.dynamic.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2755               NULL, HFILL
2756             }
2757         },
2758         { &hf_pdcp_lte_rohc_dynamic_udp_checksum,
2759             { "UDP Checksum",
2760               "pdcp-lte.rohc.dynamic.udp.checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2761               NULL, HFILL
2762             }
2763         },
2764         { &hf_pdcp_lte_rohc_dynamic_udp_seqnum,
2765             { "UDP Sequence Number",
2766               "pdcp-lte.rohc.dynamic.udp.seqnum", FT_UINT16, BASE_HEX, NULL, 0x0,
2767               NULL, HFILL
2768             }
2769         },
2770
2771         { &hf_pdcp_lte_rohc_dynamic_rtp,
2772             { "Dynamic RTP chain",
2773               "pdcp-lte.rohc.dynamic.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2774               NULL, HFILL
2775             }
2776         },
2777         { &hf_pdcp_lte_rohc_dynamic_rtp_rx,
2778             { "RX",
2779               "pdcp-lte.rohc.dynamic.rtp.rx", FT_UINT8, BASE_DEC, NULL, 0x10,
2780               NULL, HFILL
2781             }
2782         },
2783         { &hf_pdcp_lte_rohc_dynamic_rtp_cc,
2784             { "Contributing CSRCs",
2785               "pdcp-lte.rohc.dynamic.rtp.cc", FT_UINT8, BASE_DEC, NULL, 0x0f,
2786               "Dynamic RTP chain CCs", HFILL
2787             }
2788         },
2789         { &hf_pdcp_lte_rohc_dynamic_rtp_seqnum,
2790             { "RTP Sequence Number",
2791               "pdcp-lte.rohc.dynamic.rtp.seqnum", FT_UINT16, BASE_DEC, NULL, 0x0,
2792               "Dynamic RTP chain Sequence Number", HFILL
2793             }
2794         },
2795         { &hf_pdcp_lte_rohc_dynamic_rtp_timestamp,
2796             { "RTP Timestamp",
2797               "pdcp-lte.rohc.dynamic.rtp.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2798               "Dynamic RTP chain Timestamp", HFILL
2799             }
2800         },
2801         { &hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
2802             { "Reserved",
2803               "pdcp-lte.rohc.dynamic.rtp.reserved3", FT_UINT8, BASE_HEX, NULL, 0xc0,
2804               "Reserved bits", HFILL
2805             }
2806         },
2807         { &hf_pdcp_lte_rohc_dynamic_rtp_x,
2808             { "X",
2809               "pdcp-lte.rohc.dynamic.rtp.x", FT_UINT8, BASE_DEC, NULL, 0x10,
2810               NULL, HFILL
2811             }
2812         },
2813         { &hf_pdcp_lte_rohc_dynamic_rtp_mode,
2814             { "Mode",
2815               "pdcp-lte.rohc.dynamic.rtp.mode", FT_UINT8, BASE_HEX, VALS(rohc_mode_vals), 0x0c,
2816               NULL, HFILL
2817             }
2818         },
2819         { &hf_pdcp_lte_rohc_dynamic_rtp_tis,
2820             { "TIS",
2821               "pdcp-lte.rohc.dynamic.rtp.tis", FT_UINT8, BASE_HEX, NULL, 0x02,
2822               "Dynamic RTP chain TIS (indicates time_stride present)", HFILL
2823             }
2824         },
2825         { &hf_pdcp_lte_rohc_dynamic_rtp_tss,
2826             { "TSS",
2827               "pdcp-lte.rohc.dynamic.rtp.tss", FT_UINT8, BASE_HEX, NULL, 0x01,
2828               "Dynamic RTP chain TSS (indicates TS_stride present)", HFILL
2829             }
2830         },
2831         { &hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
2832             { "TS Stride",
2833               "pdcp-lte.rohc.dynamic.rtp.ts-stride", FT_UINT32, BASE_DEC, NULL, 0x0,
2834               "Dynamic RTP chain TS Stride", HFILL
2835             }
2836         },
2837         { &hf_pdcp_lte_rohc_ts,
2838             { "TS",
2839               "pdcp-lte.rohc.ts", FT_UINT8, BASE_DEC, NULL, 0x0,
2840               NULL, HFILL
2841             }
2842         },
2843         { &hf_pdcp_lte_rohc_m,
2844             { "M",
2845               "pdcp-lte.rohc.m", FT_UINT8, BASE_DEC, NULL, 0x40,
2846               NULL, HFILL
2847             }
2848         },
2849         { &hf_pdcp_lte_rohc_uor2_sn,
2850             { "SN",
2851               "pdcp-lte.rohc.uor2.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2852               NULL, HFILL
2853             }
2854         },
2855         { &hf_pdcp_lte_rohc_uor2_x,
2856             { "X",
2857               "pdcp-lte.rohc.uor2.x", FT_UINT8, BASE_DEC, NULL, 0x80,
2858               NULL, HFILL
2859             }
2860         },
2861
2862         { &hf_pdcp_lte_rohc_add_cid,
2863             { "Add-CID",
2864               "pdcp-lte.rohc.add-cid", FT_UINT8, BASE_DEC, NULL, 0x0f,
2865               NULL, HFILL
2866             }
2867         },
2868         { &hf_pdcp_lte_rohc_large_cid,
2869             { "Large-CID",
2870               "pdcp-lte.rohc.large-cid", FT_UINT16, BASE_DEC, NULL, 0x07ff,
2871               NULL, HFILL
2872             }
2873         },
2874         { &hf_pdcp_lte_rohc_uo0_sn,
2875             { "SN",
2876               "pdcp-lte.rohc.uo0.sn", FT_UINT8, BASE_DEC, NULL, 0x78,
2877               NULL, HFILL
2878             }
2879         },
2880         { &hf_pdcp_lte_rohc_uo0_crc,
2881             { "CRC",
2882               "pdcp-lte.rohc.uo0.crc", FT_UINT8, BASE_DEC, NULL, 0x07,
2883               "3-bit CRC", HFILL
2884             }
2885         },
2886         { &hf_pdcp_lte_rohc_r0_sn,
2887             { "SN",
2888               "pdcp-lte.rohc.r0.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2889               NULL, HFILL
2890             }
2891         },
2892         { &hf_pdcp_lte_rohc_r0_crc_sn,
2893             { "SN",
2894               "pdcp-lte.rohc.r0-crc.sn", FT_UINT16, BASE_DEC, NULL, 0x0,
2895               NULL, HFILL
2896             }
2897         },
2898         { &hf_pdcp_lte_rohc_r0_crc_crc,
2899             { "CRC7",
2900               "pdcp-lte.rohc.r0-crc.crc", FT_UINT8, BASE_DEC, NULL, 0x7f,
2901               "CRC 7", HFILL
2902             }
2903         },
2904         { &hf_pdcp_lte_rohc_feedback_code,
2905             { "Code",
2906               "pdcp-lte.rohc.feedback-code", FT_UINT8, BASE_DEC, NULL, 0x07,
2907               "Feedback options length (if > 0)", HFILL
2908             }
2909         },
2910         { &hf_pdcp_lte_rohc_feedback_size,
2911             { "Size",
2912               "pdcp-lte.rohc.feedback-size", FT_UINT8, BASE_DEC, NULL, 0x0,
2913               "Feedback options length", HFILL
2914             }
2915         },
2916         { &hf_pdcp_lte_rohc_feedback_feedback1,
2917             { "FEEDBACK-1 (SN)",
2918               "pdcp-lte.rohc.feedback.feedback1", FT_UINT8, BASE_DEC, NULL, 0x0,
2919               "Feedback-1", HFILL
2920             }
2921         },
2922         { &hf_pdcp_lte_rohc_feedback_feedback2,
2923             { "FEEDBACK-2",
2924               "pdcp-lte.rohc.feedback.feedback2", FT_NONE, BASE_NONE, NULL, 0x0,
2925               NULL, HFILL
2926             }
2927         },
2928
2929         { &hf_pdcp_lte_rohc_feedback_ack_type,
2930             { "Acktype",
2931               "pdcp-lte.rohc.feedback-acktype", FT_UINT8, BASE_DEC, VALS(feedback_ack_vals), 0xc0,
2932               "Feedback-2 ack type", HFILL
2933             }
2934         },
2935         { &hf_pdcp_lte_rohc_feedback_mode,
2936             { "mode",
2937               "pdcp-lte.rohc.feedback-mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
2938               "Feedback mode", HFILL
2939             }
2940         },
2941         { &hf_pdcp_lte_rohc_feedback_sn,
2942             { "SN",
2943               "pdcp-lte.rohc.feedback-sn", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2944               "Feedback sequence number", HFILL
2945             }
2946         },
2947
2948         { &hf_pdcp_lte_rohc_feedback_option,
2949             { "Option",
2950               "pdcp-lte.rohc.feedback-option", FT_UINT8, BASE_DEC, VALS(feedback_option_vals), 0xf0,
2951               "Feedback option", HFILL
2952             }
2953         },
2954         { &hf_pdcp_lte_rohc_feedback_length,
2955             { "Length",
2956               "pdcp-lte.rohc.feedback-length", FT_UINT8, BASE_DEC, NULL, 0x0f,
2957               "Feedback length", HFILL
2958             }
2959         },
2960         { &hf_pdcp_lte_rohc_feedback_crc,
2961             { "CRC",
2962               "pdcp-lte.rohc.feedback-crc", FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2963               "Feedback CRC", HFILL
2964             }
2965         },
2966         { &hf_pdcp_lte_rohc_feedback_option_sn,
2967             { "SN",
2968               "pdcp-lte.rohc.feedback-option-sn", FT_UINT8, BASE_DEC, NULL, 0x0,
2969               "Feedback Option SN", HFILL
2970             }
2971         },
2972         { &hf_pdcp_lte_rohc_feedback_option_clock,
2973             { "Clock",
2974               "pdcp-lte.rohc.feedback-option-clock", FT_UINT8, BASE_DEC, NULL, 0x0,
2975               "Feedback Option Clock", HFILL
2976             }
2977         },
2978
2979         { &hf_pdcp_lte_rohc_ip_id,
2980             { "IP-ID",
2981               "pdcp-lte.rohc.ip-id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2982               NULL, HFILL
2983             }
2984         },
2985         { &hf_pdcp_lte_rohc_udp_checksum,
2986             { "UDP Checksum",
2987               "pdcp-lte.rohc.udp-checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2988               NULL, HFILL
2989             }
2990         },
2991         { &hf_pdcp_lte_rohc_payload,
2992             { "Payload",
2993               "pdcp-lte.rohc.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
2994               NULL, HFILL
2995             }
2996         },
2997
2998     };
2999
3000     static gint *ett[] =
3001     {
3002         &ett_pdcp,
3003         &ett_pdcp_configuration,
3004         &ett_pdcp_packet,
3005         &ett_pdcp_lte_sequence_analysis,
3006         &ett_pdcp_rohc,
3007         &ett_pdcp_rohc_static_ipv4,
3008         &ett_pdcp_rohc_static_udp,
3009         &ett_pdcp_rohc_static_rtp,
3010         &ett_pdcp_rohc_dynamic_ipv4,
3011         &ett_pdcp_rohc_dynamic_udp,
3012         &ett_pdcp_rohc_dynamic_rtp,
3013         &ett_pdcp_rohc_report_bitmap
3014     };
3015
3016     module_t *pdcp_lte_module;
3017
3018     /* Register protocol. */
3019     proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
3020     proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
3021     proto_register_subtree_array(ett, array_length(ett));
3022
3023     /* Allow other dissectors to find this one by name. */
3024     register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
3025
3026     pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
3027
3028     /* Dissect uncompressed user-plane data as IP */
3029     prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
3030         "Show uncompressed User-Plane data as IP",
3031         "Show uncompressed User-Plane data as IP",
3032         &global_pdcp_dissect_user_plane_as_ip);
3033
3034     /* Dissect unciphered signalling data as RRC */
3035     prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
3036         "Show unciphered Signalling-Plane data as RRC",
3037         "Show unciphered Signalling-Plane data as RRC",
3038         &global_pdcp_dissect_signalling_plane_as_rrc);
3039
3040     /* Check for missing sequence numbers */
3041     prefs_register_bool_preference(pdcp_lte_module, "check_sequence_numbers",
3042         "Do sequence number analysis",
3043         "Do sequence number analysis",
3044         &global_pdcp_check_sequence_numbers);
3045
3046     /* Attempt to dissect ROHC headers */
3047     prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
3048         "Attempt to decode ROHC data",
3049         "Attempt to decode ROHC data",
3050         &global_pdcp_dissect_rohc);
3051
3052     prefs_register_bool_preference(pdcp_lte_module, "show_feedback_option_tag_length",
3053         "Show ROHC feedback option tag & length",
3054         "Show ROHC feedback option tag & length",
3055         &global_pdcp_show_feedback_option_tag_length);
3056
3057     prefs_register_bool_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp",
3058         "Try Heuristic LTE-PDCP over UDP framing",
3059         "When enabled, use heuristic dissector to find PDCP-LTE frames sent with "
3060         "UDP framing",
3061         &global_pdcp_lte_heur);
3062
3063     register_init_routine(&pdcp_lte_init_protocol);
3064 }
3065
3066 void proto_reg_handoff_pdcp_lte(void)
3067 {
3068     /* Add as a heuristic UDP dissector */
3069     heur_dissector_add("udp", dissect_pdcp_lte_heur, proto_pdcp_lte);
3070
3071     ip_handle = find_dissector("ip");
3072     ipv6_handle = find_dissector("ipv6");
3073     data_handle = find_dissector("data");
3074 }
3075