summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2005-06-29 09:43:27 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2005-06-29 09:43:27 +0000
commit594757d5f959a472146827a74c37df70dae806f1 (patch)
treeb9f724ee6b9b82a70fa8e500966f6bd069c79992 /usr.sbin/bgpd
parent78885a9a4f071e782047df91843c9f08dfc7b24c (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.c25
-rw-r--r--usr.sbin/bgpd/bgpd.conf.59
-rw-r--r--usr.sbin/bgpd/bgpd.h12
-rw-r--r--usr.sbin/bgpd/name2id.c26
-rw-r--r--usr.sbin/bgpd/parse.y18
-rw-r--r--usr.sbin/bgpd/printconf.c9
-rw-r--r--usr.sbin/bgpd/rde.c7
-rw-r--r--usr.sbin/bgpd/rde.h5
-rw-r--r--usr.sbin/bgpd/rde_filter.c27
-rw-r--r--usr.sbin/bgpd/rde_rib.c10
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);