static int axfr_answer_finalize(struct answer_data *adata) { struct timeval now; gettimeofday(&now, NULL); /* * Adjust zone so that node count is set properly and nodes are * marked authoritative / delegation point. */ struct xfr_proc *proc = adata->ext; int rc = zone_contents_adjust_full(proc->contents, NULL, NULL); if (rc != KNOT_EOK) { return rc; } /* Switch contents. */ zone_t *zone = adata->param->zone; zone_contents_t *old_contents = zone_switch_contents(zone, proc->contents); synchronize_rcu(); AXFRIN_LOG(LOG_INFO, "finished, " "serial %u -> %u, %.02f seconds, %u messages, %u bytes", zone_contents_serial(old_contents), zone_contents_serial(proc->contents), time_diff(&proc->tstamp, &now) / 1000.0, proc->npkts, proc->nbytes); /* Do not free new contents with cleanup. */ zone_contents_deep_free(&old_contents); proc->contents = NULL; return KNOT_EOK; }
int event_expire(conf_t *conf, zone_t *zone) { assert(zone); zone_contents_t *expired = zone_switch_contents(zone, NULL); synchronize_rcu(); /* Expire zonefile information. */ zone->zonefile_mtime = 0; zone->zonefile_serial = 0; zone->flags |= ZONE_EXPIRED; zone_contents_deep_free(&expired); log_zone_info(zone->name, "zone expired"); /* Trim extra heap. */ mem_trim(); return KNOT_EOK; }
int event_dnssec(conf_t *conf, zone_t *zone) { assert(zone); changeset_t ch; int ret = changeset_init(&ch, zone->name); if (ret != KNOT_EOK) { goto done; } uint32_t refresh_at = time(NULL); int sign_flags = 0; if (zone->flags & ZONE_FORCE_RESIGN) { log_zone_info(zone->name, "DNSSEC, dropping previous " "signatures, resigning zone"); zone->flags &= ~ZONE_FORCE_RESIGN; sign_flags = ZONE_SIGN_DROP_SIGNATURES; } else { log_zone_info(zone->name, "DNSSEC, signing zone"); sign_flags = 0; } ret = knot_dnssec_zone_sign(zone->contents, &ch, sign_flags, &refresh_at); if (ret != KNOT_EOK) { goto done; } bool zone_changed = !changeset_empty(&ch); if (zone_changed) { /* Apply change. */ apply_ctx_t a_ctx = { { 0 } }; apply_init_ctx(&a_ctx); zone_contents_t *new_contents = NULL; int ret = apply_changeset(&a_ctx, zone, &ch, &new_contents); if (ret != KNOT_EOK) { log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)", knot_strerror(ret)); goto done; } /* Write change to journal. */ ret = zone_change_store(conf, zone, &ch); if (ret != KNOT_EOK) { log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)", knot_strerror(ret)); update_rollback(&a_ctx); update_free_zone(&new_contents); goto done; } /* Switch zone contents. */ zone_contents_t *old_contents = zone_switch_contents(zone, new_contents); zone->flags &= ~ZONE_EXPIRED; synchronize_rcu(); update_free_zone(&old_contents); update_cleanup(&a_ctx); } // Schedule dependent events. schedule_dnssec(zone, refresh_at); if (zone_changed) { zone_events_schedule(zone, ZONE_EVENT_NOTIFY, ZONE_EVENT_NOW); conf_val_t val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name); if (conf_int(&val) == 0) { zone_events_schedule(zone, ZONE_EVENT_FLUSH, ZONE_EVENT_NOW); } } done: changeset_clear(&ch); return ret; }
int event_load(conf_t *conf, zone_t *zone) { assert(zone); /* Take zone file mtime and load it. */ char *filename = conf_zonefile(conf, zone->name); time_t mtime = zonefile_mtime(filename); free(filename); uint32_t dnssec_refresh = time(NULL); zone_contents_t *contents = NULL; int ret = zone_load_contents(conf, zone->name, &contents); if (ret != KNOT_EOK) { goto fail; } /* Store zonefile serial and apply changes from the journal. */ zone->zonefile_serial = zone_contents_serial(contents); ret = zone_load_journal(conf, zone, contents); if (ret != KNOT_EOK) { goto fail; } /* Post load actions - calculate delta, sign with DNSSEC... */ /*! \todo issue #242 dnssec signing should occur in the special event */ ret = zone_load_post(conf, zone, contents, &dnssec_refresh); if (ret != KNOT_EOK) { if (ret == KNOT_ESPACE) { log_zone_error(zone->name, "journal size is too small " "to fit the changes"); } else { log_zone_error(zone->name, "failed to store changes into " "journal (%s)", knot_strerror(ret)); } goto fail; } /* Check zone contents consistency. */ ret = zone_load_check(conf, contents); if (ret != KNOT_EOK) { goto fail; } /* Everything went alright, switch the contents. */ zone->zonefile_mtime = mtime; zone_contents_t *old = zone_switch_contents(zone, contents); zone->flags &= ~ZONE_EXPIRED; uint32_t old_serial = zone_contents_serial(old); if (old != NULL) { synchronize_rcu(); zone_contents_deep_free(&old); } /* Schedule notify and refresh after load. */ if (zone_is_slave(conf, zone)) { zone_events_schedule(zone, ZONE_EVENT_REFRESH, ZONE_EVENT_NOW); } if (!zone_contents_is_empty(contents)) { zone_events_schedule(zone, ZONE_EVENT_NOTIFY, ZONE_EVENT_NOW); zone->bootstrap_retry = ZONE_EVENT_NOW; } /* Schedule zone resign. */ conf_val_t val = conf_zone_get(conf, C_DNSSEC_SIGNING, zone->name); if (conf_bool(&val)) { schedule_dnssec(zone, dnssec_refresh); } /* Periodic execution. */ val = conf_zone_get(conf, C_ZONEFILE_SYNC, zone->name); int64_t sync_timeout = conf_int(&val); if (sync_timeout >= 0) { zone_events_schedule(zone, ZONE_EVENT_FLUSH, sync_timeout); } uint32_t current_serial = zone_contents_serial(zone->contents); log_zone_info(zone->name, "loaded, serial %u -> %u", old_serial, current_serial); return KNOT_EOK; fail: zone_contents_deep_free(&contents); /* Try to bootstrap the zone if local error. */ if (zone_is_slave(conf, zone) && !zone_events_is_scheduled(zone, ZONE_EVENT_XFER)) { zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW); } return ret; }