diff.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: diff.c,v 1.26 2011/03/25 23:53:02 each Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <stdlib.h>
00025 
00026 #include <isc/buffer.h>
00027 #include <isc/file.h>
00028 #include <isc/mem.h>
00029 #include <isc/string.h>
00030 #include <isc/util.h>
00031 
00032 #include <dns/db.h>
00033 #include <dns/diff.h>
00034 #include <dns/log.h>
00035 #include <dns/rdataclass.h>
00036 #include <dns/rdatalist.h>
00037 #include <dns/rdataset.h>
00038 #include <dns/rdatastruct.h>
00039 #include <dns/rdatatype.h>
00040 #include <dns/result.h>
00041 
00042 #define CHECK(op) \
00043         do { result = (op);                                     \
00044                 if (result != ISC_R_SUCCESS) goto failure;      \
00045         } while (0)
00046 
00047 #define DIFF_COMMON_LOGARGS \
00048         dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DIFF
00049 
00050 static dns_rdatatype_t
00051 rdata_covers(dns_rdata_t *rdata) {
00052         return (rdata->type == dns_rdatatype_rrsig ?
00053                 dns_rdata_covers(rdata) : 0);
00054 }
00055 
00056 isc_result_t
00057 dns_difftuple_create(isc_mem_t *mctx,
00058                      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
00059                      dns_rdata_t *rdata, dns_difftuple_t **tp)
00060 {
00061         dns_difftuple_t *t;
00062         unsigned int size;
00063         unsigned char *datap;
00064 
00065         REQUIRE(tp != NULL && *tp == NULL);
00066 
00067         /*
00068          * Create a new tuple.  The variable-size wire-format name data and
00069          * rdata immediately follow the dns_difftuple_t structure
00070          * in memory.
00071          */
00072         size = sizeof(*t) + name->length + rdata->length;
00073         t = isc_mem_allocate(mctx, size);
00074         if (t == NULL)
00075                 return (ISC_R_NOMEMORY);
00076         t->mctx = NULL;
00077         isc_mem_attach(mctx, &t->mctx);
00078         t->op = op;
00079 
00080         datap = (unsigned char *)(t + 1);
00081 
00082         memmove(datap, name->ndata, name->length);
00083         dns_name_init(&t->name, NULL);
00084         dns_name_clone(name, &t->name);
00085         t->name.ndata = datap;
00086         datap += name->length;
00087 
00088         t->ttl = ttl;
00089 
00090         memmove(datap, rdata->data, rdata->length);
00091         dns_rdata_init(&t->rdata);
00092         dns_rdata_clone(rdata, &t->rdata);
00093         t->rdata.data = datap;
00094         datap += rdata->length;
00095 
00096         ISC_LINK_INIT(&t->rdata, link);
00097         ISC_LINK_INIT(t, link);
00098         t->magic = DNS_DIFFTUPLE_MAGIC;
00099 
00100         INSIST(datap == (unsigned char *)t + size);
00101 
00102         *tp = t;
00103         return (ISC_R_SUCCESS);
00104 }
00105 
00106 void
00107 dns_difftuple_free(dns_difftuple_t **tp) {
00108         dns_difftuple_t *t = *tp;
00109         isc_mem_t *mctx;
00110 
00111         REQUIRE(DNS_DIFFTUPLE_VALID(t));
00112 
00113         dns_name_invalidate(&t->name);
00114         t->magic = 0;
00115         mctx = t->mctx;
00116         isc_mem_free(mctx, t);
00117         isc_mem_detach(&mctx);
00118         *tp = NULL;
00119 }
00120 
00121 isc_result_t
00122 dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp) {
00123         return (dns_difftuple_create(orig->mctx, orig->op, &orig->name,
00124                                      orig->ttl, &orig->rdata, copyp));
00125 }
00126 
00127 void
00128 dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff) {
00129         diff->mctx = mctx;
00130         ISC_LIST_INIT(diff->tuples);
00131         diff->magic = DNS_DIFF_MAGIC;
00132 }
00133 
00134 void
00135 dns_diff_clear(dns_diff_t *diff) {
00136         dns_difftuple_t *t;
00137         REQUIRE(DNS_DIFF_VALID(diff));
00138         while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) {
00139                 ISC_LIST_UNLINK(diff->tuples, t, link);
00140                 dns_difftuple_free(&t);
00141         }
00142         ENSURE(ISC_LIST_EMPTY(diff->tuples));
00143 }
00144 
00145 void
00146 dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuplep)
00147 {
00148         ISC_LIST_APPEND(diff->tuples, *tuplep, link);
00149         *tuplep = NULL;
00150 }
00151 
00152 /* XXX this is O(N) */
00153 
00154 void
00155 dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
00156 {
00157         dns_difftuple_t *ot, *next_ot;
00158 
00159         REQUIRE(DNS_DIFF_VALID(diff));
00160         REQUIRE(DNS_DIFFTUPLE_VALID(*tuplep));
00161 
00162         /*
00163          * Look for an existing tuple with the same owner name,
00164          * rdata, and TTL.   If we are doing an addition and find a
00165          * deletion or vice versa, remove both the old and the
00166          * new tuple since they cancel each other out (assuming
00167          * that we never delete nonexistent data or add existing
00168          * data).
00169          *
00170          * If we find an old update of the same kind as
00171          * the one we are doing, there must be a programming
00172          * error.  We report it but try to continue anyway.
00173          */
00174         for (ot = ISC_LIST_HEAD(diff->tuples); ot != NULL;
00175              ot = next_ot)
00176         {
00177                 next_ot = ISC_LIST_NEXT(ot, link);
00178                 if (dns_name_caseequal(&ot->name, &(*tuplep)->name) &&
00179                     dns_rdata_compare(&ot->rdata, &(*tuplep)->rdata) == 0 &&
00180                     ot->ttl == (*tuplep)->ttl)
00181                 {
00182                         ISC_LIST_UNLINK(diff->tuples, ot, link);
00183                         if ((*tuplep)->op == ot->op) {
00184                                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00185                                          "unexpected non-minimal diff");
00186                         } else {
00187                                 dns_difftuple_free(tuplep);
00188                         }
00189                         dns_difftuple_free(&ot);
00190                         break;
00191                 }
00192         }
00193 
00194         if (*tuplep != NULL) {
00195                 ISC_LIST_APPEND(diff->tuples, *tuplep, link);
00196                 *tuplep = NULL;
00197         }
00198 
00199         ENSURE(*tuplep == NULL);
00200 }
00201 
00202 static isc_stdtime_t
00203 setresign(dns_rdataset_t *modified) {
00204         dns_rdata_t rdata = DNS_RDATA_INIT;
00205         dns_rdata_rrsig_t sig;
00206         isc_stdtime_t when;
00207         isc_result_t result;
00208 
00209         result = dns_rdataset_first(modified);
00210         INSIST(result == ISC_R_SUCCESS);
00211         dns_rdataset_current(modified, &rdata);
00212         (void)dns_rdata_tostruct(&rdata, &sig, NULL);
00213         if ((rdata.flags & DNS_RDATA_OFFLINE) != 0)
00214                 when = 0;
00215         else
00216                 when = sig.timeexpire;
00217         dns_rdata_reset(&rdata);
00218 
00219         result = dns_rdataset_next(modified);
00220         while (result == ISC_R_SUCCESS) {
00221                 dns_rdataset_current(modified, &rdata);
00222                 (void)dns_rdata_tostruct(&rdata, &sig, NULL);
00223                 if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
00224                         goto next_rr;
00225                 }
00226                 if (when == 0 || sig.timeexpire < when)
00227                         when = sig.timeexpire;
00228  next_rr:
00229                 dns_rdata_reset(&rdata);
00230                 result = dns_rdataset_next(modified);
00231         }
00232         INSIST(result == ISC_R_NOMORE);
00233         return (when);
00234 }
00235 
00236 static void
00237 getownercase(dns_rdataset_t *rdataset, dns_name_t *name) {
00238         if (dns_rdataset_isassociated(rdataset))
00239                 dns_rdataset_getownercase(rdataset, name);
00240 }
00241 
00242 static void
00243 setownercase(dns_rdataset_t *rdataset, dns_name_t *name) {
00244         if (dns_rdataset_isassociated(rdataset))
00245                 dns_rdataset_setownercase(rdataset, name);
00246 }
00247 
00248 static isc_result_t
00249 diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
00250            isc_boolean_t warn)
00251 {
00252         dns_difftuple_t *t;
00253         dns_dbnode_t *node = NULL;
00254         isc_result_t result;
00255         char namebuf[DNS_NAME_FORMATSIZE];
00256         char typebuf[DNS_RDATATYPE_FORMATSIZE];
00257         char classbuf[DNS_RDATACLASS_FORMATSIZE];
00258 
00259         REQUIRE(DNS_DIFF_VALID(diff));
00260         REQUIRE(DNS_DB_VALID(db));
00261 
00262         t = ISC_LIST_HEAD(diff->tuples);
00263         while (t != NULL) {
00264                 dns_name_t *name;
00265 
00266                 INSIST(node == NULL);
00267                 name = &t->name;
00268                 /*
00269                  * Find the node.
00270                  * We create the node if it does not exist.
00271                  * This will cause an empty node to be created if the diff
00272                  * contains a deletion of an RR at a nonexistent name,
00273                  * but such diffs should never be created in the first
00274                  * place.
00275                  */
00276 
00277                 while (t != NULL && dns_name_equal(&t->name, name)) {
00278                         dns_rdatatype_t type, covers;
00279                         dns_diffop_t op;
00280                         dns_rdatalist_t rdl;
00281                         dns_rdataset_t rds;
00282                         dns_rdataset_t ardataset;
00283                         unsigned int options;
00284 
00285                         op = t->op;
00286                         type = t->rdata.type;
00287                         covers = rdata_covers(&t->rdata);
00288 
00289                         /*
00290                          * Collect a contiguous set of updates with
00291                          * the same operation (add/delete) and RR type
00292                          * into a single rdatalist so that the
00293                          * database rrset merging/subtraction code
00294                          * can work more efficiently than if each
00295                          * RR were merged into / subtracted from
00296                          * the database separately.
00297                          *
00298                          * This is done by linking rdata structures from the
00299                          * diff into "rdatalist".  This uses the rdata link
00300                          * field, not the diff link field, so the structure
00301                          * of the diff itself is not affected.
00302                          */
00303 
00304                         dns_rdatalist_init(&rdl);
00305                         rdl.type = type;
00306                         rdl.covers = covers;
00307                         rdl.rdclass = t->rdata.rdclass;
00308                         rdl.ttl = t->ttl;
00309 
00310                         node = NULL;
00311                         if (type != dns_rdatatype_nsec3 &&
00312                             covers != dns_rdatatype_nsec3)
00313                                 CHECK(dns_db_findnode(db, name, ISC_TRUE,
00314                                                       &node));
00315                         else
00316                                 CHECK(dns_db_findnsec3node(db, name, ISC_TRUE,
00317                                                            &node));
00318 
00319                         while (t != NULL &&
00320                                dns_name_equal(&t->name, name) &&
00321                                t->op == op &&
00322                                t->rdata.type == type &&
00323                                rdata_covers(&t->rdata) == covers)
00324                         {
00325                                 /*
00326                                  * Remember the add name for
00327                                  * dns_rdataset_setownercase.
00328                                  */
00329                                 name = &t->name;
00330                                 if (t->ttl != rdl.ttl && warn) {
00331                                         dns_name_format(name, namebuf,
00332                                                         sizeof(namebuf));
00333                                         dns_rdatatype_format(t->rdata.type,
00334                                                              typebuf,
00335                                                              sizeof(typebuf));
00336                                         dns_rdataclass_format(t->rdata.rdclass,
00337                                                               classbuf,
00338                                                               sizeof(classbuf));
00339                                         isc_log_write(DIFF_COMMON_LOGARGS,
00340                                                 ISC_LOG_WARNING,
00341                                                 "'%s/%s/%s': TTL differs in "
00342                                                 "rdataset, adjusting "
00343                                                 "%lu -> %lu",
00344                                                 namebuf, typebuf, classbuf,
00345                                                 (unsigned long) t->ttl,
00346                                                 (unsigned long) rdl.ttl);
00347                                 }
00348                                 ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
00349                                 t = ISC_LIST_NEXT(t, link);
00350                         }
00351 
00352                         /*
00353                          * Convert the rdatalist into a rdataset.
00354                          */
00355                         dns_rdataset_init(&rds);
00356                         dns_rdataset_init(&ardataset);
00357                         CHECK(dns_rdatalist_tordataset(&rdl, &rds));
00358                         rds.trust = dns_trust_ultimate;
00359 
00360                         /*
00361                          * Merge the rdataset into the database.
00362                          */
00363                         switch (op) {
00364                         case DNS_DIFFOP_ADD:
00365                         case DNS_DIFFOP_ADDRESIGN:
00366                                 options = DNS_DBADD_MERGE | DNS_DBADD_EXACT |
00367                                           DNS_DBADD_EXACTTTL;
00368                                 result = dns_db_addrdataset(db, node, ver,
00369                                                             0, &rds, options,
00370                                                             &ardataset);
00371                                 break;
00372                         case DNS_DIFFOP_DEL:
00373                         case DNS_DIFFOP_DELRESIGN:
00374                                 options = DNS_DBSUB_EXACT | DNS_DBSUB_WANTOLD;
00375                                 result = dns_db_subtractrdataset(db, node, ver,
00376                                                                  &rds, options,
00377                                                                  &ardataset);
00378                                 break;
00379                         default:
00380                                 INSIST(0);
00381                         }
00382 
00383                         if (result == ISC_R_SUCCESS) {
00384                                 if (rds.type == dns_rdatatype_rrsig &&
00385                                     (op == DNS_DIFFOP_DELRESIGN ||
00386                                      op == DNS_DIFFOP_ADDRESIGN)) {
00387                                         isc_stdtime_t resign;
00388                                         resign = setresign(&ardataset);
00389                                         dns_db_setsigningtime(db, &ardataset,
00390                                                               resign);
00391                                 }
00392                                 if (op == DNS_DIFFOP_ADD ||
00393                                     op == DNS_DIFFOP_ADDRESIGN)
00394                                         setownercase(&ardataset, name);
00395                                 if (op == DNS_DIFFOP_DEL ||
00396                                     op == DNS_DIFFOP_DELRESIGN)
00397                                         getownercase(&ardataset, name);
00398                         } else if (result == DNS_R_UNCHANGED) {
00399                                 /*
00400                                  * This will not happen when executing a
00401                                  * dynamic update, because that code will
00402                                  * generate strictly minimal diffs.
00403                                  * It may happen when receiving an IXFR
00404                                  * from a server that is not as careful.
00405                                  * Issue a warning and continue.
00406                                  */
00407                                 if (warn) {
00408                                         dns_name_format(dns_db_origin(db),
00409                                                         namebuf,
00410                                                         sizeof(namebuf));
00411                                         dns_rdataclass_format(dns_db_class(db),
00412                                                               classbuf,
00413                                                               sizeof(classbuf));
00414                                         isc_log_write(DIFF_COMMON_LOGARGS,
00415                                                       ISC_LOG_WARNING,
00416                                                       "%s/%s: dns_diff_apply: "
00417                                                       "update with no effect",
00418                                                       namebuf, classbuf);
00419                                 }
00420                                 if (op == DNS_DIFFOP_ADD ||
00421                                     op == DNS_DIFFOP_ADDRESIGN)
00422                                         setownercase(&ardataset, name);
00423                                 if (op == DNS_DIFFOP_DEL ||
00424                                     op == DNS_DIFFOP_DELRESIGN)
00425                                         getownercase(&ardataset, name);
00426                         } else if (result == DNS_R_NXRRSET) {
00427                                 /*
00428                                  * OK.
00429                                  */
00430                                 if (op == DNS_DIFFOP_DEL ||
00431                                     op == DNS_DIFFOP_DELRESIGN)
00432                                         getownercase(&ardataset, name);
00433                                 if (dns_rdataset_isassociated(&ardataset))
00434                                         dns_rdataset_disassociate(&ardataset);
00435                         } else {
00436                                 if (dns_rdataset_isassociated(&ardataset))
00437                                         dns_rdataset_disassociate(&ardataset);
00438                                 CHECK(result);
00439                         }
00440                         dns_db_detachnode(db, &node);
00441                         if (dns_rdataset_isassociated(&ardataset))
00442                                 dns_rdataset_disassociate(&ardataset);
00443                 }
00444         }
00445         return (ISC_R_SUCCESS);
00446 
00447  failure:
00448         if (node != NULL)
00449                 dns_db_detachnode(db, &node);
00450         return (result);
00451 }
00452 
00453 isc_result_t
00454 dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) {
00455         return (diff_apply(diff, db, ver, ISC_TRUE));
00456 }
00457 
00458 isc_result_t
00459 dns_diff_applysilently(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) {
00460         return (diff_apply(diff, db, ver, ISC_FALSE));
00461 }
00462 
00463 /* XXX this duplicates lots of code in diff_apply(). */
00464 
00465 isc_result_t
00466 dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
00467               void *add_private)
00468 {
00469         dns_difftuple_t *t;
00470         isc_result_t result;
00471 
00472         REQUIRE(DNS_DIFF_VALID(diff));
00473 
00474         t = ISC_LIST_HEAD(diff->tuples);
00475         while (t != NULL) {
00476                 dns_name_t *name;
00477 
00478                 name = &t->name;
00479                 while (t != NULL && dns_name_equal(&t->name, name)) {
00480                         dns_rdatatype_t type, covers;
00481                         dns_diffop_t op;
00482                         dns_rdatalist_t rdl;
00483                         dns_rdataset_t rds;
00484 
00485                         op = t->op;
00486                         type = t->rdata.type;
00487                         covers = rdata_covers(&t->rdata);
00488 
00489                         dns_rdatalist_init(&rdl);
00490                         rdl.type = type;
00491                         rdl.covers = covers;
00492                         rdl.rdclass = t->rdata.rdclass;
00493                         rdl.ttl = t->ttl;
00494 
00495                         while (t != NULL && dns_name_equal(&t->name, name) &&
00496                                t->op == op && t->rdata.type == type &&
00497                                rdata_covers(&t->rdata) == covers)
00498                         {
00499                                 ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
00500                                 t = ISC_LIST_NEXT(t, link);
00501                         }
00502 
00503                         /*
00504                          * Convert the rdatalist into a rdataset.
00505                          */
00506                         dns_rdataset_init(&rds);
00507                         CHECK(dns_rdatalist_tordataset(&rdl, &rds));
00508                         rds.trust = dns_trust_ultimate;
00509 
00510                         INSIST(op == DNS_DIFFOP_ADD);
00511                         result = (*addfunc)(add_private, name, &rds);
00512                         if (result == DNS_R_UNCHANGED) {
00513                                 isc_log_write(DIFF_COMMON_LOGARGS,
00514                                               ISC_LOG_WARNING,
00515                                               "dns_diff_load: "
00516                                               "update with no effect");
00517                         } else if (result == ISC_R_SUCCESS ||
00518                                    result == DNS_R_NXRRSET) {
00519                                 /*
00520                                  * OK.
00521                                  */
00522                         } else {
00523                                 CHECK(result);
00524                         }
00525                 }
00526         }
00527         result = ISC_R_SUCCESS;
00528  failure:
00529         return (result);
00530 }
00531 
00532 /*
00533  * XXX uses qsort(); a merge sort would be more natural for lists,
00534  * and perhaps safer wrt thread stack overflow.
00535  */
00536 isc_result_t
00537 dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
00538         unsigned int length = 0;
00539         unsigned int i;
00540         dns_difftuple_t **v;
00541         dns_difftuple_t *p;
00542         REQUIRE(DNS_DIFF_VALID(diff));
00543 
00544         for (p = ISC_LIST_HEAD(diff->tuples);
00545              p != NULL;
00546              p = ISC_LIST_NEXT(p, link))
00547                 length++;
00548         if (length == 0)
00549                 return (ISC_R_SUCCESS);
00550         v = isc_mem_get(diff->mctx, length * sizeof(dns_difftuple_t *));
00551         if (v == NULL)
00552                 return (ISC_R_NOMEMORY);
00553         for (i = 0; i < length; i++) {
00554                 p = ISC_LIST_HEAD(diff->tuples);
00555                 v[i] = p;
00556                 ISC_LIST_UNLINK(diff->tuples, p, link);
00557         }
00558         INSIST(ISC_LIST_HEAD(diff->tuples) == NULL);
00559         qsort(v, length, sizeof(v[0]), compare);
00560         for (i = 0; i < length; i++) {
00561                 ISC_LIST_APPEND(diff->tuples, v[i], link);
00562         }
00563         isc_mem_put(diff->mctx, v, length * sizeof(dns_difftuple_t *));
00564         return (ISC_R_SUCCESS);
00565 }
00566 
00567 
00568 /*
00569  * Create an rdataset containing the single RR of the given
00570  * tuple.  The caller must allocate the rdata, rdataset and
00571  * an rdatalist structure for it to refer to.
00572  */
00573 
00574 static isc_result_t
00575 diff_tuple_tordataset(dns_difftuple_t *t, dns_rdata_t *rdata,
00576                       dns_rdatalist_t *rdl, dns_rdataset_t *rds)
00577 {
00578         REQUIRE(DNS_DIFFTUPLE_VALID(t));
00579         REQUIRE(rdl != NULL);
00580         REQUIRE(rds != NULL);
00581 
00582         dns_rdatalist_init(rdl);
00583         rdl->type = t->rdata.type;
00584         rdl->rdclass = t->rdata.rdclass;
00585         rdl->ttl = t->ttl;
00586         dns_rdataset_init(rds);
00587         ISC_LINK_INIT(rdata, link);
00588         dns_rdata_clone(&t->rdata, rdata);
00589         ISC_LIST_APPEND(rdl->rdata, rdata, link);
00590         return (dns_rdatalist_tordataset(rdl, rds));
00591 }
00592 
00593 isc_result_t
00594 dns_diff_print(dns_diff_t *diff, FILE *file) {
00595         isc_result_t result;
00596         dns_difftuple_t *t;
00597         char *mem = NULL;
00598         unsigned int size = 2048;
00599         const char *op = NULL;
00600 
00601         REQUIRE(DNS_DIFF_VALID(diff));
00602 
00603         mem = isc_mem_get(diff->mctx, size);
00604         if (mem == NULL)
00605                 return (ISC_R_NOMEMORY);
00606 
00607         for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
00608              t = ISC_LIST_NEXT(t, link))
00609         {
00610                 isc_buffer_t buf;
00611                 isc_region_t r;
00612 
00613                 dns_rdatalist_t rdl;
00614                 dns_rdataset_t rds;
00615                 dns_rdata_t rd = DNS_RDATA_INIT;
00616 
00617                 result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
00618                 if (result != ISC_R_SUCCESS) {
00619                         UNEXPECTED_ERROR(__FILE__, __LINE__,
00620                                          "diff_tuple_tordataset failed: %s",
00621                                          dns_result_totext(result));
00622                         result =  ISC_R_UNEXPECTED;
00623                         goto cleanup;
00624                 }
00625  again:
00626                 isc_buffer_init(&buf, mem, size);
00627                 result = dns_rdataset_totext(&rds, &t->name,
00628                                              ISC_FALSE, ISC_FALSE, &buf);
00629 
00630                 if (result == ISC_R_NOSPACE) {
00631                         isc_mem_put(diff->mctx, mem, size);
00632                         size += 1024;
00633                         mem = isc_mem_get(diff->mctx, size);
00634                         if (mem == NULL) {
00635                                 result = ISC_R_NOMEMORY;
00636                                 goto cleanup;
00637                         }
00638                         goto again;
00639                 }
00640 
00641                 if (result != ISC_R_SUCCESS)
00642                         goto cleanup;
00643                 /*
00644                  * Get rid of final newline.
00645                  */
00646                 INSIST(buf.used >= 1 &&
00647                        ((char *) buf.base)[buf.used-1] == '\n');
00648                 buf.used--;
00649 
00650                 isc_buffer_usedregion(&buf, &r);
00651                 switch (t->op) {
00652                 case DNS_DIFFOP_EXISTS: op = "exists"; break;
00653                 case DNS_DIFFOP_ADD: op = "add"; break;
00654                 case DNS_DIFFOP_DEL: op = "del"; break;
00655                 case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
00656                 case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
00657                 }
00658                 if (file != NULL)
00659                         fprintf(file, "%s %.*s\n", op, (int) r.length,
00660                                 (char *) r.base);
00661                 else
00662                         isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
00663                                       "%s %.*s", op, (int) r.length,
00664                                       (char *) r.base);
00665         }
00666         result = ISC_R_SUCCESS;
00667  cleanup:
00668         if (mem != NULL)
00669                 isc_mem_put(diff->mctx, mem, size);
00670         return (result);
00671 }

Generated on Tue Apr 28 17:40:56 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha