diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-03-11 14:22:24 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-03-11 14:22:24 +0000 |
commit | c55c70dd41eeeb9c88f187d86ec7050e887be7f4 (patch) | |
tree | 2733c660cdebc2d11318c89ad70d2333ff7ec8c8 | |
parent | 4711b14624e2746e8235e925b9df2b14b11db7f9 (diff) |
Shutdown the RDE cleanly on exit. Plug some memleaks. OK henning@
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 88 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_decide.c | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_prefix.c | 16 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 49 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 4 |
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); |