1 /* $NetBSD: zonetodb.c,v 1.4 2014/12/10 04:37:57 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007-2009, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2002 Internet Software Consortium.
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.
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.
20 /* Id: zonetodb.c,v 1.23 2009/09/02 23:48:01 tbox Exp */
25 #include <isc/buffer.h>
26 #include <isc/entropy.h>
29 #include <isc/print.h>
30 #include <isc/result.h>
33 #include <dns/dbiterator.h>
34 #include <dns/fixedname.h>
36 #include <dns/rdata.h>
37 #include <dns/rdataset.h>
38 #include <dns/rdatasetiter.h>
39 #include <dns/rdatatype.h>
40 #include <dns/result.h>
42 #include <pgsql/libpq-fe.h>
45 * Generate a PostgreSQL table from a zone.
47 * This is compiled this with something like the following (assuming bind9 has
50 * gcc -g `isc-config.sh --cflags isc dns` -c zonetodb.c
51 * gcc -g -o zonetodb zonetodb.o `isc-config.sh --libs isc dns` -lpq
55 char *dbname
, *dbtable
;
59 closeandexit(int status
) {
66 check_result(isc_result_t result
, const char *message
) {
67 if (result
!= ISC_R_SUCCESS
) {
68 fprintf(stderr
, "%s: %s\n", message
,
69 isc_result_totext(result
));
75 * Canonicalize a string before writing it to the database.
76 * "dest" must be an array of at least size 2*strlen(source) + 1.
79 quotestring(const unsigned char *source
, unsigned char *dest
) {
80 while (*source
!= 0) {
83 else if (*source
== '\\')
91 addrdata(dns_name_t
*name
, dns_ttl_t ttl
, dns_rdata_t
*rdata
) {
92 unsigned char namearray
[DNS_NAME_MAXTEXT
+ 1];
93 unsigned char canonnamearray
[2 * DNS_NAME_MAXTEXT
+ 1];
94 unsigned char typearray
[20];
95 unsigned char canontypearray
[40];
96 unsigned char dataarray
[2048];
97 unsigned char canondataarray
[4096];
102 isc_buffer_init(&b
, namearray
, sizeof(namearray
) - 1);
103 result
= dns_name_totext(name
, ISC_TRUE
, &b
);
104 check_result(result
, "dns_name_totext");
105 namearray
[isc_buffer_usedlength(&b
)] = 0;
106 quotestring((const unsigned char *)namearray
, canonnamearray
);
108 isc_buffer_init(&b
, typearray
, sizeof(typearray
) - 1);
109 result
= dns_rdatatype_totext(rdata
->type
, &b
);
110 check_result(result
, "dns_rdatatype_totext");
111 typearray
[isc_buffer_usedlength(&b
)] = 0;
112 quotestring((const unsigned char *)typearray
, canontypearray
);
114 isc_buffer_init(&b
, dataarray
, sizeof(dataarray
) - 1);
115 result
= dns_rdata_totext(rdata
, NULL
, &b
);
116 check_result(result
, "dns_rdata_totext");
117 dataarray
[isc_buffer_usedlength(&b
)] = 0;
118 quotestring((const unsigned char *)dataarray
, canondataarray
);
120 snprintf(str
, sizeof(str
),
121 "INSERT INTO %s (NAME, TTL, RDTYPE, RDATA)"
122 " VALUES ('%s', %d, '%s', '%s')",
123 dbtable
, canonnamearray
, ttl
, canontypearray
, canondataarray
);
125 res
= PQexec(conn
, str
);
126 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
) {
127 fprintf(stderr
, "INSERT INTO command failed: %s\n",
128 PQresultErrorMessage(res
));
136 main(int argc
, char **argv
) {
137 char *porigin
, *zonefile
;
138 dns_fixedname_t forigin
, fname
;
139 dns_name_t
*origin
, *name
;
141 dns_dbiterator_t
*dbiter
;
143 dns_rdatasetiter_t
*rdsiter
;
144 dns_rdataset_t rdataset
;
145 dns_rdata_t rdata
= DNS_RDATA_INIT
;
146 isc_mem_t
*mctx
= NULL
;
147 isc_entropy_t
*ectx
= NULL
;
153 printf("usage: %s origin file dbname dbtable\n", argv
[0]);
154 printf("Note that dbname must be an existing database.\n");
163 dns_result_register();
166 result
= isc_mem_create(0, 0, &mctx
);
167 check_result(result
, "isc_mem_create");
169 result
= isc_entropy_create(mctx
, &ectx
);
170 check_result(result
, "isc_entropy_create");
172 result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
173 check_result(result
, "isc_hash_create");
175 isc_buffer_init(&b
, porigin
, strlen(porigin
));
176 isc_buffer_add(&b
, strlen(porigin
));
177 dns_fixedname_init(&forigin
);
178 origin
= dns_fixedname_name(&forigin
);
179 result
= dns_name_fromtext(origin
, &b
, dns_rootname
, 0, NULL
);
180 check_result(result
, "dns_name_fromtext");
183 result
= dns_db_create(mctx
, "rbt", origin
, dns_dbtype_zone
,
184 dns_rdataclass_in
, 0, NULL
, &db
);
185 check_result(result
, "dns_db_create");
187 result
= dns_db_load(db
, zonefile
);
188 if (result
== DNS_R_SEENINCLUDE
)
189 result
= ISC_R_SUCCESS
;
190 check_result(result
, "dns_db_load");
192 printf("Connecting to '%s'\n", dbname
);
193 conn
= PQsetdb(NULL
, NULL
, NULL
, NULL
, dbname
);
194 if (PQstatus(conn
) == CONNECTION_BAD
) {
195 fprintf(stderr
, "Connection to database '%s' failed: %s\n",
196 dbname
, PQerrorMessage(conn
));
200 snprintf(str
, sizeof(str
),
201 "DROP TABLE %s", dbtable
);
203 res
= PQexec(conn
, str
);
204 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
)
205 fprintf(stderr
, "DROP TABLE command failed: %s\n",
206 PQresultErrorMessage(res
));
209 snprintf(str
, sizeof(str
), "BEGIN");
211 res
= PQexec(conn
, str
);
212 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
) {
213 fprintf(stderr
, "BEGIN command failed: %s\n",
214 PQresultErrorMessage(res
));
220 snprintf(str
, sizeof(str
),
222 "(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT)",
225 res
= PQexec(conn
, str
);
226 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
) {
227 fprintf(stderr
, "CREATE TABLE command failed: %s\n",
228 PQresultErrorMessage(res
));
235 result
= dns_db_createiterator(db
, 0, &dbiter
);
236 check_result(result
, "dns_db_createiterator()");
238 result
= dns_dbiterator_first(dbiter
);
239 check_result(result
, "dns_dbiterator_first");
241 dns_fixedname_init(&fname
);
242 name
= dns_fixedname_name(&fname
);
243 dns_rdataset_init(&rdataset
);
244 dns_rdata_init(&rdata
);
246 while (result
== ISC_R_SUCCESS
) {
248 result
= dns_dbiterator_current(dbiter
, &node
, name
);
249 if (result
== ISC_R_NOMORE
)
251 check_result(result
, "dns_dbiterator_current");
254 result
= dns_db_allrdatasets(db
, node
, NULL
, 0, &rdsiter
);
255 check_result(result
, "dns_db_allrdatasets");
257 result
= dns_rdatasetiter_first(rdsiter
);
259 while (result
== ISC_R_SUCCESS
) {
260 dns_rdatasetiter_current(rdsiter
, &rdataset
);
261 result
= dns_rdataset_first(&rdataset
);
262 check_result(result
, "dns_rdataset_first");
263 while (result
== ISC_R_SUCCESS
) {
264 dns_rdataset_current(&rdataset
, &rdata
);
265 addrdata(name
, rdataset
.ttl
, &rdata
);
266 dns_rdata_reset(&rdata
);
267 result
= dns_rdataset_next(&rdataset
);
269 dns_rdataset_disassociate(&rdataset
);
270 result
= dns_rdatasetiter_next(rdsiter
);
272 dns_rdatasetiter_destroy(&rdsiter
);
273 dns_db_detachnode(db
, &node
);
274 result
= dns_dbiterator_next(dbiter
);
277 snprintf(str
, sizeof(str
), "COMMIT TRANSACTION");
279 res
= PQexec(conn
, str
);
280 if (!res
|| PQresultStatus(res
) != PGRES_COMMAND_OK
) {
281 fprintf(stderr
, "COMMIT command failed: %s\n",
282 PQresultErrorMessage(res
));
287 dns_dbiterator_destroy(&dbiter
);
290 isc_entropy_detach(&ectx
);
291 isc_mem_destroy(&mctx
);