summaryrefslogtreecommitdiff
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2023-11-23 20:54:22 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2023-11-23 20:54:22 +0100
commit3fb06fea1d14ef147a567052391a5b359704e971 (patch)
tree692750a6792e18fc1dcf50c277d0cde275577815 /proto/bgp/packets.c
parentb6923f6386b04340d6b2b6a75fbe83c392f207ca (diff)
BGP: Add options to require BGP capabilities
Some BGP capabilities change the BGP behavior in a significant way, so if the configuration depends on it, it is better to not establish BGP session when the capability is not available. Add several BGP option to require individual BGP capabilities during session negotiation.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 395169a4..1e5a226f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -694,7 +694,7 @@ err:
return -1;
}
-static int
+int
bgp_check_capabilities(struct bgp_conn *conn)
{
struct bgp_proto *p = conn->bgp;
@@ -706,6 +706,29 @@ bgp_check_capabilities(struct bgp_conn *conn)
/* This is partially overlapping with bgp_conn_enter_established_state(),
but we need to run this just after we receive OPEN message */
+ if (p->cf->require_refresh && !remote->route_refresh)
+ return 0;
+
+ if (p->cf->require_enhanced_refresh && !remote->enhanced_refresh)
+ return 0;
+
+ if (p->cf->require_as4 && !remote->as4_support)
+ return 0;
+
+ if (p->cf->require_extended_messages && !remote->ext_messages)
+ return 0;
+
+ if (p->cf->require_hostname && !remote->hostname)
+ return 0;
+
+ if (p->cf->require_gr && !remote->gr_aware)
+ return 0;
+
+ if (p->cf->require_llgr && !remote->llgr_aware)
+ return 0;
+
+ /* No check for require_roles, as it uses error code 2.11 instead of 2.7 */
+
BGP_WALK_CHANNELS(p, c)
{
const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi);
@@ -719,7 +742,18 @@ bgp_check_capabilities(struct bgp_conn *conn)
return 0;
if (active)
+ {
+ if (c->cf->require_ext_next_hop && !rem->ext_next_hop)
+ return 0;
+
+ if (c->cf->require_add_path && (loc->add_path & BGP_ADD_PATH_RX) && !(rem->add_path & BGP_ADD_PATH_TX))
+ return 0;
+
+ if (c->cf->require_add_path && (loc->add_path & BGP_ADD_PATH_TX) && !(rem->add_path & BGP_ADD_PATH_RX))
+ return 0;
+
count++;
+ }
}
/* We need at least one channel active */
@@ -905,7 +939,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
if (!id || (p->is_internal && id == p->local_id))
{ bgp_error(conn, 2, 3, pkt+24, -4); return; }
- /* RFC 5492 4 - check for required capabilities */
+ /* RFC 5492 5 - check for required capabilities */
if (p->cf->capabilities && !bgp_check_capabilities(conn))
{ bgp_error(conn, 2, 7, NULL, 0); return; }