summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-05-28 22:07:55 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-05-28 22:07:55 +0000
commit726de3291890e1627458e3144ae99d4e6c54b52c (patch)
tree6c8bf716686044b1e1d765abbe0f4d8aaf73c1f9
parent7d4bab594e4f26163c21a61f675c729dbbb130ec (diff)
Preload and pin nexthop used in filtersets so the are validiated when used.
This will fix problems with set nexthop on outgoing filters. Found by gluk@ OK henning@
-rw-r--r--usr.sbin/bgpd/rde.c27
-rw-r--r--usr.sbin/bgpd/rde.h3
-rw-r--r--usr.sbin/bgpd/rde_filter.c14
-rw-r--r--usr.sbin/bgpd/rde_rib.c5
4 files changed, 45 insertions, 4 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 2b7dd2ab9e5..0ae7ccf70b2 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.205 2006/04/21 08:55:21 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.206 2006/05/28 22:07:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -126,6 +126,9 @@ rde_main(struct bgpd_config *config, struct peer *peer_l,
struct peer *p;
struct listen_addr *la;
struct pollfd pfd[3];
+ struct filter_rule *f;
+ struct filter_set *set;
+ struct nexthop *nh;
int i;
switch (pid = fork()) {
@@ -201,6 +204,15 @@ rde_main(struct bgpd_config *config, struct peer *peer_l,
log_info("route decision engine ready");
+ TAILQ_FOREACH(f, rules, entry) {
+ TAILQ_FOREACH(set, &f->set, entry) {
+ if (set->type == ACTION_SET_NEXTHOP) {
+ nh = nexthop_get(&set->action.nexthop);
+ nh->refcnt++;
+ }
+ }
+ }
+
while (rde_quit == 0) {
bzero(pfd, sizeof(pfd));
pfd[PFD_PIPE_MAIN].fd = ibuf_main->fd;
@@ -280,6 +292,7 @@ rde_dispatch_imsg_session(struct imsgbuf *ibuf)
struct rde_peer *peer;
struct session_up sup;
struct filter_set *s;
+ struct nexthop *nh;
pid_t pid;
int n;
sa_family_t af = AF_UNSPEC;
@@ -393,6 +406,11 @@ badnet:
fatal(NULL);
memcpy(s, imsg.data, sizeof(struct filter_set));
TAILQ_INSERT_TAIL(session_set, s, entry);
+
+ if (s->type == ACTION_SET_NEXTHOP) {
+ nh = nexthop_get(&s->action.nexthop);
+ nh->refcnt++;
+ }
break;
case IMSG_CTL_SHOW_NETWORK:
if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(af)) {
@@ -474,6 +492,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
struct filter_rule *r;
struct filter_set *s;
struct mrt *xmrt;
+ struct nexthop *nh;
int n, reconf_in = 0, reconf_out = 0;
if ((n = imsg_read(ibuf)) == -1)
@@ -593,6 +612,11 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
fatal(NULL);
memcpy(s, imsg.data, sizeof(struct filter_set));
TAILQ_INSERT_TAIL(parent_set, s, entry);
+
+ if (s->type == ACTION_SET_NEXTHOP) {
+ nh = nexthop_get(&s->action.nexthop);
+ nh->refcnt++;
+ }
break;
case IMSG_MRT_OPEN:
case IMSG_MRT_REOPEN:
@@ -2439,6 +2463,7 @@ rde_shutdown(void)
/* free filters */
while ((r = TAILQ_FIRST(rules_l)) != NULL) {
TAILQ_REMOVE(rules_l, r, entry);
+ filterset_free(&r->set);
free(r);
}
free(rules_l);
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 198e8c4700c..bb3c0e9d6ce 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.93 2006/04/12 14:05:46 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.94 2006/05/28 22:07:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -201,6 +201,7 @@ struct nexthop {
*/
u_int32_t costs;
#endif
+ int refcnt; /* filterset reference counter */
enum nexthop_state state;
u_int8_t nexthop_netlen;
u_int8_t flags;
diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c
index 887e60efaba..12eaa717876 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.48 2006/04/26 17:13:14 claudio Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.49 2006/05/28 22:07:54 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@@ -428,6 +428,7 @@ void
filterset_free(struct filter_set_head *sh)
{
struct filter_set *s;
+ struct nexthop *nh;
while ((s = TAILQ_FIRST(sh)) != NULL) {
TAILQ_REMOVE(sh, s, entry);
@@ -435,6 +436,17 @@ filterset_free(struct filter_set_head *sh)
rtlabel_unref(s->action.id);
else if (s->type == ACTION_PFTABLE_ID)
pftable_unref(s->action.id);
+ else if (s->type == ACTION_SET_NEXTHOP &&
+ bgpd_process == PROC_RDE) {
+ nh = nexthop_get(&s->action.nexthop);
+ if (--nh->refcnt <= 0 && LIST_EMPTY(&nh->path_h)) {
+ LIST_REMOVE(nh, nexthop_l);
+ rde_send_nexthop(&nh->exit_nexthop, 0);
+
+ rdemem.nexthop_cnt--;
+ free(nh);
+ }
+ }
free(s);
}
}
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 2d93bdfe1f8..a566c0288ad 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.85 2006/04/04 12:03:26 henning Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.86 2006/05/28 22:07:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -918,6 +918,9 @@ nexthop_unlink(struct rde_aspath *asp)
nh = asp->nexthop;
asp->nexthop = NULL;
+ if (nh->refcnt > 0)
+ return;
+
if (LIST_EMPTY(&nh->path_h)) {
LIST_REMOVE(nh, nexthop_l);
rde_send_nexthop(&nh->exit_nexthop, 0);