summaryrefslogtreecommitdiffstats
path: root/usr.sbin/eigrpd
diff options
context:
space:
mode:
authorrenato <renato@openbsd.org>2016-04-15 13:24:52 +0000
committerrenato <renato@openbsd.org>2016-04-15 13:24:52 +0000
commit3745c483a9ed7e1e39c12315167554c96d272842 (patch)
tree9c06e70e408b3d0698bcd454f4e72251a2dee896 /usr.sbin/eigrpd
parentMove several other variables out of eigrpd_conf. (diff)
downloadwireguard-openbsd-3745c483a9ed7e1e39c12315167554c96d272842.tar.xz
wireguard-openbsd-3745c483a9ed7e1e39c12315167554c96d272842.zip
Properly implement the clear_config() function.
We need to free the internal pointers of the eigrpd_conf struct, not only the main struct. This avoids memory leaks when a config reload happens to fail (e.g. due to a syntax error).
Diffstat (limited to 'usr.sbin/eigrpd')
-rw-r--r--usr.sbin/eigrpd/parse.y36
1 files changed, 35 insertions, 1 deletions
diff --git a/usr.sbin/eigrpd/parse.y b/usr.sbin/eigrpd/parse.y
index 5fa2ea58ba6..72d155bd76a 100644
--- a/usr.sbin/eigrpd/parse.y
+++ b/usr.sbin/eigrpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.12 2016/04/15 13:21:45 renato Exp $ */
+/* $OpenBSD: parse.y,v 1.13 2016/04/15 13:24:52 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -1129,9 +1129,43 @@ conf_get_if(struct kif *kif)
return (e);
}
+extern struct iface_id_head ifaces_by_id;
+RB_PROTOTYPE(iface_id_head, eigrp_iface, id_tree, iface_id_compare)
+
void
clear_config(struct eigrpd_conf *xconf)
{
+ struct eigrp *e;
+ struct redistribute *r;
+ struct eigrp_iface *i;
+ struct summary_addr *s;
+
+ while ((e = TAILQ_FIRST(&xconf->instances)) != NULL) {
+ while (!SIMPLEQ_EMPTY(&e->redist_list)) {
+ r = SIMPLEQ_FIRST(&e->redist_list);
+ SIMPLEQ_REMOVE_HEAD(&e->redist_list, entry);
+ free(r);
+ }
+
+ while ((i = TAILQ_FIRST(&e->ei_list)) != NULL) {
+ RB_REMOVE(iface_id_head, &ifaces_by_id, i);
+ TAILQ_REMOVE(&e->ei_list, i, e_entry);
+ TAILQ_REMOVE(&e->ei_list, i, i_entry);
+ while ((s = TAILQ_FIRST(&i->summary_list)) != NULL) {
+ TAILQ_REMOVE(&i->summary_list, s, entry);
+ free(s);
+ }
+ if (TAILQ_EMPTY(&i->iface->ei_list)) {
+ TAILQ_REMOVE(&xconf->iface_list, i->iface, entry);
+ free(i->iface);
+ }
+ free(i);
+ }
+
+ TAILQ_REMOVE(&xconf->instances, e, entry);
+ free(e);
+ }
+
free(xconf);
}