/* * Authors: Petr Spacek * * Copyright (C) 2012 Red Hat * see file 'COPYING' for use and warranty information * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; version 2 or later * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include void logger(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } #define CHECK(op) \ do { \ logger("%4u: %s = ", __LINE__, #op); \ result = (op); \ logger("%s\n", dns_result_totext(result)); \ if (result != ISC_R_SUCCESS) \ goto cleanup; \ } while (0) #define PRINT(op) \ do { \ logger("%4u: %s\n", __LINE__, #op); \ (op); \ } while (0) static isc_result_t do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { dns_diff_t temp_diff; isc_result_t result; /* * Create a singleton diff. */ dns_diff_init(diff->mctx, &temp_diff); temp_diff.resign = diff->resign; ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); /* * Apply it to the database. */ result = dns_diff_apply(&temp_diff, db, ver); ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); if (result != ISC_R_SUCCESS) { dns_difftuple_free(tuple); return (result); } /* * Merge it into the current pending journal entry. */ dns_diff_appendminimal(diff, tuple); /* * Do not clear temp_diff. */ return (ISC_R_SUCCESS); } static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) { dns_difftuple_t *tuple = NULL; isc_result_t result; result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple); if (result != ISC_R_SUCCESS) return (result); return (do_one_tuple(&tuple, db, ver, diff)); } /* * Create an SOA record for a newly-created zone */ static isc_result_t add_soa(dns_db_t *db, dns_dbversion_t *ver) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char buf[DNS_SOA_BUFFERSIZE]; dns_diff_t diff; dns_diff_init(db->mctx, &diff); /* Build SOA record */ result = dns_soa_buildrdata(dns_rootname, dns_rootname, dns_rdataclass_in, 0, 0, 0, 0, 0, buf, &rdata); if (result != ISC_R_SUCCESS) { logger("add_soa:dns_soa_buildrdata -> %s", dns_result_totext(result)); goto failure; } result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, dns_rootname, 0, &rdata); failure: dns_diff_clear(&diff); return (result); } int main (int argc, char ** argv) { isc_result_t result = ISC_R_SUCCESS; dns_db_t *rbtdb = NULL; isc_mem_t *mctx = NULL; void *node = NULL; dns_dbversion_t *version = NULL; CHECK(isc_mem_create2(0, 0, &mctx, ISC_MEMFLAG_DEFAULT)); CHECK(isc_hash_create(mctx, NULL, 256)); CHECK(dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &rbtdb)); CHECK(dns_db_getoriginnode(rbtdb, &node)); /* This still works, references == 1. */ PRINT(dns_db_printnode(rbtdb, node, stderr)); PRINT(dns_db_detachnode(rbtdb, &node)); /* I think that the origin_node is invalid here. */ CHECK(dns_db_newversion(rbtdb, &version)); /* Following block crashes, so I commented it out. */ /* { CHECK(dns_db_getoriginnode(rbtdb, &node)); PRINT(dns_db_printnode(rbtdb, node, stderr)); PRINT(dns_db_detachnode(rbtdb, &node)); } */ /* New origin_node is created in dns_diff_apply() call. */ CHECK(add_soa(rbtdb, version)); /* This works again, references == 2. */ CHECK(dns_db_getoriginnode(rbtdb, &node)); PRINT(dns_db_printnode(rbtdb, node, stderr)); /* Discard the new record from RBTDB. */ PRINT(dns_db_closeversion(rbtdb, &version, ISC_FALSE)); /* This still works, references == 1. */ PRINT(dns_db_printnode(rbtdb, node, stderr)); /* RDATASET_ATTR_IGNORE is set! */ PRINT(dns_db_detachnode(rbtdb, &node)); /* Next block crashes again - origin_node is invalid (again). */ { CHECK(dns_db_getoriginnode(rbtdb, &node)); PRINT(dns_db_printnode(rbtdb, node, stderr)); PRINT(dns_db_detachnode(rbtdb, &node)); } cleanup: if (result != ISC_R_SUCCESS) logger("error: %s\n", dns_result_totext(result)); (void) argc; (void) argv; return 0; }