diff options
author | Anders Broman <anders.broman@ericsson.com> | 2019-01-08 14:37:59 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2019-01-08 15:58:02 +0000 |
commit | ea001cd6c16b21a993fe7358cef65715dc015e90 (patch) | |
tree | 4d3dc47f11b74575d066d052cafb5b4b849a3d47 /epan/dissectors/packet-nas_5gs.c | |
parent | e0d6041bcfa35297db9ff91c3a5fce4bd3418715 (diff) |
mas5gs: Fix dissection of QoS flow descriptions and QoS rules.
Change-Id: Ie4b9fcf0afdea19ba6f2fb531e84096ac103c99b
Reviewed-on: https://code.wireshark.org/review/31443
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-nas_5gs.c')
-rw-r--r-- | epan/dissectors/packet-nas_5gs.c | 260 |
1 files changed, 152 insertions, 108 deletions
diff --git a/epan/dissectors/packet-nas_5gs.c b/epan/dissectors/packet-nas_5gs.c index 1424e0fb10..89193a9299 100644 --- a/epan/dissectors/packet-nas_5gs.c +++ b/epan/dissectors/packet-nas_5gs.c @@ -222,6 +222,9 @@ static int hf_nas_5gs_sm_session_ambr_ul = -1; static int hf_nas_5gs_sm_all_ssc_mode_b0 = -1; static int hf_nas_5gs_sm_all_ssc_mode_b1 = -1; static int hf_nas_5gs_sm_all_ssc_mode_b2 = -1; +static int hf_nas_5gs_addr_mask_ipv4 = -1; +static int hf_nas_5gs_protocol_identifier_or_next_hd = -1; +static int hf_nas_5gs_protocol_identifier_or_next_hd_val = -1; static int ett_nas_5gs = -1; static int ett_nas_5gs_mm_nssai = -1; @@ -322,6 +325,40 @@ nas5gs_get_private_data(packet_info *pinfo) return nas5gs_data; } +static guint32 +get_ext_ambr_unit(guint32 unit, const char **unit_str) +{ + guint32 mult; + + if (unit == 0) { + mult = 1; + *unit_str = "Unit value 0, Illegal"; + return mult; + } + unit = unit - 1; + + if (unit <= 0x05) { + mult = pow4(guint32, unit); + *unit_str = "Kbps"; + } else if (unit <= 0x0a) { + mult = pow4(guint32, unit - 0x05); + *unit_str = "Mbps"; + } else if (unit <= 0x0e) { + mult = pow4(guint32, unit - 0x07); + *unit_str = "Gbps"; + } else if (unit <= 0x14) { + mult = pow4(guint32, unit - 0x0c); + *unit_str = "Tbps"; + } else if (unit <= 0x19) { + mult = pow4(guint32, unit - 0x11); + *unit_str = "Pbps"; + } else { + mult = 256; + *unit_str = "Pbps"; + } + return mult; +} + /* * 9.11.3 5GS mobility management (5GMM) information elements */ @@ -2092,12 +2129,24 @@ de_nas_5gs_sm_pdu_session_type(tvbuff_t *tvb, proto_tree *tree, packet_info *pin */ static const value_string nas_5gs_sm_qos_des_flow_opt_code_vals[] = { + { 0x00, "Reserved" }, { 0x01, "Create new QoS flow description" }, { 0x02, "Delete existing QoS flow description" }, { 0x03, "Modify existing QoS flow description" }, { 0, NULL } }; +static const value_string nas_5gs_sm_param_id_values[] = { + { 0x01, "5QI" }, + { 0x02, "GFBR uplink" }, + { 0x03, "GFBR downlink" }, + { 0x04, "MFBR uplink" }, + { 0x05, "MFBR downlink" }, + { 0x06, "Averaging window" }, + { 0x07, "EPS bearer identity" }, + { 0, NULL } +}; + static guint16 de_nas_5gs_sm_qos_flow_des(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, guint32 offset, guint len, @@ -2107,9 +2156,11 @@ de_nas_5gs_sm_qos_flow_des(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _ proto_tree *sub_tree, *sub_tree2; proto_item *item; int i = 1, j = 1; - guint32 param_len; + guint32 param_len, param_id; guint32 curr_offset, start_offset; guint8 num_param; + guint32 unit, mult, ambr_val; + const char *unit_str; static const int * param_flags[] = { &hf_nas_5gs_sm_e, @@ -2147,16 +2198,51 @@ de_nas_5gs_sm_qos_flow_des(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _ start_offset = curr_offset; /* Parameter identifier */ - proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_param_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item_ret_uint(sub_tree2, hf_nas_5gs_sm_param_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN, ¶m_id); + proto_item_append_text(item, " - %s", val_to_str_const(param_id, nas_5gs_sm_param_id_values, "Unknown")); curr_offset++; /* Length of parameter contents */ proto_tree_add_item_ret_uint(sub_tree2, hf_nas_5gs_sm_param_len, tvb, curr_offset, 1, ENC_BIG_ENDIAN, ¶m_len); curr_offset++; /*parameter content*/ - proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pal_cont, tvb, curr_offset, param_len, ENC_BIG_ENDIAN); - curr_offset += param_len; - + switch (param_id) { + /* 01H (5QI)*/ + case 0x01: + proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pal_cont, tvb, curr_offset, param_len, ENC_BIG_ENDIAN); + curr_offset += param_len; + break; + /* 02H (GFBR uplink); 04H (MFBR uplink);*/ + case 0x02: + case 0x04: + /* Unit for Session-AMBR for uplink */ + proto_tree_add_item_ret_uint(sub_tree2, hf_nas_5gs_sm_unit_for_session_ambr_ul, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &unit); + curr_offset++; + /* Session-AMBR for downlink */ + mult = get_ext_ambr_unit(unit, &unit_str); + ambr_val = tvb_get_ntohs(tvb, curr_offset); + proto_tree_add_uint_format_value(sub_tree2, hf_nas_5gs_sm_session_ambr_ul, tvb, curr_offset, param_len - 1, + ambr_val, "%u %s (%u)", ambr_val * mult, unit_str, ambr_val); + curr_offset += (param_len - 1); + break; + /* 03H (GFBR downlink); 05H (MFBR downlink);*/ + case 0x03: + case 0x05: + /* Unit for Session-AMBR for uplink */ + proto_tree_add_item_ret_uint(sub_tree2, hf_nas_5gs_sm_unit_for_session_ambr_dl, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &unit); + curr_offset++; + /* Session-AMBR for downlink*/ + mult = get_ext_ambr_unit(unit, &unit_str); + ambr_val = tvb_get_ntohs(tvb, curr_offset); + proto_tree_add_uint_format_value(sub_tree2, hf_nas_5gs_sm_session_ambr_dl, tvb, curr_offset, param_len - 1, + ambr_val, "%u %s (%u)", ambr_val * mult, unit_str, ambr_val); + curr_offset += (param_len - 1); + break; + default: + proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pal_cont, tvb, curr_offset, param_len, ENC_BIG_ENDIAN); + curr_offset += param_len; + break; + } num_param--; j++; proto_item_set_len(item, curr_offset - start_offset); @@ -2168,7 +2254,7 @@ de_nas_5gs_sm_qos_flow_des(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _ return len; } /* - * 9.12.4.13 QoS rules + * 9.11.4.13 QoS rules */ static true_false_string tfs_nas_5gs_sm_dqr = { @@ -2220,17 +2306,6 @@ static const value_string nas_5gs_sm_pkt_flt_dir_values[] = { { 0, NULL } }; -static const value_string nas_5gs_sm_param_id_values[] = { - { 0x01, "5QI" }, - { 0x02, "GFBR uplink" }, - { 0x03, "GFBR downlink" }, - { 0x04, "MFBR uplink" }, - { 0x05, "MFBR downlink" }, - { 0x06, "Averaging window" }, - { 0x07, "EPS bearer identity" }, - { 0, NULL } - }; - static const value_string nas_5gs_rule_param_cont[] = { { 0x0, "Reserved" }, { 0x01, "5QI 1" }, @@ -2251,12 +2326,12 @@ de_nas_5gs_sm_qos_rules(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gchar *add_string _U_, int string_len _U_) { - proto_tree *sub_tree, *sub_tree2, *sub_tree3; + proto_tree *sub_tree, *sub_tree2; proto_item *item; int i = 1, j = 1; - guint32 pf_len, pf_type, param_len; - guint32 length, curr_offset, start_offset, rule_start_offset; - guint8 num_pkt_flt, rop, num_param; + guint32 qos_rule_id, pf_len, pf_type; + guint32 length, curr_offset, start_offset; + guint8 num_pkt_flt, rop; static const int * pkt_flt_flags[] = { &hf_nas_5gs_sm_rop, @@ -2265,24 +2340,17 @@ de_nas_5gs_sm_qos_rules(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, NULL }; - static const int * param_flags[] = { - &hf_nas_5gs_sm_e, - &hf_nas_5gs_sm_nof_params, - NULL - }; - curr_offset = offset; while ((curr_offset - offset) < len) { /* QoS Rule */ - rule_start_offset = curr_offset; sub_tree = proto_tree_add_subtree_format(tree, tvb, curr_offset, -1, ett_nas_5gs_sm_qos_rules, &item, "QoS rule %u", i); - /* QoS rule identifier */ - proto_tree_add_item(sub_tree, hf_nas_5gs_sm_qos_rule_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + /* QoS rule identifier Octet 4*/ + proto_tree_add_item_ret_uint(sub_tree, hf_nas_5gs_sm_qos_rule_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &qos_rule_id); curr_offset += 1; - /* Length of QoS rule */ + /* Length of QoS rule Octet 5 - 6*/ proto_tree_add_item_ret_uint(sub_tree, hf_nas_5gs_sm_length, tvb, curr_offset, 2, ENC_BIG_ENDIAN, &length); curr_offset += 2; @@ -2314,8 +2382,8 @@ de_nas_5gs_sm_qos_rules(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, } } + /* Packet filter list */ while (num_pkt_flt > 0) { - /* Packet filter list */ sub_tree2 = proto_tree_add_subtree_format(sub_tree, tvb, curr_offset, -1, ett_nas_5gs_sm_qos_rules, &item, "Packet filter %u", j); start_offset = curr_offset; if (rop == 5) { @@ -2327,7 +2395,7 @@ de_nas_5gs_sm_qos_rules(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, /* "create new QoS rule", or "modify existing QoS rule and add packet filters" * or "modify existing QoS rule and replace packet filters" */ - /* 0 0 Packet filter direction 1 Packet filter identifier 1*/ + /* 0 0 Packet filter direction 1 Packet filter identifier 1*/ proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pkt_flt_dir, tvb, curr_offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pkt_flt_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN); curr_offset++; @@ -2342,59 +2410,58 @@ de_nas_5gs_sm_qos_rules(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, proto_tree_add_item_ret_uint(sub_tree2, hf_nas_5gs_sm_pf_type, tvb, curr_offset, 1, ENC_BIG_ENDIAN, &pf_type); curr_offset++; switch (pf_type) { + case 1: + /* Match-all type + * . If the "match-all type" packet filter component is present in the packet filter, no other packet filter + * component shall be present in the packet filter and the length of the packet filter contents field shall + * be set to one. + */ + curr_offset += pf_len; + break; + case 16: + /* For "IPv4 remote address type", the packet filter component value field shall be encoded as a sequence + * of a four octet IPv4 address field and a four octet IPv4 address mask field. + * The IPv4 address field shall be transmitted first. + */ + proto_tree_add_item(sub_tree2, hf_nas_5gs_sm_pdu_addr_inf_ipv4, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + curr_offset += 4; + proto_tree_add_item(sub_tree2, hf_nas_5gs_addr_mask_ipv4, tvb, curr_offset, 4, ENC_BIG_ENDIAN); + curr_offset += 4; + proto_tree_add_item(sub_tree2, hf_nas_5gs_protocol_identifier_or_next_hd, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset += 1; + proto_tree_add_item(sub_tree2, hf_nas_5gs_protocol_identifier_or_next_hd_val, tvb, curr_offset, 1, ENC_BIG_ENDIAN); + curr_offset++; + break; default: - proto_tree_add_expert(sub_tree2, pinfo, &ei_nas_5gs_not_diss, tvb, curr_offset, pf_len - 1); + proto_tree_add_expert(sub_tree2, pinfo, &ei_nas_5gs_not_diss, tvb, curr_offset, pf_len); + curr_offset += pf_len; break; } - curr_offset += (pf_len - 1); } num_pkt_flt--; j++; proto_item_set_len(item, curr_offset - start_offset); } - - /* 0 Spare E Number of parameters */ - j = 1; - num_param = tvb_get_guint8(tvb, curr_offset); - num_param = num_param & 0x3f; - proto_tree_add_bitmask_list(sub_tree, tvb, curr_offset, 1, param_flags, ENC_BIG_ENDIAN); - curr_offset++; - - while (num_param > 0) { - /* Parameter list */ - sub_tree3 = proto_tree_add_subtree_format(sub_tree, tvb, curr_offset, -1, ett_nas_5gs_sm_qos_rules, &item, "Parameter %u", j); - - start_offset = curr_offset; - - /* Parameter identifier */ - proto_tree_add_item(sub_tree3, hf_nas_5gs_sm_param_id, tvb, curr_offset, 1, ENC_BIG_ENDIAN); - curr_offset++; - /* Length of parameter contents */ - proto_tree_add_item_ret_uint(sub_tree3, hf_nas_5gs_sm_param_len, tvb, curr_offset, 1, ENC_BIG_ENDIAN, ¶m_len); + /* QoS rule precedence (octet z+1) + * For the "delete existing QoS rule" operation, the QoS rule precedence value field shall not be included. + * For the "create new QoS rule" operation, the QoS rule precedence value field shall be included. + */ + if (qos_rule_id != 2) { /* Delete existing QoS rule */ + proto_tree_add_item(sub_tree, hf_nas_5gs_sm_qos_rule_precedence, tvb, curr_offset, 1, ENC_BIG_ENDIAN); curr_offset++; - - proto_tree_add_item(sub_tree3, hf_nas_5gs_sm_pal_cont, tvb, curr_offset, param_len, ENC_BIG_ENDIAN); - curr_offset += param_len; - - num_param--; - j++; - proto_item_set_len(item, curr_offset - start_offset); } - - /* Qos rule precedence */ - proto_tree_add_item(sub_tree, hf_nas_5gs_sm_qos_rule_precedence, tvb, curr_offset, 1, ENC_BIG_ENDIAN); - curr_offset++; - - /* 0 spare 0 spare QFI */ + /* QoS flow identifier (QFI) (bits 6 to 1 of octet z+2) + * For the "delete existing QoS rule" operation, the QoS flow identifier value field shall not be included. + * For the "create new QoS rule" operation, the QoS flow identifier value field shall be included. + */ + /* Segregation bit (bit 7 of octet z+2) */ proto_tree_add_item(sub_tree, hf_nas_5gs_sm_qfi, tvb, curr_offset, 1, ENC_BIG_ENDIAN); - curr_offset++; + curr_offset += 1; i++; - curr_offset = rule_start_offset + length + 3; } - return len; } @@ -2432,44 +2499,6 @@ static const value_string nas_5gs_sm_unit_for_session_ambr_values[] = { { 0, NULL } }; -static guint32 -get_ext_ambr_unit(guint32 unit, const char **unit_str) -{ - guint32 mult; - - if (unit == 0) { - mult = 1; - *unit_str = "Unit value 0, Illegal"; - return mult; - } - unit = unit - 1; - - if (unit <= 0x05) { - mult = pow4(guint32, unit); - *unit_str = "Kbps"; - } - else if (unit <= 0x0a) { - mult = pow4(guint32, unit - 0x05); - *unit_str = "Mbps"; - } - else if (unit <= 0x0e) { - mult = pow4(guint32, unit - 0x07); - *unit_str = "Gbps"; - } - else if (unit <= 0x14) { - mult = pow4(guint32, unit - 0x0c); - *unit_str = "Tbps"; - } - else if (unit <= 0x19) { - mult = pow4(guint32, unit - 0x11); - *unit_str = "Pbps"; - } - else { - mult = 256; - *unit_str = "Pbps"; - } - return mult; -} guint16 de_nas_5gs_sm_session_ambr(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, @@ -5377,6 +5406,21 @@ proto_register_nas_5gs(void) FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_nas_5gs_addr_mask_ipv4, + { "IPv4 address mask", "nas_5gs.ipv4_address_mask", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nas_5gs_protocol_identifier_or_next_hd, + { "packet filter component type", "nas_5gs.protocol_identifier_or_next_hd", + FT_UINT8, BASE_DEC, VALS(nas_5gs_sm_pf_type_values), 0x0, + NULL, HFILL } + }, + { &hf_nas_5gs_protocol_identifier_or_next_hd_val, + { "packet filter component value", "nas_5gs.protocol_identifier_or_next_hd_val", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, { &hf_nas_5gs_sm_qos_rule_precedence, { "QoS rule precedence", "nas_5gs.sm.qos_rule_precedence", FT_UINT8, BASE_DEC, NULL, 0x0, |