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