1/* $NetBSD: nsecify.c,v 1.2.6.1 2012/06/05 21:15:19 bouyer Exp $ */ 2 3/* 4 * Copyright (C) 2004, 2007-2009, 2011 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id: nsecify.c,v 1.12 2011/08/29 23:46:44 tbox Exp */ 21 22#include <config.h> 23 24#include <stdlib.h> 25 26#include <isc/mem.h> 27#include <isc/print.h> 28#include <isc/string.h> 29 30#include <dns/db.h> 31#include <dns/dbiterator.h> 32#include <dns/fixedname.h> 33#include <dns/nsec.h> 34#include <dns/rdataset.h> 35#include <dns/rdatasetiter.h> 36#include <dns/result.h> 37 38static isc_mem_t *mctx = NULL; 39 40static inline void 41fatal(const char *message) { 42 fprintf(stderr, "%s\n", message); 43 exit(1); 44} 45 46static inline void 47check_result(isc_result_t result, const char *message) { 48 if (result != ISC_R_SUCCESS) { 49 fprintf(stderr, "%s: %s\n", message, 50 isc_result_totext(result)); 51 exit(1); 52 } 53} 54 55static inline isc_boolean_t 56active_node(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { 57 dns_rdatasetiter_t *rdsiter; 58 isc_boolean_t active = ISC_FALSE; 59 isc_result_t result; 60 dns_rdataset_t rdataset; 61 62 dns_rdataset_init(&rdataset); 63 rdsiter = NULL; 64 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); 65 check_result(result, "dns_db_allrdatasets()"); 66 result = dns_rdatasetiter_first(rdsiter); 67 while (result == ISC_R_SUCCESS) { 68 dns_rdatasetiter_current(rdsiter, &rdataset); 69 if (rdataset.type != dns_rdatatype_nsec) 70 active = ISC_TRUE; 71 dns_rdataset_disassociate(&rdataset); 72 if (!active) 73 result = dns_rdatasetiter_next(rdsiter); 74 else 75 result = ISC_R_NOMORE; 76 } 77 if (result != ISC_R_NOMORE) 78 fatal("rdataset iteration failed"); 79 dns_rdatasetiter_destroy(&rdsiter); 80 81 if (!active) { 82 /* 83 * Make sure there is no NSEC record for this node. 84 */ 85 result = dns_db_deleterdataset(db, node, version, 86 dns_rdatatype_nsec, 0); 87 if (result == DNS_R_UNCHANGED) 88 result = ISC_R_SUCCESS; 89 check_result(result, "dns_db_deleterdataset"); 90 } 91 92 return (active); 93} 94 95static inline isc_result_t 96next_active(dns_db_t *db, dns_dbversion_t *version, dns_dbiterator_t *dbiter, 97 dns_name_t *name, dns_dbnode_t **nodep) 98{ 99 isc_result_t result; 100 isc_boolean_t active; 101 102 do { 103 active = ISC_FALSE; 104 result = dns_dbiterator_current(dbiter, nodep, name); 105 if (result == ISC_R_SUCCESS) { 106 active = active_node(db, version, *nodep); 107 if (!active) { 108 dns_db_detachnode(db, nodep); 109 result = dns_dbiterator_next(dbiter); 110 } 111 } 112 } while (result == ISC_R_SUCCESS && !active); 113 114 return (result); 115} 116 117static void 118nsecify(char *filename) { 119 isc_result_t result; 120 dns_db_t *db; 121 dns_dbversion_t *wversion; 122 dns_dbnode_t *node, *nextnode; 123 char *origintext; 124 dns_fixedname_t fname, fnextname; 125 dns_name_t *name, *nextname, *target; 126 isc_buffer_t b; 127 size_t len; 128 dns_dbiterator_t *dbiter; 129 char newfilename[1024]; 130 131 dns_fixedname_init(&fname); 132 name = dns_fixedname_name(&fname); 133 dns_fixedname_init(&fnextname); 134 nextname = dns_fixedname_name(&fnextname); 135 136 origintext = strrchr(filename, '/'); 137 if (origintext == NULL) 138 origintext = filename; 139 else 140 origintext++; /* Skip '/'. */ 141 len = strlen(origintext); 142 isc_buffer_init(&b, origintext, len); 143 isc_buffer_add(&b, len); 144 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); 145 check_result(result, "dns_name_fromtext()"); 146 147 db = NULL; 148 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, 149 dns_rdataclass_in, 0, NULL, &db); 150 check_result(result, "dns_db_create()"); 151 result = dns_db_load(db, filename); 152 if (result == DNS_R_SEENINCLUDE) 153 result = ISC_R_SUCCESS; 154 check_result(result, "dns_db_load()"); 155 wversion = NULL; 156 result = dns_db_newversion(db, &wversion); 157 check_result(result, "dns_db_newversion()"); 158 dbiter = NULL; 159 result = dns_db_createiterator(db, 0, &dbiter); 160 check_result(result, "dns_db_createiterator()"); 161 result = dns_dbiterator_first(dbiter); 162 check_result(result, "dns_dbiterator_first()"); 163 node = NULL; 164 result = next_active(db, wversion, dbiter, name, &node); 165 while (result == ISC_R_SUCCESS) { 166 nextnode = NULL; 167 result = dns_dbiterator_next(dbiter); 168 if (result == ISC_R_SUCCESS) 169 result = next_active(db, wversion, dbiter, nextname, 170 &nextnode); 171 if (result == ISC_R_SUCCESS) 172 target = nextname; 173 else if (result == ISC_R_NOMORE) 174 target = dns_db_origin(db); 175 else { 176 target = NULL; /* Make compiler happy. */ 177 fatal("db iteration failed"); 178 } 179 dns_nsec_build(db, wversion, node, target, 3600); /* XXX BEW */ 180 dns_db_detachnode(db, &node); 181 node = nextnode; 182 } 183 if (result != ISC_R_NOMORE) 184 fatal("db iteration failed"); 185 dns_dbiterator_destroy(&dbiter); 186 /* 187 * XXXRTH For now, we don't increment the SOA serial. 188 */ 189 dns_db_closeversion(db, &wversion, ISC_TRUE); 190 len = strlen(filename); 191 if (len + 4 + 1 > sizeof(newfilename)) 192 fatal("filename too long"); 193 sprintf(newfilename, "%s.new", filename); 194 result = dns_db_dump(db, NULL, newfilename); 195 check_result(result, "dns_db_dump"); 196 dns_db_detach(&db); 197} 198 199int 200main(int argc, char *argv[]) { 201 int i; 202 isc_result_t result; 203 204 dns_result_register(); 205 206 result = isc_mem_create(0, 0, &mctx); 207 check_result(result, "isc_mem_create()"); 208 209 argc--; 210 argv++; 211 212 for (i = 0; i < argc; i++) 213 nsecify(argv[i]); 214 215 /* isc_mem_stats(mctx, stdout); */ 216 isc_mem_destroy(&mctx); 217 218 return (0); 219} 220