From: claudio Date: Mon, 12 Aug 2024 09:04:23 +0000 (+0000) Subject: Add 'min-version' RTR config option and default to RTR version 1 by default. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=d87cfbcc05d52e76adfe116523022dc089b2ffa6;p=openbsd Add 'min-version' RTR config option and default to RTR version 1 by default. The min-version pins a minimal required version for rtr session. This is needed if specific PDUs are required and it ensures that the session is not suddenly downgraded. This is important for ASPA where a minimum version of 2 is required. Only then the ASPA PDUs are transmitted. By default a RTR version of 1 is used but setting min-version to 2 will enable draft-ietf-sidrops-8210bis-14 support and enforce it at the same time. Right now defaulting to version 2 is not possible since draft-ietf-sidrops-8210bis failed to progress for a too long time resulting in split eco system with various incompatible RTR version 2 implementations. OK tb@ --- diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index 5987713052c..8b6e1bc70ce 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.264 2024/05/15 09:09:38 job Exp $ */ +/* $OpenBSD: bgpd.c,v 1.265 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -738,8 +738,12 @@ send_config(struct bgpd_config *conf) } free_aspatree(&conf->aspa); SIMPLEQ_FOREACH(rtr, &conf->rtrs, entry) { + struct rtr_config_msg rtrconf = { 0 }; + + strlcpy(rtrconf.descr, rtr->descr, sizeof(rtrconf.descr)); + rtrconf.min_version = rtr->min_version; if (imsg_compose(ibuf_rtr, IMSG_RECONF_RTR_CONFIG, rtr->id, - 0, -1, rtr->descr, sizeof(rtr->descr)) == -1) + 0, -1, &rtrconf, sizeof(rtrconf)) == -1) return (-1); } diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index a554e51ffb6..e01abf88b76 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.240 2024/04/24 10:41:34 claudio Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.241 2024/08/12 09:04:23 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker .\" Copyright (c) 2003, 2004 Henning Brauer @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 24 2024 $ +.Dd $Mdocdate: August 12 2024 $ .Dt BGPD.CONF 5 .Os .Sh NAME @@ -579,6 +579,12 @@ Bind to the specific IP address before opening the TCP connection to the .Em rtr server. .Pp +.Ic min-version Ar number +Require a minimal RTR version of +.Ar number . +To ensure that ASPA records are synchronised over RTR a minimal version +of 2 is required. +.Pp .It Ic port Ar number Specify the TCP destination port for the .Em rtr diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index e0ba7110cd5..a4d2a106b7d 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.493 2024/05/18 11:17:30 jsg Exp $ */ +/* $OpenBSD: bgpd.h,v 1.494 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -33,6 +33,8 @@ #include #define BGP_VERSION 4 +#define RTR_MAX_VERSION 2 +#define RTR_DEFAULT_VERSION 1 #define BGP_PORT 179 #define RTR_PORT 323 #define CONFFILE "/etc/bgpd.conf" @@ -570,11 +572,19 @@ struct rtr_config { struct bgpd_addr local_addr; uint32_t id; uint16_t remote_port; + uint8_t min_version; +}; + +struct rtr_config_msg { + char descr[PEER_DESCR_LEN]; + uint8_t min_version; }; struct ctl_show_rtr { char descr[PEER_DESCR_LEN]; char state[PEER_DESCR_LEN]; + char last_sent_msg[REASON_LEN]; + char last_recv_msg[REASON_LEN]; struct bgpd_addr remote_addr; struct bgpd_addr local_addr; uint32_t serial; @@ -582,12 +592,11 @@ struct ctl_show_rtr { uint32_t retry; uint32_t expire; int session_id; - uint16_t remote_port; - uint8_t version; enum rtr_error last_sent_error; enum rtr_error last_recv_error; - char last_sent_msg[REASON_LEN]; - char last_recv_msg[REASON_LEN]; + uint16_t remote_port; + uint8_t version; + uint8_t min_version; }; enum imsg_type { diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index fa8047d5bbf..bffd40948ed 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.463 2024/05/22 08:41:14 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.464 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -241,7 +241,7 @@ typedef struct { %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE FIBPRIORITY RTABLE %token NONE UNICAST VPN RD EXPORT EXPORTTRGT IMPORTTRGT DEFAULTROUTE -%token RDE RIB EVALUATE IGNORE COMPARE RTR PORT +%token RDE RIB EVALUATE IGNORE COMPARE RTR PORT MINVERSION %token GROUP NEIGHBOR NETWORK %token EBGP IBGP %token FLOWSPEC PROTO FLAGS FRAGMENT TOS LENGTH ICMPTYPE CODE @@ -724,6 +724,14 @@ rtropt : DESCR STRING { | PORT port { currtr->remote_port = $2; } + | MINVERSION NUMBER { + if ($2 < 0 || $2 > RTR_MAX_VERSION) { + yyerror("min-version must be between %u and %u", + 0, RTR_MAX_VERSION); + YYERROR; + } + currtr->min_version = $2; + } ; conf_main : AS as4number { @@ -3578,6 +3586,7 @@ lookup(char *s) { "med", MED}, { "metric", METRIC}, { "min", YMIN}, + { "min-version", MINVERSION}, { "multihop", MULTIHOP}, { "neighbor", NEIGHBOR}, { "neighbor-as", NEIGHBORAS}, diff --git a/usr.sbin/bgpd/rtr.c b/usr.sbin/bgpd/rtr.c index 43b471204ea..4ea5aa931dd 100644 --- a/usr.sbin/bgpd/rtr.c +++ b/usr.sbin/bgpd/rtr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtr.c,v 1.21 2024/04/09 12:05:07 claudio Exp $ */ +/* $OpenBSD: rtr.c,v 1.22 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker @@ -309,7 +309,7 @@ rtr_dispatch_imsg_parent(struct imsgbuf *imsgbuf) struct imsg imsg; struct bgpd_config tconf; struct roa roa; - char descr[PEER_DESCR_LEN]; + struct rtr_config_msg rtrconf; struct rtr_session *rs; uint32_t rtrid; int n, fd; @@ -395,13 +395,14 @@ rtr_dispatch_imsg_parent(struct imsgbuf *imsgbuf) aspa = NULL; break; case IMSG_RECONF_RTR_CONFIG: - if (imsg_get_data(&imsg, descr, sizeof(descr)) == -1) + if (imsg_get_data(&imsg, &rtrconf, + sizeof(rtrconf)) == -1) fatal("imsg_get_data"); rs = rtr_get(rtrid); if (rs == NULL) - rtr_new(rtrid, descr); + rtr_new(rtrid, &rtrconf); else - rtr_config_keep(rs); + rtr_config_keep(rs, &rtrconf); break; case IMSG_RECONF_DRAIN: imsg_compose(ibuf_main, IMSG_RECONF_DRAIN, 0, 0, diff --git a/usr.sbin/bgpd/rtr_proto.c b/usr.sbin/bgpd/rtr_proto.c index 9619f1f5936..3b09fa36cf8 100644 --- a/usr.sbin/bgpd/rtr_proto.c +++ b/usr.sbin/bgpd/rtr_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtr_proto.c,v 1.37 2024/08/09 14:00:48 claudio Exp $ */ +/* $OpenBSD: rtr_proto.c,v 1.38 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker @@ -42,7 +42,6 @@ struct rtr_header { uint32_t length; } __packed; -#define RTR_MAX_VERSION 2 #define RTR_MAX_PDU_SIZE 49152 /* XXX < IBUF_READ_SIZE */ #define RTR_MAX_PDU_ERROR_SIZE 256 #define RTR_DEFAULT_REFRESH 3600 @@ -213,6 +212,9 @@ struct rtr_session { char last_recv_msg[REASON_LEN]; uint8_t version; uint8_t prev_version; + uint8_t min_version; + uint8_t errored; + }; TAILQ_HEAD(, rtr_session) rtrs = TAILQ_HEAD_INITIALIZER(rtrs); @@ -259,6 +261,14 @@ log_rtr_type(enum rtr_pdu_type type) } }; +static uint8_t +rtr_max_session_version(struct rtr_session *rs) +{ + if (rs->min_version > RTR_DEFAULT_VERSION) + return rs->min_version; + return RTR_DEFAULT_VERSION; +} + static void rtr_reset_cache(struct rtr_session *rs) { @@ -1084,13 +1094,14 @@ rtr_fsm(struct rtr_session *rs, enum rtr_event event) switch (event) { case RTR_EVNT_UNSUPP_PROTO_VERSION: - if (rs->prev_version == rs->version) { + if (rs->prev_version == rs->version || + rs->version < rs->min_version) { /* * Can't downgrade anymore, fail connection. * RFC requires sending the error with the * highest supported version number. */ - rs->version = RTR_MAX_VERSION; + rs->version = rtr_max_session_version(rs); rtr_send_error(rs, NULL, UNSUPP_PROTOCOL_VERS, "negotiation failed"); return; @@ -1114,8 +1125,13 @@ rtr_fsm(struct rtr_session *rs, enum rtr_event event) rs->fd = -1; } /* try to reopen session */ - timer_set(&rs->timers, Timer_Rtr_Retry, - arc4random_uniform(10)); + if (!rs->errored) + timer_set(&rs->timers, Timer_Rtr_Retry, + arc4random_uniform(10)); + else + timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); + + rs->errored = 1; /* * A close event during version negotiation needs to remain * in the negotiation state else the same error will happen @@ -1190,6 +1206,7 @@ rtr_fsm(struct rtr_session *rs, enum rtr_event event) rtr_sem_release(rs->active_lock); rtr_recalc(); rs->active_lock = 0; + rs->errored = 0; /* clear the last errors */ rs->last_sent_error = NO_ERROR; rs->last_recv_error = NO_ERROR; @@ -1371,12 +1388,12 @@ rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout) } struct rtr_session * -rtr_new(uint32_t id, char *descr) +rtr_new(uint32_t id, struct rtr_config_msg *conf) { struct rtr_session *rs; if ((rs = calloc(1, sizeof(*rs))) == NULL) - fatal("RTR session %s", descr); + fatal("RTR session %s", conf->descr); RB_INIT(&rs->roa_set); RB_INIT(&rs->aspa); @@ -1384,11 +1401,12 @@ rtr_new(uint32_t id, char *descr) TAILQ_INIT(&rs->timers); msgbuf_init(&rs->w); - strlcpy(rs->descr, descr, sizeof(rs->descr)); + strlcpy(rs->descr, conf->descr, sizeof(rs->descr)); rs->id = id; rs->session_id = -1; - rs->version = RTR_MAX_VERSION; - rs->prev_version = RTR_MAX_VERSION; + rs->min_version = conf->min_version; /* must be set before version */ + rs->version = rtr_max_session_version(rs); + rs->prev_version = rtr_max_session_version(rs); rs->refresh = RTR_DEFAULT_REFRESH; rs->retry = RTR_DEFAULT_RETRY; rs->expire = RTR_DEFAULT_EXPIRE; @@ -1441,8 +1459,8 @@ rtr_open(struct rtr_session *rs, int fd) } if (rs->state == RTR_STATE_CLOSED) { - rs->version = RTR_MAX_VERSION; - rs->prev_version = RTR_MAX_VERSION; + rs->version = rtr_max_session_version(rs); + rs->prev_version = rtr_max_session_version(rs); } rs->fd = rs->w.fd = fd; @@ -1471,8 +1489,10 @@ rtr_config_merge(void) } void -rtr_config_keep(struct rtr_session *rs) +rtr_config_keep(struct rtr_session *rs, struct rtr_config_msg *conf) { + strlcpy(rs->descr, conf->descr, sizeof(rs->descr)); + rs->min_version = conf->min_version; rs->reconf_action = RECONF_KEEP; } @@ -1523,6 +1543,7 @@ rtr_show(struct rtr_session *rs, pid_t pid) /* descr, remote_addr, local_addr and remote_port set by parent */ msg.version = rs->version; + msg.min_version = rs->min_version; msg.serial = rs->serial; msg.refresh = rs->refresh; msg.retry = rs->retry; diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index 815b1242eeb..a6f4a53faec 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.170 2024/05/18 11:17:30 jsg Exp $ */ +/* $OpenBSD: session.h,v 1.171 2024/08/12 09:04:23 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -296,13 +296,14 @@ struct rtr_session; size_t rtr_count(void); void rtr_check_events(struct pollfd *, size_t); size_t rtr_poll_events(struct pollfd *, size_t, time_t *); -struct rtr_session *rtr_new(uint32_t, char *); +struct rtr_session *rtr_new(uint32_t, struct rtr_config_msg *); struct rtr_session *rtr_get(uint32_t); void rtr_free(struct rtr_session *); void rtr_open(struct rtr_session *, int); void rtr_config_prep(void); void rtr_config_merge(void); -void rtr_config_keep(struct rtr_session *); +void rtr_config_keep(struct rtr_session *, + struct rtr_config_msg *); void rtr_roa_merge(struct roa_tree *); void rtr_aspa_merge(struct aspa_tree *); void rtr_shutdown(void);