xref: /minix3/external/bsd/bind/dist/bin/tests/system/dlzexternal/driver.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: driver.c,v 1.3 2014/12/10 04:37:54 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2011-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek /*
20*00b67f09SDavid van Moolenbroek  * This provides a very simple example of an external loadable DLZ
21*00b67f09SDavid van Moolenbroek  * driver, with update support.
22*00b67f09SDavid van Moolenbroek  */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stdio.h>
27*00b67f09SDavid van Moolenbroek #include <stdlib.h>
28*00b67f09SDavid van Moolenbroek #include <stdarg.h>
29*00b67f09SDavid van Moolenbroek 
30*00b67f09SDavid van Moolenbroek #include <isc/log.h>
31*00b67f09SDavid van Moolenbroek #include <isc/print.h>
32*00b67f09SDavid van Moolenbroek #include <isc/result.h>
33*00b67f09SDavid van Moolenbroek #include <isc/string.h>
34*00b67f09SDavid van Moolenbroek #include <isc/types.h>
35*00b67f09SDavid van Moolenbroek #include <isc/util.h>
36*00b67f09SDavid van Moolenbroek 
37*00b67f09SDavid van Moolenbroek #include <dns/types.h>
38*00b67f09SDavid van Moolenbroek #include <dns/dlz_dlopen.h>
39*00b67f09SDavid van Moolenbroek 
40*00b67f09SDavid van Moolenbroek #include "driver.h"
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek #ifdef WIN32
43*00b67f09SDavid van Moolenbroek #define STRTOK_R(a, b, c)	strtok_s(a, b, c)
44*00b67f09SDavid van Moolenbroek #elif defined(_REENTRANT)
45*00b67f09SDavid van Moolenbroek #define STRTOK_R(a, b, c)       strtok_r(a, b, c)
46*00b67f09SDavid van Moolenbroek #else
47*00b67f09SDavid van Moolenbroek #define STRTOK_R(a, b, c)       strtok(a, b)
48*00b67f09SDavid van Moolenbroek #endif
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek #define CHECK(x) \
51*00b67f09SDavid van Moolenbroek 	do { \
52*00b67f09SDavid van Moolenbroek 		result = (x); \
53*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) \
54*00b67f09SDavid van Moolenbroek 			goto failure; \
55*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek /* For this simple example, use fixed sized strings */
58*00b67f09SDavid van Moolenbroek struct record {
59*00b67f09SDavid van Moolenbroek 	char name[100];
60*00b67f09SDavid van Moolenbroek 	char type[10];
61*00b67f09SDavid van Moolenbroek 	char data[200];
62*00b67f09SDavid van Moolenbroek 	dns_ttl_t ttl;
63*00b67f09SDavid van Moolenbroek };
64*00b67f09SDavid van Moolenbroek 
65*00b67f09SDavid van Moolenbroek #define MAX_RECORDS 100
66*00b67f09SDavid van Moolenbroek 
67*00b67f09SDavid van Moolenbroek typedef void log_t(int level, const char *fmt, ...);
68*00b67f09SDavid van Moolenbroek 
69*00b67f09SDavid van Moolenbroek struct dlz_example_data {
70*00b67f09SDavid van Moolenbroek 	char *zone_name;
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek 	/* An example driver doesn't need good memory management :-) */
73*00b67f09SDavid van Moolenbroek 	struct record current[MAX_RECORDS];
74*00b67f09SDavid van Moolenbroek 	struct record adds[MAX_RECORDS];
75*00b67f09SDavid van Moolenbroek 	struct record deletes[MAX_RECORDS];
76*00b67f09SDavid van Moolenbroek 
77*00b67f09SDavid van Moolenbroek 	isc_boolean_t transaction_started;
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek 	/* Helper functions from the dlz_dlopen driver */
80*00b67f09SDavid van Moolenbroek 	log_t *log;
81*00b67f09SDavid van Moolenbroek 	dns_sdlz_putrr_t *putrr;
82*00b67f09SDavid van Moolenbroek 	dns_sdlz_putnamedrr_t *putnamedrr;
83*00b67f09SDavid van Moolenbroek 	dns_dlz_writeablezone_t *writeable_zone;
84*00b67f09SDavid van Moolenbroek };
85*00b67f09SDavid van Moolenbroek 
86*00b67f09SDavid van Moolenbroek static isc_boolean_t
single_valued(const char * type)87*00b67f09SDavid van Moolenbroek single_valued(const char *type) {
88*00b67f09SDavid van Moolenbroek 	const char *single[] = { "soa", "cname", NULL };
89*00b67f09SDavid van Moolenbroek 	int i;
90*00b67f09SDavid van Moolenbroek 
91*00b67f09SDavid van Moolenbroek 	for (i = 0; single[i]; i++) {
92*00b67f09SDavid van Moolenbroek 		if (strcasecmp(single[i], type) == 0) {
93*00b67f09SDavid van Moolenbroek 			return (ISC_TRUE);
94*00b67f09SDavid van Moolenbroek 		}
95*00b67f09SDavid van Moolenbroek 	}
96*00b67f09SDavid van Moolenbroek 	return (ISC_FALSE);
97*00b67f09SDavid van Moolenbroek }
98*00b67f09SDavid van Moolenbroek 
99*00b67f09SDavid van Moolenbroek /*
100*00b67f09SDavid van Moolenbroek  * Add a record to a list
101*00b67f09SDavid van Moolenbroek  */
102*00b67f09SDavid van Moolenbroek static isc_result_t
add_name(struct dlz_example_data * state,struct record * list,const char * name,const char * type,dns_ttl_t ttl,const char * data)103*00b67f09SDavid van Moolenbroek add_name(struct dlz_example_data *state, struct record *list,
104*00b67f09SDavid van Moolenbroek 	 const char *name, const char *type, dns_ttl_t ttl, const char *data)
105*00b67f09SDavid van Moolenbroek {
106*00b67f09SDavid van Moolenbroek 	int i;
107*00b67f09SDavid van Moolenbroek 	isc_boolean_t single = single_valued(type);
108*00b67f09SDavid van Moolenbroek 	int first_empty = -1;
109*00b67f09SDavid van Moolenbroek 
110*00b67f09SDavid van Moolenbroek 	for (i = 0; i < MAX_RECORDS; i++) {
111*00b67f09SDavid van Moolenbroek 		if (first_empty == -1 && strlen(list[i].name) == 0U) {
112*00b67f09SDavid van Moolenbroek 			first_empty = i;
113*00b67f09SDavid van Moolenbroek 		}
114*00b67f09SDavid van Moolenbroek 		if (strcasecmp(list[i].name, name) != 0)
115*00b67f09SDavid van Moolenbroek 			continue;
116*00b67f09SDavid van Moolenbroek 		if (strcasecmp(list[i].type, type) != 0)
117*00b67f09SDavid van Moolenbroek 			continue;
118*00b67f09SDavid van Moolenbroek 		if (!single && strcasecmp(list[i].data, data) != 0)
119*00b67f09SDavid van Moolenbroek 			continue;
120*00b67f09SDavid van Moolenbroek 		break;
121*00b67f09SDavid van Moolenbroek 	}
122*00b67f09SDavid van Moolenbroek 	if (i == MAX_RECORDS && first_empty != -1) {
123*00b67f09SDavid van Moolenbroek 		i = first_empty;
124*00b67f09SDavid van Moolenbroek 	}
125*00b67f09SDavid van Moolenbroek 	if (i == MAX_RECORDS) {
126*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
127*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_ERROR,
128*00b67f09SDavid van Moolenbroek 				   "dlz_example: out of record space");
129*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
130*00b67f09SDavid van Moolenbroek 	}
131*00b67f09SDavid van Moolenbroek 
132*00b67f09SDavid van Moolenbroek 	if (strlen(name) >= sizeof(list[i].name) ||
133*00b67f09SDavid van Moolenbroek 	    strlen(type) >= sizeof(list[i].type) ||
134*00b67f09SDavid van Moolenbroek 	    strlen(data) >= sizeof(list[i].data))
135*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek 	strncpy(list[i].name, name, sizeof(list[i].name));
138*00b67f09SDavid van Moolenbroek 	list[i].name[sizeof(list[i].name) - 1] = '\0';
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	strncpy(list[i].type, type, sizeof(list[i].type));
141*00b67f09SDavid van Moolenbroek 	list[i].type[sizeof(list[i].type) - 1] = '\0';
142*00b67f09SDavid van Moolenbroek 
143*00b67f09SDavid van Moolenbroek 	strncpy(list[i].data, data, sizeof(list[i].data));
144*00b67f09SDavid van Moolenbroek 	list[i].data[sizeof(list[i].data) - 1] = '\0';
145*00b67f09SDavid van Moolenbroek 
146*00b67f09SDavid van Moolenbroek 	list[i].ttl = ttl;
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
149*00b67f09SDavid van Moolenbroek }
150*00b67f09SDavid van Moolenbroek 
151*00b67f09SDavid van Moolenbroek /*
152*00b67f09SDavid van Moolenbroek  * Delete a record from a list
153*00b67f09SDavid van Moolenbroek  */
154*00b67f09SDavid van Moolenbroek static isc_result_t
del_name(struct dlz_example_data * state,struct record * list,const char * name,const char * type,dns_ttl_t ttl,const char * data)155*00b67f09SDavid van Moolenbroek del_name(struct dlz_example_data *state, struct record *list,
156*00b67f09SDavid van Moolenbroek 	 const char *name, const char *type, dns_ttl_t ttl,
157*00b67f09SDavid van Moolenbroek 	 const char *data)
158*00b67f09SDavid van Moolenbroek {
159*00b67f09SDavid van Moolenbroek 	int i;
160*00b67f09SDavid van Moolenbroek 
161*00b67f09SDavid van Moolenbroek 	UNUSED(state);
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	for (i = 0; i < MAX_RECORDS; i++) {
164*00b67f09SDavid van Moolenbroek 		if (strcasecmp(name, list[i].name) == 0 &&
165*00b67f09SDavid van Moolenbroek 		    strcasecmp(type, list[i].type) == 0 &&
166*00b67f09SDavid van Moolenbroek 		    strcasecmp(data, list[i].data) == 0 &&
167*00b67f09SDavid van Moolenbroek 		    ttl == list[i].ttl) {
168*00b67f09SDavid van Moolenbroek 			break;
169*00b67f09SDavid van Moolenbroek 		}
170*00b67f09SDavid van Moolenbroek 	}
171*00b67f09SDavid van Moolenbroek 	if (i == MAX_RECORDS) {
172*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
173*00b67f09SDavid van Moolenbroek 	}
174*00b67f09SDavid van Moolenbroek 	memset(&list[i], 0, sizeof(struct record));
175*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
176*00b67f09SDavid van Moolenbroek }
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek static isc_result_t
fmt_address(isc_sockaddr_t * addr,char * buffer,size_t size)179*00b67f09SDavid van Moolenbroek fmt_address(isc_sockaddr_t *addr, char *buffer, size_t size) {
180*00b67f09SDavid van Moolenbroek 	char addr_buf[100];
181*00b67f09SDavid van Moolenbroek 	const char *ret;
182*00b67f09SDavid van Moolenbroek 	isc_uint16_t port = 0;
183*00b67f09SDavid van Moolenbroek 
184*00b67f09SDavid van Moolenbroek 	switch (addr->type.sa.sa_family) {
185*00b67f09SDavid van Moolenbroek 	case AF_INET:
186*00b67f09SDavid van Moolenbroek 		port = ntohs(addr->type.sin.sin_port);
187*00b67f09SDavid van Moolenbroek 		ret = inet_ntop(AF_INET, &addr->type.sin.sin_addr, addr_buf,
188*00b67f09SDavid van Moolenbroek 				sizeof(addr_buf));
189*00b67f09SDavid van Moolenbroek 		break;
190*00b67f09SDavid van Moolenbroek 	case AF_INET6:
191*00b67f09SDavid van Moolenbroek 		port = ntohs(addr->type.sin6.sin6_port);
192*00b67f09SDavid van Moolenbroek 		ret = inet_ntop(AF_INET6, &addr->type.sin6.sin6_addr, addr_buf,
193*00b67f09SDavid van Moolenbroek 				sizeof(addr_buf));
194*00b67f09SDavid van Moolenbroek 		break;
195*00b67f09SDavid van Moolenbroek 	default:
196*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
197*00b67f09SDavid van Moolenbroek 	}
198*00b67f09SDavid van Moolenbroek 
199*00b67f09SDavid van Moolenbroek 	if (ret == NULL)
200*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
201*00b67f09SDavid van Moolenbroek 
202*00b67f09SDavid van Moolenbroek 	snprintf(buffer, size, "%s#%u", addr_buf, port);
203*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
204*00b67f09SDavid van Moolenbroek }
205*00b67f09SDavid van Moolenbroek 
206*00b67f09SDavid van Moolenbroek /*
207*00b67f09SDavid van Moolenbroek  * Return the version of the API
208*00b67f09SDavid van Moolenbroek  */
209*00b67f09SDavid van Moolenbroek int
dlz_version(unsigned int * flags)210*00b67f09SDavid van Moolenbroek dlz_version(unsigned int *flags) {
211*00b67f09SDavid van Moolenbroek 	UNUSED(flags);
212*00b67f09SDavid van Moolenbroek 	return (DLZ_DLOPEN_VERSION);
213*00b67f09SDavid van Moolenbroek }
214*00b67f09SDavid van Moolenbroek 
215*00b67f09SDavid van Moolenbroek /*
216*00b67f09SDavid van Moolenbroek  * Remember a helper function from the bind9 dlz_dlopen driver
217*00b67f09SDavid van Moolenbroek  */
218*00b67f09SDavid van Moolenbroek static void
b9_add_helper(struct dlz_example_data * state,const char * helper_name,void * ptr)219*00b67f09SDavid van Moolenbroek b9_add_helper(struct dlz_example_data *state,
220*00b67f09SDavid van Moolenbroek 	      const char *helper_name, void *ptr)
221*00b67f09SDavid van Moolenbroek {
222*00b67f09SDavid van Moolenbroek 	if (strcmp(helper_name, "log") == 0)
223*00b67f09SDavid van Moolenbroek 		state->log = (log_t *)ptr;
224*00b67f09SDavid van Moolenbroek 	if (strcmp(helper_name, "putrr") == 0)
225*00b67f09SDavid van Moolenbroek 		state->putrr = (dns_sdlz_putrr_t *)ptr;
226*00b67f09SDavid van Moolenbroek 	if (strcmp(helper_name, "putnamedrr") == 0)
227*00b67f09SDavid van Moolenbroek 		state->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
228*00b67f09SDavid van Moolenbroek 	if (strcmp(helper_name, "writeable_zone") == 0)
229*00b67f09SDavid van Moolenbroek 		state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
230*00b67f09SDavid van Moolenbroek }
231*00b67f09SDavid van Moolenbroek 
232*00b67f09SDavid van Moolenbroek /*
233*00b67f09SDavid van Moolenbroek  * Called to initialize the driver
234*00b67f09SDavid van Moolenbroek  */
235*00b67f09SDavid van Moolenbroek isc_result_t
dlz_create(const char * dlzname,unsigned int argc,char * argv[],void ** dbdata,...)236*00b67f09SDavid van Moolenbroek dlz_create(const char *dlzname, unsigned int argc, char *argv[],
237*00b67f09SDavid van Moolenbroek 	   void **dbdata, ...)
238*00b67f09SDavid van Moolenbroek {
239*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state;
240*00b67f09SDavid van Moolenbroek 	const char *helper_name;
241*00b67f09SDavid van Moolenbroek 	va_list ap;
242*00b67f09SDavid van Moolenbroek 	char soa_data[1024];
243*00b67f09SDavid van Moolenbroek 	const char *extra;
244*00b67f09SDavid van Moolenbroek 	isc_result_t result;
245*00b67f09SDavid van Moolenbroek 	int n;
246*00b67f09SDavid van Moolenbroek 
247*00b67f09SDavid van Moolenbroek 	UNUSED(dlzname);
248*00b67f09SDavid van Moolenbroek 
249*00b67f09SDavid van Moolenbroek 	state = calloc(1, sizeof(struct dlz_example_data));
250*00b67f09SDavid van Moolenbroek 	if (state == NULL)
251*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	/* Fill in the helper functions */
254*00b67f09SDavid van Moolenbroek 	va_start(ap, dbdata);
255*00b67f09SDavid van Moolenbroek 	while ((helper_name = va_arg(ap, const char *)) != NULL) {
256*00b67f09SDavid van Moolenbroek 		b9_add_helper(state, helper_name, va_arg(ap, void *));
257*00b67f09SDavid van Moolenbroek 	}
258*00b67f09SDavid van Moolenbroek 	va_end(ap);
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek 	if (argc < 2 || argv[1][0] == '\0') {
261*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
262*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_ERROR,
263*00b67f09SDavid van Moolenbroek 				   "dlz_example: please specify a zone name");
264*00b67f09SDavid van Moolenbroek 		dlz_destroy(state);
265*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
266*00b67f09SDavid van Moolenbroek 	}
267*00b67f09SDavid van Moolenbroek 
268*00b67f09SDavid van Moolenbroek 	/* Ensure zone name is absolute */
269*00b67f09SDavid van Moolenbroek 	state->zone_name = malloc(strlen(argv[1]) + 2);
270*00b67f09SDavid van Moolenbroek 	if (state->zone_name == NULL) {
271*00b67f09SDavid van Moolenbroek 		free(state);
272*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
273*00b67f09SDavid van Moolenbroek 	}
274*00b67f09SDavid van Moolenbroek 	if (argv[1][strlen(argv[1]) - 1] == '.')
275*00b67f09SDavid van Moolenbroek 		strcpy(state->zone_name, argv[1]);
276*00b67f09SDavid van Moolenbroek 	else
277*00b67f09SDavid van Moolenbroek 		sprintf(state->zone_name, "%s.", argv[1]);
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 	if (strcmp(state->zone_name, ".") == 0)
280*00b67f09SDavid van Moolenbroek 		extra = ".root";
281*00b67f09SDavid van Moolenbroek 	else
282*00b67f09SDavid van Moolenbroek 		extra = ".";
283*00b67f09SDavid van Moolenbroek 
284*00b67f09SDavid van Moolenbroek 	n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
285*00b67f09SDavid van Moolenbroek 		    state->zone_name, extra, state->zone_name);
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 	if (n < 0)
288*00b67f09SDavid van Moolenbroek 		CHECK(ISC_R_FAILURE);
289*00b67f09SDavid van Moolenbroek 	if ((unsigned)n >= sizeof(soa_data))
290*00b67f09SDavid van Moolenbroek 		CHECK(ISC_R_NOSPACE);
291*00b67f09SDavid van Moolenbroek 
292*00b67f09SDavid van Moolenbroek 	add_name(state, &state->current[0], state->zone_name,
293*00b67f09SDavid van Moolenbroek 		 "soa", 3600, soa_data);
294*00b67f09SDavid van Moolenbroek 	add_name(state, &state->current[0], state->zone_name,
295*00b67f09SDavid van Moolenbroek 		 "ns", 3600, state->zone_name);
296*00b67f09SDavid van Moolenbroek 	add_name(state, &state->current[0], state->zone_name,
297*00b67f09SDavid van Moolenbroek 		 "a", 1800, "10.53.0.1");
298*00b67f09SDavid van Moolenbroek 
299*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
300*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: started for zone %s",
301*00b67f09SDavid van Moolenbroek 			   state->zone_name);
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek 	*dbdata = state;
304*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
305*00b67f09SDavid van Moolenbroek 
306*00b67f09SDavid van Moolenbroek  failure:
307*00b67f09SDavid van Moolenbroek 	free(state);
308*00b67f09SDavid van Moolenbroek 	return (result);
309*00b67f09SDavid van Moolenbroek 
310*00b67f09SDavid van Moolenbroek }
311*00b67f09SDavid van Moolenbroek 
312*00b67f09SDavid van Moolenbroek /*
313*00b67f09SDavid van Moolenbroek  * Shut down the backend
314*00b67f09SDavid van Moolenbroek  */
315*00b67f09SDavid van Moolenbroek void
dlz_destroy(void * dbdata)316*00b67f09SDavid van Moolenbroek dlz_destroy(void *dbdata) {
317*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
320*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO,
321*00b67f09SDavid van Moolenbroek 			   "dlz_example: shutting down zone %s",
322*00b67f09SDavid van Moolenbroek 			   state->zone_name);
323*00b67f09SDavid van Moolenbroek 	free(state->zone_name);
324*00b67f09SDavid van Moolenbroek 	free(state);
325*00b67f09SDavid van Moolenbroek }
326*00b67f09SDavid van Moolenbroek 
327*00b67f09SDavid van Moolenbroek /*
328*00b67f09SDavid van Moolenbroek  * See if we handle a given zone
329*00b67f09SDavid van Moolenbroek  */
330*00b67f09SDavid van Moolenbroek isc_result_t
dlz_findzonedb(void * dbdata,const char * name,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)331*00b67f09SDavid van Moolenbroek dlz_findzonedb(void *dbdata, const char *name,
332*00b67f09SDavid van Moolenbroek 	   dns_clientinfomethods_t *methods,
333*00b67f09SDavid van Moolenbroek 	   dns_clientinfo_t *clientinfo)
334*00b67f09SDavid van Moolenbroek {
335*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
336*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t *src;
337*00b67f09SDavid van Moolenbroek 	char addrbuf[100];
338*00b67f09SDavid van Moolenbroek 	char absolute[1024];
339*00b67f09SDavid van Moolenbroek 
340*00b67f09SDavid van Moolenbroek 	strcpy(addrbuf, "unknown");
341*00b67f09SDavid van Moolenbroek 	if (methods != NULL &&
342*00b67f09SDavid van Moolenbroek 	    methods->sourceip != NULL &&
343*00b67f09SDavid van Moolenbroek 	    methods->version - methods->age <= DNS_CLIENTINFOMETHODS_VERSION &&
344*00b67f09SDavid van Moolenbroek 	    DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
345*00b67f09SDavid van Moolenbroek 	{
346*00b67f09SDavid van Moolenbroek 		methods->sourceip(clientinfo, &src);
347*00b67f09SDavid van Moolenbroek 		fmt_address(src, addrbuf, sizeof(addrbuf));
348*00b67f09SDavid van Moolenbroek 	}
349*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "findzonedb: connection from: %s\n", addrbuf);
350*00b67f09SDavid van Moolenbroek 
351*00b67f09SDavid van Moolenbroek 	state->log(ISC_LOG_INFO,
352*00b67f09SDavid van Moolenbroek 		   "dlz_example: dlz_findzonedb called with name '%s' "
353*00b67f09SDavid van Moolenbroek 		   "in zone DB '%s'", name, state->zone_name);
354*00b67f09SDavid van Moolenbroek 
355*00b67f09SDavid van Moolenbroek 	/*
356*00b67f09SDavid van Moolenbroek 	 * Returning ISC_R_NOTFOUND will cause the query logic to
357*00b67f09SDavid van Moolenbroek 	 * check the database for parent names, looking for zone cuts.
358*00b67f09SDavid van Moolenbroek 	 *
359*00b67f09SDavid van Moolenbroek 	 * Returning ISC_R_NOMORE prevents the query logic from doing
360*00b67f09SDavid van Moolenbroek 	 * this; it will move onto the next database after a single query.
361*00b67f09SDavid van Moolenbroek 	 */
362*00b67f09SDavid van Moolenbroek 	if (strcasecmp(name, "test.example.com") == 0)
363*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
364*00b67f09SDavid van Moolenbroek 
365*00b67f09SDavid van Moolenbroek 	/*
366*00b67f09SDavid van Moolenbroek 	 * For example.net, only return ISC_R_NOMORE when queried
367*00b67f09SDavid van Moolenbroek 	 * from 10.53.0.1.
368*00b67f09SDavid van Moolenbroek 	 */
369*00b67f09SDavid van Moolenbroek 	if (strcasecmp(name, "test.example.net") == 0 &&
370*00b67f09SDavid van Moolenbroek 	    strncmp(addrbuf, "10.53.0.1", 9) == 0)
371*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMORE);
372*00b67f09SDavid van Moolenbroek 
373*00b67f09SDavid van Moolenbroek 	/*
374*00b67f09SDavid van Moolenbroek 	 * For bigcname.domain, return success so it appears to be
375*00b67f09SDavid van Moolenbroek 	 * the zone origin; this regression tests a bug in which
376*00b67f09SDavid van Moolenbroek 	 * zone origin nodes could fail to return SERVFAIL to the client.
377*00b67f09SDavid van Moolenbroek 	 */
378*00b67f09SDavid van Moolenbroek 	if (strcasecmp(name, "bigcname.domain") == 0)
379*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
380*00b67f09SDavid van Moolenbroek 
381*00b67f09SDavid van Moolenbroek 	/*
382*00b67f09SDavid van Moolenbroek 	 * Return success if we have an exact match between the
383*00b67f09SDavid van Moolenbroek 	 * zone name and the qname
384*00b67f09SDavid van Moolenbroek 	 */
385*00b67f09SDavid van Moolenbroek 	if (strcasecmp(state->zone_name, name) == 0)
386*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
387*00b67f09SDavid van Moolenbroek 
388*00b67f09SDavid van Moolenbroek 	snprintf(absolute, sizeof(absolute), "%s.", name);
389*00b67f09SDavid van Moolenbroek 	if (strcasecmp(state->zone_name, absolute) == 0)
390*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
391*00b67f09SDavid van Moolenbroek 
392*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTFOUND);
393*00b67f09SDavid van Moolenbroek }
394*00b67f09SDavid van Moolenbroek 
395*00b67f09SDavid van Moolenbroek /*
396*00b67f09SDavid van Moolenbroek  * Look up one record in the sample database.
397*00b67f09SDavid van Moolenbroek  *
398*00b67f09SDavid van Moolenbroek  * If the queryname is "source-addr", send back a TXT record containing
399*00b67f09SDavid van Moolenbroek  * the address of the client, to test the use of 'methods' and 'clientinfo'
400*00b67f09SDavid van Moolenbroek  *
401*00b67f09SDavid van Moolenbroek  * If the queryname is "too-long", send back a TXT record that's too long
402*00b67f09SDavid van Moolenbroek  * to process; this should result in a SERVFAIL when queried.
403*00b67f09SDavid van Moolenbroek  */
404*00b67f09SDavid van Moolenbroek isc_result_t
dlz_lookup(const char * zone,const char * name,void * dbdata,dns_sdlzlookup_t * lookup,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)405*00b67f09SDavid van Moolenbroek dlz_lookup(const char *zone, const char *name, void *dbdata,
406*00b67f09SDavid van Moolenbroek 	   dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods,
407*00b67f09SDavid van Moolenbroek 	   dns_clientinfo_t *clientinfo)
408*00b67f09SDavid van Moolenbroek {
409*00b67f09SDavid van Moolenbroek 	isc_result_t result;
410*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
411*00b67f09SDavid van Moolenbroek 	isc_boolean_t found = ISC_FALSE;
412*00b67f09SDavid van Moolenbroek 	isc_sockaddr_t *src;
413*00b67f09SDavid van Moolenbroek 	char full_name[256];
414*00b67f09SDavid van Moolenbroek 	char buf[512];
415*00b67f09SDavid van Moolenbroek 	int i;
416*00b67f09SDavid van Moolenbroek 
417*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
418*00b67f09SDavid van Moolenbroek 
419*00b67f09SDavid van Moolenbroek 	if (state->putrr == NULL)
420*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTIMPLEMENTED);
421*00b67f09SDavid van Moolenbroek 
422*00b67f09SDavid van Moolenbroek 	if (strcmp(name, "@") == 0) {
423*00b67f09SDavid van Moolenbroek 		strncpy(full_name, state->zone_name, 255);
424*00b67f09SDavid van Moolenbroek 		full_name[255] = '\0';
425*00b67f09SDavid van Moolenbroek 	} else
426*00b67f09SDavid van Moolenbroek 		snprintf(full_name, 255, "%s.%s", name, state->zone_name);
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek 	if (strcmp(name, "source-addr") == 0) {
429*00b67f09SDavid van Moolenbroek 		strcpy(buf, "unknown");
430*00b67f09SDavid van Moolenbroek 		if (methods != NULL &&
431*00b67f09SDavid van Moolenbroek 		    methods->sourceip != NULL &&
432*00b67f09SDavid van Moolenbroek 		    (methods->version - methods->age <=
433*00b67f09SDavid van Moolenbroek 		     DNS_CLIENTINFOMETHODS_VERSION) &&
434*00b67f09SDavid van Moolenbroek 		    DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
435*00b67f09SDavid van Moolenbroek 		{
436*00b67f09SDavid van Moolenbroek 			methods->sourceip(clientinfo, &src);
437*00b67f09SDavid van Moolenbroek 			fmt_address(src, buf, sizeof(buf));
438*00b67f09SDavid van Moolenbroek 		}
439*00b67f09SDavid van Moolenbroek 
440*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "lookup: connection from: %s\n", buf);
441*00b67f09SDavid van Moolenbroek 
442*00b67f09SDavid van Moolenbroek 		found = ISC_TRUE;
443*00b67f09SDavid van Moolenbroek 		result = state->putrr(lookup, "TXT", 0, buf);
444*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
445*00b67f09SDavid van Moolenbroek 			return (result);
446*00b67f09SDavid van Moolenbroek 	}
447*00b67f09SDavid van Moolenbroek 
448*00b67f09SDavid van Moolenbroek 	if (strcmp(name, "too-long") == 0 ||
449*00b67f09SDavid van Moolenbroek 	    strcmp(zone, "bigcname.domain") == 0)
450*00b67f09SDavid van Moolenbroek 	{
451*00b67f09SDavid van Moolenbroek 		for (i = 0; i < 511; i++)
452*00b67f09SDavid van Moolenbroek 			buf[i] = 'x';
453*00b67f09SDavid van Moolenbroek 		buf[i] = '\0';
454*00b67f09SDavid van Moolenbroek 		found = ISC_TRUE;
455*00b67f09SDavid van Moolenbroek 		result = state->putrr(lookup, "TXT", 0, buf);
456*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
457*00b67f09SDavid van Moolenbroek 			return (result);
458*00b67f09SDavid van Moolenbroek 	}
459*00b67f09SDavid van Moolenbroek 
460*00b67f09SDavid van Moolenbroek 	for (i = 0; i < MAX_RECORDS; i++) {
461*00b67f09SDavid van Moolenbroek 		if (strcasecmp(state->current[i].name, full_name) == 0) {
462*00b67f09SDavid van Moolenbroek 			found = ISC_TRUE;
463*00b67f09SDavid van Moolenbroek 			result = state->putrr(lookup, state->current[i].type,
464*00b67f09SDavid van Moolenbroek 					      state->current[i].ttl,
465*00b67f09SDavid van Moolenbroek 					      state->current[i].data);
466*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
467*00b67f09SDavid van Moolenbroek 				return (result);
468*00b67f09SDavid van Moolenbroek 		}
469*00b67f09SDavid van Moolenbroek 	}
470*00b67f09SDavid van Moolenbroek 
471*00b67f09SDavid van Moolenbroek 	if (!found)
472*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTFOUND);
473*00b67f09SDavid van Moolenbroek 
474*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
475*00b67f09SDavid van Moolenbroek }
476*00b67f09SDavid van Moolenbroek 
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek /*
479*00b67f09SDavid van Moolenbroek  * See if a zone transfer is allowed
480*00b67f09SDavid van Moolenbroek  */
481*00b67f09SDavid van Moolenbroek isc_result_t
dlz_allowzonexfr(void * dbdata,const char * name,const char * client)482*00b67f09SDavid van Moolenbroek dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
483*00b67f09SDavid van Moolenbroek 	UNUSED(client);
484*00b67f09SDavid van Moolenbroek 
485*00b67f09SDavid van Moolenbroek 	/* Just say yes for all our zones */
486*00b67f09SDavid van Moolenbroek 	return (dlz_findzonedb(dbdata, name, NULL, NULL));
487*00b67f09SDavid van Moolenbroek }
488*00b67f09SDavid van Moolenbroek 
489*00b67f09SDavid van Moolenbroek /*
490*00b67f09SDavid van Moolenbroek  * Perform a zone transfer
491*00b67f09SDavid van Moolenbroek  */
492*00b67f09SDavid van Moolenbroek isc_result_t
dlz_allnodes(const char * zone,void * dbdata,dns_sdlzallnodes_t * allnodes)493*00b67f09SDavid van Moolenbroek dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
494*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
495*00b67f09SDavid van Moolenbroek 	int i;
496*00b67f09SDavid van Moolenbroek 
497*00b67f09SDavid van Moolenbroek 	UNUSED(zone);
498*00b67f09SDavid van Moolenbroek 
499*00b67f09SDavid van Moolenbroek 	if (state->putnamedrr == NULL)
500*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTIMPLEMENTED);
501*00b67f09SDavid van Moolenbroek 
502*00b67f09SDavid van Moolenbroek 	for (i = 0; i < MAX_RECORDS; i++) {
503*00b67f09SDavid van Moolenbroek 		isc_result_t result;
504*00b67f09SDavid van Moolenbroek 		if (strlen(state->current[i].name) == 0U) {
505*00b67f09SDavid van Moolenbroek 			continue;
506*00b67f09SDavid van Moolenbroek 		}
507*00b67f09SDavid van Moolenbroek 		result = state->putnamedrr(allnodes, state->current[i].name,
508*00b67f09SDavid van Moolenbroek 					   state->current[i].type,
509*00b67f09SDavid van Moolenbroek 					   state->current[i].ttl,
510*00b67f09SDavid van Moolenbroek 					   state->current[i].data);
511*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
512*00b67f09SDavid van Moolenbroek 			return (result);
513*00b67f09SDavid van Moolenbroek 	}
514*00b67f09SDavid van Moolenbroek 
515*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
516*00b67f09SDavid van Moolenbroek }
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek 
519*00b67f09SDavid van Moolenbroek /*
520*00b67f09SDavid van Moolenbroek  * Start a transaction
521*00b67f09SDavid van Moolenbroek  */
522*00b67f09SDavid van Moolenbroek isc_result_t
dlz_newversion(const char * zone,void * dbdata,void ** versionp)523*00b67f09SDavid van Moolenbroek dlz_newversion(const char *zone, void *dbdata, void **versionp) {
524*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
525*00b67f09SDavid van Moolenbroek 
526*00b67f09SDavid van Moolenbroek 	if (state->transaction_started) {
527*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
528*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO,
529*00b67f09SDavid van Moolenbroek 				   "dlz_example: transaction already "
530*00b67f09SDavid van Moolenbroek 				   "started for zone %s", zone);
531*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
532*00b67f09SDavid van Moolenbroek 	}
533*00b67f09SDavid van Moolenbroek 
534*00b67f09SDavid van Moolenbroek 	state->transaction_started = ISC_TRUE;
535*00b67f09SDavid van Moolenbroek 	*versionp = (void *) &state->transaction_started;
536*00b67f09SDavid van Moolenbroek 
537*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
538*00b67f09SDavid van Moolenbroek }
539*00b67f09SDavid van Moolenbroek 
540*00b67f09SDavid van Moolenbroek /*
541*00b67f09SDavid van Moolenbroek  * End a transaction
542*00b67f09SDavid van Moolenbroek  */
543*00b67f09SDavid van Moolenbroek void
dlz_closeversion(const char * zone,isc_boolean_t commit,void * dbdata,void ** versionp)544*00b67f09SDavid van Moolenbroek dlz_closeversion(const char *zone, isc_boolean_t commit,
545*00b67f09SDavid van Moolenbroek 		 void *dbdata, void **versionp)
546*00b67f09SDavid van Moolenbroek {
547*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
548*00b67f09SDavid van Moolenbroek 
549*00b67f09SDavid van Moolenbroek 	if (!state->transaction_started) {
550*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
551*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO, "dlz_example: transaction not "
552*00b67f09SDavid van Moolenbroek 				   "started for zone %s", zone);
553*00b67f09SDavid van Moolenbroek 		*versionp = NULL;
554*00b67f09SDavid van Moolenbroek 		return;
555*00b67f09SDavid van Moolenbroek 	}
556*00b67f09SDavid van Moolenbroek 
557*00b67f09SDavid van Moolenbroek 	state->transaction_started = ISC_FALSE;
558*00b67f09SDavid van Moolenbroek 
559*00b67f09SDavid van Moolenbroek 	*versionp = NULL;
560*00b67f09SDavid van Moolenbroek 
561*00b67f09SDavid van Moolenbroek 	if (commit) {
562*00b67f09SDavid van Moolenbroek 		int i;
563*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
564*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO, "dlz_example: committing "
565*00b67f09SDavid van Moolenbroek 				   "transaction on zone %s", zone);
566*00b67f09SDavid van Moolenbroek 		for (i = 0; i < MAX_RECORDS; i++) {
567*00b67f09SDavid van Moolenbroek 			if (strlen(state->deletes[i].name) > 0U) {
568*00b67f09SDavid van Moolenbroek 				(void)del_name(state, &state->current[0],
569*00b67f09SDavid van Moolenbroek 					       state->deletes[i].name,
570*00b67f09SDavid van Moolenbroek 					       state->deletes[i].type,
571*00b67f09SDavid van Moolenbroek 					       state->deletes[i].ttl,
572*00b67f09SDavid van Moolenbroek 					       state->deletes[i].data);
573*00b67f09SDavid van Moolenbroek 			}
574*00b67f09SDavid van Moolenbroek 		}
575*00b67f09SDavid van Moolenbroek 		for (i = 0; i < MAX_RECORDS; i++) {
576*00b67f09SDavid van Moolenbroek 			if (strlen(state->adds[i].name) > 0U) {
577*00b67f09SDavid van Moolenbroek 				(void)add_name(state, &state->current[0],
578*00b67f09SDavid van Moolenbroek 					       state->adds[i].name,
579*00b67f09SDavid van Moolenbroek 					       state->adds[i].type,
580*00b67f09SDavid van Moolenbroek 					       state->adds[i].ttl,
581*00b67f09SDavid van Moolenbroek 					       state->adds[i].data);
582*00b67f09SDavid van Moolenbroek 			}
583*00b67f09SDavid van Moolenbroek 		}
584*00b67f09SDavid van Moolenbroek 	} else {
585*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
586*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO, "dlz_example: cancelling "
587*00b67f09SDavid van Moolenbroek 				   "transaction on zone %s", zone);
588*00b67f09SDavid van Moolenbroek 	}
589*00b67f09SDavid van Moolenbroek 	memset(state->adds, 0, sizeof(state->adds));
590*00b67f09SDavid van Moolenbroek 	memset(state->deletes, 0, sizeof(state->deletes));
591*00b67f09SDavid van Moolenbroek }
592*00b67f09SDavid van Moolenbroek 
593*00b67f09SDavid van Moolenbroek 
594*00b67f09SDavid van Moolenbroek /*
595*00b67f09SDavid van Moolenbroek  * Configure a writeable zone
596*00b67f09SDavid van Moolenbroek  */
597*00b67f09SDavid van Moolenbroek isc_result_t
dlz_configure(dns_view_t * view,dns_dlzdb_t * dlzdb,void * dbdata)598*00b67f09SDavid van Moolenbroek dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata) {
599*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
600*00b67f09SDavid van Moolenbroek 	isc_result_t result;
601*00b67f09SDavid van Moolenbroek 
602*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
603*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: starting configure");
604*00b67f09SDavid van Moolenbroek 
605*00b67f09SDavid van Moolenbroek 	if (state->writeable_zone == NULL) {
606*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
607*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO, "dlz_example: no "
608*00b67f09SDavid van Moolenbroek 				   "writeable_zone method available");
609*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
610*00b67f09SDavid van Moolenbroek 	}
611*00b67f09SDavid van Moolenbroek 
612*00b67f09SDavid van Moolenbroek 	result = state->writeable_zone(view, dlzdb, state->zone_name);
613*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
614*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
615*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_ERROR, "dlz_example: failed to "
616*00b67f09SDavid van Moolenbroek 				   "configure zone %s", state->zone_name);
617*00b67f09SDavid van Moolenbroek 		return (result);
618*00b67f09SDavid van Moolenbroek 	}
619*00b67f09SDavid van Moolenbroek 
620*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
621*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: configured writeable "
622*00b67f09SDavid van Moolenbroek 			   "zone %s", state->zone_name);
623*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
624*00b67f09SDavid van Moolenbroek }
625*00b67f09SDavid van Moolenbroek 
626*00b67f09SDavid van Moolenbroek /*
627*00b67f09SDavid van Moolenbroek  * Authorize a zone update
628*00b67f09SDavid van Moolenbroek  */
629*00b67f09SDavid van Moolenbroek isc_boolean_t
dlz_ssumatch(const char * signer,const char * name,const char * tcpaddr,const char * type,const char * key,isc_uint32_t keydatalen,unsigned char * keydata,void * dbdata)630*00b67f09SDavid van Moolenbroek dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
631*00b67f09SDavid van Moolenbroek 	     const char *type, const char *key, isc_uint32_t keydatalen,
632*00b67f09SDavid van Moolenbroek 	     unsigned char *keydata, void *dbdata)
633*00b67f09SDavid van Moolenbroek {
634*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
635*00b67f09SDavid van Moolenbroek 
636*00b67f09SDavid van Moolenbroek 	UNUSED(tcpaddr);
637*00b67f09SDavid van Moolenbroek 	UNUSED(type);
638*00b67f09SDavid van Moolenbroek 	UNUSED(key);
639*00b67f09SDavid van Moolenbroek 	UNUSED(keydatalen);
640*00b67f09SDavid van Moolenbroek 	UNUSED(keydata);
641*00b67f09SDavid van Moolenbroek 
642*00b67f09SDavid van Moolenbroek 	if (strncmp(name, "deny.", 5) == 0) {
643*00b67f09SDavid van Moolenbroek 		if (state->log != NULL)
644*00b67f09SDavid van Moolenbroek 			state->log(ISC_LOG_INFO, "dlz_example: denying update "
645*00b67f09SDavid van Moolenbroek 				   "of name=%s by %s", name, signer);
646*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
647*00b67f09SDavid van Moolenbroek 	}
648*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
649*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: allowing update of "
650*00b67f09SDavid van Moolenbroek 			   "name=%s by %s", name, signer);
651*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
652*00b67f09SDavid van Moolenbroek }
653*00b67f09SDavid van Moolenbroek 
654*00b67f09SDavid van Moolenbroek 
655*00b67f09SDavid van Moolenbroek static isc_result_t
modrdataset(struct dlz_example_data * state,const char * name,const char * rdatastr,struct record * list)656*00b67f09SDavid van Moolenbroek modrdataset(struct dlz_example_data *state, const char *name,
657*00b67f09SDavid van Moolenbroek 	    const char *rdatastr, struct record *list)
658*00b67f09SDavid van Moolenbroek {
659*00b67f09SDavid van Moolenbroek 	char *full_name, *dclass, *type, *data, *ttlstr, *buf;
660*00b67f09SDavid van Moolenbroek 	char absolute[1024];
661*00b67f09SDavid van Moolenbroek 	isc_result_t result;
662*00b67f09SDavid van Moolenbroek #if defined(WIN32) || defined(_REENTRANT)
663*00b67f09SDavid van Moolenbroek 	char *saveptr = NULL;
664*00b67f09SDavid van Moolenbroek #endif
665*00b67f09SDavid van Moolenbroek 
666*00b67f09SDavid van Moolenbroek 	buf = strdup(rdatastr);
667*00b67f09SDavid van Moolenbroek 	if (buf == NULL)
668*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek 	/*
671*00b67f09SDavid van Moolenbroek 	 * The format is:
672*00b67f09SDavid van Moolenbroek 	 * FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
673*00b67f09SDavid van Moolenbroek 	 *
674*00b67f09SDavid van Moolenbroek 	 * The DATA field is space separated, and is in the data format
675*00b67f09SDavid van Moolenbroek 	 * for the type used by dig
676*00b67f09SDavid van Moolenbroek 	 */
677*00b67f09SDavid van Moolenbroek 
678*00b67f09SDavid van Moolenbroek 	full_name = STRTOK_R(buf, "\t", &saveptr);
679*00b67f09SDavid van Moolenbroek 	if (full_name == NULL)
680*00b67f09SDavid van Moolenbroek 		goto error;
681*00b67f09SDavid van Moolenbroek 
682*00b67f09SDavid van Moolenbroek 	ttlstr = STRTOK_R(NULL, "\t", &saveptr);
683*00b67f09SDavid van Moolenbroek 	if (ttlstr == NULL)
684*00b67f09SDavid van Moolenbroek 		goto error;
685*00b67f09SDavid van Moolenbroek 
686*00b67f09SDavid van Moolenbroek 	dclass = STRTOK_R(NULL, "\t", &saveptr);
687*00b67f09SDavid van Moolenbroek 	if (dclass == NULL)
688*00b67f09SDavid van Moolenbroek 		goto error;
689*00b67f09SDavid van Moolenbroek 
690*00b67f09SDavid van Moolenbroek 	type = STRTOK_R(NULL, "\t", &saveptr);
691*00b67f09SDavid van Moolenbroek 	if (type == NULL)
692*00b67f09SDavid van Moolenbroek 		goto error;
693*00b67f09SDavid van Moolenbroek 
694*00b67f09SDavid van Moolenbroek 	data = STRTOK_R(NULL, "\t", &saveptr);
695*00b67f09SDavid van Moolenbroek 	if (data == NULL)
696*00b67f09SDavid van Moolenbroek 		goto error;
697*00b67f09SDavid van Moolenbroek 
698*00b67f09SDavid van Moolenbroek 	if (name[strlen(name) - 1] != '.') {
699*00b67f09SDavid van Moolenbroek 		snprintf(absolute, sizeof(absolute), "%s.", name);
700*00b67f09SDavid van Moolenbroek 		name = absolute;
701*00b67f09SDavid van Moolenbroek 	}
702*00b67f09SDavid van Moolenbroek 
703*00b67f09SDavid van Moolenbroek 	result = add_name(state, list, name, type,
704*00b67f09SDavid van Moolenbroek 			  strtoul(ttlstr, NULL, 10), data);
705*00b67f09SDavid van Moolenbroek 	free(buf);
706*00b67f09SDavid van Moolenbroek 	return (result);
707*00b67f09SDavid van Moolenbroek 
708*00b67f09SDavid van Moolenbroek  error:
709*00b67f09SDavid van Moolenbroek 	free(buf);
710*00b67f09SDavid van Moolenbroek 	return (ISC_R_FAILURE);
711*00b67f09SDavid van Moolenbroek }
712*00b67f09SDavid van Moolenbroek 
713*00b67f09SDavid van Moolenbroek 
714*00b67f09SDavid van Moolenbroek isc_result_t
dlz_addrdataset(const char * name,const char * rdatastr,void * dbdata,void * version)715*00b67f09SDavid van Moolenbroek dlz_addrdataset(const char *name, const char *rdatastr,
716*00b67f09SDavid van Moolenbroek 		void *dbdata, void *version)
717*00b67f09SDavid van Moolenbroek {
718*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
719*00b67f09SDavid van Moolenbroek 
720*00b67f09SDavid van Moolenbroek 	if (version != (void *) &state->transaction_started)
721*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
722*00b67f09SDavid van Moolenbroek 
723*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
724*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: adding rdataset %s '%s'",
725*00b67f09SDavid van Moolenbroek 			   name, rdatastr);
726*00b67f09SDavid van Moolenbroek 
727*00b67f09SDavid van Moolenbroek 	return (modrdataset(state, name, rdatastr, &state->adds[0]));
728*00b67f09SDavid van Moolenbroek }
729*00b67f09SDavid van Moolenbroek 
730*00b67f09SDavid van Moolenbroek isc_result_t
dlz_subrdataset(const char * name,const char * rdatastr,void * dbdata,void * version)731*00b67f09SDavid van Moolenbroek dlz_subrdataset(const char *name, const char *rdatastr,
732*00b67f09SDavid van Moolenbroek 		void *dbdata, void *version)
733*00b67f09SDavid van Moolenbroek {
734*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
735*00b67f09SDavid van Moolenbroek 
736*00b67f09SDavid van Moolenbroek 	if (version != (void *) &state->transaction_started)
737*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
738*00b67f09SDavid van Moolenbroek 
739*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
740*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: subtracting rdataset "
741*00b67f09SDavid van Moolenbroek 			   "%s '%s'", name, rdatastr);
742*00b67f09SDavid van Moolenbroek 
743*00b67f09SDavid van Moolenbroek 	return (modrdataset(state, name, rdatastr, &state->deletes[0]));
744*00b67f09SDavid van Moolenbroek }
745*00b67f09SDavid van Moolenbroek 
746*00b67f09SDavid van Moolenbroek isc_result_t
dlz_delrdataset(const char * name,const char * type,void * dbdata,void * version)747*00b67f09SDavid van Moolenbroek dlz_delrdataset(const char *name, const char *type,
748*00b67f09SDavid van Moolenbroek 		void *dbdata, void *version)
749*00b67f09SDavid van Moolenbroek {
750*00b67f09SDavid van Moolenbroek 	struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
751*00b67f09SDavid van Moolenbroek 
752*00b67f09SDavid van Moolenbroek 	if (version != (void *) &state->transaction_started)
753*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
754*00b67f09SDavid van Moolenbroek 
755*00b67f09SDavid van Moolenbroek 	if (state->log != NULL)
756*00b67f09SDavid van Moolenbroek 		state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s "
757*00b67f09SDavid van Moolenbroek 			   "of type %s", name, type);
758*00b67f09SDavid van Moolenbroek 
759*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
760*00b67f09SDavid van Moolenbroek }
761