xref: /minix3/external/bsd/bind/dist/contrib/sdb/pgsql/pgsqldb.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: pgsqldb.c,v 1.4 2014/12/10 04:37:57 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2007, 2011, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000, 2001  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: pgsqldb.c,v 1.17 2011/10/11 23:46:45 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <stdio.h>
25*00b67f09SDavid van Moolenbroek #include <string.h>
26*00b67f09SDavid van Moolenbroek #include <stdlib.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <pgsql/libpq-fe.h>
29*00b67f09SDavid van Moolenbroek 
30*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
31*00b67f09SDavid van Moolenbroek #include <isc/print.h>
32*00b67f09SDavid van Moolenbroek #include <isc/result.h>
33*00b67f09SDavid van Moolenbroek #include <isc/util.h>
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek #include <dns/sdb.h>
36*00b67f09SDavid van Moolenbroek #include <dns/result.h>
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek #include <named/globals.h>
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek #include "pgsqldb.h"
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek /*
43*00b67f09SDavid van Moolenbroek  * A simple database driver that interfaces to a PostgreSQL database.  This
44*00b67f09SDavid van Moolenbroek  * is not complete, and not designed for general use.  It opens one
45*00b67f09SDavid van Moolenbroek  * connection to the database per zone, which is inefficient.  It also may
46*00b67f09SDavid van Moolenbroek  * not handle quoting correctly.
47*00b67f09SDavid van Moolenbroek  *
48*00b67f09SDavid van Moolenbroek  * The table must contain the fields "name", "rdtype", and "rdata", and
49*00b67f09SDavid van Moolenbroek  * is expected to contain a properly constructed zone.  The program "zonetodb"
50*00b67f09SDavid van Moolenbroek  * creates such a table.
51*00b67f09SDavid van Moolenbroek  */
52*00b67f09SDavid van Moolenbroek 
53*00b67f09SDavid van Moolenbroek static dns_sdbimplementation_t *pgsqldb = NULL;
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek struct dbinfo {
56*00b67f09SDavid van Moolenbroek 	PGconn *conn;
57*00b67f09SDavid van Moolenbroek 	char *database;
58*00b67f09SDavid van Moolenbroek 	char *table;
59*00b67f09SDavid van Moolenbroek 	char *host;
60*00b67f09SDavid van Moolenbroek 	char *user;
61*00b67f09SDavid van Moolenbroek 	char *passwd;
62*00b67f09SDavid van Moolenbroek };
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek static void
65*00b67f09SDavid van Moolenbroek pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata);
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek /*
68*00b67f09SDavid van Moolenbroek  * Canonicalize a string before writing it to the database.
69*00b67f09SDavid van Moolenbroek  * "dest" must be an array of at least size 2*strlen(source) + 1.
70*00b67f09SDavid van Moolenbroek  */
71*00b67f09SDavid van Moolenbroek static void
quotestring(const char * source,char * dest)72*00b67f09SDavid van Moolenbroek quotestring(const char *source, char *dest) {
73*00b67f09SDavid van Moolenbroek 	while (*source != 0) {
74*00b67f09SDavid van Moolenbroek 		if (*source == '\'')
75*00b67f09SDavid van Moolenbroek 			*dest++ = '\'';
76*00b67f09SDavid van Moolenbroek 		/* SQL doesn't treat \ as special, but PostgreSQL does */
77*00b67f09SDavid van Moolenbroek 		else if (*source == '\\')
78*00b67f09SDavid van Moolenbroek 			*dest++ = '\\';
79*00b67f09SDavid van Moolenbroek 		*dest++ = *source++;
80*00b67f09SDavid van Moolenbroek 	}
81*00b67f09SDavid van Moolenbroek 	*dest++ = 0;
82*00b67f09SDavid van Moolenbroek }
83*00b67f09SDavid van Moolenbroek 
84*00b67f09SDavid van Moolenbroek /*
85*00b67f09SDavid van Moolenbroek  * Connect to the database.
86*00b67f09SDavid van Moolenbroek  */
87*00b67f09SDavid van Moolenbroek static isc_result_t
db_connect(struct dbinfo * dbi)88*00b67f09SDavid van Moolenbroek db_connect(struct dbinfo *dbi) {
89*00b67f09SDavid van Moolenbroek 	dbi->conn = PQsetdbLogin(dbi->host, NULL, NULL, NULL, dbi->database,
90*00b67f09SDavid van Moolenbroek 				 dbi->user, dbi->passwd);
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek 	if (PQstatus(dbi->conn) == CONNECTION_OK)
93*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
94*00b67f09SDavid van Moolenbroek 	else
95*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
96*00b67f09SDavid van Moolenbroek }
97*00b67f09SDavid van Moolenbroek 
98*00b67f09SDavid van Moolenbroek /*
99*00b67f09SDavid van Moolenbroek  * Check to see if the connection is still valid.  If not, attempt to
100*00b67f09SDavid van Moolenbroek  * reconnect.
101*00b67f09SDavid van Moolenbroek  */
102*00b67f09SDavid van Moolenbroek static isc_result_t
maybe_reconnect(struct dbinfo * dbi)103*00b67f09SDavid van Moolenbroek maybe_reconnect(struct dbinfo *dbi) {
104*00b67f09SDavid van Moolenbroek 	if (PQstatus(dbi->conn) == CONNECTION_OK)
105*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
106*00b67f09SDavid van Moolenbroek 
107*00b67f09SDavid van Moolenbroek 	return (db_connect(dbi));
108*00b67f09SDavid van Moolenbroek }
109*00b67f09SDavid van Moolenbroek 
110*00b67f09SDavid van Moolenbroek /*
111*00b67f09SDavid van Moolenbroek  * This database operates on absolute names.
112*00b67f09SDavid van Moolenbroek  *
113*00b67f09SDavid van Moolenbroek  * Queries are converted into SQL queries and issued synchronously.  Errors
114*00b67f09SDavid van Moolenbroek  * are handled really badly.
115*00b67f09SDavid van Moolenbroek  */
116*00b67f09SDavid van Moolenbroek #ifdef DNS_CLIENTINFO_VERSION
117*00b67f09SDavid van Moolenbroek static isc_result_t
pgsqldb_lookup(const char * zone,const char * name,void * dbdata,dns_sdblookup_t * lookup,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)118*00b67f09SDavid van Moolenbroek pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
119*00b67f09SDavid van Moolenbroek 	       dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
120*00b67f09SDavid van Moolenbroek 	       dns_clientinfo_t *clientinfo)
121*00b67f09SDavid van Moolenbroek #else
122*00b67f09SDavid van Moolenbroek static isc_result_t
123*00b67f09SDavid van Moolenbroek pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
124*00b67f09SDavid van Moolenbroek 	       dns_sdblookup_t *lookup)
125*00b67f09SDavid van Moolenbroek #endif /* DNS_CLIENTINFO_VERSION */
126*00b67f09SDavid van Moolenbroek {
127*00b67f09SDavid van Moolenbroek 	isc_result_t result;
128*00b67f09SDavid van Moolenbroek 	struct dbinfo *dbi = dbdata;
129*00b67f09SDavid van Moolenbroek 	PGresult *res;
130*00b67f09SDavid van Moolenbroek 	char str[1500];
131*00b67f09SDavid van Moolenbroek 	char *canonname;
132*00b67f09SDavid van Moolenbroek 	int i;
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
135*00b67f09SDavid van Moolenbroek #ifdef DNS_CLIENTINFO_VERSION
136*00b67f09SDavid van Moolenbroek 	UNUSED(methods);
137*00b67f09SDavid van Moolenbroek 	UNUSED(clientinfo);
138*00b67f09SDavid van Moolenbroek #endif /* DNS_CLIENTINFO_VERSION */
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	canonname = isc_mem_get(ns_g_mctx, strlen(name) * 2 + 1);
141*00b67f09SDavid van Moolenbroek 	if (canonname == NULL)
142*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
143*00b67f09SDavid van Moolenbroek 	quotestring(name, canonname);
144*00b67f09SDavid van Moolenbroek 	snprintf(str, sizeof(str),
145*00b67f09SDavid van Moolenbroek 		 "SELECT TTL,RDTYPE,RDATA FROM \"%s\" WHERE "
146*00b67f09SDavid van Moolenbroek 		 "lower(NAME) = lower('%s')", dbi->table, canonname);
147*00b67f09SDavid van Moolenbroek 	isc_mem_put(ns_g_mctx, canonname, strlen(name) * 2 + 1);
148*00b67f09SDavid van Moolenbroek 
149*00b67f09SDavid van Moolenbroek 	result = maybe_reconnect(dbi);
150*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
151*00b67f09SDavid van Moolenbroek 		return (result);
152*00b67f09SDavid van Moolenbroek 
153*00b67f09SDavid van Moolenbroek 	res = PQexec(dbi->conn, str);
154*00b67f09SDavid van Moolenbroek 	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
155*00b67f09SDavid van Moolenbroek 		PQclear(res);
156*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
157*00b67f09SDavid van Moolenbroek 	}
158*00b67f09SDavid van Moolenbroek 	if (PQntuples(res) == 0) {
159*00b67f09SDavid van Moolenbroek 		PQclear(res);
160*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
161*00b67f09SDavid van Moolenbroek 	}
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	for (i = 0; i < PQntuples(res); i++) {
164*00b67f09SDavid van Moolenbroek 		char *ttlstr = PQgetvalue(res, i, 0);
165*00b67f09SDavid van Moolenbroek 		char *type = PQgetvalue(res, i, 1);
166*00b67f09SDavid van Moolenbroek 		char *data = PQgetvalue(res, i, 2);
167*00b67f09SDavid van Moolenbroek 		dns_ttl_t ttl;
168*00b67f09SDavid van Moolenbroek 		char *endp;
169*00b67f09SDavid van Moolenbroek 		ttl = strtol(ttlstr, &endp, 10);
170*00b67f09SDavid van Moolenbroek 		if (*endp != '\0') {
171*00b67f09SDavid van Moolenbroek 			PQclear(res);
172*00b67f09SDavid van Moolenbroek 			return (DNS_R_BADTTL);
173*00b67f09SDavid van Moolenbroek 		}
174*00b67f09SDavid van Moolenbroek 		result = dns_sdb_putrr(lookup, type, ttl, data);
175*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
176*00b67f09SDavid van Moolenbroek 			PQclear(res);
177*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
178*00b67f09SDavid van Moolenbroek 		}
179*00b67f09SDavid van Moolenbroek 	}
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek 	PQclear(res);
182*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
183*00b67f09SDavid van Moolenbroek }
184*00b67f09SDavid van Moolenbroek 
185*00b67f09SDavid van Moolenbroek /*
186*00b67f09SDavid van Moolenbroek  * Issue an SQL query to return all nodes in the database and fill the
187*00b67f09SDavid van Moolenbroek  * allnodes structure.
188*00b67f09SDavid van Moolenbroek  */
189*00b67f09SDavid van Moolenbroek static isc_result_t
pgsqldb_allnodes(const char * zone,void * dbdata,dns_sdballnodes_t * allnodes)190*00b67f09SDavid van Moolenbroek pgsqldb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
191*00b67f09SDavid van Moolenbroek 	struct dbinfo *dbi = dbdata;
192*00b67f09SDavid van Moolenbroek 	PGresult *res;
193*00b67f09SDavid van Moolenbroek 	isc_result_t result;
194*00b67f09SDavid van Moolenbroek 	char str[1500];
195*00b67f09SDavid van Moolenbroek 	int i;
196*00b67f09SDavid van Moolenbroek 
197*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
198*00b67f09SDavid van Moolenbroek 
199*00b67f09SDavid van Moolenbroek 	snprintf(str, sizeof(str),
200*00b67f09SDavid van Moolenbroek 		 "SELECT TTL,NAME,RDTYPE,RDATA FROM \"%s\" ORDER BY NAME",
201*00b67f09SDavid van Moolenbroek 		 dbi->table);
202*00b67f09SDavid van Moolenbroek 
203*00b67f09SDavid van Moolenbroek 	result = maybe_reconnect(dbi);
204*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
205*00b67f09SDavid van Moolenbroek 		return (result);
206*00b67f09SDavid van Moolenbroek 
207*00b67f09SDavid van Moolenbroek 	res = PQexec(dbi->conn, str);
208*00b67f09SDavid van Moolenbroek 	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ) {
209*00b67f09SDavid van Moolenbroek 		PQclear(res);
210*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
211*00b67f09SDavid van Moolenbroek 	}
212*00b67f09SDavid van Moolenbroek 	if (PQntuples(res) == 0) {
213*00b67f09SDavid van Moolenbroek 		PQclear(res);
214*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
215*00b67f09SDavid van Moolenbroek 	}
216*00b67f09SDavid van Moolenbroek 
217*00b67f09SDavid van Moolenbroek 	for (i = 0; i < PQntuples(res); i++) {
218*00b67f09SDavid van Moolenbroek 		char *ttlstr = PQgetvalue(res, i, 0);
219*00b67f09SDavid van Moolenbroek 		char *name = PQgetvalue(res, i, 1);
220*00b67f09SDavid van Moolenbroek 		char *type = PQgetvalue(res, i, 2);
221*00b67f09SDavid van Moolenbroek 		char *data = PQgetvalue(res, i, 3);
222*00b67f09SDavid van Moolenbroek 		dns_ttl_t ttl;
223*00b67f09SDavid van Moolenbroek 		char *endp;
224*00b67f09SDavid van Moolenbroek 		ttl = strtol(ttlstr, &endp, 10);
225*00b67f09SDavid van Moolenbroek 		if (*endp != '\0') {
226*00b67f09SDavid van Moolenbroek 			PQclear(res);
227*00b67f09SDavid van Moolenbroek 			return (DNS_R_BADTTL);
228*00b67f09SDavid van Moolenbroek 		}
229*00b67f09SDavid van Moolenbroek 		result = dns_sdb_putnamedrr(allnodes, name, type, ttl, data);
230*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
231*00b67f09SDavid van Moolenbroek 			PQclear(res);
232*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
233*00b67f09SDavid van Moolenbroek 		}
234*00b67f09SDavid van Moolenbroek 	}
235*00b67f09SDavid van Moolenbroek 
236*00b67f09SDavid van Moolenbroek 	PQclear(res);
237*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
238*00b67f09SDavid van Moolenbroek }
239*00b67f09SDavid van Moolenbroek 
240*00b67f09SDavid van Moolenbroek /*
241*00b67f09SDavid van Moolenbroek  * Create a connection to the database and save any necessary information
242*00b67f09SDavid van Moolenbroek  * in dbdata.
243*00b67f09SDavid van Moolenbroek  *
244*00b67f09SDavid van Moolenbroek  * argv[0] is the name of the database
245*00b67f09SDavid van Moolenbroek  * argv[1] is the name of the table
246*00b67f09SDavid van Moolenbroek  * argv[2] (if present) is the name of the host to connect to
247*00b67f09SDavid van Moolenbroek  * argv[3] (if present) is the name of the user to connect as
248*00b67f09SDavid van Moolenbroek  * argv[4] (if present) is the name of the password to connect with
249*00b67f09SDavid van Moolenbroek  */
250*00b67f09SDavid van Moolenbroek static isc_result_t
pgsqldb_create(const char * zone,int argc,char ** argv,void * driverdata,void ** dbdata)251*00b67f09SDavid van Moolenbroek pgsqldb_create(const char *zone, int argc, char **argv,
252*00b67f09SDavid van Moolenbroek 	       void *driverdata, void **dbdata)
253*00b67f09SDavid van Moolenbroek {
254*00b67f09SDavid van Moolenbroek 	struct dbinfo *dbi;
255*00b67f09SDavid van Moolenbroek 	isc_result_t result;
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
258*00b67f09SDavid van Moolenbroek 	UNUSED(driverdata);
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek 	if (argc < 2)
261*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
262*00b67f09SDavid van Moolenbroek 
263*00b67f09SDavid van Moolenbroek 	dbi = isc_mem_get(ns_g_mctx, sizeof(struct dbinfo));
264*00b67f09SDavid van Moolenbroek 	if (dbi == NULL)
265*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
266*00b67f09SDavid van Moolenbroek 	dbi->conn = NULL;
267*00b67f09SDavid van Moolenbroek 	dbi->database = NULL;
268*00b67f09SDavid van Moolenbroek 	dbi->table = NULL;
269*00b67f09SDavid van Moolenbroek 	dbi->host = NULL;
270*00b67f09SDavid van Moolenbroek 	dbi->user = NULL;
271*00b67f09SDavid van Moolenbroek 	dbi->passwd = NULL;
272*00b67f09SDavid van Moolenbroek 
273*00b67f09SDavid van Moolenbroek #define STRDUP_OR_FAIL(target, source)				\
274*00b67f09SDavid van Moolenbroek 	do {							\
275*00b67f09SDavid van Moolenbroek 		target = isc_mem_strdup(ns_g_mctx, source);	\
276*00b67f09SDavid van Moolenbroek 		if (target == NULL) {				\
277*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;		\
278*00b67f09SDavid van Moolenbroek 			goto cleanup;				\
279*00b67f09SDavid van Moolenbroek 		}						\
280*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0);
281*00b67f09SDavid van Moolenbroek 
282*00b67f09SDavid van Moolenbroek 	STRDUP_OR_FAIL(dbi->database, argv[0]);
283*00b67f09SDavid van Moolenbroek 	STRDUP_OR_FAIL(dbi->table, argv[1]);
284*00b67f09SDavid van Moolenbroek 	if (argc > 2)
285*00b67f09SDavid van Moolenbroek 		STRDUP_OR_FAIL(dbi->host, argv[2]);
286*00b67f09SDavid van Moolenbroek 	if (argc > 3)
287*00b67f09SDavid van Moolenbroek 		STRDUP_OR_FAIL(dbi->user, argv[3]);
288*00b67f09SDavid van Moolenbroek 	if (argc > 4)
289*00b67f09SDavid van Moolenbroek 		STRDUP_OR_FAIL(dbi->passwd, argv[4]);
290*00b67f09SDavid van Moolenbroek 
291*00b67f09SDavid van Moolenbroek 	result = db_connect(dbi);
292*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
293*00b67f09SDavid van Moolenbroek 		goto cleanup;
294*00b67f09SDavid van Moolenbroek 
295*00b67f09SDavid van Moolenbroek 	*dbdata = dbi;
296*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
297*00b67f09SDavid van Moolenbroek 
298*00b67f09SDavid van Moolenbroek  cleanup:
299*00b67f09SDavid van Moolenbroek 	pgsqldb_destroy(zone, driverdata, (void **)&dbi);
300*00b67f09SDavid van Moolenbroek 	return (result);
301*00b67f09SDavid van Moolenbroek }
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek /*
304*00b67f09SDavid van Moolenbroek  * Close the connection to the database.
305*00b67f09SDavid van Moolenbroek  */
306*00b67f09SDavid van Moolenbroek static void
pgsqldb_destroy(const char * zone,void * driverdata,void ** dbdata)307*00b67f09SDavid van Moolenbroek pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata) {
308*00b67f09SDavid van Moolenbroek 	struct dbinfo *dbi = *dbdata;
309*00b67f09SDavid van Moolenbroek 
310*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
311*00b67f09SDavid van Moolenbroek 	UNUSED(driverdata);
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 	if (dbi->conn != NULL)
314*00b67f09SDavid van Moolenbroek 		PQfinish(dbi->conn);
315*00b67f09SDavid van Moolenbroek 	if (dbi->database != NULL)
316*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->database);
317*00b67f09SDavid van Moolenbroek 	if (dbi->table != NULL)
318*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->table);
319*00b67f09SDavid van Moolenbroek 	if (dbi->host != NULL)
320*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->host);
321*00b67f09SDavid van Moolenbroek 	if (dbi->user != NULL)
322*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->user);
323*00b67f09SDavid van Moolenbroek 	if (dbi->passwd != NULL)
324*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->passwd);
325*00b67f09SDavid van Moolenbroek 	if (dbi->database != NULL)
326*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->database);
327*00b67f09SDavid van Moolenbroek 	isc_mem_put(ns_g_mctx, dbi, sizeof(struct dbinfo));
328*00b67f09SDavid van Moolenbroek }
329*00b67f09SDavid van Moolenbroek 
330*00b67f09SDavid van Moolenbroek /*
331*00b67f09SDavid van Moolenbroek  * Since the SQL database corresponds to a zone, the authority data should
332*00b67f09SDavid van Moolenbroek  * be returned by the lookup() function.  Therefore the authority() function
333*00b67f09SDavid van Moolenbroek  * is NULL.
334*00b67f09SDavid van Moolenbroek  */
335*00b67f09SDavid van Moolenbroek static dns_sdbmethods_t pgsqldb_methods = {
336*00b67f09SDavid van Moolenbroek 	pgsqldb_lookup,
337*00b67f09SDavid van Moolenbroek 	NULL, /* authority */
338*00b67f09SDavid van Moolenbroek 	pgsqldb_allnodes,
339*00b67f09SDavid van Moolenbroek 	pgsqldb_create,
340*00b67f09SDavid van Moolenbroek 	pgsqldb_destroy,
341*00b67f09SDavid van Moolenbroek 	NULL /* lookup2 */
342*00b67f09SDavid van Moolenbroek };
343*00b67f09SDavid van Moolenbroek 
344*00b67f09SDavid van Moolenbroek /*
345*00b67f09SDavid van Moolenbroek  * Wrapper around dns_sdb_register().
346*00b67f09SDavid van Moolenbroek  */
347*00b67f09SDavid van Moolenbroek isc_result_t
pgsqldb_init(void)348*00b67f09SDavid van Moolenbroek pgsqldb_init(void) {
349*00b67f09SDavid van Moolenbroek 	unsigned int flags;
350*00b67f09SDavid van Moolenbroek 	flags = 0;
351*00b67f09SDavid van Moolenbroek 	return (dns_sdb_register("pgsql", &pgsqldb_methods, NULL, flags,
352*00b67f09SDavid van Moolenbroek 				 ns_g_mctx, &pgsqldb));
353*00b67f09SDavid van Moolenbroek }
354*00b67f09SDavid van Moolenbroek 
355*00b67f09SDavid van Moolenbroek /*
356*00b67f09SDavid van Moolenbroek  * Wrapper around dns_sdb_unregister().
357*00b67f09SDavid van Moolenbroek  */
358*00b67f09SDavid van Moolenbroek void
pgsqldb_clear(void)359*00b67f09SDavid van Moolenbroek pgsqldb_clear(void) {
360*00b67f09SDavid van Moolenbroek 	if (pgsqldb != NULL)
361*00b67f09SDavid van Moolenbroek 		dns_sdb_unregister(&pgsqldb);
362*00b67f09SDavid van Moolenbroek }
363