diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2005-06-29 09:43:27 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2005-06-29 09:43:27 +0000 |
commit | 594757d5f959a472146827a74c37df70dae806f1 (patch) | |
tree | b9f724ee6b9b82a70fa8e500966f6bd069c79992 /usr.sbin/bgpd | |
parent | 78885a9a4f071e782047df91843c9f08dfc7b24c (diff) |
rtlabel support via filter sets. Just use "set rtlabel foobar" in filters
network and neighbor statements and the routes are labeled accordingly.
While doing that fix some mem-leaks by introducing filterset_free() and
remove the free on send option of send_filterset().
This took a bit longer because we need to carefully track the rtlabel id
refcnts or bad things may happen on reloads.
henning@ looks fine
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 25 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.conf.5 | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 12 | ||||
-rw-r--r-- | usr.sbin/bgpd/name2id.c | 26 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 18 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 27 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 10 |
10 files changed, 117 insertions, 31 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index 7ea56b8791d..88463c90ead 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.c,v 1.121 2005/06/09 15:32:03 claudio Exp $ */ +/* $OpenBSD: bgpd.c,v 1.122 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -41,7 +41,7 @@ __dead void usage(void); int main(int, char *[]); int check_child(pid_t, const char *); int send_filterset(struct imsgbuf *, struct filter_set_head *, - int, int); + int); int reconfigure(char *, struct bgpd_config *, struct mrt_head *, struct peer **, struct filter_head *); int dispatch_imsg(struct imsgbuf *, int); @@ -391,21 +391,14 @@ check_child(pid_t pid, const char *pname) } int -send_filterset(struct imsgbuf *i, struct filter_set_head *set, int id, int f) +send_filterset(struct imsgbuf *i, struct filter_set_head *set, int id) { struct filter_set *s; - for (s = SIMPLEQ_FIRST(set); s != NULL; ) { + SIMPLEQ_FOREACH(s, set, entry) if (imsg_compose(i, IMSG_FILTER_SET, id, 0, -1, s, sizeof(struct filter_set)) == -1) return (-1); - if (f) { - SIMPLEQ_REMOVE_HEAD(set, entry); - free(s); - s = SIMPLEQ_FIRST(set); - } else - s = SIMPLEQ_NEXT(s, entry); - } return (0); } @@ -444,19 +437,20 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, &p->conf, sizeof(struct peer_config)) == -1) return (-1); if (send_filterset(ibuf_se, &p->conf.attrset, - p->conf.id, 0) == -1) + p->conf.id) == -1) return (-1); } while ((n = TAILQ_FIRST(&net_l)) != NULL) { if (imsg_compose(ibuf_rde, IMSG_NETWORK_ADD, 0, 0, -1, &n->net, sizeof(struct network_config)) == -1) return (-1); - if (send_filterset(ibuf_rde, &n->net.attrset, 0, 1) == -1) + if (send_filterset(ibuf_rde, &n->net.attrset, 0) == -1) return (-1); if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) return (-1); TAILQ_REMOVE(&net_l, n, entry); + filterset_free(&n->net.attrset); free(n); } /* redistribute list needs to be reloaded too */ @@ -467,9 +461,10 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1, r, sizeof(struct filter_rule)) == -1) return (-1); - if (send_filterset(ibuf_rde, &r->set, 0, 1) == -1) + if (send_filterset(ibuf_rde, &r->set, 0) == -1) return (-1); TAILQ_REMOVE(rules_l, r, entry); + filterset_free(&r->set); free(r); } TAILQ_FOREACH(la, conf->listen_addrs, entry) { @@ -705,7 +700,7 @@ bgpd_redistribute(int type, struct kroute *kr, struct kroute6 *kr6) if (type == IMSG_NETWORK_REMOVE) return (1); - if (send_filterset(ibuf_rde, h, 0, 0) == -1) + if (send_filterset(ibuf_rde, h, 0) == -1) return (-1); if (imsg_compose(ibuf_rde, IMSG_NETWORK_DONE, 0, 0, -1, NULL, 0) == -1) return (-1); diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index e3288f1fed8..b642a54d326 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.56 2005/06/09 15:32:03 claudio Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.57 2005/06/29 09:43:25 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -897,7 +897,7 @@ set nexthop reject .It Ic pftable Ar table Add the prefix in the update to the specified .Xr pf 4 -radix table, regardless of whether or not the path was selected for routing. +table, regardless of whether or not the path was selected for routing. This option may be useful in building realtime blacklists. .Pp .It Ic prepend-neighbor Ar number @@ -912,6 +912,11 @@ Prepend the local AS times to the .Em AS path . .Pp +.It Ic rtlabel Ar label +Add the prefix with the specified +.Ar label +to the kernel routing table. +.Pp .It Ic weight Ar number The .Em weight diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 7da0089767e..2c888f73ba3 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.171 2005/06/28 12:12:34 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.172 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -578,18 +578,22 @@ enum action_types { ACTION_SET_NEXTHOP_NOMODIFY, ACTION_SET_COMMUNITY, /* ACTION_SCRUB_COMMUNITY, */ - ACTION_PFTABLE + ACTION_PFTABLE, + ACTION_RTLABEL, + ACTION_RTLABEL_ID }; struct filter_set { SIMPLEQ_ENTRY(filter_set) entry; union { u_int8_t prepend; + u_int16_t id; u_int32_t metric; int32_t relative; struct bgpd_addr nexthop; struct filter_community community; char pftable[PFTABLE_LEN]; + char rtlabel[RTLABEL_LEN]; } action; enum action_types type; }; @@ -702,6 +706,10 @@ int pftable_commit(void); u_int16_t rtlabel_name2id(char *); const char *rtlabel_id2name(u_int16_t); void rtlabel_unref(u_int16_t); +void rtlabel_ref(u_int16_t); + +/* rde_filter.c */ +void filterset_free(struct filter_set_head *); #endif /* __BGPD_H__ */ diff --git a/usr.sbin/bgpd/name2id.c b/usr.sbin/bgpd/name2id.c index 03eafdcc1d4..1ee5f50a8f0 100644 --- a/usr.sbin/bgpd/name2id.c +++ b/usr.sbin/bgpd/name2id.c @@ -1,4 +1,4 @@ -/* $OpenBSD: name2id.c,v 1.2 2005/06/25 16:26:25 claudio Exp $ */ +/* $OpenBSD: name2id.c,v 1.3 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -41,6 +41,7 @@ TAILQ_HEAD(n2id_labels, n2id_label); u_int16_t _name2id(struct n2id_labels *, const char *); const char *_id2name(struct n2id_labels *, u_int16_t); void _unref(struct n2id_labels *, u_int16_t); +void _ref(struct n2id_labels *, u_int16_t); int _exists(struct n2id_labels *, const char *); struct n2id_labels rt_labels = TAILQ_HEAD_INITIALIZER(rt_labels); @@ -64,6 +65,12 @@ rtlabel_unref(u_int16_t id) _unref(&rt_labels, id); } +void +rtlabel_ref(u_int16_t id) +{ + _ref(&rt_labels, id); +} + u_int16_t _name2id(struct n2id_labels *head, const char *name) { @@ -119,7 +126,7 @@ _id2name(struct n2id_labels *head, u_int16_t id) { struct n2id_label *label; - if (!id) + if (id == 0) return (""); TAILQ_FOREACH(label, head, entry) @@ -150,6 +157,21 @@ _unref(struct n2id_labels *head, u_int16_t id) } } +void +_ref(struct n2id_labels *head, u_int16_t id) +{ + struct n2id_label *label; + + if (id == 0) + return; + + TAILQ_FOREACH(label, head, entry) + if (label->id == id) { + ++label->ref; + break; + } +} + int _exists(struct n2id_labels *head, const char *name) { diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index b47d259100c..77feafffe5b 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.164 2005/06/09 15:32:03 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.165 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -153,7 +153,7 @@ typedef struct { %token CONNECTED STATIC %token PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY -%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT +%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL %token ERROR %token IPSEC ESP AH SPI IKE %token <v.string> STRING @@ -1357,6 +1357,19 @@ filter_set_opt : LOCALPREF number { } free($2); } + | RTLABEL string { + if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) + fatal(NULL); + $$->type = ACTION_RTLABEL; + if (strlcpy($$->action.rtlabel, $2, + sizeof($$->action.rtlabel)) >= + sizeof($$->action.rtlabel)) { + yyerror("rtlabel name too long"); + free($2); + YYERROR; + } + free($2); + } | COMMUNITY STRING { if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) fatal(NULL); @@ -1492,6 +1505,7 @@ lookup(char *s) { "route-collector", ROUTECOLL}, { "route-reflector", REFLECTOR}, { "router-id", ROUTERID}, + { "rtlabel", RTLABEL}, { "set", SET}, { "source-as", SOURCEAS}, { "spi", SPI}, diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 51e4076a0ba..564082e4961 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.42 2005/06/09 15:32:03 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.43 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -126,6 +126,13 @@ print_set(struct filter_set_head *set) case ACTION_PFTABLE: printf("pftable %s ", s->action.pftable); break; + case ACTION_RTLABEL: + printf("rtlabel %s ", s->action.rtlabel); + break; + case ACTION_RTLABEL_ID: + /* not possible */ + printf("rtlabel id %d ", s->action.id); + break; } } printf("}"); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index a2e485e0403..25716d6189d 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.162 2005/06/13 21:16:18 henning Exp $ */ +/* $OpenBSD: rde.c,v 1.163 2005/06/29 09:43:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -522,6 +522,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) prefix_network_clean(&peerself, reloadtime); while ((r = TAILQ_FIRST(rules_l)) != NULL) { TAILQ_REMOVE(rules_l, r, entry); + filterset_free(&r->set); free(r); } free(rules_l); @@ -1648,8 +1649,8 @@ rde_send_kroute(struct prefix *new, struct prefix *old) kl.kr.flags |= F_REJECT; if (p->aspath->flags & F_NEXTHOP_BLACKHOLE) kl.kr.flags |= F_BLACKHOLE; - /* XXX */ - strlcpy(kl.label, rtlabel_id2name(0), sizeof(kl.label)); + strlcpy(kl.label, rtlabel_id2name(p->aspath->rtlabelid), + sizeof(kl.label)); if (imsg_compose(ibuf_main, type, 0, 0, -1, &kl, sizeof(kl)) == -1) fatal("imsg_compose error"); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index a0862b3f9ec..a978171e899 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.65 2005/06/10 09:58:09 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.66 2005/06/29 09:43:26 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -162,7 +162,8 @@ struct rde_aspath { u_int32_t med; /* multi exit disc */ u_int32_t lpref; /* local pref */ u_int32_t weight; /* low prio lpref */ - u_int16_t flags; /* internally used */ + u_int16_t rtlabelid; /* route label id */ + u_int16_t flags; /* internally used */ u_int16_t prefix_cnt; /* # of prefixes */ u_int16_t active_cnt; /* # of active prefixes */ u_int8_t origin; diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index 756afc2afdd..1a6f2c5df72 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.27 2005/04/12 14:32:01 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.28 2005/06/29 09:43:26 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -191,6 +191,16 @@ rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh, strlcpy(asp->pftable, set->action.pftable, sizeof(asp->pftable)); break; + case ACTION_RTLABEL: + /* convert the route label to an id for faster access */ + set->action.id = rtlabel_name2id(set->action.rtlabel); + set->type = ACTION_RTLABEL_ID; + /* FALLTHROUGH */ + case ACTION_RTLABEL_ID: + rtlabel_unref(asp->rtlabelid); + asp->rtlabelid = set->action.id; + rtlabel_ref(asp->rtlabelid); + break; } } } @@ -289,3 +299,18 @@ rde_filter_community(struct rde_aspath *asp, int as, int type) return (community_match(a->data, a->len, as, type)); } + +void +filterset_free(struct filter_set_head *sh) +{ + struct filter_set *s; + + while ((s = SIMPLEQ_FIRST(sh)) != NULL) { + SIMPLEQ_REMOVE_HEAD(sh, entry); + if (s->type == ACTION_RTLABEL_ID) + rtlabel_unref(s->action.id); + free(s); + } + +} + diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 6a47462580e..61b36d56792 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.66 2005/04/12 14:32:01 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.67 2005/06/29 09:43:26 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -132,6 +132,10 @@ path_compare(struct rde_aspath *a, struct rde_aspath *b) return (1); if (a->weight < b->weight) return (-1); + if (a->rtlabelid > b->rtlabelid) + return (1); + if (a->rtlabelid < b->rtlabelid) + return (-1); r = strcmp(a->pftable, b->pftable); if (r == 0) @@ -272,6 +276,8 @@ path_copy(struct rde_aspath *asp) nasp->lpref = asp->lpref; nasp->weight = asp->weight; nasp->origin = asp->origin; + nasp->rtlabelid = asp->rtlabelid; + rtlabel_ref(nasp->rtlabelid); nasp->flags = asp->flags & ~F_ATTR_LINKED; @@ -296,6 +302,7 @@ path_get(void) asp->lpref = DEFAULT_LPREF; /* med = 0 */ /* weight = 0 */ + /* rtlabel = 0 */ return (asp); } @@ -307,6 +314,7 @@ path_put(struct rde_aspath *asp) if (asp->flags & F_ATTR_LINKED) fatalx("path_put: linked object"); + rtlabel_unref(asp->rtlabelid); aspath_put(asp->aspath); attr_optfree(asp); free(asp); |