-.\" $OpenBSD: bgpd.conf.5,v 1.213 2021/08/09 08:15:34 claudio Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.214 2021/09/01 12:39:52 claudio Exp $
.\"
.\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
.\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 9 2021 $
+.Dd $Mdocdate: September 1 2021 $
.Dt BGPD.CONF 5
.Os
.Sh NAME
.Pp
.It Xo
.Ic roa-set
-.Ic { Ar address Ns Li / Ns Ar len Ic maxlen Ar mlen Ic source-as Ar asn ... Ic }
+.Ic { Ar address Ns Li / Ns Ar len Ic maxlen Ar mlen Ic source-as Ar asn
+.Oo Ic expires Ar seconds Oc ... Ic }
.Xc
The
.Ic roa-set
Each received prefix is checked against the
.Ic roa-set ,
and the Origin Validation State (OVS) is set.
+.Ic expires
+can be set to the seconds since Epoch until when this VRP is valid.
.Bd -literal -offset indent
roa-set { 192.0.2.0/24 maxlen 24 source-as 64511
203.0.113.0/24 source-as 64496 }
-/* $OpenBSD: bgpd.h,v 1.417 2021/08/09 08:15:34 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.418 2021/09/01 12:39:52 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
uint8_t maxlen;
uint8_t pad;
uint32_t asnum;
+ time_t expires;
union {
struct in_addr inet;
struct in6_addr inet6;
-/* $OpenBSD: parse.y,v 1.418 2021/08/09 08:15:34 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.419 2021/09/01 12:39:52 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
static struct filter_head *groupfilter_l;
static struct filter_rule *curpeer_filter[2];
static struct filter_rule *curgroup_filter[2];
+static int noexpires;
struct filter_rib_l {
struct filter_rib_l *next;
static void add_as_set(u_int32_t);
static void done_as_set(void);
static struct prefixset *new_prefix_set(char *, int);
-static void add_roa_set(struct prefixset_item *, u_int32_t, u_int8_t);
+static void add_roa_set(struct prefixset_item *, u_int32_t, u_int8_t,
+ time_t);
static struct rtr_config *get_rtr(struct bgpd_addr *);
static int insert_rtr(struct rtr_config *);
%token CONNECTED STATIC
%token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE
%token PREFIX PREFIXLEN PREFIXSET
-%token ROASET ORIGINSET OVS
+%token ROASET ORIGINSET OVS EXPIRES
%token ASSET SOURCEAS TRANSITAS PEERAS MAXASLEN MAXASSEQ
%token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF
%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY
%token <v.number> NUMBER
%type <v.number> asnumber as4number as4number_any optnumber
%type <v.number> espah family safi restart origincode nettype
-%type <v.number> yesno inout restricted validity
+%type <v.number> yesno inout restricted validity expires
%type <v.string> string
%type <v.addr> address
%type <v.prefix> prefix addrspec
roa_set : ROASET '{' optnl {
curroatree = &conf->roa;
+ noexpires = 0;
} roa_set_l optnl '}' {
curroatree = NULL;
+ noexpires = 1;
}
| ROASET '{' optnl '}' /* nothing */
;
YYERROR;
}
curroatree = &curoset->roaitems;
+ noexpires = 1;
free($2);
} roa_set_l optnl '}' {
SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
}
;
-roa_set_l : prefixset_item SOURCEAS as4number_any {
+expires : /* empty */ {
+ $$ = 0;
+ }
+ | EXPIRES NUMBER {
+ if (noexpires) {
+ yyerror("syntax error, expires not allowed");
+ YYERROR;
+ }
+ $$ = $2;
+ }
+
+roa_set_l : prefixset_item SOURCEAS as4number_any expires {
if ($1->p.len_min != $1->p.len) {
yyerror("unsupported prefixlen operation in "
"roa-set");
free($1);
YYERROR;
}
- add_roa_set($1, $3, $1->p.len_max);
+ add_roa_set($1, $3, $1->p.len_max, $4);
free($1);
}
- | roa_set_l comma prefixset_item SOURCEAS as4number_any {
+ | roa_set_l comma prefixset_item SOURCEAS as4number_any expires {
if ($3->p.len_min != $3->p.len) {
yyerror("unsupported prefixlen operation in "
"roa-set");
free($3);
YYERROR;
}
- add_roa_set($3, $5, $3->p.len_max);
+ add_roa_set($3, $5, $3->p.len_max, $6);
free($3);
}
;
{ "enhanced", ENHANCED },
{ "esp", ESP},
{ "evaluate", EVALUATE},
+ { "expires", EXPIRES},
{ "export", EXPORT},
{ "export-target", EXPORTTRGT},
{ "ext-community", EXTCOMMUNITY},
}
static void
-add_roa_set(struct prefixset_item *npsi, u_int32_t as, u_int8_t max)
+add_roa_set(struct prefixset_item *npsi, u_int32_t as, u_int8_t max,
+ time_t expires)
{
struct roa *roa, *r;
roa->prefixlen = npsi->p.len;
roa->maxlen = max;
roa->asnum = as;
+ roa->expires = expires;
switch (roa->aid) {
case AID_INET:
roa->prefix.inet = npsi->p.addr.v4;
}
r = RB_INSERT(roa_tree, curroatree, roa);
- if (r != NULL)
+ if (r != NULL) {
/* just ignore duplicates */
+ if (r->expires != 0 && expires != 0 && expires > r->expires)
+ r->expires = expires;
free(roa);
+ }
}
static struct rtr_config *
-/* $OpenBSD: printconf.c,v 1.147 2021/03/02 09:45:07 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.148 2021/09/01 12:39:52 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
if (roa->prefixlen != roa->maxlen)
printf(" maxlen %u", roa->maxlen);
printf(" source-as %u", roa->asnum);
+ if (roa->expires != 0)
+ printf(" expires %lld", (long long)roa->expires);
}
printf("\n}\n\n");
}
-/* $OpenBSD: rtr.c,v 1.3 2021/05/11 12:09:19 claudio Exp $ */
+/* $OpenBSD: rtr.c,v 1.4 2021/09/01 12:39:52 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
static struct imsgbuf *ibuf_main;
static struct imsgbuf *ibuf_rde;
static struct bgpd_config *conf, *nconf;
+static struct timer_head expire_timer;
static void
rtr_sighdlr(int sig)
#define PFD_PIPE_RDE 1
#define PFD_PIPE_COUNT 2
+#define EXPIRE_TIMEOUT 300
+
+/*
+ * Every EXPIRE_TIMEOUT seconds traverse the static roa-set table and expire
+ * all elements where the expires timestamp is smaller or equal to now.
+ * If any change is done recalculate the RTR table.
+ */
+static unsigned int
+rtr_expire_roas(time_t now)
+{
+ struct roa *roa, *nr;
+ unsigned int recalc = 0;
+
+ RB_FOREACH_SAFE(roa, roa_tree, &conf->roa, nr) {
+ if (roa->expires != 0 && roa->expires <= now) {
+ recalc++;
+ RB_REMOVE(roa_tree, &conf->roa, roa);
+ free(roa);
+ }
+ }
+ if (recalc != 0)
+ log_warnx("%u roa-set entries expired", recalc);
+ return recalc;
+}
+
void
roa_insert(struct roa_tree *rt, struct roa *in)
{
conf = new_config();
log_info("rtr engine ready");
+ TAILQ_INIT(&expire_timer);
+ timer_set(&expire_timer, Timer_Rtr_Expire, EXPIRE_TIMEOUT);
+
while (rtr_quit == 0) {
i = rtr_count();
if (pfd_elms < PFD_PIPE_COUNT + i) {
pfd = newp;
pfd_elms = PFD_PIPE_COUNT + i;
}
- timeout = 240; /* loop every 240s at least */
+
+ /* run the expire timeout every EXPIRE_TIMEOUT seconds */
+ timeout = timer_nextduein(&expire_timer, getmonotime());
+ if (timeout == -1)
+ fatalx("roa-set expire timer no longer runnning");
+
bzero(pfd, sizeof(struct pollfd) * pfd_elms);
set_pollfd(&pfd[PFD_PIPE_MAIN], ibuf_main);
i = PFD_PIPE_COUNT;
rtr_check_events(pfd + i, pfd_elms - i);
+
+ if (timer_nextisdue(&expire_timer, getmonotime()) != NULL) {
+ timer_set(&expire_timer, Timer_Rtr_Expire,
+ EXPIRE_TIMEOUT);
+ if (rtr_expire_roas(time(NULL)) != 0)
+ rtr_recalc();
+ }
}
rtr_shutdown();
RB_ROOT(&nconf->roa) = NULL;
/* finally merge the rtr session */
rtr_config_merge();
+ rtr_expire_roas(time(NULL));
rtr_recalc();
log_info("RTR engine reconfigured");
imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,