summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2004-03-11 14:22:24 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2004-03-11 14:22:24 +0000
commitc55c70dd41eeeb9c88f187d86ec7050e887be7f4 (patch)
tree2733c660cdebc2d11318c89ad70d2333ff7ec8c8
parent4711b14624e2746e8235e925b9df2b14b11db7f9 (diff)
Shutdown the RDE cleanly on exit. Plug some memleaks. OK henning@
-rw-r--r--usr.sbin/bgpd/bgpd.c5
-rw-r--r--usr.sbin/bgpd/rde.c88
-rw-r--r--usr.sbin/bgpd/rde.h5
-rw-r--r--usr.sbin/bgpd/rde_decide.c5
-rw-r--r--usr.sbin/bgpd/rde_prefix.c16
-rw-r--r--usr.sbin/bgpd/rde_rib.c49
-rw-r--r--usr.sbin/bgpd/session.h4
7 files changed, 160 insertions, 12 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 4d6082bf16e..6c2322ce6c4 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.85 2004/03/11 13:35:05 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.86 2004/03/11 14:22:22 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -195,7 +195,8 @@ main(int argc, char *argv[])
fatalx("control socket setup failed");
/* fork children */
- rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, pipe_m2r, pipe_s2r);
+ rde_pid = rde_main(&conf, peer_l, &net_l, rules_l, &mrt_l,
+ pipe_m2r, pipe_s2r);
io_pid = session_main(&conf, peer_l, &net_l, rules_l, &mrt_l,
pipe_m2s, pipe_s2r);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index b82b3ffeac8..cd08e4cdcfd 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.95 2004/03/10 14:29:37 henning Exp $ */
+/* $OpenBSD: rde.c,v 1.96 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -57,6 +57,7 @@ void rde_update_log(const char *,
void rde_update_queue_runner(void);
void peer_init(struct peer *, u_int32_t);
+void peer_shutdown(void);
struct rde_peer *peer_add(u_int32_t, struct peer_config *);
void peer_remove(struct rde_peer *);
struct rde_peer *peer_get(u_int32_t);
@@ -66,6 +67,8 @@ void peer_down(u_int32_t);
void network_init(struct network_head *);
void network_add(struct network_config *);
+void rde_shutdown(void);
+
volatile sig_atomic_t rde_quit = 0;
struct bgpd_config *conf, *nconf;
time_t reloadtime;
@@ -93,10 +96,11 @@ u_int32_t nexthophashsize = 64;
int
rde_main(struct bgpd_config *config, struct peer *peer_l,
struct network_head *net_l, struct filter_head *rules,
- int pipe_m2r[2], int pipe_s2r[2])
+ struct mrt_head *mrt_l, int pipe_m2r[2], int pipe_s2r[2])
{
pid_t pid;
struct passwd *pw;
+ struct mrt *m;
struct pollfd pfd[2];
int n, nfds;
@@ -139,6 +143,12 @@ rde_main(struct bgpd_config *config, struct peer *peer_l,
imsg_init(&ibuf_se, pipe_s2r[1]);
imsg_init(&ibuf_main, pipe_m2r[1]);
+ /* main mrt list is not used in the SE */
+ while ((m = LIST_FIRST(mrt_l)) != NULL) {
+ LIST_REMOVE(m, list);
+ free(m);
+ }
+
pt_init();
path_init(pathhashsize);
nexthop_init(nexthophashsize);
@@ -186,13 +196,15 @@ rde_main(struct bgpd_config *config, struct peer *peer_l,
rde_update_queue_runner();
}
+ rde_shutdown();
+
msgbuf_write(&ibuf_se.w);
msgbuf_clear(&ibuf_se.w);
msgbuf_write(&ibuf_main.w);
msgbuf_clear(&ibuf_main.w);
log_info("route decision engine exiting");
- _exit(0);
+ exit(0);
}
void
@@ -949,6 +961,18 @@ peer_init(struct peer *peer_l, u_int32_t hashsize)
peer_l = NULL;
}
+void
+peer_shutdown(void)
+{
+ u_int32_t i;
+
+ for (i = 0; i <= peertable.peer_hashmask; i++)
+ if (!LIST_EMPTY(&peertable.peer_hashtbl[i]))
+ log_warnx("peer_free: free non-free table");
+
+ free(peertable.peer_hashtbl);
+}
+
struct rde_peer *
peer_get(u_int32_t id)
{
@@ -1111,3 +1135,61 @@ network_add(struct network_config *nc)
path_update(&peerself, &attrs, &nc->prefix, nc->prefixlen);
}
+/* clean up */
+void
+rde_shutdown(void)
+{
+ struct rde_peer *p;
+ struct rde_aspath *asp, *nasp;
+ struct filter_rule *r;
+ u_int32_t i;
+
+ /*
+ * the decision process is turend of if rde_quit = 1 and
+ * rde_shutdown depends on this.
+ */
+ ENSURE(rde_quit != 0);
+
+ /* First mark all peer as down */
+ for (i = 0; i <= peertable.peer_hashmask; i++)
+ LIST_FOREACH(p, &peertable.peer_hashtbl[i], peer_l) {
+ p->remote_bgpid = 0;
+ p->state = PEER_DOWN;
+ up_down(p);
+ }
+ /*
+ * Now walk through the aspath list and remove everything.
+ * path_remove will also remove the prefixes and the pt_entries.
+ */
+ for (i = 0; i <= peertable.peer_hashmask; i++)
+ while ((p = LIST_FIRST(&peertable.peer_hashtbl[i])) != NULL) {
+ for (asp = LIST_FIRST(&p->path_h);
+ asp != NULL; asp = nasp) {
+ nasp = LIST_NEXT(asp, peer_l);
+ path_remove(asp);
+ }
+ /* finaly remove peer */
+ peer_remove(p);
+ }
+
+ /* free annoced network prefixes */
+ peerself.remote_bgpid = 0;
+ peerself.state = PEER_DOWN;
+ for (asp = LIST_FIRST(&peerself.path_h); asp != NULL; asp = nasp) {
+ nasp = LIST_NEXT(asp, peer_l);
+ path_remove(asp);
+ }
+
+ /* free filters */
+ while ((r = TAILQ_FIRST(rules_l)) != NULL) {
+ TAILQ_REMOVE(rules_l, r, entries);
+ free(r);
+ }
+ free(rules_l);
+
+ nexthop_shutdown();
+ path_shutdown();
+ pt_shutdown();
+ peer_shutdown();
+}
+
diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h
index 1822e578e34..6911a1556a7 100644
--- a/usr.sbin/bgpd/rde.h
+++ b/usr.sbin/bgpd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.34 2004/03/05 22:21:32 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.35 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -256,6 +256,7 @@ int aspath_match(struct aspath *, enum as_spec, u_int16_t);
/* rde_rib.c */
void path_init(u_int32_t);
+void path_shutdown(void);
void path_update(struct rde_peer *, struct attr_flags *,
struct bgpd_addr *, int);
struct rde_aspath *path_get(struct aspath *, struct rde_peer *);
@@ -275,6 +276,7 @@ void prefix_destroy(struct prefix *);
void prefix_network_clean(struct rde_peer *, time_t);
void nexthop_init(u_int32_t);
+void nexthop_shutdown(void);
void nexthop_add(struct rde_aspath *);
void nexthop_remove(struct rde_aspath *);
void nexthop_update(struct kroute_nexthop *);
@@ -292,6 +294,7 @@ void up_dump_upcall(struct pt_entry *, void *);
/* rde_prefix.c */
void pt_init(void);
+void pt_shutdown(void);
int pt_empty(struct pt_entry *);
struct pt_entry *pt_get(struct bgpd_addr *, int);
struct pt_entry *pt_add(struct bgpd_addr *, int);
diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c
index 9ba276be0ba..1372a879580 100644
--- a/usr.sbin/bgpd/rde_decide.c
+++ b/usr.sbin/bgpd/rde_decide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_decide.c,v 1.32 2004/03/01 16:02:01 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.33 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -195,7 +195,8 @@ prefix_evaluate(struct prefix *p, struct pt_entry *pte)
/* decision process is turned off */
if (p != NULL)
LIST_INSERT_HEAD(&pte->prefix_h, p, prefix_l);
- ENSURE(pte->active == NULL);
+ if (pte->active != NULL)
+ pte->active = NULL;
return;
}
diff --git a/usr.sbin/bgpd/rde_prefix.c b/usr.sbin/bgpd/rde_prefix.c
index 3fc87522bcc..347ababf3e0 100644
--- a/usr.sbin/bgpd/rde_prefix.c
+++ b/usr.sbin/bgpd/rde_prefix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_prefix.c,v 1.11 2004/03/02 19:29:01 claudio Exp $ */
+/* $OpenBSD: rde_prefix.c,v 1.12 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -116,6 +116,20 @@ pt_init(void)
}
}
+void
+pt_shutdown(void)
+{
+ int i;
+ u_int32_t j;
+
+ for (i = MIN_PREFIX; i <= MAX_PREFIX; i++) {
+ for (j = 0; j < pthashsize[i]; j++)
+ if (!LIST_EMPTY(&pttable[i].pt_hashtbl[j]))
+ log_warnx("pt_free: free non-free table [%d][%d]", i, j);
+ free(pttable[i].pt_hashtbl);
+ }
+}
+
int
pt_empty(struct pt_entry *pte)
{
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 9195432e080..e562dc09470 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.41 2004/03/05 22:21:32 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.42 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -100,6 +100,18 @@ path_init(u_int32_t hashsize)
}
void
+path_shutdown(void)
+{
+ u_int32_t i;
+
+ for (i = 0; i <= pathtable.path_hashmask; i++)
+ if (!LIST_EMPTY(&pathtable.path_hashtbl[i]))
+ log_warnx("path_free: free non-free table");
+
+ free(pathtable.path_hashtbl);
+}
+
+void
path_update(struct rde_peer *peer, struct attr_flags *attrs,
struct bgpd_addr *prefix, int prefixlen)
{
@@ -184,6 +196,10 @@ path_updateall(struct rde_aspath *asp, enum nexthop_state state)
{
RIB_STAT(path_updateall);
+ if (rde_noevaluate())
+ /* if the decision process is turned off this is a no-op */
+ return;
+
prefix_updateall(asp, state);
}
@@ -671,6 +687,30 @@ nexthop_init(u_int32_t hashsize)
}
void
+nexthop_shutdown(void)
+{
+ struct in_addr addr;
+ struct nexthop *nh;
+ u_int32_t i;
+
+ /* remove the dummy entry for connected networks */
+ addr.s_addr = INADDR_ANY;
+ nh = nexthop_get(addr);
+ if (nh != NULL) {
+ if (!LIST_EMPTY(&nh->path_h))
+ log_warnx("nexthop_free: free non-free announce node");
+ LIST_REMOVE(nh, nexthop_l);
+ nexthop_free(nh);
+ }
+
+ for (i = 0; i <= nexthoptable.nexthop_hashmask; i++)
+ if (!LIST_EMPTY(&nexthoptable.nexthop_hashtbl[i]))
+ log_warnx("nexthop_free: free non-free table");
+
+ free(nexthoptable.nexthop_hashtbl);
+}
+
+void
nexthop_add(struct rde_aspath *asp)
{
struct nexthop *nh;
@@ -765,6 +805,13 @@ nexthop_update(struct kroute_nexthop *msg)
if (msg->connected)
nh->flags |= NEXTHOP_CONNECTED;
+ if (rde_noevaluate())
+ /*
+ * if the decision process is turned off there is no need
+ * for the aspath list walk.
+ */
+ return;
+
LIST_FOREACH(asp, &nh->path_h, nexthop_l) {
path_updateall(asp, nh->state);
}
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index e6d5c1b795c..1a8becb38a4 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.38 2004/03/11 13:35:06 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.39 2004/03/11 14:22:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -195,7 +195,7 @@ int merge_config(struct bgpd_config *, struct bgpd_config *,
/* rde.c */
int rde_main(struct bgpd_config *, struct peer *, struct network_head *,
- struct filter_head *, int[2], int[2]);
+ struct filter_head *, struct mrt_head *, int[2], int[2]);
/* control.c */
int control_listen(void);