mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-02-03 18:49:28 -05:00
xfr: finalize timers and master serial only after commit
This commit is contained in:
parent
4c9feb2572
commit
7b2442cc0a
5 changed files with 66 additions and 44 deletions
|
|
@ -37,6 +37,7 @@ typedef struct {
|
|||
bool keys_changed;
|
||||
bool plan_ds_check;
|
||||
bool plan_dnskey_sync;
|
||||
bool zone_changed;
|
||||
} zone_sign_reschedule_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static void log_dnssec_next(const knot_dname_t *zone, knot_time_t refresh_at)
|
|||
}
|
||||
|
||||
void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
|
||||
const zone_sign_reschedule_t *refresh, bool zone_changed)
|
||||
const zone_sign_reschedule_t *refresh)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
time_t ignore = -1;
|
||||
|
|
@ -49,7 +49,7 @@ void event_dnssec_reschedule(conf_t *conf, zone_t *zone,
|
|||
ZONE_EVENT_DS_CHECK, refresh->plan_ds_check ? now : ignore,
|
||||
ZONE_EVENT_DNSKEY_SYNC, refresh->plan_dnskey_sync ? now + jitter : ignore
|
||||
);
|
||||
if (zone_changed) {
|
||||
if (refresh->zone_changed) {
|
||||
zone_schedule_notify(zone, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,6 @@ int event_dnssec(conf_t *conf, zone_t *zone)
|
|||
zone_sign_reschedule_t resch = { 0 };
|
||||
zone_sign_roll_flags_t r_flags = KEY_ROLL_ALLOW_ALL;
|
||||
int sign_flags = 0;
|
||||
bool zone_changed = false;
|
||||
|
||||
if (zone_get_flag(zone, ZONE_FORCE_RESIGN, true)) {
|
||||
log_zone_info(zone->name, "DNSSEC, dropping previous "
|
||||
|
|
@ -90,7 +89,9 @@ int event_dnssec(conf_t *conf, zone_t *zone)
|
|||
goto done;
|
||||
}
|
||||
|
||||
zone_changed = !zone_update_no_change(&up);
|
||||
resch.zone_changed = !zone_update_no_change(&up);
|
||||
|
||||
zone_update_set_post_commit(&up, (zone_update_commit_cb_t)event_dnssec_reschedule, &resch);
|
||||
|
||||
ret = zone_update_commit(conf, &up);
|
||||
if (ret != KNOT_EOK) {
|
||||
|
|
@ -98,9 +99,6 @@ int event_dnssec(conf_t *conf, zone_t *zone)
|
|||
}
|
||||
|
||||
done:
|
||||
// Schedule dependent events
|
||||
event_dnssec_reschedule(conf, zone, &resch, zone_changed);
|
||||
|
||||
if (ret != KNOT_EOK) {
|
||||
zone_update_clear(&up);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,10 +114,13 @@ struct refresh_data {
|
|||
enum state state; //!< Event processing state.
|
||||
enum xfr_type xfr_type; //!< Transfer type (mostly IXFR versus AXFR).
|
||||
bool axfr_style_ixfr; //!< Master responded with AXFR-style-IXFR.
|
||||
bool axfr_bootstrap;
|
||||
knot_rrset_t *initial_soa_copy; //!< Copy of the received initial SOA.
|
||||
struct xfr_stats stats; //!< Transfer statistics.
|
||||
struct timespec started; //!< When refresh started.
|
||||
size_t change_size; //!< Size of added and removed RRs.
|
||||
uint32_t old_serial;
|
||||
uint32_t master_serial;
|
||||
|
||||
struct {
|
||||
zone_contents_t *zone; //!< AXFR result, new zone.
|
||||
|
|
@ -330,19 +333,44 @@ static void axfr_slave_sign_serial(zone_contents_t *new_contents, zone_t *zone,
|
|||
zone_contents_set_soa_serial(new_contents, new_serial);
|
||||
}
|
||||
|
||||
static void post_commit(conf_t *conf, zone_t *zone, void *ctx)
|
||||
{
|
||||
struct refresh_data *data = ctx;
|
||||
conf_val_t val = conf_zone_get(data->conf, C_DNSSEC_SIGNING, data->zone->name);
|
||||
bool dnssec_enable = conf_bool(&val);
|
||||
|
||||
if (dnssec_enable && (data->xfr_type == XFR_TYPE_AXFR || !EMPTY_LIST(data->ixfr.changesets))) {
|
||||
int ret = zone_set_master_serial(data->zone, data->master_serial);
|
||||
if (ret != KNOT_EOK) {
|
||||
log_zone_warning(data->zone->name,
|
||||
"unable to save master serial, future transfers might be broken");
|
||||
}
|
||||
}
|
||||
|
||||
finalize_timers(data);
|
||||
xfr_log_publish(data, data->old_serial, zone_contents_serial(data->zone->contents),
|
||||
data->master_serial, dnssec_enable, data->axfr_bootstrap);
|
||||
|
||||
|
||||
if (data->xfr_type == XFR_TYPE_AXFR || data->old_serial != zone_contents_serial(data->zone->contents)) {
|
||||
data->fallback->remote = false;
|
||||
zone_set_last_master(data->zone, (const struct sockaddr_storage *)data->remote);
|
||||
}
|
||||
}
|
||||
|
||||
static int axfr_finalize(struct refresh_data *data)
|
||||
{
|
||||
zone_contents_t *new_zone = data->axfr.zone;
|
||||
|
||||
conf_val_t val = conf_zone_get(data->conf, C_DNSSEC_SIGNING, data->zone->name);
|
||||
bool dnssec_enable = conf_bool(&val);
|
||||
uint32_t old_serial = zone_contents_serial(data->zone->contents), master_serial = 0;
|
||||
bool bootstrap = (data->zone->contents == NULL);
|
||||
data->old_serial = zone_contents_serial(data->zone->contents);
|
||||
data->axfr_bootstrap = (data->zone->contents == NULL);
|
||||
zone_skip_t skip = { 0 };
|
||||
int ret = KNOT_EOK;
|
||||
|
||||
if (dnssec_enable) {
|
||||
axfr_slave_sign_serial(new_zone, data->zone, data->conf, &master_serial);
|
||||
axfr_slave_sign_serial(new_zone, data->zone, data->conf, &data->master_serial);
|
||||
ret = zone_skip_add_dnssec_diff(&skip);
|
||||
assert(ret == KNOT_EOK); // static size of zone_skip is enough to cover dnssec types
|
||||
}
|
||||
|
|
@ -388,6 +416,8 @@ static int axfr_finalize(struct refresh_data *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
zone_update_set_post_commit(&up, post_commit, data);
|
||||
|
||||
ret = zone_update_commit(data->conf, &up);
|
||||
if (ret != KNOT_EOK) {
|
||||
zone_update_clear(&up);
|
||||
|
|
@ -397,21 +427,6 @@ static int axfr_finalize(struct refresh_data *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (dnssec_enable) {
|
||||
ret = zone_set_master_serial(data->zone, master_serial);
|
||||
if (ret != KNOT_EOK) {
|
||||
log_zone_warning(data->zone->name,
|
||||
"unable to save master serial, future transfers might be broken");
|
||||
}
|
||||
}
|
||||
|
||||
finalize_timers(data);
|
||||
xfr_log_publish(data, old_serial, zone_contents_serial(data->zone->contents),
|
||||
master_serial, dnssec_enable, bootstrap);
|
||||
|
||||
data->fallback->remote = false;
|
||||
zone_set_last_master(data->zone, (const struct sockaddr_storage *)data->remote);
|
||||
|
||||
return KNOT_EOK;
|
||||
}
|
||||
|
||||
|
|
@ -595,10 +610,10 @@ static int ixfr_finalize(struct refresh_data *data)
|
|||
{
|
||||
conf_val_t val = conf_zone_get(data->conf, C_DNSSEC_SIGNING, data->zone->name);
|
||||
bool dnssec_enable = conf_bool(&val);
|
||||
uint32_t master_serial = 0, old_serial = zone_contents_serial(data->zone->contents);
|
||||
data->old_serial = zone_contents_serial(data->zone->contents);
|
||||
|
||||
if (dnssec_enable) {
|
||||
int ret = ixfr_slave_sign_serial(&data->ixfr.changesets, data->zone, data->conf, &master_serial);
|
||||
int ret = ixfr_slave_sign_serial(&data->ixfr.changesets, data->zone, data->conf, &data->master_serial);
|
||||
if (ret != KNOT_EOK) {
|
||||
IXFRIN_LOG(LOG_WARNING, data,
|
||||
"failed to adjust SOA serials from unsigned remote (%s)",
|
||||
|
|
@ -664,6 +679,8 @@ static int ixfr_finalize(struct refresh_data *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
zone_update_set_post_commit(&up, post_commit, data);
|
||||
|
||||
ret = zone_update_commit(data->conf, &up);
|
||||
if (ret != KNOT_EOK) {
|
||||
zone_update_clear(&up);
|
||||
|
|
@ -672,23 +689,6 @@ static int ixfr_finalize(struct refresh_data *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (dnssec_enable && !EMPTY_LIST(data->ixfr.changesets)) {
|
||||
ret = zone_set_master_serial(data->zone, master_serial);
|
||||
if (ret != KNOT_EOK) {
|
||||
log_zone_warning(data->zone->name,
|
||||
"unable to save master serial, future transfers might be broken");
|
||||
}
|
||||
}
|
||||
|
||||
finalize_timers(data);
|
||||
xfr_log_publish(data, old_serial, zone_contents_serial(data->zone->contents),
|
||||
master_serial, dnssec_enable, false);
|
||||
|
||||
if (old_serial != zone_contents_serial(data->zone->contents)) {
|
||||
data->fallback->remote = false;
|
||||
zone_set_last_master(data->zone, (const struct sockaddr_storage *)data->remote);
|
||||
}
|
||||
|
||||
return KNOT_EOK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1038,11 +1038,21 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
|
|||
zone_contents_serial(update->zone->contents));
|
||||
}
|
||||
|
||||
if (update->post_commit_cb != NULL) {
|
||||
update->post_commit_cb(conf, update->zone, update->post_commit_cb_ctx);
|
||||
}
|
||||
|
||||
memset(update, 0, sizeof(*update));
|
||||
|
||||
return KNOT_EOK;
|
||||
}
|
||||
|
||||
void zone_update_set_post_commit(zone_update_t *update, zone_update_commit_cb_t cb, void *cb_ctx)
|
||||
{
|
||||
update->post_commit_cb = cb;
|
||||
update->post_commit_cb_ctx = cb_ctx;
|
||||
}
|
||||
|
||||
bool zone_update_no_change(zone_update_t *update)
|
||||
{
|
||||
if (update == NULL) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ typedef struct {
|
|||
int warning;
|
||||
} dnssec_validation_hint_t;
|
||||
|
||||
typedef void (*zone_update_commit_cb_t)(conf_t *, zone_t *, void *);
|
||||
|
||||
/*! \brief Structure for zone contents updating / querying. */
|
||||
typedef struct zone_update {
|
||||
zone_t *zone; /*!< Zone being updated. */
|
||||
|
|
@ -29,6 +31,8 @@ typedef struct zone_update {
|
|||
changeset_t extra_ch; /*!< Extra changeset to store just diff btwn zonefile and result. */
|
||||
apply_ctx_t *a_ctx; /*!< Context for applying changesets. */
|
||||
uint32_t flags; /*!< Zone update flags. */
|
||||
void *post_commit_cb_ctx;
|
||||
zone_update_commit_cb_t post_commit_cb;
|
||||
dnssec_validation_hint_t validation_hint;
|
||||
} zone_update_t;
|
||||
|
||||
|
|
@ -278,6 +282,15 @@ int zone_update_verify_digest(conf_t *conf, zone_update_t *update);
|
|||
*/
|
||||
int zone_update_commit(conf_t *conf, zone_update_t *update);
|
||||
|
||||
/*!
|
||||
* \brief Set a callback to be called after successful zone_update_commit.
|
||||
*
|
||||
* \param update Zone update.
|
||||
* \param cb Callback.
|
||||
* \param cb_ctx Arbitrary context.
|
||||
*/
|
||||
void zone_update_set_post_commit(zone_update_t *update, zone_update_commit_cb_t cb, void *cb_ctx);
|
||||
|
||||
/*!
|
||||
* \brief Returns bool whether there are any changes at all.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in a new issue