summaryrefslogtreecommitdiffstats
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-11-26 20:47:59 +0100
commitbf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5 (patch)
tree59108f1bdc8f5192a27e9a40d72a7e950686dd8c /proto/bgp/packets.c
parent5e6f568115511e2bcf43c60dfdcbd7a35cb04b93 (diff)
downloadbird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.tar
bird-bf47fe4b2e40ccfcfe6af2d86548d06cdf9739c5.zip
Implements BGP route refresh.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 4176c9f..91b4792 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -64,6 +64,14 @@ bgp_put_cap_ipv4(struct bgp_conn *conn UNUSED, byte *buf)
#endif
static byte *
+bgp_put_cap_rr(struct bgp_conn *conn UNUSED, byte *buf)
+{
+ *buf++ = 2; /* Capability 2: Support for route refresh */
+ *buf++ = 0; /* Capability data length */
+ return buf;
+}
+
+static byte *
bgp_put_cap_as4(struct bgp_conn *conn, byte *buf)
{
*buf++ = 65; /* Capability 65: Support for 4-octet AS number */
@@ -105,6 +113,9 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
cap = bgp_put_cap_ipv6(conn, cap);
#endif
+ if (p->cf->enable_refresh)
+ cap = bgp_put_cap_rr(conn, cap);
+
if (conn->want_as4_support)
cap = bgp_put_cap_as4(conn, cap);
@@ -386,6 +397,24 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
#endif
+static byte *
+bgp_create_route_refresh(struct bgp_conn *conn, byte *buf)
+{
+ struct bgp_proto *p = conn->bgp;
+ BGP_TRACE(D_PACKETS, "Sending ROUTE-REFRESH");
+
+#ifdef IPV6
+ *buf++ = 0; /* AFI IPv6 */
+ *buf++ = BGP_AF_IPV6;
+#else
+ *buf++ = 0; /* AFI IPv4 */
+ *buf++ = BGP_AF_IPV4;
+#endif
+ *buf++ = 0; /* RFU */
+ *buf++ = 1; /* and SAFI 1 */
+ return buf;
+}
+
static void
bgp_create_header(byte *buf, unsigned int len, unsigned int type)
{
@@ -447,6 +476,12 @@ bgp_fire_tx(struct bgp_conn *conn)
type = PKT_OPEN;
end = bgp_create_open(conn, pkt);
}
+ else if (s & (1 << PKT_ROUTE_REFRESH))
+ {
+ s &= ~(1 << PKT_ROUTE_REFRESH);
+ type = PKT_ROUTE_REFRESH;
+ end = bgp_create_route_refresh(conn, pkt);
+ }
else if (s & (1 << PKT_UPDATE))
{
end = bgp_create_update(conn, pkt);
@@ -517,6 +552,11 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
switch (opt[0])
{
+ case 2:
+ if (cl != 0)
+ goto err;
+ conn->peer_refresh_support = 1;
+ break;
case 65:
if (cl != 4)
goto err;
@@ -1084,6 +1124,30 @@ bgp_rx_keepalive(struct bgp_conn *conn)
}
}
+static void
+bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
+{
+ struct bgp_proto *p = conn->bgp;
+
+ BGP_TRACE(D_PACKETS, "Got ROUTE-REFRESH");
+
+ if (conn->state != BS_ESTABLISHED)
+ { bgp_error(conn, 5, 0, NULL, 0); return; }
+
+ if (!p->cf->enable_refresh)
+ { bgp_error(conn, 1, 3, pkt+18, 1); return; }
+
+ if (len != (BGP_HEADER_LENGTH + 4))
+ { bgp_error(conn, 1, 2, pkt+16, 2); return; }
+
+ /* FIXME - we ignore AFI/SAFI values, as we support
+ just one value and even an error code for an invalid
+ request is not defined */
+
+ proto_request_feeding(&p->p);
+}
+
+
/**
* bgp_rx_packet - handle a received packet
* @conn: BGP connection
@@ -1103,6 +1167,7 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);
case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
+ case PKT_ROUTE_REFRESH: return bgp_rx_route_refresh(conn, pkt, len);
default: bgp_error(conn, 1, 3, pkt+18, 1);
}
}