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