diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2020-01-24 05:44:06 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2020-01-24 05:44:06 +0000 |
commit | 18714bc720466665754233878ce5dc928c5e264c (patch) | |
tree | 1748273ea31fe1a803acc9dbc4715f1207c3edc1 /usr.sbin/bgpd/rde_update.c | |
parent | e77c61be3d8b544fc0434e23b24bcef0665b0e8a (diff) |
Implement 'max-prefix NUM out' to limit the number of announced prefixes.
This is an easy safety switch to not leak full tables to upstreams and
peers. If the limit is hit a Cease notification is sent and the session
is closed.
This implements most of https://tools.ietf.org/html/draft-sa-idr-maxprefix-00
OK job@
Diffstat (limited to 'usr.sbin/bgpd/rde_update.c')
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index d290c5436a6..6e8c1ce4b9f 100644 --- a/usr.sbin/bgpd/rde_update.c +++ b/usr.sbin/bgpd/rde_update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.122 2019/08/13 12:16:20 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.123 2020/01/24 05:44:05 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -144,8 +144,10 @@ withdraw: /* withdraw prefix */ pt_getaddr(old->pt, &addr); if (prefix_adjout_withdraw(peer, &addr, - old->pt->prefixlen) == 1) + old->pt->prefixlen) == 1) { + peer->prefix_out_cnt--; peer->up_wcnt++; + } } else { switch (up_test_update(peer, new)) { case 1: @@ -169,10 +171,22 @@ withdraw: /* only send update if path changed */ if (prefix_adjout_update(peer, &state, &addr, - new->pt->prefixlen, prefix_vstate(new)) == 1) + new->pt->prefixlen, prefix_vstate(new)) == 1) { + peer->prefix_out_cnt++; peer->up_nlricnt++; + } rde_filterstate_clean(&state); + + /* max prefix checker outbound */ + if (peer->conf.max_out_prefix && + peer->prefix_out_cnt > peer->conf.max_out_prefix) { + log_peer_warnx(&peer->conf, + "outbound prefix limit reached (>%u/%u)", + peer->prefix_out_cnt, peer->conf.max_out_prefix); + rde_update_err(peer, ERR_CEASE, + ERR_CEASE_MAX_SENT_PREFIX, NULL, 0); + } } } @@ -214,11 +228,23 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer, return; } - if (prefix_adjout_update(peer, &state, &addr, 0, ROA_NOTFOUND) == 1) + if (prefix_adjout_update(peer, &state, &addr, 0, ROA_NOTFOUND) == 1) { + peer->prefix_out_cnt++; peer->up_nlricnt++; + } /* no longer needed */ rde_filterstate_clean(&state); + + /* max prefix checker outbound */ + if (peer->conf.max_out_prefix && + peer->prefix_out_cnt > peer->conf.max_out_prefix) { + log_peer_warnx(&peer->conf, + "outbound prefix limit reached (>%u/%u)", + peer->prefix_out_cnt, peer->conf.max_out_prefix); + rde_update_err(peer, ERR_CEASE, + ERR_CEASE_MAX_SENT_PREFIX, NULL, 0); + } } /* only for IPv4 */ |