diff options
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 36 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 118 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 10 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_update.c | 18 |
7 files changed, 120 insertions, 78 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index a650688de42..749c3cbd4b2 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.234 2009/06/05 19:52:32 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.235 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -603,6 +603,7 @@ enum comp_ops { struct filter_peers { u_int32_t peerid; u_int32_t groupid; + u_int16_t ribid; }; /* special community type */ @@ -657,6 +658,7 @@ TAILQ_HEAD(filter_head, filter_rule); struct filter_rule { TAILQ_ENTRY(filter_rule) entry; + char rib[PEER_DESCR_LEN]; struct filter_peers peer; struct filter_match match; struct filter_set_head set; diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index aa453587714..175a9a02fb9 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.230 2009/06/06 01:07:01 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.231 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -182,7 +182,7 @@ typedef struct { %token <v.number> NUMBER %type <v.number> asnumber as4number optnumber yesno inout %type <v.number> espah family restart -%type <v.string> string +%type <v.string> string filter_rib %type <v.addr> address %type <v.prefix> prefix addrspec %type <v.u8> action quick direction delete @@ -1197,16 +1197,37 @@ encspec : /* nada */ { } ; -filterrule : action quick direction filter_peer_h filter_match_h filter_set +filterrule : action quick filter_rib direction filter_peer_h filter_match_h filter_set { struct filter_rule r; bzero(&r, sizeof(r)); r.action = $1; r.quick = $2; - r.dir = $3; - - if (expand_rule(&r, $4, &$5, $6) == -1) + r.dir = $4; + if ($3) { + if (r.dir != DIR_IN) { + yyerror("rib only allowed on \"from\" " + "rules."); + free($3); + YYERROR; + } + if (!find_rib($3)) { + yyerror("rib \"%s\" does not exist.", + $3); + free($3); + YYERROR; + } + if (strlcpy(r.rib, $3, sizeof(r.rib)) >= + sizeof(r.rib)) { + yyerror("rib name \"%s\" too long: " + "max %u", $3, sizeof(r.rib) - 1); + free($3); + YYERROR; + } + free($3); + } + if (expand_rule(&r, $5, &$6, $7) == -1) YYERROR; } ; @@ -1224,6 +1245,9 @@ direction : FROM { $$ = DIR_IN; } | TO { $$ = DIR_OUT; } ; +filter_rib : /* empty */ { $$ = NULL; } + | RIB STRING { $$ = $2; } + filter_peer_h : filter_peer | '{' filter_peer_l '}' { $$ = $2; } ; diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 358b55e5c47..c64d23dee95 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.69 2009/06/05 20:26:38 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.70 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -423,10 +423,12 @@ print_rule(struct peer *peer_l, struct filter_rule *r) printf("deny "); else printf("match "); - if (r->quick) printf("quick "); + if (r->rib[0]) + printf("rib %s ", r->rib); + if (r->dir == DIR_IN) printf("from "); else if (r->dir == DIR_OUT) diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 26cc8436413..eedec0971ad 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.256 2009/06/06 01:02:51 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.257 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -59,7 +59,7 @@ int rde_update_get_prefix6(u_char *, u_int16_t, struct bgpd_addr *, u_int8_t *); void rde_update_err(struct rde_peer *, u_int8_t , u_int8_t, void *, u_int16_t); -void rde_update_log(const char *, +void rde_update_log(const char *, u_int16_t, const struct rde_peer *, const struct bgpd_addr *, const struct bgpd_addr *, u_int8_t); void rde_as4byte_fixup(struct rde_peer *, struct rde_aspath *); @@ -246,6 +246,7 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, log_info("route decision engine ready"); TAILQ_FOREACH(f, rules, entry) { + f->peer.ribid = rib_find(f->rib); TAILQ_FOREACH(set, &f->set, entry) { if (set->type == ACTION_SET_NEXTHOP) { nh = nexthop_get(&set->action.nexthop); @@ -622,6 +623,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) fatal(NULL); memcpy(r, imsg.data, sizeof(struct filter_rule)); TAILQ_INIT(&r->set); + r->peer.ribid = rib_find(r->rib); parent_set = &r->set; TAILQ_INSERT_TAIL(newrules, r, entry); break; @@ -1081,23 +1083,24 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp, if (peer->conf.softreconfig_in) r += path_update(&ribs[0], peer, asp, prefix, prefixlen); - /* input filter */ - if (rde_filter(&fasp, rules_l, peer, asp, prefix, prefixlen, - peer, DIR_IN) == ACTION_DENY) - goto done; + for (i = 1; i < rib_size; i++) { + /* input filter */ + if (rde_filter(i, &fasp, rules_l, peer, asp, prefix, prefixlen, + peer, DIR_IN) == ACTION_DENY) + goto done; - if (fasp == NULL) - fasp = asp; + if (fasp == NULL) + fasp = asp; - rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, - prefix, prefixlen); - for (i = 1; i < rib_size; i++) + rde_update_log("update", i, peer, &fasp->nexthop->exit_nexthop, + prefix, prefixlen); r += path_update(&ribs[i], peer, fasp, prefix, prefixlen); done: - /* free modified aspath */ - if (fasp != asp) - path_put(fasp); + /* free modified aspath */ + if (fasp != asp) + path_put(fasp); + } if (r) peer->prefix_cnt++; @@ -1111,10 +1114,13 @@ rde_update_withdraw(struct rde_peer *peer, struct bgpd_addr *prefix, u_int16_t i; peer->prefix_rcvd_withdraw++; - rde_update_log("withdraw", peer, NULL, prefix, prefixlen); for (i = rib_size - 1; ; i--) { - r += prefix_remove(&ribs[i], peer, prefix, prefixlen, 0); + if (prefix_remove(&ribs[i], peer, prefix, prefixlen, 0)) { + rde_update_log("withdraw", i, peer, NULL, prefix, + prefixlen); + r++; + } if (i == 0) break; } @@ -1563,7 +1569,7 @@ rde_update_err(struct rde_peer *peer, u_int8_t error, u_int8_t suberr, } void -rde_update_log(const char *message, +rde_update_log(const char *message, u_int16_t rid, const struct rde_peer *peer, const struct bgpd_addr *next, const struct bgpd_addr *prefix, u_int8_t prefixlen) { @@ -1580,7 +1586,7 @@ rde_update_log(const char *message, if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1) p = NULL; l = log_fmt_peer(&peer->conf); - log_info("%s AS%s: %s %s%s", + log_info("Rib %s: %s AS%s: %s %s%s", ribs[rid].name, l, log_as(peer->conf.remote_as), message, p ? p : "out of memory", n ? n : ""); @@ -1796,7 +1802,7 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p, return; pt_getaddr(p->prefix, &addr); - a = rde_filter(&asp, rules_l, peer, p->aspath, &addr, + a = rde_filter(1 /* XXX */, &asp, rules_l, peer, p->aspath, &addr, p->prefix->prefixlen, p->aspath->peer, DIR_OUT); if (asp) asp->peer = p->aspath->peer; @@ -2125,10 +2131,10 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr) if (up_test_update(peer, p) != 1) continue; - oa = rde_filter(&oasp, rules_l, peer, p->aspath, &addr, - pt->prefixlen, p->aspath->peer, DIR_OUT); - na = rde_filter(&nasp, newrules, peer, p->aspath, &addr, - pt->prefixlen, p->aspath->peer, DIR_OUT); + oa = rde_filter(re->ribid, &oasp, rules_l, peer, p->aspath, + &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); + na = rde_filter(re->ribid, &nasp, newrules, peer, p->aspath, + &addr, pt->prefixlen, p->aspath->peer, DIR_OUT); oasp = oasp != NULL ? oasp : p->aspath; nasp = nasp != NULL ? nasp : p->aspath; @@ -2169,6 +2175,7 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr) struct rde_aspath *asp, *oasp, *nasp; enum filter_actions oa, na; struct bgpd_addr addr; + u_int16_t i; pt = re->prefix; pt_getaddr(pt, &addr); @@ -2183,39 +2190,44 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr) if (peer->reconf_in == 0) continue; - /* check if prefix changed */ - oa = rde_filter(&oasp, rules_l, peer, asp, &addr, - pt->prefixlen, peer, DIR_IN); - na = rde_filter(&nasp, newrules, peer, asp, &addr, - pt->prefixlen, peer, DIR_IN); - oasp = oasp != NULL ? oasp : asp; - nasp = nasp != NULL ? nasp : asp; - - if (oa == ACTION_DENY && na == ACTION_DENY) - /* nothing todo */ - goto done; - if (oa == ACTION_DENY && na == ACTION_ALLOW) { - /* update Local-RIB */ - path_update(&ribs[1], peer, nasp, &addr, pt->prefixlen); - goto done; - } - if (oa == ACTION_ALLOW && na == ACTION_DENY) { - /* remove from Local-RIB */ - prefix_remove(&ribs[1], peer, &addr, pt->prefixlen, 0); - goto done; - } - if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { - if (path_compare(nasp, oasp) == 0) + for (i = 1; i < rib_size; i++) { + /* check if prefix changed */ + oa = rde_filter(i, &oasp, rules_l, peer, asp, &addr, + pt->prefixlen, peer, DIR_IN); + na = rde_filter(i, &nasp, newrules, peer, asp, &addr, + pt->prefixlen, peer, DIR_IN); + oasp = oasp != NULL ? oasp : asp; + nasp = nasp != NULL ? nasp : asp; + + if (oa == ACTION_DENY && na == ACTION_DENY) + /* nothing todo */ goto done; - /* send update */ - path_update(&ribs[1], peer, nasp, &addr, pt->prefixlen); - } + if (oa == ACTION_DENY && na == ACTION_ALLOW) { + /* update Local-RIB */ + path_update(&ribs[i], peer, nasp, &addr, + pt->prefixlen); + goto done; + } + if (oa == ACTION_ALLOW && na == ACTION_DENY) { + /* remove from Local-RIB */ + prefix_remove(&ribs[i], peer, &addr, + pt->prefixlen, 0); + goto done; + } + if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { + if (path_compare(nasp, oasp) == 0) + goto done; + /* send update */ + path_update(&ribs[1], peer, nasp, &addr, + pt->prefixlen); + } done: - if (oasp != asp) - path_put(oasp); - if (nasp != asp) - path_put(nasp); + if (oasp != asp) + path_put(oasp); + if (nasp != asp) + path_put(nasp); + } } } diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 41874f39e85..2664fd470aa 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.119 2009/06/06 01:07:01 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.120 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -447,10 +447,10 @@ int pt_prefix_cmp(const struct pt_entry *, const struct pt_entry *); /* rde_filter.c */ -enum filter_actions rde_filter(struct rde_aspath **, struct filter_head *, - struct rde_peer *, struct rde_aspath *, - struct bgpd_addr *, u_int8_t, struct rde_peer *, - enum directions); +enum filter_actions rde_filter(u_int16_t, struct rde_aspath **, + struct filter_head *, struct rde_peer *, + struct rde_aspath *, struct bgpd_addr *, u_int8_t, + struct rde_peer *, enum directions); void rde_apply_set(struct rde_aspath *, struct filter_set_head *, sa_family_t, struct rde_peer *, struct rde_peer *); int rde_filter_community(struct rde_aspath *, int, int); diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index f3c40e253bd..001b796489f 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.55 2008/09/29 14:03:41 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.56 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -30,7 +30,7 @@ int rde_filter_match(struct filter_rule *, struct rde_aspath *, int filterset_equal(struct filter_set_head *, struct filter_set_head *); enum filter_actions -rde_filter(struct rde_aspath **new, struct filter_head *rules, +rde_filter(u_int16_t ribid, struct rde_aspath **new, struct filter_head *rules, struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix, u_int8_t prefixlen, struct rde_peer *from, enum directions dir) { @@ -43,6 +43,8 @@ rde_filter(struct rde_aspath **new, struct filter_head *rules, TAILQ_FOREACH(f, rules, entry) { if (dir != f->dir) continue; + if (dir == DIR_IN && f->peer.ribid != ribid) + continue; if (f->peer.groupid != 0 && f->peer.groupid != peer->conf.groupid) continue; diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index 469f584e89e..209664f4a85 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.67 2009/03/26 13:59:30 henning Exp $ */ +/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -404,9 +404,9 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer, return; pt_getaddr(old->prefix, &addr); - if (rde_filter(NULL, rules, peer, old->aspath, &addr, - old->prefix->prefixlen, old->aspath->peer, DIR_OUT) == - ACTION_DENY) + if (rde_filter(peer->ribid, NULL, rules, peer, old->aspath, + &addr, old->prefix->prefixlen, old->aspath->peer, + DIR_OUT) == ACTION_DENY) return; /* withdraw prefix */ @@ -423,9 +423,9 @@ up_generate_updates(struct filter_head *rules, struct rde_peer *peer, } pt_getaddr(new->prefix, &addr); - if (rde_filter(&asp, rules, peer, new->aspath, &addr, - new->prefix->prefixlen, new->aspath->peer, DIR_OUT) == - ACTION_DENY) { + if (rde_filter(peer->ribid, &asp, rules, peer, new->aspath, + &addr, new->prefix->prefixlen, new->aspath->peer, + DIR_OUT) == ACTION_DENY) { path_put(asp); up_generate_updates(rules, peer, NULL, old); return; @@ -473,8 +473,8 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer, bzero(&addr, sizeof(addr)); addr.af = af; - if (rde_filter(&fasp, rules, peer, asp, &addr, 0, NULL, DIR_OUT) == - ACTION_DENY) { + if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, + DIR_OUT) == ACTION_DENY) { path_put(fasp); path_put(asp); return; |