parse multiple COMMUNITIES value.

svn path=/trunk/; revision=1556
This commit is contained in:
Jun-ichiro itojun Hagino 2000-01-25 09:24:42 +00:00
parent d1aac3e35f
commit f95500d623
1 changed files with 113 additions and 70 deletions

View File

@ -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");