1/*
2 * services/rpz.c - rpz service
3 *
4 * Copyright (c) 2019, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/**
37 * \file
38 *
39 * This file contains functions to enable RPZ service.
40 */
41
42#include "config.h"
43#include "services/rpz.h"
44#include "util/config_file.h"
45#include "sldns/wire2str.h"
46#include "sldns/str2wire.h"
47#include "util/data/dname.h"
48#include "util/net_help.h"
49#include "util/log.h"
50#include "util/data/dname.h"
51#include "util/locks.h"
52#include "util/regional.h"
53#include "util/data/msgencode.h"
54#include "services/cache/dns.h"
55#include "iterator/iterator.h"
56#include "iterator/iter_delegpt.h"
57#include "daemon/worker.h"
58
59typedef struct resp_addr rpz_aclnode_type;
60
61struct matched_delegation_point {
62	uint8_t* dname;
63	size_t dname_len;
64};
65
66/** string for RPZ action enum */
67const char*
68rpz_action_to_string(enum rpz_action a)
69{
70	switch(a) {
71	case RPZ_NXDOMAIN_ACTION: return "rpz-nxdomain";
72	case RPZ_NODATA_ACTION: return "rpz-nodata";
73	case RPZ_PASSTHRU_ACTION: return "rpz-passthru";
74	case RPZ_DROP_ACTION: return "rpz-drop";
75	case RPZ_TCP_ONLY_ACTION: return "rpz-tcp-only";
76	case RPZ_INVALID_ACTION: return "rpz-invalid";
77	case RPZ_LOCAL_DATA_ACTION: return "rpz-local-data";
78	case RPZ_DISABLED_ACTION: return "rpz-disabled";
79	case RPZ_CNAME_OVERRIDE_ACTION: return "rpz-cname-override";
80	case RPZ_NO_OVERRIDE_ACTION: return "rpz-no-override";
81	default: return "rpz-unknown-action";
82	}
83}
84
85/** RPZ action enum for config string */
86static enum rpz_action
87rpz_config_to_action(char* a)
88{
89	if(strcmp(a, "nxdomain") == 0) return RPZ_NXDOMAIN_ACTION;
90	else if(strcmp(a, "nodata") == 0) return RPZ_NODATA_ACTION;
91	else if(strcmp(a, "passthru") == 0) return RPZ_PASSTHRU_ACTION;
92	else if(strcmp(a, "drop") == 0) return RPZ_DROP_ACTION;
93	else if(strcmp(a, "tcp_only") == 0) return RPZ_TCP_ONLY_ACTION;
94	else if(strcmp(a, "cname") == 0) return RPZ_CNAME_OVERRIDE_ACTION;
95	else if(strcmp(a, "disabled") == 0) return RPZ_DISABLED_ACTION;
96	else return RPZ_INVALID_ACTION;
97}
98
99/** string for RPZ trigger enum */
100static const char*
101rpz_trigger_to_string(enum rpz_trigger r)
102{
103	switch(r) {
104	case RPZ_QNAME_TRIGGER: return "rpz-qname";
105	case RPZ_CLIENT_IP_TRIGGER: return "rpz-client-ip";
106	case RPZ_RESPONSE_IP_TRIGGER: return "rpz-response-ip";
107	case RPZ_NSDNAME_TRIGGER: return "rpz-nsdname";
108	case RPZ_NSIP_TRIGGER: return "rpz-nsip";
109	case RPZ_INVALID_TRIGGER: return "rpz-invalid";
110	default: return "rpz-unknown-trigger";
111	}
112}
113
114/**
115 * Get the label that is just before the root label.
116 * @param dname: dname to work on
117 * @param maxdnamelen: maximum length of the dname
118 * @return: pointer to TLD label, NULL if not found or invalid dname
119 */
120static uint8_t*
121get_tld_label(uint8_t* dname, size_t maxdnamelen)
122{
123	uint8_t* prevlab = dname;
124	size_t dnamelen = 0;
125
126	/* one byte needed for label length */
127	if(dnamelen+1 > maxdnamelen)
128		return NULL;
129
130	/* only root label */
131	if(*dname == 0)
132		return NULL;
133
134	while(*dname) {
135		dnamelen += ((size_t)*dname)+1;
136		if(dnamelen+1 > maxdnamelen)
137			return NULL;
138		dname = dname+((size_t)*dname)+1;
139		if(*dname != 0)
140			prevlab = dname;
141	}
142	return prevlab;
143}
144
145/**
146 * The RR types that are to be ignored.
147 * DNSSEC RRs at the apex, and SOA and NS are ignored.
148 */
149static int
150rpz_type_ignored(uint16_t rr_type)
151{
152	switch(rr_type) {
153		case LDNS_RR_TYPE_SOA:
154		case LDNS_RR_TYPE_NS:
155		case LDNS_RR_TYPE_DNAME:
156		/* all DNSSEC-related RRs must be ignored */
157		case LDNS_RR_TYPE_DNSKEY:
158		case LDNS_RR_TYPE_DS:
159		case LDNS_RR_TYPE_RRSIG:
160		case LDNS_RR_TYPE_NSEC:
161		case LDNS_RR_TYPE_NSEC3:
162		case LDNS_RR_TYPE_NSEC3PARAM:
163			return 1;
164		default:
165			break;
166	}
167	return 0;
168}
169
170/**
171 * Classify RPZ action for RR type/rdata
172 * @param rr_type: the RR type
173 * @param rdatawl: RDATA with 2 bytes length
174 * @param rdatalen: the length of rdatawl (including its 2 bytes length)
175 * @return: the RPZ action
176 */
177static enum rpz_action
178rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
179{
180	char* endptr;
181	uint8_t* rdata;
182	int rdatalabs;
183	uint8_t* tldlab = NULL;
184
185	switch(rr_type) {
186		case LDNS_RR_TYPE_SOA:
187		case LDNS_RR_TYPE_NS:
188		case LDNS_RR_TYPE_DNAME:
189		/* all DNSSEC-related RRs must be ignored */
190		case LDNS_RR_TYPE_DNSKEY:
191		case LDNS_RR_TYPE_DS:
192		case LDNS_RR_TYPE_RRSIG:
193		case LDNS_RR_TYPE_NSEC:
194		case LDNS_RR_TYPE_NSEC3:
195		case LDNS_RR_TYPE_NSEC3PARAM:
196			return RPZ_INVALID_ACTION;
197		case LDNS_RR_TYPE_CNAME:
198			break;
199		default:
200			return RPZ_LOCAL_DATA_ACTION;
201	}
202
203	/* use CNAME target to determine RPZ action */
204	log_assert(rr_type == LDNS_RR_TYPE_CNAME);
205	if(rdatalen < 3)
206		return RPZ_INVALID_ACTION;
207
208	rdata = rdatawl + 2; /* 2 bytes of rdata length */
209	if(dname_valid(rdata, rdatalen-2) != rdatalen-2)
210		return RPZ_INVALID_ACTION;
211
212	rdatalabs = dname_count_labels(rdata);
213	if(rdatalabs == 1)
214		return RPZ_NXDOMAIN_ACTION;
215	else if(rdatalabs == 2) {
216		if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000"))
217			return RPZ_NODATA_ACTION;
218		else if(dname_subdomain_c(rdata,
219			(uint8_t*)&"\014rpz-passthru\000"))
220			return RPZ_PASSTHRU_ACTION;
221		else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000"))
222			return RPZ_DROP_ACTION;
223		else if(dname_subdomain_c(rdata,
224			(uint8_t*)&"\014rpz-tcp-only\000"))
225			return RPZ_TCP_ONLY_ACTION;
226	}
227
228	/* all other TLDs starting with "rpz-" are invalid */
229	tldlab = get_tld_label(rdata, rdatalen-2);
230	if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr))
231		return RPZ_INVALID_ACTION;
232
233	/* no special label found */
234	return RPZ_LOCAL_DATA_ACTION;
235}
236
237static enum localzone_type
238rpz_action_to_localzone_type(enum rpz_action a)
239{
240	switch(a) {
241	case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain;
242	case RPZ_NODATA_ACTION: return local_zone_always_nodata;
243	case RPZ_DROP_ACTION: return local_zone_always_deny;
244	case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
245	case RPZ_LOCAL_DATA_ACTION:	/* fallthrough */
246	case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
247	case RPZ_TCP_ONLY_ACTION: return local_zone_truncate;
248	case RPZ_INVALID_ACTION: /* fallthrough */
249	default: return local_zone_invalid;
250	}
251}
252
253enum respip_action
254rpz_action_to_respip_action(enum rpz_action a)
255{
256	switch(a) {
257	case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain;
258	case RPZ_NODATA_ACTION: return respip_always_nodata;
259	case RPZ_DROP_ACTION: return respip_always_deny;
260	case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
261	case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
262	case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
263	case RPZ_TCP_ONLY_ACTION: return respip_truncate;
264	case RPZ_INVALID_ACTION: /* fallthrough */
265	default: return respip_invalid;
266	}
267}
268
269static enum rpz_action
270localzone_type_to_rpz_action(enum localzone_type lzt)
271{
272	switch(lzt) {
273	case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
274	case local_zone_always_nodata: return RPZ_NODATA_ACTION;
275	case local_zone_always_deny: return RPZ_DROP_ACTION;
276	case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
277	case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
278	case local_zone_truncate: return RPZ_TCP_ONLY_ACTION;
279	case local_zone_invalid: /* fallthrough */
280	default: return RPZ_INVALID_ACTION;
281	}
282}
283
284enum rpz_action
285respip_action_to_rpz_action(enum respip_action a)
286{
287	switch(a) {
288	case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
289	case respip_always_nodata: return RPZ_NODATA_ACTION;
290	case respip_always_deny: return RPZ_DROP_ACTION;
291	case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
292	case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
293	case respip_truncate: return RPZ_TCP_ONLY_ACTION;
294	case respip_invalid: /* fallthrough */
295	default: return RPZ_INVALID_ACTION;
296	}
297}
298
299/**
300 * Get RPZ trigger for dname
301 * @param dname: dname containing RPZ trigger
302 * @param dname_len: length of the dname
303 * @return: RPZ trigger enum
304 */
305static enum rpz_trigger
306rpz_dname_to_trigger(uint8_t* dname, size_t dname_len)
307{
308	uint8_t* tldlab;
309	char* endptr;
310
311	if(dname_valid(dname, dname_len) != dname_len)
312		return RPZ_INVALID_TRIGGER;
313
314	tldlab = get_tld_label(dname, dname_len);
315	if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr))
316		return RPZ_QNAME_TRIGGER;
317
318	if(dname_subdomain_c(tldlab,
319		(uint8_t*)&"\015rpz-client-ip\000"))
320		return RPZ_CLIENT_IP_TRIGGER;
321	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000"))
322		return RPZ_RESPONSE_IP_TRIGGER;
323	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000"))
324		return RPZ_NSDNAME_TRIGGER;
325	else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000"))
326		return RPZ_NSIP_TRIGGER;
327
328	return RPZ_QNAME_TRIGGER;
329}
330
331static inline struct clientip_synthesized_rrset*
332rpz_clientip_synthesized_set_create(void)
333{
334	struct clientip_synthesized_rrset* set = calloc(1, sizeof(*set));
335	if(set == NULL) {
336		return NULL;
337	}
338	set->region = regional_create();
339	if(set->region == NULL) {
340		free(set);
341		return NULL;
342	}
343	addr_tree_init(&set->entries);
344	lock_rw_init(&set->lock);
345	return set;
346}
347
348static void
349rpz_clientip_synthesized_rr_delete(rbnode_type* n, void* ATTR_UNUSED(arg))
350{
351	struct clientip_synthesized_rr* r = (struct clientip_synthesized_rr*)n->key;
352	lock_rw_destroy(&r->lock);
353#ifdef THREADS_DISABLED
354	(void)r;
355#endif
356}
357
358static inline void
359rpz_clientip_synthesized_set_delete(struct clientip_synthesized_rrset* set)
360{
361	if(set == NULL) {
362		return;
363	}
364	lock_rw_destroy(&set->lock);
365	traverse_postorder(&set->entries, rpz_clientip_synthesized_rr_delete, NULL);
366	regional_destroy(set->region);
367	free(set);
368}
369
370void
371rpz_delete(struct rpz* r)
372{
373	if(!r)
374		return;
375	local_zones_delete(r->local_zones);
376	local_zones_delete(r->nsdname_zones);
377	respip_set_delete(r->respip_set);
378	rpz_clientip_synthesized_set_delete(r->client_set);
379	rpz_clientip_synthesized_set_delete(r->ns_set);
380	regional_destroy(r->region);
381	free(r->taglist);
382	free(r->log_name);
383	free(r);
384}
385
386int
387rpz_clear(struct rpz* r)
388{
389	/* must hold write lock on auth_zone */
390	local_zones_delete(r->local_zones);
391	r->local_zones = NULL;
392	local_zones_delete(r->nsdname_zones);
393	r->nsdname_zones = NULL;
394	respip_set_delete(r->respip_set);
395	r->respip_set = NULL;
396	rpz_clientip_synthesized_set_delete(r->client_set);
397	r->client_set = NULL;
398	rpz_clientip_synthesized_set_delete(r->ns_set);
399	r->ns_set = NULL;
400	if(!(r->local_zones = local_zones_create())){
401		return 0;
402	}
403	r->nsdname_zones = local_zones_create();
404	if(r->nsdname_zones == NULL) {
405		return 0;
406	}
407	if(!(r->respip_set = respip_set_create())) {
408		return 0;
409	}
410	if(!(r->client_set = rpz_clientip_synthesized_set_create())) {
411		return 0;
412	}
413	if(!(r->ns_set = rpz_clientip_synthesized_set_create())) {
414		return 0;
415	}
416	return 1;
417}
418
419void
420rpz_finish_config(struct rpz* r)
421{
422	lock_rw_wrlock(&r->respip_set->lock);
423	addr_tree_init_parents(&r->respip_set->ip_tree);
424	lock_rw_unlock(&r->respip_set->lock);
425
426	lock_rw_wrlock(&r->client_set->lock);
427	addr_tree_init_parents(&r->client_set->entries);
428	lock_rw_unlock(&r->client_set->lock);
429
430	lock_rw_wrlock(&r->ns_set->lock);
431	addr_tree_init_parents(&r->ns_set->entries);
432	lock_rw_unlock(&r->ns_set->lock);
433}
434
435/** new rrset containing CNAME override, does not yet contain a dname */
436static struct ub_packed_rrset_key*
437new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
438{
439	struct ub_packed_rrset_key* rrset;
440	struct packed_rrset_data* pd;
441	uint16_t rdlength = htons(ctlen);
442	rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
443		sizeof(*rrset));
444	if(!rrset) {
445		log_err("out of memory");
446		return NULL;
447	}
448	rrset->entry.key = rrset;
449	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
450	if(!pd) {
451		log_err("out of memory");
452		return NULL;
453	}
454	pd->trust = rrset_trust_prim_noglue;
455	pd->security = sec_status_insecure;
456
457	pd->count = 1;
458	pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len));
459	pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl));
460	pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data));
461	if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
462		log_err("out of memory");
463		return NULL;
464	}
465	pd->rr_len[0] = ctlen+2;
466	pd->rr_ttl[0] = 3600;
467	pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen);
468	if(!pd->rr_data[0]) {
469		log_err("out of memory");
470		return NULL;
471	}
472	memmove(pd->rr_data[0], &rdlength, 2);
473	memmove(pd->rr_data[0]+2, ct, ctlen);
474
475	rrset->entry.data = pd;
476	rrset->rk.type = htons(LDNS_RR_TYPE_CNAME);
477	rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN);
478	return rrset;
479}
480
481/** delete the cname override */
482static void
483delete_cname_override(struct rpz* r)
484{
485	if(r->cname_override) {
486		/* The cname override is what is allocated in the region. */
487		regional_free_all(r->region);
488		r->cname_override = NULL;
489	}
490}
491
492/** Apply rpz config elements to the rpz structure, false on failure. */
493static int
494rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
495{
496	if(p->rpz_taglist && p->rpz_taglistlen) {
497		r->taglistlen = p->rpz_taglistlen;
498		r->taglist = memdup(p->rpz_taglist, r->taglistlen);
499		if(!r->taglist) {
500			log_err("malloc failure on RPZ taglist alloc");
501			return 0;
502		}
503	}
504
505	if(p->rpz_action_override) {
506		r->action_override = rpz_config_to_action(p->rpz_action_override);
507	}
508	else
509		r->action_override = RPZ_NO_OVERRIDE_ACTION;
510
511	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
512		uint8_t nm[LDNS_MAX_DOMAINLEN+1];
513		size_t nmlen = sizeof(nm);
514
515		if(!p->rpz_cname) {
516			log_err("rpz: override with cname action found, but no "
517				"rpz-cname-override configured");
518			return 0;
519		}
520
521		if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
522			log_err("rpz: cannot parse cname override: %s",
523				p->rpz_cname);
524			return 0;
525		}
526		r->cname_override = new_cname_override(r->region, nm, nmlen);
527		if(!r->cname_override) {
528			return 0;
529		}
530	}
531	r->log = p->rpz_log;
532	r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
533	if(p->rpz_log_name) {
534		if(!(r->log_name = strdup(p->rpz_log_name))) {
535			log_err("malloc failure on RPZ log_name strdup");
536			return 0;
537		}
538	}
539	return 1;
540}
541
542struct rpz*
543rpz_create(struct config_auth* p)
544{
545	struct rpz* r = calloc(1, sizeof(*r));
546	if(!r)
547		goto err;
548
549	r->region = regional_create_custom(sizeof(struct regional));
550	if(!r->region) {
551		goto err;
552	}
553
554	if(!(r->local_zones = local_zones_create())){
555		goto err;
556	}
557
558	r->nsdname_zones = local_zones_create();
559	if(r->local_zones == NULL){
560		goto err;
561	}
562
563	if(!(r->respip_set = respip_set_create())) {
564		goto err;
565	}
566
567	r->client_set = rpz_clientip_synthesized_set_create();
568	if(r->client_set == NULL) {
569		goto err;
570	}
571
572	r->ns_set = rpz_clientip_synthesized_set_create();
573	if(r->ns_set == NULL) {
574		goto err;
575	}
576
577	if(!rpz_apply_cfg_elements(r, p))
578		goto err;
579	return r;
580err:
581	if(r) {
582		if(r->local_zones)
583			local_zones_delete(r->local_zones);
584		if(r->nsdname_zones)
585			local_zones_delete(r->nsdname_zones);
586		if(r->respip_set)
587			respip_set_delete(r->respip_set);
588		if(r->client_set != NULL)
589			rpz_clientip_synthesized_set_delete(r->client_set);
590		if(r->ns_set != NULL)
591			rpz_clientip_synthesized_set_delete(r->ns_set);
592		if(r->taglist)
593			free(r->taglist);
594		if(r->region)
595			regional_destroy(r->region);
596		free(r);
597	}
598	return NULL;
599}
600
601int
602rpz_config(struct rpz* r, struct config_auth* p)
603{
604	/* If the zonefile changes, it is read later, after which
605	 * rpz_clear and rpz_finish_config is called. */
606
607	/* free taglist, if any */
608	if(r->taglist) {
609		free(r->taglist);
610		r->taglist = NULL;
611		r->taglistlen = 0;
612	}
613
614	/* free logname, if any */
615	if(r->log_name) {
616		free(r->log_name);
617		r->log_name = NULL;
618	}
619
620	delete_cname_override(r);
621
622	if(!rpz_apply_cfg_elements(r, p))
623		return 0;
624	return 1;
625}
626
627/**
628 * Remove RPZ zone name from dname
629 * Copy dname to newdname, without the originlen number of trailing bytes
630 */
631static size_t
632strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
633	uint8_t* newdname, size_t maxnewdnamelen)
634{
635	size_t newdnamelen;
636	if(dnamelen < originlen)
637		return 0;
638	newdnamelen = dnamelen - originlen;
639	if(newdnamelen+1 > maxnewdnamelen)
640		return 0;
641	memmove(newdname, dname, newdnamelen);
642	newdname[newdnamelen] = 0;
643	return newdnamelen + 1;	/* + 1 for root label */
644}
645
646static void
647rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
648	size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass,
649	uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
650{
651	struct local_zone* z;
652	enum localzone_type tp = local_zone_always_transparent;
653	int dnamelabs = dname_count_labels(dname);
654	int newzone = 0;
655
656	if(a == RPZ_INVALID_ACTION) {
657		char str[255+1];
658		if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
659			rrtype == LDNS_RR_TYPE_DNAME ||
660			rrtype == LDNS_RR_TYPE_DNSKEY ||
661			rrtype == LDNS_RR_TYPE_RRSIG ||
662			rrtype == LDNS_RR_TYPE_NSEC ||
663			rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
664			rrtype == LDNS_RR_TYPE_NSEC3 ||
665			rrtype == LDNS_RR_TYPE_DS) {
666			free(dname);
667			return; /* no need to log these types as unsupported */
668		}
669		dname_str(dname, str);
670		verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s",
671			str, rpz_action_to_string(a));
672		free(dname);
673		return;
674	}
675
676	lock_rw_wrlock(&lz->lock);
677	/* exact match */
678	z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN);
679	if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) {
680		char* rrstr = sldns_wire2str_rr(rr, rr_len);
681		if(rrstr == NULL) {
682			log_err("malloc error while inserting rpz nsdname trigger");
683			free(dname);
684			lock_rw_unlock(&lz->lock);
685			return;
686		}
687		if(rrstr[0])
688			rrstr[strlen(rrstr)-1]=0; /* remove newline */
689		verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr);
690		free(rrstr);
691		free(dname);
692		lock_rw_unlock(&lz->lock);
693		return;
694	}
695	if(z == NULL) {
696		tp = rpz_action_to_localzone_type(a);
697		z = local_zones_add_zone(lz, dname, dnamelen,
698					 dnamelabs, rrclass, tp);
699		if(z == NULL) {
700			log_warn("rpz: create failed");
701			lock_rw_unlock(&lz->lock);
702			/* dname will be free'd in failed local_zone_create() */
703			return;
704		}
705		newzone = 1;
706	}
707	if(a == RPZ_LOCAL_DATA_ACTION) {
708		char* rrstr = sldns_wire2str_rr(rr, rr_len);
709		if(rrstr == NULL) {
710			log_err("malloc error while inserting rpz nsdname trigger");
711			free(dname);
712			lock_rw_unlock(&lz->lock);
713			return;
714		}
715		lock_rw_wrlock(&z->lock);
716		local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
717				    rrclass, ttl, rdata, rdata_len, rrstr);
718		lock_rw_unlock(&z->lock);
719		free(rrstr);
720	}
721	if(!newzone) {
722		free(dname);
723	}
724	lock_rw_unlock(&lz->lock);
725}
726
727static void
728rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
729{
730	char buf[LDNS_MAX_DOMAINLEN+1];
731	(void)dname_len;
732	dname_str(dname, buf);
733	verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
734}
735
736static void
737rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
738	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
739	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
740{
741	if(a == RPZ_INVALID_ACTION) {
742		verbose(VERB_ALGO, "rpz: skipping invalid action");
743		free(dname);
744		return;
745	}
746
747	rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype,
748				       rrclass, ttl, rdata, rdata_len, rr, rr_len);
749}
750
751static int
752rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen,
753	uint8_t** stripdname, size_t* stripdnamelen)
754{
755	uint8_t* tldstart = get_tld_label(dname, maxdnamelen);
756	uint8_t swap;
757	if(tldstart == NULL) {
758		if(dname == NULL) {
759			*stripdname = NULL;
760			*stripdnamelen = 0;
761			return 0;
762		}
763		*stripdname = memdup(dname, maxdnamelen);
764		if(!*stripdname) {
765			*stripdnamelen = 0;
766			log_err("malloc failure for rpz strip suffix");
767			return 0;
768		}
769		*stripdnamelen = maxdnamelen;
770		return 1;
771	}
772	/* shorten the domain name briefly,
773	 * then we allocate a new name with the correct length */
774	swap = *tldstart;
775	*tldstart = 0;
776	(void)dname_count_size_labels(dname, stripdnamelen);
777	*stripdname = memdup(dname, *stripdnamelen);
778	*tldstart = swap;
779	if(!*stripdname) {
780		*stripdnamelen = 0;
781		log_err("malloc failure for rpz strip suffix");
782		return 0;
783	}
784	return 1;
785}
786
787static void
788rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
789	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
790	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
791{
792	uint8_t* dname_stripped = NULL;
793	size_t dnamelen_stripped = 0;
794
795	rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
796		&dnamelen_stripped);
797	if(a == RPZ_INVALID_ACTION) {
798		verbose(VERB_ALGO, "rpz: skipping invalid action");
799		free(dname_stripped);
800		return;
801	}
802
803	/* dname_stripped is consumed or freed by the insert routine */
804	rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped,
805		dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len,
806		rr, rr_len);
807}
808
809static int
810rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr,
811	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
812	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
813	uint8_t* rr, size_t rr_len)
814{
815	struct resp_addr* node;
816	char* rrstr;
817	enum respip_action respa = rpz_action_to_respip_action(a);
818
819	lock_rw_wrlock(&set->lock);
820	rrstr = sldns_wire2str_rr(rr, rr_len);
821	if(rrstr == NULL) {
822		log_err("malloc error while inserting rpz ipaddr based trigger");
823		lock_rw_unlock(&set->lock);
824		return 0;
825	}
826
827	node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr);
828	if(node == NULL) {
829		lock_rw_unlock(&set->lock);
830		free(rrstr);
831		return 0;
832	}
833
834	lock_rw_wrlock(&node->lock);
835	lock_rw_unlock(&set->lock);
836
837	node->action = respa;
838
839	if(a == RPZ_LOCAL_DATA_ACTION) {
840		respip_enter_rr(set->region, node, rrtype,
841				rrclass, ttl, rdata, rdata_len, rrstr, "");
842	}
843
844	lock_rw_unlock(&node->lock);
845	free(rrstr);
846	return 1;
847}
848
849static inline struct clientip_synthesized_rr*
850rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set,
851	struct sockaddr_storage* addr, socklen_t addrlen, int net)
852{
853	int insert_ok;
854	struct clientip_synthesized_rr* node =
855		(struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
856								addr, addrlen, net);
857
858	if(node != NULL) { return node; }
859
860	/* node does not yet exist => allocate one */
861	node = regional_alloc_zero(set->region, sizeof(*node));
862	if(node == NULL) {
863		log_err("out of memory");
864		return NULL;
865	}
866
867	lock_rw_init(&node->lock);
868	node->action = RPZ_INVALID_ACTION;
869	insert_ok = addr_tree_insert(&set->entries, &node->node,
870				     addr, addrlen, net);
871	if (!insert_ok) {
872		log_warn("rpz: unexpected: unable to insert clientip address node");
873		/* we can not free the just allocated node.
874		 * theoretically a memleak */
875		return NULL;
876	}
877
878	return node;
879}
880
881static void
882rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
883	char* rrstr = sldns_wire2str_rr(rr, rr_len);
884	if(rrstr == NULL) {
885		log_err("malloc error while inserting rpz clientip based record");
886		return;
887	}
888	log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr);
889	free(rrstr);
890}
891
892/* from localzone.c; difference is we don't have a dname */
893static struct local_rrset*
894rpz_clientip_new_rrset(struct regional* region,
895	struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
896{
897	struct packed_rrset_data* pd;
898	struct local_rrset* rrset = (struct local_rrset*)
899		regional_alloc_zero(region, sizeof(*rrset));
900	if(rrset == NULL) {
901		log_err("out of memory");
902		return NULL;
903	}
904	rrset->next = raddr->data;
905	raddr->data = rrset;
906	rrset->rrset = (struct ub_packed_rrset_key*)
907		regional_alloc_zero(region, sizeof(*rrset->rrset));
908	if(rrset->rrset == NULL) {
909		log_err("out of memory");
910		return NULL;
911	}
912	rrset->rrset->entry.key = rrset->rrset;
913	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
914	if(pd == NULL) {
915		log_err("out of memory");
916		return NULL;
917	}
918	pd->trust = rrset_trust_prim_noglue;
919	pd->security = sec_status_insecure;
920	rrset->rrset->entry.data = pd;
921	rrset->rrset->rk.type = htons(rrtype);
922	rrset->rrset->rk.rrset_class = htons(rrclass);
923	rrset->rrset->rk.dname = regional_alloc_zero(region, 1);
924	if(rrset->rrset->rk.dname == NULL) {
925		log_err("out of memory");
926		return NULL;
927	}
928	rrset->rrset->rk.dname_len = 1;
929	return rrset;
930}
931
932static int
933rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr,
934	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
935	size_t rdata_len)
936{
937	struct local_rrset* rrset;
938	if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) {
939		log_err("CNAME response-ip data can not co-exist with other "
940			"client-ip data");
941		return 0;
942	}
943
944	rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
945	if(raddr->data == NULL) {
946		return 0;
947	}
948
949	return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
950}
951
952static int
953rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr,
954	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
955	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
956	uint8_t* rr, size_t rr_len)
957{
958	struct clientip_synthesized_rr* node;
959
960	lock_rw_wrlock(&set->lock);
961
962	node = rpz_clientip_ensure_entry(set, addr, addrlen, net);
963	if(node == NULL) {
964		lock_rw_unlock(&set->lock);
965		rpz_report_rrset_error("client ip address", rr, rr_len);
966		return 0;
967	}
968
969	lock_rw_wrlock(&node->lock);
970	lock_rw_unlock(&set->lock);
971
972	node->action = a;
973	if(a == RPZ_LOCAL_DATA_ACTION) {
974		if(!rpz_clientip_enter_rr(set->region, node, rrtype,
975			rrclass, ttl, rdata, rdata_len)) {
976			verbose(VERB_ALGO, "rpz: unable to insert clientip rr");
977			lock_rw_unlock(&node->lock);
978			return 0;
979		}
980
981	}
982
983	lock_rw_unlock(&node->lock);
984
985	return 1;
986}
987
988static int
989rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
990	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
991	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
992{
993	struct sockaddr_storage addr;
994	socklen_t addrlen;
995	int net, af;
996
997	if(a == RPZ_INVALID_ACTION) {
998		return 0;
999	}
1000
1001	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1002		verbose(VERB_ALGO, "rpz: unable to parse client ip");
1003		return 0;
1004	}
1005
1006	return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net,
1007			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1008}
1009
1010static int
1011rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1012	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1013	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1014{
1015	struct sockaddr_storage addr;
1016	socklen_t addrlen;
1017	int net, af;
1018
1019	if(a == RPZ_INVALID_ACTION) {
1020		return 0;
1021	}
1022
1023	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1024		verbose(VERB_ALGO, "rpz: unable to parse ns ip");
1025		return 0;
1026	}
1027
1028	return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net,
1029			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1030}
1031
1032/** Insert RR into RPZ's respip_set */
1033static int
1034rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1035	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
1036	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
1037{
1038	struct sockaddr_storage addr;
1039	socklen_t addrlen;
1040	int net, af;
1041
1042	if(a == RPZ_INVALID_ACTION) {
1043		return 0;
1044	}
1045
1046	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
1047		verbose(VERB_ALGO, "rpz: unable to parse response ip");
1048		return 0;
1049	}
1050
1051	if(a == RPZ_INVALID_ACTION ||
1052		rpz_action_to_respip_action(a) == respip_invalid) {
1053		char str[255+1];
1054		dname_str(dname, str);
1055		verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
1056			str, rpz_action_to_string(a));
1057		return 0;
1058	}
1059
1060	return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net,
1061			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1062}
1063
1064int
1065rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1066	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
1067	uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
1068{
1069	size_t policydnamelen;
1070	/* name is free'd in local_zone delete */
1071	enum rpz_trigger t;
1072	enum rpz_action a;
1073	uint8_t* policydname;
1074
1075	if(rpz_type_ignored(rr_type)) {
1076		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1077		return 1;
1078	}
1079	if(!dname_subdomain_c(dname, azname)) {
1080		char* dname_str = sldns_wire2str_dname(dname, dnamelen);
1081		char* azname_str = sldns_wire2str_dname(azname, aznamelen);
1082		if(dname_str && azname_str) {
1083			log_err("rpz: name of record (%s) to insert into RPZ is not a "
1084				"subdomain of the configured name of the RPZ zone (%s)",
1085				dname_str, azname_str);
1086		} else {
1087			log_err("rpz: name of record to insert into RPZ is not a "
1088				"subdomain of the configured name of the RPZ zone");
1089		}
1090		free(dname_str);
1091		free(azname_str);
1092		return 0;
1093	}
1094
1095	log_assert(dnamelen >= aznamelen);
1096	if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
1097		log_err("malloc error while inserting RPZ RR");
1098		return 0;
1099	}
1100
1101	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1102	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1103		policydname, (dnamelen-aznamelen)+1))) {
1104		free(policydname);
1105		return 0;
1106	}
1107	t = rpz_dname_to_trigger(policydname, policydnamelen);
1108	if(t == RPZ_INVALID_TRIGGER) {
1109		free(policydname);
1110		verbose(VERB_ALGO, "rpz: skipping invalid trigger");
1111		return 1;
1112	}
1113	if(t == RPZ_QNAME_TRIGGER) {
1114		/* policydname will be consumed, no free */
1115		rpz_insert_qname_trigger(r, policydname, policydnamelen,
1116			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1117			rr_len);
1118	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1119		rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
1120			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1121			rr_len);
1122		free(policydname);
1123	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1124		rpz_insert_clientip_trigger(r, policydname, policydnamelen,
1125			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1126			rr_len);
1127		free(policydname);
1128	} else if(t == RPZ_NSIP_TRIGGER) {
1129		rpz_insert_nsip_trigger(r, policydname, policydnamelen,
1130			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1131			rr_len);
1132		free(policydname);
1133	} else if(t == RPZ_NSDNAME_TRIGGER) {
1134		rpz_insert_nsdname_trigger(r, policydname, policydnamelen,
1135			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1136			rr_len);
1137		free(policydname);
1138	} else {
1139		free(policydname);
1140		verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s",
1141			rpz_trigger_to_string(t));
1142	}
1143	return 1;
1144}
1145
1146/**
1147 * Find RPZ local-zone by qname.
1148 * @param zones: local-zone tree
1149 * @param qname: qname
1150 * @param qname_len: length of qname
1151 * @param qclass: qclass
1152 * @param only_exact: if 1 only exact (non wildcard) matches are returned
1153 * @param wr: get write lock for local-zone if 1, read lock if 0
1154 * @param zones_keep_lock: if set do not release the r->local_zones lock, this
1155 * 	  makes the caller of this function responsible for releasing the lock.
1156 * @return: NULL or local-zone holding rd or wr lock
1157 */
1158static struct local_zone*
1159rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass,
1160	int only_exact, int wr, int zones_keep_lock)
1161{
1162	uint8_t* ce;
1163	size_t ce_len;
1164	int ce_labs;
1165	uint8_t wc[LDNS_MAX_DOMAINLEN+1];
1166	int exact;
1167	struct local_zone* z = NULL;
1168
1169	if(wr) {
1170		lock_rw_wrlock(&zones->lock);
1171	} else {
1172		lock_rw_rdlock(&zones->lock);
1173	}
1174	z = local_zones_find_le(zones, qname, qname_len,
1175		dname_count_labels(qname),
1176		LDNS_RR_CLASS_IN, &exact);
1177	if(!z || (only_exact && !exact)) {
1178		if(!zones_keep_lock) {
1179			lock_rw_unlock(&zones->lock);
1180		}
1181		return NULL;
1182	}
1183	if(wr) {
1184		lock_rw_wrlock(&z->lock);
1185	} else {
1186		lock_rw_rdlock(&z->lock);
1187	}
1188	if(!zones_keep_lock) {
1189		lock_rw_unlock(&zones->lock);
1190	}
1191
1192	if(exact)
1193		return z;
1194
1195	/* No exact match found, lookup wildcard. closest encloser must
1196	 * be the shared parent between the qname and the best local
1197	 * zone match, append '*' to that and do another lookup. */
1198
1199	ce = dname_get_shared_topdomain(z->name, qname);
1200	if(!ce /* should not happen */) {
1201		lock_rw_unlock(&z->lock);
1202		if(zones_keep_lock) {
1203			lock_rw_unlock(&zones->lock);
1204		}
1205		return NULL;
1206	}
1207	ce_labs = dname_count_size_labels(ce, &ce_len);
1208	if(ce_len+2 > sizeof(wc)) {
1209		lock_rw_unlock(&z->lock);
1210		if(zones_keep_lock) {
1211			lock_rw_unlock(&zones->lock);
1212		}
1213		return NULL;
1214	}
1215	wc[0] = 1; /* length of wildcard label */
1216	wc[1] = (uint8_t)'*'; /* wildcard label */
1217	memmove(wc+2, ce, ce_len);
1218	lock_rw_unlock(&z->lock);
1219
1220	if(!zones_keep_lock) {
1221		if(wr) {
1222			lock_rw_wrlock(&zones->lock);
1223		} else {
1224			lock_rw_rdlock(&zones->lock);
1225		}
1226	}
1227	z = local_zones_find_le(zones, wc,
1228		ce_len+2, ce_labs+1, qclass, &exact);
1229	if(!z || !exact) {
1230		lock_rw_unlock(&zones->lock);
1231		return NULL;
1232	}
1233	if(wr) {
1234		lock_rw_wrlock(&z->lock);
1235	} else {
1236		lock_rw_rdlock(&z->lock);
1237	}
1238	if(!zones_keep_lock) {
1239		lock_rw_unlock(&zones->lock);
1240	}
1241	return z;
1242}
1243
1244/** Find entry for RR type in the list of rrsets for the clientip. */
1245static struct local_rrset*
1246rpz_find_synthesized_rrset(uint16_t qtype,
1247	struct clientip_synthesized_rr* data, int alias_ok)
1248{
1249	struct local_rrset* cursor = data->data, *cname = NULL;
1250	while( cursor != NULL) {
1251		struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
1252		if(htons(qtype) == packed_rrset->type) {
1253			return cursor;
1254		}
1255		if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
1256			cname = cursor;
1257		cursor = cursor->next;
1258	}
1259	if(alias_ok)
1260		return cname;
1261	return NULL;
1262}
1263
1264/**
1265 * Remove RR from RPZ's local-data
1266 * @param z: local-zone for RPZ, holding write lock
1267 * @param policydname: dname of RR to remove
1268 * @param policydnamelen: length of policydname
1269 * @param rr_type: RR type of RR to remove
1270 * @param rdata: rdata of RR to remove
1271 * @param rdatalen: length of rdata
1272 * @return: 1 if zone must be removed after RR deletion
1273 */
1274static int
1275rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
1276	size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
1277	size_t rdatalen)
1278{
1279	struct local_data* ld;
1280	struct packed_rrset_data* d;
1281	size_t index;
1282	ld = local_zone_find_data(z, policydname, policydnamelen,
1283		dname_count_labels(policydname));
1284	if(ld) {
1285		struct local_rrset* prev=NULL, *p=ld->rrsets;
1286		while(p && ntohs(p->rrset->rk.type) != rr_type) {
1287			prev = p;
1288			p = p->next;
1289		}
1290		if(!p)
1291			return 0;
1292		d = (struct packed_rrset_data*)p->rrset->entry.data;
1293		if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1294			if(d->count == 1) {
1295				/* no memory recycling for zone deletions ... */
1296				if(prev) prev->next = p->next;
1297				else ld->rrsets = p->next;
1298			}
1299			if(d->count > 1) {
1300				if(!local_rrset_remove_rr(d, index))
1301					return 0;
1302			}
1303		}
1304	}
1305	if(ld && ld->rrsets)
1306		return 0;
1307	return 1;
1308}
1309
1310/**
1311 * Remove RR from RPZ's respip set
1312 * @param raddr: respip node
1313 * @param rr_type: RR type of RR to remove
1314 * @param rdata: rdata of RR to remove
1315 * @param rdatalen: length of rdata
1316 * @return: 1 if zone must be removed after RR deletion
1317 */
1318static int
1319rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
1320	size_t rdatalen)
1321{
1322	size_t index;
1323	struct packed_rrset_data* d;
1324	if(!raddr->data)
1325		return 1;
1326	d = raddr->data->entry.data;
1327	if(ntohs(raddr->data->rk.type) != rr_type) {
1328		return 0;
1329	}
1330	if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1331		if(d->count == 1) {
1332			/* regional alloc'd */
1333			raddr->data->entry.data = NULL;
1334			raddr->data = NULL;
1335			return 1;
1336		}
1337		if(d->count > 1) {
1338			if(!local_rrset_remove_rr(d, index))
1339				return 0;
1340		}
1341	}
1342	return 0;
1343
1344}
1345
1346/** Remove RR from rpz localzones structure */
1347static void
1348rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
1349	size_t dnamelen, enum rpz_action a, uint16_t rr_type,
1350	uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
1351{
1352	struct local_zone* z;
1353	int delete_zone = 1;
1354	z = rpz_find_zone(zones, dname, dnamelen, rr_class,
1355		1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
1356	if(!z) {
1357		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1358			"RPZ domain not found");
1359		return;
1360	}
1361	if(a == RPZ_LOCAL_DATA_ACTION)
1362		delete_zone = rpz_data_delete_rr(z, dname,
1363			dnamelen, rr_type, rdatawl, rdatalen);
1364	else if(a != localzone_type_to_rpz_action(z->type)) {
1365		lock_rw_unlock(&z->lock);
1366		lock_rw_unlock(&zones->lock);
1367		return;
1368	}
1369	lock_rw_unlock(&z->lock);
1370	if(delete_zone) {
1371		local_zones_del_zone(zones, z);
1372	}
1373	lock_rw_unlock(&zones->lock);
1374}
1375
1376/** Remove RR from RPZ's local-zone */
1377static void
1378rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1379	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1380	uint8_t* rdatawl, size_t rdatalen)
1381{
1382	rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
1383		a, rr_type, rr_class, rdatawl, rdatalen);
1384}
1385
1386static void
1387rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1388	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1389{
1390	struct resp_addr* node;
1391	struct sockaddr_storage addr;
1392	socklen_t addrlen;
1393	int net, af;
1394	int delete_respip = 1;
1395
1396	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1397		return;
1398
1399	lock_rw_wrlock(&r->respip_set->lock);
1400	if(!(node = (struct resp_addr*)addr_tree_find(
1401		&r->respip_set->ip_tree, &addr, addrlen, net))) {
1402		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1403			"RPZ domain not found");
1404		lock_rw_unlock(&r->respip_set->lock);
1405		return;
1406	}
1407
1408	lock_rw_wrlock(&node->lock);
1409	if(a == RPZ_LOCAL_DATA_ACTION) {
1410		/* remove RR, signal whether RR can be removed */
1411		delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
1412			rdatalen);
1413	}
1414	lock_rw_unlock(&node->lock);
1415	if(delete_respip)
1416		respip_sockaddr_delete(r->respip_set, node);
1417	lock_rw_unlock(&r->respip_set->lock);
1418}
1419
1420/** find and remove type from list of local_rrset entries*/
1421static void
1422del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
1423{
1424	struct local_rrset* prev=NULL, *p=*list_head;
1425	while(p && ntohs(p->rrset->rk.type) != dtype) {
1426		prev = p;
1427		p = p->next;
1428	}
1429	if(!p)
1430		return; /* rrset type not found */
1431	/* unlink it */
1432	if(prev) prev->next = p->next;
1433	else *list_head = p->next;
1434	/* no memory recycling for zone deletions ... */
1435}
1436
1437/** Delete client-ip trigger RR from its RRset and perhaps also the rrset
1438 * from the linked list. Returns if the local data is empty and the node can
1439 * be deleted too, or not. */
1440static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
1441	uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1442{
1443	struct local_rrset* rrset;
1444	struct packed_rrset_data* d;
1445	size_t index;
1446	rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
1447	if(rrset == NULL)
1448		return 0; /* type not found, ignore */
1449	d = (struct packed_rrset_data*)rrset->rrset->entry.data;
1450	if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
1451		return 0; /* RR not found, ignore */
1452	if(d->count == 1) {
1453		/* regional alloc'd */
1454		/* delete the type entry from the list */
1455		del_local_rrset_from_list(&node->data, rr_type);
1456		/* if the list is empty, the node can be removed too */
1457		if(node->data == NULL)
1458			return 1;
1459	} else if (d->count > 1) {
1460		if(!local_rrset_remove_rr(d, index))
1461			return 0;
1462	}
1463	return 0;
1464}
1465
1466/** remove trigger RR from clientip_syntheized set tree. */
1467static void
1468rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
1469	struct sockaddr_storage* addr, socklen_t addrlen, int net,
1470	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1471{
1472	struct clientip_synthesized_rr* node;
1473	int delete_node = 1;
1474
1475	lock_rw_wrlock(&set->lock);
1476	node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
1477		addr, addrlen, net);
1478	if(node == NULL) {
1479		/* netblock not found */
1480		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1481			"RPZ address, netblock not found");
1482		lock_rw_unlock(&set->lock);
1483		return;
1484	}
1485	lock_rw_wrlock(&node->lock);
1486	if(a == RPZ_LOCAL_DATA_ACTION) {
1487		/* remove RR, signal whether entry can be removed */
1488		delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
1489			rdatalen);
1490	} else if(a != node->action) {
1491		/* ignore the RR with different action specification */
1492		delete_node = 0;
1493	}
1494	if(delete_node) {
1495		rbtree_delete(&set->entries, node->node.node.key);
1496	}
1497	lock_rw_unlock(&set->lock);
1498	lock_rw_unlock(&node->lock);
1499	if(delete_node) {
1500		lock_rw_destroy(&node->lock);
1501	}
1502}
1503
1504/** Remove clientip trigger RR from RPZ. */
1505static void
1506rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1507	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1508{
1509	struct sockaddr_storage addr;
1510	socklen_t addrlen;
1511	int net, af;
1512	if(a == RPZ_INVALID_ACTION)
1513		return;
1514	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1515		return;
1516	rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
1517		a, rr_type, rdatawl, rdatalen);
1518}
1519
1520/** Remove nsip trigger RR from RPZ. */
1521static void
1522rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1523	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1524{
1525	struct sockaddr_storage addr;
1526	socklen_t addrlen;
1527	int net, af;
1528	if(a == RPZ_INVALID_ACTION)
1529		return;
1530	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1531		return;
1532	rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
1533		a, rr_type, rdatawl, rdatalen);
1534}
1535
1536/** Remove nsdname trigger RR from RPZ. */
1537static void
1538rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1539	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1540	uint8_t* rdatawl, size_t rdatalen)
1541{
1542	uint8_t* dname_stripped = NULL;
1543	size_t dnamelen_stripped = 0;
1544	if(a == RPZ_INVALID_ACTION)
1545		return;
1546	if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
1547		&dnamelen_stripped))
1548		return;
1549	rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
1550		dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
1551	free(dname_stripped);
1552}
1553
1554void
1555rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1556	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
1557	size_t rdatalen)
1558{
1559	size_t policydnamelen;
1560	enum rpz_trigger t;
1561	enum rpz_action a;
1562	uint8_t* policydname;
1563
1564	if(rpz_type_ignored(rr_type)) {
1565		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1566		return;
1567	}
1568	if(!dname_subdomain_c(dname, azname)) {
1569		/* not subdomain of the RPZ zone. */
1570		return;
1571	}
1572
1573	if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
1574		return;
1575
1576	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1577	if(a == RPZ_INVALID_ACTION) {
1578		free(policydname);
1579		return;
1580	}
1581	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1582		policydname, LDNS_MAX_DOMAINLEN + 1))) {
1583		free(policydname);
1584		return;
1585	}
1586	t = rpz_dname_to_trigger(policydname, policydnamelen);
1587	if(t == RPZ_INVALID_TRIGGER) {
1588		/* skipping invalid trigger */
1589		free(policydname);
1590		return;
1591	}
1592	if(t == RPZ_QNAME_TRIGGER) {
1593		rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
1594			rr_type, rr_class, rdatawl, rdatalen);
1595	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1596		rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
1597			a, rr_type, rdatawl, rdatalen);
1598	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1599		rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
1600			rr_type, rdatawl, rdatalen);
1601	} else if(t == RPZ_NSIP_TRIGGER) {
1602		rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
1603			rr_type, rdatawl, rdatalen);
1604	} else if(t == RPZ_NSDNAME_TRIGGER) {
1605		rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
1606			rr_type, rr_class, rdatawl, rdatalen);
1607	}
1608	/* else it was an unsupported trigger, also skipped. */
1609	free(policydname);
1610}
1611
1612/** print log information for an applied RPZ policy. Based on local-zone's
1613 * lz_inform_print().
1614 * The repinfo contains the reply address. If it is NULL, the module
1615 * state is used to report the first IP address (if any).
1616 * The dname is used, for the applied rpz, if NULL, addrnode is used.
1617 */
1618static void
1619log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
1620	enum rpz_action a, struct query_info* qinfo,
1621	struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
1622{
1623	char ip[128], txt[512], portstr[32];
1624	char dnamestr[LDNS_MAX_DOMAINLEN+1];
1625	uint16_t port = 0;
1626	if(dname) {
1627		dname_str(dname, dnamestr);
1628	} else if(addrnode) {
1629		char addrbuf[128];
1630		addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf));
1631		snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net);
1632	} else {
1633		dnamestr[0]=0;
1634	}
1635	if(repinfo) {
1636		addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
1637		port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
1638	} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
1639		addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
1640			ms->mesh_info->reply_list->query_reply.client_addrlen,
1641			ip, sizeof(ip));
1642		port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
1643	} else {
1644		ip[0]=0;
1645		port = 0;
1646	}
1647	snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port);
1648	snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s",
1649		(log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""),
1650		(strcmp(trigger,"qname")==0?"":trigger),
1651		(strcmp(trigger,"qname")==0?"":" "),
1652		dnamestr, rpz_action_to_string(a),
1653		(ip[0]?ip:""), (ip[0]?portstr:""));
1654	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1655}
1656
1657static struct clientip_synthesized_rr*
1658rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set,
1659	struct sockaddr_storage* addr, socklen_t addrlen, char* triggername)
1660{
1661	struct clientip_synthesized_rr* raddr = NULL;
1662	enum rpz_action action = RPZ_INVALID_ACTION;
1663
1664	lock_rw_rdlock(&set->lock);
1665
1666	raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries,
1667			addr, addrlen);
1668	if(raddr != NULL) {
1669		lock_rw_rdlock(&raddr->lock);
1670		action = raddr->action;
1671		if(verbosity >= VERB_ALGO) {
1672			char ip[256], net[256];
1673			addr_to_str(addr, addrlen, ip, sizeof(ip));
1674			addr_to_str(&raddr->node.addr, raddr->node.addrlen,
1675				net, sizeof(net));
1676			verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s",
1677				triggername, net, raddr->node.net, ip, rpz_action_to_string(action));
1678		}
1679	}
1680	lock_rw_unlock(&set->lock);
1681
1682	return raddr;
1683}
1684
1685static inline
1686struct clientip_synthesized_rr*
1687rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo,
1688	struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
1689	struct ub_server_stats* stats,
1690	/* output parameters */
1691	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
1692{
1693	struct clientip_synthesized_rr* node = NULL;
1694	struct auth_zone* a = NULL;
1695	struct rpz* r = NULL;
1696	struct local_zone* z = NULL;
1697
1698	lock_rw_rdlock(&az->rpz_lock);
1699
1700	for(a = az->rpz_first; a; a = a->rpz_az_next) {
1701		lock_rw_rdlock(&a->lock);
1702		r = a->rpz;
1703		if(r->disabled) {
1704			lock_rw_unlock(&a->lock);
1705			continue;
1706		}
1707		if(r->taglist && !taglist_intersect(r->taglist,
1708					r->taglistlen, taglist, taglen)) {
1709			lock_rw_unlock(&a->lock);
1710			continue;
1711		}
1712		z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
1713			qinfo->qclass, 0, 0, 0);
1714		node = rpz_ipbased_trigger_lookup(r->client_set,
1715			&repinfo->client_addr, repinfo->client_addrlen,
1716			"clientip");
1717		if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
1718			if(r->log)
1719				log_rpz_apply((node?"clientip":"qname"),
1720					(z?z->name:NULL),
1721					(node?&node->node:NULL),
1722					r->action_override,
1723					qinfo, repinfo, NULL, r->log_name);
1724			stats->rpz_action[r->action_override]++;
1725			if(z != NULL) {
1726				lock_rw_unlock(&z->lock);
1727				z = NULL;
1728			}
1729			if(node != NULL) {
1730				lock_rw_unlock(&node->lock);
1731				node = NULL;
1732			}
1733		}
1734		if(z || node) {
1735			break;
1736		}
1737		/* not found in this auth_zone */
1738		lock_rw_unlock(&a->lock);
1739	}
1740
1741	lock_rw_unlock(&az->rpz_lock);
1742
1743	*r_out = r;
1744	*a_out = a;
1745	*z_out = z;
1746
1747	return node;
1748}
1749
1750static inline int
1751rpz_is_udp_query(struct comm_reply* repinfo) {
1752	return repinfo != NULL
1753			? (repinfo->c != NULL
1754				? repinfo->c->type == comm_udp
1755				: 0)
1756			: 0;
1757}
1758
1759/** encode answer consisting of 1 rrset */
1760static int
1761rpz_local_encode(struct module_env* env, struct query_info* qinfo,
1762	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1763	struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
1764	int rcode, struct ub_packed_rrset_key* soa_rrset)
1765{
1766	struct reply_info rep;
1767	uint16_t udpsize;
1768	struct ub_packed_rrset_key* rrsetlist[3];
1769
1770	memset(&rep, 0, sizeof(rep));
1771	rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1772	rep.qdcount = 1;
1773	rep.rrset_count = ansec;
1774	rep.rrsets = rrsetlist;
1775	if(ansec > 0) {
1776		rep.an_numrrsets = 1;
1777		rep.rrsets[0] = rrset;
1778		rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
1779	}
1780	if(soa_rrset != NULL) {
1781		rep.ar_numrrsets = 1;
1782		rep.rrsets[rep.rrset_count] = soa_rrset;
1783		rep.rrset_count ++;
1784		if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
1785			rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
1786		}
1787	}
1788
1789	udpsize = edns->udp_size;
1790	edns->edns_version = EDNS_ADVERTISED_VERSION;
1791	edns->udp_size = EDNS_ADVERTISED_SIZE;
1792	edns->ext_rcode = 0;
1793	edns->bits &= EDNS_DO;
1794	if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
1795		repinfo, temp, env->now_tv) ||
1796	  !reply_info_answer_encode(qinfo, &rep,
1797		*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
1798		buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
1799		error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1800			*(uint16_t*)sldns_buffer_begin(buf),
1801			sldns_buffer_read_u16_at(buf, 2), edns);
1802	}
1803
1804	return 1;
1805}
1806
1807/** allocate SOA record ubrrsetkey in region */
1808static struct ub_packed_rrset_key*
1809make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
1810	struct regional* temp)
1811{
1812	struct ub_packed_rrset_key csoa;
1813	if(!soa)
1814		return NULL;
1815	memset(&csoa, 0, sizeof(csoa));
1816	csoa.entry.key = &csoa;
1817	csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
1818	csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
1819	csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
1820		| PACKED_RRSET_RPZ;
1821	csoa.rk.dname = auth_zone->name;
1822	csoa.rk.dname_len = auth_zone->namelen;
1823	csoa.entry.hash = rrset_key_hash(&csoa.rk);
1824	csoa.entry.data = soa->data;
1825	return respip_copy_rrset(&csoa, temp);
1826}
1827
1828static void
1829rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
1830	struct module_env* env, struct query_info* qinfo,
1831	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1832	struct regional* temp, struct auth_zone* auth_zone)
1833{
1834	struct local_rrset* rrset;
1835	enum rpz_action action = RPZ_INVALID_ACTION;
1836	struct ub_packed_rrset_key* rp = NULL;
1837	struct ub_packed_rrset_key* rsoa = NULL;
1838	int rcode = LDNS_RCODE_NOERROR|BIT_AA;
1839	int rrset_count = 1;
1840
1841	/* prepare synthesized answer for client */
1842	action = raddr->action;
1843	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) {
1844		verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
1845		return;
1846	}
1847
1848	/* check query type / rr type */
1849	rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
1850	if(rrset == NULL) {
1851		verbose(VERB_ALGO, "rpz: unable to find local-data for query");
1852		rrset_count = 0;
1853		goto nodata;
1854	}
1855
1856	rp = respip_copy_rrset(rrset->rrset, temp);
1857	if(!rp) {
1858		verbose(VERB_ALGO, "rpz: local data action: out of memory");
1859		return;
1860	}
1861
1862	rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
1863	rp->rk.dname = qinfo->qname;
1864	rp->rk.dname_len = qinfo->qname_len;
1865	rp->entry.hash = rrset_key_hash(&rp->rk);
1866nodata:
1867	if(auth_zone) {
1868		struct auth_rrset* soa = NULL;
1869		soa = auth_zone_get_soa_rrset(auth_zone);
1870		if(soa) {
1871			rsoa = make_soa_ubrrset(auth_zone, soa, temp);
1872			if(!rsoa) {
1873				verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
1874				return;
1875			}
1876		}
1877	}
1878
1879	rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
1880		rrset_count, rcode, rsoa);
1881}
1882
1883/** Apply the cname override action, during worker request callback.
1884 * false on failure. */
1885static int
1886rpz_apply_cname_override_action(struct rpz* r,
1887	struct query_info* qinfo, struct regional* temp)
1888{
1889	if(!r)
1890		return 0;
1891	qinfo->local_alias = regional_alloc_zero(temp,
1892		sizeof(struct local_rrset));
1893	if(qinfo->local_alias == NULL)
1894		return 0; /* out of memory */
1895	qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
1896	if(qinfo->local_alias->rrset == NULL) {
1897		qinfo->local_alias = NULL;
1898		return 0; /* out of memory */
1899	}
1900	qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1901	qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1902	return 1;
1903}
1904
1905/** add additional section SOA record to the reply.
1906 * Since this gets fed into the normal iterator answer creation, it
1907 * gets minimal-responses applied to it, that can remove the additional SOA
1908 * again. */
1909static int
1910rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
1911	struct auth_zone* az)
1912{
1913	struct auth_rrset* soa = NULL;
1914	struct ub_packed_rrset_key* rsoa = NULL;
1915	struct ub_packed_rrset_key** prevrrsets;
1916	if(!az) return 1;
1917	soa = auth_zone_get_soa_rrset(az);
1918	if(!soa) return 1;
1919	if(!rep) return 0;
1920	rsoa = make_soa_ubrrset(az, soa, ms->region);
1921	if(!rsoa) return 0;
1922	prevrrsets = rep->rrsets;
1923	rep->rrsets = regional_alloc_zero(ms->region,
1924		sizeof(*rep->rrsets)*(rep->rrset_count+1));
1925	if(!rep->rrsets)
1926		return 0;
1927	if(prevrrsets && rep->rrset_count > 0)
1928		memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
1929	rep->rrset_count++;
1930	rep->ar_numrrsets++;
1931	rep->rrsets[rep->rrset_count-1] = rsoa;
1932	return 1;
1933}
1934
1935static inline struct dns_msg*
1936rpz_dns_msg_new(struct regional* region)
1937{
1938	struct dns_msg* msg =
1939			(struct dns_msg*)regional_alloc(region,
1940							sizeof(struct dns_msg));
1941	if(msg == NULL) { return NULL; }
1942	memset(msg, 0, sizeof(struct dns_msg));
1943
1944	return msg;
1945}
1946
1947static inline struct dns_msg*
1948rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1949	struct query_info* qinfo, struct auth_zone* az)
1950{
1951	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1952	if(msg == NULL) { return msg; }
1953	msg->qinfo = *qinfo;
1954	msg->rep = construct_reply_info_base(ms->region,
1955					     LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1956					     1, /* qd */
1957					     0, /* ttl */
1958					     0, /* prettl */
1959					     0, /* expttl */
1960					     0, /* an */
1961					     0, /* ns */
1962					     0, /* ar */
1963					     0, /* total */
1964					     sec_status_insecure,
1965					     LDNS_EDE_NONE);
1966	if(msg->rep)
1967		msg->rep->authoritative = 1;
1968	if(!rpz_add_soa(msg->rep, ms, az))
1969		return NULL;
1970	return msg;
1971}
1972
1973static inline struct dns_msg*
1974rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
1975	struct query_info* qinfo, struct auth_zone* az)
1976{
1977	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1978	uint16_t flags;
1979	if(msg == NULL) { return msg; }
1980	msg->qinfo = *qinfo;
1981	flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA;
1982	if(r->signal_nxdomain_ra)
1983		flags &= ~BIT_RA;
1984	msg->rep = construct_reply_info_base(ms->region,
1985					     flags,
1986					     1, /* qd */
1987					     0, /* ttl */
1988					     0, /* prettl */
1989					     0, /* expttl */
1990					     0, /* an */
1991					     0, /* ns */
1992					     0, /* ar */
1993					     0, /* total */
1994					     sec_status_insecure,
1995					     LDNS_EDE_NONE);
1996	if(msg->rep)
1997		msg->rep->authoritative = 1;
1998	if(!rpz_add_soa(msg->rep, ms, az))
1999		return NULL;
2000	return msg;
2001}
2002
2003static inline struct dns_msg*
2004rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
2005	struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
2006{
2007	struct dns_msg* msg = NULL;
2008	struct reply_info* new_reply_info;
2009	struct ub_packed_rrset_key* rp;
2010
2011
2012	msg = rpz_dns_msg_new(ms->region);
2013	if(msg == NULL) { return NULL; }
2014
2015	msg->qinfo = *qi;
2016        new_reply_info = construct_reply_info_base(ms->region,
2017                                                   LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2018                                                   1, /* qd */
2019                                                   0, /* ttl */
2020                                                   0, /* prettl */
2021                                                   0, /* expttl */
2022                                                   1, /* an */
2023                                                   0, /* ns */
2024                                                   0, /* ar */
2025                                                   1, /* total */
2026                                                   sec_status_insecure,
2027                                                   LDNS_EDE_NONE);
2028	if(new_reply_info == NULL) {
2029		log_err("out of memory");
2030		return NULL;
2031	}
2032	new_reply_info->authoritative = 1;
2033	rp = respip_copy_rrset(rrset->rrset, ms->region);
2034	if(rp == NULL) {
2035		log_err("out of memory");
2036		return NULL;
2037	}
2038	rp->rk.dname = qi->qname;
2039	rp->rk.dname_len = qi->qname_len;
2040	/* this rrset is from the rpz data, or synthesized.
2041	 * It is not actually from the network, so we flag it with this
2042	 * flags as a fake RRset. If later the cache is used to look up
2043	 * rrsets, then the fake ones are not returned (if you look without
2044	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2045	 * lookups for nameserver targets, it would use the without flag
2046	 * actual data. So that the actual network data and fake data
2047	 * are kept track of separately. */
2048	rp->rk.flags |= PACKED_RRSET_RPZ;
2049	new_reply_info->rrsets[0] = rp;
2050	msg->rep = new_reply_info;
2051	if(!rpz_add_soa(msg->rep, ms, az))
2052		return NULL;
2053	return msg;
2054}
2055
2056static inline struct dns_msg*
2057rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
2058	struct query_info* qi, struct clientip_synthesized_rr* data,
2059	struct auth_zone* az)
2060{
2061	struct local_rrset* rrset;
2062
2063	rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
2064	if(rrset == NULL) {
2065		verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
2066		return NULL;
2067	}
2068
2069	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2070}
2071
2072/* copy'n'paste from localzone.c */
2073static struct local_rrset*
2074local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
2075{
2076	struct local_rrset* p, *cname = NULL;
2077	type = htons(type);
2078	for(p = data->rrsets; p; p = p->next) {
2079		if(p->rrset->rk.type == type)
2080			return p;
2081		if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
2082			cname = p;
2083	}
2084	if(alias_ok)
2085		return cname;
2086	return NULL;
2087}
2088
2089/* based on localzone.c:local_data_answer() */
2090static inline struct dns_msg*
2091rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
2092	struct query_info* qi, struct local_zone* z,
2093	struct matched_delegation_point const* match, struct auth_zone* az)
2094{
2095	struct local_data key;
2096	struct local_data* ld;
2097	struct local_rrset* rrset;
2098
2099	if(match->dname == NULL) { return NULL; }
2100
2101	key.node.key = &key;
2102	key.name = match->dname;
2103	key.namelen = match->dname_len;
2104	key.namelabs = dname_count_labels(match->dname);
2105
2106	rpz_log_dname("nsdname local data", key.name, key.namelen);
2107
2108	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2109	if(ld == NULL) {
2110		verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found");
2111		return NULL;
2112	}
2113
2114	rrset = local_data_find_type(ld, qi->qtype, 1);
2115	if(rrset == NULL) {
2116		verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
2117		return NULL;
2118	}
2119
2120	return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
2121}
2122
2123/* like local_data_answer for qname triggers after a cname */
2124static struct dns_msg*
2125rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
2126	struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
2127{
2128	struct local_data key;
2129	struct local_data* ld;
2130	struct local_rrset* rrset;
2131	key.node.key = &key;
2132	key.name = qinfo->qname;
2133	key.namelen = qinfo->qname_len;
2134	key.namelabs = dname_count_labels(qinfo->qname);
2135	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2136	if(ld == NULL) {
2137		verbose(VERB_ALGO, "rpz: qname: name not found");
2138		return NULL;
2139	}
2140	rrset = local_data_find_type(ld, qinfo->qtype, 1);
2141	if(rrset == NULL) {
2142		verbose(VERB_ALGO, "rpz: qname: type not found");
2143		return NULL;
2144	}
2145	return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
2146}
2147
2148/** Synthesize a CNAME message for RPZ action override */
2149static struct dns_msg*
2150rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
2151	struct query_info* qinfo)
2152{
2153	struct dns_msg* msg = NULL;
2154	struct reply_info* new_reply_info;
2155	struct ub_packed_rrset_key* rp;
2156
2157	msg = rpz_dns_msg_new(ms->region);
2158	if(msg == NULL) { return NULL; }
2159
2160	msg->qinfo = *qinfo;
2161        new_reply_info = construct_reply_info_base(ms->region,
2162                                                   LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
2163                                                   1, /* qd */
2164                                                   0, /* ttl */
2165                                                   0, /* prettl */
2166                                                   0, /* expttl */
2167                                                   1, /* an */
2168                                                   0, /* ns */
2169                                                   0, /* ar */
2170                                                   1, /* total */
2171                                                   sec_status_insecure,
2172                                                   LDNS_EDE_NONE);
2173	if(new_reply_info == NULL) {
2174		log_err("out of memory");
2175		return NULL;
2176	}
2177	new_reply_info->authoritative = 1;
2178
2179	rp = respip_copy_rrset(r->cname_override, ms->region);
2180	if(rp == NULL) {
2181		log_err("out of memory");
2182		return NULL;
2183	}
2184	rp->rk.dname = qinfo->qname;
2185	rp->rk.dname_len = qinfo->qname_len;
2186	/* this rrset is from the rpz data, or synthesized.
2187	 * It is not actually from the network, so we flag it with this
2188	 * flags as a fake RRset. If later the cache is used to look up
2189	 * rrsets, then the fake ones are not returned (if you look without
2190	 * the flag). For like CNAME lookups from the iterator or A, AAAA
2191	 * lookups for nameserver targets, it would use the without flag
2192	 * actual data. So that the actual network data and fake data
2193	 * are kept track of separately. */
2194	rp->rk.flags |= PACKED_RRSET_RPZ;
2195	new_reply_info->rrsets[0] = rp;
2196
2197	msg->rep = new_reply_info;
2198	return msg;
2199}
2200
2201static int
2202rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
2203	struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
2204	struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
2205	struct comm_reply* repinfo, struct ub_server_stats* stats)
2206{
2207	struct local_data* ld = NULL;
2208	int ret = 0;
2209	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
2210		if(!rpz_apply_cname_override_action(r, qinfo, temp))
2211			return 0;
2212		if(r->log) {
2213			log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
2214				      qinfo, repinfo, NULL, r->log_name);
2215		}
2216		stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
2217		return 0;
2218	}
2219
2220	if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
2221		edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
2222		&ld, lzt, -1, NULL, 0, NULL, 0)) {
2223		if(r->log) {
2224			log_rpz_apply("qname", z->name, NULL,
2225				localzone_type_to_rpz_action(lzt), qinfo,
2226				repinfo, NULL, r->log_name);
2227		}
2228		stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2229		return !qinfo->local_alias;
2230	}
2231
2232	ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
2233		0 /* no local data used */, lzt);
2234	if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2235		== LDNS_RCODE_NXDOMAIN)
2236		LDNS_RA_CLR(sldns_buffer_begin(buf));
2237	if(r->log) {
2238		log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
2239			      qinfo, repinfo, NULL, r->log_name);
2240	}
2241	stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2242	return ret;
2243}
2244
2245static struct clientip_synthesized_rr*
2246rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
2247{
2248	struct delegpt_addr* cursor;
2249	struct clientip_synthesized_rr* action = NULL;
2250	if(is->dp == NULL) { return NULL; }
2251	for(cursor = is->dp->target_list;
2252	    cursor != NULL;
2253	    cursor = cursor->next_target) {
2254		if(cursor->bogus) { continue; }
2255		action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr,
2256						    cursor->addrlen, "nsip");
2257		if(action != NULL) { return action; }
2258	}
2259	return NULL;
2260}
2261
2262static struct dns_msg*
2263rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
2264	struct rpz* r, struct clientip_synthesized_rr* raddr,
2265	struct auth_zone* az)
2266{
2267	enum rpz_action action = raddr->action;
2268	struct dns_msg* ret = NULL;
2269
2270	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2271		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2272			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2273		action = r->action_override;
2274	}
2275
2276	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
2277		verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
2278		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2279		goto done;
2280	}
2281
2282	switch(action) {
2283	case RPZ_NXDOMAIN_ACTION:
2284		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2285		break;
2286	case RPZ_NODATA_ACTION:
2287		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2288		break;
2289	case RPZ_TCP_ONLY_ACTION:
2290		/* basically a passthru here but the tcp-only will be
2291		 * honored before the query gets sent. */
2292		ms->tcp_required = 1;
2293		ret = NULL;
2294		break;
2295	case RPZ_DROP_ACTION:
2296		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2297		ms->is_drop = 1;
2298		break;
2299	case RPZ_LOCAL_DATA_ACTION:
2300		ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
2301		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2302		break;
2303	case RPZ_PASSTHRU_ACTION:
2304		ret = NULL;
2305		ms->rpz_passthru = 1;
2306		break;
2307	case RPZ_CNAME_OVERRIDE_ACTION:
2308		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2309		break;
2310	default:
2311		verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2312			rpz_action_to_string(action));
2313		ret = NULL;
2314	}
2315
2316done:
2317	if(r->log)
2318		log_rpz_apply("nsip", NULL, &raddr->node,
2319			action, &ms->qinfo, NULL, ms, r->log_name);
2320	if(ms->env->worker)
2321		ms->env->worker->stats.rpz_action[action]++;
2322	lock_rw_unlock(&raddr->lock);
2323	return ret;
2324}
2325
2326static struct dns_msg*
2327rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
2328	struct rpz* r, struct local_zone* z,
2329	struct matched_delegation_point const* match, struct auth_zone* az)
2330{
2331	struct dns_msg* ret = NULL;
2332	enum rpz_action action = localzone_type_to_rpz_action(z->type);
2333
2334	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2335		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2336			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2337		action = r->action_override;
2338	}
2339
2340	switch(action) {
2341	case RPZ_NXDOMAIN_ACTION:
2342		ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
2343		break;
2344	case RPZ_NODATA_ACTION:
2345		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2346		break;
2347	case RPZ_TCP_ONLY_ACTION:
2348		/* basically a passthru here but the tcp-only will be
2349		 * honored before the query gets sent. */
2350		ms->tcp_required = 1;
2351		ret = NULL;
2352		break;
2353	case RPZ_DROP_ACTION:
2354		ret = rpz_synthesize_nodata(r, ms, qchase, az);
2355		ms->is_drop = 1;
2356		break;
2357	case RPZ_LOCAL_DATA_ACTION:
2358		ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
2359		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
2360		break;
2361	case RPZ_PASSTHRU_ACTION:
2362		ret = NULL;
2363		ms->rpz_passthru = 1;
2364		break;
2365	case RPZ_CNAME_OVERRIDE_ACTION:
2366		ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
2367		break;
2368	default:
2369		verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
2370			rpz_action_to_string(action));
2371		ret = NULL;
2372	}
2373
2374	if(r->log)
2375		log_rpz_apply("nsdname", match->dname, NULL,
2376			action, &ms->qinfo, NULL, ms, r->log_name);
2377	if(ms->env->worker)
2378		ms->env->worker->stats.rpz_action[action]++;
2379	lock_rw_unlock(&z->lock);
2380	return ret;
2381}
2382
2383static struct local_zone*
2384rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
2385	uint16_t qclass,
2386	/* output parameter */
2387	struct matched_delegation_point* match)
2388{
2389	struct delegpt_ns* nameserver;
2390	struct local_zone* z = NULL;
2391
2392	/* the rpz specs match the nameserver names (NS records), not the
2393	 * name of the delegation point itself, to the nsdname triggers */
2394	for(nameserver = dp->nslist;
2395	    nameserver != NULL;
2396	    nameserver = nameserver->next) {
2397		z = rpz_find_zone(zones, nameserver->name, nameserver->namelen,
2398				  qclass, 0, 0, 0);
2399		if(z != NULL) {
2400			match->dname = nameserver->name;
2401			match->dname_len = nameserver->namelen;
2402			if(verbosity >= VERB_ALGO) {
2403				char nm[255+1], zn[255+1];
2404				dname_str(match->dname, nm);
2405				dname_str(z->name, zn);
2406				if(strcmp(nm, zn) != 0)
2407					verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s",
2408						zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2409				else
2410					verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s",
2411						nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2412			}
2413			break;
2414		}
2415	}
2416
2417	return z;
2418}
2419
2420struct dns_msg*
2421rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is)
2422{
2423	struct auth_zones* az;
2424	struct auth_zone* a;
2425	struct clientip_synthesized_rr* raddr = NULL;
2426	struct rpz* r = NULL;
2427	struct local_zone* z = NULL;
2428	struct matched_delegation_point match = {0};
2429
2430	if(ms->rpz_passthru) {
2431		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2432		return NULL;
2433	}
2434
2435	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2436
2437	az = ms->env->auth_zones;
2438
2439	verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
2440
2441	lock_rw_rdlock(&az->rpz_lock);
2442
2443	/* precedence of RPZ works, loosely, like this:
2444	 * CNAMEs in order of the CNAME chain. rpzs in the order they are
2445	 * configured. In an RPZ: first client-IP addr, then QNAME, then
2446	 * response IP, then NSDNAME, then NSIP. Longest match first. Smallest
2447	 * one from a set. */
2448	/* we use the precedence rules for the topics and triggers that
2449	 * are pertinent at this stage of the resolve processing */
2450	for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) {
2451		lock_rw_rdlock(&a->lock);
2452		r = a->rpz;
2453		if(r->disabled) {
2454			lock_rw_unlock(&a->lock);
2455			continue;
2456		}
2457
2458		/* the nsdname has precedence over the nsip triggers */
2459		z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
2460						     is->qchase.qclass, &match);
2461		if(z != NULL) {
2462			lock_rw_unlock(&a->lock);
2463			break;
2464		}
2465
2466		raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
2467		if(raddr != NULL) {
2468			lock_rw_unlock(&a->lock);
2469			break;
2470		}
2471		lock_rw_unlock(&a->lock);
2472	}
2473
2474	lock_rw_unlock(&az->rpz_lock);
2475
2476	if(raddr == NULL && z == NULL)
2477		return NULL;
2478
2479	if(raddr != NULL) {
2480		if(z) {
2481			lock_rw_unlock(&z->lock);
2482		}
2483		return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
2484	}
2485	return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
2486}
2487
2488struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
2489	struct iter_qstate* is)
2490{
2491	struct auth_zones* az;
2492	struct auth_zone* a = NULL;
2493	struct rpz* r = NULL;
2494	struct local_zone* z = NULL;
2495	enum localzone_type lzt;
2496	struct dns_msg* ret = NULL;
2497
2498	if(ms->rpz_passthru) {
2499		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2500		return NULL;
2501	}
2502
2503	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2504	az = ms->env->auth_zones;
2505
2506	lock_rw_rdlock(&az->rpz_lock);
2507
2508	for(a = az->rpz_first; a; a = a->rpz_az_next) {
2509		lock_rw_rdlock(&a->lock);
2510		r = a->rpz;
2511		if(r->disabled) {
2512			lock_rw_unlock(&a->lock);
2513			continue;
2514		}
2515		z = rpz_find_zone(r->local_zones, is->qchase.qname,
2516			is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
2517		if(z && r->action_override == RPZ_DISABLED_ACTION) {
2518			if(r->log)
2519				log_rpz_apply("qname", z->name, NULL,
2520					r->action_override,
2521					&ms->qinfo, NULL, ms, r->log_name);
2522			if(ms->env->worker)
2523				ms->env->worker->stats.rpz_action[r->action_override]++;
2524			lock_rw_unlock(&z->lock);
2525			z = NULL;
2526		}
2527		if(z) {
2528			break;
2529		}
2530		/* not found in this auth_zone */
2531		lock_rw_unlock(&a->lock);
2532	}
2533	lock_rw_unlock(&az->rpz_lock);
2534
2535	if(z == NULL)
2536		return NULL;
2537	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2538		lzt = z->type;
2539	} else {
2540		lzt = rpz_action_to_localzone_type(r->action_override);
2541	}
2542
2543	if(verbosity >= VERB_ALGO) {
2544		char nm[255+1], zn[255+1];
2545		dname_str(is->qchase.qname, nm);
2546		dname_str(z->name, zn);
2547		if(strcmp(zn, nm) != 0)
2548			verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
2549				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2550		else
2551			verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
2552				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2553	}
2554	switch(localzone_type_to_rpz_action(lzt)) {
2555	case RPZ_NXDOMAIN_ACTION:
2556		ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
2557		break;
2558	case RPZ_NODATA_ACTION:
2559		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2560		break;
2561	case RPZ_TCP_ONLY_ACTION:
2562		/* basically a passthru here but the tcp-only will be
2563		 * honored before the query gets sent. */
2564		ms->tcp_required = 1;
2565		ret = NULL;
2566		break;
2567	case RPZ_DROP_ACTION:
2568		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2569		ms->is_drop = 1;
2570		break;
2571	case RPZ_LOCAL_DATA_ACTION:
2572		ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
2573		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
2574		break;
2575	case RPZ_PASSTHRU_ACTION:
2576		ret = NULL;
2577		ms->rpz_passthru = 1;
2578		break;
2579	default:
2580		verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
2581			rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2582		ret = NULL;
2583	}
2584	if(r->log)
2585		log_rpz_apply("qname", (z?z->name:NULL), NULL,
2586			localzone_type_to_rpz_action(lzt),
2587			&is->qchase, NULL, ms, r->log_name);
2588	lock_rw_unlock(&z->lock);
2589	lock_rw_unlock(&a->lock);
2590	return ret;
2591}
2592
2593static int
2594rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
2595	struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo,
2596	uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
2597	sldns_buffer* buf, struct regional* temp,
2598	/* output parameters */
2599	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
2600	int* passthru)
2601{
2602	int ret = 0;
2603	enum rpz_action client_action;
2604	struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone(
2605		az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
2606
2607	client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
2608	if(node != NULL && *r_out &&
2609		(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
2610		client_action = (*r_out)->action_override;
2611	}
2612	if(client_action == RPZ_PASSTHRU_ACTION) {
2613		if(*r_out && (*r_out)->log)
2614			log_rpz_apply(
2615				(node?"clientip":"qname"),
2616				((*z_out)?(*z_out)->name:NULL),
2617				(node?&node->node:NULL),
2618				client_action, qinfo, repinfo, NULL,
2619				(*r_out)->log_name);
2620		*passthru = 1;
2621		ret = 0;
2622		goto done;
2623	}
2624	if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
2625			      client_action != RPZ_PASSTHRU_ACTION)) {
2626		if(client_action == RPZ_PASSTHRU_ACTION
2627			|| client_action == RPZ_INVALID_ACTION
2628			|| (client_action == RPZ_TCP_ONLY_ACTION
2629				&& !rpz_is_udp_query(repinfo))) {
2630			ret = 0;
2631			goto done;
2632		}
2633		stats->rpz_action[client_action]++;
2634		if(client_action == RPZ_LOCAL_DATA_ACTION) {
2635			rpz_apply_clientip_localdata_action(node, env, qinfo,
2636				edns, repinfo, buf, temp, *a_out);
2637			ret = 1;
2638		} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
2639			if(!rpz_apply_cname_override_action(*r_out, qinfo,
2640				temp)) {
2641				ret = 0;
2642				goto done;
2643			}
2644			ret = 0;
2645		} else {
2646			local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
2647				repinfo, buf, temp, 0 /* no local data used */,
2648				rpz_action_to_localzone_type(client_action));
2649			if(*r_out && (*r_out)->signal_nxdomain_ra &&
2650				LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2651				== LDNS_RCODE_NXDOMAIN)
2652				LDNS_RA_CLR(sldns_buffer_begin(buf));
2653			ret = 1;
2654		}
2655		if(*r_out && (*r_out)->log)
2656			log_rpz_apply(
2657				(node?"clientip":"qname"),
2658				((*z_out)?(*z_out)->name:NULL),
2659				(node?&node->node:NULL),
2660				client_action, qinfo, repinfo, NULL,
2661				(*r_out)->log_name);
2662		goto done;
2663	}
2664	ret = -1;
2665done:
2666	if(node != NULL) {
2667		lock_rw_unlock(&node->lock);
2668	}
2669	return ret;
2670}
2671
2672int
2673rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
2674	struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
2675	struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
2676	size_t taglen, struct ub_server_stats* stats, int* passthru)
2677{
2678	struct rpz* r = NULL;
2679	struct auth_zone* a = NULL;
2680	struct local_zone* z = NULL;
2681	int ret;
2682	enum localzone_type lzt;
2683
2684	int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
2685		edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
2686		passthru);
2687	if(clientip_trigger >= 0) {
2688		if(a) {
2689			lock_rw_unlock(&a->lock);
2690		}
2691		if(z) {
2692			lock_rw_unlock(&z->lock);
2693		}
2694		return clientip_trigger;
2695	}
2696
2697	if(z == NULL) {
2698		if(a) {
2699			lock_rw_unlock(&a->lock);
2700		}
2701		return 0;
2702	}
2703
2704	log_assert(r);
2705
2706	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2707		lzt = z->type;
2708	} else {
2709		lzt = rpz_action_to_localzone_type(r->action_override);
2710	}
2711	if(r->action_override == RPZ_PASSTHRU_ACTION ||
2712		lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
2713		*passthru = 1;
2714	}
2715
2716	if(verbosity >= VERB_ALGO) {
2717		char nm[255+1], zn[255+1];
2718		dname_str(qinfo->qname, nm);
2719		dname_str(z->name, zn);
2720		if(strcmp(zn, nm) != 0)
2721			verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s",
2722				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2723		else
2724			verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s",
2725				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2726	}
2727
2728	ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp,
2729					     repinfo, stats);
2730
2731	lock_rw_unlock(&z->lock);
2732	lock_rw_unlock(&a->lock);
2733
2734	return ret;
2735}
2736
2737void rpz_enable(struct rpz* r)
2738{
2739    if(!r)
2740        return;
2741    r->disabled = 0;
2742}
2743
2744void rpz_disable(struct rpz* r)
2745{
2746    if(!r)
2747        return;
2748    r->disabled = 1;
2749}
2750