4 * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001 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: tcldb.c,v 1.10 2007/06/19 23:47:10 tbox Exp */
23 * A simple database driver that calls a Tcl procedure to define
24 * the contents of the DNS namespace. The procedure is loaded
25 * from the file lookup.tcl; look at the comments there for
37 #include <isc/print.h>
38 #include <isc/result.h>
44 #include <named/globals.h>
52 if (result != ISC_R_SUCCESS) return (result); \
55 typedef struct tcldb_driver
{
60 static tcldb_driver_t
*the_driver
= NULL
;
62 static dns_sdbimplementation_t
*tcldb
= NULL
;
65 tcldb_driver_create(isc_mem_t
*mctx
, tcldb_driver_t
**driverp
) {
67 isc_result_t result
= ISC_R_SUCCESS
;
68 tcldb_driver_t
*driver
= isc_mem_get(mctx
, sizeof(tcldb_driver_t
));
70 return (ISC_R_NOMEMORY
);
72 driver
->interp
= Tcl_CreateInterp();
74 tclres
= Tcl_EvalFile(driver
->interp
, (char *) "lookup.tcl");
75 if (tclres
!= TCL_OK
) {
76 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
77 DNS_LOGMODULE_SDB
, ISC_LOG_ERROR
,
78 "initializing tcldb: "
79 "loading 'lookup.tcl' failed: %s",
80 driver
->interp
->result
);
81 result
= ISC_R_FAILURE
;
85 return (ISC_R_SUCCESS
);
88 isc_mem_put(mctx
, driver
, sizeof(tcldb_driver_t
));
94 tcldb_driver_destroy(tcldb_driver_t
**driverp
) {
95 tcldb_driver_t
*driver
= *driverp
;
96 Tcl_DeleteInterp(driver
->interp
);
97 isc_mem_put(driver
->mctx
, driver
, sizeof(tcldb_driver_t
));
101 * Perform a lookup, by invoking the Tcl procedure "lookup".
104 tcldb_lookup(const char *zone
, const char *name
, void *dbdata
,
105 dns_sdblookup_t
*lookup
)
107 isc_result_t result
= ISC_R_SUCCESS
;
109 int rrc
; /* RR count */
110 char **rrv
; /* RR vector */
115 tcldb_driver_t
*driver
= (tcldb_driver_t
*) dbdata
;
120 cmd
= Tcl_Merge(3, cmdv
);
121 tclres
= Tcl_Eval(driver
->interp
, cmd
);
124 if (tclres
!= TCL_OK
) {
125 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
126 DNS_LOGMODULE_SDB
, ISC_LOG_ERROR
,
127 "zone '%s': tcl lookup function failed: %s",
128 zone
, driver
->interp
->result
);
129 return (ISC_R_FAILURE
);
132 if (strcmp(driver
->interp
->result
, "NXDOMAIN") == 0) {
133 result
= ISC_R_NOTFOUND
;
137 tclres
= Tcl_SplitList(driver
->interp
, driver
->interp
->result
,
139 if (tclres
!= TCL_OK
)
142 for (i
= 0; i
< rrc
; i
++) {
144 int fieldc
; /* Field count */
145 char **fieldv
; /* Field vector */
146 tclres
= Tcl_SplitList(driver
->interp
, rrv
[i
],
148 if (tclres
!= TCL_OK
) {
149 tmpres
= ISC_R_FAILURE
;
154 tmpres
= dns_sdb_putrr(lookup
, fieldv
[0], atoi(fieldv
[1]),
156 Tcl_Free((char *) fieldv
);
158 if (tmpres
!= ISC_R_SUCCESS
)
161 Tcl_Free((char *) rrv
);
162 if (result
== ISC_R_SUCCESS
)
166 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
167 DNS_LOGMODULE_SDB
, ISC_LOG_ERROR
,
169 "malformed return value from tcl lookup function: %s",
170 zone
, driver
->interp
->result
);
171 result
= ISC_R_FAILURE
;
177 * Set up per-zone state. In our case, the database arguments of the
178 * zone are collected into a Tcl list and assigned to an element of
179 * the global array "dbargs".
182 tcldb_create(const char *zone
, int argc
, char **argv
,
183 void *driverdata
, void **dbdata
)
185 tcldb_driver_t
*driver
= (tcldb_driver_t
*) driverdata
;
187 char *list
= Tcl_Merge(argc
, argv
);
189 Tcl_SetVar2(driver
->interp
, (char *) "dbargs", (char *) zone
, list
, 0);
193 *dbdata
= driverdata
;
195 return (ISC_R_SUCCESS
);
199 * This driver does not support zone transfer, so allnodes() is NULL.
201 static dns_sdbmethods_t tcldb_methods
= {
203 NULL
, /* authority */
210 * Initialize the tcldb driver.
215 int flags
= DNS_SDBFLAG_RELATIVEOWNER
| DNS_SDBFLAG_RELATIVERDATA
;
217 result
= tcldb_driver_create(ns_g_mctx
, &the_driver
);
218 if (result
!= ISC_R_SUCCESS
)
221 return (dns_sdb_register("tcl", &tcldb_methods
, the_driver
, flags
,
226 * Wrapper around dns_sdb_unregister().
231 dns_sdb_unregister(&tcldb
);
232 if (the_driver
!= NULL
)
233 tcldb_driver_destroy(&the_driver
);