diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 32 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 12 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 42 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 34 |
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. */ |