1/*	$NetBSD: instance.c,v 1.5 2022/09/23 12:15:25 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0 AND ISC
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16/*
17 * Copyright (C) 2009-2015 Red Hat
18 *
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH
24 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
25 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
26 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
27 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
28 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 * PERFORMANCE OF THIS SOFTWARE.
30 */
31
32/*
33 * Driver instance object.
34 *
35 * One instance is equivalent to dynamic-db section in named.conf.
36 * This module parses arguments and provide high-level operations
37 * instance init/zone load/instance destroy.
38 */
39
40#include "instance.h"
41
42#include <isc/task.h>
43#include <isc/util.h>
44
45#include <dns/db.h>
46#include <dns/dyndb.h>
47#include <dns/fixedname.h>
48#include <dns/name.h>
49#include <dns/view.h>
50#include <dns/zone.h>
51
52#include "db.h"
53#include "log.h"
54#include "util.h"
55#include "zone.h"
56
57/*
58 * Parse parameters and convert them to zone names. Caller has to deallocate
59 * resulting DNS names.
60 *
61 * @param[in]  argv NULL-terminated string array of length 2 (excluding NULL)
62 * 		    Each string has to be a valid DNS name.
63 * @param[out] z1   Zone name from argv[0]
64 * @param[out] z2   Zone name from argv[1]
65 */
66static isc_result_t
67parse_params(isc_mem_t *mctx, int argc, char **argv, dns_name_t *z1,
68	     dns_name_t *z2) {
69	isc_result_t result;
70	int i;
71
72	REQUIRE(argv != NULL);
73	REQUIRE(z1 != NULL);
74	REQUIRE(z2 != NULL);
75
76	for (i = 0; i < argc; i++) {
77		log_info("param: '%s'", argv[i]);
78	}
79	log_info("number of params: %d", i);
80
81	if (argc != 2) {
82		log_error("exactly two parameters "
83			  "(absolute zone names) are required");
84		result = ISC_R_FAILURE;
85		goto cleanup;
86	}
87	result = dns_name_fromstring2(z1, argv[0], dns_rootname, 0, mctx);
88	if (result != ISC_R_SUCCESS) {
89		log_write(ISC_LOG_ERROR,
90			  "parse_params: dns_name_fromstring2 -> %s",
91			  isc_result_totext(result));
92		goto cleanup;
93	}
94	result = dns_name_fromstring2(z2, argv[1], dns_rootname, 0, mctx);
95	if (result != ISC_R_SUCCESS) {
96		log_write(ISC_LOG_ERROR,
97			  "parse_params: dns_name_fromstring2 -> %s",
98			  isc_result_totext(result));
99		goto cleanup;
100	}
101
102	result = ISC_R_SUCCESS;
103
104cleanup:
105	return (result);
106}
107
108/*
109 * Initialize new driver instance. It will not create zones until
110 * load_sample_instance_zones() is called.
111 */
112isc_result_t
113new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv,
114		    const dns_dyndbctx_t *dctx,
115		    sample_instance_t **sample_instp) {
116	isc_result_t result;
117	sample_instance_t *inst = NULL;
118
119	REQUIRE(sample_instp != NULL && *sample_instp == NULL);
120
121	CHECKED_MEM_GET_PTR(mctx, inst);
122	ZERO_PTR(inst);
123	isc_mem_attach(mctx, &inst->mctx);
124
125	inst->db_name = isc_mem_strdup(mctx, db_name);
126
127	inst->zone1_name = dns_fixedname_initname(&inst->zone1_fn);
128	inst->zone2_name = dns_fixedname_initname(&inst->zone2_fn);
129
130	result = parse_params(mctx, argc, argv, inst->zone1_name,
131			      inst->zone2_name);
132	if (result != ISC_R_SUCCESS) {
133		log_write(ISC_LOG_ERROR,
134			  "new_sample_instance: parse_params -> %s",
135			  isc_result_totext(result));
136		goto cleanup;
137	}
138
139	dns_view_attach(dctx->view, &inst->view);
140	dns_zonemgr_attach(dctx->zmgr, &inst->zmgr);
141	isc_task_attach(dctx->task, &inst->task);
142
143	/* Register new DNS DB implementation. */
144	result = dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp);
145	if (result != ISC_R_SUCCESS) {
146		log_write(ISC_LOG_ERROR,
147			  "new_sample_instance: dns_db_register -> %s",
148			  isc_result_totext(result));
149		goto cleanup;
150	}
151
152	*sample_instp = inst;
153	result = ISC_R_SUCCESS;
154
155cleanup:
156	if (result != ISC_R_SUCCESS) {
157		destroy_sample_instance(&inst);
158	}
159	return (result);
160}
161
162/*
163 * Create empty zones, add fake SOA, NS, and A records, load fake zones
164 * and add them to inst->view.
165 */
166isc_result_t
167load_sample_instance_zones(sample_instance_t *inst) {
168	isc_result_t result;
169
170	result = create_zone(inst, inst->zone1_name, &inst->zone1);
171	if (result != ISC_R_SUCCESS) {
172		log_write(ISC_LOG_ERROR,
173			  "load_sample_instance_zones: create_zone -> %s",
174			  isc_result_totext(result));
175		goto cleanup;
176	}
177	result = activate_zone(inst, inst->zone1);
178	if (result != ISC_R_SUCCESS) {
179		log_write(ISC_LOG_ERROR,
180			  "load_sample_instance_zones: activate_zone -> %s",
181			  isc_result_totext(result));
182		goto cleanup;
183	}
184
185	result = create_zone(inst, inst->zone2_name, &inst->zone2);
186	if (result != ISC_R_SUCCESS) {
187		log_write(ISC_LOG_ERROR,
188			  "load_sample_instance_zones: create_zone -> %s",
189			  isc_result_totext(result));
190		goto cleanup;
191	}
192	result = activate_zone(inst, inst->zone2);
193	if (result != ISC_R_SUCCESS) {
194		log_write(ISC_LOG_ERROR,
195			  "load_sample_instance_zones: activate_zone -> %s",
196			  isc_result_totext(result));
197		goto cleanup;
198	}
199
200cleanup:
201	return (result);
202}
203
204void
205destroy_sample_instance(sample_instance_t **instp) {
206	sample_instance_t *inst;
207	REQUIRE(instp != NULL);
208
209	inst = *instp;
210	*instp = NULL;
211	if (inst == NULL) {
212		return;
213	}
214
215	if (inst->db_name != NULL) {
216		isc_mem_free(inst->mctx, inst->db_name);
217	}
218	if (inst->zone1 != NULL) {
219		dns_zone_detach(&inst->zone1);
220	}
221	if (inst->zone2 != NULL) {
222		dns_zone_detach(&inst->zone2);
223	}
224	if (inst->db_imp != NULL) {
225		dns_db_unregister(&inst->db_imp);
226	}
227
228	dns_view_detach(&inst->view);
229	dns_zonemgr_detach(&inst->zmgr);
230	isc_task_detach(&inst->task);
231
232	MEM_PUT_AND_DETACH(inst);
233}
234