diff options
-rw-r--r-- | proto/bgp/bgp.c | 23 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 7 | ||||
-rw-r--r-- | proto/bgp/config.Y | 3 | ||||
-rw-r--r-- | proto/bgp/packets.c | 17 |
4 files changed, 42 insertions, 8 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b42ea302..eae835ab 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -212,7 +212,7 @@ bgp_update_startup_delay(struct bgp_proto *p, struct bgp_conn *conn, unsigned co struct bgp_config *cf = p->cf; /* Don't handle cease messages as errors */ - if (code == 6 && !subcode) + if (code == 6 && !subcode && p->last_error_class != BE_AUTO_DOWN) { p->startup_delay = 0; return; @@ -483,6 +483,21 @@ bgp_active(struct bgp_proto *p, int delay) bgp_start_timer(conn->connect_retry_timer, delay); } +int +bgp_apply_limits(struct bgp_proto *p) +{ + if (p->cf->route_limit && (p->p.stats.imp_routes > p->cf->route_limit)) + { + log(L_WARN "%s: Route limit exceeded, shutting down", p->p.name); + bgp_store_error(p, NULL, BE_AUTO_DOWN, BEA_ROUTE_LIMIT_EXCEEDED); + bgp_stop(p); + return -1; + } + + return 0; +} + + /** * bgp_connect - initiate an outgoing connection * @p: BGP instance @@ -848,8 +863,9 @@ bgp_check(struct bgp_config *c) } static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" }; -static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown", ""}; +static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""}; static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed" }; +static char *bgp_auto_errors[] = { "", "Route limit exceeded"}; static void @@ -873,6 +889,9 @@ bgp_get_status(struct proto *P, byte *buf) case BE_BGP_TX: err2 = bgp_error_dsc(errbuf, p->last_error_code >> 16, p->last_error_code & 0xFF); break; + case BE_AUTO_DOWN: + err2 = bgp_auto_errors[p->last_error_code]; + break; } if (P->proto_state == PS_DOWN) diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 8477f9e5..1f29d59d 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -31,6 +31,7 @@ struct bgp_config { int rr_client; /* Whether neighbor is RR client of me */ int rs_client; /* Whether neighbor is RS client of me */ int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */ + u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */ unsigned connect_retry_time; unsigned hold_time, initial_hold_time; unsigned keepalive_time; @@ -132,6 +133,7 @@ void bgp_conn_enter_established_state(struct bgp_conn *conn); void bgp_conn_enter_close_state(struct bgp_conn *conn); void bgp_conn_enter_idle_state(struct bgp_conn *conn); void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code); +int bgp_apply_limits(struct bgp_proto *p); #ifdef LOCAL_DEBUG @@ -256,8 +258,11 @@ void bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subco #define BEM_NEIGHBOR_LOST 1 #define BEM_INVALID_NEXT_HOP 2 -#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported */ +#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */ +/* Automatic shutdown error codes */ + +#define BEA_ROUTE_LIMIT_EXCEEDED 1 /* Well-known communities */ diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index c5ea87de..872fb271 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -22,7 +22,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE, BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP, BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4, - CAPABILITIES) + CAPABILITIES, LIMIT) CF_GRAMMAR @@ -77,6 +77,7 @@ bgp_proto: | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; } | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; } | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; } + | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; } ; CF_ADDTO(dynamic_attr, BGP_PATH diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index d5397f5f..f358012a 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -725,13 +725,19 @@ bgp_do_rx_update(struct bgp_conn *conn, e->net = n; e->pflags = 0; rte_update(p->p.table, n, &p->p, &p->p, e); + if (bgp_apply_limits(p) < 0) + goto bad2; } + rta_free(a); } -bad: + + return; + + bad: + bgp_error(conn, 3, err, NULL, 0); + bad2: if (a) rta_free(a); - if (err) - bgp_error(conn, 3, err, NULL, 0); return; } @@ -825,6 +831,8 @@ bgp_do_rx_update(struct bgp_conn *conn, e->net = n; e->pflags = 0; rte_update(p->p.table, n, &p->p, &p->p, e); + if (bgp_apply_limits(p) < 0) + goto bad2; } rta_free(a); } @@ -832,8 +840,9 @@ bgp_do_rx_update(struct bgp_conn *conn, return; -bad: + bad: bgp_error(conn, 3, 9, start, len0); + bad2: if (a) rta_free(a); return; |