From d0aaffe65fa12a59c2ab29deee4470efb2fab333 Mon Sep 17 00:00:00 2001 From: Marek Vavrusa <marek.vavrusa@nic.cz> Date: Wed, 15 Aug 2012 13:21:41 +0200 Subject: [PATCH] Zone data takes ownership of the zone config, which is removed from the global conf(). This way it retains a valid pointer to it's configuration when server reloads and zone gets discarded. refs #1976 --- src/common/lists.h | 1 + src/knot/conf/conf.c | 138 +++++++++++++++++++--------------------- src/knot/conf/conf.h | 12 ++++ src/knot/server/zones.c | 26 +++++++- 4 files changed, 102 insertions(+), 75 deletions(-) diff --git a/src/common/lists.h b/src/common/lists.h index 972ea49efb..897b1a9407 100644 --- a/src/common/lists.h +++ b/src/common/lists.h @@ -71,6 +71,7 @@ typedef struct list { /* In fact two overlayed nodes */ WALK_LIST_DELSAFE(n,nxt,list) { \ free(n); \ } \ + init_list(&list); \ } while(0) void add_tail(list *, node *); diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 447f59a8aa..e0bd0ea5ce 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -73,74 +73,6 @@ void cf_error(void *scanner, const char *msg) _parser_res = KNOTD_EPARSEFAIL; } -/* - * Config helper functions. - */ - -/*! \brief Free TSIG key. */ -static void key_free(conf_key_t *k) -{ - /* Secure erase. */ - if (k->k.secret) { - memset(k->k.secret, 0, strlen(k->k.secret)); - } - free(k->k.secret); - knot_dname_free(&k->k.name); - free(k); -} - -/*! \brief Free config interfaces. */ -static void iface_free(conf_iface_t *iface) -{ - if (!iface) { - return; - } - - free(iface->name); - free(iface->address); - free(iface); -} - -/*! \brief Free config logs. */ -static void log_free(conf_log_t *log) -{ - if (!log) { - return; - } - - if (log->file) { - free(log->file); - } - - /* Free loglevel mapping. */ - node *n = 0, *nxt = 0; - WALK_LIST_DELSAFE(n, nxt, log->map) { - free((conf_log_map_t*)n); - } - - free(log); -} - -/*! \brief Free config zones. */ -static void zone_free(conf_zone_t *zone) -{ - if (!zone) { - return; - } - - /* Free ACL lists. */ - WALK_LIST_FREE(zone->acl.xfr_in); - WALK_LIST_FREE(zone->acl.xfr_out); - WALK_LIST_FREE(zone->acl.notify_in); - WALK_LIST_FREE(zone->acl.notify_out); - - free(zone->name); - free(zone->file); - free(zone->db); - free(zone->ixfr_db); - free(zone); -} - /*! * \brief Call config hooks that need updating. * @@ -574,33 +506,33 @@ void conf_truncate(conf_t *conf, int unload_hooks) // Free keys WALK_LIST_DELSAFE(n, nxt, conf->keys) { - key_free((conf_key_t *)n); + conf_free_key((conf_key_t *)n); } // Free interfaces WALK_LIST_DELSAFE(n, nxt, conf->ifaces) { - iface_free((conf_iface_t*)n); + conf_free_iface((conf_iface_t*)n); } conf->ifaces_count = 0; init_list(&conf->ifaces); // Free logs WALK_LIST_DELSAFE(n, nxt, conf->logs) { - log_free((conf_log_t*)n); + conf_free_log((conf_log_t*)n); } conf->logs_count = 0; init_list(&conf->logs); // Free remotes WALK_LIST_DELSAFE(n, nxt, conf->remotes) { - iface_free((conf_iface_t*)n); + conf_free_iface((conf_iface_t*)n); } conf->remotes_count = 0; init_list(&conf->remotes); // Free zones WALK_LIST_DELSAFE(n, nxt, conf->zones) { - zone_free((conf_zone_t*)n); + conf_free_zone((conf_zone_t*)n); } conf->zones_count = 0; init_list(&conf->zones); @@ -805,3 +737,63 @@ char* strcpath(char *path) return path; } +void conf_free_zone(conf_zone_t *zone) +{ + if (!zone) { + return; + } + + /* Free ACL lists. */ + WALK_LIST_FREE(zone->acl.xfr_in); + WALK_LIST_FREE(zone->acl.xfr_out); + WALK_LIST_FREE(zone->acl.notify_in); + WALK_LIST_FREE(zone->acl.notify_out); + + free(zone->name); + free(zone->file); + free(zone->db); + free(zone->ixfr_db); + free(zone); +} + +void conf_free_key(conf_key_t *k) +{ + /* Secure erase. */ + if (k->k.secret) { + memset(k->k.secret, 0, strlen(k->k.secret)); + } + free(k->k.secret); + knot_dname_free(&k->k.name); + free(k); +} + +void conf_free_iface(conf_iface_t *iface) +{ + if (!iface) { + return; + } + + free(iface->name); + free(iface->address); + free(iface); +} + +void conf_free_log(conf_log_t *log) +{ + if (!log) { + return; + } + + if (log->file) { + free(log->file); + } + + /* Free loglevel mapping. */ + node *n = 0, *nxt = 0; + WALK_LIST_DELSAFE(n, nxt, log->map) { + free((conf_log_map_t*)n); + } + + free(log); +} + diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index 3712e4b6b4..ae41454a53 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -349,6 +349,18 @@ char* strcdup(const char *s1, const char *s2); */ char* strcpath(char *path); +/*! \brief Free zone config. */ +void conf_free_zone(conf_zone_t *zone); + +/*! \brief Free TSIG key config. */ +void conf_free_key(conf_key_t *k); + +/*! \brief Free interface config. */ +void conf_free_iface(conf_iface_t *iface); + +/*! \brief Free log config. */ +void conf_free_log(conf_log_t *log); + #endif /* _KNOTD_CONF_H_ */ /*! @} */ diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index 2e9ff9100e..20a859e51d 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -118,6 +118,9 @@ static int zonedata_destroy(knot_zone_t *zone) /* Close IXFR db. */ journal_release(zd->ixfr_db); + + /* Free assigned config. */ + conf_free_zone(zd->conf); free(zd); @@ -1490,7 +1493,10 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst, assert(zd != NULL); /* Update refs. */ - zd->conf = z; + if (zd->conf != z) { + conf_free_zone(zd->conf); + zd->conf = z; + } /* Update ACLs. */ dbg_zones("Updating zone ACLs.\n"); @@ -1664,11 +1670,15 @@ static int zonewalker(dthread_t *thread) pthread_mutex_lock(&zw->lock); zw->inserted += inserted; for (int i = 0; i < inserted; ++i) { + zonedata_t *zd = (zonedata_t *)knot_zone_data(zones[i]); if (knot_zonedb_add_zone(zw->db_new, zones[i]) != KNOT_EOK) { - zonedata_t *zd = (zonedata_t *)knot_zone_data(zones[i]); log_server_error("Failed to insert zone '%s' " "into database.\n", zd->conf->name); knot_zone_deep_free(zones + i, 0); + } else { + /* Unlink zone config from conf(), + * transferring ownership to zonedata. */ + rem_node(&zd->conf->n); } } pthread_mutex_unlock(&zw->lock); @@ -1782,6 +1792,18 @@ dbg_zones_exec( "from database.\n", name); free(name); ); + /* Invalidate ACLs - since we would need to copy each + * remote data and keep ownership, I think it's no harm + * to drop all ACLs for the discarded zone. + * refs #1976 */ + zonedata_t *zd = (zonedata_t*)knot_zone_data(old_zone); + conf_zone_t *zconf = zd->conf; + WALK_LIST_FREE(zconf->acl.xfr_in); + WALK_LIST_FREE(zconf->acl.xfr_out); + WALK_LIST_FREE(zconf->acl.notify_in); + WALK_LIST_FREE(zconf->acl.notify_out); + + /* Remove from zone db. */ knot_zone_t * rm = knot_zonedb_remove_zone(db_old, knot_zone_name(old_zone)); assert(rm == old_zone); -- GitLab