diff options
author | Jun-ichiro itojun Hagino <itojun@itojun.org> | 2000-01-25 09:24:42 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@itojun.org> | 2000-01-25 09:24:42 +0000 |
commit | f95500d6230b849050cbbd3786e31d30eb74d9b7 (patch) | |
tree | 36c8fbcd7eaeec16e5d3a7741fa14649b0ce3530 /packet-bgp.c | |
parent | d1aac3e35f7e2d1430a198f8c41a5bed7ac3b3a7 (diff) | |
download | wireshark-f95500d6230b849050cbbd3786e31d30eb74d9b7.tar.gz wireshark-f95500d6230b849050cbbd3786e31d30eb74d9b7.tar.bz2 wireshark-f95500d6230b849050cbbd3786e31d30eb74d9b7.zip |
parse multiple COMMUNITIES value.
svn path=/trunk/; revision=1556
Diffstat (limited to 'packet-bgp.c')
-rw-r--r-- | packet-bgp.c | 183 |
1 files changed, 113 insertions, 70 deletions
diff --git a/packet-bgp.c b/packet-bgp.c index aafe62bfb3..205bd84485 100644 --- a/packet-bgp.c +++ b/packet-bgp.c @@ -197,6 +197,7 @@ static gint ett_bgp_open = -1; static gint ett_bgp_update = -1; static gint ett_bgp_notification = -1; static gint ett_bgp_as_paths = -1; +static gint ett_bgp_communities = -1; /* * Decode an IPv4 prefix. @@ -298,24 +299,27 @@ static void dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - struct bgp bgp; /* BGP header */ - struct bgp_attr bgpa; /* path attributes */ - int hlen; /* message length */ - const u_char *p; /* packet offset pointer */ - const u_char *q; /* tmp */ - const u_char *end; /* message end */ - int len; /* tmp */ - proto_item *ti; /* tree item */ - proto_tree *subtree; /* subtree for attibutes */ - proto_tree *subtree2; /* subtree for attibutes */ - proto_tree *subtree3; /* subtree for attibutes */ - proto_tree *as_paths_tree; /* subtree for AS_PATHs */ - proto_tree *as_path_tree; /* subtree for AS_PATH */ - int i, j; /* tmp */ - guint8 length; /* AS_PATH length */ - guint8 type; /* AS_PATH type */ - char *as_path_str = NULL; /* AS_PATH string */ - char junk_buf[256]; /* tmp */ + struct bgp bgp; /* BGP header */ + struct bgp_attr bgpa; /* path attributes */ + int hlen; /* message length */ + const u_char *p; /* packet offset pointer */ + const u_char *q; /* tmp */ + const u_char *end; /* message end */ + int len; /* tmp */ + proto_item *ti; /* tree item */ + proto_tree *subtree; /* subtree for attibutes */ + proto_tree *subtree2; /* subtree for attibutes */ + proto_tree *subtree3; /* subtree for attibutes */ + proto_tree *as_paths_tree; /* subtree for AS_PATHs */ + proto_tree *as_path_tree; /* subtree for AS_PATH */ + proto_tree *communities_tree; /* subtree for COMMUNITIES */ + proto_tree *community_tree; /* subtree for a community */ + int i, j; /* tmp */ + guint8 length; /* AS_PATH length */ + guint8 type; /* AS_PATH type */ + char *as_path_str = NULL; /* AS_PATH string */ + char *communities_str = NULL; /* COMMUNITIES string */ + char junk_buf[256]; /* tmp */ /* snarf UPDATE message */ @@ -486,29 +490,48 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, (alen + aoff == 1) ? "byte" : "bytes"); break; case BGPTYPE_COMMUNITIES: - if (alen != 4) + if (alen % 4 != 0) goto default_attribute_top; - /* check for well-known communities */ - if (pntohl(&p[i + aoff]) == BGP_COMM_NO_EXPORT) - strncpy(junk_buf, "NO_EXPORT", 10); - else if (pntohl(&p[i + aoff]) == - BGP_COMM_NO_ADVERTISE) - strncpy(junk_buf, "NO_ADVERTISE", 13); - else if (pntohl(&p[i + aoff]) == - BGP_COMM_NO_EXPORT_SUBCONFED) - strncpy(junk_buf, "NO_EXPORT_SUBCONFED", 20); - else { - snprintf(junk_buf, sizeof(junk_buf), "%u:%u", - pntohs(&p[i + aoff]), - pntohs(&p[i + aoff + 2])); - } + /* (p + i + 3) = + (p + current attribute + 3 bytes to first tuple) */ + end = p + alen + i + 3; + q = p + i + 3; + /* must be freed by second switch! */ + /* "alen * 12" (5 digits, a :, 5 digits + space ) should be + a good estimate of how long the communities string could + be */ + communities_str = malloc((alen + 1) * 12); + if (communities_str == NULL) break; + communities_str[0] = '\0'; + memset(junk_buf, 0, sizeof(junk_buf)); + + /* snarf each community */ + while (q < end) { + /* check for well-known communities */ + if (pntohl(q) == BGP_COMM_NO_EXPORT) + strncpy(junk_buf, "NO_EXPORT ", 10); + else if (pntohl(q) == BGP_COMM_NO_ADVERTISE) + strncpy(junk_buf, "NO_ADVERTISE ", 13); + else if (pntohl(q) == BGP_COMM_NO_EXPORT_SUBCONFED) + strncpy(junk_buf, "NO_EXPORT_SUBCONFED ", 20); + else { + snprintf(junk_buf, sizeof(junk_buf), "%u:%u ", + pntohs(q), + pntohs(q + 2)); + } + q += 4; + + strncat(communities_str, junk_buf, sizeof(junk_buf)); + } + /* cleanup end of string */ + communities_str[strlen(communities_str) - 1] = '\0'; ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff, "%s: %s (%u %s)", val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"), - junk_buf, alen + aoff, - (alen + aoff == 1) ? "byte" : "bytes"); + communities_str, alen + aoff, + (alen + aoff == 1) ? "byte" : "bytes"); break; case BGPTYPE_ORIGINATOR_ID: if (alen != 4) @@ -517,7 +540,7 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, "%s: %s (%u %s)", val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"), ip_to_str(&p[i + aoff]), alen + aoff, (alen + aoff == 1) - ? "byte" : "bytes"); + ? "byte" : "bytes"); break; case BGPTYPE_CLUSTER_LIST: default: @@ -723,43 +746,62 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, } break; case BGPTYPE_COMMUNITIES: - if (alen != 4) { - proto_tree_add_text(subtree2, p - pd + i + aoff, 4, + if (alen % 4 != 0) { + proto_tree_add_text(subtree2, p - pd + i + aoff, alen, "Communities (invalid): %u %s", alen, (alen == 1) ? "byte" : "bytes"); } - /* check for reserved values */ - else if (pntohs(&p[i + aoff]) == FOURHEX0 || - pntohs(&p[i + aoff]) == FOURHEXF) { - /* check for well-known communities */ - if (pntohl(&p[i + aoff]) == BGP_COMM_NO_EXPORT) - proto_tree_add_text(subtree2, p - pd + i + aoff, 4, - "Communities: NO_EXPORT (0x%x)", - pntohl(&p[i + aoff])); - else if (pntohl(&p[i + aoff]) == - BGP_COMM_NO_ADVERTISE) - proto_tree_add_text(subtree2, p - pd + i + aoff, 4, - "Communities: NO_ADVERTISE (0x%x)", - pntohl(&p[i + aoff])); - else if (pntohl(&p[i + aoff]) == - BGP_COMM_NO_EXPORT_SUBCONFED) - proto_tree_add_text(subtree2, p - pd + i + aoff, 4, - "Communities: NO_EXPORT_SUBCONFED (0x%x)", - pntohl(&p[i + aoff])); - else { - proto_tree_add_text(subtree2, p - pd + i + aoff, 4, - "Communities (reserved): 0x%x", - pntohl(&p[i + aoff])); - } - } - else { - proto_tree_add_text(subtree2, p - pd + i + aoff, 2, - "Communities AS: %u", - pntohs(&p[i + aoff])); - proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 2, - "Communities value: %u", - pntohs(&p[i + aoff + 2])); - } + + ti = proto_tree_add_text(subtree2, p - pd + i + aoff, alen, + "Communities: %s", communities_str); + communities_tree = proto_item_add_subtree(ti, + ett_bgp_communities); + + /* (p + i + 3) = + (p + current attribute + 3 bytes to first tuple) */ + end = p + alen + i + 3; + q = p + i + 3; + + /* snarf each community */ + while (q < end) { + /* check for reserved values */ + if (pntohs(q) == FOURHEX0 || pntohs(q) == FOURHEXF) { + /* check for well-known communities */ + if (pntohl(q) == BGP_COMM_NO_EXPORT) + proto_tree_add_text(communities_tree, + q - pd - 3 + aoff, 4, + "Community: NO_EXPORT (0x%x)", pntohl(q)); + else if (pntohl(q) == BGP_COMM_NO_ADVERTISE) + proto_tree_add_text(communities_tree, + q - pd - 3 + aoff, 4, + "Community: NO_ADVERTISE (0x%x)", pntohl(q)); + else if (pntohl(q) == BGP_COMM_NO_EXPORT_SUBCONFED) + proto_tree_add_text(communities_tree, + q - pd - 3 + aoff, 4, + "Community: NO_EXPORT_SUBCONFED (0x%x)", + pntohl(q)); + else + proto_tree_add_text(communities_tree, + q - pd - 3 + aoff, 4, + "Community (reserved): 0x%x", pntohl(q)); + } + else { + + ti = proto_tree_add_text(communities_tree, + q - pd - 3 + aoff, 4, "Community: %u:%u", + pntohs(q), pntohs(q + 2)); + community_tree = proto_item_add_subtree(ti, + ett_bgp_communities); + proto_tree_add_text(community_tree, q - pd - 3 + aoff, + 2, "Community AS: %u", pntohs(q)); + proto_tree_add_text(community_tree, q - pd - 1 + aoff, + 2, "Community value: %u", pntohs(q + 2)); + } + + q += 4; + } + + free(communities_str); break; case BGPTYPE_ORIGINATOR_ID: if (alen != 4) { @@ -1154,6 +1196,7 @@ proto_register_bgp(void) &ett_bgp_update, &ett_bgp_notification, &ett_bgp_as_paths, + &ett_bgp_communities, }; proto_bgp = proto_register_protocol("Border Gateway Protocol", "bgp"); |