driver.c revision 1.4
1/*	$NetBSD: driver.c,v 1.4 2019/09/05 19:32:56 christos Exp $	*/
2
3/*
4 * Driver API implementation and main entry point for BIND.
5 *
6 * BIND calls dyndb_version() before loading, dyndb_init() during startup
7 * and dyndb_destroy() during shutdown.
8 *
9 * It is completely up to implementation what to do.
10 *
11 * dyndb <name> <driver> {} sections in named.conf are independent so
12 * driver init() and destroy() functions are called independently for
13 * each section even if they reference the same driver/library. It is
14 * up to driver implementation to detect and catch this situation if
15 * it is undesirable.
16 *
17 * Copyright (C) 2009-2015  Red Hat ; see COPYRIGHT for license
18 */
19
20#include <config.h>
21
22#include <isc/commandline.h>
23#include <isc/hash.h>
24#include <isc/mem.h>
25#include <isc/lib.h>
26#include <isc/util.h>
27
28#include <dns/db.h>
29#include <dns/dyndb.h>
30#include <dns/lib.h>
31#include <dns/types.h>
32
33#include "db.h"
34#include "log.h"
35#include "instance.h"
36#include "util.h"
37
38dns_dyndb_destroy_t dyndb_destroy;
39dns_dyndb_register_t dyndb_init;
40dns_dyndb_version_t dyndb_version;
41
42/*
43 * Driver init is called for each dyndb section in named.conf
44 * once during startup and then again on every reload.
45 *
46 * @code
47 * dyndb example-name "sample.so" { param1 param2 };
48 * @endcode
49 *
50 * @param[in] name        User-defined string from dyndb "name" {}; definition
51 *                        in named.conf.
52 *                        The example above will have name = "example-name".
53 * @param[in] parameters  User-defined parameters from dyndb section as one
54 *                        string. The example above will have
55 *                        params = "param1 param2";
56 * @param[in] file	  The name of the file from which the parameters
57 *                        were read.
58 * @param[in] line	  The line number from which the parameters were read.
59 * @param[out] instp      Pointer to instance-specific data
60 *                        (for one dyndb section).
61 */
62isc_result_t
63dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters,
64	   const char *file, unsigned long line,
65	   const dns_dyndbctx_t *dctx, void **instp)
66{
67	isc_result_t result;
68	unsigned int argc;
69	char **argv = NULL;
70	char *s = NULL;
71	sample_instance_t *sample_inst = NULL;
72
73	REQUIRE(name != NULL);
74	REQUIRE(dctx != NULL);
75
76	/*
77	 * Depending on how dlopen() was called, we may not have
78	 * access to named's global namespace, in which case we need
79	 * to initialize libisc/libdns
80	 */
81	if (dctx->refvar != &isc_bind9) {
82		isc_lib_register();
83		isc_log_setcontext(dctx->lctx);
84		dns_log_setcontext(dctx->lctx);
85		isc_hash_set_initializer(dctx->hashinit);
86	}
87
88	s = isc_mem_strdup(mctx, parameters);
89	if (s == NULL) {
90		result = ISC_R_NOMEMORY;
91		goto cleanup;
92	}
93
94	result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0);
95	if (result != ISC_R_SUCCESS) {
96		log_write(ISC_LOG_ERROR,
97			  "dyndb_init: isc_commandline_strtoargv -> %s\n",
98			  isc_result_totext(result));
99		goto cleanup;
100	}
101
102	log_write(ISC_LOG_DEBUG(9),
103		  "loading params for dyndb '%s' from %s:%lu",
104		  name, file, line);
105
106	/* Finally, create the instance. */
107	result = new_sample_instance(mctx, name, argc, argv, dctx,
108				     &sample_inst);
109	if (result != ISC_R_SUCCESS) {
110		log_write(ISC_LOG_ERROR,
111			  "dyndb_init: new_sample_instance -> %s\n",
112			  isc_result_totext(result));
113		goto cleanup;
114	}
115
116	/*
117	 * This is an example so we create and load zones
118	 * right now.  This step can be arbitrarily postponed.
119	 */
120	result = load_sample_instance_zones(sample_inst);
121	if (result != ISC_R_SUCCESS) {
122		log_write(ISC_LOG_ERROR,
123			  "dyndb_init: load_sample_instance_zones -> %s\n",
124			  isc_result_totext(result));
125		goto cleanup;
126	}
127
128	*instp = sample_inst;
129
130 cleanup:
131	if (s != NULL)
132		isc_mem_free(mctx, s);
133	if (argv != NULL)
134		isc_mem_put(mctx, argv, argc * sizeof(*argv));
135
136	return (result);
137}
138
139/*
140 * Driver destroy is called for every instance on every reload and then once
141 * during shutdown.
142 *
143 * @param[out] instp Pointer to instance-specific data (for one dyndb section).
144 */
145void
146dyndb_destroy(void **instp) {
147	destroy_sample_instance((sample_instance_t **)instp);
148}
149
150/*
151 * Driver version is called when loading the driver to ensure there
152 * is no API mismatch betwen the driver and the caller.
153 */
154int
155dyndb_version(unsigned int *flags) {
156	UNUSED(flags);
157
158	return (DNS_DYNDB_VERSION);
159}
160