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