2 * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: tcldb.c,v 1.10 2007/06/19 23:47:10 tbox Exp $ */
21 * A simple database driver that calls a Tcl procedure to define
22 * the contents of the DNS namespace. The procedure is loaded
23 * from the file lookup.tcl; look at the comments there for
35 #include <isc/print.h>
36 #include <isc/result.h>
42 #include <named/globals.h>
50 if (result != ISC_R_SUCCESS) return (result); \
53 typedef struct tcldb_driver {
58 static tcldb_driver_t *the_driver = NULL;
60 static dns_sdbimplementation_t *tcldb = NULL;
63 tcldb_driver_create(isc_mem_t *mctx, tcldb_driver_t **driverp) {
65 isc_result_t result = ISC_R_SUCCESS;
66 tcldb_driver_t *driver = isc_mem_get(mctx, sizeof(tcldb_driver_t));
68 return (ISC_R_NOMEMORY);
70 driver->interp = Tcl_CreateInterp();
72 tclres = Tcl_EvalFile(driver->interp, (char *) "lookup.tcl");
73 if (tclres != TCL_OK) {
74 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
75 DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
76 "initializing tcldb: "
77 "loading 'lookup.tcl' failed: %s",
78 driver->interp->result);
79 result = ISC_R_FAILURE;
83 return (ISC_R_SUCCESS);
86 isc_mem_put(mctx, driver, sizeof(tcldb_driver_t));
92 tcldb_driver_destroy(tcldb_driver_t **driverp) {
93 tcldb_driver_t *driver = *driverp;
94 Tcl_DeleteInterp(driver->interp);
95 isc_mem_put(driver->mctx, driver, sizeof(tcldb_driver_t));
99 * Perform a lookup, by invoking the Tcl procedure "lookup".
102 tcldb_lookup(const char *zone, const char *name, void *dbdata,
103 dns_sdblookup_t *lookup)
105 isc_result_t result = ISC_R_SUCCESS;
107 int rrc; /* RR count */
108 char **rrv; /* RR vector */
113 tcldb_driver_t *driver = (tcldb_driver_t *) dbdata;
118 cmd = Tcl_Merge(3, cmdv);
119 tclres = Tcl_Eval(driver->interp, cmd);
122 if (tclres != TCL_OK) {
123 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
124 DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
125 "zone '%s': tcl lookup function failed: %s",
126 zone, driver->interp->result);
127 return (ISC_R_FAILURE);
130 if (strcmp(driver->interp->result, "NXDOMAIN") == 0) {
131 result = ISC_R_NOTFOUND;
135 tclres = Tcl_SplitList(driver->interp, driver->interp->result,
137 if (tclres != TCL_OK)
140 for (i = 0; i < rrc; i++) {
142 int fieldc; /* Field count */
143 char **fieldv; /* Field vector */
144 tclres = Tcl_SplitList(driver->interp, rrv[i],
146 if (tclres != TCL_OK) {
147 tmpres = ISC_R_FAILURE;
152 tmpres = dns_sdb_putrr(lookup, fieldv[0], atoi(fieldv[1]),
154 Tcl_Free((char *) fieldv);
156 if (tmpres != ISC_R_SUCCESS)
159 Tcl_Free((char *) rrv);
160 if (result == ISC_R_SUCCESS)
164 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
165 DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
167 "malformed return value from tcl lookup function: %s",
168 zone, driver->interp->result);
169 result = ISC_R_FAILURE;
175 * Set up per-zone state. In our case, the database arguments of the
176 * zone are collected into a Tcl list and assigned to an element of
177 * the global array "dbargs".
180 tcldb_create(const char *zone, int argc, char **argv,
181 void *driverdata, void **dbdata)
183 tcldb_driver_t *driver = (tcldb_driver_t *) driverdata;
185 char *list = Tcl_Merge(argc, argv);
187 Tcl_SetVar2(driver->interp, (char *) "dbargs", (char *) zone, list, 0);
191 *dbdata = driverdata;
193 return (ISC_R_SUCCESS);
197 * This driver does not support zone transfer, so allnodes() is NULL.
199 static dns_sdbmethods_t tcldb_methods = {
201 NULL, /* authority */
208 * Initialize the tcldb driver.
213 int flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
215 result = tcldb_driver_create(ns_g_mctx, &the_driver);
216 if (result != ISC_R_SUCCESS)
219 return (dns_sdb_register("tcl", &tcldb_methods, the_driver, flags,
224 * Wrapper around dns_sdb_unregister().
229 dns_sdb_unregister(&tcldb);
230 if (the_driver != NULL)
231 tcldb_driver_destroy(&the_driver);