e6f82b9dbba43699d9f8231a566ec4830da2cee5Brian Wellington/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000, 2001, 2004, 2007, 2011, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
e6f82b9dbba43699d9f8231a566ec4830da2cee5Brian Wellington *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
e6f82b9dbba43699d9f8231a566ec4830da2cee5Brian Wellington */
e6f82b9dbba43699d9f8231a566ec4830da2cee5Brian Wellington
0e11ca0f0bdeb8eface941671926a9f4d2fc2685Automatic Updater/* $Id: pgsqldb.c,v 1.17 2011/10/11 23:46:45 tbox Exp $ */
e6f82b9dbba43699d9f8231a566ec4830da2cee5Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <config.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <stdio.h>
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington#include <string.h>
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington#include <stdlib.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <pgsql/libpq-fe.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <isc/mem.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <isc/print.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <isc/result.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <isc/util.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <dns/sdb.h>
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington#include <dns/result.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington#include <named/globals.h>
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
5f3e10434705a04ecfc8baeae9ad2b4fd2d921afBrian Wellington#include "pgsqldb.h"
5f3e10434705a04ecfc8baeae9ad2b4fd2d921afBrian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * A simple database driver that interfaces to a PostgreSQL database. This
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * is not complete, and not designed for general use. It opens one
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * connection to the database per zone, which is inefficient. It also may
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * not handle quoting correctly.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington *
0e11ca0f0bdeb8eface941671926a9f4d2fc2685Automatic Updater * The table must contain the fields "name", "rdtype", and "rdata", and
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * is expected to contain a properly constructed zone. The program "zonetodb"
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * creates such a table.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic dns_sdbimplementation_t *pgsqldb = NULL;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstruct dbinfo {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PGconn *conn;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington char *database;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington char *table;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington char *host;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington char *user;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington char *passwd;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington};
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonstatic void
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonpgsqldb_destroy(const char *zone, void *driverdata, void **dbdata);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington/*
2e9fc5226745131fbf08b3f9d3979502fb92ae12Andreas Gustafsson * Canonicalize a string before writing it to the database.
2e9fc5226745131fbf08b3f9d3979502fb92ae12Andreas Gustafsson * "dest" must be an array of at least size 2*strlen(source) + 1.
2e9fc5226745131fbf08b3f9d3979502fb92ae12Andreas Gustafsson */
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellingtonstatic void
8befe9e546443b25d5a61237abfa52c348c4ae8eBrian Wellingtonquotestring(const char *source, char *dest) {
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington while (*source != 0) {
8d69143c079b212a98fcffac7ff394040c27033fBrian Wellington if (*source == '\'')
8d69143c079b212a98fcffac7ff394040c27033fBrian Wellington *dest++ = '\'';
db237e5475a51f50f9058b4441225882cc65a976Brian Wellington /* SQL doesn't treat \ as special, but PostgreSQL does */
8d69143c079b212a98fcffac7ff394040c27033fBrian Wellington else if (*source == '\\')
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington *dest++ = '\\';
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington *dest++ = *source++;
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington }
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington *dest++ = 0;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington}
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington/*
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Connect to the database.
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington */
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonstatic isc_result_t
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtondb_connect(struct dbinfo *dbi) {
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->conn = PQsetdbLogin(dbi->host, NULL, NULL, NULL, dbi->database,
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->user, dbi->passwd);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (PQstatus(dbi->conn) == CONNECTION_OK)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (ISC_R_SUCCESS);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington else
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (ISC_R_FAILURE);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington}
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington/*
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Check to see if the connection is still valid. If not, attempt to
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * reconnect.
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington */
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonstatic isc_result_t
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonmaybe_reconnect(struct dbinfo *dbi) {
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (PQstatus(dbi->conn) == CONNECTION_OK)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (ISC_R_SUCCESS);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (db_connect(dbi));
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington}
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * This database operates on absolute names.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington *
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Queries are converted into SQL queries and issued synchronously. Errors
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * are handled really badly.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#ifdef DNS_CLIENTINFO_VERSION
793814f80703afdd69b59ade91e63efa81ae4178Evan Huntstatic isc_result_t
793814f80703afdd69b59ade91e63efa81ae4178Evan Huntpgsqldb_lookup(const char *zone, const char *name, void *dbdata,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt dns_clientinfo_t *clientinfo)
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#else
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic isc_result_t
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_lookup(const char *zone, const char *name, void *dbdata,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington dns_sdblookup_t *lookup)
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#endif /* DNS_CLIENTINFO_VERSION */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington{
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington isc_result_t result;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington struct dbinfo *dbi = dbdata;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PGresult *res;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington char str[1500];
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington char *canonname;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington int i;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(zone);
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#ifdef DNS_CLIENTINFO_VERSION
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt UNUSED(methods);
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt UNUSED(clientinfo);
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#endif /* DNS_CLIENTINFO_VERSION */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington canonname = isc_mem_get(ns_g_mctx, strlen(name) * 2 + 1);
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington if (canonname == NULL)
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington return (ISC_R_NOMEMORY);
8befe9e546443b25d5a61237abfa52c348c4ae8eBrian Wellington quotestring(name, canonname);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington snprintf(str, sizeof(str),
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington "SELECT TTL,RDTYPE,RDATA FROM \"%s\" WHERE "
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington "lower(NAME) = lower('%s')", dbi->table, canonname);
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington isc_mem_put(ns_g_mctx, canonname, strlen(name) * 2 + 1);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington result = maybe_reconnect(dbi);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (result != ISC_R_SUCCESS)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (result);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington res = PQexec(dbi->conn, str);
2e9fc5226745131fbf08b3f9d3979502fb92ae12Andreas Gustafsson if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_FAILURE);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (PQntuples(res) == 0) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_NOTFOUND);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington for (i = 0; i < PQntuples(res); i++) {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *ttlstr = PQgetvalue(res, i, 0);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *type = PQgetvalue(res, i, 1);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *data = PQgetvalue(res, i, 2);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington dns_ttl_t ttl;
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *endp;
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington ttl = strtol(ttlstr, &endp, 10);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington if (*endp != '\0') {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington PQclear(res);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington return (DNS_R_BADTTL);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington }
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington result = dns_sdb_putrr(lookup, type, ttl, data);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (result != ISC_R_SUCCESS) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_FAILURE);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_SUCCESS);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Issue an SQL query to return all nodes in the database and fill the
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * allnodes structure.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic isc_result_t
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington struct dbinfo *dbi = dbdata;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PGresult *res;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington isc_result_t result;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington char str[1500];
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington int i;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(zone);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington snprintf(str, sizeof(str),
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington "SELECT TTL,NAME,RDTYPE,RDATA FROM \"%s\" ORDER BY NAME",
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington dbi->table);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington result = maybe_reconnect(dbi);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (result != ISC_R_SUCCESS)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (result);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington res = PQexec(dbi->conn, str);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_FAILURE);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (PQntuples(res) == 0) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_NOTFOUND);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington for (i = 0; i < PQntuples(res); i++) {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *ttlstr = PQgetvalue(res, i, 0);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *name = PQgetvalue(res, i, 1);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *type = PQgetvalue(res, i, 2);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *data = PQgetvalue(res, i, 3);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington dns_ttl_t ttl;
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington char *endp;
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington ttl = strtol(ttlstr, &endp, 10);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington if (*endp != '\0') {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington PQclear(res);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington return (DNS_R_BADTTL);
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington }
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington result = dns_sdb_putnamedrr(allnodes, name, type, ttl, data);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (result != ISC_R_SUCCESS) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_FAILURE);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington }
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington PQclear(res);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_SUCCESS);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Create a connection to the database and save any necessary information
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * in dbdata.
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington *
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * argv[0] is the name of the database
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * argv[1] is the name of the table
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * argv[2] (if present) is the name of the host to connect to
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * argv[3] (if present) is the name of the user to connect as
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * argv[4] (if present) is the name of the password to connect with
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic isc_result_t
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_create(const char *zone, int argc, char **argv,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington void *driverdata, void **dbdata)
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington{
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington struct dbinfo *dbi;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_result_t result;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(zone);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(driverdata);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (argc < 2)
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_FAILURE);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington dbi = isc_mem_get(ns_g_mctx, sizeof(struct dbinfo));
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (dbi == NULL)
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_NOMEMORY);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->conn = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->database = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->table = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->host = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->user = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->passwd = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington#define STRDUP_OR_FAIL(target, source) \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington do { \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington target = isc_mem_strdup(ns_g_mctx, source); \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (target == NULL) { \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington result = ISC_R_NOMEMORY; \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington goto cleanup; \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington } \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington } while (0);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington STRDUP_OR_FAIL(dbi->database, argv[0]);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington STRDUP_OR_FAIL(dbi->table, argv[1]);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (argc > 2)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington STRDUP_OR_FAIL(dbi->host, argv[2]);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (argc > 3)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington STRDUP_OR_FAIL(dbi->user, argv[3]);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (argc > 4)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington STRDUP_OR_FAIL(dbi->passwd, argv[4]);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington result = db_connect(dbi);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (result != ISC_R_SUCCESS)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington goto cleanup;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington *dbdata = dbi;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (ISC_R_SUCCESS);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington cleanup:
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington pgsqldb_destroy(zone, driverdata, (void **)&dbi);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington return (result);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Close the connection to the database.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic void
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_destroy(const char *zone, void *driverdata, void **dbdata) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington struct dbinfo *dbi = *dbdata;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(zone);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington UNUSED(driverdata);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->conn != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington PQfinish(dbi->conn);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->database != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->database);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->table != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->table);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->host != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->host);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->user != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->user);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->passwd != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->passwd);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington if (dbi->database != NULL)
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington isc_mem_free(ns_g_mctx, dbi->database);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington isc_mem_put(ns_g_mctx, dbi, sizeof(struct dbinfo));
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Since the SQL database corresponds to a zone, the authority data should
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * be returned by the lookup() function. Therefore the authority() function
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * is NULL.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonstatic dns_sdbmethods_t pgsqldb_methods = {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington pgsqldb_lookup,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington NULL, /* authority */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington pgsqldb_allnodes,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington pgsqldb_create,
58f1ac8dadf2c1f215343a0b2d1df2df954c4b19Mark Andrews pgsqldb_destroy,
58f1ac8dadf2c1f215343a0b2d1df2df954c4b19Mark Andrews NULL /* lookup2 */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington};
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Wrapper around dns_sdb_register().
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonisc_result_t
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_init(void) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington unsigned int flags;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington flags = 0;
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (dns_sdb_register("pgsql", &pgsqldb_methods, NULL, flags,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington ns_g_mctx, &pgsqldb));
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington/*
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Wrapper around dns_sdb_unregister().
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington */
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonvoid
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_clear(void) {
94b6d69d94c580b2966aead209ba28db1f9e9195Brian Wellington if (pgsqldb != NULL)
94b6d69d94c580b2966aead209ba28db1f9e9195Brian Wellington dns_sdb_unregister(&pgsqldb);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington}