diff options
author | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2013-07-26 16:26:21 +0000 |
---|---|---|
committer | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2013-07-26 16:26:21 +0000 |
commit | 54fc4025e6e3eeb22a14287b5cddda0eeba31f36 (patch) | |
tree | 07c0f30ca4f973c2f5737ab929ef90ad48cd5bba /epan/dissectors/packet-bgp.c | |
parent | aa27f065a1bd8ec46d2cbcc89f9eaf395e99be3e (diff) | |
download | wireshark-54fc4025e6e3eeb22a14287b5cddda0eeba31f36.tar.gz |
Enhance BGP Update
First step ! Remove ugly double switch(bgpa_type)... (use proto_item_append_text)
svn path=/trunk/; revision=50917
Diffstat (limited to 'epan/dissectors/packet-bgp.c')
-rw-r--r-- | epan/dissectors/packet-bgp.c | 364 |
1 files changed, 130 insertions, 234 deletions
diff --git a/epan/dissectors/packet-bgp.c b/epan/dissectors/packet-bgp.c index 077399069f..8c5d98f6ba 100644 --- a/epan/dissectors/packet-bgp.c +++ b/epan/dissectors/packet-bgp.c @@ -862,6 +862,8 @@ static int hf_bgp_encaps_tunnel_subtlv_type = -1; static int hf_bgp_mdt_safi_rd = -1; static int hf_bgp_mdt_safi_ipv4_addr = -1; static int hf_bgp_mdt_safi_group_addr = -1; + +static int hf_bgp_update_path_attribute = -1; static int hf_bgp_flags_optional = -1; static int hf_bgp_flags_transitive = -1; static int hf_bgp_flags_partial = -1; @@ -3077,7 +3079,7 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) i = 2; while (i < len) { proto_item *hidden_item; - const char *msg; + proto_item *ti_pa; int off; gint k; guint16 alen, tlen, aoff, aoff_save; @@ -3099,18 +3101,67 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) } tlen = alen; - /* This is kind of ugly - similar code appears twice, but it - helps browsing attrs. */ - /* the first switch prints things in the title of the subtree */ + + ti_pa = proto_tree_add_item(subtree, hf_bgp_update_path_attribute, tvb, o + i, tlen + aoff, ENC_NA); + proto_item_append_text(ti_pa, " - %s", val_to_str_const(bgpa_type, bgpattr_type, "Unknown %d")); + + subtree2 = proto_item_add_subtree(ti_pa, ett_bgp_attr); + + /* figure out flags */ + ep_strbuf_truncate(junk_emstr, 0); + if (bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) { + ep_strbuf_append(junk_emstr, "Optional, "); + } + else { + ep_strbuf_append(junk_emstr, "Well-known, "); + } + if (bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) { + ep_strbuf_append(junk_emstr, "Transitive, "); + } + else { + ep_strbuf_append(junk_emstr, "Non-transitive, "); + } + if (bgpa_flags & BGP_ATTR_FLAG_PARTIAL) { + ep_strbuf_append(junk_emstr, "Partial"); + } + else { + ep_strbuf_append(junk_emstr, "Complete"); + } + if (bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) { + ep_strbuf_append(junk_emstr, ", Extended Length"); + } + ti = proto_tree_add_text(subtree2, tvb, o + i, 1, + "Flags: 0x%02x (%s)", bgpa_flags, junk_emstr->str); + subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags); + + /* add flag bitfield subtrees */ + proto_tree_add_item(subtree3, hf_bgp_flags_optional, tvb, o + i, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree3, hf_bgp_flags_transitive, tvb, o + i, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree3, hf_bgp_flags_partial, tvb, o + i, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree3, hf_bgp_flags_extended_length, tvb, o + i, 1, ENC_BIG_ENDIAN); + + proto_tree_add_text(subtree2, tvb, + o + i + 1, 1, + "Type code: %s (%u)", + val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), + bgpa_type); + + proto_tree_add_text(subtree2, tvb, o + i + BGP_SIZE_OF_PATH_ATTRIBUTE, + aoff - BGP_SIZE_OF_PATH_ATTRIBUTE, "Length: %d byte%s", tlen, + plurality(tlen, "", "s")); + + /* Path Attribute Type */ switch (bgpa_type) { case BGPTYPE_ORIGIN: - if (tlen != 1) - goto default_attribute_top; - msg = val_to_str_const(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown"); - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - msg, tlen + aoff, plurality(tlen + aoff, "", "s")); + if (tlen != 1) { + proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, + "Origin (invalid): %u byte%s", tlen, + plurality(tlen, "", "s")); + } else { + proto_tree_add_item(subtree2, hf_bgp_origin, tvb, + o + i + aoff, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti_pa, ": %s", val_to_str_const(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown")); + } break; case BGPTYPE_AS_PATH: case BGPTYPE_NEW_AS_PATH: @@ -3213,229 +3264,8 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) if (tlen == 0) ep_strbuf_printf(as_path_emstr, "empty"); - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - as_path_emstr->str, tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_NEXT_HOP: - if (tlen != 4) - goto default_attribute_top; - ipaddr = tvb_get_ipv4(tvb, o + i + aoff); - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - ip_to_str((guint8 *)&ipaddr), tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_MULTI_EXIT_DISC: - if (tlen != 4) - goto default_attribute_top; - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %u (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_LOCAL_PREF: - if (tlen != 4) - goto default_attribute_top; - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %u (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_ATOMIC_AGGREGATE: - if (tlen != 0) - goto default_attribute_top; - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - tlen + aoff, plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_AGGREGATOR: - if (tlen != 6 && tlen != 8) - goto default_attribute_top; - case BGPTYPE_NEW_AGGREGATOR: - if (bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8) - goto default_attribute_top; - asn_len = tlen - 4; - ipaddr = tvb_get_ipv4(tvb, o + i + aoff + asn_len); - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: AS: %u origin: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) : - tvb_get_ntohl(tvb, o + i + aoff), - ip_to_str((guint8 *)&ipaddr), - tlen + aoff, plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_COMMUNITIES: - if (tlen % 4 != 0) - goto default_attribute_top; - - /* (o + i + aoff) = - (o + current attribute + aoff bytes to first tuple) */ - q = o + i + aoff; - end = q + tlen; - /* must be freed by second switch! */ - /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be - a good estimate of how long the communities string could - be */ - if (communities_emstr == NULL) - communities_emstr = ep_strbuf_sized_new((tlen + 1) * 12, 0); - ep_strbuf_truncate(communities_emstr, 0); - - /* snarf each community */ - while (q < end) { - /* check for well-known communities */ - if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT) - ep_strbuf_append(communities_emstr, "NO_EXPORT "); - else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE) - ep_strbuf_append(communities_emstr, "NO_ADVERTISE "); - else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED) - ep_strbuf_append(communities_emstr, "NO_EXPORT_SUBCONFED "); - else { - ep_strbuf_append_printf(communities_emstr, "%u:%u ", - tvb_get_ntohs(tvb, q), - tvb_get_ntohs(tvb, q + 2)); - } - q += 4; - } - /* cleanup end of string */ - ep_strbuf_truncate(communities_emstr, communities_emstr->len - 1); - - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - communities_emstr->str, tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_ORIGINATOR_ID: - if (tlen != 4) - goto default_attribute_top; - ipaddr = tvb_get_ipv4(tvb, o + i + aoff); - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - ip_to_str((guint8 *)&ipaddr), - tlen + aoff, plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_CLUSTER_LIST: - if (tlen % 4 != 0) - goto default_attribute_top; - - /* (o + i + aoff) = - (o + current attribute + aoff bytes to first tuple) */ - q = o + i + aoff; - end = q + tlen; - /* must be freed by second switch! */ - /* "tlen * 16" (12 digits, 3 dots + space ) should be - a good estimate of how long the cluster_list string could - be */ - if (cluster_list_emstr == NULL) - cluster_list_emstr = ep_strbuf_sized_new((tlen + 1) * 16, 0); - ep_strbuf_truncate(cluster_list_emstr, 0); - - /* snarf each cluster list */ - while (q < end) { - ipaddr = tvb_get_ipv4(tvb, q); - ep_strbuf_append_printf(cluster_list_emstr, "%s ", ip_to_str((guint8 *)&ipaddr)); - q += 4; - } - /* cleanup end of string */ - ep_strbuf_truncate(cluster_list_emstr, cluster_list_emstr->len - 1); - - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s: %s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - cluster_list_emstr->str, tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_EXTENDED_COMMUNITY: - if (tlen %8 != 0) - break; - ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff, - "%s: (%u byte%s)", - val_to_str_const(bgpa_type,bgpattr_type,"Unknown"), - tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - case BGPTYPE_SAFI_SPECIFIC_ATTR: - ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff, - "%s: (%u byte%s)", - val_to_str_const(bgpa_type,bgpattr_type,"Unknown"), - tlen + aoff, - plurality(tlen + aoff, "", "s")); - break; - default: - default_attribute_top: - ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff, - "%s (%u byte%s)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - tlen + aoff, plurality(tlen + aoff, "", "s")); - } /* switch (bgpa.bgpa_type) */ /* end of first switch */ - subtree2 = proto_item_add_subtree(ti, ett_bgp_attr); + proto_item_append_text(ti_pa, ": %s", as_path_emstr->str); - /* figure out flags */ - ep_strbuf_truncate(junk_emstr, 0); - if (bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) { - ep_strbuf_append(junk_emstr, "Optional, "); - } - else { - ep_strbuf_append(junk_emstr, "Well-known, "); - } - if (bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) { - ep_strbuf_append(junk_emstr, "Transitive, "); - } - else { - ep_strbuf_append(junk_emstr, "Non-transitive, "); - } - if (bgpa_flags & BGP_ATTR_FLAG_PARTIAL) { - ep_strbuf_append(junk_emstr, "Partial"); - } - else { - ep_strbuf_append(junk_emstr, "Complete"); - } - if (bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) { - ep_strbuf_append(junk_emstr, ", Extended Length"); - } - ti = proto_tree_add_text(subtree2, tvb, o + i, 1, - "Flags: 0x%02x (%s)", bgpa_flags, junk_emstr->str); - subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags); - - /* add flag bitfield subtrees */ - proto_tree_add_item(subtree3, hf_bgp_flags_optional, tvb, o + i, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(subtree3, hf_bgp_flags_transitive, tvb, o + i, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(subtree3, hf_bgp_flags_partial, tvb, o + i, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(subtree3, hf_bgp_flags_extended_length, tvb, o + i, 1, ENC_BIG_ENDIAN); - - proto_tree_add_text(subtree2, tvb, - o + i + 1, 1, - "Type code: %s (%u)", - val_to_str_const(bgpa_type, bgpattr_type, "Unknown"), - bgpa_type); - - proto_tree_add_text(subtree2, tvb, o + i + BGP_SIZE_OF_PATH_ATTRIBUTE, - aoff - BGP_SIZE_OF_PATH_ATTRIBUTE, "Length: %d byte%s", tlen, - plurality(tlen, "", "s")); - - /* the second switch prints things in the actual subtree of each - attribute */ - switch (bgpa_type) { - case BGPTYPE_ORIGIN: - if (tlen != 1) { - proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, - "Origin (invalid): %u byte%s", tlen, - plurality(tlen, "", "s")); - } else { - proto_tree_add_item(subtree2, hf_bgp_origin, tvb, - o + i + aoff, 1, ENC_BIG_ENDIAN); - } - break; - case BGPTYPE_AS_PATH: - case BGPTYPE_NEW_AS_PATH: ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, "AS path: %s", as_path_emstr->str); as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths); @@ -3527,7 +3357,8 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) plurality(tlen, "", "s")); } else { proto_tree_add_item(subtree2, hf_bgp_next_hop, tvb, - o + i + aoff, tlen, ENC_BIG_ENDIAN); + o + i + aoff, 4, ENC_BIG_ENDIAN); + proto_item_append_text(ti_pa, ": %s ", tvb_ip_to_str(tvb, o + i + aoff)); } break; case BGPTYPE_MULTI_EXIT_DISC: @@ -3538,6 +3369,7 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) } else { proto_tree_add_item(subtree2, hf_bgp_multi_exit_disc, tvb, o + i + aoff, tlen, ENC_BIG_ENDIAN); + proto_item_append_text(ti_pa,": %u", tvb_get_ntohl(tvb, o + i + aoff)); } break; case BGPTYPE_LOCAL_PREF: @@ -3548,6 +3380,7 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) } else { proto_tree_add_item(subtree2, hf_bgp_local_pref, tvb, o + i + aoff, tlen, ENC_BIG_ENDIAN); + proto_item_append_text(ti_pa, ": %u", tvb_get_ntohl(tvb, o + i + aoff)); } break; case BGPTYPE_ATOMIC_AGGREGATE: @@ -3570,6 +3403,7 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) "Aggregator (invalid): %u byte%s", tlen, plurality(tlen, "", "s")); else { + asn_len = tlen - 4; aggregator_as = (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) : @@ -3578,6 +3412,9 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) o + i + aoff, asn_len, aggregator_as); proto_tree_add_item(subtree2, hf_bgp_aggregator_origin, tvb, o + i + aoff + asn_len, 4, ENC_BIG_ENDIAN); + + proto_item_append_text(ti_pa, ": AS: %u origin: %s", aggregator_as, + tvb_ip_to_str(tvb, o + i + aoff + asn_len)); } break; case BGPTYPE_COMMUNITIES: @@ -3588,6 +3425,39 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) break; } + /* (o + i + aoff) = + (o + current attribute + aoff bytes to first tuple) */ + q = o + i + aoff; + end = q + tlen; + /* must be freed by second switch! */ + /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be + a good estimate of how long the communities string could + be */ + if (communities_emstr == NULL) + communities_emstr = ep_strbuf_sized_new((tlen + 1) * 12, 0); + ep_strbuf_truncate(communities_emstr, 0); + + /* snarf each community */ + while (q < end) { + /* check for well-known communities */ + if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT) + ep_strbuf_append(communities_emstr, "NO_EXPORT "); + else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE) + ep_strbuf_append(communities_emstr, "NO_ADVERTISE "); + else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED) + ep_strbuf_append(communities_emstr, "NO_EXPORT_SUBCONFED "); + else { + ep_strbuf_append_printf(communities_emstr, "%u:%u ", + tvb_get_ntohs(tvb, q), + tvb_get_ntohs(tvb, q + 2)); + } + q += 4; + } + /* cleanup end of string */ + ep_strbuf_truncate(communities_emstr, communities_emstr->len - 1); + + proto_item_append_text(ti_pa,": %s", communities_emstr->str); + ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, "Communities: %s", communities_emstr ? communities_emstr->str : "<none>"); communities_tree = proto_item_add_subtree(ti, @@ -3634,6 +3504,7 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) } else { proto_tree_add_item(subtree2, hf_bgp_originator_id, tvb, o + i + aoff, tlen, ENC_BIG_ENDIAN); + proto_item_append_text(ti_pa, ": %s ", tvb_ip_to_str(tvb, o + i + aoff)); } break; case BGPTYPE_MP_REACH_NLRI: @@ -3788,6 +3659,28 @@ dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo) break; } + /* (o + i + aoff) = + (o + current attribute + aoff bytes to first tuple) */ + q = o + i + aoff; + end = q + tlen; + /* must be freed by second switch! */ + /* "tlen * 16" (12 digits, 3 dots + space ) should be + a good estimate of how long the cluster_list string could + be */ + if (cluster_list_emstr == NULL) + cluster_list_emstr = ep_strbuf_sized_new((tlen + 1) * 16, 0); + ep_strbuf_truncate(cluster_list_emstr, 0); + + /* snarf each cluster list */ + while (q < end) { + ep_strbuf_append_printf(cluster_list_emstr, "%s ", tvb_ip_to_str(tvb, q)); + q += 4; + } + /* cleanup end of string */ + ep_strbuf_truncate(cluster_list_emstr, cluster_list_emstr->len - 1); + + proto_item_append_text(ti_pa, ": %s", cluster_list_emstr->str); + ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen, "Cluster list: %s", cluster_list_emstr ? cluster_list_emstr->str : "<none>"); cluster_list_tree = proto_item_add_subtree(ti, @@ -5107,6 +5000,9 @@ proto_register_bgp(void) { &hf_bgp_mdt_safi_group_addr, { "Group Address", "bgp.mdt_safi_group_addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + { &hf_bgp_update_path_attribute, + { "Path Attribut", "bgp.update.path_attribute", FT_NONE, BASE_NONE, + NULL, 0x0, NULL, HFILL}}, { &hf_bgp_flags_optional, { "Optional", "bgp.flags.optional", FT_BOOLEAN, 8, TFS(&tfs_optional_wellknown), BGP_ATTR_FLAG_OPTIONAL, NULL, HFILL}}, |