diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c index ff30f5efd7..aba487d9ff 100644 --- a/epan/dissectors/packet-sip.c +++ b/epan/dissectors/packet-sip.c @@ -219,6 +219,7 @@ static gint hf_sip_session_id_param = -1; static gint hf_sip_session_id_local_uuid = -1; static gint hf_sip_session_id_remote_uuid = -1; static gint hf_sip_continuation = -1; +static gint hf_sip_feature_cap = -1; static gint hf_sip_p_acc_net_i_acc_type = -1; static gint hf_sip_p_acc_net_i_ucid_3gpp = -1; @@ -255,6 +256,7 @@ static gint ett_sip_ppi_uri = -1; static gint ett_sip_tc_uri = -1; static gint ett_sip_session_id = -1; static gint ett_sip_p_access_net_info = -1; +static gint ett_sip_feature_caps = -1; static expert_field ei_sip_unrecognized_header = EI_INIT; static expert_field ei_sip_header_no_colon = EI_INIT; @@ -2801,6 +2803,56 @@ static void dissect_sip_p_access_network_info_header(tvbuff_t *tvb, proto_tree * } } +/* +https://tools.ietf.org/html/rfc6809 +The ABNF for the Feature-Caps header fields is: + +Feature-Caps = "Feature-Caps" HCOLON fc-value +*(COMMA fc-value) +fc-value = "*" *(SEMI feature-cap) + +The ABNF for the feature-capability indicator is: + +feature-cap = "+" fcap-name [EQUAL LDQUOT (fcap-value-list +/ fcap-string-value ) RDQUOT] +fcap-name = ftag-name +fcap-value-list = tag-value-list +fcap-string-value = string-value +;; ftag-name, tag-value-list, string-value defined in RFC 3840 + +NOTE: In comparison with media feature tags, the "+" sign in front of +the feature-capability indicator name is mandatory. + +*/ +static void +dissect_sip_p_feature_caps(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset) +{ + gint current_offset, next_offset, length; + guint16 semi_plus = 0x3b2b; + + /* skip Spaces and Tabs */ + next_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset); + + if (next_offset >= line_end_offset) { + /* Nothing to parse */ + return; + } + + while (next_offset < line_end_offset) { + /* Find the end of feature cap or start of feature cap parameter, ";+" should indicate the start of a new feature-cap */ + current_offset = next_offset; + next_offset = tvb_find_guint16(tvb, current_offset, line_end_offset - current_offset, semi_plus); + if (next_offset == -1) { + length = line_end_offset - current_offset; + next_offset = line_end_offset; + } + else { + length = next_offset - current_offset; + next_offset += 2; + } + proto_tree_add_item(tree, hf_sip_feature_cap, tvb, current_offset, length, ENC_UTF_8 | ENC_NA); + } +} /* Code to actually dissect the packets */ static int @@ -4035,6 +4087,19 @@ dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info dissect_sip_p_access_network_info_header(tvb, p_access_net_info_tree, value_offset, line_end_offset); } break; + case POS_FEATURE_CAPS: + if (hdr_tree) { + proto_tree *feature_caps_tree; + + sip_element_item = sip_proto_tree_add_string(hdr_tree, + hf_header_array[hf_index], tvb, + offset, next_offset - offset, + value_offset, value_len); + sip_proto_set_format_text(hdr_tree, sip_element_item, tvb, offset, linelen); + feature_caps_tree = proto_item_add_subtree(sip_element_item, ett_sip_feature_caps); + dissect_sip_p_feature_caps(tvb, feature_caps_tree, value_offset, line_end_offset); + } + break; default : /* Default case is to assume it's an FT_STRING field */ sip_element_item = sip_proto_tree_add_string(hdr_tree, @@ -6589,6 +6654,12 @@ void proto_register_sip(void) { "Continuation data", "sip.continuation", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_sip_feature_cap, + { "Feature Cap", "sip.feature_cap", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } } }; @@ -6632,7 +6703,8 @@ void proto_register_sip(void) &ett_sip_from_uri, &ett_sip_curi, &ett_sip_session_id, - &ett_sip_p_access_net_info + &ett_sip_p_access_net_info, + &ett_sip_feature_caps }; static gint *ett_raw[] = { &ett_raw_text,