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 - More deciphering. Next steps are:
56 - separate preferences to control signalling/user-plane decryption?
57 - Verify MAC authentication bytes for supported protocol(s)?
58 - Add Relay Node user plane data PDU dissection
62 /* Initialize the protocol and registered fields. */
63 int proto_pdcp_lte = -1;
65 extern int proto_rlc_lte;
67 /* Configuration (info known outside of PDU) */
68 static int hf_pdcp_lte_configuration = -1;
69 static int hf_pdcp_lte_direction = -1;
70 static int hf_pdcp_lte_ueid = -1;
71 static int hf_pdcp_lte_channel_type = -1;
72 static int hf_pdcp_lte_channel_id = -1;
74 static int hf_pdcp_lte_rohc_compression = -1;
75 static int hf_pdcp_lte_rohc_mode = -1;
76 static int hf_pdcp_lte_rohc_rnd = -1;
77 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
78 static int hf_pdcp_lte_rohc_profile = -1;
80 static int hf_pdcp_lte_no_header_pdu = -1;
81 static int hf_pdcp_lte_plane = -1;
82 static int hf_pdcp_lte_seqnum_length = -1;
83 static int hf_pdcp_lte_cid_inclusion_info = -1;
84 static int hf_pdcp_lte_large_cid_present = -1;
86 /* PDCP header fields */
87 static int hf_pdcp_lte_control_plane_reserved = -1;
88 static int hf_pdcp_lte_seq_num_5 = -1;
89 static int hf_pdcp_lte_seq_num_7 = -1;
90 static int hf_pdcp_lte_reserved3 = -1;
91 static int hf_pdcp_lte_seq_num_12 = -1;
92 static int hf_pdcp_lte_seq_num_15 = -1;
93 static int hf_pdcp_lte_signalling_data = -1;
94 static int hf_pdcp_lte_mac = -1;
95 static int hf_pdcp_lte_data_control = -1;
96 static int hf_pdcp_lte_user_plane_data = -1;
97 static int hf_pdcp_lte_control_pdu_type = -1;
98 static int hf_pdcp_lte_fms = -1;
99 static int hf_pdcp_lte_reserved4 = -1;
100 static int hf_pdcp_lte_fms2 = -1;
101 static int hf_pdcp_lte_bitmap = -1;
104 /* Sequence Analysis */
105 static int hf_pdcp_lte_sequence_analysis = -1;
106 static int hf_pdcp_lte_sequence_analysis_ok = -1;
107 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
108 static int hf_pdcp_lte_sequence_analysis_next_frame = -1;
109 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
111 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
112 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
114 /* Security Settings */
115 static int hf_pdcp_lte_security = -1;
116 static int hf_pdcp_lte_security_setup_frame = -1;
117 static int hf_pdcp_lte_security_integrity_algorithm = -1;
118 static int hf_pdcp_lte_security_ciphering_algorithm = -1;
120 static int hf_pdcp_lte_security_bearer = -1;
121 static int hf_pdcp_lte_security_direction = -1;
122 static int hf_pdcp_lte_security_count = -1;
123 static int hf_pdcp_lte_security_key = -1;
127 /* Protocol subtree. */
128 static int ett_pdcp = -1;
129 static int ett_pdcp_configuration = -1;
130 static int ett_pdcp_packet = -1;
131 static int ett_pdcp_lte_sequence_analysis = -1;
132 static int ett_pdcp_report_bitmap = -1;
133 static int ett_pdcp_security = -1;
135 static expert_field ei_pdcp_lte_sequence_analysis_wrong_sequence_number = EI_INIT;
136 static expert_field ei_pdcp_lte_reserved_bits_not_zero = EI_INIT;
137 static expert_field ei_pdcp_lte_sequence_analysis_sn_repeated = EI_INIT;
138 static expert_field ei_pdcp_lte_sequence_analysis_sn_missing = EI_INIT;
140 #ifdef HAVE_LIBGCRYPT
141 /*-------------------------------------
143 *-------------------------------------
145 /* UAT entry structure. */
151 guint8 rrcBinaryKey[16];
153 guint8 upBinaryKey[16];
155 } uat_ue_keys_record_t;
157 static uat_ue_keys_record_t *uat_ue_keys_records = NULL;
159 static uat_t * ue_keys_uat = NULL;
160 static guint num_ue_keys_uat = 0;
162 /* TODO: do this better, being tolerant of spaces and dashes... */
163 static guchar hex_ascii_to_binary(gchar c)
165 if ((c >= '0') && (c <= '9')) {
168 else if ((c >= 'a') && (c <= 'f')) {
171 else if ((c >= 'A') && (c <= 'F')) {
179 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
180 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
181 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
183 new_rec->ueid = old_rec->ueid;
184 new_rec->rrcKeyString = (old_rec->rrcKeyString) ? g_strdup(old_rec->rrcKeyString) : NULL;
185 new_rec->upKeyString = (old_rec->upKeyString) ? g_strdup(old_rec->upKeyString) : NULL;
190 static void uat_ue_keys_record_update_cb(void* record, const char** error _U_) {
191 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
194 /* Check and convert RRC key */
195 if (strlen(rec->rrcKeyString) != 32) {
196 rec->rrcKeyOK = FALSE;
199 for (n=0; n < 32; n += 2) {
200 rec->rrcBinaryKey[n/2] = (hex_ascii_to_binary(rec->rrcKeyString[n]) << 4) +
201 hex_ascii_to_binary(rec->rrcKeyString[n+1]);
203 rec->rrcKeyOK = TRUE;
206 /* Check and convert User-plane key */
207 if (strlen(rec->upKeyString) != 32) {
208 rec->rrcKeyOK = FALSE;
211 for (n=0; n < 32; n += 2) {
212 rec->upBinaryKey[n/2] = (hex_ascii_to_binary(rec->upKeyString[n]) << 4) +
213 hex_ascii_to_binary(rec->upKeyString[n+1]);
220 static void uat_ue_keys_record_free_cb(void*r) {
221 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
223 g_free(rec->rrcKeyString);
224 g_free(rec->upKeyString);
227 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
228 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcKeyString, uat_ue_keys_record_t)
229 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upKeyString, uat_ue_keys_record_t)
231 static gboolean global_pdcp_decipher_signalling = FALSE;
232 static gboolean global_pdcp_decipher_userplane = FALSE;
235 static const value_string direction_vals[] =
237 { DIRECTION_UPLINK, "Uplink"},
238 { DIRECTION_DOWNLINK, "Downlink"},
243 static const value_string pdcp_plane_vals[] = {
244 { SIGNALING_PLANE, "Signalling" },
245 { USER_PLANE, "User" },
249 static const value_string logical_channel_vals[] = {
250 { Channel_DCCH, "DCCH"},
251 { Channel_BCCH, "BCCH"},
252 { Channel_CCCH, "CCCH"},
253 { Channel_PCCH, "PCCH"},
257 static const value_string rohc_mode_vals[] = {
258 { UNIDIRECTIONAL, "Unidirectional" },
259 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
260 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
265 /* Values taken from:
266 http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
267 static const value_string rohc_profile_vals[] = {
268 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
269 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
270 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
271 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
272 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
273 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
274 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
275 { 0x0004, "ROHC IP" }, /* [RFC3843] */
276 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
277 { 0x0005, "ROHC LLA" }, /* [RFC4362] */
278 { 0x0105, "ROHC LLA with R-mode" }, /* [RFC3408] */
279 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
280 { 0x0007, "ROHC RTP/UDP-Lite" }, /* [RFC4019] */
281 { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /* [RFC5225] */
282 { 0x0008, "ROHC UDP-Lite" }, /* [RFC4019] */
283 { 0x0108, "ROHCv2 UDP-Lite" }, /* [RFC5225] */
287 static const value_string pdu_type_vals[] = {
288 { 0, "Control PDU" },
293 static const value_string control_pdu_type_vals[] = {
294 { 0, "PDCP Status report" },
295 { 1, "Header Compression Feedback Information" },
299 static const value_string integrity_algorithm_vals[] = {
306 static const value_string ciphering_algorithm_vals[] = {
314 static dissector_handle_t ip_handle;
315 static dissector_handle_t ipv6_handle;
316 static dissector_handle_t rohc_handle;
317 static dissector_handle_t data_handle;
320 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
321 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
323 /* Preference variables */
324 static gboolean global_pdcp_dissect_user_plane_as_ip = TRUE;
325 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = TRUE;
326 static gint global_pdcp_check_sequence_numbers = TRUE;
327 static gboolean global_pdcp_dissect_rohc = FALSE;
329 /* Which layer info to show in the info column */
331 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
333 static gint global_pdcp_lte_layer_to_show = (gint)ShowRLCLayer;
337 /**************************************************/
338 /* Sequence number analysis */
343 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
344 heap memory for these structs */
350 } pdcp_channel_hash_key;
355 guint16 previousSequenceNumber;
356 guint32 previousFrameNum;
358 } pdcp_channel_status;
360 /* The sequence analysis channel hash table.
361 Maps key -> status */
362 static GHashTable *pdcp_sequence_analysis_channel_hash = NULL;
365 static gint pdcp_channel_equal(gconstpointer v, gconstpointer v2)
367 /* Key fits in 4 bytes, so just compare pointers! */
371 /* Compute a hash value for a given key. */
372 static guint pdcp_channel_hash_func(gconstpointer v)
374 /* Just use pointer, as the fields are all in this value */
375 return GPOINTER_TO_UINT(v);
379 /* Hash table types & functions for frame reports */
385 guint32 channelId: 5;
386 guint32 direction: 1;
388 } pdcp_result_hash_key;
390 static gint pdcp_result_hash_equal(gconstpointer v, gconstpointer v2)
392 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
393 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
395 /* All fields must match */
396 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
399 /* Compute a hash value for a given key. */
400 static guint pdcp_result_hash_func(gconstpointer v)
402 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
404 /* TODO: This is a bit random. */
405 return val1->frameNumber + (val1->channelId<<13) +
408 (val1->direction<<9);
411 /* pdcp_channel_hash_key fits into the pointer, so just copy the value into
412 a guint, cast to apointer and return that as the key */
413 static gpointer get_channel_hash_key(pdcp_channel_hash_key *key)
416 /* TODO: assert that sizeof(pdcp_channel_hash_key) <= sizeof(guint) ? */
417 memcpy(&asInt, key, sizeof(pdcp_channel_hash_key));
418 return GUINT_TO_POINTER(asInt);
421 /* Convenience function to get a pointer for the hash_func to work with */
422 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
423 pdcp_lte_info *p_pdcp_lte_info,
426 static pdcp_result_hash_key key;
427 pdcp_result_hash_key *p_key;
429 /* Only allocate a struct when will be adding entry */
431 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
434 memset(&key, 0, sizeof(pdcp_result_hash_key));
438 /* Fill in details, and return pointer */
439 p_key->frameNumber = frameNumber;
441 p_key->plane = (guint8)p_pdcp_lte_info->plane;
442 p_key->channelId = p_pdcp_lte_info->channelId;
443 p_key->direction = p_pdcp_lte_info->direction;
450 /* Info to attach to frame when first read, recording what to show about sequence */
453 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
457 gboolean sequenceExpectedCorrect;
458 guint16 sequenceExpected;
459 guint32 previousFrameNum;
460 guint32 nextFrameNum;
466 sequence_state state;
467 } pdcp_sequence_report_in_frame;
469 /* The sequence analysis frame report hash table.
470 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
471 static GHashTable *pdcp_lte_sequence_analysis_report_hash = NULL;
473 /* Gather together security settings in order to be able to do deciphering */
474 typedef struct pdu_security_settings_t
477 enum security_ciphering_algorithm_e ciphering;
482 } pdu_security_settings_t;
485 /* Add to the tree values associated with sequence analysis for this frame */
486 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
487 pdcp_lte_info *p_pdcp_lte_info,
488 guint16 sequenceNumber,
489 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
490 proto_tree *security_tree,
491 pdu_security_settings_t *pdu_security)
493 proto_tree *seqnum_tree;
494 proto_item *seqnum_ti;
495 proto_item *ti_expected_sn;
499 seqnum_ti = proto_tree_add_string_format(tree,
500 hf_pdcp_lte_sequence_analysis,
502 "", "Sequence Analysis");
503 seqnum_tree = proto_item_add_subtree(seqnum_ti,
504 ett_pdcp_lte_sequence_analysis);
505 PROTO_ITEM_SET_GENERATED(seqnum_ti);
508 /* Previous channel frame */
509 if (p->previousFrameNum != 0) {
510 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
511 tvb, 0, 0, p->previousFrameNum);
514 /* Expected sequence number */
515 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
516 tvb, 0, 0, p->sequenceExpected);
517 PROTO_ITEM_SET_GENERATED(ti_expected_sn);
519 /* Make sure we have recognised SN length */
520 switch (p_pdcp_lte_info->seqnum_length) {
521 case PDCP_SN_LENGTH_5_BITS:
522 case PDCP_SN_LENGTH_7_BITS:
523 case PDCP_SN_LENGTH_12_BITS:
524 case PDCP_SN_LENGTH_15_BITS:
527 DISSECTOR_ASSERT_NOT_REACHED();
533 PROTO_ITEM_SET_HIDDEN(ti_expected_sn);
534 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
536 PROTO_ITEM_SET_GENERATED(ti);
537 proto_item_append_text(seqnum_ti, " - OK");
539 /* Link to next SN in channel (if known) */
540 if (p->nextFrameNum != 0) {
541 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_next_frame,
542 tvb, 0, 0, p->nextFrameNum);
545 /* May also be able to add key inputs to security tree here */
546 if (security_tree != NULL) {
547 guint32 hfn_multiplier;
554 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_bearer,
555 tvb, 0, 0, p_pdcp_lte_info->channelId-1);
556 PROTO_ITEM_SET_GENERATED(ti);
557 pdu_security->bearer = p_pdcp_lte_info->channelId-1;
560 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_direction,
561 tvb, 0, 0, p_pdcp_lte_info->direction);
562 PROTO_ITEM_SET_GENERATED(ti);
564 /* COUNT (HFN * snLength^2 + SN) */
565 switch (p_pdcp_lte_info->seqnum_length) {
566 case PDCP_SN_LENGTH_5_BITS:
569 case PDCP_SN_LENGTH_7_BITS:
570 hfn_multiplier = 128;
572 case PDCP_SN_LENGTH_12_BITS:
573 hfn_multiplier = 2048;
575 case PDCP_SN_LENGTH_15_BITS:
576 hfn_multiplier = 32768;
579 DISSECTOR_ASSERT_NOT_REACHED();
582 count = (p->hfn * hfn_multiplier) + sequenceNumber;
583 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_count,
585 PROTO_ITEM_SET_GENERATED(ti);
586 pdu_security->count = count;
590 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
591 if (uat_ue_keys_records[record_id].ueid == p_pdcp_lte_info->ueid) {
592 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
593 if (uat_ue_keys_records[record_id].rrcKeyOK) {
594 key = uat_ue_keys_records[record_id].rrcKeyString;
595 pdu_security->key = &(uat_ue_keys_records[record_id].rrcBinaryKey[0]);
596 pdu_security->valid = TRUE;
600 if (uat_ue_keys_records[record_id].upKeyOK) {
601 key = uat_ue_keys_records[record_id].upKeyString;
602 pdu_security->key = &(uat_ue_keys_records[record_id].upBinaryKey[0]);
603 pdu_security->valid = TRUE;
608 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_key,
610 PROTO_ITEM_SET_GENERATED(ti);
616 pdu_security->direction = p_pdcp_lte_info->direction;
621 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
623 PROTO_ITEM_SET_GENERATED(ti);
624 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
626 PROTO_ITEM_SET_GENERATED(ti);
627 if (p->lastSN != p->firstSN) {
628 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
629 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
630 p->firstSN, p->lastSN,
631 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
632 p_pdcp_lte_info->ueid,
633 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
634 p_pdcp_lte_info->channelId);
635 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
636 p->firstSN, p->lastSN);
639 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
640 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
642 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
643 p_pdcp_lte_info->ueid,
644 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
645 p_pdcp_lte_info->channelId);
646 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
652 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
654 PROTO_ITEM_SET_GENERATED(ti);
655 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
657 PROTO_ITEM_SET_GENERATED(ti);
658 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_repeated,
659 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
661 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
662 p_pdcp_lte_info->ueid,
663 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
664 p_pdcp_lte_info->channelId);
665 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
670 /* Incorrect sequence number */
671 expert_add_info_format(pinfo, ti_expected_sn, &ei_pdcp_lte_sequence_analysis_wrong_sequence_number,
672 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
673 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
674 p_pdcp_lte_info->ueid,
675 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
676 p_pdcp_lte_info->channelId,
677 sequenceNumber, p->sequenceExpected);
683 /* Update the channel status and set report for this frame */
684 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
685 pdcp_lte_info *p_pdcp_lte_info,
686 guint16 sequenceNumber,
688 proto_tree *security_tree,
689 pdu_security_settings_t *pdu_security)
691 pdcp_channel_hash_key channel_key;
692 pdcp_channel_status *p_channel_status;
693 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
694 gboolean createdChannel = FALSE;
695 guint16 expectedSequenceNumber = 0;
698 /* If find stat_report_in_frame already, use that and get out */
699 if (pinfo->fd->flags.visited) {
701 (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
702 get_report_hash_key(sequenceNumber,
704 p_pdcp_lte_info, FALSE));
705 if (p_report_in_frame != NULL) {
706 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
708 pinfo, tree, tvb, security_tree, pdu_security);
712 /* Give up - we must have tried already... */
718 /**************************************************/
719 /* Create or find an entry for this channel state */
720 channel_key.ueId = p_pdcp_lte_info->ueid;
721 channel_key.plane = p_pdcp_lte_info->plane;
722 channel_key.channelId = p_pdcp_lte_info->channelId;
723 channel_key.direction = p_pdcp_lte_info->direction;
724 channel_key.notUsed = 0;
726 /* Do the table lookup */
727 p_channel_status = (pdcp_channel_status*)g_hash_table_lookup(pdcp_sequence_analysis_channel_hash,
728 get_channel_hash_key(&channel_key));
730 /* Create table entry if necessary */
731 if (p_channel_status == NULL) {
732 createdChannel = TRUE;
734 /* Allocate a new value and duplicate key contents */
735 p_channel_status = wmem_new0(wmem_file_scope(), pdcp_channel_status);
738 g_hash_table_insert(pdcp_sequence_analysis_channel_hash,
739 get_channel_hash_key(&channel_key), p_channel_status);
742 /* Create space for frame state_report */
743 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
744 p_report_in_frame->nextFrameNum = 0;
746 switch (p_pdcp_lte_info->seqnum_length) {
747 case PDCP_SN_LENGTH_5_BITS:
750 case PDCP_SN_LENGTH_7_BITS:
753 case PDCP_SN_LENGTH_12_BITS:
756 case PDCP_SN_LENGTH_15_BITS:
760 DISSECTOR_ASSERT_NOT_REACHED();
764 /* Work out expected sequence number */
765 if (!createdChannel) {
766 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
769 expectedSequenceNumber = sequenceNumber;
772 /* Set report for this frame */
773 /* For PDCP, sequence number is always expectedSequence number */
774 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
775 p_report_in_frame->hfn = p_channel_status->hfn;
777 /* For wrong sequence number... */
778 if (!p_report_in_frame->sequenceExpectedCorrect) {
780 /* Frames are not missing if we get an earlier sequence number again */
781 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
782 p_report_in_frame->state = SN_Missing;
783 p_report_in_frame->firstSN = expectedSequenceNumber;
784 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
786 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
787 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
789 /* Update channel status to remember *this* frame */
790 p_channel_status->previousFrameNum = pinfo->fd->num;
791 p_channel_status->previousSequenceNumber = sequenceNumber;
794 /* An SN has been repeated */
795 p_report_in_frame->state = SN_Repeated;
796 p_report_in_frame->firstSN = sequenceNumber;
798 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
799 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
804 p_report_in_frame->state = SN_OK;
805 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
806 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
807 /* SN has rolled around, inc hfn! */
808 if (!createdChannel && (sequenceNumber == 0)) {
809 /* TODO: not worrying about HFN rolling over for now! */
810 p_channel_status->hfn++;
811 p_report_in_frame->hfn = p_channel_status->hfn;
814 /* Update channel status to remember *this* frame */
815 p_channel_status->previousFrameNum = pinfo->fd->num;
816 p_channel_status->previousSequenceNumber = sequenceNumber;
818 if (p_report_in_frame->previousFrameNum != 0) {
819 /* Get report for previous frame */
820 pdcp_sequence_report_in_frame *p_previous_report;
821 p_previous_report = (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
822 get_report_hash_key((sequenceNumber+32767) % 32768,
823 p_report_in_frame->previousFrameNum,
826 /* It really shouldn't be NULL... */
827 if (p_previous_report != NULL) {
828 /* Point it forward to this one */
829 p_previous_report->nextFrameNum = pinfo->fd->num;
834 /* Associate with this frame number */
835 g_hash_table_insert(pdcp_lte_sequence_analysis_report_hash,
836 get_report_hash_key(sequenceNumber, pinfo->fd->num,
837 p_pdcp_lte_info, TRUE),
840 /* Add state report for this frame into tree */
841 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
842 pinfo, tree, tvb, security_tree, pdu_security);
847 /* Hash table for security state for a UE
848 Maps UEId -> pdcp_security_info_t* */
849 static gint pdcp_lte_ueid_hash_equal(gconstpointer v, gconstpointer v2)
853 static guint pdcp_lte_ueid_hash_func(gconstpointer v)
855 return GPOINTER_TO_UINT(v);
857 static GHashTable *pdcp_security_hash = NULL;
859 /* Result is (ueid, framenum) -> pdcp_security_info_t* */
860 typedef struct ueid_frame_t {
865 /* Convenience function to get a pointer for the hash_func to work with */
866 static gpointer get_ueid_frame_hash_key(guint16 ueid, guint32 frameNumber,
869 static ueid_frame_t key;
872 /* Only allocate a struct when will be adding entry */
874 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
877 memset(&key, 0, sizeof(ueid_frame_t));
881 /* Fill in details, and return pointer */
882 p_key->framenum = frameNumber;
888 static gint pdcp_lte_ueid_frame_hash_equal(gconstpointer v, gconstpointer v2)
890 ueid_frame_t *ueid_frame_1 = (ueid_frame_t *)v;
891 ueid_frame_t *ueid_frame_2 = (ueid_frame_t *)v2;
892 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) && (ueid_frame_1->ueid == ueid_frame_2->ueid));
894 static guint pdcp_lte_ueid_frame_hash_func(gconstpointer v)
896 ueid_frame_t *ueid_frame = (ueid_frame_t *)v;
897 return ueid_frame->framenum + 100*ueid_frame->ueid;
899 static GHashTable *pdcp_security_result_hash = NULL;
904 /* Write the given formatted text to:
906 - the top-level RLC PDU item */
907 static void write_pdu_label_and_info(proto_item *pdu_ti,
908 packet_info *pinfo, const char *format, ...)
910 #define MAX_INFO_BUFFER 256
911 static char info_buffer[MAX_INFO_BUFFER];
915 va_start(ap, format);
916 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
919 /* Add to indicated places */
920 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
921 proto_item_append_text(pdu_ti, "%s", info_buffer);
926 /***************************************************************/
930 /* Show in the tree the config info attached to this frame, as generated fields */
931 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
932 pdcp_lte_info *p_pdcp_info)
935 proto_tree *configuration_tree;
936 proto_item *configuration_ti = proto_tree_add_item(tree,
937 hf_pdcp_lte_configuration,
938 tvb, 0, 0, ENC_ASCII|ENC_NA);
939 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
942 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
943 p_pdcp_info->direction);
944 PROTO_ITEM_SET_GENERATED(ti);
947 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
949 PROTO_ITEM_SET_GENERATED(ti);
952 if (p_pdcp_info->ueid != 0) {
953 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
955 PROTO_ITEM_SET_GENERATED(ti);
959 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
960 p_pdcp_info->channelType);
961 PROTO_ITEM_SET_GENERATED(ti);
962 if (p_pdcp_info->channelId != 0) {
964 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
965 p_pdcp_info->channelId);
966 PROTO_ITEM_SET_GENERATED(ti);
970 /* User-plane-specific fields */
971 if (p_pdcp_info->plane == USER_PLANE) {
974 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
975 p_pdcp_info->no_header_pdu);
976 PROTO_ITEM_SET_GENERATED(ti);
978 if (!p_pdcp_info->no_header_pdu) {
981 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
982 p_pdcp_info->seqnum_length);
983 PROTO_ITEM_SET_GENERATED(ti);
987 /* ROHC compression */
988 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
989 p_pdcp_info->rohc.rohc_compression);
990 PROTO_ITEM_SET_GENERATED(ti);
992 /* ROHC-specific settings */
993 if (p_pdcp_info->rohc.rohc_compression) {
996 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
997 p_pdcp_info->rohc.mode);
998 PROTO_ITEM_SET_GENERATED(ti);
1001 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1002 p_pdcp_info->rohc.rnd);
1003 PROTO_ITEM_SET_GENERATED(ti);
1006 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1007 p_pdcp_info->rohc.udp_checksum_present);
1008 PROTO_ITEM_SET_GENERATED(ti);
1011 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1012 p_pdcp_info->rohc.profile);
1013 PROTO_ITEM_SET_GENERATED(ti);
1015 /* CID Inclusion Info */
1016 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1017 p_pdcp_info->rohc.cid_inclusion_info);
1018 PROTO_ITEM_SET_GENERATED(ti);
1021 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1022 p_pdcp_info->rohc.large_cid_present);
1023 PROTO_ITEM_SET_GENERATED(ti);
1026 /* Append summary to configuration root */
1027 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1028 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1029 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1031 if (p_pdcp_info->rohc.rohc_compression) {
1032 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1033 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1035 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1037 proto_item_append_text(configuration_ti, ")");
1038 PROTO_ITEM_SET_GENERATED(configuration_ti);
1040 /* Show plane in info column */
1041 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1042 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1047 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1048 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info *p_pdcp_info)
1050 dissector_handle_t rrc_handle = 0;
1052 switch (p_pdcp_info->channelType)
1055 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1056 rrc_handle = find_dissector("lte_rrc.ul_ccch");
1059 rrc_handle = find_dissector("lte_rrc.dl_ccch");
1063 rrc_handle = find_dissector("lte_rrc.pcch");
1066 switch (p_pdcp_info->BCCHTransport) {
1068 rrc_handle = find_dissector("lte_rrc.bcch_bch");
1070 case DLSCH_TRANSPORT:
1071 rrc_handle = find_dissector("lte_rrc.bcch_dl_sch");
1076 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1077 rrc_handle = find_dissector("lte_rrc.ul_dcch");
1080 rrc_handle = find_dissector("lte_rrc.dl_dcch");
1093 /* Forwad declarations */
1094 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1096 /* Heuristic dissection */
1097 static gboolean global_pdcp_lte_heur = FALSE;
1099 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1100 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1101 proto_tree *tree, void *data _U_)
1104 struct pdcp_lte_info *p_pdcp_lte_info;
1107 gboolean infoAlreadySet = FALSE;
1108 gboolean seqnumLengthTagPresent = FALSE;
1110 /* This is a heuristic dissector, which means we get all the UDP
1111 * traffic not sent to a known dissector and not claimed by
1112 * a heuristic dissector called before us!
1115 if (!global_pdcp_lte_heur) {
1119 /* Do this again on re-dissection to re-discover offset of actual PDU */
1121 /* Needs to be at least as long as:
1122 - the signature string
1123 - fixed header bytes
1125 - at least one byte of PDCP PDU payload */
1126 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(PDCP_LTE_START_STRING)+3+2)) {
1130 /* OK, compare with signature string */
1131 if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1134 offset += (gint)strlen(PDCP_LTE_START_STRING);
1137 /* If redissecting, use previous info struct (if available) */
1138 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1139 if (p_pdcp_lte_info == NULL) {
1140 /* Allocate new info struct for this frame */
1141 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1142 infoAlreadySet = FALSE;
1145 infoAlreadySet = TRUE;
1149 /* Read fixed fields */
1150 p_pdcp_lte_info->no_header_pdu = (gboolean)tvb_get_guint8(tvb, offset++);
1151 p_pdcp_lte_info->plane = (enum pdcp_plane)tvb_get_guint8(tvb, offset++);
1152 p_pdcp_lte_info->rohc.rohc_compression = (gboolean)tvb_get_guint8(tvb, offset++);
1154 /* Read optional fields */
1155 while (tag != PDCP_LTE_PAYLOAD_TAG) {
1156 /* Process next tag */
1157 tag = tvb_get_guint8(tvb, offset++);
1159 case PDCP_LTE_SEQNUM_LENGTH_TAG:
1160 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1162 seqnumLengthTagPresent = TRUE;
1164 case PDCP_LTE_DIRECTION_TAG:
1165 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1168 case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1169 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
1172 case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1173 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_guint8(tvb, offset);
1176 case PDCP_LTE_ROHC_IP_VERSION_TAG:
1177 p_pdcp_lte_info->rohc.rohc_ip_version = tvb_get_ntohs(tvb, offset);
1180 case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1181 p_pdcp_lte_info->rohc.cid_inclusion_info = tvb_get_guint8(tvb, offset);
1184 case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1185 p_pdcp_lte_info->rohc.large_cid_present = tvb_get_guint8(tvb, offset);
1188 case PDCP_LTE_ROHC_MODE_TAG:
1189 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)tvb_get_guint8(tvb, offset);
1192 case PDCP_LTE_ROHC_RND_TAG:
1193 p_pdcp_lte_info->rohc.rnd = tvb_get_guint8(tvb, offset);
1196 case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1197 p_pdcp_lte_info->rohc.udp_checksum_present = tvb_get_guint8(tvb, offset);
1200 case PDCP_LTE_ROHC_PROFILE_TAG:
1201 p_pdcp_lte_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1204 case PDCP_LTE_CHANNEL_ID_TAG:
1205 p_pdcp_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1208 case PDCP_LTE_UEID_TAG:
1209 p_pdcp_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1213 case PDCP_LTE_PAYLOAD_TAG:
1214 /* Have reached data, so get out of loop */
1218 /* It must be a recognised tag */
1223 if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1224 /* Conditional field is not present */
1228 if (!infoAlreadySet) {
1229 /* Store info in packet */
1230 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1233 /**************************************/
1234 /* OK, now dissect as PDCP LTE */
1236 /* Create tvb that starts at actual PDCP PDU */
1237 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
1238 dissect_pdcp_lte(pdcp_tvb, pinfo, tree);
1242 /* Called from control protocol to configure security algorithms for the given UE */
1243 void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_security_info_t *security_info)
1245 /* Copy security struct */
1246 pdcp_security_info_t *p_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1247 *p_security = *security_info;
1249 /* And add into security table */
1250 g_hash_table_insert(pdcp_security_hash, GUINT_TO_POINTER((guint)ueid), p_security);
1254 /* Decipher payload if algorithm is supported and plausible inputs are available */
1255 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
1256 pdu_security_settings_t *pdu_security_settings,
1257 enum pdcp_plane plane, gboolean *deciphered)
1259 unsigned char ctr_block[16];
1260 gcry_cipher_hd_t cypher_hd;
1262 guint8* encrypted_data;
1263 guint8* decrypted_data;
1264 gint payload_length;
1265 tvbuff_t *decrypted_tvb;
1267 /* Nothing to do if no ciphering algorithm was specified */
1268 if (!pdu_security_settings->valid) {
1272 /* Only EEA2 supported at the moment */
1273 if (pdu_security_settings->ciphering != eea2) {
1277 /* Don't decipher if turned off in preferences */
1278 if (((plane == SIGNALING_PLANE) && !global_pdcp_decipher_signalling) ||
1279 ((plane == USER_PLANE) && !global_pdcp_decipher_userplane)) {
1284 memset(ctr_block, 0, 16);
1285 /* Only first 5 bytes set */
1286 ctr_block[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1287 ctr_block[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1288 ctr_block[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1289 ctr_block[3] = (pdu_security_settings->count & 0x000000ff);
1290 ctr_block[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1292 /* Open gcrypt handle */
1293 gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0);
1294 if (gcrypt_err != 0) {
1299 gcrypt_err = gcry_cipher_setkey(cypher_hd, pdu_security_settings->key, 16);
1300 if (gcrypt_err != 0) {
1305 gcrypt_err = gcry_cipher_setctr(cypher_hd, ctr_block, 16);
1306 if (gcrypt_err != 0) {
1310 /* Extract the encrypted data into a buffer */
1311 payload_length = tvb_length_remaining(tvb, *offset);
1312 encrypted_data = (guint8 *)g_malloc0(payload_length);
1313 tvb_memcpy(tvb, encrypted_data, *offset, payload_length);
1315 /* Allocate memory to receive decrypted payload */
1316 decrypted_data = (guint8 *)g_malloc0(payload_length);
1318 /* Decrypt the actual data */
1319 gcrypt_err = gcry_cipher_decrypt(cypher_hd,
1320 decrypted_data, payload_length,
1321 encrypted_data, payload_length);
1322 if (gcrypt_err != 0) {
1326 /* TODO: close gcry handle!!! */
1328 /* Create tvb for resulting deciphered sdu */
1329 decrypted_tvb = tvb_new_child_real_data(tvb, decrypted_data, payload_length, payload_length);
1330 tvb_set_free_cb(decrypted_tvb, g_free);
1331 add_new_data_source(pinfo, decrypted_tvb, "Deciphered Payload");
1333 /* Free temp buffer */
1334 g_free(encrypted_data);
1336 /* Return deciphered data, i.e. beginning of new tvb */
1339 return decrypted_tvb;
1342 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo _U_, int *offset _U_,
1343 pdu_security_settings_t *pdu_security_settings _U_,
1344 enum pdcp_plane plane _U_, gboolean *deciphered _U_)
1351 /******************************/
1352 /* Main dissection function. */
1353 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1356 proto_tree *pdcp_tree = NULL;
1357 proto_item *root_ti = NULL;
1360 struct pdcp_lte_info *p_pdcp_info;
1361 tvbuff_t *rohc_tvb = NULL;
1363 pdcp_security_info_t *current_security = NULL; /* current security for this UE */
1364 pdcp_security_info_t *pdu_security; /* security in place for this PDU */
1365 proto_tree *security_tree = NULL;
1366 proto_item *security_ti;
1367 tvbuff_t *payload_tvb;
1368 pdu_security_settings_t pdu_security_settings;
1369 gboolean payload_deciphered = FALSE;
1371 /* Initialise security settings */
1372 pdu_security_settings.valid = FALSE;
1374 /* Set protocol name. */
1375 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1377 /* Look for attached packet info! */
1378 p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1379 /* Can't dissect anything without it... */
1380 if (p_pdcp_info == NULL) {
1384 /* Don't want to overwrite the RLC Info column if configured not to */
1385 if ((global_pdcp_lte_layer_to_show == ShowRLCLayer) &&
1386 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL)) {
1388 col_set_writable(pinfo->cinfo, FALSE);
1391 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
1392 col_clear(pinfo->cinfo, COL_INFO);
1393 col_set_writable(pinfo->cinfo, TRUE);
1396 /* Create pdcp tree. */
1398 root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, ENC_NA);
1399 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1402 /* Set mode string */
1403 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1405 /*****************************************************/
1406 /* Show configuration (attached packet) info in tree */
1408 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1411 /* Show ROHC mode */
1412 if (p_pdcp_info->rohc.rohc_compression) {
1413 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1416 /***************************************/
1417 /* UE security algorithms */
1418 if (!pinfo->fd->flags.visited) {
1419 /* Look up current state by UEID */
1420 current_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_hash,
1421 GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
1422 if (current_security != NULL) {
1423 /* Store any result for this frame in the result table */
1424 pdcp_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1425 *security_to_store = *current_security;
1426 g_hash_table_insert(pdcp_security_result_hash,
1427 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, TRUE),
1432 /* Show security settings for this PDU */
1433 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));
1434 if (pdu_security != NULL) {
1437 /* Create subtree */
1438 security_ti = proto_tree_add_string_format(pdcp_tree,
1439 hf_pdcp_lte_security,
1442 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
1443 PROTO_ITEM_SET_GENERATED(security_ti);
1446 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_setup_frame,
1447 tvb, 0, 0, pdu_security->configuration_frame);
1448 PROTO_ITEM_SET_GENERATED(ti);
1451 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_ciphering_algorithm,
1452 tvb, 0, 0, pdu_security->ciphering);
1453 PROTO_ITEM_SET_GENERATED(ti);
1456 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_integrity_algorithm,
1457 tvb, 0, 0, pdu_security->integrity);
1458 PROTO_ITEM_SET_GENERATED(ti);
1460 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
1461 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
1462 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
1464 pdu_security_settings.ciphering = pdu_security->ciphering;
1468 /***********************************/
1469 /* Handle PDCP header (if present) */
1470 if (!p_pdcp_info->no_header_pdu) {
1472 /* TODO: shouldn't need to initialise this one!! */
1474 gboolean seqnum_set = FALSE;
1476 guint8 first_byte = tvb_get_guint8(tvb, offset);
1478 /*****************************/
1479 /* Signalling plane messages */
1480 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1481 /* Verify 3 reserved bits are 0 */
1482 guint8 reserved = (first_byte & 0xe0) >> 5;
1483 proto_item *ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_plane_reserved,
1484 tvb, offset, 1, ENC_BIG_ENDIAN);
1485 if (reserved != 0) {
1486 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1487 "PDCP signalling header reserved bits not zero");
1490 /* 5-bit sequence number */
1491 seqnum = first_byte & 0x1f;
1493 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, ENC_BIG_ENDIAN);
1494 write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
1497 if (tvb_length_remaining(tvb, offset) == 0) {
1498 /* Only PDCP header was captured, stop dissection here */
1502 else if (p_pdcp_info->plane == USER_PLANE) {
1504 /**********************************/
1505 /* User-plane messages */
1506 gboolean pdu_type = (first_byte & 0x80) >> 7;
1508 /* Data/Control flag */
1509 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
1511 if (pdu_type == 1) {
1512 /*****************************/
1513 /* Use-plane Data */
1515 /* Number of sequence number bits depends upon config */
1516 switch (p_pdcp_info->seqnum_length) {
1517 case PDCP_SN_LENGTH_7_BITS:
1518 seqnum = first_byte & 0x7f;
1520 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, ENC_BIG_ENDIAN);
1523 case PDCP_SN_LENGTH_12_BITS:
1526 guint8 reserved_value;
1528 /* 3 reserved bits */
1529 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN);
1530 reserved_value = (first_byte & 0x70) >> 4;
1532 /* Complain if not 0 */
1533 if (reserved_value != 0) {
1534 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1535 "Reserved bits have value 0x%x - should be 0x0",
1539 /* 12-bit sequence number */
1540 seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
1542 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN);
1546 case PDCP_SN_LENGTH_15_BITS:
1547 seqnum = tvb_get_ntohs(tvb, offset) & 0x7fff;
1549 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_15, tvb, offset, 2, ENC_BIG_ENDIAN);
1553 /* Not a recognised data format!!!!! */
1557 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
1560 /*******************************/
1561 /* User-plane Control messages */
1562 guint8 control_pdu_type = (first_byte & 0x70) >> 4;
1563 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1565 switch (control_pdu_type) {
1566 case 0: /* PDCP status report */
1571 guint not_received = 0;
1573 guint32 len, bit_offset;
1574 proto_tree *bitmap_tree;
1575 proto_item *bitmap_ti = NULL;
1577 #define BUFF_SIZE 49
1579 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
1580 /* First-Missing-Sequence SN */
1581 fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
1582 sn = (fms + 1) % 4096;
1583 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
1584 offset, 2, ENC_BIG_ENDIAN);
1589 guint8 reserved_value;
1591 /* 5 reserved bits */
1592 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN);
1593 reserved_value = (tvb_get_ntohs(tvb, offset) & 0x0f80)>>7;
1596 /* Complain if not 0 */
1597 if (reserved_value != 0) {
1598 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1599 "Reserved bits have value 0x%x - should be 0x0",
1603 /* First-Missing-Sequence SN */
1604 fms = tvb_get_ntohs(tvb, offset) & 0x7fff;
1605 sn = (fms + 1) % 32768;
1606 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms2, tvb,
1607 offset, 2, ENC_BIG_ENDIAN);
1613 if (tvb_length_remaining(tvb, offset) > 0) {
1614 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
1615 offset, -1, ENC_NA);
1616 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
1618 buff = (gchar *)wmem_alloc(wmem_packet_scope(), BUFF_SIZE);
1619 len = tvb_length_remaining(tvb, offset);
1620 bit_offset = offset<<3;
1621 /* For each byte... */
1622 for (i=0; i<len; i++) {
1623 bits = tvb_get_bits8(tvb, bit_offset, 8);
1624 for (l=0, j=0; l<8; l++) {
1625 if ((bits << l) & 0x80) {
1626 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%5u,", (unsigned)(sn+(8*i)+l)%modulo);
1628 j += g_snprintf(&buff[j], BUFF_SIZE-j, " ,");
1632 proto_tree_add_text(bitmap_tree, tvb, bit_offset/8, 1, "%s", buff);
1637 if (bitmap_ti != NULL) {
1638 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
1640 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
1645 case 1: /* ROHC Feedback */
1647 break; /* Drop-through to dissect feedback */
1649 default: /* Reserved */
1655 /* Invalid plane setting...! */
1656 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
1657 p_pdcp_info->plane);
1661 /* Do sequence analysis if configured to. */
1663 gboolean do_analysis = FALSE;
1665 switch (global_pdcp_check_sequence_numbers) {
1668 case SEQUENCE_ANALYSIS_RLC_ONLY:
1669 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL) &&
1670 !p_pdcp_info->is_retx) {
1674 case SEQUENCE_ANALYSIS_PDCP_ONLY:
1675 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) == NULL) {
1682 checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
1683 (guint16)seqnum, pdcp_tree, security_tree,
1684 &pdu_security_settings);
1689 /* Show that it's a no-header PDU */
1690 write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
1693 /*******************************************************/
1694 /* Now deal with the payload */
1695 /*******************************************************/
1697 /* Check pdu_security_settings - may need to do deciphering before calling
1698 further dissectors on payload */
1699 payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info->plane, &payload_deciphered);
1701 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1702 guint32 data_length;
1705 /* RRC data is all but last 4 bytes.
1706 Call lte-rrc dissector (according to direction and channel type) */
1707 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
1708 ((pdu_security == NULL) || (pdu_security->ciphering == 0) || payload_deciphered || !pdu_security->seen_next_ul_pdu)){
1709 /* Get appropriate dissector handle */
1710 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1712 if (rrc_handle != 0) {
1713 /* Call RRC dissector if have one */
1714 tvbuff_t *rrc_payload_tvb = tvb_new_subset(payload_tvb, offset,
1715 tvb_length_remaining(payload_tvb, offset) - 4,
1716 tvb_length_remaining(payload_tvb, offset) - 4);
1717 gboolean was_writable = col_get_writable(pinfo->cinfo);
1719 /* We always want to see this in the info column */
1720 col_set_writable(pinfo->cinfo, TRUE);
1722 call_dissector_only(rrc_handle, rrc_payload_tvb, pinfo, pdcp_tree, NULL);
1724 /* Restore to whatever it was */
1725 col_set_writable(pinfo->cinfo, was_writable);
1728 /* Just show data */
1729 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
1730 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1733 if (!pinfo->fd->flags.visited &&
1734 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
1735 p_pdcp_info->direction == DIRECTION_UPLINK)
1737 /* i.e. we have already seen SecurityModeResponse! */
1738 current_security->seen_next_ul_pdu = TRUE;
1743 /* Just show as unparsed data */
1744 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
1745 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1748 data_length = tvb_length_remaining(payload_tvb, offset) - 4;
1749 offset += data_length;
1751 /* Last 4 bytes are MAC */
1752 mac = tvb_get_ntohl(tvb, offset);
1753 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
1756 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
1760 /* User-plane payload here */
1762 /* If not compressed with ROHC, show as user-plane data */
1763 if (!p_pdcp_info->rohc.rohc_compression) {
1764 gint payload_length = tvb_length_remaining(payload_tvb, offset);
1765 if (payload_length > 0) {
1766 if (p_pdcp_info->plane == USER_PLANE) {
1768 /* Not attempting to decode payload if ciphering is enabled
1769 (and NULL ciphering is not being used) */
1770 if (global_pdcp_dissect_user_plane_as_ip &&
1771 ((pdu_security == NULL) || (pdu_security->ciphering == 0) || payload_deciphered))
1773 tvbuff_t *ip_payload_tvb = tvb_new_subset_remaining(payload_tvb, offset);
1775 /* Don't update info column for ROHC unless configured to */
1776 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
1777 col_set_writable(pinfo->cinfo, FALSE);
1780 switch (tvb_get_guint8(ip_payload_tvb, offset) & 0xf0) {
1782 call_dissector_only(ip_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
1785 call_dissector_only(ipv6_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
1788 call_dissector_only(data_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
1792 /* Freeze the columns again because we don't want other layers writing to info */
1793 if (global_pdcp_lte_layer_to_show == ShowTrafficLayer) {
1794 col_set_writable(pinfo->cinfo, FALSE);
1799 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, payload_tvb, offset, -1, ENC_NA);
1803 write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
1807 /* (there will be no signalling data left at this point) */
1809 /* Let RLC write to columns again */
1810 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
1812 /* DROPPING OUT HERE IF NOT DOING ROHC! */
1816 /***************************/
1818 /***************************/
1820 /* Only attempt ROHC if configured to */
1821 if (!global_pdcp_dissect_rohc) {
1822 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
1823 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1827 rohc_offset = offset;
1828 rohc_tvb = tvb_new_subset_remaining(payload_tvb, rohc_offset);
1830 /* Only enable writing to column if configured to show ROHC */
1831 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
1832 col_set_writable(pinfo->cinfo, FALSE);
1835 col_clear(pinfo->cinfo, COL_INFO);
1838 /* Call the ROHC dissector */
1839 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
1841 /* Let RLC write to columns again */
1842 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
1847 /* Initializes the hash tables each time a new
1848 * file is loaded or re-loaded in wireshark */
1849 static void pdcp_lte_init_protocol(void)
1851 /* Destroy any existing hashes. */
1852 if (pdcp_sequence_analysis_channel_hash) {
1853 g_hash_table_destroy(pdcp_sequence_analysis_channel_hash);
1855 if (pdcp_lte_sequence_analysis_report_hash) {
1856 g_hash_table_destroy(pdcp_lte_sequence_analysis_report_hash);
1858 if (pdcp_security_hash) {
1859 g_hash_table_destroy(pdcp_security_hash);
1861 if (pdcp_security_result_hash) {
1862 g_hash_table_destroy(pdcp_security_result_hash);
1865 /* Now create them over */
1866 pdcp_sequence_analysis_channel_hash = g_hash_table_new(pdcp_channel_hash_func, pdcp_channel_equal);
1867 pdcp_lte_sequence_analysis_report_hash = g_hash_table_new(pdcp_result_hash_func, pdcp_result_hash_equal);
1868 pdcp_security_hash = g_hash_table_new(pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal);
1869 pdcp_security_result_hash = g_hash_table_new(pdcp_lte_ueid_frame_hash_func, pdcp_lte_ueid_frame_hash_equal);
1874 void proto_register_pdcp(void)
1876 static hf_register_info hf[] =
1878 { &hf_pdcp_lte_configuration,
1880 "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
1881 "Configuration info passed into dissector", HFILL
1885 { &hf_pdcp_lte_rohc_compression,
1886 { "ROHC Compression",
1887 "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1891 { &hf_pdcp_lte_rohc_mode,
1893 "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
1897 { &hf_pdcp_lte_rohc_rnd,
1899 "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
1900 "RND of outer ip header", HFILL
1903 { &hf_pdcp_lte_rohc_udp_checksum_present,
1905 "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1906 "UDP Checksum present", HFILL
1909 { &hf_pdcp_lte_direction,
1911 "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1912 "Direction of message", HFILL
1915 { &hf_pdcp_lte_ueid,
1917 "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1918 "UE Identifier", HFILL
1921 { &hf_pdcp_lte_channel_type,
1923 "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
1927 { &hf_pdcp_lte_channel_id,
1929 "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
1933 { &hf_pdcp_lte_rohc_profile,
1935 "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
1939 { &hf_pdcp_lte_no_header_pdu,
1941 "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
1945 { &hf_pdcp_lte_plane,
1947 "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
1951 { &hf_pdcp_lte_seqnum_length,
1953 "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
1954 "Sequence Number Length", HFILL
1959 { &hf_pdcp_lte_cid_inclusion_info,
1960 { "CID Inclusion Info",
1961 "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
1965 { &hf_pdcp_lte_large_cid_present,
1966 { "Large CID Present",
1967 "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
1972 { &hf_pdcp_lte_control_plane_reserved,
1974 "pdcp-lte.reserved", FT_UINT8, BASE_DEC, NULL, 0xe0,
1978 { &hf_pdcp_lte_seq_num_5,
1980 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
1981 "PDCP Seq num", HFILL
1984 { &hf_pdcp_lte_seq_num_7,
1986 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
1987 "PDCP Seq num", HFILL
1990 { &hf_pdcp_lte_reserved3,
1992 "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
1993 "3 reserved bits", HFILL
1996 { &hf_pdcp_lte_seq_num_12,
1998 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
1999 "PDCP Seq num", HFILL
2002 { &hf_pdcp_lte_seq_num_15,
2004 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2005 "PDCP Seq num", HFILL
2008 { &hf_pdcp_lte_signalling_data,
2009 { "Signalling Data",
2010 "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2016 "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
2020 { &hf_pdcp_lte_data_control,
2022 "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
2026 { &hf_pdcp_lte_user_plane_data,
2027 { "User-Plane Data",
2028 "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2032 { &hf_pdcp_lte_control_pdu_type,
2033 { "Control PDU Type",
2034 "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2039 { "First Missing Sequence Number",
2040 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2041 "First Missing PDCP Sequence Number", HFILL
2044 { &hf_pdcp_lte_reserved4,
2046 "pdcp-lte.reserved4", FT_UINT16, BASE_HEX, NULL, 0x0f80,
2047 "5 reserved bits", HFILL
2050 { &hf_pdcp_lte_fms2,
2051 { "First Missing Sequence Number",
2052 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x07fff,
2053 "First Missing PDCP Sequence Number", HFILL
2056 { &hf_pdcp_lte_bitmap,
2058 "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2059 "Status report bitmap (0=error, 1=OK)", HFILL
2064 { &hf_pdcp_lte_sequence_analysis,
2065 { "Sequence Analysis",
2066 "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2070 { &hf_pdcp_lte_sequence_analysis_ok,
2072 "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2076 { &hf_pdcp_lte_sequence_analysis_previous_frame,
2077 { "Previous frame for channel",
2078 "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2082 { &hf_pdcp_lte_sequence_analysis_next_frame,
2083 { "Next frame for channel",
2084 "pdcp-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2088 { &hf_pdcp_lte_sequence_analysis_expected_sn,
2090 "pdcp-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2094 { &hf_pdcp_lte_sequence_analysis_skipped,
2096 "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2100 { &hf_pdcp_lte_sequence_analysis_repeated,
2102 "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2107 { &hf_pdcp_lte_security,
2108 { "Security Config",
2109 "pdcp-lte.security-cofig", FT_STRING, BASE_NONE, 0, 0x0,
2113 { &hf_pdcp_lte_security_setup_frame,
2114 { "Configuration frame",
2115 "pdcp-lte.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2119 { &hf_pdcp_lte_security_integrity_algorithm,
2120 { "Integrity Algorithm",
2121 "pdcp-lte.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
2125 { &hf_pdcp_lte_security_ciphering_algorithm,
2126 { "Ciphering Algorithm",
2127 "pdcp-lte.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
2131 { &hf_pdcp_lte_security_bearer,
2133 "pdcp-lte.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
2137 { &hf_pdcp_lte_security_direction,
2139 "pdcp-lte.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2143 { &hf_pdcp_lte_security_count,
2145 "pdcp-lte.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2149 { &hf_pdcp_lte_security_key,
2151 "pdcp-lte.security-config.key", FT_STRING, BASE_NONE, NULL, 0x0,
2157 static gint *ett[] =
2160 &ett_pdcp_configuration,
2162 &ett_pdcp_lte_sequence_analysis,
2163 &ett_pdcp_report_bitmap,
2167 static ei_register_info ei[] = {
2168 { &ei_pdcp_lte_sequence_analysis_sn_missing, { "pdcp-lte.sequence-analysis.sn-missing", PI_SEQUENCE, PI_WARN, "PDCP SN missing", EXPFILL }},
2169 { &ei_pdcp_lte_sequence_analysis_sn_repeated, { "pdcp-lte.sequence-analysis.sn-repeated", PI_SEQUENCE, PI_WARN, "PDCP SN repeated", EXPFILL }},
2170 { &ei_pdcp_lte_sequence_analysis_wrong_sequence_number, { "pdcp-lte.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
2171 { &ei_pdcp_lte_reserved_bits_not_zero, { "pdcp-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
2174 static const enum_val_t sequence_analysis_vals[] = {
2175 {"no-analysis", "No-Analysis", FALSE},
2176 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
2177 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
2181 static const enum_val_t show_info_col_vals[] = {
2182 {"show-rlc", "RLC Info", ShowRLCLayer},
2183 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
2184 {"show-traffic", "Traffic Info", ShowTrafficLayer},
2188 #ifdef HAVE_LIBGCRYPT
2189 static uat_field_t ue_keys_uat_flds[] = {
2190 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
2191 UAT_FLD_CSTRING(uat_ue_keys_records, rrcKeyString, "RRC Key", "Key for deciphering signalling messages"),
2192 UAT_FLD_CSTRING(uat_ue_keys_records, upKeyString, "User-Plane Key", "Key for deciphering user-plane messages"),
2197 module_t *pdcp_lte_module;
2198 expert_module_t* expert_pdcp_lte;
2200 /* Register protocol. */
2201 proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
2202 proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
2203 proto_register_subtree_array(ett, array_length(ett));
2204 expert_pdcp_lte = expert_register_protocol(proto_pdcp_lte);
2205 expert_register_field_array(expert_pdcp_lte, ei, array_length(ei));
2207 /* Allow other dissectors to find this one by name. */
2208 register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
2210 pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
2212 /* Obsolete preferences */
2213 prefs_register_obsolete_preference(pdcp_lte_module, "show_feedback_option_tag_length");
2216 /* Dissect uncompressed user-plane data as IP */
2217 prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
2218 "Show uncompressed User-Plane data as IP",
2219 "Show uncompressed User-Plane data as IP",
2220 &global_pdcp_dissect_user_plane_as_ip);
2222 /* Dissect unciphered signalling data as RRC */
2223 prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
2224 "Show unciphered Signalling-Plane data as RRC",
2225 "Show unciphered Signalling-Plane data as RRC",
2226 &global_pdcp_dissect_signalling_plane_as_rrc);
2228 /* Check for missing sequence numbers */
2229 prefs_register_enum_preference(pdcp_lte_module, "check_sequence_numbers",
2230 "Do sequence number analysis",
2231 "Do sequence number analysis",
2232 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, FALSE);
2234 /* Attempt to dissect ROHC messages */
2235 prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
2236 "Attempt to decode ROHC data",
2237 "Attempt to decode ROHC data",
2238 &global_pdcp_dissect_rohc);
2240 prefs_register_bool_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp",
2241 "Try Heuristic LTE-PDCP over UDP framing",
2242 "When enabled, use heuristic dissector to find PDCP-LTE frames sent with "
2244 &global_pdcp_lte_heur);
2246 prefs_register_enum_preference(pdcp_lte_module, "layer_to_show",
2247 "Which layer info to show in Info column",
2248 "Can show RLC, PDCP or Traffic layer info in Info column",
2249 &global_pdcp_lte_layer_to_show, show_info_col_vals, FALSE);
2251 #ifdef HAVE_LIBGCRYPT
2252 ue_keys_uat = uat_new("PDCP UE security keys",
2253 sizeof(uat_ue_keys_record_t), /* record size */
2254 "pdcp_lte_ue_keys", /* filename */
2255 TRUE, /* from_profile */
2256 (void**) &uat_ue_keys_records, /* data_ptr */
2257 &num_ue_keys_uat, /* numitems_ptr */
2258 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
2260 uat_ue_keys_record_copy_cb, /* copy callback */
2261 uat_ue_keys_record_update_cb, /* update callback */
2262 uat_ue_keys_record_free_cb, /* free callback */
2263 NULL, /* post update callback */
2264 ue_keys_uat_flds); /* UAT field definitions */
2266 prefs_register_uat_preference(pdcp_lte_module,
2269 "Preconfigured PDCP keys",
2272 /* Attempt to decipher RRC messages */
2273 prefs_register_bool_preference(pdcp_lte_module, "decipher_signalling",
2274 "Attempt to decipher Signalling (RRC) SDUs",
2275 "N.B. only possible if key available and configured",
2276 &global_pdcp_decipher_signalling);
2278 /* Attempt to decipher user-plane messages */
2279 prefs_register_bool_preference(pdcp_lte_module, "decipher_userplane",
2280 "Attempt to decipher User-plane (IP) SDUs",
2281 "N.B. only possible if key available and configured",
2282 &global_pdcp_decipher_userplane);
2285 register_init_routine(&pdcp_lte_init_protocol);
2288 void proto_reg_handoff_pdcp_lte(void)
2290 /* Add as a heuristic UDP dissector */
2291 heur_dissector_add("udp", dissect_pdcp_lte_heur, proto_pdcp_lte);
2293 ip_handle = find_dissector("ip");
2294 ipv6_handle = find_dissector("ipv6");
2295 rohc_handle = find_dissector("rohc");
2296 data_handle = find_dissector("data");
2305 * indent-tabs-mode: nil
2308 * ex: set shiftwidth=4 tabstop=8 expandtab:
2309 * :indentSize=4:tabSize=8:noTabs=true: