summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/rde.c32
-rw-r--r--usr.sbin/bgpd/rde.h12
-rw-r--r--usr.sbin/bgpd/rde_filter.c42
-rw-r--r--usr.sbin/bgpd/rde_rib.c4
-rw-r--r--usr.sbin/bgpd/rde_update.c34
5 files changed, 72 insertions, 52 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index da5b9978054..1a33948d18f 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.381 2018/06/25 14:28:33 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.382 2018/06/28 08:07:21 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1364,6 +1364,7 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
struct bgpd_addr *prefix, u_int8_t prefixlen)
{
struct rde_aspath *fasp;
+ struct prefix *p;
enum filter_actions action;
u_int16_t i;
@@ -1372,12 +1373,15 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
if (path_update(&ribs[RIB_ADJ_IN].rib, peer, asp, prefix, prefixlen, 0))
peer->prefix_cnt++;
+ p = prefix_get(&ribs[RIB_ADJ_IN].rib, peer, prefix, prefixlen, 0);
+ if (p == NULL)
+ fatalx("rde_update_update: no prefix in Adj-RIB-In");
+
for (i = RIB_LOC_START; i < rib_size; i++) {
if (*ribs[i].name == '\0')
break;
/* input filter */
- action = rde_filter(ribs[i].in_rules, &fasp, peer, asp, prefix,
- prefixlen, peer);
+ action = rde_filter(ribs[i].in_rules, peer, &fasp, p, asp);
if (fasp == NULL)
fasp = asp;
@@ -2303,8 +2307,7 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p,
pt_getaddr(p->re->prefix, &addr);
asp = prefix_aspath(p);
- a = rde_filter(out_rules, &fasp, peer, asp, &addr,
- p->re->prefix->prefixlen, asp->peer);
+ a = rde_filter(out_rules, peer, &fasp, p, asp);
if (fasp)
fasp->peer = asp->peer;
else
@@ -3064,16 +3067,14 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr)
/* check if prefix changed */
if (rib->state == RECONF_RELOAD) {
- oa = rde_filter(rib->in_rules_tmp, &oasp, peer,
- asp, &addr, pt->prefixlen, peer);
+ oa = rde_filter(rib->in_rules_tmp, peer, &oasp, p, asp);
oasp = oasp != NULL ? oasp : asp;
} else {
/* make sure we update everything for RECONF_REINIT */
oa = ACTION_DENY;
oasp = asp;
}
- na = rde_filter(rib->in_rules, &nasp, peer, asp,
- &addr, pt->prefixlen, peer);
+ na = rde_filter(rib->in_rules, peer, &nasp, p, asp);
nasp = nasp != NULL ? nasp : asp;
/* go through all 4 possible combinations */
@@ -3122,10 +3123,8 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr)
if (up_test_update(peer, p) != 1)
return;
- oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
- &addr, pt->prefixlen, prefix_peer(p));
- na = rde_filter(out_rules, &nasp, peer, prefix_aspath(p),
- &addr, pt->prefixlen, prefix_peer(p));
+ oa = rde_filter(out_rules_tmp, peer, &oasp, p, prefix_aspath(p));
+ na = rde_filter(out_rules, peer, &nasp, p, prefix_aspath(p));
oasp = oasp != NULL ? oasp : prefix_aspath(p);
nasp = nasp != NULL ? nasp : prefix_aspath(p);
@@ -3167,8 +3166,7 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr)
if (up_test_update(peer, p) != 1)
return;
- oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
- &addr, pt->prefixlen, prefix_peer(p));
+ oa = rde_filter(out_rules_tmp, peer, &oasp, p, prefix_aspath(p));
oasp = oasp != NULL ? oasp : prefix_aspath(p);
if (oa == ACTION_DENY)
@@ -3648,9 +3646,9 @@ network_add(struct network_config *nc, int flagstatic)
}
if (!flagstatic)
asp->flags |= F_ANN_DYNAMIC;
- rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself);
+ rde_apply_set(&nc->attrset, asp, nc->prefix.aid, peerself, peerself);
if (vpnset)
- rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself);
+ rde_apply_set(vpnset, asp, nc->prefix.aid, peerself, peerself);
for (i = RIB_LOC_START; i < rib_size; i++) {
if (*ribs[i].name == '\0')
break;
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index cb3037afa01..6bb7f7b8c0d 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.171 2018/06/27 13:14:44 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.172 2018/06/28 08:07:21 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -402,10 +402,10 @@ u_char *community_ext_delete_non_trans(u_char *, u_int16_t,
void prefix_evaluate(struct prefix *, struct rib_entry *);
/* rde_filter.c */
-enum filter_actions rde_filter(struct filter_head *, struct rde_aspath **,
- struct rde_peer *, struct rde_aspath *,
- struct bgpd_addr *, u_int8_t, struct rde_peer *);
-void rde_apply_set(struct rde_aspath *, struct filter_set_head *,
+enum filter_actions rde_filter(struct filter_head *, struct rde_peer *,
+ struct rde_aspath **, struct prefix *,
+ struct rde_aspath *);
+void rde_apply_set(struct filter_set_head *, struct rde_aspath *,
u_int8_t, struct rde_peer *, struct rde_peer *);
int rde_filter_equal(struct filter_head *, struct filter_head *,
struct rde_peer *, struct prefixset_head *);
@@ -479,6 +479,8 @@ struct rde_aspath *path_get(void);
void path_put(struct rde_aspath *);
#define PREFIX_SIZE(x) (((x) + 7) / 8 + 1)
+struct prefix *prefix_get(struct rib *, struct rde_peer *,
+ struct bgpd_addr *, int, u_int32_t);
int prefix_remove(struct rib *, struct rde_peer *,
struct bgpd_addr *, int, u_int32_t);
int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t, int);
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index dfd4f420a85..08de8583921 100644
--- a/usr.sbin/bgpd/rde_filter.c
+++ b/usr.sbin/bgpd/rde_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_filter.c,v 1.90 2018/06/27 11:06:49 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.91 2018/06/28 08:07:21 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -29,13 +29,13 @@
#include "rde.h"
#include "log.h"
-int rde_filter_match(struct filter_rule *, struct rde_aspath *,
- struct bgpd_addr *, u_int8_t, struct rde_peer *, struct rde_peer *);
+int rde_filter_match(struct filter_rule *, struct rde_peer *,
+ struct rde_aspath *, struct prefix *);
+int rde_prefix_match(struct filter_prefix *, struct prefix *);
int filterset_equal(struct filter_set_head *, struct filter_set_head *);
-int rde_test_prefix(struct filter_prefix *, struct bgpd_addr *, u_int8_t);
void
-rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh,
+rde_apply_set(struct filter_set_head *sh, struct rde_aspath *asp,
u_int8_t aid, struct rde_peer *from, struct rde_peer *peer)
{
struct filter_set *set;
@@ -330,9 +330,8 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh,
}
int
-rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
- struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer,
- struct rde_peer *from)
+rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
+ struct rde_aspath *asp, struct prefix *p)
{
u_int32_t pas;
int cas, type;
@@ -453,7 +452,7 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR)
cmpaddr = &f->match.nexthop.addr;
else
- cmpaddr = &from->remote_addr;
+ cmpaddr = &prefix_peer(p)->remote_addr;
if (cmpaddr->aid != nexthop->aid)
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
@@ -481,7 +480,7 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
log_debug("%s: processing filter for prefixset %s",
__func__, f->match.prefixset.name);
SIMPLEQ_FOREACH(psi, &f->match.prefixset.ps->psitems, entry) {
- if (rde_test_prefix(&psi->p, prefix, plen)) {
+ if (rde_prefix_match(&psi->p, p)) {
log_debug("%s: prefixset %s matched %s",
__func__, f->match.prefixset.ps->name,
log_addr(&psi->p.addr));
@@ -490,7 +489,7 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
}
return (0);
} else if (f->match.prefix.addr.aid != 0)
- return (rde_test_prefix(&f->match.prefix, prefix, plen));
+ return (rde_prefix_match(&f->match.prefix, p));
/* matched somewhen or is anymatch rule */
return (1);
@@ -498,9 +497,14 @@ rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
/* return 1 when prefix matches filter_prefix, 0 if not */
int
-rde_test_prefix(struct filter_prefix *fp, struct bgpd_addr *prefix,
- u_int8_t plen)
+rde_prefix_match(struct filter_prefix *fp, struct prefix *p)
{
+ struct bgpd_addr addr, *prefix = &addr;
+ u_int8_t plen;
+
+ pt_getaddr(p->re->prefix, prefix);
+ plen = p->re->prefix->prefixlen;
+
if (fp->addr.aid != prefix->aid)
/* don't use IPv4 rules for IPv6 and vice versa */
return (0);
@@ -976,9 +980,8 @@ rde_filter_calc_skip_steps(struct filter_head *rules)
} while (0)
enum filter_actions
-rde_filter(struct filter_head *rules, struct rde_aspath **new,
- struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix,
- u_int8_t prefixlen, struct rde_peer *from)
+rde_filter(struct filter_head *rules, struct rde_peer *peer,
+ struct rde_aspath **new, struct prefix *p, struct rde_aspath *asp)
{
struct filter_rule *f;
enum filter_actions action = ACTION_DENY; /* default deny */
@@ -1010,7 +1013,8 @@ rde_filter(struct filter_head *rules, struct rde_aspath **new,
(f->peer.peerid &&
f->peer.peerid != peer->conf.id),
f->skip[RDE_FILTER_SKIP_PEERID].ptr);
- if (rde_filter_match(f, asp, prefix, prefixlen, peer, from)) {
+
+ if (rde_filter_match(f, peer, asp, p)) {
if (asp != NULL && new != NULL) {
/* asp may get modified so create a copy */
if (*new == NULL) {
@@ -1018,8 +1022,8 @@ rde_filter(struct filter_head *rules, struct rde_aspath **new,
/* ... and use the copy from now on */
asp = *new;
}
- rde_apply_set(asp, &f->set, prefix->aid,
- from, peer);
+ rde_apply_set(&f->set, asp, p->re->prefix->aid,
+ prefix_peer(p), peer);
}
if (f->action != ACTION_NONE)
action = f->action;
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 7ff53f15cd4..7e51e58a793 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.162 2018/06/27 13:14:44 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.163 2018/06/28 08:07:21 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -47,8 +47,6 @@ struct rib_entry *rib_restart(struct rib_context *);
RB_PROTOTYPE(rib_tree, rib_entry, rib_e, rib_compare);
RB_GENERATE(rib_tree, rib_entry, rib_e, rib_compare);
-struct prefix *prefix_get(struct rib *, struct rde_peer *,
- struct bgpd_addr *, int, u_int32_t);
int prefix_add(struct rib *, struct rde_aspath *,
struct bgpd_addr *, int, int);
void prefix_move(struct rde_aspath *, struct prefix *, int);
diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c
index 7463970f456..e5764fc4c8e 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.91 2018/06/26 13:34:26 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.92 2018/06/28 08:07:21 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -411,8 +411,7 @@ withdraw:
asp = prefix_aspath(old);
pt_getaddr(old->re->prefix, &addr);
- if (rde_filter(rules, NULL, peer, asp, &addr,
- old->re->prefix->prefixlen, asp->peer) == ACTION_DENY)
+ if (rde_filter(rules, peer, NULL, old, asp) == ACTION_DENY)
return;
/* withdraw prefix */
@@ -429,8 +428,7 @@ withdraw:
asp = prefix_aspath(new);
pt_getaddr(new->re->prefix, &addr);
- if (rde_filter(rules, &fasp, peer, asp, &addr,
- new->re->prefix->prefixlen, asp->peer) == ACTION_DENY) {
+ if (rde_filter(rules, peer, &fasp, new, asp) == ACTION_DENY) {
path_put(fasp);
goto withdraw;
}
@@ -445,12 +443,18 @@ withdraw:
}
}
+struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int);
+void rib_remove(struct rib_entry *);
+int rib_empty(struct rib_entry *);
+
/* send a default route to the specified peer */
void
up_generate_default(struct filter_head *rules, struct rde_peer *peer,
u_int8_t aid)
{
struct rde_aspath *asp, *fasp;
+ struct prefix p;
+ struct rib_entry *re;
struct bgpd_addr addr;
if (peer->capa.mp[aid] == 0)
@@ -467,12 +471,23 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer,
*/
/* rde_apply_set(asp, set, af, NULL ???, DIR_IN); */
- /* filter as usual */
+ /*
+ * XXX this is ugly but it will get better once we have a proper
+ * Adj-RIB-Out. Since then this will be just inserted there.
+ */
+ bzero(&p, sizeof(p));
bzero(&addr, sizeof(addr));
addr.aid = aid;
+ re = rib_get(peer->rib, &addr, 0);
+ if (re == NULL)
+ re = rib_add(peer->rib, &addr, 0);
+ p.re = re;
+ p.aspath = asp;
+ p.peer = peer;
+ p.flags = 0;
- if (rde_filter(rules, &fasp, peer, asp, &addr, 0, NULL) ==
- ACTION_DENY) {
+ /* filter as usual */
+ if (rde_filter(rules, peer, &fasp, &p, asp) == ACTION_DENY) {
path_put(fasp);
path_put(asp);
return;
@@ -487,6 +502,9 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer,
if (fasp != asp)
path_put(fasp);
path_put(asp);
+
+ if (rib_empty(re))
+ rib_remove(re);
}
/* generate a EoR marker in the update list. This is a horrible hack. */