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