1 /* Routines for LTE PDCP
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/wmem/wmem.h>
39 #include <wsutil/wsgcrypt.h>
40 #endif /* HAVE_LIBGCRYPT */
42 #include "packet-rlc-lte.h"
43 #include "packet-pdcp-lte.h"
45 void proto_register_pdcp(void);
46 void proto_reg_handoff_pdcp_lte(void);
49 * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
50 * Packet Data Convergence Protocol (PDCP) specification v11.0.0
55 - Support for deciphering. Next steps are:
56 - use gcrypt to decipher AES frames
57 - separate preferences to control signalling/user-plane decryption?
58 - Verify MAC authentication bytes for supported protocol(s)?
59 - Add Relay Node user plane data PDU dissection
63 /* Initialize the protocol and registered fields. */
64 int proto_pdcp_lte = -1;
66 extern int proto_rlc_lte;
68 /* Configuration (info known outside of PDU) */
69 static int hf_pdcp_lte_configuration = -1;
70 static int hf_pdcp_lte_direction = -1;
71 static int hf_pdcp_lte_ueid = -1;
72 static int hf_pdcp_lte_channel_type = -1;
73 static int hf_pdcp_lte_channel_id = -1;
75 static int hf_pdcp_lte_rohc_compression = -1;
76 static int hf_pdcp_lte_rohc_mode = -1;
77 static int hf_pdcp_lte_rohc_rnd = -1;
78 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
79 static int hf_pdcp_lte_rohc_profile = -1;
81 static int hf_pdcp_lte_no_header_pdu = -1;
82 static int hf_pdcp_lte_plane = -1;
83 static int hf_pdcp_lte_seqnum_length = -1;
84 static int hf_pdcp_lte_cid_inclusion_info = -1;
85 static int hf_pdcp_lte_large_cid_present = -1;
87 /* PDCP header fields */
88 static int hf_pdcp_lte_control_plane_reserved = -1;
89 static int hf_pdcp_lte_seq_num_5 = -1;
90 static int hf_pdcp_lte_seq_num_7 = -1;
91 static int hf_pdcp_lte_reserved3 = -1;
92 static int hf_pdcp_lte_seq_num_12 = -1;
93 static int hf_pdcp_lte_seq_num_15 = -1;
94 static int hf_pdcp_lte_signalling_data = -1;
95 static int hf_pdcp_lte_mac = -1;
96 static int hf_pdcp_lte_data_control = -1;
97 static int hf_pdcp_lte_user_plane_data = -1;
98 static int hf_pdcp_lte_control_pdu_type = -1;
99 static int hf_pdcp_lte_fms = -1;
100 static int hf_pdcp_lte_reserved4 = -1;
101 static int hf_pdcp_lte_fms2 = -1;
102 static int hf_pdcp_lte_bitmap = -1;
105 /* Sequence Analysis */
106 static int hf_pdcp_lte_sequence_analysis = -1;
107 static int hf_pdcp_lte_sequence_analysis_ok = -1;
108 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
109 static int hf_pdcp_lte_sequence_analysis_next_frame = -1;
110 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
112 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
113 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
115 /* Security Settings */
116 static int hf_pdcp_lte_security = -1;
117 static int hf_pdcp_lte_security_setup_frame = -1;
118 static int hf_pdcp_lte_security_integrity_algorithm = -1;
119 static int hf_pdcp_lte_security_ciphering_algorithm = -1;
121 static int hf_pdcp_lte_security_bearer = -1;
122 static int hf_pdcp_lte_security_direction = -1;
123 static int hf_pdcp_lte_security_count = -1;
124 static int hf_pdcp_lte_security_key = -1;
128 /* Protocol subtree. */
129 static int ett_pdcp = -1;
130 static int ett_pdcp_configuration = -1;
131 static int ett_pdcp_packet = -1;
132 static int ett_pdcp_lte_sequence_analysis = -1;
133 static int ett_pdcp_report_bitmap = -1;
134 static int ett_pdcp_security = -1;
136 static expert_field ei_pdcp_lte_sequence_analysis_wrong_sequence_number = EI_INIT;
137 static expert_field ei_pdcp_lte_reserved_bits_not_zero = EI_INIT;
138 static expert_field ei_pdcp_lte_sequence_analysis_sn_repeated = EI_INIT;
139 static expert_field ei_pdcp_lte_sequence_analysis_sn_missing = EI_INIT;
141 #ifdef HAVE_LIBGCRYPT
142 /*-------------------------------------
144 *-------------------------------------
146 /* UAT entry structure. */
151 } uat_ue_keys_record_t;
153 static uat_ue_keys_record_t *uat_ue_keys_records = NULL;
155 static uat_t * ue_keys_uat = NULL;
156 static guint num_ue_keys_uat = 0;
158 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
159 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
160 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
162 new_rec->ueid = old_rec->ueid;
163 new_rec->rrcKey = (old_rec->rrcKey) ? g_strdup(old_rec->rrcKey) : NULL;
164 new_rec->upKey = (old_rec->upKey) ? g_strdup(old_rec->upKey) : NULL;
169 static void uat_ue_keys_record_free_cb(void*r) {
170 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
176 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
177 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcKey, uat_ue_keys_record_t)
178 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upKey, uat_ue_keys_record_t)
182 static const value_string direction_vals[] =
184 { DIRECTION_UPLINK, "Uplink"},
185 { DIRECTION_DOWNLINK, "Downlink"},
190 static const value_string pdcp_plane_vals[] = {
191 { SIGNALING_PLANE, "Signalling" },
192 { USER_PLANE, "User" },
196 static const value_string logical_channel_vals[] = {
197 { Channel_DCCH, "DCCH"},
198 { Channel_BCCH, "BCCH"},
199 { Channel_CCCH, "CCCH"},
200 { Channel_PCCH, "PCCH"},
204 static const value_string rohc_mode_vals[] = {
205 { UNIDIRECTIONAL, "Unidirectional" },
206 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
207 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
212 /* Values taken from:
213 http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
214 static const value_string rohc_profile_vals[] = {
215 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
216 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
217 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
218 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
219 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
220 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
221 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
222 { 0x0004, "ROHC IP" }, /* [RFC3843] */
223 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
224 { 0x0005, "ROHC LLA" }, /* [RFC4362] */
225 { 0x0105, "ROHC LLA with R-mode" }, /* [RFC3408] */
226 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
227 { 0x0007, "ROHC RTP/UDP-Lite" }, /* [RFC4019] */
228 { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /* [RFC5225] */
229 { 0x0008, "ROHC UDP-Lite" }, /* [RFC4019] */
230 { 0x0108, "ROHCv2 UDP-Lite" }, /* [RFC5225] */
234 static const value_string pdu_type_vals[] = {
235 { 0, "Control PDU" },
240 static const value_string control_pdu_type_vals[] = {
241 { 0, "PDCP Status report" },
242 { 1, "Header Compression Feedback Information" },
246 static const value_string integrity_algorithm_vals[] = {
253 static const value_string ciphering_algorithm_vals[] = {
261 static dissector_handle_t ip_handle;
262 static dissector_handle_t ipv6_handle;
263 static dissector_handle_t rohc_handle;
264 static dissector_handle_t data_handle;
267 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
268 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
270 /* Preference variables */
271 static gboolean global_pdcp_dissect_user_plane_as_ip = TRUE;
272 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = TRUE;
273 static gint global_pdcp_check_sequence_numbers = TRUE;
274 static gboolean global_pdcp_dissect_rohc = FALSE;
276 /* Which layer info to show in the info column */
278 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
280 static gint global_pdcp_lte_layer_to_show = (gint)ShowRLCLayer;
284 /**************************************************/
285 /* Sequence number analysis */
290 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
291 heap memory for these structs */
297 } pdcp_channel_hash_key;
302 guint16 previousSequenceNumber;
303 guint32 previousFrameNum;
305 } pdcp_channel_status;
307 /* The sequence analysis channel hash table.
308 Maps key -> status */
309 static GHashTable *pdcp_sequence_analysis_channel_hash = NULL;
312 static gint pdcp_channel_equal(gconstpointer v, gconstpointer v2)
314 /* Key fits in 4 bytes, so just compare pointers! */
318 /* Compute a hash value for a given key. */
319 static guint pdcp_channel_hash_func(gconstpointer v)
321 /* Just use pointer, as the fields are all in this value */
322 return GPOINTER_TO_UINT(v);
326 /* Hash table types & functions for frame reports */
332 guint32 channelId: 5;
333 guint32 direction: 1;
335 } pdcp_result_hash_key;
337 static gint pdcp_result_hash_equal(gconstpointer v, gconstpointer v2)
339 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
340 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
342 /* All fields must match */
343 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
346 /* Compute a hash value for a given key. */
347 static guint pdcp_result_hash_func(gconstpointer v)
349 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
351 /* TODO: This is a bit random. */
352 return val1->frameNumber + (val1->channelId<<13) +
355 (val1->direction<<9);
358 /* pdcp_channel_hash_key fits into the pointer, so just copy the value into
359 a guint, cast to apointer and return that as the key */
360 static gpointer get_channel_hash_key(pdcp_channel_hash_key *key)
363 /* TODO: assert that sizeof(pdcp_channel_hash_key) <= sizeof(guint) ? */
364 memcpy(&asInt, key, sizeof(pdcp_channel_hash_key));
365 return GUINT_TO_POINTER(asInt);
368 /* Convenience function to get a pointer for the hash_func to work with */
369 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
370 pdcp_lte_info *p_pdcp_lte_info,
373 static pdcp_result_hash_key key;
374 pdcp_result_hash_key *p_key;
376 /* Only allocate a struct when will be adding entry */
378 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
381 memset(&key, 0, sizeof(pdcp_result_hash_key));
385 /* Fill in details, and return pointer */
386 p_key->frameNumber = frameNumber;
388 p_key->plane = (guint8)p_pdcp_lte_info->plane;
389 p_key->channelId = p_pdcp_lte_info->channelId;
390 p_key->direction = p_pdcp_lte_info->direction;
397 /* Info to attach to frame when first read, recording what to show about sequence */
400 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
404 gboolean sequenceExpectedCorrect;
405 guint16 sequenceExpected;
406 guint32 previousFrameNum;
407 guint32 nextFrameNum;
413 sequence_state state;
414 } pdcp_sequence_report_in_frame;
416 /* The sequence analysis frame report hash table.
417 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
418 static GHashTable *pdcp_lte_sequence_analysis_report_hash = NULL;
420 /* Gather together security settings in order to be able to do deciphering */
421 typedef struct pdu_security_settings_t
424 enum security_ciphering_algorithm_e ciphering;
429 } pdu_security_settings_t;
432 /* Add to the tree values associated with sequence analysis for this frame */
433 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
434 pdcp_lte_info *p_pdcp_lte_info,
435 guint16 sequenceNumber,
436 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
437 proto_tree *security_tree,
438 pdu_security_settings_t *pdu_security)
440 proto_tree *seqnum_tree;
441 proto_item *seqnum_ti;
442 proto_item *ti_expected_sn;
446 seqnum_ti = proto_tree_add_string_format(tree,
447 hf_pdcp_lte_sequence_analysis,
449 "", "Sequence Analysis");
450 seqnum_tree = proto_item_add_subtree(seqnum_ti,
451 ett_pdcp_lte_sequence_analysis);
452 PROTO_ITEM_SET_GENERATED(seqnum_ti);
455 /* Previous channel frame */
456 if (p->previousFrameNum != 0) {
457 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
458 tvb, 0, 0, p->previousFrameNum);
461 /* Expected sequence number */
462 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
463 tvb, 0, 0, p->sequenceExpected);
464 PROTO_ITEM_SET_GENERATED(ti_expected_sn);
466 /* Make sure we have recognised SN length */
467 switch (p_pdcp_lte_info->seqnum_length) {
468 case PDCP_SN_LENGTH_5_BITS:
469 case PDCP_SN_LENGTH_7_BITS:
470 case PDCP_SN_LENGTH_12_BITS:
471 case PDCP_SN_LENGTH_15_BITS:
474 DISSECTOR_ASSERT_NOT_REACHED();
480 PROTO_ITEM_SET_HIDDEN(ti_expected_sn);
481 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
483 PROTO_ITEM_SET_GENERATED(ti);
484 proto_item_append_text(seqnum_ti, " - OK");
486 /* Link to next SN in channel (if known) */
487 if (p->nextFrameNum != 0) {
488 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_next_frame,
489 tvb, 0, 0, p->nextFrameNum);
492 /* May also be able to add key inputs to security tree here */
493 if (security_tree != NULL) {
494 guint32 hfn_multiplier;
500 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_bearer,
501 tvb, 0, 0, p_pdcp_lte_info->channelId-1);
502 PROTO_ITEM_SET_GENERATED(ti);
503 pdu_security->bearer = p_pdcp_lte_info->channelId-1;
506 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_direction,
507 tvb, 0, 0, p_pdcp_lte_info->direction);
508 PROTO_ITEM_SET_GENERATED(ti);
510 /* COUNT (HFN * snLength^2 + SN) */
511 switch (p_pdcp_lte_info->seqnum_length) {
512 case PDCP_SN_LENGTH_5_BITS:
515 case PDCP_SN_LENGTH_7_BITS:
516 hfn_multiplier = 128;
518 case PDCP_SN_LENGTH_12_BITS:
519 hfn_multiplier = 2048;
521 case PDCP_SN_LENGTH_15_BITS:
522 hfn_multiplier = 32768;
525 DISSECTOR_ASSERT_NOT_REACHED();
528 count = (p->hfn * hfn_multiplier) + sequenceNumber;
529 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_count,
531 PROTO_ITEM_SET_GENERATED(ti);
532 pdu_security->count = count;
535 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
536 if (uat_ue_keys_records[record_id].ueid == p_pdcp_lte_info->ueid) {
537 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
538 key = uat_ue_keys_records[record_id].rrcKey;
541 key = uat_ue_keys_records[record_id].upKey;
545 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_key,
547 PROTO_ITEM_SET_GENERATED(ti);
548 pdu_security->key = key;
553 pdu_security->direction = p_pdcp_lte_info->direction;
558 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
560 PROTO_ITEM_SET_GENERATED(ti);
561 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
563 PROTO_ITEM_SET_GENERATED(ti);
564 if (p->lastSN != p->firstSN) {
565 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
566 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
567 p->firstSN, p->lastSN,
568 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
569 p_pdcp_lte_info->ueid,
570 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
571 p_pdcp_lte_info->channelId);
572 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
573 p->firstSN, p->lastSN);
576 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
577 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
579 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
580 p_pdcp_lte_info->ueid,
581 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
582 p_pdcp_lte_info->channelId);
583 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
589 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
591 PROTO_ITEM_SET_GENERATED(ti);
592 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
594 PROTO_ITEM_SET_GENERATED(ti);
595 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_repeated,
596 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
598 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
599 p_pdcp_lte_info->ueid,
600 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
601 p_pdcp_lte_info->channelId);
602 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
607 /* Incorrect sequence number */
608 expert_add_info_format(pinfo, ti_expected_sn, &ei_pdcp_lte_sequence_analysis_wrong_sequence_number,
609 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
610 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
611 p_pdcp_lte_info->ueid,
612 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
613 p_pdcp_lte_info->channelId,
614 sequenceNumber, p->sequenceExpected);
620 /* Update the channel status and set report for this frame */
621 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
622 pdcp_lte_info *p_pdcp_lte_info,
623 guint16 sequenceNumber,
625 proto_tree *security_tree,
626 pdu_security_settings_t *pdu_security)
628 pdcp_channel_hash_key channel_key;
629 pdcp_channel_status *p_channel_status;
630 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
631 gboolean createdChannel = FALSE;
632 guint16 expectedSequenceNumber = 0;
635 /* If find stat_report_in_frame already, use that and get out */
636 if (pinfo->fd->flags.visited) {
638 (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
639 get_report_hash_key(sequenceNumber,
641 p_pdcp_lte_info, FALSE));
642 if (p_report_in_frame != NULL) {
643 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
645 pinfo, tree, tvb, security_tree, pdu_security);
649 /* Give up - we must have tried already... */
655 /**************************************************/
656 /* Create or find an entry for this channel state */
657 channel_key.ueId = p_pdcp_lte_info->ueid;
658 channel_key.plane = p_pdcp_lte_info->plane;
659 channel_key.channelId = p_pdcp_lte_info->channelId;
660 channel_key.direction = p_pdcp_lte_info->direction;
661 channel_key.notUsed = 0;
663 /* Do the table lookup */
664 p_channel_status = (pdcp_channel_status*)g_hash_table_lookup(pdcp_sequence_analysis_channel_hash,
665 get_channel_hash_key(&channel_key));
667 /* Create table entry if necessary */
668 if (p_channel_status == NULL) {
669 createdChannel = TRUE;
671 /* Allocate a new value and duplicate key contents */
672 p_channel_status = wmem_new0(wmem_file_scope(), pdcp_channel_status);
675 g_hash_table_insert(pdcp_sequence_analysis_channel_hash,
676 get_channel_hash_key(&channel_key), p_channel_status);
679 /* Create space for frame state_report */
680 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
681 p_report_in_frame->nextFrameNum = 0;
683 switch (p_pdcp_lte_info->seqnum_length) {
684 case PDCP_SN_LENGTH_5_BITS:
687 case PDCP_SN_LENGTH_7_BITS:
690 case PDCP_SN_LENGTH_12_BITS:
693 case PDCP_SN_LENGTH_15_BITS:
697 DISSECTOR_ASSERT_NOT_REACHED();
701 /* Work out expected sequence number */
702 if (!createdChannel) {
703 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
706 expectedSequenceNumber = sequenceNumber;
709 /* Set report for this frame */
710 /* For PDCP, sequence number is always expectedSequence number */
711 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
712 p_report_in_frame->hfn = p_channel_status->hfn;
714 /* For wrong sequence number... */
715 if (!p_report_in_frame->sequenceExpectedCorrect) {
717 /* Frames are not missing if we get an earlier sequence number again */
718 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
719 p_report_in_frame->state = SN_Missing;
720 p_report_in_frame->firstSN = expectedSequenceNumber;
721 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
723 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
724 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
726 /* Update channel status to remember *this* frame */
727 p_channel_status->previousFrameNum = pinfo->fd->num;
728 p_channel_status->previousSequenceNumber = sequenceNumber;
731 /* An SN has been repeated */
732 p_report_in_frame->state = SN_Repeated;
733 p_report_in_frame->firstSN = sequenceNumber;
735 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
736 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
741 p_report_in_frame->state = SN_OK;
742 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
743 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
744 /* SN has rolled around, inc hfn! */
745 if (!createdChannel && (sequenceNumber == 0)) {
746 /* TODO: not worrying about HFN rolling over for now! */
747 p_channel_status->hfn++;
748 p_report_in_frame->hfn = p_channel_status->hfn;
752 /* Update channel status to remember *this* frame */
753 p_channel_status->previousFrameNum = pinfo->fd->num;
754 p_channel_status->previousSequenceNumber = sequenceNumber;
756 if (p_report_in_frame->previousFrameNum != 0) {
757 /* Get report for previous frame */
758 pdcp_sequence_report_in_frame *p_previous_report;
759 p_previous_report = (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
760 get_report_hash_key((sequenceNumber+32767) % 32768,
761 p_report_in_frame->previousFrameNum,
764 /* It really shouldn't be NULL... */
765 if (p_previous_report != NULL) {
766 /* Point it forward to this one */
767 p_previous_report->nextFrameNum = pinfo->fd->num;
772 /* Associate with this frame number */
773 g_hash_table_insert(pdcp_lte_sequence_analysis_report_hash,
774 get_report_hash_key(sequenceNumber, pinfo->fd->num,
775 p_pdcp_lte_info, TRUE),
778 /* Add state report for this frame into tree */
779 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
780 pinfo, tree, tvb, security_tree, pdu_security);
785 /* Hash table for security state for a UE
786 Maps UEId -> pdcp_security_info_t* */
787 static gint pdcp_lte_ueid_hash_equal(gconstpointer v, gconstpointer v2)
791 static guint pdcp_lte_ueid_hash_func(gconstpointer v)
793 return GPOINTER_TO_UINT(v);
795 static GHashTable *pdcp_security_hash = NULL;
797 /* Result is (ueid, framenum) -> pdcp_security_info_t* */
798 typedef struct ueid_frame_t {
803 /* Convenience function to get a pointer for the hash_func to work with */
804 static gpointer get_ueid_frame_hash_key(guint16 ueid, guint32 frameNumber,
807 static ueid_frame_t key;
810 /* Only allocate a struct when will be adding entry */
812 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
815 memset(&key, 0, sizeof(ueid_frame_t));
819 /* Fill in details, and return pointer */
820 p_key->framenum = frameNumber;
826 static gint pdcp_lte_ueid_frame_hash_equal(gconstpointer v, gconstpointer v2)
828 ueid_frame_t *ueid_frame_1 = (ueid_frame_t *)v;
829 ueid_frame_t *ueid_frame_2 = (ueid_frame_t *)v2;
830 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) && (ueid_frame_1->ueid == ueid_frame_2->ueid));
832 static guint pdcp_lte_ueid_frame_hash_func(gconstpointer v)
834 ueid_frame_t *ueid_frame = (ueid_frame_t *)v;
835 return ueid_frame->framenum + 100*ueid_frame->ueid;
837 static GHashTable *pdcp_security_result_hash = NULL;
842 /* Write the given formatted text to:
844 - the top-level RLC PDU item */
845 static void write_pdu_label_and_info(proto_item *pdu_ti,
846 packet_info *pinfo, const char *format, ...)
848 #define MAX_INFO_BUFFER 256
849 static char info_buffer[MAX_INFO_BUFFER];
853 va_start(ap, format);
854 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
857 /* Add to indicated places */
858 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
859 proto_item_append_text(pdu_ti, "%s", info_buffer);
864 /***************************************************************/
868 /* Show in the tree the config info attached to this frame, as generated fields */
869 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
870 pdcp_lte_info *p_pdcp_info)
873 proto_tree *configuration_tree;
874 proto_item *configuration_ti = proto_tree_add_item(tree,
875 hf_pdcp_lte_configuration,
876 tvb, 0, 0, ENC_ASCII|ENC_NA);
877 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
880 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
881 p_pdcp_info->direction);
882 PROTO_ITEM_SET_GENERATED(ti);
885 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
887 PROTO_ITEM_SET_GENERATED(ti);
890 if (p_pdcp_info->ueid != 0) {
891 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
893 PROTO_ITEM_SET_GENERATED(ti);
897 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
898 p_pdcp_info->channelType);
899 PROTO_ITEM_SET_GENERATED(ti);
900 if (p_pdcp_info->channelId != 0) {
902 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
903 p_pdcp_info->channelId);
904 PROTO_ITEM_SET_GENERATED(ti);
908 /* User-plane-specific fields */
909 if (p_pdcp_info->plane == USER_PLANE) {
912 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
913 p_pdcp_info->no_header_pdu);
914 PROTO_ITEM_SET_GENERATED(ti);
916 if (!p_pdcp_info->no_header_pdu) {
919 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
920 p_pdcp_info->seqnum_length);
921 PROTO_ITEM_SET_GENERATED(ti);
925 /* ROHC compression */
926 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
927 p_pdcp_info->rohc.rohc_compression);
928 PROTO_ITEM_SET_GENERATED(ti);
930 /* ROHC-specific settings */
931 if (p_pdcp_info->rohc.rohc_compression) {
934 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
935 p_pdcp_info->rohc.mode);
936 PROTO_ITEM_SET_GENERATED(ti);
939 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
940 p_pdcp_info->rohc.rnd);
941 PROTO_ITEM_SET_GENERATED(ti);
944 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
945 p_pdcp_info->rohc.udp_checksum_present);
946 PROTO_ITEM_SET_GENERATED(ti);
949 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
950 p_pdcp_info->rohc.profile);
951 PROTO_ITEM_SET_GENERATED(ti);
953 /* CID Inclusion Info */
954 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
955 p_pdcp_info->rohc.cid_inclusion_info);
956 PROTO_ITEM_SET_GENERATED(ti);
959 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
960 p_pdcp_info->rohc.large_cid_present);
961 PROTO_ITEM_SET_GENERATED(ti);
964 /* Append summary to configuration root */
965 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
966 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
967 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
969 if (p_pdcp_info->rohc.rohc_compression) {
970 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
971 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
973 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
975 proto_item_append_text(configuration_ti, ")");
976 PROTO_ITEM_SET_GENERATED(configuration_ti);
978 /* Show plane in info column */
979 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
980 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
985 /* Look for an RRC dissector for signalling data (using channel type and direction) */
986 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info *p_pdcp_info)
988 dissector_handle_t rrc_handle = 0;
990 switch (p_pdcp_info->channelType)
993 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
994 rrc_handle = find_dissector("lte_rrc.ul_ccch");
997 rrc_handle = find_dissector("lte_rrc.dl_ccch");
1001 rrc_handle = find_dissector("lte_rrc.pcch");
1004 switch (p_pdcp_info->BCCHTransport) {
1006 rrc_handle = find_dissector("lte_rrc.bcch_bch");
1008 case DLSCH_TRANSPORT:
1009 rrc_handle = find_dissector("lte_rrc.bcch_dl_sch");
1014 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1015 rrc_handle = find_dissector("lte_rrc.ul_dcch");
1018 rrc_handle = find_dissector("lte_rrc.dl_dcch");
1031 /* Forwad declarations */
1032 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1034 /* Heuristic dissection */
1035 static gboolean global_pdcp_lte_heur = FALSE;
1037 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1038 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1039 proto_tree *tree, void *data _U_)
1042 struct pdcp_lte_info *p_pdcp_lte_info;
1045 gboolean infoAlreadySet = FALSE;
1046 gboolean seqnumLengthTagPresent = FALSE;
1048 /* This is a heuristic dissector, which means we get all the UDP
1049 * traffic not sent to a known dissector and not claimed by
1050 * a heuristic dissector called before us!
1053 if (!global_pdcp_lte_heur) {
1057 /* Do this again on re-dissection to re-discover offset of actual PDU */
1059 /* Needs to be at least as long as:
1060 - the signature string
1061 - fixed header bytes
1063 - at least one byte of PDCP PDU payload */
1064 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(PDCP_LTE_START_STRING)+3+2)) {
1068 /* OK, compare with signature string */
1069 if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1072 offset += (gint)strlen(PDCP_LTE_START_STRING);
1075 /* If redissecting, use previous info struct (if available) */
1076 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1077 if (p_pdcp_lte_info == NULL) {
1078 /* Allocate new info struct for this frame */
1079 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1080 infoAlreadySet = FALSE;
1083 infoAlreadySet = TRUE;
1087 /* Read fixed fields */
1088 p_pdcp_lte_info->no_header_pdu = (gboolean)tvb_get_guint8(tvb, offset++);
1089 p_pdcp_lte_info->plane = (enum pdcp_plane)tvb_get_guint8(tvb, offset++);
1090 p_pdcp_lte_info->rohc.rohc_compression = (gboolean)tvb_get_guint8(tvb, offset++);
1092 /* Read optional fields */
1093 while (tag != PDCP_LTE_PAYLOAD_TAG) {
1094 /* Process next tag */
1095 tag = tvb_get_guint8(tvb, offset++);
1097 case PDCP_LTE_SEQNUM_LENGTH_TAG:
1098 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1100 seqnumLengthTagPresent = TRUE;
1102 case PDCP_LTE_DIRECTION_TAG:
1103 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1106 case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1107 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
1110 case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1111 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_guint8(tvb, offset);
1114 case PDCP_LTE_ROHC_IP_VERSION_TAG:
1115 p_pdcp_lte_info->rohc.rohc_ip_version = tvb_get_ntohs(tvb, offset);
1118 case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1119 p_pdcp_lte_info->rohc.cid_inclusion_info = tvb_get_guint8(tvb, offset);
1122 case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1123 p_pdcp_lte_info->rohc.large_cid_present = tvb_get_guint8(tvb, offset);
1126 case PDCP_LTE_ROHC_MODE_TAG:
1127 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)tvb_get_guint8(tvb, offset);
1130 case PDCP_LTE_ROHC_RND_TAG:
1131 p_pdcp_lte_info->rohc.rnd = tvb_get_guint8(tvb, offset);
1134 case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1135 p_pdcp_lte_info->rohc.udp_checksum_present = tvb_get_guint8(tvb, offset);
1138 case PDCP_LTE_ROHC_PROFILE_TAG:
1139 p_pdcp_lte_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1142 case PDCP_LTE_CHANNEL_ID_TAG:
1143 p_pdcp_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1146 case PDCP_LTE_UEID_TAG:
1147 p_pdcp_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1151 case PDCP_LTE_PAYLOAD_TAG:
1152 /* Have reached data, so get out of loop */
1156 /* It must be a recognised tag */
1161 if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1162 /* Conditional field is not present */
1166 if (!infoAlreadySet) {
1167 /* Store info in packet */
1168 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1171 /**************************************/
1172 /* OK, now dissect as PDCP LTE */
1174 /* Create tvb that starts at actual PDCP PDU */
1175 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
1176 dissect_pdcp_lte(pdcp_tvb, pinfo, tree);
1180 /* Called from control protocol to configure security algorithms for the given UE */
1181 void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_security_info_t *security_info)
1183 /* Copy security struct */
1184 pdcp_security_info_t *p_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1185 *p_security = *security_info;
1187 /* And add into security table */
1188 g_hash_table_insert(pdcp_security_hash, GUINT_TO_POINTER((guint)ueid), p_security);
1191 /* TODO: do this better! */
1192 static guchar hex_ascii_to_binary(gchar c)
1194 if ((c >= '0') && (c <= '9')) {
1197 else if ((c >= 'a') && (c <= 'f')) {
1204 /* Decipher payload if algorithm is supported and plausible inputs are available */
1205 tvbuff_t* decipher_payload(tvbuff_t *tvb, int *offset _U_, pdu_security_settings_t *pdu_security_settings)
1207 char *k = pdu_security_settings->key;
1211 /* Nothing to do if no ciphering algorithm was specified */
1212 if (!pdu_security_settings->valid) {
1216 /* Only EEA2 supported at the moment */
1217 if (pdu_security_settings->ciphering != eea2) {
1221 /* Key must be present and 16 bytes long */
1222 if (strlen(k) != 32) {
1226 /* And must be able to convert string into binary key */
1227 for (n=0; n < 16; n += 2) {
1228 key[n] = (hex_ascii_to_binary(k[2*n]) << 4) + hex_ascii_to_binary(k[(2*n)+1]);
1231 /* TODO: call AES and return result TVB !!!!! And set *offset. */
1236 /******************************/
1237 /* Main dissection function. */
1238 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1241 proto_tree *pdcp_tree = NULL;
1242 proto_item *root_ti = NULL;
1245 struct pdcp_lte_info *p_pdcp_info;
1246 tvbuff_t *rohc_tvb = NULL;
1248 pdcp_security_info_t *current_security = NULL; /* current security for this UE */
1249 pdcp_security_info_t *pdu_security; /* security in place for this PDU */
1250 proto_tree *security_tree = NULL;
1251 proto_item *security_ti;
1252 tvbuff_t *payload_tvb;
1253 pdu_security_settings_t pdu_security_settings;
1255 /* Initialise security settings */
1256 pdu_security_settings.valid = FALSE;
1257 pdu_security_settings.key = "";
1260 /* Set protocol name. */
1261 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1263 /* Look for attached packet info! */
1264 p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1265 /* Can't dissect anything without it... */
1266 if (p_pdcp_info == NULL) {
1270 /* Don't want to overwrite the RLC Info column if configured not to */
1271 if ((global_pdcp_lte_layer_to_show == ShowRLCLayer) &&
1272 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL)) {
1274 col_set_writable(pinfo->cinfo, FALSE);
1277 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
1278 col_clear(pinfo->cinfo, COL_INFO);
1279 col_set_writable(pinfo->cinfo, TRUE);
1282 /* Create pdcp tree. */
1284 root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, ENC_NA);
1285 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1288 /* Set mode string */
1289 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1291 /*****************************************************/
1292 /* Show configuration (attached packet) info in tree */
1294 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1297 /* Show ROHC mode */
1298 if (p_pdcp_info->rohc.rohc_compression) {
1299 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1302 /***************************************/
1303 /* UE security algorithms */
1304 if (!pinfo->fd->flags.visited) {
1305 /* Look up current state by UEID */
1306 current_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_hash,
1307 GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
1308 if (current_security != NULL) {
1309 /* Store any result for this frame in the result table */
1310 pdcp_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1311 *security_to_store = *current_security;
1312 g_hash_table_insert(pdcp_security_result_hash,
1313 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, TRUE),
1318 /* Show security settings for this PDU */
1319 pdu_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_result_hash, get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, FALSE));
1320 if (pdu_security != NULL) {
1323 /* Create subtree */
1324 security_ti = proto_tree_add_string_format(pdcp_tree,
1325 hf_pdcp_lte_security,
1328 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
1329 PROTO_ITEM_SET_GENERATED(security_ti);
1332 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_setup_frame,
1333 tvb, 0, 0, pdu_security->configuration_frame);
1334 PROTO_ITEM_SET_GENERATED(ti);
1337 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_ciphering_algorithm,
1338 tvb, 0, 0, pdu_security->ciphering);
1339 PROTO_ITEM_SET_GENERATED(ti);
1342 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_integrity_algorithm,
1343 tvb, 0, 0, pdu_security->integrity);
1344 PROTO_ITEM_SET_GENERATED(ti);
1346 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
1347 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
1348 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
1350 pdu_security_settings.valid = TRUE;
1351 pdu_security_settings.ciphering = pdu_security->ciphering;
1355 /***********************************/
1356 /* Handle PDCP header (if present) */
1357 if (!p_pdcp_info->no_header_pdu) {
1359 /* TODO: shouldn't need to initialise this one!! */
1361 gboolean seqnum_set = FALSE;
1363 guint8 first_byte = tvb_get_guint8(tvb, offset);
1365 /*****************************/
1366 /* Signalling plane messages */
1367 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1368 /* Verify 3 reserved bits are 0 */
1369 guint8 reserved = (first_byte & 0xe0) >> 5;
1370 proto_item *ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_plane_reserved,
1371 tvb, offset, 1, ENC_BIG_ENDIAN);
1372 if (reserved != 0) {
1373 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1374 "PDCP signalling header reserved bits not zero");
1377 /* 5-bit sequence number */
1378 seqnum = first_byte & 0x1f;
1380 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, ENC_BIG_ENDIAN);
1381 write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
1384 if (tvb_length_remaining(tvb, offset) == 0) {
1385 /* Only PDCP header was captured, stop dissection here */
1389 else if (p_pdcp_info->plane == USER_PLANE) {
1391 /**********************************/
1392 /* User-plane messages */
1393 gboolean pdu_type = (first_byte & 0x80) >> 7;
1395 /* Data/Control flag */
1396 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
1398 if (pdu_type == 1) {
1399 /*****************************/
1400 /* Use-plane Data */
1402 /* Number of sequence number bits depends upon config */
1403 switch (p_pdcp_info->seqnum_length) {
1404 case PDCP_SN_LENGTH_7_BITS:
1405 seqnum = first_byte & 0x7f;
1407 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, ENC_BIG_ENDIAN);
1410 case PDCP_SN_LENGTH_12_BITS:
1413 guint8 reserved_value;
1415 /* 3 reserved bits */
1416 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN);
1417 reserved_value = (first_byte & 0x70) >> 4;
1419 /* Complain if not 0 */
1420 if (reserved_value != 0) {
1421 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1422 "Reserved bits have value 0x%x - should be 0x0",
1426 /* 12-bit sequence number */
1427 seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
1429 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN);
1433 case PDCP_SN_LENGTH_15_BITS:
1434 seqnum = tvb_get_ntohs(tvb, offset) & 0x7fff;
1436 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_15, tvb, offset, 2, ENC_BIG_ENDIAN);
1440 /* Not a recognised data format!!!!! */
1444 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
1447 /*******************************/
1448 /* User-plane Control messages */
1449 guint8 control_pdu_type = (first_byte & 0x70) >> 4;
1450 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1452 switch (control_pdu_type) {
1453 case 0: /* PDCP status report */
1458 guint not_received = 0;
1460 guint32 len, bit_offset;
1461 proto_tree *bitmap_tree;
1462 proto_item *bitmap_ti = NULL;
1464 #define BUFF_SIZE 49
1466 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
1467 /* First-Missing-Sequence SN */
1468 fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
1469 sn = (fms + 1) % 4096;
1470 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
1471 offset, 2, ENC_BIG_ENDIAN);
1476 guint8 reserved_value;
1478 /* 5 reserved bits */
1479 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN);
1480 reserved_value = (tvb_get_ntohs(tvb, offset) & 0x0f80)>>7;
1483 /* Complain if not 0 */
1484 if (reserved_value != 0) {
1485 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1486 "Reserved bits have value 0x%x - should be 0x0",
1490 /* First-Missing-Sequence SN */
1491 fms = tvb_get_ntohs(tvb, offset) & 0x7fff;
1492 sn = (fms + 1) % 32768;
1493 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms2, tvb,
1494 offset, 2, ENC_BIG_ENDIAN);
1500 if (tvb_length_remaining(tvb, offset) > 0) {
1501 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
1502 offset, -1, ENC_NA);
1503 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
1505 buff = (gchar *)wmem_alloc(wmem_packet_scope(), BUFF_SIZE);
1506 len = tvb_length_remaining(tvb, offset);
1507 bit_offset = offset<<3;
1508 /* For each byte... */
1509 for (i=0; i<len; i++) {
1510 bits = tvb_get_bits8(tvb, bit_offset, 8);
1511 for (l=0, j=0; l<8; l++) {
1512 if ((bits << l) & 0x80) {
1513 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%5u,", (unsigned)(sn+(8*i)+l)%modulo);
1515 j += g_snprintf(&buff[j], BUFF_SIZE-j, " ,");
1519 proto_tree_add_text(bitmap_tree, tvb, bit_offset/8, 1, "%s", buff);
1524 if (bitmap_ti != NULL) {
1525 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
1527 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
1532 case 1: /* ROHC Feedback */
1534 break; /* Drop-through to dissect feedback */
1536 default: /* Reserved */
1542 /* Invalid plane setting...! */
1543 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
1544 p_pdcp_info->plane);
1548 /* Do sequence analysis if configured to. */
1550 gboolean do_analysis = FALSE;
1552 switch (global_pdcp_check_sequence_numbers) {
1555 case SEQUENCE_ANALYSIS_RLC_ONLY:
1556 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL) &&
1557 !p_pdcp_info->is_retx) {
1561 case SEQUENCE_ANALYSIS_PDCP_ONLY:
1562 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) == NULL) {
1569 checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
1570 (guint16)seqnum, pdcp_tree, security_tree,
1571 &pdu_security_settings);
1576 /* Show that it's a no-header PDU */
1577 write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
1580 /*******************************************************/
1581 /* Now deal with the payload */
1582 /*******************************************************/
1584 /* Check pdu_security_settings - may need to do deciphering before calling
1585 further dissectors on payload */
1586 payload_tvb = decipher_payload(tvb, &offset, &pdu_security_settings);
1588 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1589 guint32 data_length;
1592 /* RRC data is all but last 4 bytes.
1593 Call lte-rrc dissector (according to direction and channel type) */
1594 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
1595 ((pdu_security == NULL) || (pdu_security->ciphering == 0) || !pdu_security->seen_next_ul_pdu)){
1596 /* Get appropriate dissector handle */
1597 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1599 if (rrc_handle != 0) {
1600 /* Call RRC dissector if have one */
1601 tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
1602 tvb_length_remaining(tvb, offset) - 4,
1603 tvb_length_remaining(tvb, offset) - 4);
1604 gboolean was_writable = col_get_writable(pinfo->cinfo);
1606 /* We always want to see this in the info column */
1607 col_set_writable(pinfo->cinfo, TRUE);
1609 call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree, NULL);
1611 /* Restore to whatever it was */
1612 col_set_writable(pinfo->cinfo, was_writable);
1615 /* Just show data */
1616 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1617 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1620 if (!pinfo->fd->flags.visited &&
1621 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
1622 p_pdcp_info->direction == DIRECTION_UPLINK)
1624 /* i.e. we have already seen SecurityModeResponse! */
1625 current_security->seen_next_ul_pdu = TRUE;
1630 /* Just show as unparsed data */
1631 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1632 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1635 data_length = tvb_length_remaining(tvb, offset) - 4;
1636 offset += data_length;
1638 /* Last 4 bytes are MAC */
1639 mac = tvb_get_ntohl(tvb, offset);
1640 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, tvb, offset, 4, ENC_BIG_ENDIAN);
1643 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
1647 /* User-plane payload here */
1649 /* If not compressed with ROHC, show as user-plane data */
1650 if (!p_pdcp_info->rohc.rohc_compression) {
1651 gint payload_length = tvb_length_remaining(tvb, offset);
1652 if (payload_length > 0) {
1653 if (p_pdcp_info->plane == USER_PLANE) {
1655 /* Not attempting to decode payload if ciphering is enabled
1656 (and NULL ciphering is not being used) */
1657 if (global_pdcp_dissect_user_plane_as_ip &&
1658 ((pdu_security == NULL) || (pdu_security->ciphering == 0)))
1660 tvbuff_t *payload_tvb = tvb_new_subset_remaining(tvb, offset);
1662 /* Don't update info column for ROHC unless configured to */
1663 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
1664 col_set_writable(pinfo->cinfo, FALSE);
1667 switch (tvb_get_guint8(tvb, offset) & 0xf0) {
1669 call_dissector_only(ip_handle, payload_tvb, pinfo, pdcp_tree, NULL);
1672 call_dissector_only(ipv6_handle, payload_tvb, pinfo, pdcp_tree, NULL);
1675 call_dissector_only(data_handle, payload_tvb, pinfo, pdcp_tree, NULL);
1679 /* Freeze the columns again because we don't want other layers writing to info */
1680 if (global_pdcp_lte_layer_to_show == ShowTrafficLayer) {
1681 col_set_writable(pinfo->cinfo, FALSE);
1686 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, tvb, offset, -1, ENC_NA);
1690 write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
1694 /* (there will be no signalling data left at this point) */
1696 /* Let RLC write to columns again */
1697 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
1699 /* DROPPING OUT HERE IF NOT DOING ROHC! */
1703 /***************************/
1705 /***************************/
1707 /* Only attempt ROHC if configured to */
1708 if (!global_pdcp_dissect_rohc) {
1709 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
1710 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1714 rohc_offset = offset;
1715 rohc_tvb = tvb_new_subset_remaining(tvb, rohc_offset);
1717 /* Only enable writing to column if configured to show ROHC */
1718 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
1719 col_set_writable(pinfo->cinfo, FALSE);
1722 col_clear(pinfo->cinfo, COL_INFO);
1725 /* Call the ROHC dissector */
1726 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
1728 /* Let RLC write to columns again */
1729 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
1734 /* Initializes the hash tables each time a new
1735 * file is loaded or re-loaded in wireshark */
1736 static void pdcp_lte_init_protocol(void)
1738 /* Destroy any existing hashes. */
1739 if (pdcp_sequence_analysis_channel_hash) {
1740 g_hash_table_destroy(pdcp_sequence_analysis_channel_hash);
1742 if (pdcp_lte_sequence_analysis_report_hash) {
1743 g_hash_table_destroy(pdcp_lte_sequence_analysis_report_hash);
1745 if (pdcp_security_hash) {
1746 g_hash_table_destroy(pdcp_security_hash);
1748 if (pdcp_security_result_hash) {
1749 g_hash_table_destroy(pdcp_security_result_hash);
1752 /* Now create them over */
1753 pdcp_sequence_analysis_channel_hash = g_hash_table_new(pdcp_channel_hash_func, pdcp_channel_equal);
1754 pdcp_lte_sequence_analysis_report_hash = g_hash_table_new(pdcp_result_hash_func, pdcp_result_hash_equal);
1755 pdcp_security_hash = g_hash_table_new(pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal);
1756 pdcp_security_result_hash = g_hash_table_new(pdcp_lte_ueid_frame_hash_func, pdcp_lte_ueid_frame_hash_equal);
1761 void proto_register_pdcp(void)
1763 static hf_register_info hf[] =
1765 { &hf_pdcp_lte_configuration,
1767 "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
1768 "Configuration info passed into dissector", HFILL
1772 { &hf_pdcp_lte_rohc_compression,
1773 { "ROHC Compression",
1774 "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1778 { &hf_pdcp_lte_rohc_mode,
1780 "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
1784 { &hf_pdcp_lte_rohc_rnd,
1786 "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
1787 "RND of outer ip header", HFILL
1790 { &hf_pdcp_lte_rohc_udp_checksum_present,
1792 "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1793 "UDP Checksum present", HFILL
1796 { &hf_pdcp_lte_direction,
1798 "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1799 "Direction of message", HFILL
1802 { &hf_pdcp_lte_ueid,
1804 "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1805 "UE Identifier", HFILL
1808 { &hf_pdcp_lte_channel_type,
1810 "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
1814 { &hf_pdcp_lte_channel_id,
1816 "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
1820 { &hf_pdcp_lte_rohc_profile,
1822 "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
1826 { &hf_pdcp_lte_no_header_pdu,
1828 "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
1832 { &hf_pdcp_lte_plane,
1834 "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
1838 { &hf_pdcp_lte_seqnum_length,
1840 "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1841 "Sequence Number Length", HFILL
1846 { &hf_pdcp_lte_cid_inclusion_info,
1847 { "CID Inclusion Info",
1848 "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
1852 { &hf_pdcp_lte_large_cid_present,
1853 { "Large CID Present",
1854 "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1859 { &hf_pdcp_lte_control_plane_reserved,
1861 "pdcp-lte.reserved", FT_UINT8, BASE_DEC, NULL, 0xe0,
1865 { &hf_pdcp_lte_seq_num_5,
1867 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
1868 "PDCP Seq num", HFILL
1871 { &hf_pdcp_lte_seq_num_7,
1873 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
1874 "PDCP Seq num", HFILL
1877 { &hf_pdcp_lte_reserved3,
1879 "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
1880 "3 reserved bits", HFILL
1883 { &hf_pdcp_lte_seq_num_12,
1885 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
1886 "PDCP Seq num", HFILL
1889 { &hf_pdcp_lte_seq_num_15,
1891 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x7fff,
1892 "PDCP Seq num", HFILL
1895 { &hf_pdcp_lte_signalling_data,
1896 { "Signalling Data",
1897 "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
1903 "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
1907 { &hf_pdcp_lte_data_control,
1909 "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
1913 { &hf_pdcp_lte_user_plane_data,
1914 { "User-Plane Data",
1915 "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
1919 { &hf_pdcp_lte_control_pdu_type,
1920 { "Control PDU Type",
1921 "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
1926 { "First Missing Sequence Number",
1927 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
1928 "First Missing PDCP Sequence Number", HFILL
1931 { &hf_pdcp_lte_reserved4,
1933 "pdcp-lte.reserved4", FT_UINT16, BASE_HEX, NULL, 0x0f80,
1934 "5 reserved bits", HFILL
1937 { &hf_pdcp_lte_fms2,
1938 { "First Missing Sequence Number",
1939 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x07fff,
1940 "First Missing PDCP Sequence Number", HFILL
1943 { &hf_pdcp_lte_bitmap,
1945 "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
1946 "Status report bitmap (0=error, 1=OK)", HFILL
1951 { &hf_pdcp_lte_sequence_analysis,
1952 { "Sequence Analysis",
1953 "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
1957 { &hf_pdcp_lte_sequence_analysis_ok,
1959 "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
1963 { &hf_pdcp_lte_sequence_analysis_previous_frame,
1964 { "Previous frame for channel",
1965 "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
1969 { &hf_pdcp_lte_sequence_analysis_next_frame,
1970 { "Next frame for channel",
1971 "pdcp-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
1975 { &hf_pdcp_lte_sequence_analysis_expected_sn,
1977 "pdcp-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
1981 { &hf_pdcp_lte_sequence_analysis_skipped,
1983 "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
1987 { &hf_pdcp_lte_sequence_analysis_repeated,
1989 "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
1994 { &hf_pdcp_lte_security,
1995 { "Security Config",
1996 "pdcp-lte.security-cofig", FT_STRING, BASE_NONE, 0, 0x0,
2000 { &hf_pdcp_lte_security_setup_frame,
2001 { "Configuration frame",
2002 "pdcp-lte.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2006 { &hf_pdcp_lte_security_integrity_algorithm,
2007 { "Integrity Algorithm",
2008 "pdcp-lte.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
2012 { &hf_pdcp_lte_security_ciphering_algorithm,
2013 { "Ciphering Algorithm",
2014 "pdcp-lte.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
2018 { &hf_pdcp_lte_security_bearer,
2020 "pdcp-lte.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
2024 { &hf_pdcp_lte_security_direction,
2026 "pdcp-lte.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2030 { &hf_pdcp_lte_security_count,
2032 "pdcp-lte.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2036 { &hf_pdcp_lte_security_key,
2038 "pdcp-lte.security-config.key", FT_STRING, BASE_NONE, NULL, 0x0,
2044 static gint *ett[] =
2047 &ett_pdcp_configuration,
2049 &ett_pdcp_lte_sequence_analysis,
2050 &ett_pdcp_report_bitmap,
2054 static ei_register_info ei[] = {
2055 { &ei_pdcp_lte_sequence_analysis_sn_missing, { "pdcp-lte.sequence-analysis.sn-missing", PI_SEQUENCE, PI_WARN, "PDCP SN missing", EXPFILL }},
2056 { &ei_pdcp_lte_sequence_analysis_sn_repeated, { "pdcp-lte.sequence-analysis.sn-repeated", PI_SEQUENCE, PI_WARN, "PDCP SN repeated", EXPFILL }},
2057 { &ei_pdcp_lte_sequence_analysis_wrong_sequence_number, { "pdcp-lte.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
2058 { &ei_pdcp_lte_reserved_bits_not_zero, { "pdcp-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
2061 static const enum_val_t sequence_analysis_vals[] = {
2062 {"no-analysis", "No-Analysis", FALSE},
2063 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
2064 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
2068 static const enum_val_t show_info_col_vals[] = {
2069 {"show-rlc", "RLC Info", ShowRLCLayer},
2070 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
2071 {"show-traffic", "Traffic Info", ShowTrafficLayer},
2075 #ifdef HAVE_LIBGCRYPT
2076 static uat_field_t ue_keys_uat_flds[] = {
2077 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
2078 UAT_FLD_CSTRING(uat_ue_keys_records, rrcKey, "RRC Key", "Key for deciphering signalling messages"),
2079 UAT_FLD_CSTRING(uat_ue_keys_records, upKey, "User-Plane Key", "Key for deciphering user-plane messages"),
2084 module_t *pdcp_lte_module;
2085 expert_module_t* expert_pdcp_lte;
2087 /* Register protocol. */
2088 proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
2089 proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
2090 proto_register_subtree_array(ett, array_length(ett));
2091 expert_pdcp_lte = expert_register_protocol(proto_pdcp_lte);
2092 expert_register_field_array(expert_pdcp_lte, ei, array_length(ei));
2094 /* Allow other dissectors to find this one by name. */
2095 register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
2097 pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
2099 /* Obsolete preferences */
2100 prefs_register_obsolete_preference(pdcp_lte_module, "show_feedback_option_tag_length");
2102 /* Dissect uncompressed user-plane data as IP */
2103 prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
2104 "Show uncompressed User-Plane data as IP",
2105 "Show uncompressed User-Plane data as IP",
2106 &global_pdcp_dissect_user_plane_as_ip);
2108 /* Dissect unciphered signalling data as RRC */
2109 prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
2110 "Show unciphered Signalling-Plane data as RRC",
2111 "Show unciphered Signalling-Plane data as RRC",
2112 &global_pdcp_dissect_signalling_plane_as_rrc);
2114 /* Check for missing sequence numbers */
2115 prefs_register_enum_preference(pdcp_lte_module, "check_sequence_numbers",
2116 "Do sequence number analysis",
2117 "Do sequence number analysis",
2118 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, FALSE);
2120 /* Attempt to dissect ROHC messages */
2121 prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
2122 "Attempt to decode ROHC data",
2123 "Attempt to decode ROHC data",
2124 &global_pdcp_dissect_rohc);
2126 prefs_register_bool_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp",
2127 "Try Heuristic LTE-PDCP over UDP framing",
2128 "When enabled, use heuristic dissector to find PDCP-LTE frames sent with "
2130 &global_pdcp_lte_heur);
2132 prefs_register_enum_preference(pdcp_lte_module, "layer_to_show",
2133 "Which layer info to show in Info column",
2134 "Can show RLC, PDCP or Traffic layer info in Info column",
2135 &global_pdcp_lte_layer_to_show, show_info_col_vals, FALSE);
2137 #ifdef HAVE_LIBGCRYPT
2138 ue_keys_uat = uat_new("PDCP UE security keys",
2139 sizeof(uat_ue_keys_record_t), /* record size */
2140 "pdcp_lte_ue_keys", /* filename */
2141 TRUE, /* from_profile */
2142 (void**) &uat_ue_keys_records, /* data_ptr */
2143 &num_ue_keys_uat, /* numitems_ptr */
2144 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
2146 uat_ue_keys_record_copy_cb, /* copy callback */
2147 NULL, /* update callback */
2148 uat_ue_keys_record_free_cb, /* free callback */
2149 NULL, /* post update callback */
2150 ue_keys_uat_flds); /* UAT field definitions */
2152 prefs_register_uat_preference(pdcp_lte_module,
2155 "Preconfigured PDCP keys",
2160 register_init_routine(&pdcp_lte_init_protocol);
2163 void proto_reg_handoff_pdcp_lte(void)
2165 /* Add as a heuristic UDP dissector */
2166 heur_dissector_add("udp", dissect_pdcp_lte_heur, proto_pdcp_lte);
2168 ip_handle = find_dissector("ip");
2169 ipv6_handle = find_dissector("ipv6");
2170 rohc_handle = find_dissector("rohc");
2171 data_handle = find_dissector("data");