1/*
2 * Copyright (C) 2002  Nuno M. Rodrigues.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
11 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: zone2bdb.c,v 1.3 2009/09/01 00:22:26 jinmei Exp $ */
19
20#include <stdio.h>
21
22#include <isc/mem.h>
23#include <isc/result.h>
24#include <isc/types.h>
25#include <isc/util.h>
26
27#include <dns/db.h>
28#include <dns/dbiterator.h>
29#include <dns/fixedname.h>
30#include <dns/name.h>
31#include <dns/rdata.h>
32#include <dns/rdataset.h>
33#include <dns/rdatasetiter.h>
34#include <dns/rdatatype.h>
35#include <dns/ttl.h>
36#include <dns/types.h>
37
38#include <db.h>
39
40#define MAX_RDATATEXT	63 + 4 + 65535 + 2	/* ttl + type + rdata + sep */
41
42/*
43 * Returns a valid 'DB' handle.
44 *
45 * Requires:
46 *	'file' is a valid non-existant path.
47 */
48DB *
49bdb_init(const char *file)
50{
51	DB *db;
52
53	REQUIRE(db_create(&db, NULL, 0) == 0);
54	REQUIRE(db->set_flags(db, DB_DUP) == 0);
55	REQUIRE(db->open(db, file, NULL, DB_HASH, DB_CREATE | DB_EXCL, 0) == 0);
56
57	return db;
58}
59
60/*
61 * Puts resource record data on 'db'.
62 */
63isc_result_t
64bdb_putrdata(DB *db, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
65{
66	static DBT key, data;
67	isc_buffer_t keybuf, databuf;
68	char nametext[DNS_NAME_MAXTEXT];
69	char rdatatext[MAX_RDATATEXT];
70
71	isc_buffer_init(&keybuf, nametext, DNS_NAME_MAXTEXT);
72
73	dns_name_totext(name, ISC_TRUE, &keybuf);
74
75	key.data = isc_buffer_base(&keybuf);
76	key.size = isc_buffer_usedlength(&keybuf);
77
78	isc_buffer_init(&databuf, rdatatext, MAX_RDATATEXT);
79
80	dns_ttl_totext(ttl, ISC_FALSE, &databuf);
81	*(char *)isc_buffer_used(&databuf) = ' ';
82	isc_buffer_add(&databuf, 1);
83
84	dns_rdatatype_totext(rdata->type, &databuf);	/* XXX private data */
85	*(char *)isc_buffer_used(&databuf) = ' ';
86	isc_buffer_add(&databuf, 1);
87
88	dns_rdata_totext(rdata, NULL, &databuf);
89
90	data.data = isc_buffer_base(&databuf);
91	data.size = isc_buffer_usedlength(&databuf);
92
93	REQUIRE(db->put(db, NULL, &key, &data, 0) == 0);
94
95	return ISC_R_SUCCESS;
96}
97
98isc_result_t
99bdb_destroy(DB *db)
100{
101
102	return (db->close(db, 0) == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE;
103}
104
105void
106usage(const char *prog)
107{
108
109	fprintf(stderr, "Usage: %s <origin> <zonefile> <db>\n", prog);
110	exit(1);
111}
112
113int
114main(int argc, char *argv[])
115{
116	isc_mem_t *mctx = NULL;
117	isc_buffer_t b;
118	int n;
119	dns_fixedname_t origin, name;
120	dns_db_t *db = NULL;
121	dns_dbiterator_t *dbiter = NULL;
122	isc_result_t res;
123	dns_dbnode_t *node = NULL;
124	dns_rdataset_t rdataset;
125	dns_rdatasetiter_t *rdatasetiter = NULL;
126	dns_rdata_t rdata;
127	DB *bdb;
128
129	if (argc != 4) usage(*argv);
130
131	REQUIRE(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
132
133	n = strlen(argv[1]);
134	isc_buffer_init(&b, argv[1], n);
135	isc_buffer_add(&b, n);
136
137	dns_fixedname_init(&origin);
138
139	REQUIRE(dns_name_fromtext(dns_fixedname_name(&origin), &b, dns_rootname,
140				  0, NULL) == ISC_R_SUCCESS);
141	REQUIRE(dns_db_create(mctx, "rbt", dns_fixedname_name(&origin),
142			      dns_dbtype_zone, dns_rdataclass_in, 0, NULL,
143			      &db) == ISC_R_SUCCESS);
144
145	REQUIRE(dns_db_load(db, argv[2]) == ISC_R_SUCCESS);
146
147	REQUIRE(dns_db_createiterator(db, 0, &dbiter) == ISC_R_SUCCESS);
148
149	dns_rdataset_init(&rdataset);
150	dns_rdata_init(&rdata);
151	dns_fixedname_init(&name);
152	bdb = bdb_init(argv[3]);
153
154	for (res = dns_dbiterator_first(dbiter); res == ISC_R_SUCCESS;
155	    res = dns_dbiterator_next(dbiter)) {
156		dns_dbiterator_current(dbiter, &node, dns_fixedname_name(&name));
157		REQUIRE(dns_db_allrdatasets(db, node, NULL, 0, &rdatasetiter)
158		    == ISC_R_SUCCESS);
159
160		for (res = dns_rdatasetiter_first(rdatasetiter);
161		    res == ISC_R_SUCCESS;
162		    res = dns_rdatasetiter_next(rdatasetiter)) {
163			dns_rdatasetiter_current(rdatasetiter, &rdataset);
164
165			res = dns_rdataset_first(&rdataset);
166			while (res == ISC_R_SUCCESS) {
167				dns_rdataset_current(&rdataset, &rdata);
168				REQUIRE(bdb_putrdata(bdb,
169						     dns_fixedname_name(&name),
170						     rdataset.ttl, &rdata)
171					== ISC_R_SUCCESS);
172
173				dns_rdata_reset(&rdata);
174				res = dns_rdataset_next(&rdataset);
175			}
176
177			dns_rdataset_disassociate(&rdataset);
178		}
179		dns_rdatasetiter_destroy(&rdatasetiter);
180		dns_db_detachnode(db, &node);
181	}
182	dns_dbiterator_destroy(&dbiter);
183
184	REQUIRE(bdb_destroy(bdb) == ISC_R_SUCCESS);
185
186	return 0;
187}
188