static int axfr_answer_init(struct answer_data *data) { assert(data); /* Create new zone contents. */ zone_t *zone = data->param->zone; zone_contents_t *new_contents = zone_contents_new(zone->name); if (new_contents == NULL) { return KNOT_ENOMEM; } /* Create new processing context. */ struct xfr_proc *proc = mm_alloc(data->mm, sizeof(struct xfr_proc)); if (proc == NULL) { zone_contents_deep_free(&new_contents); return KNOT_ENOMEM; } memset(proc, 0, sizeof(struct xfr_proc)); proc->contents = new_contents; gettimeofday(&proc->tstamp, NULL); /* Set up cleanup callback. */ data->ext = proc; data->ext_cleanup = &axfr_answer_cleanup; return KNOT_EOK; }
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; }
static void axfr_answer_cleanup(struct answer_data *data) { assert(data != NULL); struct xfr_proc *proc = data->ext; if (proc) { zone_contents_deep_free(&proc->contents); mm_free(data->mm, proc); data->ext = NULL; } }
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_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; }