"Fossies" - the Fresh Open Source Software Archive

Member "nsd-4.3.6/difffile.c" (6 Apr 2021, 62339 Bytes) of package /linux/misc/dns/nsd-4.3.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * difffile.c - DIFF file handling source code. Read and write diff files.
    3  *
    4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
    5  *
    6  * See LICENSE for the license.
    7  *
    8  */
    9 
   10 #include "config.h"
   11 #include <assert.h>
   12 #include <string.h>
   13 #include <unistd.h>
   14 #include <stdlib.h>
   15 #include <errno.h>
   16 #include "difffile.h"
   17 #include "xfrd-disk.h"
   18 #include "util.h"
   19 #include "packet.h"
   20 #include "rdata.h"
   21 #include "udb.h"
   22 #include "udbzone.h"
   23 #include "nsec3.h"
   24 #include "nsd.h"
   25 #include "rrl.h"
   26 
   27 static int
   28 write_64(FILE *out, uint64_t val)
   29 {
   30     return write_data(out, &val, sizeof(val));
   31 }
   32 
   33 static int
   34 write_32(FILE *out, uint32_t val)
   35 {
   36     val = htonl(val);
   37     return write_data(out, &val, sizeof(val));
   38 }
   39 
   40 static int
   41 write_8(FILE *out, uint8_t val)
   42 {
   43     return write_data(out, &val, sizeof(val));
   44 }
   45 
   46 static int
   47 write_str(FILE *out, const char* str)
   48 {
   49     uint32_t len = strlen(str);
   50     if(!write_32(out, len))
   51         return 0;
   52     return write_data(out, str, len);
   53 }
   54 
   55 void
   56 diff_write_packet(const char* zone, const char* pat, uint32_t old_serial,
   57     uint32_t new_serial, uint32_t seq_nr, uint8_t* data, size_t len,
   58     struct nsd* nsd, uint64_t filenumber)
   59 {
   60     FILE* df = xfrd_open_xfrfile(nsd, filenumber, seq_nr?"a":"w");
   61     if(!df) {
   62         log_msg(LOG_ERR, "could not open transfer %s file %lld: %s",
   63             zone, (long long)filenumber, strerror(errno));
   64         return;
   65     }
   66 
   67     /* if first part, first write the header */
   68     if(seq_nr == 0) {
   69         struct timeval tv;
   70         if (gettimeofday(&tv, NULL) != 0) {
   71             log_msg(LOG_ERR, "could not get timestamp for %s: %s",
   72                 zone, strerror(errno));
   73         }
   74         if(!write_32(df, DIFF_PART_XFRF) ||
   75             !write_8(df, 0) /* notcommitted(yet) */ ||
   76             !write_32(df, 0) /* numberofparts when done */ ||
   77             !write_64(df, (uint64_t) tv.tv_sec) ||
   78             !write_32(df, (uint32_t) tv.tv_usec) ||
   79             !write_32(df, old_serial) ||
   80             !write_32(df, new_serial) ||
   81             !write_64(df, (uint64_t) tv.tv_sec) ||
   82             !write_32(df, (uint32_t) tv.tv_usec) ||
   83             !write_str(df, zone) ||
   84             !write_str(df, pat)) {
   85             log_msg(LOG_ERR, "could not write transfer %s file %lld: %s",
   86                 zone, (long long)filenumber, strerror(errno));
   87             fclose(df);
   88             return;
   89         }
   90     }
   91 
   92     if(!write_32(df, DIFF_PART_XXFR) ||
   93         !write_32(df, len) ||
   94         !write_data(df, data, len) ||
   95         !write_32(df, len))
   96     {
   97         log_msg(LOG_ERR, "could not write transfer %s file %lld: %s",
   98             zone, (long long)filenumber, strerror(errno));
   99     }
  100     fclose(df);
  101 }
  102 
  103 void
  104 diff_write_commit(const char* zone, uint32_t old_serial, uint32_t new_serial,
  105     uint32_t num_parts, uint8_t commit, const char* log_str,
  106     struct nsd* nsd, uint64_t filenumber)
  107 {
  108     struct timeval tv;
  109     FILE* df;
  110 
  111     if (gettimeofday(&tv, NULL) != 0) {
  112         log_msg(LOG_ERR, "could not set timestamp for %s: %s",
  113             zone, strerror(errno));
  114     }
  115 
  116     /* overwrite the first part of the file with 'committed = 1', 
  117      * as well as the end_time and number of parts.
  118      * also write old_serial and new_serial, so that a bad file mixup
  119      * will result in unusable serial numbers. */
  120 
  121     df = xfrd_open_xfrfile(nsd, filenumber, "r+");
  122     if(!df) {
  123         log_msg(LOG_ERR, "could not open transfer %s file %lld: %s",
  124             zone, (long long)filenumber, strerror(errno));
  125         return;
  126     }
  127     if(!write_32(df, DIFF_PART_XFRF) ||
  128         !write_8(df, commit) /* committed */ ||
  129         !write_32(df, num_parts) ||
  130         !write_64(df, (uint64_t) tv.tv_sec) ||
  131         !write_32(df, (uint32_t) tv.tv_usec) ||
  132         !write_32(df, old_serial) ||
  133         !write_32(df, new_serial))
  134     {
  135         log_msg(LOG_ERR, "could not write transfer %s file %lld: %s",
  136             zone, (long long)filenumber, strerror(errno));
  137         fclose(df);
  138         return;
  139     }
  140 
  141     /* append the log_str to the end of the file */
  142     if(fseek(df, 0, SEEK_END) == -1) {
  143         log_msg(LOG_ERR, "could not fseek transfer %s file %lld: %s",
  144             zone, (long long)filenumber, strerror(errno));
  145         fclose(df);
  146         return;
  147     }
  148     if(!write_str(df, log_str)) {
  149         log_msg(LOG_ERR, "could not write transfer %s file %lld: %s",
  150             zone, (long long)filenumber, strerror(errno));
  151         fclose(df);
  152         return;
  153 
  154     }
  155     fflush(df);
  156     fclose(df);
  157 }
  158 
  159 int
  160 diff_read_64(FILE *in, uint64_t* result)
  161 {
  162     if (fread(result, sizeof(*result), 1, in) == 1) {
  163         return 1;
  164     } else {
  165         return 0;
  166     }
  167 }
  168 
  169 int
  170 diff_read_32(FILE *in, uint32_t* result)
  171 {
  172     if (fread(result, sizeof(*result), 1, in) == 1) {
  173         *result = ntohl(*result);
  174         return 1;
  175     } else {
  176         return 0;
  177     }
  178 }
  179 
  180 int
  181 diff_read_8(FILE *in, uint8_t* result)
  182 {
  183         if (fread(result, sizeof(*result), 1, in) == 1) {
  184                 return 1;
  185         } else {
  186                 return 0;
  187         }
  188 }
  189 
  190 int
  191 diff_read_str(FILE* in, char* buf, size_t len)
  192 {
  193     uint32_t disklen;
  194     if(!diff_read_32(in, &disklen))
  195         return 0;
  196     if(disklen >= len)
  197         return 0;
  198     if(fread(buf, disklen, 1, in) != 1)
  199         return 0;
  200     buf[disklen] = 0;
  201     return 1;
  202 }
  203 
  204 static void
  205 add_rdata_to_recyclebin(namedb_type* db, rr_type* rr)
  206 {
  207     /* add rdatas to recycle bin. */
  208     size_t i;
  209     for(i=0; i<rr->rdata_count; i++)
  210     {
  211         if(!rdata_atom_is_domain(rr->type, i))
  212             region_recycle(db->region, rr->rdatas[i].data,
  213                 rdata_atom_size(rr->rdatas[i])
  214                 + sizeof(uint16_t));
  215     }
  216     region_recycle(db->region, rr->rdatas,
  217         sizeof(rdata_atom_type)*rr->rdata_count);
  218 }
  219 
  220 /* this routine determines if below a domain there exist names with
  221  * data (is_existing) or no names below the domain have data.
  222  */
  223 static int
  224 has_data_below(domain_type* top)
  225 {
  226     domain_type* d = top;
  227     assert(d != NULL);
  228     /* in the canonical ordering subdomains are after this name */
  229     d = domain_next(d);
  230     while(d != NULL && domain_is_subdomain(d, top)) {
  231         if(d->is_existing)
  232             return 1;
  233         d = domain_next(d);
  234     }
  235     return 0;
  236 }
  237 
  238 /** check if domain with 0 rrsets has become empty (nonexist) */
  239 static domain_type*
  240 rrset_zero_nonexist_check(domain_type* domain, domain_type* ce)
  241 {
  242     /* is the node now an empty node (completely deleted) */
  243     if(domain->rrsets == 0) {
  244         /* if there is no data below it, it becomes non existing.
  245            also empty nonterminals above it become nonexisting */
  246         /* check for data below this node. */
  247         if(!has_data_below(domain)) {
  248             /* nonexist this domain and all parent empty nonterminals */
  249             domain_type* p = domain;
  250             while(p != NULL && p->rrsets == 0) {
  251                 if(p == ce || has_data_below(p))
  252                     return p;
  253                 p->is_existing = 0;
  254                 /* fixup wildcard child of parent */
  255                 if(p->parent &&
  256                     p->parent->wildcard_child_closest_match == p)
  257                     p->parent->wildcard_child_closest_match = domain_previous_existing_child(p);
  258                 p = p->parent;
  259             }
  260         }
  261     }
  262     return NULL;
  263 }
  264 
  265 /** remove rrset.  Adjusts zone params.  Does not remove domain */
  266 static void
  267 rrset_delete(namedb_type* db, domain_type* domain, rrset_type* rrset)
  268 {
  269     int i;
  270     /* find previous */
  271     rrset_type** pp = &domain->rrsets;
  272     while(*pp && *pp != rrset) {
  273         pp = &( (*pp)->next );
  274     }
  275     if(!*pp) {
  276         /* rrset does not exist for domain */
  277         return;
  278     }
  279     *pp = rrset->next;
  280 
  281     DEBUG(DEBUG_XFRD,2, (LOG_INFO, "delete rrset of %s type %s",
  282         domain_to_string(domain),
  283         rrtype_to_string(rrset_rrtype(rrset))));
  284 
  285     /* is this a SOA rrset ? */
  286     if(rrset->zone->soa_rrset == rrset) {
  287         rrset->zone->soa_rrset = 0;
  288     }
  289     if(rrset->zone->ns_rrset == rrset) {
  290         rrset->zone->ns_rrset = 0;
  291     }
  292     if(domain == rrset->zone->apex && rrset_rrtype(rrset) == TYPE_RRSIG) {
  293         for (i = 0; i < rrset->rr_count; ++i) {
  294             if(rr_rrsig_type_covered(&rrset->rrs[i])==TYPE_DNSKEY) {
  295                 rrset->zone->is_secure = 0;
  296                 break;
  297             }
  298         }
  299     }
  300     /* recycle the memory space of the rrset */
  301     for (i = 0; i < rrset->rr_count; ++i)
  302         add_rdata_to_recyclebin(db, &rrset->rrs[i]);
  303     region_recycle(db->region, rrset->rrs,
  304         sizeof(rr_type) * rrset->rr_count);
  305     rrset->rr_count = 0;
  306     region_recycle(db->region, rrset, sizeof(rrset_type));
  307 }
  308 
  309 static int
  310 rdatas_equal(rdata_atom_type *a, rdata_atom_type *b, int num, uint16_t type,
  311     int* rdnum, char** reason)
  312 {
  313     int k, start, end;
  314     start = 0;
  315     end = num;
  316     /**
  317      * SOA RDATA comparisons in XFR are more lenient,
  318      * only serial rdata is checked.
  319      **/
  320     if (type == TYPE_SOA) {
  321         start = 2;
  322         end = 3;
  323     }
  324     for(k = start; k < end; k++)
  325     {
  326         if(rdata_atom_is_domain(type, k)) {
  327             if(dname_compare(domain_dname(a[k].domain),
  328                 domain_dname(b[k].domain))!=0) {
  329                 *rdnum = k;
  330                 *reason = "dname data";
  331                 return 0;
  332             }
  333         } else if(rdata_atom_is_literal_domain(type, k)) {
  334             /* literal dname, but compare case insensitive */
  335             if(a[k].data[0] != b[k].data[0]) {
  336                 *rdnum = k;
  337                 *reason = "literal dname len";
  338                 return 0; /* uncompressed len must be equal*/
  339             }
  340             if(!dname_equal_nocase((uint8_t*)(a[k].data+1),
  341                 (uint8_t*)(b[k].data+1), a[k].data[0])) {
  342                 *rdnum = k;
  343                 *reason = "literal dname data";
  344                 return 0;
  345             }
  346         } else {
  347             /* check length */
  348             if(a[k].data[0] != b[k].data[0]) {
  349                 *rdnum = k;
  350                 *reason = "rdata len";
  351                 return 0;
  352             }
  353             /* check data */
  354             if(memcmp(a[k].data+1, b[k].data+1, a[k].data[0])!=0) {
  355                 *rdnum = k;
  356                 *reason = "rdata data";
  357                 return 0;
  358             }
  359         }
  360     }
  361     return 1;
  362 }
  363 
  364 static void
  365 debug_find_rr_num(rrset_type* rrset, uint16_t type, uint16_t klass,
  366     rdata_atom_type *rdatas, ssize_t rdata_num)
  367 {
  368     int i, rd;
  369     char* reason = "";
  370 
  371     for(i=0; i < rrset->rr_count; ++i) {
  372         if (rrset->rrs[i].type != type) {
  373             log_msg(LOG_WARNING, "diff: RR <%s, %s> does not match "
  374                 "RR num %d type %s",
  375                 dname_to_string(domain_dname(rrset->rrs[i].owner),0),
  376                 rrtype_to_string(type), i,
  377                 rrtype_to_string(rrset->rrs[i].type));
  378         }
  379         if (rrset->rrs[i].klass != klass) {
  380             log_msg(LOG_WARNING, "diff: RR <%s, %s> class %d "
  381                 "does not match RR num %d class %d",
  382                 dname_to_string(domain_dname(rrset->rrs[i].owner),0),
  383                 rrtype_to_string(type),
  384                 klass, i,
  385                 rrset->rrs[i].klass);
  386         }
  387         if (rrset->rrs[i].rdata_count != rdata_num) {
  388             log_msg(LOG_WARNING, "diff: RR <%s, %s> rdlen %u "
  389                 "does not match RR num %d rdlen %d",
  390                 dname_to_string(domain_dname(rrset->rrs[i].owner),0),
  391                 rrtype_to_string(type),
  392                 (unsigned) rdata_num, i,
  393                 (unsigned) rrset->rrs[i].rdata_count);
  394         }
  395         if (!rdatas_equal(rdatas, rrset->rrs[i].rdatas, rdata_num, type,
  396             &rd, &reason)) {
  397             log_msg(LOG_WARNING, "diff: RR <%s, %s> rdata element "
  398                 "%d differs from RR num %d rdata (%s)",
  399                 dname_to_string(domain_dname(rrset->rrs[i].owner),0),
  400                 rrtype_to_string(type),
  401                 rd, i, reason);
  402         }
  403     }
  404 }
  405 
  406 static int
  407 find_rr_num(rrset_type* rrset, uint16_t type, uint16_t klass,
  408     rdata_atom_type *rdatas, ssize_t rdata_num, int add)
  409 {
  410     int i, rd;
  411     char* reason;
  412 
  413     for(i=0; i < rrset->rr_count; ++i) {
  414         if(rrset->rrs[i].type == type &&
  415            rrset->rrs[i].klass == klass &&
  416            rrset->rrs[i].rdata_count == rdata_num &&
  417            rdatas_equal(rdatas, rrset->rrs[i].rdatas, rdata_num, type,
  418             &rd, &reason))
  419         {
  420             return i;
  421         }
  422     }
  423         /* this is odd. Log why rr cannot be found. */
  424     if (!add) {
  425         debug_find_rr_num(rrset, type, klass, rdatas, rdata_num);
  426     }
  427     return -1;
  428 }
  429 
  430 #ifdef NSEC3
  431 /* see if nsec3 deletion triggers need action */
  432 static void
  433 nsec3_delete_rr_trigger(namedb_type* db, rr_type* rr, zone_type* zone,
  434     udb_ptr* udbz)
  435 {
  436     /* the RR has not actually been deleted yet, so we can inspect it */
  437     if(!zone->nsec3_param)
  438         return;
  439     /* see if the domain was an NSEC3-domain in the chain, but no longer */
  440     if(rr->type == TYPE_NSEC3 && rr->owner->nsec3 &&
  441         rr->owner->nsec3->nsec3_node.key &&
  442         nsec3_rr_uses_params(rr, zone) &&
  443         nsec3_in_chain_count(rr->owner, zone) <= 1) {
  444         domain_type* prev = nsec3_chain_find_prev(zone, rr->owner);
  445         /* remove from prehash because no longer an NSEC3 domain */
  446         if(domain_is_prehash(db->domains, rr->owner))
  447             prehash_del(db->domains, rr->owner);
  448         /* fixup the last in the zone */
  449         if(rr->owner == zone->nsec3_last)
  450             zone->nsec3_last = prev;
  451         /* unlink from the nsec3tree */
  452         zone_del_domain_in_hash_tree(zone->nsec3tree,
  453             &rr->owner->nsec3->nsec3_node);
  454         /* add previous NSEC3 to the prehash list */
  455         if(prev && prev != rr->owner)
  456             prehash_add(db->domains, prev);
  457         else    nsec3_clear_precompile(db, zone);
  458         /* this domain becomes ordinary data domain: done later */
  459     }
  460     /* see if the rr was NSEC3PARAM that we were using */
  461     else if(rr->type == TYPE_NSEC3PARAM && rr == zone->nsec3_param) {
  462         /* clear trees, wipe hashes, wipe precompile */
  463         nsec3_clear_precompile(db, zone);
  464         /* pick up new nsec3param (from udb, or avoid deleted rr) */
  465         nsec3_find_zone_param(db, zone, udbz, rr, 0);
  466         /* if no more NSEC3, done */
  467         if(!zone->nsec3_param)
  468             return;
  469         nsec3_precompile_newparam(db, zone);
  470     }
  471 }
  472 
  473 /* see if nsec3 prehash can be removed with new rrset content */
  474 static void
  475 nsec3_rrsets_changed_remove_prehash(domain_type* domain, zone_type* zone)
  476 {
  477     /* deletion of rrset already done, we can check if conditions apply */
  478     /* see if the domain is no longer precompiled */
  479     /* it has a hash_node, but no longer fulfills conditions */
  480     if(nsec3_domain_part_of_zone(domain, zone) && domain->nsec3 &&
  481         domain->nsec3->hash_wc &&
  482         domain->nsec3->hash_wc->hash.node.key &&
  483         !nsec3_condition_hash(domain, zone)) {
  484         /* remove precompile */
  485         domain->nsec3->nsec3_cover = NULL;
  486         domain->nsec3->nsec3_wcard_child_cover = NULL;
  487         domain->nsec3->nsec3_is_exact = 0;
  488         /* remove it from the hash tree */
  489         zone_del_domain_in_hash_tree(zone->hashtree,
  490             &domain->nsec3->hash_wc->hash.node);
  491         zone_del_domain_in_hash_tree(zone->wchashtree,
  492             &domain->nsec3->hash_wc->wc.node);
  493     }
  494     if(domain != zone->apex && domain->nsec3 &&
  495         domain->nsec3->ds_parent_hash &&
  496         domain->nsec3->ds_parent_hash->node.key &&
  497         (!domain->parent || nsec3_domain_part_of_zone(domain->parent, zone)) &&
  498         !nsec3_condition_dshash(domain, zone)) {
  499         /* remove precompile */
  500         domain->nsec3->nsec3_ds_parent_cover = NULL;
  501         domain->nsec3->nsec3_ds_parent_is_exact = 0;
  502         /* remove it from the hash tree */
  503         zone_del_domain_in_hash_tree(zone->dshashtree,
  504             &domain->nsec3->ds_parent_hash->node);
  505     }
  506 }
  507 
  508 /* see if domain needs to get precompiled info */
  509 static void
  510 nsec3_rrsets_changed_add_prehash(namedb_type* db, domain_type* domain,
  511     zone_type* zone)
  512 {
  513     if(!zone->nsec3_param)
  514         return;
  515     if((!domain->nsec3 || !domain->nsec3->hash_wc
  516                        || !domain->nsec3->hash_wc->hash.node.key)
  517         && nsec3_condition_hash(domain, zone)) {
  518         region_type* tmpregion = region_create(xalloc, free);
  519         nsec3_precompile_domain(db, domain, zone, tmpregion);
  520         region_destroy(tmpregion);
  521     }
  522     if((!domain->nsec3 || !domain->nsec3->ds_parent_hash
  523                        || !domain->nsec3->ds_parent_hash->node.key)
  524         && nsec3_condition_dshash(domain, zone)) {
  525         nsec3_precompile_domain_ds(db, domain, zone);
  526     }
  527 }
  528 
  529 /* see if nsec3 rrset-deletion triggers need action */
  530 static void
  531 nsec3_delete_rrset_trigger(namedb_type* db, domain_type* domain,
  532     zone_type* zone, uint16_t type)
  533 {
  534     if(!zone->nsec3_param)
  535         return;
  536     nsec3_rrsets_changed_remove_prehash(domain, zone);
  537     /* for type nsec3, or a delegation, the domain may have become a
  538      * 'normal' domain with its remaining data now */
  539     if(type == TYPE_NSEC3 || type == TYPE_NS || type == TYPE_DS)
  540         nsec3_rrsets_changed_add_prehash(db, domain, zone);
  541     /* for type DNAME or a delegation, obscured data may be revealed */
  542     if(type == TYPE_NS || type == TYPE_DS || type == TYPE_DNAME) {
  543         /* walk over subdomains and check them each */
  544         domain_type *d;
  545         for(d=domain_next(domain); d && domain_is_subdomain(d, domain);
  546             d=domain_next(d)) {
  547             nsec3_rrsets_changed_add_prehash(db, d, zone);
  548         }
  549     }
  550 }
  551 
  552 /* see if nsec3 addition triggers need action */
  553 static void
  554 nsec3_add_rr_trigger(namedb_type* db, rr_type* rr, zone_type* zone,
  555     udb_ptr* udbz)
  556 {
  557     /* the RR has been added in full, also to UDB (and thus NSEC3PARAM 
  558      * in the udb has been adjusted) */
  559     if(zone->nsec3_param && rr->type == TYPE_NSEC3 &&
  560         (!rr->owner->nsec3 || !rr->owner->nsec3->nsec3_node.key)
  561         && nsec3_rr_uses_params(rr, zone)) {
  562         /* added NSEC3 into the chain */
  563         nsec3_precompile_nsec3rr(db, rr->owner, zone);
  564         /* the domain has become an NSEC3-domain, if it was precompiled
  565          * previously, remove that, neatly done in routine above */
  566         nsec3_rrsets_changed_remove_prehash(rr->owner, zone);
  567         /* set this NSEC3 to prehash */
  568         prehash_add(db->domains, rr->owner);
  569     } else if(!zone->nsec3_param && rr->type == TYPE_NSEC3PARAM) {
  570         /* see if this means NSEC3 chain can be used */
  571         nsec3_find_zone_param(db, zone, udbz, NULL, 0);
  572         if(!zone->nsec3_param)
  573             return;
  574         nsec3_zone_trees_create(db->region, zone);
  575         nsec3_precompile_newparam(db, zone);
  576     }
  577 }
  578 
  579 /* see if nsec3 rrset-addition triggers need action */
  580 static void
  581 nsec3_add_rrset_trigger(namedb_type* db, domain_type* domain, zone_type* zone,
  582     uint16_t type)
  583 {
  584     /* the rrset has been added so we can inspect it */
  585     if(!zone->nsec3_param)
  586         return;
  587     /* because the rrset is added we can check conditions easily.
  588      * check if domain needs to become precompiled now */
  589     nsec3_rrsets_changed_add_prehash(db, domain, zone);
  590     /* if a delegation, it changes from normal name to unhashed referral */
  591     if(type == TYPE_NS || type == TYPE_DS) {
  592         nsec3_rrsets_changed_remove_prehash(domain, zone);
  593     }
  594     /* if delegation or DNAME added, then some RRs may get obscured */
  595     if(type == TYPE_NS || type == TYPE_DS || type == TYPE_DNAME) {
  596         /* walk over subdomains and check them each */
  597         domain_type *d;
  598         for(d=domain_next(domain); d && domain_is_subdomain(d, domain);
  599             d=domain_next(d)) {
  600             nsec3_rrsets_changed_remove_prehash(d, zone);
  601         }
  602     }
  603 }
  604 #endif /* NSEC3 */
  605 
  606 /* fixup usage lower for domain names in the rdata */
  607 static void
  608 rr_lower_usage(namedb_type* db, rr_type* rr)
  609 {
  610     unsigned i;
  611     for(i=0; i<rr->rdata_count; i++) {
  612         if(rdata_atom_is_domain(rr->type, i)) {
  613             assert(rdata_atom_domain(rr->rdatas[i])->usage > 0);
  614             rdata_atom_domain(rr->rdatas[i])->usage --;
  615             if(rdata_atom_domain(rr->rdatas[i])->usage == 0)
  616                 domain_table_deldomain(db,
  617                     rdata_atom_domain(rr->rdatas[i]));
  618         }
  619     }
  620 }
  621 
  622 static void
  623 rrset_lower_usage(namedb_type* db, rrset_type* rrset)
  624 {
  625     unsigned i;
  626     for(i=0; i<rrset->rr_count; i++)
  627         rr_lower_usage(db, &rrset->rrs[i]);
  628 }
  629 
  630 int
  631 delete_RR(namedb_type* db, const dname_type* dname,
  632     uint16_t type, uint16_t klass,
  633     buffer_type* packet, size_t rdatalen, zone_type *zone,
  634     region_type* temp_region, udb_ptr* udbz, int* softfail)
  635 {
  636     domain_type *domain;
  637     rrset_type *rrset;
  638     domain = domain_table_find(db->domains, dname);
  639     if(!domain) {
  640         log_msg(LOG_WARNING, "diff: domain %s does not exist",
  641             dname_to_string(dname,0));
  642         buffer_skip(packet, rdatalen);
  643         *softfail = 1;
  644         return 1; /* not fatal error */
  645     }
  646     rrset = domain_find_rrset(domain, zone, type);
  647     if(!rrset) {
  648         log_msg(LOG_WARNING, "diff: rrset %s does not exist",
  649             dname_to_string(dname,0));
  650         buffer_skip(packet, rdatalen);
  651         *softfail = 1;
  652         return 1; /* not fatal error */
  653     } else {
  654         /* find the RR in the rrset */
  655         domain_table_type *temptable;
  656         rdata_atom_type *rdatas;
  657         ssize_t rdata_num;
  658         int rrnum;
  659         temptable = domain_table_create(temp_region);
  660         /* This will ensure that the dnames in rdata are
  661          * normalized, conform RFC 4035, section 6.2
  662          */
  663         rdata_num = rdata_wireformat_to_rdata_atoms(
  664             temp_region, temptable, type, rdatalen, packet, &rdatas);
  665         if(rdata_num == -1) {
  666             log_msg(LOG_ERR, "diff: bad rdata for %s",
  667                 dname_to_string(dname,0));
  668             return 0;
  669         }
  670         rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num, 0);
  671         if(rrnum == -1 && type == TYPE_SOA && domain == zone->apex
  672             && rrset->rr_count != 0)
  673             rrnum = 0; /* replace existing SOA if no match */
  674         if(rrnum == -1) {
  675             log_msg(LOG_WARNING, "diff: RR <%s, %s> does not exist",
  676                 dname_to_string(dname,0), rrtype_to_string(type));
  677             *softfail = 1;
  678             return 1; /* not fatal error */
  679         }
  680         /* delete the normalized RR from the udb */
  681         if(db->udb)
  682             udb_del_rr(db->udb, udbz, &rrset->rrs[rrnum]);
  683 #ifdef NSEC3
  684         /* process triggers for RR deletions */
  685         nsec3_delete_rr_trigger(db, &rrset->rrs[rrnum], zone, udbz);
  686 #endif
  687         /* lower usage (possibly deleting other domains, and thus
  688          * invalidating the current RR's domain pointers) */
  689         rr_lower_usage(db, &rrset->rrs[rrnum]);
  690         if(rrset->rr_count == 1) {
  691             /* delete entire rrset */
  692             rrset_delete(db, domain, rrset);
  693             /* check if domain is now nonexisting (or parents) */
  694             rrset_zero_nonexist_check(domain, NULL);
  695 #ifdef NSEC3
  696             /* cleanup nsec3 */
  697             nsec3_delete_rrset_trigger(db, domain, zone, type);
  698 #endif
  699             /* see if the domain can be deleted (and inspect parents) */
  700             domain_table_deldomain(db, domain);
  701         } else {
  702             /* swap out the bad RR and decrease the count */
  703             rr_type* rrs_orig = rrset->rrs;
  704             add_rdata_to_recyclebin(db, &rrset->rrs[rrnum]);
  705             if(rrnum < rrset->rr_count-1)
  706                 rrset->rrs[rrnum] = rrset->rrs[rrset->rr_count-1];
  707             memset(&rrset->rrs[rrset->rr_count-1], 0, sizeof(rr_type));
  708             /* realloc the rrs array one smaller */
  709             rrset->rrs = region_alloc_array_init(db->region, rrs_orig,
  710                 (rrset->rr_count-1), sizeof(rr_type));
  711             if(!rrset->rrs) {
  712                 log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
  713                 exit(1);
  714             }
  715             region_recycle(db->region, rrs_orig,
  716                 sizeof(rr_type) * rrset->rr_count);
  717 #ifdef NSEC3
  718             if(type == TYPE_NSEC3PARAM && zone->nsec3_param) {
  719                 /* fixup nsec3_param pointer to same RR */
  720                 assert(zone->nsec3_param >= rrs_orig &&
  721                     zone->nsec3_param <=
  722                     rrs_orig+rrset->rr_count);
  723                 /* last moved to rrnum, others at same index*/
  724                 if(zone->nsec3_param == &rrs_orig[
  725                     rrset->rr_count-1])
  726                     zone->nsec3_param = &rrset->rrs[rrnum];
  727                 else
  728                     zone->nsec3_param =
  729                         (void*)zone->nsec3_param
  730                         -(void*)rrs_orig +
  731                         (void*)rrset->rrs;
  732             }
  733 #endif /* NSEC3 */
  734             rrset->rr_count --;
  735 #ifdef NSEC3
  736             /* for type nsec3, the domain may have become a
  737              * 'normal' domain with its remaining data now */
  738             if(type == TYPE_NSEC3)
  739                 nsec3_rrsets_changed_add_prehash(db, domain,
  740                     zone);
  741 #endif /* NSEC3 */
  742         }
  743     }
  744     return 1;
  745 }
  746 
  747 int
  748 add_RR(namedb_type* db, const dname_type* dname,
  749     uint16_t type, uint16_t klass, uint32_t ttl,
  750     buffer_type* packet, size_t rdatalen, zone_type *zone, udb_ptr* udbz,
  751     int* softfail)
  752 {
  753     domain_type* domain;
  754     rrset_type* rrset;
  755     rdata_atom_type *rdatas;
  756     rr_type *rrs_old;
  757     ssize_t rdata_num;
  758     int rrnum;
  759 #ifdef NSEC3
  760     int rrset_added = 0;
  761 #endif
  762     domain = domain_table_find(db->domains, dname);
  763     if(!domain) {
  764         /* create the domain */
  765         domain = domain_table_insert(db->domains, dname);
  766     }
  767     rrset = domain_find_rrset(domain, zone, type);
  768     if(!rrset) {
  769         /* create the rrset */
  770         rrset = region_alloc(db->region, sizeof(rrset_type));
  771         if(!rrset) {
  772             log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
  773             exit(1);
  774         }
  775         rrset->zone = zone;
  776         rrset->rrs = 0;
  777         rrset->rr_count = 0;
  778         domain_add_rrset(domain, rrset);
  779 #ifdef NSEC3
  780         rrset_added = 1;
  781 #endif
  782     }
  783 
  784     /* dnames in rdata are normalized, conform RFC 4035,
  785      * Section 6.2
  786      */
  787     rdata_num = rdata_wireformat_to_rdata_atoms(
  788         db->region, db->domains, type, rdatalen, packet, &rdatas);
  789     if(rdata_num == -1) {
  790         log_msg(LOG_ERR, "diff: bad rdata for %s",
  791             dname_to_string(dname,0));
  792         return 0;
  793     }
  794     rrnum = find_rr_num(rrset, type, klass, rdatas, rdata_num, 1);
  795     if(rrnum != -1) {
  796         DEBUG(DEBUG_XFRD, 2, (LOG_ERR, "diff: RR <%s, %s> already exists",
  797             dname_to_string(dname,0), rrtype_to_string(type)));
  798         /* ignore already existing RR: lenient accepting of messages */
  799         *softfail = 1;
  800         return 1;
  801     }
  802     if(rrset->rr_count == 65535) {
  803         log_msg(LOG_ERR, "diff: too many RRs at %s",
  804             dname_to_string(dname,0));
  805         return 0;
  806     }
  807 
  808     /* re-alloc the rrs and add the new */
  809     rrs_old = rrset->rrs;
  810     rrset->rrs = region_alloc_array(db->region,
  811         (rrset->rr_count+1), sizeof(rr_type));
  812     if(!rrset->rrs) {
  813         log_msg(LOG_ERR, "out of memory, %s:%d", __FILE__, __LINE__);
  814         exit(1);
  815     }
  816     if(rrs_old)
  817         memcpy(rrset->rrs, rrs_old, rrset->rr_count * sizeof(rr_type));
  818     region_recycle(db->region, rrs_old, sizeof(rr_type) * rrset->rr_count);
  819     rrset->rr_count ++;
  820 
  821     rrset->rrs[rrset->rr_count - 1].owner = domain;
  822     rrset->rrs[rrset->rr_count - 1].rdatas = rdatas;
  823     rrset->rrs[rrset->rr_count - 1].ttl = ttl;
  824     rrset->rrs[rrset->rr_count - 1].type = type;
  825     rrset->rrs[rrset->rr_count - 1].klass = klass;
  826     rrset->rrs[rrset->rr_count - 1].rdata_count = rdata_num;
  827 
  828     /* see if it is a SOA */
  829     if(domain == zone->apex) {
  830         apex_rrset_checks(db, rrset, domain);
  831 #ifdef NSEC3
  832         if(type == TYPE_NSEC3PARAM && zone->nsec3_param) {
  833             /* the pointer just changed, fix it up to point
  834              * to the same record */
  835             assert(zone->nsec3_param >= rrs_old &&
  836                 zone->nsec3_param < rrs_old+rrset->rr_count);
  837             /* in this order to make sure no overflow/underflow*/
  838             zone->nsec3_param = (void*)zone->nsec3_param - 
  839                 (void*)rrs_old + (void*)rrset->rrs;
  840         }
  841 #endif /* NSEC3 */
  842     }
  843 
  844     /* write the just-normalized RR to the udb */
  845     if(db->udb) {
  846         if(!udb_write_rr(db->udb, udbz, &rrset->rrs[rrset->rr_count - 1])) {
  847             log_msg(LOG_ERR, "could not add RR to nsd.db, disk-space?");
  848             return 0;
  849         }
  850     }
  851 #ifdef NSEC3
  852     if(rrset_added) {
  853         domain_type* p = domain->parent;
  854         nsec3_add_rrset_trigger(db, domain, zone, type);
  855         /* go up and process (possibly created) empty nonterminals, 
  856          * until we hit the apex or root */
  857         while(p && p->rrsets == NULL && !p->is_apex) {
  858             nsec3_rrsets_changed_add_prehash(db, p, zone);
  859             p = p->parent;
  860         }
  861     }
  862     nsec3_add_rr_trigger(db, &rrset->rrs[rrset->rr_count - 1], zone, udbz);
  863 #endif /* NSEC3 */
  864     return 1;
  865 }
  866 
  867 static zone_type*
  868 find_or_create_zone(namedb_type* db, const dname_type* zone_name,
  869     struct nsd_options* opt, const char* zstr, const char* patname)
  870 {
  871     zone_type* zone;
  872     struct zone_options* zopt;
  873     zone = namedb_find_zone(db, zone_name);
  874     if(zone) {
  875         return zone;
  876     }
  877     zopt = zone_options_find(opt, zone_name);
  878     if(!zopt) {
  879         /* if _implicit_ then insert as _part_of_config */
  880         if(strncmp(patname, PATTERN_IMPLICIT_MARKER,
  881             strlen(PATTERN_IMPLICIT_MARKER)) == 0) {
  882             zopt = zone_options_create(opt->region);
  883             if(!zopt) return 0;
  884             zopt->part_of_config = 1;
  885             zopt->name = region_strdup(opt->region, zstr);
  886             zopt->pattern = pattern_options_find(opt, patname);
  887             if(!zopt->name || !zopt->pattern) return 0;
  888             if(!nsd_options_insert_zone(opt, zopt)) {
  889                 log_msg(LOG_ERR, "bad domain name or duplicate zone '%s' "
  890                     "pattern %s", zstr, patname);
  891             }
  892         } else {
  893             /* create zone : presumably already added to zonelist
  894              * by xfrd, who wrote the AXFR or IXFR to disk, so we only
  895              * need to add it to our config.
  896              * This process does not need linesize and offset zonelist */
  897             zopt = zone_list_zone_insert(opt, zstr, patname, 0, 0);
  898             if(!zopt)
  899                 return 0;
  900         }
  901     }
  902     zone = namedb_zone_create(db, zone_name, zopt);
  903     return zone;
  904 }
  905 
  906 void
  907 delete_zone_rrs(namedb_type* db, zone_type* zone)
  908 {
  909     rrset_type *rrset;
  910     domain_type *domain = zone->apex, *next;
  911     int nonexist_check = 0;
  912     /* go through entire tree below the zone apex (incl subzones) */
  913     while(domain && domain_is_subdomain(domain, zone->apex))
  914     {
  915         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "delete zone visit %s",
  916             domain_to_string(domain)));
  917         /* delete all rrsets of the zone */
  918         while((rrset = domain_find_any_rrset(domain, zone))) {
  919             /* lower usage can delete other domains */
  920             rrset_lower_usage(db, rrset);
  921             /* rrset del does not delete our domain(yet) */
  922             rrset_delete(db, domain, rrset);
  923             /* no rrset_zero_nonexist_check, do that later */
  924             if(domain->rrsets == 0)
  925                 nonexist_check = 1;
  926         }
  927         /* the delete upcoming could delete parents, but nothing next
  928          * or after the domain so store next ptr */
  929         next = domain_next(domain);
  930         /* see if the domain can be deleted (and inspect parents) */
  931         domain_table_deldomain(db, domain);
  932         domain = next;
  933     }
  934 
  935     /* check if data deletions have created nonexisting domain entries,
  936      * but after deleting domains so the checks are faster */
  937     if(nonexist_check) {
  938         domain_type* ce = NULL; /* for speeding up has_data_below */
  939         DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "axfrdel: zero rrset check"));
  940         domain = zone->apex;
  941         while(domain && domain_is_subdomain(domain, zone->apex))
  942         {
  943             /* the interesting domains should be existing==1
  944              * and rrsets==0, speeding up out processing of
  945              * sub-zones, since we only spuriously check empty
  946              * nonterminals */
  947             if(domain->is_existing)
  948                 ce = rrset_zero_nonexist_check(domain, ce);
  949             domain = domain_next(domain);
  950         }
  951     }
  952 
  953     DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "axfrdel: recyclebin holds %lu bytes",
  954         (unsigned long) region_get_recycle_size(db->region)));
  955 #ifndef NDEBUG
  956     if(nsd_debug_level >= 2)
  957         region_log_stats(db->region);
  958 #endif
  959 
  960     assert(zone->soa_rrset == 0);
  961     /* keep zone->soa_nx_rrset alloced: it is reused */
  962     assert(zone->ns_rrset == 0);
  963     assert(zone->is_secure == 0);
  964 }
  965 
  966 /* return value 0: syntaxerror,badIXFR, 1:OK, 2:done_and_skip_it */
  967 static int
  968 apply_ixfr(namedb_type* db, FILE *in, const char* zone, uint32_t serialno,
  969     struct nsd_options* opt, uint32_t seq_nr, uint32_t seq_total,
  970     int* is_axfr, int* delete_mode, int* rr_count,
  971     udb_ptr* udbz, struct zone** zone_res, const char* patname, int* bytes,
  972     int* softfail)
  973 {
  974     uint32_t msglen, checklen, pkttype;
  975     int qcount, ancount, counter;
  976     buffer_type* packet;
  977     region_type* region;
  978     int i;
  979     uint16_t rrlen;
  980     const dname_type *dname_zone, *dname;
  981     zone_type* zone_db;
  982 
  983     /* note that errors could not really happen due to format of the
  984      * packet since xfrd has checked all dnames and RRs before commit,
  985      * this is why the errors are fatal (exit process), it must be
  986      * something internal or a bad disk or something. */
  987 
  988     /* read ixfr packet RRs and apply to in memory db */
  989     if(!diff_read_32(in, &pkttype) || pkttype != DIFF_PART_XXFR) {
  990         log_msg(LOG_ERR, "could not read type or wrong type");
  991         return 0;
  992     }
  993 
  994     if(!diff_read_32(in, &msglen)) {
  995         log_msg(LOG_ERR, "could not read len");
  996         return 0;
  997     }
  998 
  999     if(msglen < QHEADERSZ) {
 1000         log_msg(LOG_ERR, "msg too short");
 1001         return 0;
 1002     }
 1003 
 1004     region = region_create(xalloc, free);
 1005     if(!region) {
 1006         log_msg(LOG_ERR, "out of memory");
 1007         return 0;
 1008     }
 1009     packet = buffer_create(region, QIOBUFSZ);
 1010     if(msglen > QIOBUFSZ) {
 1011         log_msg(LOG_ERR, "msg too long");
 1012         region_destroy(region);
 1013         return 0;
 1014     }
 1015     buffer_clear(packet);
 1016     if(fread(buffer_begin(packet), msglen, 1, in) != 1) {
 1017         log_msg(LOG_ERR, "short fread: %s", strerror(errno));
 1018         region_destroy(region);
 1019         return 0;
 1020     }
 1021     buffer_set_limit(packet, msglen);
 1022 
 1023     /* see if check on data fails: checks that we are not reading
 1024      * random garbage */
 1025     if(!diff_read_32(in, &checklen) || checklen != msglen) {
 1026         log_msg(LOG_ERR, "transfer part has incorrect checkvalue");
 1027         return 0;
 1028     }
 1029     *bytes += msglen;
 1030 
 1031     dname_zone = dname_parse(region, zone);
 1032     zone_db = find_or_create_zone(db, dname_zone, opt, zone, patname);
 1033     if(!zone_db) {
 1034         log_msg(LOG_ERR, "could not create zone %s %s", zone, patname);
 1035         region_destroy(region);
 1036         return 0;
 1037     }
 1038     *zone_res = zone_db;
 1039 
 1040     /* only answer section is really used, question, additional and
 1041        authority section RRs are skipped */
 1042     qcount = QDCOUNT(packet);
 1043     ancount = ANCOUNT(packet);
 1044     buffer_skip(packet, QHEADERSZ);
 1045     /* qcount should be 0 or 1 really, ancount limited by 64k packet */
 1046     if(qcount > 64 || ancount > 65530) {
 1047         log_msg(LOG_ERR, "RR count impossibly high");
 1048         region_destroy(region);
 1049         return 0;
 1050     }
 1051 
 1052     /* skip queries */
 1053     for(i=0; i<qcount; ++i)
 1054         if(!packet_skip_rr(packet, 1)) {
 1055             log_msg(LOG_ERR, "bad RR in question section");
 1056             region_destroy(region);
 1057             return 0;
 1058         }
 1059 
 1060     DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: started packet for zone %s",
 1061             dname_to_string(dname_zone, 0)));
 1062     /* first RR: check if SOA and correct zone & serialno */
 1063     if(*rr_count == 0) {
 1064         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parse first RR",
 1065             dname_to_string(dname_zone, 0)));
 1066         dname = dname_make_from_packet(region, packet, 1, 1);
 1067         if(!dname) {
 1068             log_msg(LOG_ERR, "could not parse dname");
 1069             region_destroy(region);
 1070             return 0;
 1071         }
 1072         if(dname_compare(dname_zone, dname) != 0) {
 1073             log_msg(LOG_ERR, "SOA dname %s not equal to zone",
 1074                 dname_to_string(dname,0));
 1075             log_msg(LOG_ERR, "zone dname is %s",
 1076                 dname_to_string(dname_zone,0));
 1077             region_destroy(region);
 1078             return 0;
 1079         }
 1080         if(!buffer_available(packet, 10)) {
 1081             log_msg(LOG_ERR, "bad SOA RR");
 1082             region_destroy(region);
 1083             return 0;
 1084         }
 1085         if(buffer_read_u16(packet) != TYPE_SOA ||
 1086             buffer_read_u16(packet) != CLASS_IN) {
 1087             log_msg(LOG_ERR, "first RR not SOA IN");
 1088             region_destroy(region);
 1089             return 0;
 1090         }
 1091         buffer_skip(packet, sizeof(uint32_t)); /* ttl */
 1092         if(!buffer_available(packet, buffer_read_u16(packet)) ||
 1093             !packet_skip_dname(packet) /* skip prim_ns */ ||
 1094             !packet_skip_dname(packet) /* skip email */) {
 1095             log_msg(LOG_ERR, "bad SOA RR");
 1096             region_destroy(region);
 1097             return 0;
 1098         }
 1099         if(buffer_read_u32(packet) != serialno) {
 1100             buffer_skip(packet, -4);
 1101             log_msg(LOG_ERR, "SOA serial %u different from commit %u",
 1102                 (unsigned)buffer_read_u32(packet), (unsigned)serialno);
 1103             region_destroy(region);
 1104             return 0;
 1105         }
 1106         buffer_skip(packet, sizeof(uint32_t)*4);
 1107         counter = 1;
 1108         *rr_count = 1;
 1109         *is_axfr = 0;
 1110         *delete_mode = 0;
 1111         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s start count %d, ax %d, delmode %d",
 1112             dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
 1113     }
 1114     else  counter = 0;
 1115 
 1116     for(; counter < ancount; ++counter,++(*rr_count))
 1117     {
 1118         uint16_t type, klass;
 1119         uint32_t ttl;
 1120 
 1121         if(!(dname=dname_make_from_packet(region, packet, 1,1))) {
 1122             log_msg(LOG_ERR, "bad xfr RR dname %d", *rr_count);
 1123             region_destroy(region);
 1124             return 0;
 1125         }
 1126         if(!buffer_available(packet, 10)) {
 1127             log_msg(LOG_ERR, "bad xfr RR format %d", *rr_count);
 1128             region_destroy(region);
 1129             return 0;
 1130         }
 1131         type = buffer_read_u16(packet);
 1132         klass = buffer_read_u16(packet);
 1133         ttl = buffer_read_u32(packet);
 1134         rrlen = buffer_read_u16(packet);
 1135         if(!buffer_available(packet, rrlen)) {
 1136             log_msg(LOG_ERR, "bad xfr RR rdata %d, len %d have %d",
 1137                 *rr_count, rrlen, (int)buffer_remaining(packet));
 1138             region_destroy(region);
 1139             return 0;
 1140         }
 1141         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s parsed count %d, ax %d, delmode %d",
 1142             dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
 1143 
 1144         if(*rr_count == 1 && type != TYPE_SOA) {
 1145             /* second RR: if not SOA: this is an AXFR; delete all zone contents */
 1146 #ifdef NSEC3
 1147             nsec3_clear_precompile(db, zone_db);
 1148             zone_db->nsec3_param = NULL;
 1149 #endif
 1150             delete_zone_rrs(db, zone_db);
 1151             if(db->udb)
 1152                 udb_zone_clear(db->udb, udbz);
 1153             /* add everything else (incl end SOA) */
 1154             *delete_mode = 0;
 1155             *is_axfr = 1;
 1156             DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s sawAXFR count %d, ax %d, delmode %d",
 1157                 dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
 1158         }
 1159         if(*rr_count == 1 && type == TYPE_SOA) {
 1160             /* if the serial no of the SOA equals the serialno, then AXFR */
 1161             size_t bufpos = buffer_position(packet);
 1162             uint32_t thisserial;
 1163             if(!packet_skip_dname(packet) ||
 1164                 !packet_skip_dname(packet) ||
 1165                 buffer_remaining(packet) < sizeof(uint32_t)*5)
 1166             {
 1167                 log_msg(LOG_ERR, "bad xfr SOA RR formerr.");
 1168                 region_destroy(region);
 1169                 return 0;
 1170             }
 1171             thisserial = buffer_read_u32(packet);
 1172             if(thisserial == serialno) {
 1173                 /* AXFR */
 1174 #ifdef NSEC3
 1175                 nsec3_clear_precompile(db, zone_db);
 1176                 zone_db->nsec3_param = NULL;
 1177 #endif
 1178                 delete_zone_rrs(db, zone_db);
 1179                 if(db->udb)
 1180                     udb_zone_clear(db->udb, udbz);
 1181                 *delete_mode = 0;
 1182                 *is_axfr = 1;
 1183             }
 1184             /* must have stuff in memory for a successful IXFR,
 1185              * the serial number of the SOA has been checked
 1186              * previously (by check_for_bad_serial) if it exists */
 1187             if(!*is_axfr && !domain_find_rrset(zone_db->apex,
 1188                 zone_db, TYPE_SOA)) {
 1189                 log_msg(LOG_ERR, "%s SOA serial %u is not "
 1190                     "in memory, skip IXFR", zone, serialno);
 1191                 region_destroy(region);
 1192                 /* break out and stop the IXFR, ignore it */
 1193                 return 2;
 1194             }
 1195             buffer_set_position(packet, bufpos);
 1196         }
 1197         if(type == TYPE_SOA && !*is_axfr) {
 1198             /* switch from delete-part to add-part and back again,
 1199                just before soa - so it gets deleted and added too */
 1200             /* this means we switch to delete mode for the final SOA */
 1201             *delete_mode = !*delete_mode;
 1202             DEBUG(DEBUG_XFRD,2, (LOG_INFO, "diff: %s IXFRswapdel count %d, ax %d, delmode %d",
 1203                 dname_to_string(dname_zone, 0), *rr_count, *is_axfr, *delete_mode));
 1204         }
 1205         if(type == TYPE_TSIG || type == TYPE_OPT) {
 1206             /* ignore pseudo RRs */
 1207             buffer_skip(packet, rrlen);
 1208             continue;
 1209         }
 1210 
 1211         DEBUG(DEBUG_XFRD,2, (LOG_INFO, "xfr %s RR dname is %s type %s",
 1212             *delete_mode?"del":"add",
 1213             dname_to_string(dname,0), rrtype_to_string(type)));
 1214         if(*delete_mode) {
 1215             /* delete this rr */
 1216             if(!*is_axfr && type == TYPE_SOA && counter==ancount-1
 1217                 && seq_nr == seq_total-1) {
 1218                 continue; /* do not delete final SOA RR for IXFR */
 1219             }
 1220             if(!delete_RR(db, dname, type, klass, packet,
 1221                 rrlen, zone_db, region, udbz, softfail)) {
 1222                 region_destroy(region);
 1223                 return 0;
 1224             }
 1225         }
 1226         else
 1227         {
 1228             /* add this rr */
 1229             if(!add_RR(db, dname, type, klass, ttl, packet,
 1230                 rrlen, zone_db, udbz, softfail)) {
 1231                 region_destroy(region);
 1232                 return 0;
 1233             }
 1234         }
 1235     }
 1236     region_destroy(region);
 1237     return 1;
 1238 }
 1239 
 1240 static int
 1241 check_for_bad_serial(namedb_type* db, const char* zone_str, uint32_t old_serial)
 1242 {
 1243     /* see if serial OK with in-memory serial */
 1244     domain_type* domain;
 1245     region_type* region = region_create(xalloc, free);
 1246     const dname_type* zone_name = dname_parse(region, zone_str);
 1247     zone_type* zone = 0;
 1248     domain = domain_table_find(db->domains, zone_name);
 1249     if(domain)
 1250         zone = domain_find_zone(db, domain);
 1251     if(zone && zone->apex == domain && zone->soa_rrset && old_serial)
 1252     {
 1253         uint32_t memserial;
 1254         memcpy(&memserial, rdata_atom_data(zone->soa_rrset->rrs[0].rdatas[2]),
 1255             sizeof(uint32_t));
 1256         if(old_serial != ntohl(memserial)) {
 1257             region_destroy(region);
 1258             return 1;
 1259         }
 1260     }
 1261     region_destroy(region);
 1262     return 0;
 1263 }
 1264 
 1265 static int
 1266 apply_ixfr_for_zone(nsd_type* nsd, zone_type* zonedb, FILE* in,
 1267     struct nsd_options* opt, udb_base* taskudb, udb_ptr* last_task,
 1268     uint32_t xfrfilenr)
 1269 {
 1270     char zone_buf[3072];
 1271     char log_buf[5120];
 1272     char patname_buf[2048];
 1273 
 1274     uint32_t old_serial, new_serial, num_parts, type;
 1275     uint64_t time_end_0, time_start_0;
 1276     uint32_t time_end_1, time_start_1;
 1277     uint8_t committed;
 1278     uint32_t i;
 1279     int num_bytes = 0;
 1280     assert(zonedb);
 1281 
 1282     /* read zone name and serial */
 1283     if(!diff_read_32(in, &type)) {
 1284         log_msg(LOG_ERR, "diff file too short");
 1285         return 0;
 1286     }
 1287     if(type != DIFF_PART_XFRF) {
 1288         log_msg(LOG_ERR, "xfr file has wrong format");
 1289         return 0;
 1290 
 1291     }
 1292     /* committed and num_parts are first because they need to be
 1293      * updated once the rest is written.  The log buf is not certain
 1294      * until its done, so at end of file.  The patname is in case a
 1295      * new zone is created, we know what the options-pattern is */
 1296     if(!diff_read_8(in, &committed) ||
 1297         !diff_read_32(in, &num_parts) ||
 1298         !diff_read_64(in, &time_end_0) ||
 1299         !diff_read_32(in, &time_end_1) ||
 1300         !diff_read_32(in, &old_serial) ||
 1301         !diff_read_32(in, &new_serial) ||
 1302         !diff_read_64(in, &time_start_0) ||
 1303         !diff_read_32(in, &time_start_1) ||
 1304         !diff_read_str(in, zone_buf, sizeof(zone_buf)) ||
 1305         !diff_read_str(in, patname_buf, sizeof(patname_buf))) {
 1306         log_msg(LOG_ERR, "diff file bad commit part");
 1307         return 0;
 1308     }
 1309 
 1310     /* has been read in completely */
 1311     if(strcmp(zone_buf, domain_to_string(zonedb->apex)) != 0) {
 1312         log_msg(LOG_ERR, "file %s does not match task %s",
 1313             zone_buf, domain_to_string(zonedb->apex));
 1314         return 0;
 1315     }
 1316     if(!committed) {
 1317         log_msg(LOG_ERR, "diff file %s was not committed", zone_buf);
 1318         return 0;
 1319     }
 1320     if(num_parts == 0) {
 1321         log_msg(LOG_ERR, "diff file %s was not completed", zone_buf);
 1322         return 0;
 1323     }
 1324     if(check_for_bad_serial(nsd->db, zone_buf, old_serial)) {
 1325         DEBUG(DEBUG_XFRD,1, (LOG_ERR,
 1326             "skipping diff file commit with bad serial"));
 1327         return 1;
 1328     }
 1329 
 1330     if(committed)
 1331     {
 1332         int is_axfr=0, delete_mode=0, rr_count=0, softfail=0;
 1333         const dname_type* apex = domain_dname_const(zonedb->apex);
 1334         udb_ptr z;
 1335 
 1336         DEBUG(DEBUG_XFRD,1, (LOG_INFO, "processing xfr: %s", zone_buf));
 1337         memset(&z, 0, sizeof(z)); /* if udb==NULL, have &z defined */
 1338         if(nsd->db->udb) {
 1339             if(udb_base_get_userflags(nsd->db->udb) != 0) {
 1340                 log_msg(LOG_ERR, "database corrupted, cannot update");
 1341                 xfrd_unlink_xfrfile(nsd, xfrfilenr);
 1342                 exit(1);
 1343             }
 1344             /* all parts were checked by xfrd before commit */
 1345             if(!udb_zone_search(nsd->db->udb, &z, dname_name(apex),
 1346                 apex->name_size)) {
 1347                 /* create it */
 1348                 if(!udb_zone_create(nsd->db->udb, &z, dname_name(apex),
 1349                     apex->name_size)) {
 1350                     /* out of disk space perhaps */
 1351                     log_msg(LOG_ERR, "could not udb_create_zone "
 1352                         "%s, disk space full?", zone_buf);
 1353                     return 0;
 1354                 }
 1355             }
 1356             /* set the udb dirty until we are finished applying changes */
 1357             udb_base_set_userflags(nsd->db->udb, 1);
 1358         }
 1359         /* read and apply all of the parts */
 1360         for(i=0; i<num_parts; i++) {
 1361             int ret;
 1362             DEBUG(DEBUG_XFRD,2, (LOG_INFO, "processing xfr: apply part %d", (int)i));
 1363             ret = apply_ixfr(nsd->db, in, zone_buf, new_serial, opt,
 1364                 i, num_parts, &is_axfr, &delete_mode,
 1365                 &rr_count, (nsd->db->udb?&z:NULL), &zonedb,
 1366                 patname_buf, &num_bytes, &softfail);
 1367             assert(zonedb);
 1368             if(ret == 0) {
 1369                 log_msg(LOG_ERR, "bad ixfr packet part %d in diff file for %s", (int)i, zone_buf);
 1370                 xfrd_unlink_xfrfile(nsd, xfrfilenr);
 1371                 /* the udb is still dirty, it is bad */
 1372                 exit(1);
 1373             } else if(ret == 2) {
 1374                 break;
 1375             }
 1376         }
 1377         if(nsd->db->udb)
 1378             udb_base_set_userflags(nsd->db->udb, 0);
 1379         /* read the final log_str: but do not fail on it */
 1380         if(!diff_read_str(in, log_buf, sizeof(log_buf))) {
 1381             log_msg(LOG_ERR, "could not read log for transfer %s",
 1382                 zone_buf);
 1383             snprintf(log_buf, sizeof(log_buf), "error reading log");
 1384         }
 1385 #ifdef NSEC3
 1386         if(zonedb) prehash_zone(nsd->db, zonedb);
 1387 #endif /* NSEC3 */
 1388         zonedb->is_changed = 1;
 1389         if(nsd->db->udb) {
 1390             assert(z.base);
 1391             ZONE(&z)->is_changed = 1;
 1392             ZONE(&z)->mtime = time_end_0;
 1393             ZONE(&z)->mtime_nsec = time_end_1*1000;
 1394             udb_zone_set_log_str(nsd->db->udb, &z, log_buf);
 1395             udb_zone_set_file_str(nsd->db->udb, &z, NULL);
 1396             udb_ptr_unlink(&z, nsd->db->udb);
 1397         } else {
 1398             zonedb->mtime.tv_sec = time_end_0;
 1399             zonedb->mtime.tv_nsec = time_end_1*1000;
 1400             if(zonedb->logstr)
 1401                 region_recycle(nsd->db->region, zonedb->logstr,
 1402                     strlen(zonedb->logstr)+1);
 1403             zonedb->logstr = region_strdup(nsd->db->region, log_buf);
 1404             if(zonedb->filename)
 1405                 region_recycle(nsd->db->region, zonedb->filename,
 1406                     strlen(zonedb->filename)+1);
 1407             zonedb->filename = NULL;
 1408         }
 1409         if(softfail && taskudb && !is_axfr) {
 1410             log_msg(LOG_ERR, "Failed to apply IXFR cleanly "
 1411                 "(deletes nonexistent RRs, adds existing RRs). "
 1412                 "Zone %s contents is different from master, "
 1413                 "starting AXFR. Transfer %s", zone_buf, log_buf);
 1414             /* add/del failures in IXFR, get an AXFR */
 1415             task_new_soainfo(taskudb, last_task, zonedb, 1);
 1416         } else {
 1417             if(taskudb)
 1418                 task_new_soainfo(taskudb, last_task, zonedb, 0);
 1419         }
 1420 
 1421         if(1 <= verbosity) {
 1422             double elapsed = (double)(time_end_0 - time_start_0)+
 1423                 (double)((double)time_end_1
 1424                 -(double)time_start_1) / 1000000.0;
 1425             VERBOSITY(1, (LOG_INFO, "zone %s %s of %d bytes in %g seconds",
 1426                 zone_buf, log_buf, num_bytes, elapsed));
 1427         }
 1428     }
 1429     else {
 1430         DEBUG(DEBUG_XFRD,1, (LOG_INFO, "skipping xfr: %s", log_buf));
 1431     }
 1432     return 1;
 1433 }
 1434 
 1435 struct udb_base* task_file_create(const char* file)
 1436 {
 1437         return udb_base_create_new(file, &namedb_walkfunc, NULL);
 1438 }
 1439 
 1440 static int
 1441 task_create_new_elem(struct udb_base* udb, udb_ptr* last, udb_ptr* e,
 1442     size_t sz, const dname_type* zname)
 1443 {
 1444     if(!udb_ptr_alloc_space(e, udb, udb_chunk_type_task, sz)) {
 1445         return 0;
 1446     }
 1447     if(udb_ptr_is_null(last)) {
 1448         udb_base_set_userdata(udb, e->data);
 1449     } else {
 1450         udb_rptr_set_ptr(&TASKLIST(last)->next, udb, e);
 1451     }
 1452     udb_ptr_set_ptr(last, udb, e);
 1453 
 1454     /* fill in tasklist item */
 1455     udb_rel_ptr_init(&TASKLIST(e)->next);
 1456     TASKLIST(e)->size = sz;
 1457     TASKLIST(e)->oldserial = 0;
 1458     TASKLIST(e)->newserial = 0;
 1459     TASKLIST(e)->yesno = 0;
 1460 
 1461     if(zname) {
 1462         memmove(TASKLIST(e)->zname, zname, dname_total_size(zname));
 1463     }
 1464     return 1;
 1465 }
 1466 
 1467 void task_new_soainfo(struct udb_base* udb, udb_ptr* last, struct zone* z,
 1468     int gone)
 1469 {
 1470     /* calculate size */
 1471     udb_ptr e;
 1472     size_t sz;
 1473     const dname_type* apex, *ns, *em;
 1474     if(!z || !z->apex || !domain_dname(z->apex))
 1475         return; /* safety check */
 1476 
 1477     DEBUG(DEBUG_IPC,1, (LOG_INFO, "nsd: add soa info for zone %s",
 1478         domain_to_string(z->apex)));
 1479     apex = domain_dname(z->apex);
 1480     sz = sizeof(struct task_list_d) + dname_total_size(apex);
 1481     if(z->soa_rrset && !gone) {
 1482         ns = domain_dname(rdata_atom_domain(
 1483             z->soa_rrset->rrs[0].rdatas[0]));
 1484         em = domain_dname(rdata_atom_domain(
 1485             z->soa_rrset->rrs[0].rdatas[1]));
 1486         sz += sizeof(uint32_t)*6 + sizeof(uint8_t)*2
 1487             + ns->name_size + em->name_size;
 1488     } else {
 1489         ns = 0;
 1490         em = 0;
 1491     }
 1492 
 1493     /* create new task_list item */
 1494     if(!task_create_new_elem(udb, last, &e, sz, apex)) {
 1495         log_msg(LOG_ERR, "tasklist: out of space, cannot add SOAINFO");
 1496         return;
 1497     }
 1498     TASKLIST(&e)->task_type = task_soa_info;
 1499 
 1500     if(z->soa_rrset && !gone) {
 1501         uint32_t ttl = htonl(z->soa_rrset->rrs[0].ttl);
 1502         uint8_t* p = (uint8_t*)TASKLIST(&e)->zname;
 1503         p += dname_total_size(apex);
 1504         memmove(p, &ttl, sizeof(uint32_t));
 1505         p += sizeof(uint32_t);
 1506         memmove(p, &ns->name_size, sizeof(uint8_t));
 1507         p += sizeof(uint8_t);
 1508         memmove(p, dname_name(ns), ns->name_size);
 1509         p += ns->name_size;
 1510         memmove(p, &em->name_size, sizeof(uint8_t));
 1511         p += sizeof(uint8_t);
 1512         memmove(p, dname_name(em), em->name_size);
 1513         p += em->name_size;
 1514         memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[2]),
 1515             sizeof(uint32_t));
 1516         p += sizeof(uint32_t);
 1517         memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[3]),
 1518             sizeof(uint32_t));
 1519         p += sizeof(uint32_t);
 1520         memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[4]),
 1521             sizeof(uint32_t));
 1522         p += sizeof(uint32_t);
 1523         memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[5]),
 1524             sizeof(uint32_t));
 1525         p += sizeof(uint32_t);
 1526         memmove(p, rdata_atom_data(z->soa_rrset->rrs[0].rdatas[6]),
 1527             sizeof(uint32_t));
 1528     }
 1529     udb_ptr_unlink(&e, udb);
 1530 }
 1531 
 1532 void task_process_sync(struct udb_base* taskudb)
 1533 {
 1534     /* need to sync before other process uses the mmap? */
 1535     DEBUG(DEBUG_IPC,1, (LOG_INFO, "task procsync %s size %d",
 1536         taskudb->fname, (int)taskudb->base_size));
 1537     (void)taskudb;
 1538 }
 1539 
 1540 void task_remap(struct udb_base* taskudb)
 1541 {
 1542     DEBUG(DEBUG_IPC,1, (LOG_INFO, "task remap %s size %d",
 1543         taskudb->fname, (int)taskudb->glob_data->fsize));
 1544     udb_base_remap_process(taskudb);
 1545 }
 1546 
 1547 void task_clear(struct udb_base* taskudb)
 1548 {
 1549     udb_ptr t, n;
 1550     udb_ptr_new(&t, taskudb, udb_base_get_userdata(taskudb));
 1551     udb_base_set_userdata(taskudb, 0);
 1552     udb_ptr_init(&n, taskudb);
 1553     while(!udb_ptr_is_null(&t)) {
 1554         udb_ptr_set_rptr(&n, taskudb, &TASKLIST(&t)->next);
 1555         udb_rptr_zero(&TASKLIST(&t)->next, taskudb);
 1556         udb_ptr_free_space(&t, taskudb, TASKLIST(&t)->size);
 1557         udb_ptr_set_ptr(&t, taskudb, &n);
 1558     }
 1559     udb_ptr_unlink(&t, taskudb);
 1560     udb_ptr_unlink(&n, taskudb);
 1561 }
 1562 
 1563 void task_new_expire(struct udb_base* udb, udb_ptr* last,
 1564     const struct dname* z, int expired)
 1565 {
 1566     udb_ptr e;
 1567     if(!z) return;
 1568     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add expire info for zone %s",
 1569         dname_to_string(z,NULL)));
 1570     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)+
 1571         dname_total_size(z), z)) {
 1572         log_msg(LOG_ERR, "tasklist: out of space, cannot add expire");
 1573         return;
 1574     }
 1575     TASKLIST(&e)->task_type = task_expire;
 1576     TASKLIST(&e)->yesno = expired;
 1577     udb_ptr_unlink(&e, udb);
 1578 }
 1579 
 1580 void task_new_check_zonefiles(udb_base* udb, udb_ptr* last,
 1581     const dname_type* zone)
 1582 {
 1583     udb_ptr e;
 1584     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task checkzonefiles"));
 1585     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) +
 1586         (zone?dname_total_size(zone):0), zone)) {
 1587         log_msg(LOG_ERR, "tasklist: out of space, cannot add check_zones");
 1588         return;
 1589     }
 1590     TASKLIST(&e)->task_type = task_check_zonefiles;
 1591     TASKLIST(&e)->yesno = (zone!=NULL);
 1592     udb_ptr_unlink(&e, udb);
 1593 }
 1594 
 1595 void task_new_write_zonefiles(udb_base* udb, udb_ptr* last,
 1596     const dname_type* zone)
 1597 {
 1598     udb_ptr e;
 1599     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task writezonefiles"));
 1600     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d) +
 1601         (zone?dname_total_size(zone):0), zone)) {
 1602         log_msg(LOG_ERR, "tasklist: out of space, cannot add writezones");
 1603         return;
 1604     }
 1605     TASKLIST(&e)->task_type = task_write_zonefiles;
 1606     TASKLIST(&e)->yesno = (zone!=NULL);
 1607     udb_ptr_unlink(&e, udb);
 1608 }
 1609 
 1610 void task_new_set_verbosity(udb_base* udb, udb_ptr* last, int v)
 1611 {
 1612     udb_ptr e;
 1613     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task set_verbosity"));
 1614     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d),
 1615         NULL)) {
 1616         log_msg(LOG_ERR, "tasklist: out of space, cannot add set_v");
 1617         return;
 1618     }
 1619     TASKLIST(&e)->task_type = task_set_verbosity;
 1620     TASKLIST(&e)->yesno = v;
 1621     udb_ptr_unlink(&e, udb);
 1622 }
 1623 
 1624 #ifdef BIND8_STATS
 1625 void* task_new_stat_info(udb_base* udb, udb_ptr* last, struct nsdst* stat,
 1626     size_t child_count)
 1627 {
 1628     void* p;
 1629     udb_ptr e;
 1630     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task stat_info"));
 1631     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)+
 1632         sizeof(*stat) + sizeof(stc_type)*child_count, NULL)) {
 1633         log_msg(LOG_ERR, "tasklist: out of space, cannot add stati");
 1634         return NULL;
 1635     }
 1636     TASKLIST(&e)->task_type = task_stat_info;
 1637     p = TASKLIST(&e)->zname;
 1638     memcpy(p, stat, sizeof(*stat));
 1639     udb_ptr_unlink(&e, udb);
 1640     return (char*)p + sizeof(*stat);
 1641 }
 1642 #endif /* BIND8_STATS */
 1643 
 1644 void
 1645 task_new_add_zone(udb_base* udb, udb_ptr* last, const char* zone,
 1646     const char* pattern, unsigned zonestatid)
 1647 {
 1648     size_t zlen = strlen(zone);
 1649     size_t plen = strlen(pattern);
 1650     void *p;
 1651     udb_ptr e;
 1652     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addzone %s %s", zone, pattern));
 1653     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)+
 1654         zlen + 1 + plen + 1, NULL)) {
 1655         log_msg(LOG_ERR, "tasklist: out of space, cannot add addz");
 1656         return;
 1657     }
 1658     TASKLIST(&e)->task_type = task_add_zone;
 1659     TASKLIST(&e)->yesno = zonestatid;
 1660     p = TASKLIST(&e)->zname;
 1661     memcpy(p, zone, zlen+1);
 1662     memmove((char*)p+zlen+1, pattern, plen+1);
 1663     udb_ptr_unlink(&e, udb);
 1664 }
 1665 
 1666 void
 1667 task_new_del_zone(udb_base* udb, udb_ptr* last, const dname_type* dname)
 1668 {
 1669     udb_ptr e;
 1670     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delzone %s", dname_to_string(dname, 0)));
 1671     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1672         +dname_total_size(dname), dname)) {
 1673         log_msg(LOG_ERR, "tasklist: out of space, cannot add delz");
 1674         return;
 1675     }
 1676     TASKLIST(&e)->task_type = task_del_zone;
 1677     udb_ptr_unlink(&e, udb);
 1678 }
 1679 
 1680 void task_new_add_key(udb_base* udb, udb_ptr* last, struct key_options* key)
 1681 {
 1682     char* p;
 1683     udb_ptr e;
 1684     assert(key->name && key->algorithm && key->secret);
 1685     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addkey"));
 1686     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1687         +strlen(key->name)+1+strlen(key->algorithm)+1+
 1688         strlen(key->secret)+1, NULL)) {
 1689         log_msg(LOG_ERR, "tasklist: out of space, cannot add addk");
 1690         return;
 1691     }
 1692     TASKLIST(&e)->task_type = task_add_key;
 1693     p = (char*)TASKLIST(&e)->zname;
 1694     memmove(p, key->name, strlen(key->name)+1);
 1695     p+=strlen(key->name)+1;
 1696     memmove(p, key->algorithm, strlen(key->algorithm)+1);
 1697     p+=strlen(key->algorithm)+1;
 1698     memmove(p, key->secret, strlen(key->secret)+1);
 1699     udb_ptr_unlink(&e, udb);
 1700 }
 1701 
 1702 void task_new_del_key(udb_base* udb, udb_ptr* last, const char* name)
 1703 {
 1704     char* p;
 1705     udb_ptr e;
 1706     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delkey"));
 1707     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1708         +strlen(name)+1, NULL)) {
 1709         log_msg(LOG_ERR, "tasklist: out of space, cannot add delk");
 1710         return;
 1711     }
 1712     TASKLIST(&e)->task_type = task_del_key;
 1713     p = (char*)TASKLIST(&e)->zname;
 1714     memmove(p, name, strlen(name)+1);
 1715     udb_ptr_unlink(&e, udb);
 1716 }
 1717 
 1718 void task_new_add_pattern(udb_base* udb, udb_ptr* last,
 1719     struct pattern_options* p)
 1720 {
 1721     region_type* temp;
 1722     buffer_type* buffer;
 1723     udb_ptr e;
 1724     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task addpattern %s", p->pname));
 1725     temp = region_create(xalloc, free);
 1726     buffer = buffer_create(temp, 4096);
 1727     pattern_options_marshal(buffer, p);
 1728     buffer_flip(buffer);
 1729     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1730         + buffer_limit(buffer), NULL)) {
 1731         log_msg(LOG_ERR, "tasklist: out of space, cannot add addp");
 1732         region_destroy(temp);
 1733         return;
 1734     }
 1735     TASKLIST(&e)->task_type = task_add_pattern;
 1736     TASKLIST(&e)->yesno = buffer_limit(buffer);
 1737     memmove(TASKLIST(&e)->zname, buffer_begin(buffer),
 1738         buffer_limit(buffer));
 1739     udb_ptr_unlink(&e, udb);
 1740     region_destroy(temp);
 1741 }
 1742 
 1743 void task_new_del_pattern(udb_base* udb, udb_ptr* last, const char* name)
 1744 {
 1745     char* p;
 1746     udb_ptr e;
 1747     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task delpattern %s", name));
 1748     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1749         +strlen(name)+1, NULL)) {
 1750         log_msg(LOG_ERR, "tasklist: out of space, cannot add delp");
 1751         return;
 1752     }
 1753     TASKLIST(&e)->task_type = task_del_pattern;
 1754     p = (char*)TASKLIST(&e)->zname;
 1755     memmove(p, name, strlen(name)+1);
 1756     udb_ptr_unlink(&e, udb);
 1757 }
 1758 
 1759 void task_new_opt_change(udb_base* udb, udb_ptr* last, struct nsd_options* opt)
 1760 {
 1761     udb_ptr e;
 1762     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task opt_change"));
 1763     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d),
 1764         NULL)) {
 1765         log_msg(LOG_ERR, "tasklist: out of space, cannot add o_c");
 1766         return;
 1767     }
 1768     TASKLIST(&e)->task_type = task_opt_change;
 1769 #ifdef RATELIMIT
 1770     TASKLIST(&e)->oldserial = opt->rrl_ratelimit;
 1771     TASKLIST(&e)->newserial = opt->rrl_whitelist_ratelimit;
 1772     TASKLIST(&e)->yesno = (uint64_t) opt->rrl_slip;
 1773 #else
 1774     (void)opt;
 1775 #endif
 1776     udb_ptr_unlink(&e, udb);
 1777 }
 1778 
 1779 void task_new_zonestat_inc(udb_base* udb, udb_ptr* last, unsigned sz)
 1780 {
 1781     udb_ptr e;
 1782     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task zonestat_inc"));
 1783     if(sz == 0)
 1784         return; /* no need to decrease to 0 */
 1785     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d),
 1786         NULL)) {
 1787         log_msg(LOG_ERR, "tasklist: out of space, cannot add z_i");
 1788         return;
 1789     }
 1790     TASKLIST(&e)->task_type = task_zonestat_inc;
 1791     TASKLIST(&e)->oldserial = (uint32_t)sz;
 1792     udb_ptr_unlink(&e, udb);
 1793 }
 1794 
 1795 int
 1796 task_new_apply_xfr(udb_base* udb, udb_ptr* last, const dname_type* dname,
 1797     uint32_t old_serial, uint32_t new_serial, uint64_t filenumber)
 1798 {
 1799     udb_ptr e;
 1800     DEBUG(DEBUG_IPC,1, (LOG_INFO, "add task apply_xfr"));
 1801     if(!task_create_new_elem(udb, last, &e, sizeof(struct task_list_d)
 1802         +dname_total_size(dname), dname)) {
 1803         log_msg(LOG_ERR, "tasklist: out of space, cannot add applyxfr");
 1804         return 0;
 1805     }
 1806     TASKLIST(&e)->oldserial = old_serial;
 1807     TASKLIST(&e)->newserial = new_serial;
 1808     TASKLIST(&e)->yesno = filenumber;
 1809     TASKLIST(&e)->task_type = task_apply_xfr;
 1810     udb_ptr_unlink(&e, udb);
 1811     return 1;
 1812 }
 1813 
 1814 void
 1815 task_process_expire(namedb_type* db, struct task_list_d* task)
 1816 {
 1817     uint8_t ok;
 1818     zone_type* z = namedb_find_zone(db, task->zname);
 1819     assert(task->task_type == task_expire);
 1820     if(!z) {
 1821         DEBUG(DEBUG_IPC, 1, (LOG_WARNING, "zone %s %s but not in zonetree",
 1822             dname_to_string(task->zname, NULL),
 1823             task->yesno?"expired":"unexpired"));
 1824         return;
 1825     }
 1826     DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: expire task zone %s %s",
 1827         dname_to_string(task->zname,0),
 1828         task->yesno?"expired":"unexpired"));
 1829     /* find zone, set expire flag */
 1830     ok = !task->yesno;
 1831     /* only update zone->is_ok if needed to minimize copy-on-write
 1832      * of memory pages shared after fork() */
 1833     if(ok && !z->is_ok)
 1834         z->is_ok = 1;
 1835     else if(!ok && z->is_ok)
 1836         z->is_ok = 0;
 1837 }
 1838 
 1839 static void
 1840 task_process_set_verbosity(struct task_list_d* task)
 1841 {
 1842     DEBUG(DEBUG_IPC,1, (LOG_INFO, "verbosity task %d", (int)task->yesno));
 1843     verbosity = task->yesno;
 1844 }
 1845 
 1846 static void
 1847 task_process_checkzones(struct nsd* nsd, udb_base* udb, udb_ptr* last_task,
 1848     struct task_list_d* task)
 1849 {
 1850     /* on SIGHUP check if zone-text-files changed and if so,
 1851      * reread.  When from xfrd-reload, no need to fstat the files */
 1852     if(task->yesno) {
 1853         struct zone_options* zo = zone_options_find(nsd->options,
 1854             task->zname);
 1855         if(zo)
 1856             namedb_check_zonefile(nsd, udb, last_task, zo);
 1857     } else {
 1858         /* check all zones */
 1859         namedb_check_zonefiles(nsd, nsd->options, udb, last_task);
 1860     }
 1861 }
 1862 
 1863 static void
 1864 task_process_writezones(struct nsd* nsd, struct task_list_d* task)
 1865 {
 1866     if(task->yesno) {
 1867         struct zone_options* zo = zone_options_find(nsd->options,
 1868             task->zname);
 1869         if(zo)
 1870             namedb_write_zonefile(nsd, zo);
 1871     } else {
 1872         namedb_write_zonefiles(nsd, nsd->options);
 1873     }
 1874 }
 1875 
 1876 static void
 1877 task_process_add_zone(struct nsd* nsd, udb_base* udb, udb_ptr* last_task,
 1878     struct task_list_d* task)
 1879 {
 1880     zone_type* z;
 1881     const dname_type* zdname;
 1882     const char* zname = (const char*)task->zname;
 1883     const char* pname = zname + strlen(zname)+1;
 1884     DEBUG(DEBUG_IPC,1, (LOG_INFO, "addzone task %s %s", zname, pname));
 1885     zdname = dname_parse(nsd->db->region, zname);
 1886     if(!zdname) {
 1887         log_msg(LOG_ERR, "can not parse zone name %s", zname);
 1888         return;
 1889     }
 1890     /* create zone */
 1891     z = find_or_create_zone(nsd->db, zdname, nsd->options, zname, pname);
 1892     if(!z) {
 1893         region_recycle(nsd->db->region, (void*)zdname,
 1894             dname_total_size(zdname));
 1895         log_msg(LOG_ERR, "can not add zone %s %s", zname, pname);
 1896         return;
 1897     }
 1898     z->zonestatid = (unsigned)task->yesno;
 1899     /* if zone is empty, attempt to read the zonefile from disk (if any) */
 1900     if(!z->soa_rrset && z->opts->pattern->zonefile) {
 1901         namedb_read_zonefile(nsd, z, udb, last_task);
 1902     }
 1903 }
 1904 
 1905 static void
 1906 task_process_del_zone(struct nsd* nsd, struct task_list_d* task)
 1907 {
 1908     zone_type* zone;
 1909     struct zone_options* zopt;
 1910     DEBUG(DEBUG_IPC,1, (LOG_INFO, "delzone task %s", dname_to_string(
 1911         task->zname, NULL)));
 1912     zone = namedb_find_zone(nsd->db, task->zname);
 1913     if(!zone)
 1914         return;
 1915 
 1916 #ifdef NSEC3
 1917     nsec3_clear_precompile(nsd->db, zone);
 1918     zone->nsec3_param = NULL;
 1919 #endif
 1920     delete_zone_rrs(nsd->db, zone);
 1921     if(nsd->db->udb) {
 1922         udb_ptr udbz;
 1923         if(udb_zone_search(nsd->db->udb, &udbz, dname_name(task->zname),
 1924             task->zname->name_size)) {
 1925             udb_zone_delete(nsd->db->udb, &udbz);
 1926             udb_ptr_unlink(&udbz, nsd->db->udb);
 1927         }
 1928     }
 1929 
 1930     /* remove from zonetree, apex, soa */
 1931     zopt = zone->opts;
 1932     namedb_zone_delete(nsd->db, zone);
 1933     /* remove from options (zone_list already edited by xfrd) */
 1934     zone_options_delete(nsd->options, zopt);
 1935 }
 1936 
 1937 static void
 1938 task_process_add_key(struct nsd* nsd, struct task_list_d* task)
 1939 {
 1940     struct key_options key;
 1941     key.name = (char*)task->zname;
 1942     DEBUG(DEBUG_IPC,1, (LOG_INFO, "addkey task %s", key.name));
 1943     key.algorithm = key.name + strlen(key.name)+1;
 1944     key.secret = key.algorithm + strlen(key.algorithm)+1;
 1945     key_options_add_modify(nsd->options, &key);
 1946     memset(key.secret, 0xdd, strlen(key.secret)); /* wipe secret */
 1947 }
 1948 
 1949 static void
 1950 task_process_del_key(struct nsd* nsd, struct task_list_d* task)
 1951 {
 1952     char* name = (char*)task->zname;
 1953     DEBUG(DEBUG_IPC,1, (LOG_INFO, "delkey task %s", name));
 1954     /* this is reload and nothing is using the TSIG key right now */
 1955     key_options_remove(nsd->options, name);
 1956 }
 1957 
 1958 static void
 1959 task_process_add_pattern(struct nsd* nsd, struct task_list_d* task)
 1960 {
 1961     region_type* temp = region_create(xalloc, free);
 1962     buffer_type buffer;
 1963     struct pattern_options *pat;
 1964     buffer_create_from(&buffer, task->zname, task->yesno);
 1965     pat = pattern_options_unmarshal(temp, &buffer);
 1966     DEBUG(DEBUG_IPC,1, (LOG_INFO, "addpattern task %s", pat->pname));
 1967     pattern_options_add_modify(nsd->options, pat);
 1968     region_destroy(temp);
 1969 }
 1970 
 1971 static void
 1972 task_process_del_pattern(struct nsd* nsd, struct task_list_d* task)
 1973 {
 1974     char* name = (char*)task->zname;
 1975     DEBUG(DEBUG_IPC,1, (LOG_INFO, "delpattern task %s", name));
 1976     pattern_options_remove(nsd->options, name);
 1977 }
 1978 
 1979 static void
 1980 task_process_opt_change(struct nsd* nsd, struct task_list_d* task)
 1981 {
 1982     DEBUG(DEBUG_IPC,1, (LOG_INFO, "optchange task"));
 1983 #ifdef RATELIMIT
 1984     nsd->options->rrl_ratelimit = task->oldserial;
 1985     nsd->options->rrl_whitelist_ratelimit = task->newserial;
 1986     nsd->options->rrl_slip = task->yesno;
 1987     rrl_set_limit(nsd->options->rrl_ratelimit, nsd->options->rrl_whitelist_ratelimit,
 1988         nsd->options->rrl_slip);
 1989 #else
 1990     (void)nsd; (void)task;
 1991 #endif
 1992 }
 1993 
 1994 #ifdef USE_ZONE_STATS
 1995 static void
 1996 task_process_zonestat_inc(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
 1997     struct task_list_d* task)
 1998 {
 1999     DEBUG(DEBUG_IPC,1, (LOG_INFO, "zonestat_inc task %u", (unsigned)task->oldserial));
 2000     nsd->zonestatdesired = (unsigned)task->oldserial;
 2001     /* send echo to xfrd to increment on its end */
 2002     task_new_zonestat_inc(udb, last_task, nsd->zonestatdesired);
 2003 }
 2004 #endif
 2005 
 2006 static void
 2007 task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
 2008     udb_ptr* task)
 2009 {
 2010     /* we have to use an udb_ptr task here, because the apply_xfr procedure
 2011      * appends soa_info which may remap and change the pointer. */
 2012     zone_type* zone;
 2013     FILE* df;
 2014     DEBUG(DEBUG_IPC,1, (LOG_INFO, "applyxfr task %s", dname_to_string(
 2015         TASKLIST(task)->zname, NULL)));
 2016     zone = namedb_find_zone(nsd->db, TASKLIST(task)->zname);
 2017     if(!zone) {
 2018         /* assume the zone has been deleted and a zone transfer was
 2019          * still waiting to be processed */
 2020         xfrd_unlink_xfrfile(nsd, TASKLIST(task)->yesno);
 2021         return;
 2022     }
 2023     /* apply the XFR */
 2024     /* oldserial, newserial, yesno is filenumber */
 2025     df = xfrd_open_xfrfile(nsd, TASKLIST(task)->yesno, "r");
 2026     if(!df) {
 2027         /* could not open file to update */
 2028         /* there is no reply to xfrd failed-update,
 2029          * because xfrd has a scan for apply-failures. */
 2030         xfrd_unlink_xfrfile(nsd, TASKLIST(task)->yesno);
 2031         return;
 2032     }
 2033     /* read and apply zone transfer */
 2034     if(!apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb,
 2035         last_task, TASKLIST(task)->yesno)) {
 2036         /* there is no reply to xfrd failed-update,
 2037          * because xfrd has a scan for apply-failures. */
 2038     }
 2039 
 2040     fclose(df);
 2041     xfrd_unlink_xfrfile(nsd, TASKLIST(task)->yesno);
 2042 }
 2043 
 2044 
 2045 void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
 2046         udb_ptr* task)
 2047 {
 2048     switch(TASKLIST(task)->task_type) {
 2049     case task_expire:
 2050         task_process_expire(nsd->db, TASKLIST(task));
 2051         break;
 2052     case task_check_zonefiles:
 2053         task_process_checkzones(nsd, udb, last_task, TASKLIST(task));
 2054         break;
 2055     case task_write_zonefiles:
 2056         task_process_writezones(nsd, TASKLIST(task));
 2057         break;
 2058     case task_set_verbosity:
 2059         task_process_set_verbosity(TASKLIST(task));
 2060         break;
 2061     case task_add_zone:
 2062         task_process_add_zone(nsd, udb, last_task, TASKLIST(task));
 2063         break;
 2064     case task_del_zone:
 2065         task_process_del_zone(nsd, TASKLIST(task));
 2066         break;
 2067     case task_add_key:
 2068         task_process_add_key(nsd, TASKLIST(task));
 2069         break;
 2070     case task_del_key:
 2071         task_process_del_key(nsd, TASKLIST(task));
 2072         break;
 2073     case task_add_pattern:
 2074         task_process_add_pattern(nsd, TASKLIST(task));
 2075         break;
 2076     case task_del_pattern:
 2077         task_process_del_pattern(nsd, TASKLIST(task));
 2078         break;
 2079     case task_opt_change:
 2080         task_process_opt_change(nsd, TASKLIST(task));
 2081         break;
 2082 #ifdef USE_ZONE_STATS
 2083     case task_zonestat_inc:
 2084         task_process_zonestat_inc(nsd, udb, last_task, TASKLIST(task));
 2085         break;
 2086 #endif
 2087     case task_apply_xfr:
 2088         task_process_apply_xfr(nsd, udb, last_task, task);
 2089         break;
 2090     default:
 2091         log_msg(LOG_WARNING, "unhandled task in reload type %d",
 2092             (int)TASKLIST(task)->task_type);
 2093         break;
 2094     }
 2095     udb_ptr_free_space(task, udb, TASKLIST(task)->size);
 2096 }