diff options
author | Anders <anders.broman@ericsson.com> | 2018-08-23 14:57:35 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-08-24 11:17:16 +0000 |
commit | 7b7f0e81f9e9b91ec9f0b8dfc2a4b2386b340933 (patch) | |
tree | b391e43dd3927bdaec7be4b7f0cba6aeb44b0019 /epan/dissectors/packet-gtp.c | |
parent | 6c836f7b954a3ddd5145f911fe9687bb45449f05 (diff) |
GTP: Refactor dissection of T-PDU and adding of PDCP data
Change-Id: I9548ec85a351f8682a8a7d89f43c6dbd20cfe66d
Reviewed-on: https://code.wireshark.org/review/29271
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-gtp.c')
-rw-r--r-- | epan/dissectors/packet-gtp.c | 463 |
1 files changed, 316 insertions, 147 deletions
diff --git a/epan/dissectors/packet-gtp.c b/epan/dissectors/packet-gtp.c index 65bf2146b0..77a5779431 100644 --- a/epan/dissectors/packet-gtp.c +++ b/epan/dissectors/packet-gtp.c @@ -53,6 +53,7 @@ #include <epan/srt_table.h> #include <epan/to_str.h> #include <epan/uat.h> +#include <epan/proto_data.h> #include "packet-ppp.h" #include "packet-radius.h" @@ -64,6 +65,7 @@ #include "packet-gtp.h" #include "packet-ranap.h" #include "packet-pdcp-nr.h" +#include "packet-pdcp-lte.h" #include "packet-rohc.h" void proto_register_gtp(void); @@ -89,7 +91,9 @@ static dissector_handle_t gtp_handle, gtp_prime_handle; #define GTP_TPDU_AS_NONE -1 #define GTP_TPDU_AS_TPDU_HEUR 0 -#define GTP_TPDU_AS_SYNC 2 +#define GTP_TPDU_AS_PDCP_LTE 1 +#define GTP_TPDU_AS_PDCP_NR 2 +#define GTP_TPDU_AS_SYNC 3 static gboolean g_gtp_over_tcp = TRUE; gboolean g_gtp_session = FALSE; @@ -435,6 +439,7 @@ static gint ett_gtp_cdr_dr = -1; static gint ett_gtp_mm_cntxt = -1; static gint ett_gtp_utran_cont = -1; static gint ett_gtp_nr_ran_cont = -1; +static gint ett_gtp_pdcp_no_conf = -1; static expert_field ei_gtp_ext_hdr_pdcpsn = EI_INIT; static expert_field ei_gtp_ext_length_mal = EI_INIT; @@ -450,9 +455,31 @@ static expert_field ei_gtp_ext_geo_loc_type = EI_INIT; static expert_field ei_gtp_iei = EI_INIT; static expert_field ei_gtp_unknown_extention_header = EI_INIT; -/* --- PDCP NR DECODE ADDITIONS --- */ +/* --- PDCP DECODE ADDITIONS --- */ +typedef struct { + guint teid; + guint header_present; + enum pdcp_plane plane; + guint lte_sn_length; + guint rohc_compression; + //guint rohc_mode; + guint rohc_profile; +} uat_pdcp_lte_keys_record_t; + +/* N.B. this is an array/table of the struct above, where ueid is the key */ +static uat_pdcp_lte_keys_record_t *uat_pdcp_lte_keys_records = NULL; + +#define PDCP_SN_LENGTH_12_BITS_STR "12 BITS" +static const value_string vs_pdcp_lte_sn_length[] = { + {PDCP_SN_LENGTH_5_BITS, "5 BITS"}, + {PDCP_SN_LENGTH_7_BITS, "7 BITS"}, + {PDCP_SN_LENGTH_12_BITS, PDCP_SN_LENGTH_12_BITS_STR}, + {PDCP_SN_LENGTH_15_BITS, "15 BITS"}, + {PDCP_SN_LENGTH_18_BITS, "18 BITS"}, + {0, NULL} +}; -/* Struct for saving PDCP information about specific TEID */ +/* Struct for saving PDCP-NR information about specific TEID */ typedef struct { guint teid; guint direction; @@ -460,14 +487,14 @@ typedef struct { guint sdap_header_present; guint mac_i_presence; enum pdcp_nr_plane plane; - guint pdcp_sn_length; + guint pdcp_nr_sn_length; guint rohc_compression; //guint rohc_mode; guint rohc_profile; } uat_pdcp_nr_keys_record_t; /* N.B. this is an array/table of the struct above, where ueid is the key */ -static uat_pdcp_nr_keys_record_t *uat_pdcp_keys_records = NULL; +static uat_pdcp_nr_keys_record_t *uat_pdcp_nr_keys_records = NULL; #define PDCP_NR_DIRECTION_UPLINK_STR "UL" static const value_string vs_direction[] = { @@ -486,6 +513,16 @@ static const value_string vs_sdap_header_present[] = { { 0, NULL } }; +#define PDCP_LTE_HEADER_NOT_PRESENT_STR "Header NOT present" +#define PDCP_LTE_HEADER_NOT_PRESENT 0 +#define PDCP_LTE_HEADER_PRESENT 1 + +static const value_string vs_header_present[] = { + { 0, PDCP_LTE_HEADER_NOT_PRESENT_STR }, + { 1, "Header present" }, + { 0, NULL } +}; + #define MAC_I_PRESENCE_FALSE_STR "FALSE" static const value_string vs_mac_i_presence[] = { @@ -502,7 +539,7 @@ static const value_string vs_pdcp_plane[] = { }; #define PDCP_SN_LENGTH_12_BITS_STR "12 BITS" -static const value_string vs_pdcp_sn_length[] = { +static const value_string vs_pdcp_nr_sn_length[] = { { PDCP_NR_SN_LENGTH_12_BITS, PDCP_SN_LENGTH_12_BITS_STR }, { PDCP_NR_SN_LENGTH_18_BITS, "18 BITS" }, { 0, NULL } @@ -536,38 +573,76 @@ static const value_string vs_rohc_profile[] = { }; /* Entries added by UAT */ -static uat_t * pdcp_keys_uat = NULL; -static guint num_pdcp_keys_uat = 0; +static uat_t * pdcp_nr_keys_uat = NULL; +static guint num_pdcp_nr_keys_uat = 0; /* Default values for a TEID entry */ -UAT_HEX_CB_DEF(uat_pdcp_keys_records, teid, uat_pdcp_nr_keys_record_t) -UAT_VS_DEF(pdcp_users, direction, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_DIRECTION_UPLINK, PDCP_NR_DIRECTION_UPLINK_STR) -UAT_VS_DEF(pdcp_users, sdap_header_present, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_SDAP_HEADER_PRESENT, PDCP_NR_SDAP_HEADER_PRESENT_STR) -UAT_VS_DEF(pdcp_users, mac_i_presence, uat_pdcp_nr_keys_record_t, guint, FALSE, MAC_I_PRESENCE_FALSE_STR) -UAT_VS_DEF(pdcp_users, plane, uat_pdcp_nr_keys_record_t, enum pdcp_nr_plane, NR_USER_PLANE, USER_PLANE_STR) -UAT_VS_DEF(pdcp_users, pdcp_sn_length, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_SN_LENGTH_12_BITS, PDCP_SN_LENGTH_12_BITS_STR) -UAT_VS_DEF(pdcp_users, rohc_compression, uat_pdcp_nr_keys_record_t, guint, TRUE, ROHC_COMPRESSION_TRUE_STR) -//UAT_VS_DEF(pdcp_users, rohc_mode, uat_pdcp_nr_keys_record_t, guint, MODE_NOT_SET, ROHC_MODE_NOT_SET_STR) -UAT_VS_DEF(pdcp_users, rohc_profile, uat_pdcp_nr_keys_record_t, guint, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_UNCOMPRESSED_STR) +UAT_HEX_CB_DEF(uat_pdcp_nr_keys_records, teid, uat_pdcp_nr_keys_record_t) +UAT_VS_DEF(pdcp_nr_users, direction, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_DIRECTION_UPLINK, PDCP_NR_DIRECTION_UPLINK_STR) +UAT_VS_DEF(pdcp_nr_users, sdap_header_present, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_SDAP_HEADER_PRESENT, PDCP_NR_SDAP_HEADER_PRESENT_STR) +UAT_VS_DEF(pdcp_nr_users, mac_i_presence, uat_pdcp_nr_keys_record_t, guint, FALSE, MAC_I_PRESENCE_FALSE_STR) +UAT_VS_DEF(pdcp_nr_users, plane, uat_pdcp_nr_keys_record_t, enum pdcp_nr_plane, NR_USER_PLANE, USER_PLANE_STR) +UAT_VS_DEF(pdcp_nr_users, pdcp_nr_sn_length, uat_pdcp_nr_keys_record_t, guint, PDCP_NR_SN_LENGTH_12_BITS, PDCP_SN_LENGTH_12_BITS_STR) +UAT_VS_DEF(pdcp_nr_users, rohc_compression, uat_pdcp_nr_keys_record_t, guint, TRUE, ROHC_COMPRESSION_TRUE_STR) +//UAT_VS_DEF(pdcp_nr_users, rohc_mode, uat_pdcp_nr_keys_record_t, guint, MODE_NOT_SET, ROHC_MODE_NOT_SET_STR) +UAT_VS_DEF(pdcp_nr_users, rohc_profile, uat_pdcp_nr_keys_record_t, guint, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_UNCOMPRESSED_STR) /* Table from ueid -> uat_pdcp_nr_keys_record_t* */ -static wmem_map_t *pdcp_security_key_hash = NULL; +static wmem_map_t *pdcp_nr_security_key_hash = NULL; + +static uat_pdcp_nr_keys_record_t* look_up_pdcp_nr_keys_record(guint32 teidn) +{ + unsigned int record_id; + + /* Try hash table first (among entries added by set_pdcp_lte_xxx_key() functions) */ + uat_pdcp_nr_keys_record_t* key_record = (uat_pdcp_nr_keys_record_t*)wmem_map_lookup(pdcp_nr_security_key_hash, GUINT_TO_POINTER((guint)teidn)); -static uat_pdcp_nr_keys_record_t* look_up_keys_record(guint32 teidn) + if (key_record != NULL) { + return key_record; + } + + /* Else look up UAT entries. N.B. linear search... */ + for (record_id = 0; record_id < num_pdcp_nr_keys_uat; record_id++) { + if (uat_pdcp_nr_keys_records[record_id].teid == teidn) { + return &uat_pdcp_nr_keys_records[record_id]; + } + } + + /* No match at all - return NULL */ + return NULL; +} + +/* Entries added by UAT */ +static uat_t * pdcp_lte_keys_uat = NULL; +static guint num_pdcp_lte_keys_uat = 0; + +/* Default values for a TEID entry */ +UAT_HEX_CB_DEF(uat_pdcp_lte_keys_records, teid, uat_pdcp_lte_keys_record_t) +UAT_VS_DEF(pdcp_lte_users, header_present, uat_pdcp_lte_keys_record_t, guint, PDCP_LTE_HEADER_PRESENT, PDCP_LTE_HEADER_NOT_PRESENT_STR) +UAT_VS_DEF(pdcp_lte_users, plane, uat_pdcp_lte_keys_record_t, enum pdcp_plane, USER_PLANE, USER_PLANE_STR) +UAT_VS_DEF(pdcp_lte_users, lte_sn_length, uat_pdcp_lte_keys_record_t, guint, PDCP_NR_SN_LENGTH_12_BITS, PDCP_SN_LENGTH_12_BITS_STR) +UAT_VS_DEF(pdcp_lte_users, rohc_compression, uat_pdcp_lte_keys_record_t, guint, TRUE, ROHC_COMPRESSION_TRUE_STR) +//UAT_VS_DEF(pdcp_lte_users, rohc_mode, uat_pdcp_lte_keys_record_t, guint, MODE_NOT_SET, ROHC_MODE_NOT_SET_STR) +UAT_VS_DEF(pdcp_lte_users, rohc_profile, uat_pdcp_lte_keys_record_t, guint, ROHC_PROFILE_UNCOMPRESSED, ROHC_PROFILE_UNCOMPRESSED_STR) + +/* Table from ueid -> uat_pdcp_lte_keys_record_t* */ +static wmem_map_t *pdcp_lte_security_key_hash = NULL; + +static uat_pdcp_lte_keys_record_t* look_up_pdcp_lte_keys_record(guint32 teidn) { unsigned int record_id; /* Try hash table first (among entries added by set_pdcp_lte_xxx_key() functions) */ - uat_pdcp_nr_keys_record_t* key_record = (uat_pdcp_nr_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash, GUINT_TO_POINTER((guint)teidn)); + uat_pdcp_lte_keys_record_t* key_record = (uat_pdcp_lte_keys_record_t*)wmem_map_lookup(pdcp_lte_security_key_hash, GUINT_TO_POINTER((guint)teidn)); if (key_record != NULL) { return key_record; } /* Else look up UAT entries. N.B. linear search... */ - for (record_id = 0; record_id < num_pdcp_keys_uat; record_id++) { - if (uat_pdcp_keys_records[record_id].teid == teidn) { - return &uat_pdcp_keys_records[record_id]; + for (record_id = 0; record_id < num_pdcp_lte_keys_uat; record_id++) { + if (uat_pdcp_lte_keys_records[record_id].teid == teidn) { + return &uat_pdcp_lte_keys_records[record_id]; } } @@ -594,6 +669,8 @@ static gint dissect_tpdu_as = GTP_TPDU_AS_TPDU_HEUR; static const enum_val_t gtp_decode_tpdu_as[] = { {"none", "None", GTP_TPDU_AS_NONE}, {"tpdu heuristic", "TPDU Heuristic", GTP_TPDU_AS_TPDU_HEUR}, + {"pdcp-lte", "PDCP-LTE", GTP_TPDU_AS_PDCP_LTE }, + {"pdcp-nr", "PDCP-NR", GTP_TPDU_AS_PDCP_NR }, {"sync", "SYNC", GTP_TPDU_AS_SYNC}, {NULL, NULL, 0} }; @@ -2063,7 +2140,11 @@ static dissector_handle_t sndcpxid_handle; static dissector_handle_t gtpv2_handle; static dissector_handle_t bssgp_handle; static dissector_handle_t pdcp_nr_handle; +static dissector_handle_t pdcp_lte_handle; static dissector_table_t bssap_pdu_type_table; + +static int proto_pdcp_lte = -1;; + guint32 gtp_session_count; /* Relation between frame -> session */ @@ -8680,7 +8761,7 @@ track_gtp_session(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, gtp_hd } /* TS 38.425 15.2.0*/ -static int +static void addRANContParameter(tvbuff_t *tvb, proto_tree *ran_cont_tree, gint offset) { guint32 pdu_type; @@ -8801,14 +8882,13 @@ addRANContParameter(tvbuff_t *tvb, proto_tree *ran_cont_tree, gint offset) proto_tree_add_item(ran_cont_tree, hf_gtp_ext_hdr_nr_ran_cont_high_retx_nr_pdcp_sn,tvb, offset,3, ENC_BIG_ENDIAN); } } - return pdu_type; } static int dissect_gtp_common(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { - guint8 octet,nr_pdu_type; + guint8 octet; gtp_hdr_t *gtp_hdr = NULL; proto_tree *gtp_tree = NULL, *ext_tree; proto_tree *ran_cont_tree = NULL; @@ -9175,82 +9255,7 @@ dissect_gtp_common(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) * header may be sent without a T-PDU. */ ran_cont_tree = proto_tree_add_subtree(ext_tree, tvb, offset, (ext_hdr_length*4)-1, ett_gtp_nr_ran_cont, NULL,"NR RAN Container"); - nr_pdu_type= addRANContParameter(tvb,ran_cont_tree,offset); - - offset += ext_hdr_length * 4 - 2; - - next_hdr = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(ext_tree, hf_gtp_ext_hdr_next, tvb, offset, 1, next_hdr); - offset++; - if (tvb_reported_length_remaining(tvb, offset) > 0) { - if ((nr_pdu_type == 0) || (nr_pdu_type == 1)) { - /*NR-U DUD or DDDS PDU - * This is NR-U DUD/DDDS PDU. It contains PDCP - * payload as per 3GPP TS 38.323 - */ - /* Check if we have info to call the PDCP dissector */ - uat_pdcp_nr_keys_record_t* found_record; - - if ((found_record = look_up_keys_record((guint32)gtp_hdr->teid))) { - tvbuff_t *pdcp_tvb; - struct pdcp_nr_info temp_data; - - /* Set the ROHC data */ - temp_data.rohc.rohc_compression = found_record->rohc_compression; - temp_data.rohc.rohc_ip_version = 4; /* For now set it explicitly */ - temp_data.rohc.cid_inclusion_info = FALSE; - temp_data.rohc.large_cid_present = FALSE; - temp_data.rohc.mode = MODE_NOT_SET; - temp_data.rohc.rnd = FALSE; - temp_data.rohc.udp_checksum_present = FALSE; - temp_data.rohc.profile = found_record->rohc_profile; - - - pdcp_tvb = tvb_new_subset_remaining(tvb, offset); - /* Fill in pdcp_nr_info */ - - temp_data.direction = found_record->direction; - /*temp_data.ueid*/ - /*temp_data.bearerType;*/ - /*temp_data.bearerId;*/ - - /* Details of PDCP header */ - temp_data.plane = found_record->plane; - temp_data.seqnum_length = found_record->pdcp_sn_length; - /* PDCP_NR_(U|D)L_sdap_hdr_PRESENT bitmask */ - if (found_record->sdap_header_present == PDCP_NR_SDAP_HEADER_PRESENT) { - if (temp_data.direction == PDCP_NR_DIRECTION_UPLINK) { - temp_data.sdap_header = PDCP_NR_UL_SDAP_HEADER_PRESENT; - } else { - temp_data.sdap_header = PDCP_NR_DL_SDAP_HEADER_PRESENT; - } - } else { - temp_data.sdap_header = 0; - } - temp_data.maci_present = found_record->mac_i_presence; - - /* RoHC settings */ - temp_data.rohc.rohc_compression = found_record->rohc_compression; - temp_data.rohc.rohc_ip_version = 4; /* For now set it explicitly */ - temp_data.rohc.cid_inclusion_info = FALSE; - temp_data.rohc.large_cid_present = FALSE; - temp_data.rohc.mode = MODE_NOT_SET; - temp_data.rohc.rnd = FALSE; - temp_data.rohc.udp_checksum_present = FALSE; - temp_data.rohc.profile = found_record->rohc_profile; - - temp_data.is_retx = 0; - - /* Used by heuristic dissector only */ - temp_data.pdu_length = 0; - - call_dissector_with_data(pdcp_nr_handle, pdcp_tvb, pinfo, tree, &temp_data); - } else { - proto_tree_add_item(tree, hf_pdcp_cont, tvb, offset, -1, ENC_NA); - } - return tvb_reported_length(tvb); - } - } + addRANContParameter(tvb,ran_cont_tree,offset); break; @@ -9399,9 +9404,9 @@ dissect_gtp_common(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) } proto_item_set_end(ti, tvb, offset); - if ((gtp_hdr->message == GTP_MSG_TPDU) && dissect_tpdu_as == GTP_TPDU_AS_TPDU_HEUR) { - if(tvb_reported_length_remaining(tvb, offset) > 0){ - + if ((gtp_hdr->message == GTP_MSG_TPDU) && (tvb_reported_length_remaining(tvb, offset) > 0)) { + switch (dissect_tpdu_as) { + case GTP_TPDU_AS_TPDU_HEUR: sub_proto = tvb_get_guint8(tvb, offset); if ((sub_proto >= 0x45) && (sub_proto <= 0x4e)) { @@ -9435,19 +9440,145 @@ dissect_gtp_common(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) call_dissector(ppp_handle, next_tvb, pinfo, tree); #endif proto_tree_add_item(tree, hf_gtp_tpdu_data, tvb, offset, -1, ENC_NA); + col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "GTP <"); + col_append_str(pinfo->cinfo, COL_PROTOCOL, ">"); } - } + break; + case GTP_TPDU_AS_PDCP_LTE: + if (tvb_reported_length_remaining(tvb, offset) > 0) { + /* Check if we have info to call the PDCP dissector */ + struct pdcp_lte_info *p_pdcp_info; + uat_pdcp_lte_keys_record_t * found_record; + tvbuff_t *pdcp_lte_tvb; + + if ((found_record = look_up_pdcp_lte_keys_record((guint32)gtp_hdr->teid))) { + /* Look for attached packet info! */ + p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0); + /* If we don't have the data, add it */ + if (p_pdcp_info == NULL) { + p_pdcp_info = wmem_new0(wmem_file_scope(), pdcp_lte_info); + /* Channel info is needed for RRC parsing */ + /*p_pdcp_info->direction;*/ + /*p_pdcp_info->ueid;*/ + /*p_pdcp_info->channelType;*/ + /*p_pdcp_info->channelId;*/ + /*p_pdcp_info->BCCHTransport;*/ + + /* Details of PDCP header */ + if (found_record->header_present == PDCP_LTE_HEADER_PRESENT) { + p_pdcp_info->no_header_pdu = FALSE; + } else { + p_pdcp_info->no_header_pdu = TRUE; + } + p_pdcp_info->plane = found_record->plane; + p_pdcp_info->seqnum_length = found_record->lte_sn_length; + + /* RoHC settings */ + p_pdcp_info->rohc.rohc_compression = found_record->rohc_compression; + p_pdcp_info->rohc.rohc_ip_version = 4; /* For now set it explicitly */ + p_pdcp_info->rohc.cid_inclusion_info = FALSE; + p_pdcp_info->rohc.large_cid_present = FALSE; + p_pdcp_info->rohc.mode = MODE_NOT_SET; + p_pdcp_info->rohc.rnd = FALSE; + p_pdcp_info->rohc.udp_checksum_present = FALSE; + p_pdcp_info->rohc.profile = found_record->rohc_profile; + + /* p_pdcp_info->is_retx;*/ + + /* Used by heuristic dissector only */ + /*p_pdcp_info->pdu_length;*/ + p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_info); + } + pdcp_lte_tvb = tvb_new_subset_remaining(tvb, offset); + call_dissector(pdcp_lte_handle, pdcp_lte_tvb, pinfo, tree); - col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "GTP <"); - col_append_str(pinfo->cinfo, COL_PROTOCOL, ">"); - } - else if ((gtp_hdr->message == GTP_MSG_TPDU) && dissect_tpdu_as == GTP_TPDU_AS_SYNC) { - next_tvb = tvb_new_subset_remaining(tvb, offset + acfield_len); - call_dissector(sync_handle, next_tvb, pinfo, tree); - col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "GTP <"); - col_append_str(pinfo->cinfo, COL_PROTOCOL, ">"); - } else { - proto_tree_add_item(tree, hf_gtp_tpdu_data, tvb, offset, -1, ENC_NA); + } else { + proto_tree_add_subtree(tree, tvb, offset, -1, ett_gtp_pdcp_no_conf, NULL, "[No PDCP-LTE Configuration data found]"); + proto_tree_add_item(tree, hf_pdcp_cont, tvb, offset, -1, ENC_NA); + } + } + + break; + case GTP_TPDU_AS_PDCP_NR: + if (tvb_reported_length_remaining(tvb, offset) > 0) { + /*NR-U DUD or DDDS PDU + * This is NR-U DUD/DDDS PDU. It contains PDCP + * payload as per 3GPP TS 38.323 + */ + /* Check if we have info to call the PDCP dissector */ + uat_pdcp_nr_keys_record_t* found_record; + + if ((found_record = look_up_pdcp_nr_keys_record((guint32)gtp_hdr->teid))) { + tvbuff_t *pdcp_tvb; + struct pdcp_nr_info temp_data; + + /* Set the ROHC data */ + temp_data.rohc.rohc_compression = found_record->rohc_compression; + temp_data.rohc.rohc_ip_version = 4; /* For now set it explicitly */ + temp_data.rohc.cid_inclusion_info = FALSE; + temp_data.rohc.large_cid_present = FALSE; + temp_data.rohc.mode = MODE_NOT_SET; + temp_data.rohc.rnd = FALSE; + temp_data.rohc.udp_checksum_present = FALSE; + temp_data.rohc.profile = found_record->rohc_profile; + + + pdcp_tvb = tvb_new_subset_remaining(tvb, offset); + /* Fill in pdcp_nr_info */ + + temp_data.direction = found_record->direction; + /*temp_data.ueid*/ + /*temp_data.bearerType;*/ + /*temp_data.bearerId;*/ + + /* Details of PDCP header */ + temp_data.plane = found_record->plane; + temp_data.seqnum_length = found_record->pdcp_nr_sn_length; + /* PDCP_NR_(U|D)L_sdap_hdr_PRESENT bitmask */ + if (found_record->sdap_header_present == PDCP_NR_SDAP_HEADER_PRESENT) { + if (temp_data.direction == PDCP_NR_DIRECTION_UPLINK) { + temp_data.sdap_header = PDCP_NR_UL_SDAP_HEADER_PRESENT; + } else { + temp_data.sdap_header = PDCP_NR_DL_SDAP_HEADER_PRESENT; + } + } else { + temp_data.sdap_header = 0; + } + temp_data.maci_present = found_record->mac_i_presence; + + /* RoHC settings */ + temp_data.rohc.rohc_compression = found_record->rohc_compression; + temp_data.rohc.rohc_ip_version = 4; /* For now set it explicitly */ + temp_data.rohc.cid_inclusion_info = FALSE; + temp_data.rohc.large_cid_present = FALSE; + temp_data.rohc.mode = MODE_NOT_SET; + temp_data.rohc.rnd = FALSE; + temp_data.rohc.udp_checksum_present = FALSE; + temp_data.rohc.profile = found_record->rohc_profile; + + temp_data.is_retx = 0; + + /* Used by heuristic dissector only */ + temp_data.pdu_length = 0; + + call_dissector_with_data(pdcp_nr_handle, pdcp_tvb, pinfo, tree, &temp_data); + } else { + proto_tree_add_subtree(tree, tvb, offset, -1, ett_gtp_pdcp_no_conf, NULL, "[No PDCP-NR Configuration data found]"); + proto_tree_add_item(tree, hf_pdcp_cont, tvb, offset, -1, ENC_NA); + } + } + + break; + case GTP_TPDU_AS_SYNC: + next_tvb = tvb_new_subset_remaining(tvb, offset + acfield_len); + call_dissector(sync_handle, next_tvb, pinfo, tree); + col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "GTP <"); + col_append_str(pinfo->cinfo, COL_PROTOCOL, ">"); + break; + default: + proto_tree_add_item(tree, hf_gtp_tpdu_data, tvb, offset, -1, ENC_NA); + break; + } } tap_queue_packet(gtpv1_tap,pinfo, gtp_hdr); @@ -10819,7 +10950,7 @@ proto_register_gtp(void) }; /* Setup protocol subtree array */ -#define GTP_NUM_INDIVIDUAL_ELEMS 28 +#define GTP_NUM_INDIVIDUAL_ELEMS 29 static gint *ett_gtp_array[GTP_NUM_INDIVIDUAL_ELEMS + NUM_GTP_IES]; ett_gtp_array[0] = &ett_gtp; @@ -10850,6 +10981,7 @@ proto_register_gtp(void) ett_gtp_array[25] = &ett_gtp_mm_cntxt; ett_gtp_array[26] = &ett_gtp_utran_cont; ett_gtp_array[27] = &ett_gtp_nr_ran_cont; + ett_gtp_array[28] = &ett_gtp_pdcp_no_conf; last_offset = GTP_NUM_INDIVIDUAL_ELEMS; @@ -10897,43 +11029,77 @@ proto_register_gtp(void) prefs_register_bool_preference(gtp_module, "dissect_gtp_over_tcp", "Dissect GTP over TCP", "Dissect GTP over TCP", &g_gtp_over_tcp); prefs_register_bool_preference(gtp_module, "track_gtp_session", "Track GTP session", "Track GTP session", &g_gtp_session); - /* --- PDCP NR DECODE ADDITIONS --- */ - - static uat_field_t pdcp_keys_uat_flds[] = { - UAT_FLD_HEX(uat_pdcp_keys_records, teid, "TEID", "Tunnel Endpoint Identifier"), - UAT_FLD_VS(pdcp_users, direction, "Direction", vs_direction, "Direction"), - UAT_FLD_VS(pdcp_users, sdap_header_present, "SDAP header present flag", vs_sdap_header_present, "SDAP header present flag"), - UAT_FLD_VS(pdcp_users, mac_i_presence, "MAC-I presence flag", vs_mac_i_presence, "MAC-I presence flag"), - UAT_FLD_VS(pdcp_users, plane, "PLANE", vs_pdcp_plane, "Signaling or user plane"), - UAT_FLD_VS(pdcp_users, pdcp_sn_length, "PDCP SN LENGTH", vs_pdcp_sn_length, "Length of PDCP sequence number"), - UAT_FLD_VS(pdcp_users, rohc_compression, "ROHC compression", vs_rohc_compression, "Header compression"), - //UAT_FLD_VS(pdcp_users, rohc_mode, "ROHC mode", vs_rohc_mode, "ROHC mode"), - UAT_FLD_VS(pdcp_users, rohc_profile, "ROHC profile", vs_rohc_profile, "ROHC profile"), + /* --- PDCP DECODE ADDITIONS --- */ + + static uat_field_t pdcp_lte_keys_uat_flds[] = { + UAT_FLD_HEX(uat_pdcp_lte_keys_records, teid, "TEID", "Tunnel Endpoint Identifier"), + UAT_FLD_VS(pdcp_lte_users, header_present, "Header present", vs_header_present, "Header present flag"), + UAT_FLD_VS(pdcp_lte_users, plane, "PLANE", vs_pdcp_plane, "Signaling or user plane"), + UAT_FLD_VS(pdcp_lte_users, lte_sn_length, "PDCP SN LENGTH", vs_pdcp_lte_sn_length, "Length of PDCP sequence number"), + UAT_FLD_VS(pdcp_lte_users, rohc_compression, "ROHC compression", vs_rohc_compression, "Header compression"), + //UAT_FLD_VS(pdcp_lte_users, rohc_mode, "ROHC mode", vs_rohc_mode, "ROHC mode"), + UAT_FLD_VS(pdcp_lte_users, rohc_profile, "ROHC profile", vs_rohc_profile, "ROHC profile"), UAT_END_FIELDS }; - pdcp_keys_uat = uat_new("PDCP NR Keys", + pdcp_lte_keys_uat = uat_new("PDCP LTE Keys", + sizeof(uat_pdcp_lte_keys_record_t), /* record size */ + "gtp_pdcp_lte_keys", /* filename */ + TRUE, /* from_profile */ + &uat_pdcp_lte_keys_records, /* data_ptr */ + &num_pdcp_lte_keys_uat, /* numitems_ptr */ + UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ + NULL, /* help */ + NULL, /* copy callback */ + NULL, /* update callback */ + NULL, /* free callback */ + NULL, /* post update callback */ + NULL, /* reset callback */ + pdcp_lte_keys_uat_flds); /* UAT field definitions */ + + prefs_register_uat_preference(gtp_module, + "pdcp_lte_table", + "GTP PDCP LTE Keys", + "Preconfigured PDCP-LTE Keys", + pdcp_lte_keys_uat); + + pdcp_lte_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal); + + static uat_field_t pdcp_nr_keys_uat_flds[] = { + UAT_FLD_HEX(uat_pdcp_nr_keys_records, teid, "TEID", "Tunnel Endpoint Identifier"), + UAT_FLD_VS(pdcp_nr_users, direction, "Direction", vs_direction, "Direction"), + UAT_FLD_VS(pdcp_nr_users, sdap_header_present, "SDAP header present flag", vs_sdap_header_present, "SDAP header present flag"), + UAT_FLD_VS(pdcp_nr_users, mac_i_presence, "MAC-I presence flag", vs_mac_i_presence, "MAC-I presence flag"), + UAT_FLD_VS(pdcp_nr_users, plane, "PLANE", vs_pdcp_plane, "Signaling or user plane"), + UAT_FLD_VS(pdcp_nr_users, pdcp_nr_sn_length, "PDCP SN LENGTH", vs_pdcp_nr_sn_length, "Length of PDCP sequence number"), + UAT_FLD_VS(pdcp_nr_users, rohc_compression, "ROHC compression", vs_rohc_compression, "Header compression"), + //UAT_FLD_VS(pdcp_nr_users, rohc_mode, "ROHC mode", vs_rohc_mode, "ROHC mode"), + UAT_FLD_VS(pdcp_nr_users, rohc_profile, "ROHC profile", vs_rohc_profile, "ROHC profile"), + UAT_END_FIELDS + }; + + pdcp_nr_keys_uat = uat_new("PDCP NR Keys", sizeof(uat_pdcp_nr_keys_record_t), /* record size */ - "gtp_nr_ran_cont_pdcp_keys", /* filename */ - TRUE, /* from_profile */ - &uat_pdcp_keys_records, /* data_ptr */ - &num_pdcp_keys_uat, /* numitems_ptr */ - UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ - NULL, /* help */ - NULL, /* copy callback */ - NULL, /* update callback */ - NULL, /* free callback */ - NULL, /* post update callback */ - NULL, /* reset callback */ - pdcp_keys_uat_flds); /* UAT field definitions */ + "gtp_pdcp_nr_keys", /* filename */ + TRUE, /* from_profile */ + &uat_pdcp_nr_keys_records, /* data_ptr */ + &num_pdcp_nr_keys_uat, /* numitems_ptr */ + UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ + NULL, /* help */ + NULL, /* copy callback */ + NULL, /* update callback */ + NULL, /* free callback */ + NULL, /* post update callback */ + NULL, /* reset callback */ + pdcp_nr_keys_uat_flds); /* UAT field definitions */ prefs_register_uat_preference(gtp_module, - "nr_ran_cont_pdcp_table", - "GTP NR RAN container PDCP Keys", - "Preconfigured NR RAN container PDCP Keys", - pdcp_keys_uat); + "pdcp_nr_table", + "GTP PDCP-NR Keys", + "Preconfigured PDCP-NR Keys", + pdcp_nr_keys_uat); - pdcp_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal); + pdcp_nr_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal); /* --- END PDCP NR DECODE ADDITIONS ---*/ @@ -10988,6 +11154,9 @@ proto_reg_handoff_gtp(void) gtpv2_handle = find_dissector_add_dependency("gtpv2", proto_gtp); bssgp_handle = find_dissector_add_dependency("bssgp", proto_gtp); pdcp_nr_handle = find_dissector_add_dependency("pdcp-nr", proto_gtp); + pdcp_lte_handle = find_dissector_add_dependency("pdcp-lte", proto_gtp); + proto_pdcp_lte = dissector_handle_get_protocol_index(pdcp_lte_handle); + bssap_pdu_type_table = find_dissector_table("bssap.pdu_type"); /* AVP Code: 5 3GPP-GPRS Negotiated QoS profile */ dissector_add_uint("diameter.3gpp", 5, create_dissector_handle(dissect_diameter_3gpp_qosprofile, proto_gtp)); |