diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-03-19 17:44:50 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-03-19 17:44:50 +0100 |
commit | 3c3605818fb304f8de6975c56096bfafa43a8b6b (patch) | |
tree | c14d8690e1e722f07987e11a80f8416f61a375b5 /proto/bgp/packets.c | |
parent | 7e5f769d91319b4130f7d611dd14252806892ace (diff) |
BGP: Mandatory option for channels
Allow to mark channel to be mandatory, and do not allow BGP sessions if
no common AFI/SAFI is established.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r-- | proto/bgp/packets.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 4ae6c5cf..c09e9859 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -574,6 +574,42 @@ err: } static int +bgp_check_capabilities(struct bgp_conn *conn) +{ + struct bgp_proto *p = conn->bgp; + struct bgp_caps *local = conn->local_caps; + struct bgp_caps *remote = conn->remote_caps; + struct bgp_channel *c; + int count = 0; + + /* This is partially overlapping with bgp_conn_enter_established_state(), + but we need to run this just after we receive OPEN message */ + + WALK_LIST(c, p->p.channels) + { + const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi); + const struct bgp_af_caps *rem = bgp_find_af_caps(remote, c->afi); + + /* Find out whether this channel will be active */ + int active = loc && loc->ready && + ((rem && rem->ready) || (!remote->length && (c->afi == BGP_AF_IPV4))); + + /* Mandatory must be active */ + if (c->cf->mandatory && !active) + return 0; + + if (active) + count++; + } + + /* We need at least one channel active */ + if (!count) + return 0; + + return 1; +} + +static int bgp_read_options(struct bgp_conn *conn, byte *pos, int len) { struct bgp_proto *p = conn->bgp; @@ -683,6 +719,10 @@ 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 */ + if (p->cf->capabilities && !bgp_check_capabilities(conn)) + { bgp_error(conn, 2, 7, NULL, 0); return; } + struct bgp_caps *caps = conn->remote_caps; if (caps->as4_support) |