aboutsummaryrefslogtreecommitdiffstats
path: root/packet-bgp.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@itojun.org>2000-03-29 06:27:54 +0000
committerJun-ichiro itojun Hagino <itojun@itojun.org>2000-03-29 06:27:54 +0000
commit01d2363d0e2825576836b66db1237d0e186faaf3 (patch)
tree3d2ae04377154182d9213784fec225d41b856cd2 /packet-bgp.c
parentc317b042a8e3ecb1fc973ed1ea50793dda057bde (diff)
update RFC1966 (BGP route reflection) support.
From: Greg Hankins <gregh@twoguys.org> svn path=/trunk/; revision=1759
Diffstat (limited to 'packet-bgp.c')
-rw-r--r--packet-bgp.c292
1 files changed, 178 insertions, 114 deletions
diff --git a/packet-bgp.c b/packet-bgp.c
index 3d9344add6..f394ca81ec 100644
--- a/packet-bgp.c
+++ b/packet-bgp.c
@@ -6,11 +6,11 @@
*
* Supports:
* RFC1771 A Border Gateway Protocol 4 (BGP-4)
+ * RFC1966 BGP Route Reflection An alternative to full mesh IBGP
* RFC1997 BGP Communities Attribute
* RFC2283 Multiprotocol Extensions for BGP-4
*
* TODO:
- * RFC1966 BGP Route Reflection An alternative to full mesh IBGP
* RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
* RFC1965 Autonomous System Confederations for BGP
* Destination Preference Attribute for BGP (work in progress)
@@ -198,6 +198,7 @@ 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;
+static gint ett_bgp_cluster_list = -1;
/*
* Decode an IPv4 prefix.
@@ -298,28 +299,30 @@ dissect_bgp_open(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
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 */
- 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 */
+ {
+ 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 */
+ proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
+ 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 *cluster_list_str = NULL; /* CLUSTER_LIST string */
+ char junk_buf[256]; /* tmp */
/* snarf UPDATE message */
@@ -459,7 +462,7 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
"%s: %u (%u %s)",
val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
- pntohl(&p[i + aoff]), alen + aoff,
+ pntohl(&p[i + aoff]), alen + aoff,
(alen + aoff == 1) ? "byte" : "bytes");
break;
case BGPTYPE_LOCAL_PREF:
@@ -493,45 +496,45 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
if (alen % 4 != 0)
goto default_attribute_top;
- /* (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 */
+ /* (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);
+ strncpy(junk_buf, "NO_EXPORT ", 10);
else if (pntohl(q) == BGP_COMM_NO_ADVERTISE)
- strncpy(junk_buf, "NO_ADVERTISE ", 13);
+ 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';
+ 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"),
- communities_str, alen + aoff,
- (alen + aoff == 1) ? "byte" : "bytes");
+ communities_str, alen + aoff,
+ (alen + aoff == 1) ? "byte" : "bytes");
break;
case BGPTYPE_ORIGINATOR_ID:
if (alen != 4)
@@ -540,16 +543,47 @@ 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:
+ if (alen % 4 != 0)
+ goto default_attribute_top;
+
+ /* (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 * 16" (12 digits, 3 dots + space ) should be
+ a good estimate of how long the cluster_list string could
+ be */
+ cluster_list_str = malloc((alen + 1) * 16);
+ if (cluster_list_str == NULL) break;
+ cluster_list_str[0] = '\0';
+ memset(junk_buf, 0, sizeof(junk_buf));
+
+ /* snarf each cluster list */
+ while (q < end) {
+ snprintf(junk_buf, sizeof(junk_buf), "%s ", ip_to_str(q));
+ strncat(cluster_list_str, junk_buf, sizeof(junk_buf));
+ q += 4;
+ }
+ /* cleanup end of string */
+ cluster_list_str[strlen(cluster_list_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"),
+ cluster_list_str, alen + aoff,
+ (alen + aoff == 1) ? "byte" : "bytes");
+ break;
default:
default_attribute_top:
ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
"%s (%u %s)",
val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
alen + aoff, (alen + aoff == 1) ? "byte" : "bytes");
- }
+ } /* end of first switch */
subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
/* figure out flags */
@@ -705,11 +739,11 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
case BGPTYPE_MULTI_EXIT_DISC:
if (alen != 4) {
proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
- "Multi exit discriminator (invalid): %u %s",
+ "Multiple exit discriminator (invalid): %u %s",
alen, (alen == 1) ? "byte" : "bytes");
} else {
proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
- "Multi exit discriminator: %u",
+ "Multiple exit discriminator: %u",
pntohl(&p[i + aoff]));
}
break;
@@ -720,8 +754,7 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
(alen == 1) ? "byte" : "bytes");
} else {
proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
- "Local preference: %u",
- pntohl(&p[i + aoff]));
+ "Local preference: %u", pntohl(&p[i + aoff]));
}
break;
case BGPTYPE_ATOMIC_AGGREGATE:
@@ -738,8 +771,7 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
(alen == 1) ? "byte" : "bytes");
} else {
proto_tree_add_text(subtree2, p - pd + i + aoff, 2,
- "Aggregator AS: %u",
- pntohs(&p[i + aoff]));
+ "Aggregator AS: %u", pntohs(&p[i + aoff]));
proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 4,
"Aggregator origin: %s",
ip_to_str(&p[i + aoff + 2]));
@@ -750,58 +782,60 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
"Communities (invalid): %u %s", alen,
(alen == 1) ? "byte" : "bytes");
+ free(communities_str);
+ break;
}
- 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 */
+ 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));
- }
+ /* 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 {
- q += 4;
- }
+ 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);
+ free(communities_str);
break;
case BGPTYPE_ORIGINATOR_ID:
if (alen != 4) {
@@ -910,7 +944,7 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
break;
case BGPTYPE_MP_UNREACH_NLRI:
- af = pntohs(&p[i + aoff]);
+ af = pntohs(&p[i + aoff]);
proto_tree_add_text(subtree2, p - pd + i + aoff, 2,
"Address family: %s (%u)",
val_to_str(af, afnumber, "Unknown"), af);
@@ -952,12 +986,41 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
break;
case BGPTYPE_CLUSTER_LIST:
+ if (alen % 4 != 0) {
+ proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
+ "Cluster list (invalid): %u %s", alen,
+ (alen == 1) ? "byte" : "bytes");
+ free(cluster_list_str);
+ break;
+ }
+
+ ti = proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
+ "Cluster list: %s", cluster_list_str);
+ cluster_list_tree = proto_item_add_subtree(ti,
+ ett_bgp_cluster_list);
+
+ /* (p + i + 3) =
+ (p + current attribute + 3 bytes to first tuple) */
+ end = p + alen + i + 3;
+ q = p + i + 3;
+
+ /* snarf each cluster identifier */
+ while (q < end) {
+ ti = proto_tree_add_text(cluster_list_tree,
+ q - pd - 3 + aoff, 4, "Cluster identifier: %s",
+ ip_to_str(q));
+
+ q += 4;
+ }
+
+ free(cluster_list_str);
+ break;
default:
proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
"Unknown (%d %s)", alen, (alen == 1) ? "byte" :
"bytes");
break;
- }
+ } /* end of second switch */
i += alen + aoff;
}
@@ -1134,7 +1197,7 @@ dissect_bgp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
}
proto_tree_add_text(bgp1_tree, offset + i, BGP_MARKER_SIZE,
- "Marker");
+ "Marker: 16 bytes");
if (hlen < BGP_HEADER_SIZE || hlen > BGP_MAX_PACKET_SIZE) {
proto_tree_add_text(bgp1_tree,
@@ -1197,6 +1260,7 @@ proto_register_bgp(void)
&ett_bgp_notification,
&ett_bgp_as_paths,
&ett_bgp_communities,
+ &ett_bgp_cluster_list,
};
proto_bgp = proto_register_protocol("Border Gateway Protocol", "bgp");