0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000, 2001, 2004, 2007, 2011, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
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/.
0e11ca0f0bdeb8eface941671926a9f4d2fc2685Automatic Updater/* $Id: pgsqldb.c,v 1.17 2011/10/11 23:46:45 tbox Exp $ */
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.
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 Wellingtonstatic dns_sdbimplementation_t *pgsqldb = NULL;
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellingtonpgsqldb_destroy(const char *zone, void *driverdata, void **dbdata);
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.
8befe9e546443b25d5a61237abfa52c348c4ae8eBrian Wellingtonquotestring(const char *source, char *dest) {
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington while (*source != 0) {
db237e5475a51f50f9058b4441225882cc65a976Brian Wellington /* SQL doesn't treat \ as special, but PostgreSQL does */
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Connect to the database.
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington dbi->conn = PQsetdbLogin(dbi->host, NULL, NULL, NULL, dbi->database,
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Check to see if the connection is still valid. If not, attempt to
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * This database operates on absolute names.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Queries are converted into SQL queries and issued synchronously. Errors
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * are handled really badly.
793814f80703afdd69b59ade91e63efa81ae4178Evan Huntpgsqldb_lookup(const char *zone, const char *name, void *dbdata,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_lookup(const char *zone, const char *name, void *dbdata,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#endif /* DNS_CLIENTINFO_VERSION */
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#endif /* DNS_CLIENTINFO_VERSION */
dfd5809a58c3503501c17016b8b0691b0f1f39a2Brian Wellington canonname = isc_mem_get(ns_g_mctx, strlen(name) * 2 + 1);
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);
2e9fc5226745131fbf08b3f9d3979502fb92ae12Andreas Gustafsson if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington result = dns_sdb_putrr(lookup, type, ttl, data);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Issue an SQL query to return all nodes in the database and fill the
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * allnodes structure.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington "SELECT TTL,NAME,RDTYPE,RDATA FROM \"%s\" ORDER BY NAME",
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ) {
5aee7a4da49ab97751023a6e096ee8d473f47056Brian Wellington result = dns_sdb_putnamedrr(allnodes, name, type, ttl, data);
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington * Create a connection to the database and save any necessary information
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 Wellingtonpgsqldb_create(const char *zone, int argc, char **argv,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington dbi = isc_mem_get(ns_g_mctx, sizeof(struct dbinfo));
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington target = isc_mem_strdup(ns_g_mctx, source); \
1ff970120a57b9a1e88d0a5326c44d9abb4a3863Brian Wellington pgsqldb_destroy(zone, driverdata, (void **)&dbi);
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Close the connection to the database.
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellingtonpgsqldb_destroy(const char *zone, void *driverdata, void **dbdata) {
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington isc_mem_put(ns_g_mctx, dbi, sizeof(struct dbinfo));
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 * Wrapper around dns_sdb_register().
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington return (dns_sdb_register("pgsql", &pgsqldb_methods, NULL, flags,
18cd5a8e599b26eb7011abde33e15475716109c0Brian Wellington * Wrapper around dns_sdb_unregister().