From Kovarththanan Rajaratnam via bug 3548:
[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 <epan/packet.h>
31 #include <epan/prefs.h>
32 #include <epan/expert.h>
33 #include <epan/addr_resolv.h>
34
35 #include "packet-pdcp-lte.h"
36
37 /* Described in:
38  * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
39  *                Packet Data Convergence Protocol (PDCP) specification
40  *
41  * RFC 3095       RObust Header Compression (ROHC):
42  *                Framework and four profiles: RTP, UDP, ESP, and uncompressed
43  */
44
45
46 /* TODO:
47    - Update to latest version of 36.323
48    - Complete ROHC support for RTP and extend to other profiles (including ROHCv2)
49    - Support for decryption
50    - Verify MAC authentication bytes
51    - Call LTE RRC dissector for uncompressed, signalling payloads
52 */
53
54
55 /* Initialize the protocol and registered fields. */
56 int proto_pdcp_lte = -1;
57
58 /* Configuration (info known outside of PDU) */
59 static int hf_pdcp_lte_configuration = -1;
60 static int hf_pdcp_lte_direction = -1;
61 static int hf_pdcp_lte_rohc = -1;
62 static int hf_pdcp_lte_rohc_compression = -1;
63 static int hf_pdcp_lte_rohc_mode = -1;
64 static int hf_pdcp_lte_rohc_rnd = -1;
65 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
66 static int hf_pdcp_lte_rohc_profile = -1;
67 static int hf_pdcp_lte_no_header_pdu = -1;
68 static int hf_pdcp_lte_plane = -1;
69 static int hf_pdcp_lte_seqnum_length = -1;
70 static int hf_pdcp_lte_cid_inclusion_info = -1;
71 static int hf_pdcp_lte_large_cid_present = -1;
72
73 /* PDCP header fields */
74 static int hf_pdcp_lte_seq_num_5 = -1;
75 static int hf_pdcp_lte_seq_num_7 = -1;
76 static int hf_pdcp_lte_reserved3 = -1;
77 static int hf_pdcp_lte_seq_num_12 = -1;
78 static int hf_pdcp_lte_signalling_data = -1;
79 static int hf_pdcp_lte_mac = -1;
80 static int hf_pdcp_lte_data_control = -1;
81 static int hf_pdcp_lte_user_plane_data = -1;
82 static int hf_pdcp_lte_control_pdu_type = -1;
83 static int hf_pdcp_lte_fms = -1;
84 static int hf_pdcp_lte_bitmap = -1;
85 static int hf_pdcp_lte_bitmap_not_received = -1;
86
87 /* Robust Header Compression Fields */
88 static int hf_pdcp_lte_rohc_padding = -1;
89 static int hf_pdcp_lte_rohc_r_0_crc = -1;
90 static int hf_pdcp_lte_rohc_feedback = -1;
91
92 static int hf_pdcp_lte_rohc_type0_t = -1;
93 static int hf_pdcp_lte_rohc_type1_t = -1;
94 static int hf_pdcp_lte_rohc_type2_t = -1;
95
96 static int hf_pdcp_lte_rohc_d = -1;
97 static int hf_pdcp_lte_rohc_ir_crc = -1;
98
99 static int hf_pdcp_lte_rohc_static_ipv4 = -1;
100 static int hf_pdcp_lte_rohc_ip_version = -1;
101 static int hf_pdcp_lte_rohc_ip_protocol = -1;
102 static int hf_pdcp_lte_rohc_ip_src = -1;
103 static int hf_pdcp_lte_rohc_ip_dst = -1;
104
105 static int hf_pdcp_lte_rohc_static_udp = -1;
106 static int hf_pdcp_lte_rohc_static_udp_src_port = -1;
107 static int hf_pdcp_lte_rohc_static_udp_dst_port = -1;
108
109 static int hf_pdcp_lte_rohc_static_rtp = -1;
110 static int hf_pdcp_lte_rohc_static_rtp_ssrc = -1;
111
112 static int hf_pdcp_lte_rohc_dynamic_ipv4 = -1;
113 static int hf_pdcp_lte_rohc_dynamic_ipv4_tos = -1;
114 static int hf_pdcp_lte_rohc_dynamic_ipv4_ttl = -1;
115 static int hf_pdcp_lte_rohc_dynamic_ipv4_id = -1;
116 static int hf_pdcp_lte_rohc_dynamic_ipv4_df = -1;
117 static int hf_pdcp_lte_rohc_dynamic_ipv4_rnd = -1;
118 static int hf_pdcp_lte_rohc_dynamic_ipv4_nbo = -1;
119
120 static int hf_pdcp_lte_rohc_dynamic_udp = -1;
121 static int hf_pdcp_lte_rohc_dynamic_udp_checksum = -1;
122 static int hf_pdcp_lte_rohc_dynamic_udp_seqnum = -1;
123
124 static int hf_pdcp_lte_rohc_dynamic_rtp = -1;
125 static int hf_pdcp_lte_rohc_dynamic_rtp_rx = -1;
126 static int hf_pdcp_lte_rohc_dynamic_rtp_cc = -1;
127 static int hf_pdcp_lte_rohc_dynamic_rtp_seqnum = -1;
128 static int hf_pdcp_lte_rohc_dynamic_rtp_timestamp = -1;
129 static int hf_pdcp_lte_rohc_dynamic_rtp_reserved3 = -1;
130 static int hf_pdcp_lte_rohc_dynamic_rtp_x = -1;
131 static int hf_pdcp_lte_rohc_dynamic_rtp_mode = -1;
132 static int hf_pdcp_lte_rohc_dynamic_rtp_tis = -1;
133 static int hf_pdcp_lte_rohc_dynamic_rtp_tss = -1;
134 static int hf_pdcp_lte_rohc_dynamic_rtp_ts_stride = -1;
135
136 static int hf_pdcp_lte_rohc_ts = -1;
137 static int hf_pdcp_lte_rohc_m = -1;
138 static int hf_pdcp_lte_rohc_uor2_sn = -1;
139 static int hf_pdcp_lte_rohc_uor2_x = -1;
140
141 static int hf_pdcp_lte_rohc_add_cid = -1;
142 static int hf_pdcp_lte_rohc_large_cid = -1;
143
144 static int hf_pdcp_lte_rohc_uo0_sn = -1;
145 static int hf_pdcp_lte_rohc_uo0_crc = -1;
146
147 static int hf_pdcp_lte_rohc_r0_sn = -1;
148 static int hf_pdcp_lte_rohc_r0_crc_sn = -1;
149 static int hf_pdcp_lte_rohc_r0_crc_crc = -1;
150
151 static int hf_pdcp_lte_rohc_feedback_code = -1;
152 static int hf_pdcp_lte_rohc_feedback_size = -1;
153 static int hf_pdcp_lte_rohc_feedback_feedback1 = -1;
154 static int hf_pdcp_lte_rohc_feedback_feedback2 = -1;
155 static int hf_pdcp_lte_rohc_feedback_ack_type = -1;
156 static int hf_pdcp_lte_rohc_feedback_mode = -1;
157 static int hf_pdcp_lte_rohc_feedback_sn = -1;
158 static int hf_pdcp_lte_rohc_feedback_option = -1;
159 static int hf_pdcp_lte_rohc_feedback_length = -1;
160 static int hf_pdcp_lte_rohc_feedback_crc = -1;
161 static int hf_pdcp_lte_rohc_feedback_option_sn = -1;
162 static int hf_pdcp_lte_rohc_feedback_option_clock = -1;
163
164 static int hf_pdcp_lte_rohc_ip_id = -1;
165 static int hf_pdcp_lte_rohc_udp_checksum = -1;
166 static int hf_pdcp_lte_rohc_payload = -1;
167
168
169 /* Protocol subtree. */
170 static int ett_pdcp = -1;
171 static int ett_pdcp_configuration = -1;
172 static int ett_pdcp_packet = -1;
173 static int ett_pdcp_rohc = -1;
174 static int ett_pdcp_rohc_static_ipv4 = -1;
175 static int ett_pdcp_rohc_static_udp = -1;
176 static int ett_pdcp_rohc_static_rtp = -1;
177 static int ett_pdcp_rohc_dynamic_ipv4 = -1;
178 static int ett_pdcp_rohc_dynamic_udp = -1;
179 static int ett_pdcp_rohc_dynamic_rtp = -1;
180 static int ett_pdcp_rohc_report_bitmap = -1;
181
182
183 static const value_string direction_vals[] =
184 {
185     { DIRECTION_UPLINK,      "Uplink"},
186     { DIRECTION_DOWNLINK,    "Downlink"},
187     { 0, NULL }
188 };
189
190
191 static const value_string pdcp_plane_vals[] = {
192     { SIGNALING_PLANE,    "Signalling" },
193     { USER_PLANE,         "User" },
194     { 0,   NULL }
195 };
196
197
198 static const value_string rohc_mode_vals[] = {
199     { UNIDIRECTIONAL,            "Unidirectional" },
200     { OPTIMISTIC_BIDIRECTIONAL,  "Optimistic Bidirectional" },
201     { RELIABLE_BIDIRECTIONAL,    "Reliable Bidirectional" },
202     { 0,   NULL }
203 };
204
205
206 /* TODO: add more */
207 static const value_string rohc_profile_vals[] = {
208     { 0,   "Uncompressed" },
209     { 1,   "RTP" },
210     { 2,   "UDP" },
211     { 3,   "ESP/IP" },
212     { 0,   NULL }
213 };
214
215 static const value_string pdu_type_vals[] = {
216     { 0,   "Control PDU" },
217     { 1,   "Data PDU" },
218     { 0,   NULL }
219 };
220
221 static const value_string feedback_ack_vals[] = {
222     { 0,   "ACK" },
223     { 1,   "NACK" },
224     { 2,   "STATIC-NACK" },
225     { 0,   NULL }
226 };
227
228 static const value_string feedback_option_vals[] = {
229     { 1,   "CRC" },
230     { 2,   "REJECT" },
231     { 3,   "SN-Not-Valid" },
232     { 4,   "SN" },
233     { 5,   "Clock" },
234     { 6,   "Jitter" },
235     { 7,   "Loss" },
236     { 0,   NULL }
237 };
238
239 static const value_string control_pdu_type_vals[] = {
240     { 0,   "PDCP Status report" },
241     { 1,   "Header Compression Feedback Information" },
242     { 0,   NULL }
243 };
244
245 static const value_string t_vals[] = {
246     { 0,   "ID message format" },
247     { 1,   "TS message format" },
248     { 0,   NULL }
249 };
250
251 static const value_string ip_protocol_vals[] = {
252     { 6,   "TCP" },
253     { 17,  "UDP" },
254     { 0,   NULL }
255 };
256
257
258 dissector_handle_t ip_handle = 0;
259
260
261 /* Preference variables */
262 static gboolean global_pdcp_show_feedback_option_tag_length = FALSE;
263 static gboolean global_pdcp_dissect_user_plane_as_ip = FALSE;
264 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = FALSE;
265 static gboolean global_pdcp_dissect_rohc = FALSE;
266
267 /* Dissect a Large-CID field.
268    Return following offset */
269 static int dissect_large_cid(proto_tree *tree,
270                              tvbuff_t *tvb,
271                              int offset)
272 {
273     guint8 first_octet = tvb_get_guint8(tvb, offset);
274
275     if ((first_octet & 0x80) == 0) {
276         /* One byte */
277         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 1,
278                             first_octet);
279         return offset+1;
280     }
281     else {
282         /* Two bytes */
283         guint16 bytes = tvb_get_ntohs(tvb, offset) & 0x7fff;
284         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 2,
285                             bytes);
286         return offset+2;
287     }
288
289 }
290
291 static int dissect_pdcp_dynamic_chain(proto_tree *tree,
292                                       proto_item *root_item _U_,
293                                       tvbuff_t *tvb,
294                                       int offset,
295                                       struct pdcp_lte_info *p_pdcp_info,
296                                       packet_info *pinfo)
297 {
298     /* IPv4 dynamic */
299     if (p_pdcp_info->rohc_ip_version == 4) {
300         proto_tree *dynamic_ipv4_tree;
301         proto_item *root_ti;
302         int tree_start_offset = offset;
303         guint8 tos, ttl, id, rnd, nbo;
304
305         /* Create dynamic IPv4 subtree */
306         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_ipv4, tvb, offset, -1, FALSE);
307         dynamic_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_ipv4);
308
309         /* ToS */
310         tos = tvb_get_guint8(tvb, offset);
311         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_tos, tvb, offset, 1, FALSE);
312         offset++;
313
314         /* TTL */
315         ttl = tvb_get_guint8(tvb, offset);
316         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_ttl, tvb, offset, 1, FALSE);
317         offset++;
318
319         /* IP-ID */
320         id = tvb_get_guint8(tvb, offset);
321         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_id, tvb, offset, 1, FALSE);
322         offset++;
323
324         /* IP flags */
325         rnd = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
326         nbo = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
327         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_df, tvb, offset, 1, FALSE);
328         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_rnd, tvb, offset, 1, FALSE);
329         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_nbo, tvb, offset, 1, FALSE);
330
331         /* TODO: general extension header list... */
332         offset += 3;
333
334         /* Set proper length for subtree */
335         proto_item_set_len(root_ti, offset-tree_start_offset);
336
337         /* Add summary to root item */
338         proto_item_append_text(root_ti, " (ToS=%u, TTL=%u, ID=%u, RND=%u, NBO=%u)",
339                                tos, ttl, id, rnd, nbo);
340     }
341
342     /* UDP dynamic */
343     if ((p_pdcp_info->profile == 1) ||
344         (p_pdcp_info->profile == 2)) {
345
346         proto_tree *dynamic_udp_tree;
347         proto_item *root_ti;
348         unsigned short checksum;
349
350         /* Create dynamic UDP subtree */
351         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_udp, tvb, offset, 2, FALSE);
352         dynamic_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_udp);
353
354         /* 16-bit checksum */
355         checksum = tvb_get_ntohs(tvb, offset);
356         proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_checksum, tvb, offset, 2, FALSE);
357         offset +=2;
358
359         if (p_pdcp_info->profile == 2) {
360             guint16 seqnum;
361
362             seqnum = tvb_get_ntohs(tvb, offset);
363             proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_seqnum, tvb, offset, 2, FALSE);
364             offset +=2;
365
366             /* Add summary to root item */
367             proto_item_append_text(root_ti, " (checksum = %04x, seqnum = %u)", checksum, seqnum);
368         }
369         else {
370             /* Add summary to root item */
371             proto_item_append_text(root_ti, " (checksum = %04x)", checksum);
372         }
373     }
374
375     /* RTP dynamic */
376     if (p_pdcp_info->profile == 1) {
377         proto_tree *dynamic_rtp_tree;
378         proto_item *root_ti;
379         int tree_start_offset = offset;
380         guint8     rx;
381         guint8     contributing_csrcs;
382         guint16    sequence_number;
383         guint32    timestamp;
384         guint8     tis=0, tss=0;
385         guint64    ts_stride=0;
386
387         /* Create dynamic RTP subtree */
388         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_rtp, tvb, offset, -1, FALSE);
389         dynamic_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_rtp);
390
391         /* TODO: */
392         /* V | P | RX | CC */
393         rx = tvb_get_guint8(tvb, offset) & 0x10;
394         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_rx, tvb, offset, 1, FALSE);
395         contributing_csrcs = tvb_get_guint8(tvb, offset) & 0x0f;
396         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_cc, tvb, offset, 1, FALSE);
397         offset += 1;
398
399         /* TODO: */
400         /* M | PT */
401         offset += 1;
402
403         /* Sequence number */
404         sequence_number = tvb_get_ntohs(tvb, offset);
405         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_seqnum, tvb, offset, 2, FALSE);
406         offset += 2;
407
408         /* Timestamp (4 octets) */
409         timestamp = tvb_get_ntohl(tvb, offset);
410         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_timestamp, tvb, offset, 4, FALSE);
411         offset += 4;
412
413         /* TODO: CSRC list */
414         /*offset += (4 * contributing_csrcs); */
415         offset++;
416
417         /* TODO: Reserved | X | Mode | TIS | TIS */
418         if (rx) {
419             guint8 this_byte = tvb_get_guint8(tvb, offset);
420             proto_item *reserved_ti = proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
421                                                           tvb, offset, 1, FALSE);
422
423             /* Check reserved bits are 0 */
424             if ((this_byte & 0xe0) != 0) {
425                 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
426                                        "Reserved bits have value 0x%x - should be 0x0",
427                                        (this_byte & 0xe0));
428             }
429             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_x, tvb, offset, 1, FALSE);
430             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_mode, tvb, offset, 1, FALSE);
431             tss = (this_byte & 0x02);
432             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tss, tvb, offset, 1, FALSE);
433             tis = (this_byte & 0x01);
434             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tis, tvb, offset, 1, FALSE);
435             offset++;
436         }
437
438         /* TODO: the length of these fields can be learned by looked at the leading bits, see
439            RFC 3095, "4.5.6.  Self-describing variable-length values" */
440         /* TODO: TS-Stride (1-4 bytes) */
441         if (tis) {
442             /* Assume encoded in two bytes for now... */
443             proto_tree_add_bits_ret_val(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
444                                         tvb, offset*8 + 2, 14, &ts_stride, FALSE);
445             offset += 2;
446         }
447
448         /* TODO: Time-stride (1-4 bytes) */
449         if (tss) {
450         }
451
452         /* Set proper length for subtree */
453         proto_item_set_len(root_ti, offset-tree_start_offset);
454
455         /* Add summary to root item */
456         proto_item_append_text(root_ti, " (seqnum = %u, timestamp = %u)",
457                                sequence_number, timestamp);
458     }
459
460     return offset;
461 }
462
463
464
465 static int dissect_pdcp_irdyn_packet(proto_tree *tree _U_,
466                                      proto_item *root_item,
467                                      tvbuff_t *tvb _U_,
468                                      int offset,
469                                      struct pdcp_lte_info *p_pdcp_info _U_,
470                                      packet_info *pinfo)
471 {
472     if (check_col(pinfo->cinfo, COL_INFO)) {
473         col_append_str(pinfo->cinfo, COL_INFO, " IRDYN");
474     }
475     proto_item_append_text(root_item, " (IRDYN)");
476
477     /* Large CID */
478     if (p_pdcp_info->large_cid_present) {
479         offset = dissect_large_cid(tree, tvb, offset);
480     }
481
482     /* Profile */
483     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
484     offset++;
485
486     /* 8-bit CRC */
487     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
488     offset++;
489
490     /* Dissect dynamic chain */
491     offset = dissect_pdcp_dynamic_chain(tree,
492                                         root_item,
493                                         tvb,
494                                         offset,
495                                         p_pdcp_info,
496                                         pinfo);
497     return offset;
498 }
499
500
501 static int dissect_pdcp_ir_packet(proto_tree *tree,
502                                   proto_item *root_item,
503                                   tvbuff_t *tvb,
504                                   int offset,
505                                   struct pdcp_lte_info *p_pdcp_info,
506                                   packet_info *pinfo)
507 {
508     unsigned char dynamic_chain_present;
509
510     if (check_col(pinfo->cinfo, COL_INFO)) {
511         col_append_str(pinfo->cinfo, COL_INFO, " IR");
512     }
513     proto_item_append_text(root_item, " (IR)");
514
515     /* Is dynamic chain present? */
516     dynamic_chain_present = tvb_get_guint8(tvb, offset) & 0x1;
517     proto_tree_add_item(tree, hf_pdcp_lte_rohc_d, tvb, offset, 1, FALSE);
518     offset++;
519
520     /* Large CID */
521     if (p_pdcp_info->large_cid_present) {
522         offset = dissect_large_cid(tree, tvb, offset);
523     }
524
525     /* Profile */
526     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
527     offset++;
528
529     /* 8-bit CRC */
530     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
531     offset++;
532
533     /* IPv4 static part */
534     if (p_pdcp_info->rohc_ip_version == 4) {
535         proto_tree *static_ipv4_tree;
536         proto_item *root_ti;
537         int tree_start_offset = offset;
538         guint8  protocol;
539         guint32 source, dest;
540
541         /* Create static IPv4 subtree */
542         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_ipv4, tvb, offset, -1, FALSE);
543         static_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_ipv4);
544
545         /* IP version (must be 4) */
546         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_version, tvb, offset, 1, FALSE);
547         offset++;
548
549         /* Protocol */
550         protocol = tvb_get_guint8(tvb, offset);
551         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_protocol, tvb, offset, 1, FALSE);
552         offset++;
553
554         /* Source address */
555         source = tvb_get_ipv4(tvb, offset);
556         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_src, tvb, offset, 4, FALSE);
557         offset += 4;
558
559         /* Dest address */
560         dest = tvb_get_ipv4(tvb, offset);
561         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_dst, tvb, offset, 4, FALSE);
562         offset += 4;
563
564         /* Set proper length for subtree */
565         proto_item_set_len(root_ti, offset-tree_start_offset);
566
567         /* Add summary to root item */
568         proto_item_append_text(root_ti, " (prot=%s: %s -> %s)",
569                                val_to_str(protocol, ip_protocol_vals, "Unknown"),
570                                (char*)get_hostname(source),
571                                (char*)get_hostname(dest));
572     }
573
574     /* UDP static part. TODO: also check protocol from last part!? */
575     if ((p_pdcp_info->profile == 1) ||
576         (p_pdcp_info->profile == 2)) {
577
578         proto_tree *static_udp_tree;
579         proto_item *root_ti;
580         int tree_start_offset = offset;
581         unsigned short source_port, dest_port;
582
583         /* Create static UDP subtree */
584         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_udp, tvb, offset, -1, FALSE);
585         static_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_udp);
586
587         /* Source port */
588         source_port = tvb_get_ntohs(tvb, offset);
589         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
590         offset += 2;
591
592         /* Dest port */
593         dest_port = tvb_get_ntohs(tvb, offset);
594         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
595         offset += 2;
596
597         /* Set proper length for subtree */
598         proto_item_set_len(root_ti, offset-tree_start_offset);
599
600         /* Add summary to root item */
601         proto_item_append_text(root_ti, " (%u -> %u)", source_port, dest_port);
602     }
603
604     /* RTP static */
605     if (p_pdcp_info->profile == 1) {
606         proto_tree *static_rtp_tree;
607         proto_item *root_ti;
608         guint32    ssrc;
609
610         /* Create static RTP subtree */
611         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_rtp, tvb, offset, 4, FALSE);
612         static_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_rtp);
613
614         /* SSRC */
615         ssrc = tvb_get_ntohl(tvb, offset);
616         proto_tree_add_item(static_rtp_tree, hf_pdcp_lte_rohc_static_rtp_ssrc, tvb, offset, 4, FALSE);
617         offset += 4;
618
619         /* Add summary to root item */
620         proto_item_append_text(root_ti, " (SSRC=%u)", ssrc);
621     }
622
623
624     /* Dynamic chain */
625     if (dynamic_chain_present) {
626         offset = dissect_pdcp_dynamic_chain(tree,
627                                             root_item,
628                                             tvb,
629                                             offset,
630                                             p_pdcp_info,
631                                             pinfo);
632     }
633
634     return offset;
635 }
636
637
638
639 static int dissect_pdcp_feedback_feedback1(proto_tree *tree,
640                                            proto_item *item,
641                                            tvbuff_t *tvb,
642                                            int offset,
643                                            struct pdcp_lte_info *p_pdcp_info _U_,
644                                            packet_info *pinfo)
645 {
646     guint8 sn;
647
648     proto_item_append_text(item, " (type 1)");
649
650     /* TODO: profile-specific */
651     sn = tvb_get_guint8(tvb, offset);
652     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback1, tvb, offset, 1, FALSE);
653     offset++;
654
655     if (check_col(pinfo->cinfo, COL_INFO)) {
656         col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
657     }
658
659     return offset;
660 }
661
662 /* Includes Large-CID, if present */
663 static int dissect_pdcp_feedback_feedback2(proto_tree *tree,
664                                            proto_item *item,
665                                            tvbuff_t *tvb,
666                                            int offset,
667                                            int size,
668                                            struct pdcp_lte_info *p_pdcp_info _U_,
669                                            packet_info *pinfo _U_)
670 {
671     proto_item *ti;
672     guint8  ack_type;
673     guint8  mode;
674     guint8  first_octet;
675     guint16 sn;
676     const char * full_mode_name;
677     int size_remaining;
678
679     proto_item_append_text(item, " (type 2)");
680
681     /* Large CID */
682     if (p_pdcp_info->large_cid_present) {
683         offset = dissect_large_cid(tree, tvb, offset);
684     }
685
686     /* Feedback2 hidden filter */
687     ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback2, tvb, offset, -1, FALSE);
688     PROTO_ITEM_SET_HIDDEN(ti);
689
690     /* Ack-type */
691     first_octet = tvb_get_guint8(tvb, offset);
692     ack_type = (first_octet & 0xc0) >> 6;
693     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_ack_type, tvb, offset, 1, FALSE);
694
695     /* TODO: expert info on NACK? */
696
697     /* Mode */
698     mode = (first_octet & 0x30) >> 4;
699     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_mode, tvb, offset, 1, FALSE);
700
701     /* Show ACK-TYPE(Mode) in info column */
702     if (check_col(pinfo->cinfo, COL_INFO)) {
703         full_mode_name = val_to_str(mode, rohc_mode_vals, "Error");
704
705         col_append_fstr(pinfo->cinfo, COL_INFO, " %s(%c)",
706                         val_to_str(ack_type, feedback_ack_vals, "Unknown"),
707                         full_mode_name[0]);
708     }
709
710     /* 11 bits of SN */
711     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_sn, tvb, offset, 2, FALSE);
712     sn = tvb_get_ntohs(tvb, offset) & 0x7ff;
713     offset += 2;
714
715     if (check_col(pinfo->cinfo, COL_INFO)) {
716         col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
717     }
718
719     /* Loop over any remaining feedback options */
720     size_remaining = size - 2;
721
722     while (tvb_length_remaining(tvb, offset) > 0) {
723         guint8 option = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
724         guint8 length = tvb_get_guint8(tvb, offset) & 0x0f;
725         guint8 one_byte_value;
726
727         /* Preference setting controls showing option and lengths */
728         if (global_pdcp_show_feedback_option_tag_length) {
729             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option, tvb, offset, 1, FALSE);
730             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_length, tvb, offset, 1, FALSE);
731         }
732         offset++;
733         size_remaining--;
734
735         /* TODO: switch including missing option types */
736         switch (option) {
737             case 1:
738                 /* CRC */
739                 one_byte_value = tvb_get_guint8(tvb, offset);
740                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_crc, tvb, offset, 1, FALSE);
741                 if (check_col(pinfo->cinfo, COL_INFO)) {
742                     col_append_fstr(pinfo->cinfo, COL_INFO, " CRC=%u ", one_byte_value);
743                 }
744                 break;
745             case 2:
746                 /* REJECT: TODO */
747                 break;
748             case 3:
749                 /* SN-Not-Valid: TODO */
750                 break;
751             case 4:
752                 /* SN */
753                 one_byte_value = tvb_get_guint8(tvb, offset);
754                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_sn, tvb, offset, 1, FALSE);
755                 if (check_col(pinfo->cinfo, COL_INFO)) {
756                     col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u ", one_byte_value);
757                 }
758                 break;
759             case 5:
760                 /* Clock */
761                 one_byte_value = tvb_get_guint8(tvb, offset);
762                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_clock, tvb, offset, 1, FALSE);
763                 if (check_col(pinfo->cinfo, COL_INFO)) {
764                     col_append_fstr(pinfo->cinfo, COL_INFO, " Clock=%u ", one_byte_value);
765                 }
766                 break;
767             case 6:
768                 /* Jitter: TODO */
769                 break;
770             case 7:
771                 /* Loss: TODO */
772                 break;
773
774             default:
775                 /* TODO: unhandled option */
776                 break;
777         }
778
779         /* Skip length */
780         offset += length;
781         size_remaining -= length;
782     }
783
784     return offset;
785 }
786
787
788 /* Dissect a feedback packet.
789    Return following offset */
790 static int dissect_pdcp_feedback_packet(proto_tree *tree,
791                                         proto_item *root_item,
792                                         tvbuff_t *tvb,
793                                         int offset,
794                                         struct pdcp_lte_info *p_pdcp_info,
795                                         packet_info *pinfo)
796 {
797     guint8 code;
798     guint8 size;
799     proto_item *ti;
800     proto_item *feedback_ti;
801     proto_tree *feedback_tree;
802
803     if (check_col(pinfo->cinfo, COL_INFO)) {
804         col_append_str(pinfo->cinfo, COL_INFO, " Feedback");
805     }
806     proto_item_append_text(root_item, " (Feedback)");
807
808     /* Create feedback tree root */
809     feedback_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback, tvb, offset, -1, FALSE);
810     feedback_tree = proto_item_add_subtree(feedback_ti, ett_pdcp_packet);
811
812     /* Code */
813     code = tvb_get_guint8(tvb, offset) & 0x07;
814     ti = proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_code, tvb, offset, 1, FALSE);
815     offset++;
816
817     /* Optional length field */
818     if (code != 0) {
819         proto_item_append_text(ti, " (length of feedback data)");
820         size = code;
821     }
822     else {
823         proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_size, tvb, offset, 1, FALSE);
824         size = tvb_get_guint8(tvb, offset);
825         offset++;
826     }
827
828     /* Work out feedback type */
829     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
830          !p_pdcp_info->large_cid_present) {
831
832         /* Small CID */
833         if (size == 1) {
834             offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
835         }
836         else if ((size > 1) && ((tvb_get_guint8(tvb, offset) & 0xc0) == 0xc0)) {
837             /* Add-CID here! */
838             proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
839             offset++;
840
841             if (size == 2) {
842                 offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
843             }
844             else {
845                 offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
846             }
847         }
848         else {
849             offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
850         }
851     }
852     else {
853         offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
854     }
855
856     return offset;
857 }
858
859
860 /* Dissect R-0 packet.
861    Return following offset */
862 static int dissect_pdcp_r_0_packet(proto_tree *tree,
863                                    proto_item *root_item,
864                                    tvbuff_t *tvb,
865                                    int offset,
866                                    struct pdcp_lte_info *p_pdcp_info _U_,
867                                    packet_info *pinfo)
868 {
869     guint8 sn;
870
871     if (check_col(pinfo->cinfo, COL_INFO)) {
872         col_append_str(pinfo->cinfo, COL_INFO, " R-0");
873     }
874     proto_item_append_text(root_item, " (R-0)");
875
876     /* 6 bits of sn */
877     sn = tvb_get_guint8(tvb, offset) & 0x3f;
878     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_sn, tvb, offset, 1, FALSE);
879     offset++;
880
881     /* Large CID */
882     if (p_pdcp_info->large_cid_present) {
883         offset = dissect_large_cid(tree, tvb, offset);
884     }
885
886     if (check_col(pinfo->cinfo, COL_INFO)) {
887         col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
888     }
889
890     return offset;
891 }
892
893
894 /* Dissect R-0-CRC packet.
895    Return following offset */
896 static int dissect_pdcp_r_0_crc_packet(proto_tree *tree,
897                                        proto_item *root_item,
898                                        tvbuff_t *tvb,
899                                        int offset,
900                                        struct pdcp_lte_info *p_pdcp_info,
901                                        packet_info *pinfo)
902 {
903     guint8 sn;
904
905     if (check_col(pinfo->cinfo, COL_INFO)) {
906         col_append_str(pinfo->cinfo, COL_INFO, " R-0-CRC");
907     }
908     proto_item_append_text(root_item, " (R-0-CRC)");
909
910     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r_0_crc, tvb, offset, -1, FALSE);
911
912     /* 7 bits of sn */
913     /* TODO: wrong!  Large-cid may be in-between!!!! */
914     sn = tvb_get_guint8(tvb, offset) & 0x3f;
915     offset++;
916
917     /* Large CID */
918     if (p_pdcp_info->large_cid_present) {
919         offset = dissect_large_cid(tree, tvb, offset);
920     }
921
922     /* Conclude SN */
923     sn = (sn << 1) + ((tvb_get_guint8(tvb, offset) & 0x80) >> 7);
924     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_r0_crc_sn, tvb, offset, 1, sn);
925
926     /* 7 bit CRC */
927     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_crc_crc, tvb, offset, 1, FALSE);
928     offset++;
929
930     /* Show SN in info column */
931     if (check_col(pinfo->cinfo, COL_INFO)) {
932         col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
933     }
934
935     return offset;
936 }
937
938
939 /* Dissect UO-0-CRC packet.
940    Return following offset */
941 static int dissect_pdcp_uo_0_packet(proto_tree *tree,
942                                     proto_item *root_item,
943                                     tvbuff_t *tvb,
944                                     int offset,
945                                     struct pdcp_lte_info *p_pdcp_info,
946                                     packet_info *pinfo)
947 {
948     guint8 sn;
949
950     if (check_col(pinfo->cinfo, COL_INFO)) {
951         col_append_str(pinfo->cinfo, COL_INFO, " U0-0");
952     }
953     proto_item_append_text(root_item, " (UO-0)");
954
955     /* SN */
956     sn = (tvb_get_guint8(tvb, offset) & 0x78) >> 3;
957     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_sn, tvb, offset, 1, FALSE);
958
959     /* CRC (3 bits) */
960     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_crc, tvb, offset, 1, FALSE);
961
962     offset++;
963
964     /* Large CID */
965     if (p_pdcp_info->large_cid_present) {
966         offset = dissect_large_cid(tree, tvb, offset);
967     }
968
969     /* Show SN in info column */
970     if (check_col(pinfo->cinfo, COL_INFO)) {
971         col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
972     }
973
974     return offset;
975 }
976
977
978 /* Dissect R-1 packet.
979    Return following offset */
980 static int  dissect_pdcp_r_1_packet(proto_tree *tree,
981                                     proto_item *root_item,
982                                     tvbuff_t *tvb,
983                                     int offset,
984                                     struct pdcp_lte_info *p_pdcp_info,
985                                     packet_info *pinfo)
986 {
987     if (check_col(pinfo->cinfo, COL_INFO)) {
988         col_append_str(pinfo->cinfo, COL_INFO, " R-1");
989     }
990     proto_item_append_text(root_item, " (R-1)");
991
992     /* TODO: octet before large-cid */
993     offset++;
994
995     /* Large CID */
996     if (p_pdcp_info->large_cid_present) {
997         offset = dissect_large_cid(tree, tvb, offset);
998     }
999
1000     if (p_pdcp_info->profile == 1) {
1001         /* TODO: */
1002     }
1003     else if (p_pdcp_info->profile == 2) {
1004         /* TODO: */
1005     }
1006
1007     return offset;
1008 }
1009
1010
1011 /* Dissect R-1-TS or R-1-ID packet.
1012    Return following offset */
1013 static int  dissect_pdcp_r_1_ts_or_id_packet(proto_tree *tree,
1014                                              proto_item *root_item,
1015                                              tvbuff_t *tvb,
1016                                              int offset,
1017                                              struct pdcp_lte_info *p_pdcp_info,
1018                                              packet_info *pinfo)
1019 {
1020     unsigned char T;
1021
1022     /* TODO: octet before large-cid */
1023     offset++;
1024
1025     /* Large CID */
1026     if (p_pdcp_info->large_cid_present) {
1027         offset = dissect_large_cid(tree, tvb, offset);
1028     }
1029
1030     /* T determines frame type */
1031     T = tvb_get_guint8(tvb, ++offset) >> 7;
1032     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type1_t, tvb, offset, 1, FALSE);
1033     if (T) {
1034         if (check_col(pinfo->cinfo, COL_INFO)) {
1035             col_append_str(pinfo->cinfo, COL_INFO, " R-1-TS");
1036         }
1037         proto_item_append_text(root_item, " (R-1-TS)");
1038     }
1039     else {
1040         if (check_col(pinfo->cinfo, COL_INFO)) {
1041             col_append_str(pinfo->cinfo, COL_INFO, " R-1-ID");
1042         }
1043         proto_item_append_text(root_item, " (R-1-ID)");
1044     }
1045
1046     if (p_pdcp_info->profile == 1) {
1047         /* TODO: */
1048     }
1049     else if (p_pdcp_info->profile == 2) {
1050         /* TODO: */
1051     }
1052
1053     return offset;
1054 }
1055
1056
1057 /* Dissect UO-1 packet.
1058    Return following offset */
1059 static int  dissect_pdcp_uo_1_packet(proto_tree *tree,
1060                                      proto_item *root_item,
1061                                      tvbuff_t *tvb,
1062                                      int offset,
1063                                      struct pdcp_lte_info *p_pdcp_info,
1064                                      packet_info *pinfo)
1065 {
1066     if (check_col(pinfo->cinfo, COL_INFO)) {
1067         col_append_str(pinfo->cinfo, COL_INFO, " UO-1");
1068     }
1069     proto_item_append_text(root_item, " (UO-1)");
1070
1071     /* TODO: octet before large-cid */
1072     offset++;
1073
1074     /* Large CID */
1075     if (p_pdcp_info->large_cid_present) {
1076         offset = dissect_large_cid(tree, tvb, offset);
1077     }
1078
1079     if (p_pdcp_info->profile == 1) {
1080         /* TODO: */
1081     }
1082     else if (p_pdcp_info->profile == 2) {
1083         /* TODO: */
1084     }
1085
1086     return offset;
1087 }
1088
1089
1090 /* Dissect UO-1-TS or UO-1-ID packet.
1091    Return following offset */
1092 static int  dissect_pdcp_uo_1_ts_or_id_packet(proto_tree *tree,
1093                                               proto_item *root_item,
1094                                               tvbuff_t *tvb,
1095                                               int offset,
1096                                               struct pdcp_lte_info *p_pdcp_info,
1097                                               packet_info *pinfo)
1098 {
1099     unsigned char T;
1100
1101     /* TODO: octet before large-cid */
1102     offset++;
1103
1104     /* Large CID */
1105     if (p_pdcp_info->large_cid_present) {
1106         offset = dissect_large_cid(tree, tvb, offset);
1107     }
1108
1109     /* T determines frame type */
1110     T = tvb_get_guint8(tvb, ++offset) >> 5;
1111     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type0_t, tvb, offset, 1, FALSE);
1112     if (T) {
1113         if (check_col(pinfo->cinfo, COL_INFO)) {
1114             col_append_str(pinfo->cinfo, COL_INFO, " UO-1-TS");
1115         }
1116         proto_item_append_text(root_item, " (UO-1-TS)");
1117     }
1118     else {
1119         if (check_col(pinfo->cinfo, COL_INFO)) {
1120             col_append_str(pinfo->cinfo, COL_INFO, " UO-1-ID");
1121         }
1122         proto_item_append_text(root_item, " (UO-1-ID)");
1123     }
1124
1125     if (p_pdcp_info->profile == 1) {
1126         /* TODO: */
1127     }
1128     else if (p_pdcp_info->profile == 2) {
1129         /* TODO: */
1130     }
1131
1132     return offset;
1133 }
1134
1135
1136
1137
1138
1139 /* Dissect UOR-2 packet.
1140    Return following offset */
1141 static int  dissect_pdcp_uor_2_packet(proto_tree *tree,
1142                                       proto_item *root_item,
1143                                       tvbuff_t *tvb,
1144                                       int offset,
1145                                       struct pdcp_lte_info *p_pdcp_info,
1146                                       packet_info *pinfo)
1147 {
1148     guint8 ts;
1149
1150     if (check_col(pinfo->cinfo, COL_INFO)) {
1151         col_append_str(pinfo->cinfo, COL_INFO, " U0R-2");
1152     }
1153     proto_item_append_text(root_item, " (UOR-2)");
1154
1155     /* TS straddles CID */
1156     ts = tvb_get_guint8(tvb, offset) & 0x1f;
1157     offset++;
1158
1159     /* Large CID */
1160     if (p_pdcp_info->large_cid_present) {
1161         offset = dissect_large_cid(tree, tvb, offset);
1162     }
1163
1164     /* Last bit of TS is here */
1165     ts = (ts << 1) | (tvb_get_guint8(tvb, offset) >> 7);
1166     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1167
1168     if (p_pdcp_info->profile == 1) {
1169         /* M */
1170         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, FALSE);
1171
1172         /* SN (6 bits) */
1173         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_sn, tvb, offset, 1, FALSE);
1174         offset++;
1175
1176         /* X (one bit) */
1177         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_x, tvb, offset, 1, FALSE);
1178
1179         /* TODO: CRC */
1180         offset++;
1181     }
1182     else if (p_pdcp_info->profile == 2) {
1183         /* TODO: */
1184         offset += 2;
1185     }
1186
1187     return offset;
1188 }
1189
1190
1191 /* Dissect UOR-2-TS or UOR-2-ID packet.
1192    Return following offset */
1193 static int  dissect_pdcp_uor_2_ts_or_id_packet(proto_tree *tree,
1194                                                proto_item *root_item,
1195                                                tvbuff_t *tvb,
1196                                                int offset,
1197                                                struct pdcp_lte_info *p_pdcp_info,
1198                                                packet_info *pinfo)
1199 {
1200     unsigned char T;
1201
1202     /* TODO: octet before large-cid.
1203        TODO: can't decode this until we know what T is,
1204              but T is after large-cid... */
1205     offset++;
1206
1207     /* T determines frame type */
1208     T = tvb_get_guint8(tvb, offset) >> 7;
1209     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type2_t, tvb, offset, 1, FALSE);
1210
1211     if (T) {
1212         if (check_col(pinfo->cinfo, COL_INFO)) {
1213             col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-TS");
1214         }
1215         proto_item_append_text(root_item, " (UOR-2-TS)");
1216     }
1217     else {
1218         if (check_col(pinfo->cinfo, COL_INFO)) {
1219             col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-ID");
1220         }
1221         proto_item_append_text(root_item, " (UOR-2-ID)");
1222     }
1223
1224
1225     if (T) {
1226         /* UOR-2-TS format */
1227
1228         /* TS */
1229         guint8 ts = tvb_get_guint8(tvb, offset) & 0x1f;
1230         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1231         offset++;
1232
1233         /* Large CID */
1234         if (p_pdcp_info->large_cid_present) {
1235             offset = dissect_large_cid(tree, tvb, offset);
1236         }
1237
1238         /* m */
1239         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, ts);
1240
1241         /* TODO: */
1242     }
1243     else {
1244         /* TODO: UOR-2-ID format */
1245
1246         /* IP-ID */
1247
1248         /* Large CID */
1249         if (p_pdcp_info->large_cid_present) {
1250             offset = dissect_large_cid(tree, tvb, offset);
1251         }
1252
1253         /* TODO: */
1254     }
1255
1256     if (p_pdcp_info->profile == 1) {
1257         /* TODO: */
1258     }
1259     else if (p_pdcp_info->profile == 2) {
1260         /* TODO: */
1261     }
1262
1263     return offset;
1264 }
1265
1266
1267
1268
1269 /* Show in the tree the config info attached to this frame, as generated fields */
1270 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1271                              pdcp_lte_info *p_pdcp_info)
1272 {
1273     proto_item *ti;
1274     proto_tree *configuration_tree;
1275     proto_item *configuration_ti = proto_tree_add_item(tree,
1276                                                        hf_pdcp_lte_configuration,
1277                                                        tvb, 0, 0, FALSE);
1278     configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1279
1280     /* Direction */
1281     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1282                              p_pdcp_info->direction);
1283     PROTO_ITEM_SET_GENERATED(ti);
1284
1285     /* Plane */
1286     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1287                              p_pdcp_info->plane);
1288     PROTO_ITEM_SET_GENERATED(ti);
1289
1290     /* User-plane-specific fields */
1291     if (p_pdcp_info->plane == USER_PLANE) {
1292
1293         /* No Header PDU */
1294         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1295                                  p_pdcp_info->no_header_pdu);
1296         PROTO_ITEM_SET_GENERATED(ti);
1297
1298         if (!p_pdcp_info->no_header_pdu) {
1299
1300             /* Seqnum length */
1301             ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1302                                      p_pdcp_info->seqnum_length);
1303             PROTO_ITEM_SET_GENERATED(ti);
1304         }
1305     }
1306
1307     /* ROHC compression */
1308     ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1309                                 p_pdcp_info->rohc_compression);
1310     PROTO_ITEM_SET_GENERATED(ti);
1311
1312     /* ROHC-specific settings */
1313     if (p_pdcp_info->rohc_compression) {
1314
1315         /* Show ROHC mode */
1316         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1317                                  p_pdcp_info->mode);
1318         PROTO_ITEM_SET_GENERATED(ti);
1319
1320         /* Show RND */
1321         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1322                                  p_pdcp_info->rnd);
1323         PROTO_ITEM_SET_GENERATED(ti);
1324
1325         /* UDP Checksum */
1326         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1327                                  p_pdcp_info->udp_checkum_present);
1328         PROTO_ITEM_SET_GENERATED(ti);
1329
1330         /* ROHC profile */
1331         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1332                                  p_pdcp_info->profile);
1333         PROTO_ITEM_SET_GENERATED(ti);
1334
1335         /* CID Inclusion Info */
1336         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1337                                  p_pdcp_info->cid_inclusion_info);
1338         PROTO_ITEM_SET_GENERATED(ti);
1339
1340         /* Large CID */
1341         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1342                                  p_pdcp_info->large_cid_present);
1343         PROTO_ITEM_SET_GENERATED(ti);
1344     }
1345
1346     /* Append summary to configuration root */
1347     proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1348                            val_to_str(p_pdcp_info->direction, direction_vals, "Unknown"),
1349                            val_to_str(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1350
1351     if (p_pdcp_info->rohc_compression) {
1352         const char *mode = val_to_str(p_pdcp_info->mode, rohc_mode_vals, "Error");
1353         proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1354                                mode[0],
1355                                val_to_str(p_pdcp_info->profile, rohc_profile_vals, "Unknown"));
1356     }
1357     proto_item_append_text(configuration_ti, ")");
1358     PROTO_ITEM_SET_GENERATED(configuration_ti);
1359
1360     /* Show plane in info column */
1361     if (check_col(pinfo->cinfo, COL_INFO)) {
1362         col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1363                         val_to_str(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1364     }
1365
1366 }
1367
1368
1369 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1370 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info  *p_pdcp_info)
1371 {
1372     dissector_handle_t rrc_handle = 0;
1373
1374     switch (p_pdcp_info->channelType)
1375     {
1376         case Channel_CCCH:
1377             if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1378                 rrc_handle = find_dissector("lte-rrc.ul.ccch");
1379             }
1380             else {
1381                 rrc_handle = find_dissector("lte-rrc.dl.ccch");
1382             }
1383             break;
1384         case Channel_PCCH:
1385             rrc_handle = find_dissector("lte-rrc.pcch");
1386             break;
1387         case Channel_BCCH:
1388             switch (p_pdcp_info->BCCHTransport) {
1389                 case BCH_TRANSPORT:
1390                     rrc_handle = find_dissector("lte-rrc.bcch.bch");
1391                     break;
1392                 case DLSCH_TRANSPORT:
1393                     rrc_handle = find_dissector("lte-rrc.bcch.dl.sch");
1394                     break;
1395             }
1396             break;
1397
1398         default:
1399             break;
1400     }
1401
1402     return rrc_handle;
1403 }
1404
1405
1406 /******************************/
1407 /* Main dissection function.  */
1408 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1409 {
1410     const char         *mode;
1411     proto_tree         *pdcp_tree = NULL;
1412     proto_item         *root_ti = NULL;
1413     proto_tree         *rohc_tree = NULL;
1414     proto_item         *rohc_ti = NULL;
1415     gint               offset = 0;
1416     gint               rohc_offset;
1417     struct pdcp_lte_info  *p_pdcp_info;
1418     guint8             base_header_byte;
1419     gboolean           udp_checksum_needed = TRUE;
1420     gboolean           ip_id_needed = TRUE;
1421
1422     /* Append this protocol name rather than replace. */
1423     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1424         col_add_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1425
1426     /* Create pdcp tree. */
1427     if (tree) {
1428         root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, FALSE);
1429         pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1430     }
1431
1432
1433     /* Look for attached packet info! */
1434     p_pdcp_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1435     /* Can't dissect anything without it... */
1436     if (p_pdcp_info == NULL) {
1437         return;
1438     }
1439
1440
1441     /* Set mode string */
1442     mode = val_to_str(p_pdcp_info->mode, rohc_mode_vals, "Error");
1443
1444     /* Show configuration (attached packet) info in tree */
1445     if (pdcp_tree) {
1446         show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1447     }
1448
1449     /* Show ROHC mode */
1450     if (p_pdcp_info->rohc_compression &&
1451         check_col(pinfo->cinfo, COL_INFO)) {
1452
1453         col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1454     }
1455
1456
1457     /* Handle PDCP header (if present) */
1458     if (!p_pdcp_info->no_header_pdu) {
1459
1460         /*****************************/
1461         /* Signalling plane messages */
1462         if (p_pdcp_info->plane == SIGNALING_PLANE) {
1463             guint32 mac;
1464             guint32 data_length;
1465
1466             /* 5-bit sequence number */
1467             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, FALSE);
1468             if (check_col(pinfo->cinfo, COL_INFO)) {
1469                 col_append_fstr(pinfo->cinfo, COL_INFO, " sn=%u ",
1470                                 tvb_get_guint8(tvb, offset) & 0x1f);
1471             }
1472             offset++;
1473
1474
1475             /* RRC data is all but last 4 bytes.
1476                Call lte-rrc dissector (according to direction and channel type) */
1477             if (global_pdcp_dissect_signalling_plane_as_rrc) {
1478                 /* Get appropriate dissector handle */
1479                 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1480
1481                 if (rrc_handle != 0) {
1482                     /* Call RRC dissector if have one */
1483                     tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
1484                                                            tvb_length_remaining(tvb, offset) - 4,
1485                                                            tvb_length_remaining(tvb, offset) - 4);
1486                     call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
1487                 }
1488                 else {
1489                      /* Just show data */
1490                         proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1491                                             tvb_length_remaining(tvb, offset) - 4, FALSE);
1492                 }
1493             }
1494             else {
1495                 /* Just show as unparsed data */
1496                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1497                                     tvb_length_remaining(tvb, offset) - 4, FALSE);
1498             }
1499
1500             data_length = tvb_length_remaining(tvb, offset) - 4;
1501             offset += data_length;
1502
1503             /* Last 4 bytes are MAC */
1504             mac = tvb_get_ntohl(tvb, offset);
1505             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, tvb, offset, 4, FALSE);
1506             offset += 4;
1507
1508             if (check_col(pinfo->cinfo, COL_INFO)) {
1509                 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
1510                                 mac, data_length);
1511             }
1512
1513             return;
1514         }
1515         else if (p_pdcp_info->plane == USER_PLANE) {
1516
1517             /**********************************/
1518             /* User-plane messages            */
1519             guint16 seqnum;
1520             gboolean pdu_type = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1521
1522             /* Data/Control flag */
1523             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, FALSE);
1524
1525             if (pdu_type == 1) {
1526                 /*****************************/
1527                 /* Use-plane Data            */
1528
1529                 /* Number of sequence number bits depends upon config */
1530                 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_7_BITS) {
1531                     seqnum = tvb_get_guint8(tvb, offset) & 0x7f;
1532                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, FALSE);
1533                     offset++;
1534                 }
1535                 else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
1536                     proto_item *ti;
1537                     guint8 reserved_value;
1538
1539                     /* 3 reserved bits */
1540                     ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, FALSE);
1541                     reserved_value = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
1542
1543                     /* Complain if not 0 */
1544                     if (reserved_value != 0) {
1545                         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
1546                                                "Reserved bits have value 0x%x - should be 0x0",
1547                                                reserved_value);
1548                     }
1549
1550                     /* 12-bit sequence number */
1551                     seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
1552                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, FALSE);
1553                     offset += 2;
1554                 }
1555                 else {
1556                     /* Not a recognised data format!!!!! */
1557                     return;
1558                 }
1559
1560                 if (check_col(pinfo->cinfo, COL_INFO)) {
1561                     col_append_fstr(pinfo->cinfo, COL_INFO, " sn=%u ", seqnum);
1562                 }
1563             }
1564             else {
1565                 /*******************************/
1566                 /* User-plane Control messages */
1567                 guint8 control_pdu_type = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
1568                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, FALSE);
1569
1570                 switch (control_pdu_type) {
1571                     case 0:    /* PDCP status report */
1572                         {
1573                             guint16 fms;
1574                             guint   not_received = 0;
1575                             guint   sn;
1576                             proto_tree *bitmap_tree;
1577                             proto_item *bitmap_ti;
1578
1579                             /* First-Missing-Sequence SN */
1580                             fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
1581                             sn = fms;
1582                             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
1583                                                 offset, 2, FALSE);
1584                             offset += 2;
1585
1586                             /* Bitmap tree */
1587                             bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
1588                                                             offset, -1, FALSE);
1589                             bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_rohc_report_bitmap);
1590
1591
1592                             /* For each byte... */
1593                             for ( ; tvb_length_remaining(tvb, offset); offset++) {
1594                                 guint bit_offset = 0;
1595                                 /* .. look for error (0) in each bit */
1596                                 for ( ; bit_offset < 8; bit_offset++) {
1597                                     if ((tvb_get_guint8(tvb, offset) >> (7-bit_offset) & 0x1) == 0) {
1598                                         proto_tree_add_boolean_format_value(bitmap_tree, hf_pdcp_lte_bitmap_not_received, tvb, offset, 1, TRUE,
1599                                                                             " (SN=%u)", sn);
1600                                         not_received++;
1601                                     }
1602                                     sn = (sn + 1) % 4096;
1603                                 }
1604                             }
1605
1606                             proto_item_append_text(bitmap_ti, " (not-received=%u)", not_received);
1607                             if (check_col(pinfo->cinfo, COL_INFO)) {
1608                                 col_append_fstr(pinfo->cinfo, COL_INFO,
1609                                                " Status Report (fms=%u) not-received=%u",
1610                                                fms, not_received);
1611                             }
1612                         }
1613                         return;
1614
1615                     case 1:     /* ROHC Feedback */
1616                         offset++;
1617                         break;  /* Drop-through to dissect feedback */
1618
1619                     default:    /* Reserved */
1620                         return;
1621                 }
1622             }
1623         }
1624         else {
1625             /* Invalid plane setting...! */
1626             if (check_col(pinfo->cinfo, COL_INFO)) {
1627                 col_append_fstr(pinfo->cinfo, COL_INFO, " - INVALID PLANE (%u)",
1628                                 p_pdcp_info->plane);
1629             }
1630             return;
1631         }
1632     }
1633     else {
1634         /* Show that its a no-header PDU */
1635         if (check_col(pinfo->cinfo, COL_INFO)) {
1636             col_append_str(pinfo->cinfo, COL_INFO, " No-Header ");
1637         }
1638     }
1639
1640
1641     /* If not compressed with ROHC, show as user-plane data */
1642     if (!p_pdcp_info->rohc_compression) {
1643
1644         if (global_pdcp_dissect_user_plane_as_ip && (ip_handle != 0)) {
1645             tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset, -1, -1);
1646             call_dissector_only(ip_handle, payload_tvb, pinfo, pdcp_tree);
1647         }
1648         else {
1649             if (tvb_length_remaining(tvb, offset) > 0) {
1650                 if (p_pdcp_info->plane == USER_PLANE) {
1651                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, tvb, offset, -1, FALSE);
1652                 }
1653                 else {
1654                     if (global_pdcp_dissect_signalling_plane_as_rrc) {
1655                         /* Get appropriate dissector handle */
1656                         dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1657
1658                         if (rrc_handle != 0) {
1659                             /* Call RRC dissector if have one */
1660                             tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
1661                                                                    tvb_length_remaining(tvb, offset),
1662                                                                    tvb_length_remaining(tvb, offset));
1663                             call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
1664                         }
1665                         else {
1666                              /* Just show data */
1667                              proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1668                                                  tvb_length_remaining(tvb, offset), FALSE);
1669                         }
1670                     }
1671                     else {
1672                         proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset, -1, FALSE);
1673                     }
1674                 }
1675
1676                 if (check_col(pinfo->cinfo, COL_INFO)) {
1677                     col_append_fstr(pinfo->cinfo, COL_INFO, "(%u bytes data)",
1678                                     tvb_length_remaining(tvb, offset));
1679                 }
1680             }
1681         }
1682         return;
1683     }
1684
1685
1686     /***************************/
1687     /* ROHC packets            */
1688     /***************************/
1689
1690     if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
1691         col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
1692                         val_to_str(p_pdcp_info->profile, rohc_profile_vals, "Unkown"));
1693     }
1694
1695     /* Only attempt ROHC if configured to */
1696     if (!global_pdcp_dissect_rohc) {
1697         return;
1698     }
1699     
1700     /* Create pdcp tree. */
1701     if (pdcp_tree) {
1702         rohc_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_rohc, tvb, offset, -1, FALSE);
1703         rohc_tree = proto_item_add_subtree(rohc_ti, ett_pdcp_rohc);
1704     }
1705
1706     rohc_offset = offset;
1707
1708     /* Skip any leading padding octets (11100000) */
1709     while (tvb_get_guint8(tvb, offset) == 0xe0) {
1710         offset++;
1711     }
1712     if (offset > rohc_offset) {
1713         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_padding, tvb, rohc_offset,
1714                             offset-rohc_offset, FALSE);
1715     }
1716
1717     /* Add-CID octet */
1718     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
1719         !p_pdcp_info->large_cid_present)
1720     {
1721         if (((tvb_get_guint8(tvb, offset) >> 4) & 0x0f) == 0x0e) {
1722             proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
1723             offset++;
1724         }
1725         else {
1726             /* Assume CID value of 0 if field absent */
1727             proto_item *ti = proto_tree_add_uint(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 0, 0);
1728             PROTO_ITEM_SET_GENERATED(ti);
1729         }
1730     }
1731
1732     /* Now look at first octet of base header and identify packet type */
1733     base_header_byte = tvb_get_guint8(tvb, offset);
1734
1735     /* IR (1111110) */
1736     if ((base_header_byte & 0xfe) == 0xfc) {
1737         offset = dissect_pdcp_ir_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1738         udp_checksum_needed = FALSE;
1739         ip_id_needed = FALSE;
1740     }
1741
1742     /* IRDYN (11111000) */
1743     else if (base_header_byte == 0xf8) {
1744         offset = dissect_pdcp_irdyn_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1745         udp_checksum_needed = FALSE;
1746         ip_id_needed = FALSE;
1747     }
1748
1749     /* Feedback (begins with 11110) */
1750     else if (((base_header_byte & 0xf8) >> 3) == 0x1e) {
1751         offset = dissect_pdcp_feedback_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1752         return;
1753     }
1754
1755     /* Packet type 0 (0) */
1756     else if ((base_header_byte & 0x80) == 0) {
1757
1758         /* TODO: decide type based upon:
1759            - mode
1760            - 2nd bit
1761            - length remaining (taking into account large-cid) */
1762
1763         /* R-0 begins with 00 */
1764         if (((base_header_byte & 0xc0) == 0) &&
1765              (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
1766
1767             offset = dissect_pdcp_r_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1768         }
1769
1770         /* R-0-CRC begins with 01 */
1771         else if ((((base_header_byte & 0x40) >> 6) == 1) &&
1772                   (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
1773
1774             offset = dissect_pdcp_r_0_crc_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1775         }
1776
1777         else {
1778             offset = dissect_pdcp_uo_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1779         }
1780     }
1781
1782     /* Packet type 1 (10) */
1783     else if (((base_header_byte & 0xc0) >> 6) == 2) {
1784
1785         switch (p_pdcp_info->mode) {
1786
1787             case RELIABLE_BIDIRECTIONAL:
1788                  /* R-1 if !(ipv4 && rand) */
1789                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
1790                       (!p_pdcp_info->rnd))) {
1791                     offset = dissect_pdcp_r_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1792                     return;
1793                  }
1794                 else {
1795                     /* Whether its R-1-ID or R-1-TS depends upon T bit */
1796                     dissect_pdcp_r_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1797                     return;
1798                 }
1799                 break;
1800
1801             case UNIDIRECTIONAL:
1802             case OPTIMISTIC_BIDIRECTIONAL:
1803                  /* UO-1 if !(ipv4 && rand) */
1804                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
1805                       (!p_pdcp_info->rnd))) {
1806                     offset = dissect_pdcp_uo_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1807                     return;
1808                  }
1809                 else {
1810                     /* Whether its UO-1-ID or UO-1-TS depends upon T bit */
1811                     dissect_pdcp_uo_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1812                     return;
1813                 }
1814
1815                 return; 
1816
1817         }
1818     }
1819
1820     /* Packet type 2 (110) */
1821     else if (((base_header_byte & 0xe0) >> 5) == 6) {
1822
1823         /* UOR-2 if !(ipv4 && rand) */
1824         if (!((p_pdcp_info->rohc_ip_version == 4) &&
1825               (!p_pdcp_info->rnd))) {
1826
1827             offset = dissect_pdcp_uor_2_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1828         }
1829         else {
1830             /* Whether its UOR-2-ID or UOR-2-TS depends upon T bit */
1831             dissect_pdcp_uor_2_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
1832             return;
1833         }
1834     }
1835
1836     /* Segment (1111111) */
1837     else if ((base_header_byte & 0xfe) == 0xfe) {
1838         /* TODO: */
1839         return;
1840     }
1841
1842
1843     /* Fields beyond base header */
1844
1845     /* These 2 fields not present for IR, IR-DYN frames */
1846
1847     /* IP-ID */
1848     if (p_pdcp_info->rnd && ip_id_needed) {
1849         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_ip_id, tvb, offset, 2, FALSE);
1850         offset += 2;
1851     }
1852
1853     /* UDP Checksum */
1854     if (p_pdcp_info->udp_checkum_present && udp_checksum_needed) {
1855         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_udp_checksum, tvb, offset, 2, FALSE);
1856         offset += 2;
1857     }
1858
1859     /* Payload */
1860     if (tvb_reported_length_remaining(tvb, offset) > 0) {
1861         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_payload, tvb, offset, -1, FALSE);
1862     }
1863 }
1864
1865 void proto_register_pdcp(void)
1866 {
1867     static hf_register_info hf[] =
1868     {
1869         { &hf_pdcp_lte_configuration,
1870             { "Configuration",
1871               "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
1872               "Configuation info passed into dissector", HFILL
1873             }
1874         },
1875
1876         { &hf_pdcp_lte_rohc_compression,
1877             { "ROHC Compression",
1878               "pdcp-lte.rohc", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1879               "ROHC Mode", HFILL
1880             }
1881         },
1882         { &hf_pdcp_lte_rohc_mode,
1883             { "ROHC mode",
1884               "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
1885               "ROHC Mode", HFILL
1886             }
1887         },
1888         { &hf_pdcp_lte_rohc_rnd,
1889             { "RND",  /* TODO: true/false vals? */
1890               "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
1891               "RND of outer ip header", HFILL
1892             }
1893         },
1894         { &hf_pdcp_lte_rohc_udp_checksum_present,
1895             { "UDP Checksum",  /* TODO: true/false vals? */
1896               "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1897               "UDP Checksum_present", HFILL
1898             }
1899         },
1900
1901
1902         { &hf_pdcp_lte_direction,
1903             { "Direction",
1904               "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1905               "Direction of message", HFILL
1906             }
1907         },
1908         { &hf_pdcp_lte_rohc_profile,
1909             { "ROHC profile",
1910               "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
1911               "ROHC Mode", HFILL
1912             }
1913         },
1914         { &hf_pdcp_lte_no_header_pdu,
1915             { "No Header PDU",
1916               "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
1917               NULL, HFILL
1918             }
1919         },
1920         { &hf_pdcp_lte_plane,
1921             { "Plane",
1922               "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
1923               "No Header PDU", HFILL
1924             }
1925         },
1926         { &hf_pdcp_lte_seqnum_length,
1927             { "Seqnum length",
1928               "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1929               "Sequence Number Length", HFILL
1930             }
1931         },
1932
1933
1934         { &hf_pdcp_lte_cid_inclusion_info,
1935             { "CID Inclusion Info",
1936               "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
1937               NULL, HFILL
1938             }
1939         },
1940         { &hf_pdcp_lte_large_cid_present,
1941             { "Large CID Present",
1942               "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1943               NULL, HFILL
1944             }
1945         },
1946
1947         { &hf_pdcp_lte_seq_num_5,
1948             { "Seq Num",
1949               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
1950               "PDCP Seq num", HFILL
1951             }
1952         },
1953         { &hf_pdcp_lte_seq_num_7,
1954             { "Seq Num",
1955               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
1956               "PDCP Seq num", HFILL
1957             }
1958         },
1959         { &hf_pdcp_lte_reserved3,
1960             { "Reserved",
1961               "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
1962               "3 reserved bits", HFILL
1963             }
1964         },
1965         { &hf_pdcp_lte_seq_num_12,
1966             { "Seq Num",
1967               "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
1968               "PDCP Seq num", HFILL
1969             }
1970         },
1971         { &hf_pdcp_lte_signalling_data,
1972             { "Signalling Data",
1973               "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
1974               NULL, HFILL
1975             }
1976         },
1977         { &hf_pdcp_lte_mac,
1978             { "MAC",
1979               "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
1980               NULL, HFILL
1981             }
1982         },
1983         { &hf_pdcp_lte_data_control,
1984             { "PDU Type",
1985               "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
1986               "PDU type", HFILL
1987             }
1988         },
1989         { &hf_pdcp_lte_user_plane_data,
1990             { "User-Plane Data",
1991               "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
1992               NULL, HFILL
1993             }
1994         },
1995         { &hf_pdcp_lte_control_pdu_type,
1996             { "Control PDU Type",
1997               "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
1998               "Control PDU type", HFILL
1999             }
2000         },
2001         { &hf_pdcp_lte_fms,
2002             { "First Missing Sequence Number",
2003               "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2004               "First Missing PDCP Sequence Number", HFILL
2005             }
2006         },
2007         { &hf_pdcp_lte_bitmap,
2008             { "Bitmap",
2009               "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2010               "Status report bitmap (0=error, 1=OK)", HFILL
2011             }
2012         },
2013         { &hf_pdcp_lte_bitmap_not_received,
2014             { "Not Received",
2015               "pdcp-lte.bitmap.error", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2016               "Status report PDU error", HFILL
2017             }
2018         },
2019
2020         { &hf_pdcp_lte_rohc,
2021             { "ROHC Message",
2022               "pdcp-lte.rohc", FT_NONE, BASE_NONE, NULL, 0,
2023               NULL, HFILL
2024             }
2025         },
2026
2027         { &hf_pdcp_lte_rohc_padding,
2028             { "Padding",
2029               "pdcp-lte.rohc.padding", FT_NONE, BASE_NONE, NULL, 0,
2030               "ROHC Padding", HFILL
2031             }
2032         },
2033         { &hf_pdcp_lte_rohc_r_0_crc,
2034             { "R-0-CRC Packet",
2035               "pdcp-lte.r-0-crc", FT_NONE, BASE_NONE, NULL, 0,
2036               NULL, HFILL
2037             }
2038         },
2039         { &hf_pdcp_lte_rohc_feedback,
2040             { "Feedback",
2041               "pdcp-lte.rohc.feedback", FT_NONE, BASE_NONE, NULL, 0,
2042               "Feedback Packet", HFILL
2043             }
2044         },
2045
2046         { &hf_pdcp_lte_rohc_type0_t,
2047             { "T",
2048               "pdcp-lte.rohc.t0.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x20,
2049               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2050             }
2051         },
2052         { &hf_pdcp_lte_rohc_type1_t,
2053             { "T",
2054               "pdcp-lte.rohc.t1.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2055               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2056             }
2057         },
2058         { &hf_pdcp_lte_rohc_type2_t,
2059             { "T",
2060               "pdcp-lte.rohc.t2.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2061               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2062             }
2063         },
2064
2065         { &hf_pdcp_lte_rohc_d,
2066             { "D",
2067               "pdcp-lte.rohc.t2.t", FT_UINT8, BASE_HEX, NULL, 0x01,
2068               "Indicates whether Dynamic chain is present", HFILL
2069             }
2070         },
2071         { &hf_pdcp_lte_rohc_ir_crc,
2072             { "CRC",
2073               "pdcp-lte.rohc.ir.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
2074               "8-bit CRC", HFILL
2075             }
2076         },
2077
2078         { &hf_pdcp_lte_rohc_static_ipv4,
2079             { "Static IPv4 chain",
2080               "pdcp-lte.rohc.static.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2081               NULL, HFILL
2082             }
2083         },
2084         { &hf_pdcp_lte_rohc_ip_version,
2085             { "IP Version",
2086               "pdcp-lte.rohc.ip-version", FT_UINT8, BASE_HEX, NULL, 0xf0,
2087               NULL, HFILL
2088             }
2089         },
2090         /* TODO: create/use value_string */
2091         { &hf_pdcp_lte_rohc_ip_protocol,
2092             { "IP Protocol",
2093               "pdcp-lte.rohc.ip-protocol", FT_UINT8, BASE_DEC, VALS(ip_protocol_vals), 0x0,
2094               NULL, HFILL
2095             }
2096         },
2097         { &hf_pdcp_lte_rohc_ip_src,
2098             { "IP Source address",
2099               "pdcp-lte.rohc.ip-src", FT_IPv4, BASE_NONE, NULL, 0x0,
2100               NULL, HFILL
2101             }
2102         },
2103         { &hf_pdcp_lte_rohc_ip_dst,
2104             { "IP Destination address",
2105               "pdcp-lte.rohc.ip-dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2106               NULL, HFILL
2107             }
2108         },
2109
2110         { &hf_pdcp_lte_rohc_static_udp,
2111             { "Static UDP chain",
2112               "pdcp-lte.rohc.static.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2113               NULL, HFILL
2114             }
2115         },
2116         { &hf_pdcp_lte_rohc_static_udp_src_port,
2117             { "Static UDP source port",
2118               "pdcp-lte.rohc.static.udp.src-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2119               NULL, HFILL
2120             }
2121         },
2122         { &hf_pdcp_lte_rohc_static_udp_dst_port,
2123             { "Static UDP destination port",
2124               "pdcp-lte.rohc.static.udp.dst-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2125               NULL, HFILL
2126             }
2127         },
2128
2129
2130         { &hf_pdcp_lte_rohc_static_rtp,
2131             { "Static RTP chain",
2132               "pdcp-lte.rohc.static.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2133               NULL, HFILL
2134             }
2135         },
2136         { &hf_pdcp_lte_rohc_static_rtp_ssrc,
2137             { "SSRC",
2138               "pdcp-lte.rohc.static.rtp.ssrc", FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2139               "Static RTP chain SSRC", HFILL
2140             }
2141         },
2142
2143         { &hf_pdcp_lte_rohc_dynamic_ipv4,
2144             { "Dynamic IPv4 chain",
2145               "pdcp-lte.rohc.dynamic.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2146               NULL, HFILL
2147             }
2148         },
2149         { &hf_pdcp_lte_rohc_dynamic_ipv4_tos,
2150             { "ToS",
2151               "pdcp-lte.rohc.ip.tos", FT_UINT8, BASE_HEX, NULL, 0x0,
2152               "IP Type of Service", HFILL
2153             }
2154         },
2155         { &hf_pdcp_lte_rohc_dynamic_ipv4_ttl,
2156             { "TTL",
2157               "pdcp-lte.rohc.ip.ttl", FT_UINT8, BASE_HEX, NULL, 0x0,
2158               "IP Time To Live", HFILL
2159             }
2160         },
2161         { &hf_pdcp_lte_rohc_dynamic_ipv4_id,
2162             { "IP-ID",
2163               "pdcp-lte.rohc.ip.id", FT_UINT8, BASE_HEX, NULL, 0x0,
2164               "IP ID", HFILL
2165             }
2166         },
2167         { &hf_pdcp_lte_rohc_dynamic_ipv4_df,
2168             { "Don't Fragment",
2169               "pdcp-lte.rohc.ip.df", FT_UINT8, BASE_HEX, NULL, 0x80,
2170               "IP Don't Fragment flag", HFILL
2171             }
2172         },
2173         { &hf_pdcp_lte_rohc_dynamic_ipv4_rnd,
2174             { "Random IP-ID field",
2175               "pdcp-lte.rohc.ip.rnd", FT_UINT8, BASE_HEX, NULL, 0x40,
2176               NULL, HFILL
2177             }
2178         },
2179         { &hf_pdcp_lte_rohc_dynamic_ipv4_nbo,
2180             { "Network Byte Order IP-ID field",
2181               "pdcp-lte.rohc.ip.nbo", FT_UINT8, BASE_HEX, NULL, 0x20,
2182               NULL, HFILL
2183             }
2184         },
2185
2186         { &hf_pdcp_lte_rohc_dynamic_udp,
2187             { "Dynamic UDP chain",
2188               "pdcp-lte.rohc.dynamic.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2189               NULL, HFILL
2190             }
2191         },
2192         { &hf_pdcp_lte_rohc_dynamic_udp_checksum,
2193             { "UDP Checksum",
2194               "pdcp-lte.rohc.dynamic.udp.checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2195               NULL, HFILL
2196             }
2197         },
2198         { &hf_pdcp_lte_rohc_dynamic_udp_seqnum,
2199             { "UDP Sequence Number",
2200               "pdcp-lte.rohc.dynamic.udp.seqnum", FT_UINT16, BASE_HEX, NULL, 0x0,
2201               NULL, HFILL
2202             }
2203         },
2204
2205         { &hf_pdcp_lte_rohc_dynamic_rtp,
2206             { "Dynamic RTP chain",
2207               "pdcp-lte.rohc.dynamic.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2208               NULL, HFILL
2209             }
2210         },
2211         { &hf_pdcp_lte_rohc_dynamic_rtp_rx,
2212             { "RX",
2213               "pdcp-lte.rohc.dynamic.rtp.rx", FT_UINT8, BASE_DEC, NULL, 0x10,
2214               NULL, HFILL
2215             }
2216         },
2217         { &hf_pdcp_lte_rohc_dynamic_rtp_cc,
2218             { "Contributing CSRCs",
2219               "pdcp-lte.rohc.dynamic.rtp.cc", FT_UINT8, BASE_DEC, NULL, 0x0f,
2220               "Dynamic RTP chain CCs", HFILL
2221             }
2222         },
2223         { &hf_pdcp_lte_rohc_dynamic_rtp_seqnum,
2224             { "RTP Sequence Number",
2225               "pdcp-lte.rohc.dynamic.rtp.seqnum", FT_UINT16, BASE_DEC, NULL, 0x0,
2226               "Dynamic RTP chain Sequence Number", HFILL
2227             }
2228         },
2229         { &hf_pdcp_lte_rohc_dynamic_rtp_timestamp,
2230             { "RTP Timestamp",
2231               "pdcp-lte.rohc.dynamic.rtp.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2232               "Dynamic RTP chain Timestamp", HFILL
2233             }
2234         },
2235
2236         { &hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
2237             { "Reserved",
2238               "pdcp-lte.rohc.dynamic.rtp.reserved3", FT_UINT8, BASE_HEX, NULL, 0xc0,
2239               "Reserved bits", HFILL
2240             }
2241         },
2242         { &hf_pdcp_lte_rohc_dynamic_rtp_x,
2243             { "X",
2244               "pdcp-lte.rohc.dynamic.rtp.x", FT_UINT8, BASE_DEC, NULL, 0x10,
2245               NULL, HFILL
2246             }
2247         },
2248         { &hf_pdcp_lte_rohc_dynamic_rtp_mode,
2249             { "Mode",
2250               "pdcp-lte.rohc.dynamic.rtp.mode", FT_UINT8, BASE_HEX, VALS(rohc_mode_vals), 0x0c,
2251               NULL, HFILL
2252             }
2253         },
2254         { &hf_pdcp_lte_rohc_dynamic_rtp_tis,
2255             { "TIS",
2256               "pdcp-lte.rohc.dynamic.rtp.tis", FT_UINT8, BASE_HEX, NULL, 0x02,
2257               "Dynamic RTP chain TIS (indicates time_stride present)", HFILL
2258             }
2259         },
2260         { &hf_pdcp_lte_rohc_dynamic_rtp_tss,
2261             { "TSS",
2262               "pdcp-lte.rohc.dynamic.rtp.tss", FT_UINT8, BASE_HEX, NULL, 0x01,
2263               "Dynamic RTP chain TSS (indicates TS_stride present)", HFILL
2264             }
2265         },
2266         { &hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
2267             { "TS Stride",
2268               "pdcp-lte.rohc.dynamic.rtp.ts-stride", FT_UINT32, BASE_DEC, NULL, 0x0,
2269               "Dynamic RTP chain TS Stride", HFILL
2270             }
2271         },
2272         { &hf_pdcp_lte_rohc_ts,
2273             { "TS",
2274               "pdcp-lte.rohc.ts", FT_UINT8, BASE_DEC, NULL, 0x0,
2275               NULL, HFILL
2276             }
2277         },
2278         { &hf_pdcp_lte_rohc_m,
2279             { "M",
2280               "pdcp-lte.rohc.m", FT_UINT8, BASE_DEC, NULL, 0x40,
2281               NULL, HFILL
2282             }
2283         },
2284         { &hf_pdcp_lte_rohc_uor2_sn,
2285             { "SN",
2286               "pdcp-lte.rohc.uor2.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2287               NULL, HFILL
2288             }
2289         },
2290         { &hf_pdcp_lte_rohc_uor2_x,
2291             { "X",
2292               "pdcp-lte.rohc.uor2.x", FT_UINT8, BASE_DEC, NULL, 0x80,
2293               NULL, HFILL
2294             }
2295         },
2296
2297         { &hf_pdcp_lte_rohc_add_cid,
2298             { "Add-CID",
2299               "pdcp-lte.rohc.add-cid", FT_UINT8, BASE_DEC, NULL, 0x0f,
2300               NULL, HFILL
2301             }
2302         },
2303         { &hf_pdcp_lte_rohc_large_cid,
2304             { "Large-CID",
2305               "pdcp-lte.rohc.large-cid", FT_UINT16, BASE_DEC, NULL, 0x07ff,
2306               NULL, HFILL
2307             }
2308         },
2309         { &hf_pdcp_lte_rohc_uo0_sn,
2310             { "SN",
2311               "pdcp-lte.rohc.uo0.sn", FT_UINT8, BASE_DEC, NULL, 0x78,
2312               NULL, HFILL
2313             }
2314         },
2315         { &hf_pdcp_lte_rohc_uo0_crc,
2316             { "CRC",
2317               "pdcp-lte.rohc.uo0.crc", FT_UINT8, BASE_DEC, NULL, 0x07,
2318               "3-bit CRC", HFILL
2319             }
2320         },
2321         { &hf_pdcp_lte_rohc_r0_sn,
2322             { "SN",
2323               "pdcp-lte.rohc.r0.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2324               NULL, HFILL
2325             }
2326         },
2327         { &hf_pdcp_lte_rohc_r0_crc_sn,
2328             { "SN",
2329               "pdcp-lte.rohc.r0-crc.sn", FT_UINT16, BASE_DEC, NULL, 0x0,
2330               NULL, HFILL
2331             }
2332         },
2333         { &hf_pdcp_lte_rohc_r0_crc_crc,
2334             { "CRC7",
2335               "pdcp-lte.rohc.r0-crc.crc", FT_UINT8, BASE_DEC, NULL, 0x7f,
2336               "CRC 7", HFILL
2337             }
2338         },
2339
2340         { &hf_pdcp_lte_rohc_feedback_code,
2341             { "Code",
2342               "pdcp-lte.rohc.feedback-code", FT_UINT8, BASE_DEC, NULL, 0x07,
2343               "Feedback options length (if > 0)", HFILL
2344             }
2345         },
2346         { &hf_pdcp_lte_rohc_feedback_size,
2347             { "Size",
2348               "pdcp-lte.rohc.feedback-size", FT_UINT8, BASE_DEC, NULL, 0x0,
2349               "Feedback options length", HFILL
2350             }
2351         },
2352         { &hf_pdcp_lte_rohc_feedback_feedback1,
2353             { "FEEDBACK-1 (SN)",
2354               "pdcp-lte.rohc.feedback.feedback1", FT_UINT8, BASE_DEC, NULL, 0x0,
2355               "Feedback-1", HFILL
2356             }
2357         },
2358         { &hf_pdcp_lte_rohc_feedback_feedback2,
2359             { "FEEDBACK-2",
2360               "pdcp-lte.rohc.feedback.feedback2", FT_NONE, BASE_NONE, NULL, 0x0,
2361               "Feedback-2", HFILL
2362             }
2363         },
2364
2365         { &hf_pdcp_lte_rohc_feedback_ack_type,
2366             { "Acktype",
2367               "pdcp-lte.rohc.feedback-acktype", FT_UINT8, BASE_DEC, VALS(feedback_ack_vals), 0xc0,
2368               "Feedback-2 ack type", HFILL
2369             }
2370         },
2371         { &hf_pdcp_lte_rohc_feedback_mode,
2372             { "mode",
2373               "pdcp-lte.rohc.feedback-mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
2374               "Feedback mode", HFILL
2375             }
2376         },
2377         { &hf_pdcp_lte_rohc_feedback_sn,
2378             { "SN",
2379               "pdcp-lte.rohc.feedback-sn", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2380               "Feedback mode", HFILL
2381             }
2382         },
2383
2384         { &hf_pdcp_lte_rohc_feedback_option,
2385             { "Option",
2386               "pdcp-lte.rohc.feedback-option", FT_UINT8, BASE_DEC, VALS(feedback_option_vals), 0xf0,
2387               "Feedback mode", HFILL
2388             }
2389         },
2390         { &hf_pdcp_lte_rohc_feedback_length,
2391             { "Length",
2392               "pdcp-lte.rohc.feedback-length", FT_UINT8, BASE_DEC, NULL, 0x0f,
2393               "Feedback length", HFILL
2394             }
2395         },
2396         { &hf_pdcp_lte_rohc_feedback_crc,
2397             { "CRC",
2398               "pdcp-lte.rohc.feedback-crc", FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2399               "Feedback CRC", HFILL
2400             }
2401         },
2402         { &hf_pdcp_lte_rohc_feedback_option_sn,
2403             { "SN",
2404               "pdcp-lte.rohc.feedback-option-sn", FT_UINT8, BASE_DEC, NULL, 0x0,
2405               "Feedback Option SN", HFILL
2406             }
2407         },
2408         { &hf_pdcp_lte_rohc_feedback_option_clock,
2409             { "Clock",
2410               "pdcp-lte.rohc.feedback-option-clock", FT_UINT8, BASE_DEC, NULL, 0x0,
2411               "Feedback Option Clock", HFILL
2412             }
2413         },
2414
2415         { &hf_pdcp_lte_rohc_ip_id,
2416             { "IP-ID",
2417               "pdcp-lte.rohc.ip-id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2418               NULL, HFILL
2419             }
2420         },
2421         { &hf_pdcp_lte_rohc_udp_checksum,
2422             { "UDP Checksum",
2423               "pdcp-lte.rohc.udp-checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2424               NULL, HFILL
2425             }
2426         },
2427         { &hf_pdcp_lte_rohc_payload,
2428             { "Payload",
2429               "pdcp-lte.rohc.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
2430               NULL, HFILL
2431             }
2432         },
2433
2434     };
2435
2436     static gint *ett[] =
2437     {
2438         &ett_pdcp,
2439         &ett_pdcp_configuration,
2440         &ett_pdcp_packet,
2441         &ett_pdcp_rohc,
2442         &ett_pdcp_rohc_static_ipv4,
2443         &ett_pdcp_rohc_static_udp,
2444         &ett_pdcp_rohc_static_rtp,
2445         &ett_pdcp_rohc_dynamic_ipv4,
2446         &ett_pdcp_rohc_dynamic_udp,
2447         &ett_pdcp_rohc_dynamic_rtp,
2448         &ett_pdcp_rohc_report_bitmap
2449     };
2450
2451     module_t *pdcp_lte_module;
2452
2453     /* Register protocol. */
2454     proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
2455     proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
2456     proto_register_subtree_array(ett, array_length(ett));
2457
2458     /* Allow other dissectors to find this one by name. */
2459     register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
2460
2461     pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
2462
2463     /* Dissect uncompressed user-plane data as IP */
2464     prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
2465         "Show uncompressed User-Plane data as IP",
2466         "Show uncompressed User-Plane data as IP",
2467         &global_pdcp_dissect_user_plane_as_ip);
2468
2469     /* Dissect unciphered signalling data as RRC */
2470     prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
2471         "Show unciphered Signalling-Plane data as RRC",
2472         "Show unciphered Signalling-Plane data as RRC",
2473         &global_pdcp_dissect_signalling_plane_as_rrc);
2474
2475     /* Attempt to dissect ROHC headers */
2476     prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
2477         "Attempt to decode ROHC data",
2478         "Attempt to decode ROHC data",
2479         &global_pdcp_dissect_rohc);
2480
2481     prefs_register_bool_preference(pdcp_lte_module, "show_feedback_option_tag_length",
2482         "Show ROHC feedback option tag & length",
2483         "Show ROHC feedback option tag & length",
2484         &global_pdcp_show_feedback_option_tag_length);
2485 }
2486
2487 void proto_reg_handoff_pdcp_lte(void)
2488 {
2489     ip_handle = find_dissector("ip");
2490 }
2491