aboutsummaryrefslogtreecommitdiffstats
path: root/packet-bgp.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@itojun.org>2000-01-25 09:24:42 +0000
committerJun-ichiro itojun Hagino <itojun@itojun.org>2000-01-25 09:24:42 +0000
commitf95500d6230b849050cbbd3786e31d30eb74d9b7 (patch)
tree36c8fbcd7eaeec16e5d3a7741fa14649b0ce3530 /packet-bgp.c
parentd1aac3e35f7e2d1430a198f8c41a5bed7ac3b3a7 (diff)
parse multiple COMMUNITIES value.
svn path=/trunk/; revision=1556
Diffstat (limited to 'packet-bgp.c')
-rw-r--r--packet-bgp.c183
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");