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