1 /* $NetBSD: dnsrps.c,v 1.1 2024/02/18 20:57:31 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
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 /*! \file */
17
18 #include <inttypes.h>
19 #include <stdbool.h>
20
21 #ifdef USE_DNSRPS
22
23 #include <stdlib.h>
24
25 #include <isc/mem.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
28
29 #include <dns/db.h>
30 #define LIBRPZ_LIB_OPEN DNSRPS_LIB_OPEN
31 #include <dns/dnsrps.h>
32 #include <dns/rdataset.h>
33 #include <dns/rdatasetiter.h>
34 #include <dns/result.h>
35 #include <dns/rpz.h>
36
37 librpz_t *librpz;
38 librpz_emsg_t librpz_lib_open_emsg;
39 static void *librpz_handle;
40
41 #define RPSDB_MAGIC ISC_MAGIC('R', 'P', 'Z', 'F')
42 #define VALID_RPSDB(rpsdb) ((rpsdb)->common.impmagic == RPSDB_MAGIC)
43
44 #define RD_DB(r) ((r)->private1)
45 #define RD_CUR_RR(r) ((r)->private2)
46 #define RD_NEXT_RR(r) ((r)->resign)
47 #define RD_COUNT(r) ((r)->privateuint4)
48
49 typedef struct {
50 dns_rdatasetiter_t common;
51 dns_rdatatype_t type;
52 dns_rdataclass_t class;
53 uint32_t ttl;
54 uint count;
55 librpz_idx_t next_rr;
56 } rpsdb_rdatasetiter_t;
57
58 static dns_dbmethods_t rpsdb_db_methods;
59 static dns_rdatasetmethods_t rpsdb_rdataset_methods;
60 static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods;
61
62 static librpz_clist_t *clist;
63
64 static isc_mutex_t dnsrps_mutex;
65
66 static void
dnsrps_lock(void * mutex0)67 dnsrps_lock(void *mutex0) {
68 isc_mutex_t *mutex = mutex0;
69
70 LOCK(mutex);
71 }
72
73 static void
dnsrps_unlock(void * mutex0)74 dnsrps_unlock(void *mutex0) {
75 isc_mutex_t *mutex = mutex0;
76
77 UNLOCK(mutex);
78 }
79
80 static void
dnsrps_mutex_destroy(void * mutex0)81 dnsrps_mutex_destroy(void *mutex0) {
82 isc_mutex_t *mutex = mutex0;
83
84 isc_mutex_destroy(mutex);
85 }
86
87 static void
dnsrps_log_fnc(librpz_log_level_t level,void * ctxt,const char * buf)88 dnsrps_log_fnc(librpz_log_level_t level, void *ctxt, const char *buf) {
89 int isc_level;
90
91 UNUSED(ctxt);
92
93 /* Setting librpz_log_level in the configuration overrides the
94 * BIND9 logging levels. */
95 if (level > LIBRPZ_LOG_TRACE1 &&
96 level <= librpz->log_level_val(LIBRPZ_LOG_INVALID))
97 {
98 level = LIBRPZ_LOG_TRACE1;
99 }
100
101 switch (level) {
102 case LIBRPZ_LOG_FATAL:
103 case LIBRPZ_LOG_ERROR: /* errors */
104 default:
105 isc_level = DNS_RPZ_ERROR_LEVEL;
106 break;
107
108 case LIBRPZ_LOG_TRACE1: /* big events such as dnsrpzd starts */
109 isc_level = DNS_RPZ_INFO_LEVEL;
110 break;
111
112 case LIBRPZ_LOG_TRACE2: /* smaller dnsrpzd zone transfers */
113 isc_level = DNS_RPZ_DEBUG_LEVEL1;
114 break;
115
116 case LIBRPZ_LOG_TRACE3: /* librpz hits */
117 isc_level = DNS_RPZ_DEBUG_LEVEL2;
118 break;
119
120 case LIBRPZ_LOG_TRACE4: /* librpz lookups */
121 isc_level = DNS_RPZ_DEBUG_LEVEL3;
122 break;
123 }
124 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
125 isc_level, "dnsrps: %s", buf);
126 }
127
128 /*
129 * Start dnsrps for the entire server.
130 * This is not thread safe, but it is called by a single thread.
131 */
132 isc_result_t
dns_dnsrps_server_create(void)133 dns_dnsrps_server_create(void) {
134 librpz_emsg_t emsg;
135
136 INSIST(clist == NULL);
137 INSIST(librpz == NULL);
138 INSIST(librpz_handle == NULL);
139
140 /*
141 * Notice if librpz is available.
142 */
143 librpz = librpz_lib_open(&librpz_lib_open_emsg, &librpz_handle,
144 DNSRPS_LIBRPZ_PATH);
145 /*
146 * Stop now without complaining if librpz is not available.
147 * Complain later if and when librpz is needed for a view with
148 * "dnsrps-enable yes" (including the default view).
149 */
150 if (librpz == NULL) {
151 return (ISC_R_SUCCESS);
152 }
153
154 isc_mutex_init(&dnsrps_mutex);
155
156 librpz->set_log(dnsrps_log_fnc, NULL);
157
158 clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock,
159 dnsrps_mutex_destroy, &dnsrps_mutex,
160 dns_lctx);
161 if (clist == NULL) {
162 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
163 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
164 "dnsrps: %s", emsg.c);
165 return (ISC_R_NOMEMORY);
166 }
167 return (ISC_R_SUCCESS);
168 }
169
170 /*
171 * Stop dnsrps for the entire server.
172 * This is not thread safe.
173 */
174 void
dns_dnsrps_server_destroy(void)175 dns_dnsrps_server_destroy(void) {
176 if (clist != NULL) {
177 librpz->clist_detach(&clist);
178 }
179
180 #ifdef LIBRPZ_USE_DLOPEN
181 if (librpz != NULL) {
182 INSIST(librpz_handle != NULL);
183 if (dlclose(librpz_handle) != 0) {
184 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
185 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
186 "dnsrps: dlclose(): %s", dlerror());
187 }
188 librpz_handle = NULL;
189 }
190 #endif /* ifdef LIBRPZ_USE_DLOPEN */
191 }
192
193 /*
194 * Ready dnsrps for a view.
195 */
196 isc_result_t
dns_dnsrps_view_init(dns_rpz_zones_t * new,char * rps_cstr)197 dns_dnsrps_view_init(dns_rpz_zones_t *new, char *rps_cstr) {
198 librpz_emsg_t emsg;
199
200 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
201 DNS_RPZ_DEBUG_LEVEL3, "dnsrps configuration \"%s\"",
202 rps_cstr);
203
204 new->rps_client = librpz->client_create(&emsg, clist, rps_cstr, false);
205 if (new->rps_client == NULL) {
206 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
207 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
208 "librpz->client_create(): %s", emsg.c);
209 new->p.dnsrps_enabled = false;
210 return (ISC_R_FAILURE);
211 }
212
213 new->p.dnsrps_enabled = true;
214 return (ISC_R_SUCCESS);
215 }
216
217 /*
218 * Connect to and start the dnsrps daemon, dnsrpzd.
219 */
220 isc_result_t
dns_dnsrps_connect(dns_rpz_zones_t * rpzs)221 dns_dnsrps_connect(dns_rpz_zones_t *rpzs) {
222 librpz_emsg_t emsg;
223
224 if (rpzs == NULL || !rpzs->p.dnsrps_enabled) {
225 return (ISC_R_SUCCESS);
226 }
227
228 /*
229 * Fail only if we failed to link to librpz.
230 */
231 if (librpz == NULL) {
232 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
233 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
234 "librpz->connect(): %s", librpz_lib_open_emsg.c);
235 return (ISC_R_FAILURE);
236 }
237
238 if (!librpz->connect(&emsg, rpzs->rps_client, true)) {
239 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
240 DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
241 "librpz->connect(): %s", emsg.c);
242 return (ISC_R_SUCCESS);
243 }
244
245 isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
246 DNS_RPZ_INFO_LEVEL, "dnsrps: librpz version %s",
247 librpz->version);
248
249 return (ISC_R_SUCCESS);
250 }
251
252 /*
253 * Get ready to try RPZ rewriting.
254 */
255 isc_result_t
dns_dnsrps_rewrite_init(librpz_emsg_t * emsg,dns_rpz_st_t * st,dns_rpz_zones_t * rpzs,const dns_name_t * qname,isc_mem_t * mctx,bool have_rd)256 dns_dnsrps_rewrite_init(librpz_emsg_t *emsg, dns_rpz_st_t *st,
257 dns_rpz_zones_t *rpzs, const dns_name_t *qname,
258 isc_mem_t *mctx, bool have_rd) {
259 rpsdb_t *rpsdb;
260
261 rpsdb = isc_mem_get(mctx, sizeof(*rpsdb));
262 memset(rpsdb, 0, sizeof(*rpsdb));
263
264 if (!librpz->rsp_create(emsg, &rpsdb->rsp, NULL, rpzs->rps_client,
265 have_rd, false))
266 {
267 isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
268 return (DNS_R_SERVFAIL);
269 }
270 if (rpsdb->rsp == NULL) {
271 isc_mem_put(mctx, rpsdb, sizeof(*rpsdb));
272 return (DNS_R_DISALLOWED);
273 }
274
275 rpsdb->common.magic = DNS_DB_MAGIC;
276 rpsdb->common.impmagic = RPSDB_MAGIC;
277 rpsdb->common.methods = &rpsdb_db_methods;
278 rpsdb->common.rdclass = dns_rdataclass_in;
279 dns_name_init(&rpsdb->common.origin, NULL);
280 isc_mem_attach(mctx, &rpsdb->common.mctx);
281
282 rpsdb->ref_cnt = 1;
283 rpsdb->qname = qname;
284
285 st->rpsdb = &rpsdb->common;
286 return (ISC_R_SUCCESS);
287 }
288
289 /*
290 * Convert a dnsrps policy to a classic BIND9 RPZ policy.
291 */
292 dns_rpz_policy_t
dns_dnsrps_2policy(librpz_policy_t rps_policy)293 dns_dnsrps_2policy(librpz_policy_t rps_policy) {
294 switch (rps_policy) {
295 case LIBRPZ_POLICY_UNDEFINED:
296 return (DNS_RPZ_POLICY_MISS);
297 case LIBRPZ_POLICY_PASSTHRU:
298 return (DNS_RPZ_POLICY_PASSTHRU);
299 case LIBRPZ_POLICY_DROP:
300 return (DNS_RPZ_POLICY_DROP);
301 case LIBRPZ_POLICY_TCP_ONLY:
302 return (DNS_RPZ_POLICY_TCP_ONLY);
303 case LIBRPZ_POLICY_NXDOMAIN:
304 return (DNS_RPZ_POLICY_NXDOMAIN);
305 case LIBRPZ_POLICY_NODATA:
306 return (DNS_RPZ_POLICY_NODATA);
307 case LIBRPZ_POLICY_RECORD:
308 case LIBRPZ_POLICY_CNAME:
309 return (DNS_RPZ_POLICY_RECORD);
310
311 case LIBRPZ_POLICY_DELETED:
312 case LIBRPZ_POLICY_GIVEN:
313 case LIBRPZ_POLICY_DISABLED:
314 default:
315 UNREACHABLE();
316 }
317 }
318
319 /*
320 * Convert a dnsrps trigger to a classic BIND9 RPZ rewrite or trigger type.
321 */
322 dns_rpz_type_t
dns_dnsrps_trig2type(librpz_trig_t trig)323 dns_dnsrps_trig2type(librpz_trig_t trig) {
324 switch (trig) {
325 case LIBRPZ_TRIG_BAD:
326 default:
327 return (DNS_RPZ_TYPE_BAD);
328 case LIBRPZ_TRIG_CLIENT_IP:
329 return (DNS_RPZ_TYPE_CLIENT_IP);
330 case LIBRPZ_TRIG_QNAME:
331 return (DNS_RPZ_TYPE_QNAME);
332 case LIBRPZ_TRIG_IP:
333 return (DNS_RPZ_TYPE_IP);
334 case LIBRPZ_TRIG_NSDNAME:
335 return (DNS_RPZ_TYPE_NSDNAME);
336 case LIBRPZ_TRIG_NSIP:
337 return (DNS_RPZ_TYPE_NSIP);
338 }
339 }
340
341 /*
342 * Convert a classic BIND9 RPZ rewrite or trigger type to a librpz trigger type.
343 */
344 librpz_trig_t
dns_dnsrps_type2trig(dns_rpz_type_t type)345 dns_dnsrps_type2trig(dns_rpz_type_t type) {
346 switch (type) {
347 case DNS_RPZ_TYPE_BAD:
348 default:
349 return (LIBRPZ_TRIG_BAD);
350 case DNS_RPZ_TYPE_CLIENT_IP:
351 return (LIBRPZ_TRIG_CLIENT_IP);
352 case DNS_RPZ_TYPE_QNAME:
353 return (LIBRPZ_TRIG_QNAME);
354 case DNS_RPZ_TYPE_IP:
355 return (LIBRPZ_TRIG_IP);
356 case DNS_RPZ_TYPE_NSDNAME:
357 return (LIBRPZ_TRIG_NSDNAME);
358 case DNS_RPZ_TYPE_NSIP:
359 return (LIBRPZ_TRIG_NSIP);
360 }
361 }
362
363 static void
rpsdb_attach(dns_db_t * source,dns_db_t ** targetp)364 rpsdb_attach(dns_db_t *source, dns_db_t **targetp) {
365 rpsdb_t *rpsdb = (rpsdb_t *)source;
366
367 REQUIRE(VALID_RPSDB(rpsdb));
368
369 /*
370 * Use a simple count because only one thread uses any single rpsdb_t
371 */
372 ++rpsdb->ref_cnt;
373 *targetp = source;
374 }
375
376 static void
rpsdb_detach(dns_db_t ** dbp)377 rpsdb_detach(dns_db_t **dbp) {
378 rpsdb_t *rpsdb = (rpsdb_t *)*dbp;
379
380 REQUIRE(VALID_RPSDB(rpsdb));
381 REQUIRE(rpsdb->ref_cnt > 0);
382
383 *dbp = NULL;
384
385 /*
386 * Simple count because only one thread uses a rpsdb_t.
387 */
388 if (--rpsdb->ref_cnt != 0) {
389 return;
390 }
391
392 librpz->rsp_detach(&rpsdb->rsp);
393 rpsdb->common.impmagic = 0;
394 isc_mem_putanddetach(&rpsdb->common.mctx, rpsdb, sizeof(*rpsdb));
395 }
396
397 static void
rpsdb_attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)398 rpsdb_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
399 rpsdb_t *rpsdb = (rpsdb_t *)db;
400
401 REQUIRE(VALID_RPSDB(rpsdb));
402 REQUIRE(targetp != NULL && *targetp == NULL);
403 REQUIRE(source == &rpsdb->origin_node || source == &rpsdb->data_node);
404
405 /*
406 * Simple count because only one thread uses a rpsdb_t.
407 */
408 ++rpsdb->ref_cnt;
409 *targetp = source;
410 }
411
412 static void
rpsdb_detachnode(dns_db_t * db,dns_dbnode_t ** targetp)413 rpsdb_detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
414 rpsdb_t *rpsdb = (rpsdb_t *)db;
415
416 REQUIRE(VALID_RPSDB(rpsdb));
417 REQUIRE(*targetp == &rpsdb->origin_node ||
418 *targetp == &rpsdb->data_node);
419
420 *targetp = NULL;
421 rpsdb_detach(&db);
422 }
423
424 static isc_result_t
rpsdb_findnode(dns_db_t * db,const dns_name_t * name,bool create,dns_dbnode_t ** nodep)425 rpsdb_findnode(dns_db_t *db, const dns_name_t *name, bool create,
426 dns_dbnode_t **nodep) {
427 rpsdb_t *rpsdb = (rpsdb_t *)db;
428 dns_db_t *dbp;
429
430 REQUIRE(VALID_RPSDB(rpsdb));
431 REQUIRE(nodep != NULL && *nodep == NULL);
432 REQUIRE(!create);
433
434 /*
435 * A fake/shim rpsdb has two nodes.
436 * One is the origin to support query_addsoa() in bin/named/query.c.
437 * The other contains rewritten RRs.
438 */
439 if (dns_name_equal(name, &db->origin)) {
440 *nodep = &rpsdb->origin_node;
441 } else {
442 *nodep = &rpsdb->data_node;
443 }
444 dbp = NULL;
445 rpsdb_attach(db, &dbp);
446
447 return (ISC_R_SUCCESS);
448 }
449
450 static void
rpsdb_bind_rdataset(dns_rdataset_t * rdataset,uint count,librpz_idx_t next_rr,dns_rdatatype_t type,uint16_t class,uint32_t ttl,rpsdb_t * rpsdb)451 rpsdb_bind_rdataset(dns_rdataset_t *rdataset, uint count, librpz_idx_t next_rr,
452 dns_rdatatype_t type, uint16_t class, uint32_t ttl,
453 rpsdb_t *rpsdb) {
454 dns_db_t *dbp;
455
456 INSIST(rdataset->methods == NULL); /* We must be disassociated. */
457 REQUIRE(type != dns_rdatatype_none);
458
459 rdataset->methods = &rpsdb_rdataset_methods;
460 rdataset->rdclass = class;
461 rdataset->type = type;
462 rdataset->ttl = ttl;
463 dbp = NULL;
464 dns_db_attach(&rpsdb->common, &dbp);
465 RD_DB(rdataset) = dbp;
466 RD_COUNT(rdataset) = count;
467 RD_NEXT_RR(rdataset) = next_rr;
468 RD_CUR_RR(rdataset) = NULL;
469 }
470
471 static isc_result_t
rpsdb_bind_soa(dns_rdataset_t * rdataset,rpsdb_t * rpsdb)472 rpsdb_bind_soa(dns_rdataset_t *rdataset, rpsdb_t *rpsdb) {
473 uint32_t ttl;
474 librpz_emsg_t emsg;
475
476 if (!librpz->rsp_soa(&emsg, &ttl, NULL, NULL, &rpsdb->result,
477 rpsdb->rsp))
478 {
479 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
480 return (DNS_R_SERVFAIL);
481 }
482 rpsdb_bind_rdataset(rdataset, 1, LIBRPZ_IDX_BAD, dns_rdatatype_soa,
483 dns_rdataclass_in, ttl, rpsdb);
484 return (ISC_R_SUCCESS);
485 }
486
487 /*
488 * Forge an rdataset of the desired type from a librpz result.
489 * This is written for simplicity instead of speed, because RPZ rewriting
490 * should be rare compared to normal BIND operations.
491 */
492 static isc_result_t
rpsdb_findrdataset(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dns_rdatatype_t covers,isc_stdtime_t now,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)493 rpsdb_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
494 dns_rdatatype_t type, dns_rdatatype_t covers,
495 isc_stdtime_t now, dns_rdataset_t *rdataset,
496 dns_rdataset_t *sigrdataset) {
497 rpsdb_t *rpsdb = (rpsdb_t *)db;
498 dns_rdatatype_t foundtype;
499 dns_rdataclass_t class;
500 uint32_t ttl;
501 uint count;
502 librpz_emsg_t emsg;
503
504 UNUSED(version);
505 UNUSED(covers);
506 UNUSED(now);
507 UNUSED(sigrdataset);
508
509 REQUIRE(VALID_RPSDB(rpsdb));
510
511 if (node == &rpsdb->origin_node) {
512 if (type == dns_rdatatype_any) {
513 return (ISC_R_SUCCESS);
514 }
515 if (type == dns_rdatatype_soa) {
516 return (rpsdb_bind_soa(rdataset, rpsdb));
517 }
518 return (DNS_R_NXRRSET);
519 }
520
521 REQUIRE(node == &rpsdb->data_node);
522
523 switch (rpsdb->result.policy) {
524 case LIBRPZ_POLICY_UNDEFINED:
525 case LIBRPZ_POLICY_DELETED:
526 case LIBRPZ_POLICY_PASSTHRU:
527 case LIBRPZ_POLICY_DROP:
528 case LIBRPZ_POLICY_TCP_ONLY:
529 case LIBRPZ_POLICY_GIVEN:
530 case LIBRPZ_POLICY_DISABLED:
531 default:
532 librpz->log(LIBRPZ_LOG_ERROR, NULL,
533 "impossible dnsrps policy %d at %s:%d",
534 rpsdb->result.policy, __FILE__, __LINE__);
535 return (DNS_R_SERVFAIL);
536
537 case LIBRPZ_POLICY_NXDOMAIN:
538 return (DNS_R_NXDOMAIN);
539
540 case LIBRPZ_POLICY_NODATA:
541 return (DNS_R_NXRRSET);
542
543 case LIBRPZ_POLICY_RECORD:
544 case LIBRPZ_POLICY_CNAME:
545 break;
546 }
547
548 if (type == dns_rdatatype_soa) {
549 return (rpsdb_bind_soa(rdataset, rpsdb));
550 }
551
552 /*
553 * There is little to do for an ANY query.
554 */
555 if (type == dns_rdatatype_any) {
556 return (ISC_R_SUCCESS);
557 }
558
559 /*
560 * Reset to the start of the RRs.
561 * This function is only used after a policy has been chosen,
562 * and so without caring whether it is after recursion.
563 */
564 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
565 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
566 return (DNS_R_SERVFAIL);
567 }
568 if (!librpz->rsp_rr(&emsg, &foundtype, &class, &ttl, NULL,
569 &rpsdb->result, rpsdb->qname->ndata,
570 rpsdb->qname->length, rpsdb->rsp))
571 {
572 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
573 return (DNS_R_SERVFAIL);
574 }
575 REQUIRE(foundtype != dns_rdatatype_none);
576
577 /*
578 * Ho many of the target RR type are available?
579 */
580 count = 0;
581 do {
582 if (type == foundtype || type == dns_rdatatype_any) {
583 ++count;
584 }
585
586 if (!librpz->rsp_rr(&emsg, &foundtype, NULL, NULL, NULL,
587 &rpsdb->result, rpsdb->qname->ndata,
588 rpsdb->qname->length, rpsdb->rsp))
589 {
590 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
591 return (DNS_R_SERVFAIL);
592 }
593 } while (foundtype != dns_rdatatype_none);
594 if (count == 0) {
595 return (DNS_R_NXRRSET);
596 }
597 rpsdb_bind_rdataset(rdataset, count, rpsdb->result.next_rr, type, class,
598 ttl, rpsdb);
599 return (ISC_R_SUCCESS);
600 }
601
602 static isc_result_t
rpsdb_finddb(dns_db_t * db,const dns_name_t * name,dns_dbversion_t * version,dns_rdatatype_t type,unsigned int options,isc_stdtime_t now,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)603 rpsdb_finddb(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
604 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
605 dns_dbnode_t **nodep, dns_name_t *foundname,
606 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
607 dns_dbnode_t *node;
608
609 UNUSED(version);
610 UNUSED(options);
611 UNUSED(now);
612 UNUSED(sigrdataset);
613
614 if (nodep == NULL) {
615 node = NULL;
616 nodep = &node;
617 }
618 rpsdb_findnode(db, name, false, nodep);
619 dns_name_copynf(name, foundname);
620 return (rpsdb_findrdataset(db, *nodep, NULL, type, 0, 0, rdataset,
621 sigrdataset));
622 }
623
624 static isc_result_t
rpsdb_allrdatasets(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int options,isc_stdtime_t now,dns_rdatasetiter_t ** iteratorp)625 rpsdb_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
626 unsigned int options, isc_stdtime_t now,
627 dns_rdatasetiter_t **iteratorp) {
628 rpsdb_t *rpsdb = (rpsdb_t *)db;
629 rpsdb_rdatasetiter_t *rpsdb_iter;
630
631 UNUSED(version);
632 UNUSED(now);
633
634 REQUIRE(VALID_RPSDB(rpsdb));
635 REQUIRE(node == &rpsdb->origin_node || node == &rpsdb->data_node);
636
637 rpsdb_iter = isc_mem_get(rpsdb->common.mctx, sizeof(*rpsdb_iter));
638
639 memset(rpsdb_iter, 0, sizeof(*rpsdb_iter));
640 rpsdb_iter->common.magic = DNS_RDATASETITER_MAGIC;
641 rpsdb_iter->common.methods = &rpsdb_rdatasetiter_methods;
642 rpsdb_iter->common.db = db;
643 rpsdb_iter->common.options = options;
644 rpsdb_attachnode(db, node, &rpsdb_iter->common.node);
645
646 *iteratorp = &rpsdb_iter->common;
647
648 return (ISC_R_SUCCESS);
649 }
650
651 static bool
rpsdb_issecure(dns_db_t * db)652 rpsdb_issecure(dns_db_t *db) {
653 UNUSED(db);
654
655 return (false);
656 }
657
658 static isc_result_t
rpsdb_getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)659 rpsdb_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
660 rpsdb_t *rpsdb = (rpsdb_t *)db;
661
662 REQUIRE(VALID_RPSDB(rpsdb));
663 REQUIRE(nodep != NULL && *nodep == NULL);
664
665 rpsdb_attachnode(db, &rpsdb->origin_node, nodep);
666 return (ISC_R_SUCCESS);
667 }
668
669 static void
rpsdb_rdataset_disassociate(dns_rdataset_t * rdataset)670 rpsdb_rdataset_disassociate(dns_rdataset_t *rdataset) {
671 dns_db_t *db;
672
673 /*
674 * Detach the last RR delivered.
675 */
676 if (RD_CUR_RR(rdataset) != NULL) {
677 free(RD_CUR_RR(rdataset));
678 RD_CUR_RR(rdataset) = NULL;
679 }
680
681 db = RD_DB(rdataset);
682 RD_DB(rdataset) = NULL;
683 dns_db_detach(&db);
684 }
685
686 static isc_result_t
rpsdb_rdataset_next(dns_rdataset_t * rdataset)687 rpsdb_rdataset_next(dns_rdataset_t *rdataset) {
688 rpsdb_t *rpsdb;
689 uint16_t type;
690 dns_rdataclass_t class;
691 librpz_rr_t *rr;
692 librpz_emsg_t emsg;
693
694 rpsdb = RD_DB(rdataset);
695
696 /*
697 * Detach the previous RR.
698 */
699 if (RD_CUR_RR(rdataset) != NULL) {
700 free(RD_CUR_RR(rdataset));
701 RD_CUR_RR(rdataset) = NULL;
702 }
703
704 /*
705 * Get the next RR of the specified type.
706 * SOAs differ.
707 */
708 if (rdataset->type == dns_rdatatype_soa) {
709 if (RD_NEXT_RR(rdataset) == LIBRPZ_IDX_NULL) {
710 return (ISC_R_NOMORE);
711 }
712 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_NULL;
713 if (!librpz->rsp_soa(&emsg, NULL, &rr, NULL, &rpsdb->result,
714 rpsdb->rsp))
715 {
716 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
717 return (DNS_R_SERVFAIL);
718 }
719 RD_CUR_RR(rdataset) = rr;
720 return (ISC_R_SUCCESS);
721 }
722
723 rpsdb->result.next_rr = RD_NEXT_RR(rdataset);
724 for (;;) {
725 if (!librpz->rsp_rr(&emsg, &type, &class, NULL, &rr,
726 &rpsdb->result, rpsdb->qname->ndata,
727 rpsdb->qname->length, rpsdb->rsp))
728 {
729 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
730 return (DNS_R_SERVFAIL);
731 }
732 if (rdataset->type == type && rdataset->rdclass == class) {
733 RD_CUR_RR(rdataset) = rr;
734 RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
735 return (ISC_R_SUCCESS);
736 }
737 if (type == dns_rdatatype_none) {
738 return (ISC_R_NOMORE);
739 }
740 free(rr);
741 }
742 }
743
744 static isc_result_t
rpsdb_rdataset_first(dns_rdataset_t * rdataset)745 rpsdb_rdataset_first(dns_rdataset_t *rdataset) {
746 rpsdb_t *rpsdb;
747 librpz_emsg_t emsg;
748
749 rpsdb = RD_DB(rdataset);
750 REQUIRE(VALID_RPSDB(rpsdb));
751
752 if (RD_CUR_RR(rdataset) != NULL) {
753 free(RD_CUR_RR(rdataset));
754 RD_CUR_RR(rdataset) = NULL;
755 }
756
757 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
758 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
759 return (DNS_R_SERVFAIL);
760 }
761 if (rdataset->type == dns_rdatatype_soa) {
762 RD_NEXT_RR(rdataset) = LIBRPZ_IDX_BAD;
763 } else {
764 RD_NEXT_RR(rdataset) = rpsdb->result.next_rr;
765 }
766
767 return (rpsdb_rdataset_next(rdataset));
768 }
769
770 static void
rpsdb_rdataset_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)771 rpsdb_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
772 rpsdb_t *rpsdb;
773 librpz_rr_t *rr;
774 isc_region_t r;
775
776 rpsdb = RD_DB(rdataset);
777 REQUIRE(VALID_RPSDB(rpsdb));
778 rr = RD_CUR_RR(rdataset);
779 REQUIRE(rr != NULL);
780
781 r.length = ntohs(rr->rdlength);
782 r.base = rr->rdata;
783 dns_rdata_fromregion(rdata, ntohs(rr->class), ntohs(rr->type), &r);
784 }
785
786 static void
rpsdb_rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)787 rpsdb_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
788 rpsdb_t *rpsdb;
789 dns_db_t *dbp;
790
791 INSIST(!ISC_LINK_LINKED(target, link));
792 *target = *source;
793 ISC_LINK_INIT(target, link);
794 rpsdb = RD_DB(source);
795 REQUIRE(VALID_RPSDB(rpsdb));
796 dbp = NULL;
797 dns_db_attach(&rpsdb->common, &dbp);
798 RD_DB(target) = dbp;
799 RD_CUR_RR(target) = NULL;
800 RD_NEXT_RR(target) = LIBRPZ_IDX_NULL;
801 }
802
803 static unsigned int
rpsdb_rdataset_count(dns_rdataset_t * rdataset)804 rpsdb_rdataset_count(dns_rdataset_t *rdataset) {
805 rpsdb_t *rpsdb;
806
807 rpsdb = RD_DB(rdataset);
808 REQUIRE(VALID_RPSDB(rpsdb));
809
810 return (RD_COUNT(rdataset));
811 }
812
813 static void
rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)814 rpsdb_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
815 rpsdb_t *rpsdb;
816 dns_rdatasetiter_t *iterator;
817 isc_mem_t *mctx;
818
819 iterator = *iteratorp;
820 *iteratorp = NULL;
821 rpsdb = (rpsdb_t *)iterator->db;
822 REQUIRE(VALID_RPSDB(rpsdb));
823
824 mctx = iterator->db->mctx;
825 dns_db_detachnode(iterator->db, &iterator->node);
826 isc_mem_put(mctx, iterator, sizeof(rpsdb_rdatasetiter_t));
827 }
828
829 static isc_result_t
rpsdb_rdatasetiter_next(dns_rdatasetiter_t * iter)830 rpsdb_rdatasetiter_next(dns_rdatasetiter_t *iter) {
831 rpsdb_t *rpsdb;
832 rpsdb_rdatasetiter_t *rpsdb_iter;
833 dns_rdatatype_t next_type, type;
834 dns_rdataclass_t next_class, class;
835 uint32_t ttl;
836 librpz_emsg_t emsg;
837
838 rpsdb = (rpsdb_t *)iter->db;
839 REQUIRE(VALID_RPSDB(rpsdb));
840 rpsdb_iter = (rpsdb_rdatasetiter_t *)iter;
841
842 /*
843 * This function is only used after a policy has been chosen,
844 * and so without caring whether it is after recursion.
845 */
846 if (!librpz->rsp_result(&emsg, &rpsdb->result, true, rpsdb->rsp)) {
847 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
848 return (DNS_R_SERVFAIL);
849 }
850 /*
851 * Find the next class and type after the current class and type
852 * among the RRs in current result.
853 * As a side effect, count the number of those RRs.
854 */
855 rpsdb_iter->count = 0;
856 next_class = dns_rdataclass_reserved0;
857 next_type = dns_rdatatype_none;
858 for (;;) {
859 if (!librpz->rsp_rr(&emsg, &type, &class, &ttl, NULL,
860 &rpsdb->result, rpsdb->qname->ndata,
861 rpsdb->qname->length, rpsdb->rsp))
862 {
863 librpz->log(LIBRPZ_LOG_ERROR, NULL, "%s", emsg.c);
864 return (DNS_R_SERVFAIL);
865 }
866 if (type == dns_rdatatype_none) {
867 if (next_type == dns_rdatatype_none) {
868 return (ISC_R_NOMORE);
869 }
870 rpsdb_iter->type = next_type;
871 rpsdb_iter->class = next_class;
872 return (ISC_R_SUCCESS);
873 }
874 /*
875 * Skip RRs with the current class and type or before.
876 */
877 if (rpsdb_iter->class > class ||
878 (rpsdb_iter->class = class && rpsdb_iter->type >= type))
879 {
880 continue;
881 }
882 if (next_type == dns_rdatatype_none || next_class > class ||
883 (next_class == class && next_type > type))
884 {
885 /*
886 * This is the first of a subsequent class and type.
887 */
888 next_type = type;
889 next_class = class;
890 rpsdb_iter->ttl = ttl;
891 rpsdb_iter->count = 1;
892 rpsdb_iter->next_rr = rpsdb->result.next_rr;
893 } else if (next_type == type && next_class == class) {
894 ++rpsdb_iter->count;
895 }
896 }
897 }
898
899 static isc_result_t
rpsdb_rdatasetiter_first(dns_rdatasetiter_t * iterator)900 rpsdb_rdatasetiter_first(dns_rdatasetiter_t *iterator) {
901 rpsdb_t *rpsdb;
902 rpsdb_rdatasetiter_t *rpsdb_iter;
903
904 rpsdb = (rpsdb_t *)iterator->db;
905 REQUIRE(VALID_RPSDB(rpsdb));
906 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
907
908 rpsdb_iter->type = dns_rdatatype_none;
909 rpsdb_iter->class = dns_rdataclass_reserved0;
910 return (rpsdb_rdatasetiter_next(iterator));
911 }
912
913 static void
rpsdb_rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)914 rpsdb_rdatasetiter_current(dns_rdatasetiter_t *iterator,
915 dns_rdataset_t *rdataset) {
916 rpsdb_t *rpsdb;
917 rpsdb_rdatasetiter_t *rpsdb_iter;
918
919 rpsdb = (rpsdb_t *)iterator->db;
920 REQUIRE(VALID_RPSDB(rpsdb));
921 rpsdb_iter = (rpsdb_rdatasetiter_t *)iterator;
922 REQUIRE(rpsdb_iter->type != dns_rdatatype_none);
923
924 rpsdb_bind_rdataset(rdataset, rpsdb_iter->count, rpsdb_iter->next_rr,
925 rpsdb_iter->type, rpsdb_iter->class,
926 rpsdb_iter->ttl, rpsdb);
927 }
928
929 static dns_dbmethods_t rpsdb_db_methods = {
930 rpsdb_attach,
931 rpsdb_detach,
932 NULL, /* beginload */
933 NULL, /* endload */
934 NULL, /* serialize */
935 NULL, /* dump */
936 NULL, /* currentversion */
937 NULL, /* newversion */
938 NULL, /* attachversion */
939 NULL, /* closeversion */
940 rpsdb_findnode,
941 rpsdb_finddb,
942 NULL, /* findzonecut*/
943 rpsdb_attachnode,
944 rpsdb_detachnode,
945 NULL, /* expirenode */
946 NULL, /* printnode */
947 NULL, /* createiterator */
948 rpsdb_findrdataset,
949 rpsdb_allrdatasets,
950 NULL, /* addrdataset */
951 NULL, /* subtractrdataset */
952 NULL, /* deleterdataset */
953 rpsdb_issecure,
954 NULL, /* nodecount */
955 NULL, /* ispersistent */
956 NULL, /* overmem */
957 NULL, /* settask */
958 rpsdb_getoriginnode,
959 NULL, /* transfernode */
960 NULL, /* getnsec3parameters */
961 NULL, /* findnsec3node */
962 NULL, /* setsigningtime */
963 NULL, /* getsigningtime */
964 NULL, /* resigned */
965 NULL, /* isdnssec */
966 NULL, /* getrrsetstats */
967 NULL, /* rpz_attach */
968 NULL, /* rpz_ready */
969 NULL, /* findnodeext */
970 NULL, /* findext */
971 NULL, /* setcachestats */
972 NULL, /* hashsize */
973 NULL, /* nodefullname */
974 NULL, /* getsize */
975 NULL, /* setservestalettl */
976 NULL, /* getservestalettl */
977 NULL, /* setservestalerefresh */
978 NULL, /* getservestalerefresh */
979 NULL, /* setgluecachestats */
980 NULL /* adjusthashsize */
981 };
982
983 static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
984 rpsdb_rdataset_disassociate,
985 rpsdb_rdataset_first,
986 rpsdb_rdataset_next,
987 rpsdb_rdataset_current,
988 rpsdb_rdataset_clone,
989 rpsdb_rdataset_count,
990 NULL,
991 NULL,
992 NULL,
993 NULL,
994 NULL,
995 NULL,
996 NULL,
997 NULL,
998 NULL,
999 NULL
1000 };
1001
1002 static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = {
1003 rpsdb_rdatasetiter_destroy, rpsdb_rdatasetiter_first,
1004 rpsdb_rdatasetiter_next, rpsdb_rdatasetiter_current
1005 };
1006
1007 #endif /* USE_DNSRPS */
1008