mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-09-12 12:57:42 +02:00
- auth-load-thread, process IXFR, by making a copy, adjust changes, swap in.
This commit is contained in:
@@ -358,6 +358,11 @@ auth_load_process_http(struct auth_load_thread* thr)
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
return 0;
|
||||
}
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xfr_http_preview(task->file, task->chunks_first);
|
||||
if(!xfr_http_syntax_check(task->name, task->namelen, task->dclass,
|
||||
@@ -366,6 +371,11 @@ auth_load_process_http(struct auth_load_thread* thr)
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
if(!xfr_apply_http(task->name, task->namelen, task->host, task->file,
|
||||
task->chunks_first, z, scratch_buffer)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
@@ -375,9 +385,140 @@ auth_load_process_http(struct auth_load_thread* thr)
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
if(z->rpz)
|
||||
rpz_finish_config(z->rpz);
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auth_load_swap_zone(thr, z);
|
||||
auth_zone_delete_proxy(z);
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Copy RRset and append it to the domain, update last pointer. */
|
||||
static int
|
||||
rrset_append_copy(struct auth_data* domain, struct auth_rrset* rrset,
|
||||
struct auth_rrset** last)
|
||||
{
|
||||
struct auth_rrset* s = calloc(1, sizeof(*s));
|
||||
if(!s)
|
||||
return 0;
|
||||
s->type = rrset->type;
|
||||
s->data = (struct packed_rrset_data*)memdup(rrset->data,
|
||||
packed_rrset_sizeof(rrset->data));
|
||||
if(!s->data)
|
||||
return 0;
|
||||
packed_rrset_ptr_fixup(s->data);
|
||||
if(!*last)
|
||||
domain->rrsets = s;
|
||||
else (*last)->next = s;
|
||||
*last = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Copy the existing zone for modification */
|
||||
static int
|
||||
auth_load_copy_into_zone(struct auth_load_thread* thr, struct auth_zone* proxyz)
|
||||
{
|
||||
int count = 0;
|
||||
struct auth_zone* z;
|
||||
struct auth_data* d;
|
||||
lock_rw_rdlock(&thr->task->worker->env.auth_zones->lock);
|
||||
z = auth_zone_find(thr->task->worker->env.auth_zones,
|
||||
thr->task->name, thr->task->namelen, thr->task->dclass);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
|
||||
verbose(VERB_ALGO, "auth zone missing for copy for IXFR.");
|
||||
return 0;
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
|
||||
|
||||
/* Copy from z into proxyz. */
|
||||
RBTREE_FOR(d, struct auth_data*, &z->data) {
|
||||
struct auth_rrset* rrset, *last = NULL;
|
||||
struct auth_data* proxy_d = az_domain_create(proxyz,
|
||||
d->name, d->namelen);
|
||||
if(!proxy_d) {
|
||||
log_err("out of memory");
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
for(rrset = d->rrsets; rrset; rrset=rrset->next) {
|
||||
if(!rrset_append_copy(proxy_d, rrset, &last)) {
|
||||
log_err("out of memory");
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
if((count++)%10000 == 0) {
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((count++)%10000 == 0) {
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Process ixfr transfer */
|
||||
static int
|
||||
auth_load_process_ixfr(struct auth_load_thread* thr)
|
||||
{
|
||||
struct auth_load_task* task = thr->task;
|
||||
struct sldns_buffer* scratch_buffer;
|
||||
struct auth_zone* z;
|
||||
|
||||
scratch_buffer = sldns_buffer_new(sldns_buffer_capacity(
|
||||
thr->task->worker->env.scratch_buffer));
|
||||
if(!scratch_buffer) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
z = auth_zone_create_proxy(task->name, task->namelen, task->dclass);
|
||||
if(!z) {
|
||||
log_err("out of memory");
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
return 0;
|
||||
}
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the existing zone for modification, that uses a read lock.
|
||||
* That then does not interrupt the service of threads. */
|
||||
if(!auth_load_copy_into_zone(thr, z)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
if(!xfr_apply_ixfr(task->chunks_first, task->serial, z,
|
||||
scratch_buffer)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
if(auth_load_thread_poll_for_quit(thr)) {
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
auth_zone_delete_proxy(z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auth_load_swap_zone(thr, z);
|
||||
auth_zone_delete_proxy(z);
|
||||
sldns_buffer_free(scratch_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -392,6 +533,8 @@ auth_load_thread_process(struct auth_load_thread* thr)
|
||||
if(!auth_load_process_http(thr))
|
||||
return 0;
|
||||
} else if(task->on_ixfr && !task->on_ixfr_is_axfr) {
|
||||
if(!auth_load_process_ixfr(thr))
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
return 1;
|
||||
|
||||
+16
-13
@@ -593,7 +593,7 @@ auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr)
|
||||
}
|
||||
|
||||
/** create domain with the given name */
|
||||
static struct auth_data*
|
||||
struct auth_data*
|
||||
az_domain_create(struct auth_zone* z, uint8_t* nm, size_t nmlen)
|
||||
{
|
||||
struct auth_data* n = (struct auth_data*)malloc(sizeof(*n));
|
||||
@@ -4823,10 +4823,10 @@ http_parse_add_rr(const char* host, const char* file, struct auth_zone* z,
|
||||
/** RR list iterator, returns RRs from answer section one by one from the
|
||||
* dns packets in the chunklist */
|
||||
static void
|
||||
chunk_rrlist_start(struct auth_xfer* xfr, struct auth_chunk** rr_chunk,
|
||||
chunk_rrlist_start(struct auth_chunk* chunk_list, struct auth_chunk** rr_chunk,
|
||||
int* rr_num, size_t* rr_pos)
|
||||
{
|
||||
*rr_chunk = xfr->task_transfer->chunks_first;
|
||||
*rr_chunk = chunk_list;
|
||||
*rr_num = 0;
|
||||
*rr_pos = 0;
|
||||
}
|
||||
@@ -4993,9 +4993,9 @@ ixfr_start_serial(struct auth_chunk* rr_chunk, int rr_num, size_t rr_pos,
|
||||
}
|
||||
|
||||
/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */
|
||||
static int
|
||||
apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
struct sldns_buffer* scratch_buffer)
|
||||
int
|
||||
xfr_apply_ixfr(struct auth_chunk* chunk_list, uint32_t xfr_serial,
|
||||
struct auth_zone* z, struct sldns_buffer* scratch_buffer)
|
||||
{
|
||||
struct auth_chunk* rr_chunk;
|
||||
int rr_num;
|
||||
@@ -5011,7 +5011,7 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
int softfail = 0;
|
||||
|
||||
/* start RR iterator over chunklist of packets */
|
||||
chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos);
|
||||
chunk_rrlist_start(chunk_list, &rr_chunk, &rr_num, &rr_pos);
|
||||
while(!chunk_rrlist_end(rr_chunk, rr_num)) {
|
||||
if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos,
|
||||
&rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen,
|
||||
@@ -5042,7 +5042,7 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
if(!ixfr_start_serial(rr_chunk, rr_num, rr_pos,
|
||||
rr_dname, rr_type, rr_class, rr_ttl,
|
||||
rr_rdlen, rr_rdata, rr_nextpos,
|
||||
transfer_serial, xfr->serial)) {
|
||||
transfer_serial, xfr_serial)) {
|
||||
return 0;
|
||||
}
|
||||
} else if(transfer_serial == serial) {
|
||||
@@ -5063,7 +5063,8 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
* SOA 3 followed by add
|
||||
* SOA 3 end */
|
||||
/* ended by SOA record */
|
||||
xfr->serial = transfer_serial;
|
||||
/* xfr->serial is set by xfr_find_soa
|
||||
* after this function. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5131,12 +5132,13 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
|
||||
/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */
|
||||
static int
|
||||
xfr_apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
struct sldns_buffer* scratch_buffer)
|
||||
{
|
||||
xfr->num_ixfrs++;
|
||||
|
||||
return apply_ixfr(xfr, z, scratch_buffer);
|
||||
return xfr_apply_ixfr(xfr->task_transfer->chunks_first, xfr->serial, z,
|
||||
scratch_buffer);
|
||||
}
|
||||
|
||||
/** apply AXFR to zone in memory. z is locked. false on failure(mallocfail) */
|
||||
@@ -5164,7 +5166,8 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
/* insert all RRs in to the zone */
|
||||
/* insert the SOA only once, skip the last one */
|
||||
/* start RR iterator over chunklist of packets */
|
||||
chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos);
|
||||
chunk_rrlist_start(xfr->task_transfer->chunks_first, &rr_chunk,
|
||||
&rr_num, &rr_pos);
|
||||
while(!chunk_rrlist_end(rr_chunk, rr_num)) {
|
||||
if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos,
|
||||
&rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen,
|
||||
@@ -5469,7 +5472,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
|
||||
}
|
||||
} else if(xfr->task_transfer->on_ixfr &&
|
||||
!xfr->task_transfer->on_ixfr_is_axfr) {
|
||||
if(!xfr_apply_ixfr(xfr, z, env->scratch_buffer)) {
|
||||
if(!apply_ixfr(xfr, z, env->scratch_buffer)) {
|
||||
auth_zone_clear_data(z);
|
||||
lock_rw_unlock(&z->lock);
|
||||
verbose(VERB_ALGO, "xfr from %s: could not store IXFR"
|
||||
|
||||
@@ -857,6 +857,10 @@ int chunkline_count_parens(struct sldns_buffer* buf, size_t start);
|
||||
/** Clear data in auth zone */
|
||||
void auth_zone_clear_data(struct auth_zone* z);
|
||||
|
||||
/** create domain with the given name */
|
||||
struct auth_data* az_domain_create(struct auth_zone* z, uint8_t* nm,
|
||||
size_t nmlen);
|
||||
|
||||
/** helper traverse to delete zones */
|
||||
void auth_data_del(rbnode_type* n, void* arg);
|
||||
|
||||
@@ -877,4 +881,8 @@ int xfr_apply_http(uint8_t* name, size_t namelen, const char* host,
|
||||
const char* file, struct auth_chunk* chunk_list, struct auth_zone* z,
|
||||
struct sldns_buffer* scratch_buffer);
|
||||
|
||||
/** Apply IXFR transfer to auth_zone */
|
||||
int xfr_apply_ixfr(struct auth_chunk* chunk_list, uint32_t xfr_serial,
|
||||
struct auth_zone* z, struct sldns_buffer* scratch_buffer);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
|
||||
Reference in New Issue
Block a user