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
481struct rpz*
482rpz_create(struct config_auth* p)
483{
484	struct rpz* r = calloc(1, sizeof(*r));
485	if(!r)
486		goto err;
487
488	r->region = regional_create_custom(sizeof(struct regional));
489	if(!r->region) {
490		goto err;
491	}
492
493	if(!(r->local_zones = local_zones_create())){
494		goto err;
495	}
496
497	r->nsdname_zones = local_zones_create();
498	if(r->local_zones == NULL){
499		goto err;
500	}
501
502	if(!(r->respip_set = respip_set_create())) {
503		goto err;
504	}
505
506	r->client_set = rpz_clientip_synthesized_set_create();
507	if(r->client_set == NULL) {
508		goto err;
509	}
510
511	r->ns_set = rpz_clientip_synthesized_set_create();
512	if(r->ns_set == NULL) {
513		goto err;
514	}
515
516	r->taglistlen = p->rpz_taglistlen;
517	r->taglist = memdup(p->rpz_taglist, r->taglistlen);
518	if(p->rpz_action_override) {
519		r->action_override = rpz_config_to_action(p->rpz_action_override);
520	}
521	else
522		r->action_override = RPZ_NO_OVERRIDE_ACTION;
523
524	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
525		uint8_t nm[LDNS_MAX_DOMAINLEN+1];
526		size_t nmlen = sizeof(nm);
527
528		if(!p->rpz_cname) {
529			log_err("rpz: override with cname action found, but no "
530				"rpz-cname-override configured");
531			goto err;
532		}
533
534		if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
535			log_err("rpz: cannot parse cname override: %s",
536				p->rpz_cname);
537			goto err;
538		}
539		r->cname_override = new_cname_override(r->region, nm, nmlen);
540		if(!r->cname_override) {
541			goto err;
542		}
543	}
544	r->log = p->rpz_log;
545	r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
546	if(p->rpz_log_name) {
547		if(!(r->log_name = strdup(p->rpz_log_name))) {
548			log_err("malloc failure on RPZ log_name strdup");
549			goto err;
550		}
551	}
552	return r;
553err:
554	if(r) {
555		if(r->local_zones)
556			local_zones_delete(r->local_zones);
557		if(r->nsdname_zones)
558			local_zones_delete(r->nsdname_zones);
559		if(r->respip_set)
560			respip_set_delete(r->respip_set);
561		if(r->client_set != NULL)
562			rpz_clientip_synthesized_set_delete(r->client_set);
563		if(r->ns_set != NULL)
564			rpz_clientip_synthesized_set_delete(r->ns_set);
565		if(r->taglist)
566			free(r->taglist);
567		if(r->region)
568			regional_destroy(r->region);
569		free(r);
570	}
571	return NULL;
572}
573
574/**
575 * Remove RPZ zone name from dname
576 * Copy dname to newdname, without the originlen number of trailing bytes
577 */
578static size_t
579strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
580	uint8_t* newdname, size_t maxnewdnamelen)
581{
582	size_t newdnamelen;
583	if(dnamelen < originlen)
584		return 0;
585	newdnamelen = dnamelen - originlen;
586	if(newdnamelen+1 > maxnewdnamelen)
587		return 0;
588	memmove(newdname, dname, newdnamelen);
589	newdname[newdnamelen] = 0;
590	return newdnamelen + 1;	/* + 1 for root label */
591}
592
593static void
594rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
595	size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass,
596	uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
597{
598	struct local_zone* z;
599	enum localzone_type tp = local_zone_always_transparent;
600	int dnamelabs = dname_count_labels(dname);
601	int newzone = 0;
602
603	if(a == RPZ_INVALID_ACTION) {
604		char str[255+1];
605		if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
606			rrtype == LDNS_RR_TYPE_DNAME ||
607			rrtype == LDNS_RR_TYPE_DNSKEY ||
608			rrtype == LDNS_RR_TYPE_RRSIG ||
609			rrtype == LDNS_RR_TYPE_NSEC ||
610			rrtype == LDNS_RR_TYPE_NSEC3PARAM ||
611			rrtype == LDNS_RR_TYPE_NSEC3 ||
612			rrtype == LDNS_RR_TYPE_DS) {
613			free(dname);
614			return; /* no need to log these types as unsupported */
615		}
616		dname_str(dname, str);
617		verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s",
618			str, rpz_action_to_string(a));
619		free(dname);
620		return;
621	}
622
623	lock_rw_wrlock(&lz->lock);
624	/* exact match */
625	z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN);
626	if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) {
627		char* rrstr = sldns_wire2str_rr(rr, rr_len);
628		if(rrstr == NULL) {
629			log_err("malloc error while inserting rpz nsdname trigger");
630			free(dname);
631			lock_rw_unlock(&lz->lock);
632			return;
633		}
634		if(rrstr[0])
635			rrstr[strlen(rrstr)-1]=0; /* remove newline */
636		verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr);
637		free(rrstr);
638		free(dname);
639		lock_rw_unlock(&lz->lock);
640		return;
641	}
642	if(z == NULL) {
643		tp = rpz_action_to_localzone_type(a);
644		z = local_zones_add_zone(lz, dname, dnamelen,
645					 dnamelabs, rrclass, tp);
646		if(z == NULL) {
647			log_warn("rpz: create failed");
648			lock_rw_unlock(&lz->lock);
649			/* dname will be free'd in failed local_zone_create() */
650			return;
651		}
652		newzone = 1;
653	}
654	if(a == RPZ_LOCAL_DATA_ACTION) {
655		char* rrstr = sldns_wire2str_rr(rr, rr_len);
656		if(rrstr == NULL) {
657			log_err("malloc error while inserting rpz nsdname trigger");
658			free(dname);
659			lock_rw_unlock(&lz->lock);
660			return;
661		}
662		lock_rw_wrlock(&z->lock);
663		local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
664				    rrclass, ttl, rdata, rdata_len, rrstr);
665		lock_rw_unlock(&z->lock);
666		free(rrstr);
667	}
668	if(!newzone) {
669		free(dname);
670	}
671	lock_rw_unlock(&lz->lock);
672}
673
674static void
675rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
676{
677	char buf[LDNS_MAX_DOMAINLEN+1];
678	(void)dname_len;
679	dname_str(dname, buf);
680	verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
681}
682
683static void
684rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
685	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
686	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
687{
688	if(a == RPZ_INVALID_ACTION) {
689		verbose(VERB_ALGO, "rpz: skipping invalid action");
690		free(dname);
691		return;
692	}
693
694	rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype,
695				       rrclass, ttl, rdata, rdata_len, rr, rr_len);
696}
697
698static int
699rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen,
700	uint8_t** stripdname, size_t* stripdnamelen)
701{
702	uint8_t* tldstart = get_tld_label(dname, maxdnamelen);
703	uint8_t swap;
704	if(tldstart == NULL) {
705		if(dname == NULL) {
706			*stripdname = NULL;
707			*stripdnamelen = 0;
708			return 0;
709		}
710		*stripdname = memdup(dname, maxdnamelen);
711		if(!*stripdname) {
712			*stripdnamelen = 0;
713			log_err("malloc failure for rpz strip suffix");
714			return 0;
715		}
716		*stripdnamelen = maxdnamelen;
717		return 1;
718	}
719	/* shorten the domain name briefly,
720	 * then we allocate a new name with the correct length */
721	swap = *tldstart;
722	*tldstart = 0;
723	(void)dname_count_size_labels(dname, stripdnamelen);
724	*stripdname = memdup(dname, *stripdnamelen);
725	*tldstart = swap;
726	if(!*stripdname) {
727		*stripdnamelen = 0;
728		log_err("malloc failure for rpz strip suffix");
729		return 0;
730	}
731	return 1;
732}
733
734static void
735rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
736	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
737	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
738{
739	uint8_t* dname_stripped = NULL;
740	size_t dnamelen_stripped = 0;
741
742	rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
743		&dnamelen_stripped);
744	if(a == RPZ_INVALID_ACTION) {
745		verbose(VERB_ALGO, "rpz: skipping invalid action");
746		free(dname_stripped);
747		return;
748	}
749
750	/* dname_stripped is consumed or freed by the insert routine */
751	rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped,
752		dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len,
753		rr, rr_len);
754}
755
756static int
757rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr,
758	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
759	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
760	uint8_t* rr, size_t rr_len)
761{
762	struct resp_addr* node;
763	char* rrstr;
764	enum respip_action respa = rpz_action_to_respip_action(a);
765
766	lock_rw_wrlock(&set->lock);
767	rrstr = sldns_wire2str_rr(rr, rr_len);
768	if(rrstr == NULL) {
769		log_err("malloc error while inserting rpz ipaddr based trigger");
770		lock_rw_unlock(&set->lock);
771		return 0;
772	}
773
774	node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr);
775	if(node == NULL) {
776		lock_rw_unlock(&set->lock);
777		free(rrstr);
778		return 0;
779	}
780
781	lock_rw_wrlock(&node->lock);
782	lock_rw_unlock(&set->lock);
783
784	node->action = respa;
785
786	if(a == RPZ_LOCAL_DATA_ACTION) {
787		respip_enter_rr(set->region, node, rrtype,
788				rrclass, ttl, rdata, rdata_len, rrstr, "");
789	}
790
791	lock_rw_unlock(&node->lock);
792	free(rrstr);
793	return 1;
794}
795
796static inline struct clientip_synthesized_rr*
797rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set,
798	struct sockaddr_storage* addr, socklen_t addrlen, int net)
799{
800	int insert_ok;
801	struct clientip_synthesized_rr* node =
802		(struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
803								addr, addrlen, net);
804
805	if(node != NULL) { return node; }
806
807	/* node does not yet exist => allocate one */
808	node = regional_alloc_zero(set->region, sizeof(*node));
809	if(node == NULL) {
810		log_err("out of memory");
811		return NULL;
812	}
813
814	lock_rw_init(&node->lock);
815	node->action = RPZ_INVALID_ACTION;
816	insert_ok = addr_tree_insert(&set->entries, &node->node,
817				     addr, addrlen, net);
818	if (!insert_ok) {
819		log_warn("rpz: unexpected: unable to insert clientip address node");
820		/* we can not free the just allocated node.
821		 * theoretically a memleak */
822		return NULL;
823	}
824
825	return node;
826}
827
828static void
829rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
830	char* rrstr = sldns_wire2str_rr(rr, rr_len);
831	if(rrstr == NULL) {
832		log_err("malloc error while inserting rpz clientip based record");
833		return;
834	}
835	log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr);
836	free(rrstr);
837}
838
839/* from localzone.c; difference is we don't have a dname */
840static struct local_rrset*
841rpz_clientip_new_rrset(struct regional* region,
842	struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
843{
844	struct packed_rrset_data* pd;
845	struct local_rrset* rrset = (struct local_rrset*)
846		regional_alloc_zero(region, sizeof(*rrset));
847	if(rrset == NULL) {
848		log_err("out of memory");
849		return NULL;
850	}
851	rrset->next = raddr->data;
852	raddr->data = rrset;
853	rrset->rrset = (struct ub_packed_rrset_key*)
854		regional_alloc_zero(region, sizeof(*rrset->rrset));
855	if(rrset->rrset == NULL) {
856		log_err("out of memory");
857		return NULL;
858	}
859	rrset->rrset->entry.key = rrset->rrset;
860	pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
861	if(pd == NULL) {
862		log_err("out of memory");
863		return NULL;
864	}
865	pd->trust = rrset_trust_prim_noglue;
866	pd->security = sec_status_insecure;
867	rrset->rrset->entry.data = pd;
868	rrset->rrset->rk.type = htons(rrtype);
869	rrset->rrset->rk.rrset_class = htons(rrclass);
870	rrset->rrset->rk.dname = regional_alloc_zero(region, 1);
871	if(rrset->rrset->rk.dname == NULL) {
872		log_err("out of memory");
873		return NULL;
874	}
875	rrset->rrset->rk.dname_len = 1;
876	return rrset;
877}
878
879static int
880rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr,
881	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
882	size_t rdata_len)
883{
884	struct local_rrset* rrset;
885	if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) {
886		log_err("CNAME response-ip data can not co-exist with other "
887			"client-ip data");
888		return 0;
889	}
890
891	rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
892	if(raddr->data == NULL) {
893		return 0;
894	}
895
896	return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
897}
898
899static int
900rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr,
901	socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype,
902	uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
903	uint8_t* rr, size_t rr_len)
904{
905	struct clientip_synthesized_rr* node;
906
907	lock_rw_wrlock(&set->lock);
908
909	node = rpz_clientip_ensure_entry(set, addr, addrlen, net);
910	if(node == NULL) {
911		lock_rw_unlock(&set->lock);
912		rpz_report_rrset_error("client ip address", rr, rr_len);
913		return 0;
914	}
915
916	lock_rw_wrlock(&node->lock);
917	lock_rw_unlock(&set->lock);
918
919	node->action = a;
920	if(a == RPZ_LOCAL_DATA_ACTION) {
921		if(!rpz_clientip_enter_rr(set->region, node, rrtype,
922			rrclass, ttl, rdata, rdata_len)) {
923			verbose(VERB_ALGO, "rpz: unable to insert clientip rr");
924			lock_rw_unlock(&node->lock);
925			return 0;
926		}
927
928	}
929
930	lock_rw_unlock(&node->lock);
931
932	return 1;
933}
934
935static int
936rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
937	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
938	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
939{
940	struct sockaddr_storage addr;
941	socklen_t addrlen;
942	int net, af;
943
944	if(a == RPZ_INVALID_ACTION) {
945		return 0;
946	}
947
948	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
949		verbose(VERB_ALGO, "rpz: unable to parse client ip");
950		return 0;
951	}
952
953	return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net,
954			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
955}
956
957static int
958rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
959	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
960	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
961{
962	struct sockaddr_storage addr;
963	socklen_t addrlen;
964	int net, af;
965
966	if(a == RPZ_INVALID_ACTION) {
967		return 0;
968	}
969
970	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
971		verbose(VERB_ALGO, "rpz: unable to parse ns ip");
972		return 0;
973	}
974
975	return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net,
976			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
977}
978
979/** Insert RR into RPZ's respip_set */
980static int
981rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
982	enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
983	uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
984{
985	struct sockaddr_storage addr;
986	socklen_t addrlen;
987	int net, af;
988
989	if(a == RPZ_INVALID_ACTION) {
990		return 0;
991	}
992
993	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) {
994		verbose(VERB_ALGO, "rpz: unable to parse response ip");
995		return 0;
996	}
997
998	if(a == RPZ_INVALID_ACTION ||
999		rpz_action_to_respip_action(a) == respip_invalid) {
1000		char str[255+1];
1001		dname_str(dname, str);
1002		verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
1003			str, rpz_action_to_string(a));
1004		return 0;
1005	}
1006
1007	return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net,
1008			a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len);
1009}
1010
1011int
1012rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1013	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
1014	uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
1015{
1016	size_t policydnamelen;
1017	/* name is free'd in local_zone delete */
1018	enum rpz_trigger t;
1019	enum rpz_action a;
1020	uint8_t* policydname;
1021
1022	if(rpz_type_ignored(rr_type)) {
1023		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1024		return 1;
1025	}
1026	if(!dname_subdomain_c(dname, azname)) {
1027		char* dname_str = sldns_wire2str_dname(dname, dnamelen);
1028		char* azname_str = sldns_wire2str_dname(azname, aznamelen);
1029		if(dname_str && azname_str) {
1030			log_err("rpz: name of record (%s) to insert into RPZ is not a "
1031				"subdomain of the configured name of the RPZ zone (%s)",
1032				dname_str, azname_str);
1033		} else {
1034			log_err("rpz: name of record to insert into RPZ is not a "
1035				"subdomain of the configured name of the RPZ zone");
1036		}
1037		free(dname_str);
1038		free(azname_str);
1039		return 0;
1040	}
1041
1042	log_assert(dnamelen >= aznamelen);
1043	if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
1044		log_err("malloc error while inserting RPZ RR");
1045		return 0;
1046	}
1047
1048	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1049	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1050		policydname, (dnamelen-aznamelen)+1))) {
1051		free(policydname);
1052		return 0;
1053	}
1054	t = rpz_dname_to_trigger(policydname, policydnamelen);
1055	if(t == RPZ_INVALID_TRIGGER) {
1056		free(policydname);
1057		verbose(VERB_ALGO, "rpz: skipping invalid trigger");
1058		return 1;
1059	}
1060	if(t == RPZ_QNAME_TRIGGER) {
1061		/* policydname will be consumed, no free */
1062		rpz_insert_qname_trigger(r, policydname, policydnamelen,
1063			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1064			rr_len);
1065	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1066		rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
1067			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1068			rr_len);
1069		free(policydname);
1070	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1071		rpz_insert_clientip_trigger(r, policydname, policydnamelen,
1072			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1073			rr_len);
1074		free(policydname);
1075	} else if(t == RPZ_NSIP_TRIGGER) {
1076		rpz_insert_nsip_trigger(r, policydname, policydnamelen,
1077			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1078			rr_len);
1079		free(policydname);
1080	} else if(t == RPZ_NSDNAME_TRIGGER) {
1081		rpz_insert_nsdname_trigger(r, policydname, policydnamelen,
1082			a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
1083			rr_len);
1084		free(policydname);
1085	} else {
1086		free(policydname);
1087		verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s",
1088			rpz_trigger_to_string(t));
1089	}
1090	return 1;
1091}
1092
1093/**
1094 * Find RPZ local-zone by qname.
1095 * @param zones: local-zone tree
1096 * @param qname: qname
1097 * @param qname_len: length of qname
1098 * @param qclass: qclass
1099 * @param only_exact: if 1 only exact (non wildcard) matches are returned
1100 * @param wr: get write lock for local-zone if 1, read lock if 0
1101 * @param zones_keep_lock: if set do not release the r->local_zones lock, this
1102 * 	  makes the caller of this function responsible for releasing the lock.
1103 * @return: NULL or local-zone holding rd or wr lock
1104 */
1105static struct local_zone*
1106rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass,
1107	int only_exact, int wr, int zones_keep_lock)
1108{
1109	uint8_t* ce;
1110	size_t ce_len;
1111	int ce_labs;
1112	uint8_t wc[LDNS_MAX_DOMAINLEN+1];
1113	int exact;
1114	struct local_zone* z = NULL;
1115
1116	if(wr) {
1117		lock_rw_wrlock(&zones->lock);
1118	} else {
1119		lock_rw_rdlock(&zones->lock);
1120	}
1121	z = local_zones_find_le(zones, qname, qname_len,
1122		dname_count_labels(qname),
1123		LDNS_RR_CLASS_IN, &exact);
1124	if(!z || (only_exact && !exact)) {
1125		if(!zones_keep_lock) {
1126			lock_rw_unlock(&zones->lock);
1127		}
1128		return NULL;
1129	}
1130	if(wr) {
1131		lock_rw_wrlock(&z->lock);
1132	} else {
1133		lock_rw_rdlock(&z->lock);
1134	}
1135	if(!zones_keep_lock) {
1136		lock_rw_unlock(&zones->lock);
1137	}
1138
1139	if(exact)
1140		return z;
1141
1142	/* No exact match found, lookup wildcard. closest encloser must
1143	 * be the shared parent between the qname and the best local
1144	 * zone match, append '*' to that and do another lookup. */
1145
1146	ce = dname_get_shared_topdomain(z->name, qname);
1147	if(!ce /* should not happen */) {
1148		lock_rw_unlock(&z->lock);
1149		if(zones_keep_lock) {
1150			lock_rw_unlock(&zones->lock);
1151		}
1152		return NULL;
1153	}
1154	ce_labs = dname_count_size_labels(ce, &ce_len);
1155	if(ce_len+2 > sizeof(wc)) {
1156		lock_rw_unlock(&z->lock);
1157		if(zones_keep_lock) {
1158			lock_rw_unlock(&zones->lock);
1159		}
1160		return NULL;
1161	}
1162	wc[0] = 1; /* length of wildcard label */
1163	wc[1] = (uint8_t)'*'; /* wildcard label */
1164	memmove(wc+2, ce, ce_len);
1165	lock_rw_unlock(&z->lock);
1166
1167	if(!zones_keep_lock) {
1168		if(wr) {
1169			lock_rw_wrlock(&zones->lock);
1170		} else {
1171			lock_rw_rdlock(&zones->lock);
1172		}
1173	}
1174	z = local_zones_find_le(zones, wc,
1175		ce_len+2, ce_labs+1, qclass, &exact);
1176	if(!z || !exact) {
1177		lock_rw_unlock(&zones->lock);
1178		return NULL;
1179	}
1180	if(wr) {
1181		lock_rw_wrlock(&z->lock);
1182	} else {
1183		lock_rw_rdlock(&z->lock);
1184	}
1185	if(!zones_keep_lock) {
1186		lock_rw_unlock(&zones->lock);
1187	}
1188	return z;
1189}
1190
1191/** Find entry for RR type in the list of rrsets for the clientip. */
1192static struct local_rrset*
1193rpz_find_synthesized_rrset(uint16_t qtype,
1194	struct clientip_synthesized_rr* data)
1195{
1196	struct local_rrset* cursor = data->data;
1197	while( cursor != NULL) {
1198		struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
1199		if(htons(qtype) == packed_rrset->type) {
1200			return cursor;
1201		}
1202		cursor = cursor->next;
1203	}
1204	return NULL;
1205}
1206
1207/**
1208 * Remove RR from RPZ's local-data
1209 * @param z: local-zone for RPZ, holding write lock
1210 * @param policydname: dname of RR to remove
1211 * @param policydnamelen: length of policydname
1212 * @param rr_type: RR type of RR to remove
1213 * @param rdata: rdata of RR to remove
1214 * @param rdatalen: length of rdata
1215 * @return: 1 if zone must be removed after RR deletion
1216 */
1217static int
1218rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
1219	size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
1220	size_t rdatalen)
1221{
1222	struct local_data* ld;
1223	struct packed_rrset_data* d;
1224	size_t index;
1225	ld = local_zone_find_data(z, policydname, policydnamelen,
1226		dname_count_labels(policydname));
1227	if(ld) {
1228		struct local_rrset* prev=NULL, *p=ld->rrsets;
1229		while(p && ntohs(p->rrset->rk.type) != rr_type) {
1230			prev = p;
1231			p = p->next;
1232		}
1233		if(!p)
1234			return 0;
1235		d = (struct packed_rrset_data*)p->rrset->entry.data;
1236		if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1237			if(d->count == 1) {
1238				/* no memory recycling for zone deletions ... */
1239				if(prev) prev->next = p->next;
1240				else ld->rrsets = p->next;
1241			}
1242			if(d->count > 1) {
1243				if(!local_rrset_remove_rr(d, index))
1244					return 0;
1245			}
1246		}
1247	}
1248	if(ld && ld->rrsets)
1249		return 0;
1250	return 1;
1251}
1252
1253/**
1254 * Remove RR from RPZ's respip set
1255 * @param raddr: respip node
1256 * @param rr_type: RR type of RR to remove
1257 * @param rdata: rdata of RR to remove
1258 * @param rdatalen: length of rdata
1259 * @return: 1 if zone must be removed after RR deletion
1260 */
1261static int
1262rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
1263	size_t rdatalen)
1264{
1265	size_t index;
1266	struct packed_rrset_data* d;
1267	if(!raddr->data)
1268		return 1;
1269	d = raddr->data->entry.data;
1270	if(ntohs(raddr->data->rk.type) != rr_type) {
1271		return 0;
1272	}
1273	if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
1274		if(d->count == 1) {
1275			/* regional alloc'd */
1276			raddr->data->entry.data = NULL;
1277			raddr->data = NULL;
1278			return 1;
1279		}
1280		if(d->count > 1) {
1281			if(!local_rrset_remove_rr(d, index))
1282				return 0;
1283		}
1284	}
1285	return 0;
1286
1287}
1288
1289/** Remove RR from rpz localzones structure */
1290static void
1291rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
1292	size_t dnamelen, enum rpz_action a, uint16_t rr_type,
1293	uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
1294{
1295	struct local_zone* z;
1296	int delete_zone = 1;
1297	z = rpz_find_zone(zones, dname, dnamelen, rr_class,
1298		1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
1299	if(!z) {
1300		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1301			"RPZ domain not found");
1302		return;
1303	}
1304	if(a == RPZ_LOCAL_DATA_ACTION)
1305		delete_zone = rpz_data_delete_rr(z, dname,
1306			dnamelen, rr_type, rdatawl, rdatalen);
1307	else if(a != localzone_type_to_rpz_action(z->type)) {
1308		lock_rw_unlock(&z->lock);
1309		lock_rw_unlock(&zones->lock);
1310		return;
1311	}
1312	lock_rw_unlock(&z->lock);
1313	if(delete_zone) {
1314		local_zones_del_zone(zones, z);
1315	}
1316	lock_rw_unlock(&zones->lock);
1317}
1318
1319/** Remove RR from RPZ's local-zone */
1320static void
1321rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1322	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1323	uint8_t* rdatawl, size_t rdatalen)
1324{
1325	rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
1326		a, rr_type, rr_class, rdatawl, rdatalen);
1327}
1328
1329static void
1330rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1331	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1332{
1333	struct resp_addr* node;
1334	struct sockaddr_storage addr;
1335	socklen_t addrlen;
1336	int net, af;
1337	int delete_respip = 1;
1338
1339	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1340		return;
1341
1342	lock_rw_wrlock(&r->respip_set->lock);
1343	if(!(node = (struct resp_addr*)addr_tree_find(
1344		&r->respip_set->ip_tree, &addr, addrlen, net))) {
1345		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1346			"RPZ domain not found");
1347		lock_rw_unlock(&r->respip_set->lock);
1348		return;
1349	}
1350
1351	lock_rw_wrlock(&node->lock);
1352	if(a == RPZ_LOCAL_DATA_ACTION) {
1353		/* remove RR, signal whether RR can be removed */
1354		delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
1355			rdatalen);
1356	}
1357	lock_rw_unlock(&node->lock);
1358	if(delete_respip)
1359		respip_sockaddr_delete(r->respip_set, node);
1360	lock_rw_unlock(&r->respip_set->lock);
1361}
1362
1363/** find and remove type from list of local_rrset entries*/
1364static void
1365del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
1366{
1367	struct local_rrset* prev=NULL, *p=*list_head;
1368	while(p && ntohs(p->rrset->rk.type) != dtype) {
1369		prev = p;
1370		p = p->next;
1371	}
1372	if(!p)
1373		return; /* rrset type not found */
1374	/* unlink it */
1375	if(prev) prev->next = p->next;
1376	else *list_head = p->next;
1377	/* no memory recycling for zone deletions ... */
1378}
1379
1380/** Delete client-ip trigger RR from its RRset and perhaps also the rrset
1381 * from the linked list. Returns if the local data is empty and the node can
1382 * be deleted too, or not. */
1383static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
1384	uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1385{
1386	struct local_rrset* rrset;
1387	struct packed_rrset_data* d;
1388	size_t index;
1389	rrset = rpz_find_synthesized_rrset(rr_type, node);
1390	if(rrset == NULL)
1391		return 0; /* type not found, ignore */
1392	d = (struct packed_rrset_data*)rrset->rrset->entry.data;
1393	if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
1394		return 0; /* RR not found, ignore */
1395	if(d->count == 1) {
1396		/* regional alloc'd */
1397		/* delete the type entry from the list */
1398		del_local_rrset_from_list(&node->data, rr_type);
1399		/* if the list is empty, the node can be removed too */
1400		if(node->data == NULL)
1401			return 1;
1402	} else if (d->count > 1) {
1403		if(!local_rrset_remove_rr(d, index))
1404			return 0;
1405	}
1406	return 0;
1407}
1408
1409/** remove trigger RR from clientip_syntheized set tree. */
1410static void
1411rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
1412	struct sockaddr_storage* addr, socklen_t addrlen, int net,
1413	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1414{
1415	struct clientip_synthesized_rr* node;
1416	int delete_node = 1;
1417
1418	lock_rw_wrlock(&set->lock);
1419	node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
1420		addr, addrlen, net);
1421	if(node == NULL) {
1422		/* netblock not found */
1423		verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
1424			"RPZ address, netblock not found");
1425		lock_rw_unlock(&set->lock);
1426		return;
1427	}
1428	lock_rw_wrlock(&node->lock);
1429	if(a == RPZ_LOCAL_DATA_ACTION) {
1430		/* remove RR, signal whether entry can be removed */
1431		delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
1432			rdatalen);
1433	} else if(a != node->action) {
1434		/* ignore the RR with different action specification */
1435		delete_node = 0;
1436	}
1437	if(delete_node) {
1438		rbtree_delete(&set->entries, node->node.node.key);
1439	}
1440	lock_rw_unlock(&set->lock);
1441	lock_rw_unlock(&node->lock);
1442	if(delete_node) {
1443		lock_rw_destroy(&node->lock);
1444	}
1445}
1446
1447/** Remove clientip trigger RR from RPZ. */
1448static void
1449rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1450	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1451{
1452	struct sockaddr_storage addr;
1453	socklen_t addrlen;
1454	int net, af;
1455	if(a == RPZ_INVALID_ACTION)
1456		return;
1457	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1458		return;
1459	rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
1460		a, rr_type, rdatawl, rdatalen);
1461}
1462
1463/** Remove nsip trigger RR from RPZ. */
1464static void
1465rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1466	enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
1467{
1468	struct sockaddr_storage addr;
1469	socklen_t addrlen;
1470	int net, af;
1471	if(a == RPZ_INVALID_ACTION)
1472		return;
1473	if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
1474		return;
1475	rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
1476		a, rr_type, rdatawl, rdatalen);
1477}
1478
1479/** Remove nsdname trigger RR from RPZ. */
1480static void
1481rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
1482	enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
1483	uint8_t* rdatawl, size_t rdatalen)
1484{
1485	uint8_t* dname_stripped = NULL;
1486	size_t dnamelen_stripped = 0;
1487	if(a == RPZ_INVALID_ACTION)
1488		return;
1489	if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
1490		&dnamelen_stripped))
1491		return;
1492	rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
1493		dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
1494	free(dname_stripped);
1495}
1496
1497void
1498rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
1499	size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
1500	size_t rdatalen)
1501{
1502	size_t policydnamelen;
1503	enum rpz_trigger t;
1504	enum rpz_action a;
1505	uint8_t* policydname;
1506
1507	if(rpz_type_ignored(rr_type)) {
1508		/* this rpz action is not valid, eg. this is the SOA or NS RR */
1509		return;
1510	}
1511	if(!dname_subdomain_c(dname, azname)) {
1512		/* not subdomain of the RPZ zone. */
1513		return;
1514	}
1515
1516	if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
1517		return;
1518
1519	a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
1520	if(a == RPZ_INVALID_ACTION) {
1521		free(policydname);
1522		return;
1523	}
1524	if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
1525		policydname, LDNS_MAX_DOMAINLEN + 1))) {
1526		free(policydname);
1527		return;
1528	}
1529	t = rpz_dname_to_trigger(policydname, policydnamelen);
1530	if(t == RPZ_INVALID_TRIGGER) {
1531		/* skipping invalid trigger */
1532		free(policydname);
1533		return;
1534	}
1535	if(t == RPZ_QNAME_TRIGGER) {
1536		rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
1537			rr_type, rr_class, rdatawl, rdatalen);
1538	} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
1539		rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
1540			a, rr_type, rdatawl, rdatalen);
1541	} else if(t == RPZ_CLIENT_IP_TRIGGER) {
1542		rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
1543			rr_type, rdatawl, rdatalen);
1544	} else if(t == RPZ_NSIP_TRIGGER) {
1545		rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
1546			rr_type, rdatawl, rdatalen);
1547	} else if(t == RPZ_NSDNAME_TRIGGER) {
1548		rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
1549			rr_type, rr_class, rdatawl, rdatalen);
1550	}
1551	/* else it was an unsupported trigger, also skipped. */
1552	free(policydname);
1553}
1554
1555/** print log information for an applied RPZ policy. Based on local-zone's
1556 * lz_inform_print().
1557 * The repinfo contains the reply address. If it is NULL, the module
1558 * state is used to report the first IP address (if any).
1559 * The dname is used, for the applied rpz, if NULL, addrnode is used.
1560 */
1561static void
1562log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
1563	enum rpz_action a, struct query_info* qinfo,
1564	struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
1565{
1566	char ip[128], txt[512], portstr[32];
1567	char dnamestr[LDNS_MAX_DOMAINLEN+1];
1568	uint16_t port = 0;
1569	if(dname) {
1570		dname_str(dname, dnamestr);
1571	} else if(addrnode) {
1572		char addrbuf[128];
1573		addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf));
1574		snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net);
1575	} else {
1576		dnamestr[0]=0;
1577	}
1578	if(repinfo) {
1579		addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
1580		port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
1581	} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
1582		addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
1583			ms->mesh_info->reply_list->query_reply.client_addrlen,
1584			ip, sizeof(ip));
1585		port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
1586	} else {
1587		ip[0]=0;
1588		port = 0;
1589	}
1590	snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port);
1591	snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s",
1592		(log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""),
1593		(strcmp(trigger,"qname")==0?"":trigger),
1594		(strcmp(trigger,"qname")==0?"":" "),
1595		dnamestr, rpz_action_to_string(a),
1596		(ip[0]?ip:""), (ip[0]?portstr:""));
1597	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1598}
1599
1600static struct clientip_synthesized_rr*
1601rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set,
1602	struct sockaddr_storage* addr, socklen_t addrlen, char* triggername)
1603{
1604	struct clientip_synthesized_rr* raddr = NULL;
1605	enum rpz_action action = RPZ_INVALID_ACTION;
1606
1607	lock_rw_rdlock(&set->lock);
1608
1609	raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries,
1610			addr, addrlen);
1611	if(raddr != NULL) {
1612		lock_rw_rdlock(&raddr->lock);
1613		action = raddr->action;
1614		if(verbosity >= VERB_ALGO) {
1615			char ip[256], net[256];
1616			addr_to_str(addr, addrlen, ip, sizeof(ip));
1617			addr_to_str(&raddr->node.addr, raddr->node.addrlen,
1618				net, sizeof(net));
1619			verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s",
1620				triggername, net, raddr->node.net, ip, rpz_action_to_string(action));
1621		}
1622	}
1623	lock_rw_unlock(&set->lock);
1624
1625	return raddr;
1626}
1627
1628static inline
1629struct clientip_synthesized_rr*
1630rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo,
1631	struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
1632	struct ub_server_stats* stats,
1633	/* output parameters */
1634	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
1635{
1636	struct clientip_synthesized_rr* node = NULL;
1637	struct auth_zone* a = NULL;
1638	struct rpz* r = NULL;
1639	struct local_zone* z = NULL;
1640
1641	lock_rw_rdlock(&az->rpz_lock);
1642
1643	for(a = az->rpz_first; a; a = a->rpz_az_next) {
1644		lock_rw_rdlock(&a->lock);
1645		r = a->rpz;
1646		if(r->disabled) {
1647			lock_rw_unlock(&a->lock);
1648			continue;
1649		}
1650		if(r->taglist && !taglist_intersect(r->taglist,
1651					r->taglistlen, taglist, taglen)) {
1652			lock_rw_unlock(&a->lock);
1653			continue;
1654		}
1655		z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
1656			qinfo->qclass, 0, 0, 0);
1657		node = rpz_ipbased_trigger_lookup(r->client_set,
1658			&repinfo->client_addr, repinfo->client_addrlen,
1659			"clientip");
1660		if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
1661			if(r->log)
1662				log_rpz_apply((node?"clientip":"qname"),
1663					(z?z->name:NULL),
1664					(node?&node->node:NULL),
1665					r->action_override,
1666					qinfo, repinfo, NULL, r->log_name);
1667			stats->rpz_action[r->action_override]++;
1668			if(z != NULL) {
1669				lock_rw_unlock(&z->lock);
1670				z = NULL;
1671			}
1672			if(node != NULL) {
1673				lock_rw_unlock(&node->lock);
1674				node = NULL;
1675			}
1676		}
1677		if(z || node) {
1678			break;
1679		}
1680		/* not found in this auth_zone */
1681		lock_rw_unlock(&a->lock);
1682	}
1683
1684	lock_rw_unlock(&az->rpz_lock);
1685
1686	*r_out = r;
1687	*a_out = a;
1688	*z_out = z;
1689
1690	return node;
1691}
1692
1693static inline int
1694rpz_is_udp_query(struct comm_reply* repinfo) {
1695	return repinfo != NULL
1696			? (repinfo->c != NULL
1697				? repinfo->c->type == comm_udp
1698				: 0)
1699			: 0;
1700}
1701
1702/** encode answer consisting of 1 rrset */
1703static int
1704rpz_local_encode(struct module_env* env, struct query_info* qinfo,
1705	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1706	struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
1707	int rcode, struct ub_packed_rrset_key* soa_rrset)
1708{
1709	struct reply_info rep;
1710	uint16_t udpsize;
1711	struct ub_packed_rrset_key* rrsetlist[3];
1712
1713	memset(&rep, 0, sizeof(rep));
1714	rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1715	rep.qdcount = 1;
1716	rep.rrset_count = ansec;
1717	rep.rrsets = rrsetlist;
1718	if(ansec > 0) {
1719		rep.an_numrrsets = 1;
1720		rep.rrsets[0] = rrset;
1721		rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
1722	}
1723	if(soa_rrset != NULL) {
1724		rep.ar_numrrsets = 1;
1725		rep.rrsets[rep.rrset_count] = soa_rrset;
1726		rep.rrset_count ++;
1727		if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
1728			rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
1729		}
1730	}
1731
1732	udpsize = edns->udp_size;
1733	edns->edns_version = EDNS_ADVERTISED_VERSION;
1734	edns->udp_size = EDNS_ADVERTISED_SIZE;
1735	edns->ext_rcode = 0;
1736	edns->bits &= EDNS_DO;
1737	if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
1738		repinfo, temp, env->now_tv) ||
1739	  !reply_info_answer_encode(qinfo, &rep,
1740		*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
1741		buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
1742		error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1743			*(uint16_t*)sldns_buffer_begin(buf),
1744			sldns_buffer_read_u16_at(buf, 2), edns);
1745	}
1746
1747	return 1;
1748}
1749
1750/** allocate SOA record ubrrsetkey in region */
1751static struct ub_packed_rrset_key*
1752make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
1753	struct regional* temp)
1754{
1755	struct ub_packed_rrset_key csoa;
1756	if(!soa)
1757		return NULL;
1758	memset(&csoa, 0, sizeof(csoa));
1759	csoa.entry.key = &csoa;
1760	csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
1761	csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
1762	csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
1763		| PACKED_RRSET_RPZ;
1764	csoa.rk.dname = auth_zone->name;
1765	csoa.rk.dname_len = auth_zone->namelen;
1766	csoa.entry.hash = rrset_key_hash(&csoa.rk);
1767	csoa.entry.data = soa->data;
1768	return respip_copy_rrset(&csoa, temp);
1769}
1770
1771static void
1772rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
1773	struct module_env* env, struct query_info* qinfo,
1774	struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
1775	struct regional* temp, struct auth_zone* auth_zone)
1776{
1777	struct local_rrset* rrset;
1778	enum rpz_action action = RPZ_INVALID_ACTION;
1779	struct ub_packed_rrset_key* rp = NULL;
1780	struct ub_packed_rrset_key* rsoa = NULL;
1781	int rcode = LDNS_RCODE_NOERROR|BIT_AA;
1782	int rrset_count = 1;
1783
1784	/* prepare synthesized answer for client */
1785	action = raddr->action;
1786	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) {
1787		verbose(VERB_ALGO, "rpz: bug: local-data action but no local data");
1788		return;
1789	}
1790
1791	/* check query type / rr type */
1792	rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
1793	if(rrset == NULL) {
1794		verbose(VERB_ALGO, "rpz: unable to find local-data for query");
1795		rrset_count = 0;
1796		goto nodata;
1797	}
1798
1799	rp = respip_copy_rrset(rrset->rrset, temp);
1800	if(!rp) {
1801		verbose(VERB_ALGO, "rpz: local data action: out of memory");
1802		return;
1803	}
1804
1805	rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
1806	rp->rk.dname = qinfo->qname;
1807	rp->rk.dname_len = qinfo->qname_len;
1808	rp->entry.hash = rrset_key_hash(&rp->rk);
1809nodata:
1810	if(auth_zone) {
1811		struct auth_rrset* soa = NULL;
1812		soa = auth_zone_get_soa_rrset(auth_zone);
1813		if(soa) {
1814			rsoa = make_soa_ubrrset(auth_zone, soa, temp);
1815			if(!rsoa) {
1816				verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
1817				return;
1818			}
1819		}
1820	}
1821
1822	rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
1823		rrset_count, rcode, rsoa);
1824}
1825
1826/** add additional section SOA record to the reply.
1827 * Since this gets fed into the normal iterator answer creation, it
1828 * gets minimal-responses applied to it, that can remove the additional SOA
1829 * again. */
1830static int
1831rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
1832	struct auth_zone* az)
1833{
1834	struct auth_rrset* soa = NULL;
1835	struct ub_packed_rrset_key* rsoa = NULL;
1836	struct ub_packed_rrset_key** prevrrsets;
1837	if(!az) return 1;
1838	soa = auth_zone_get_soa_rrset(az);
1839	if(!soa) return 1;
1840	if(!rep) return 0;
1841	rsoa = make_soa_ubrrset(az, soa, ms->region);
1842	if(!rsoa) return 0;
1843	prevrrsets = rep->rrsets;
1844	rep->rrsets = regional_alloc_zero(ms->region,
1845		sizeof(*rep->rrsets)*(rep->rrset_count+1));
1846	if(!rep->rrsets)
1847		return 0;
1848	if(prevrrsets && rep->rrset_count > 0)
1849		memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
1850	rep->rrset_count++;
1851	rep->ar_numrrsets++;
1852	rep->rrsets[rep->rrset_count-1] = rsoa;
1853	return 1;
1854}
1855
1856static inline struct dns_msg*
1857rpz_dns_msg_new(struct regional* region)
1858{
1859	struct dns_msg* msg =
1860			(struct dns_msg*)regional_alloc(region,
1861							sizeof(struct dns_msg));
1862	if(msg == NULL) { return NULL; }
1863	memset(msg, 0, sizeof(struct dns_msg));
1864
1865	return msg;
1866}
1867
1868static inline struct dns_msg*
1869rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1870	struct query_info* qinfo, struct auth_zone* az)
1871{
1872	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1873	if(msg == NULL) { return msg; }
1874	msg->qinfo = *qinfo;
1875	msg->rep = construct_reply_info_base(ms->region,
1876					     LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1877					     1, /* qd */
1878					     0, /* ttl */
1879					     0, /* prettl */
1880					     0, /* expttl */
1881					     0, /* an */
1882					     0, /* ns */
1883					     0, /* ar */
1884					     0, /* total */
1885					     sec_status_insecure,
1886					     LDNS_EDE_NONE);
1887	if(msg->rep)
1888		msg->rep->authoritative = 1;
1889	if(!rpz_add_soa(msg->rep, ms, az))
1890		return NULL;
1891	return msg;
1892}
1893
1894static inline struct dns_msg*
1895rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
1896	struct query_info* qinfo, struct auth_zone* az)
1897{
1898	struct dns_msg* msg = rpz_dns_msg_new(ms->region);
1899	uint16_t flags;
1900	if(msg == NULL) { return msg; }
1901	msg->qinfo = *qinfo;
1902	flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA;
1903	if(r->signal_nxdomain_ra)
1904		flags &= ~BIT_RA;
1905	msg->rep = construct_reply_info_base(ms->region,
1906					     flags,
1907					     1, /* qd */
1908					     0, /* ttl */
1909					     0, /* prettl */
1910					     0, /* expttl */
1911					     0, /* an */
1912					     0, /* ns */
1913					     0, /* ar */
1914					     0, /* total */
1915					     sec_status_insecure,
1916					     LDNS_EDE_NONE);
1917	if(msg->rep)
1918		msg->rep->authoritative = 1;
1919	if(!rpz_add_soa(msg->rep, ms, az))
1920		return NULL;
1921	return msg;
1922}
1923
1924static inline struct dns_msg*
1925rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
1926	struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
1927{
1928	struct dns_msg* msg = NULL;
1929	struct reply_info* new_reply_info;
1930	struct ub_packed_rrset_key* rp;
1931
1932
1933	msg = rpz_dns_msg_new(ms->region);
1934	if(msg == NULL) { return NULL; }
1935
1936        new_reply_info = construct_reply_info_base(ms->region,
1937                                                   LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1938                                                   1, /* qd */
1939                                                   0, /* ttl */
1940                                                   0, /* prettl */
1941                                                   0, /* expttl */
1942                                                   1, /* an */
1943                                                   0, /* ns */
1944                                                   0, /* ar */
1945                                                   1, /* total */
1946                                                   sec_status_insecure,
1947                                                   LDNS_EDE_NONE);
1948	if(new_reply_info == NULL) {
1949		log_err("out of memory");
1950		return NULL;
1951	}
1952	new_reply_info->authoritative = 1;
1953	rp = respip_copy_rrset(rrset->rrset, ms->region);
1954	if(rp == NULL) {
1955		log_err("out of memory");
1956		return NULL;
1957	}
1958	rp->rk.dname = qi->qname;
1959	rp->rk.dname_len = qi->qname_len;
1960	/* this rrset is from the rpz data, or synthesized.
1961	 * It is not actually from the network, so we flag it with this
1962	 * flags as a fake RRset. If later the cache is used to look up
1963	 * rrsets, then the fake ones are not returned (if you look without
1964	 * the flag). For like CNAME lookups from the iterator or A, AAAA
1965	 * lookups for nameserver targets, it would use the without flag
1966	 * actual data. So that the actual network data and fake data
1967	 * are kept track of separately. */
1968	rp->rk.flags |= PACKED_RRSET_RPZ;
1969	new_reply_info->rrsets[0] = rp;
1970	msg->rep = new_reply_info;
1971	if(!rpz_add_soa(msg->rep, ms, az))
1972		return NULL;
1973	return msg;
1974}
1975
1976static inline struct dns_msg*
1977rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
1978	struct clientip_synthesized_rr* data, struct auth_zone* az)
1979{
1980	struct query_info* qi = &ms->qinfo;
1981	struct local_rrset* rrset;
1982
1983	rrset = rpz_find_synthesized_rrset(qi->qtype, data);
1984	if(rrset == NULL) {
1985		verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
1986		return NULL;
1987	}
1988
1989	return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
1990}
1991
1992/* copy'n'paste from localzone.c */
1993static struct local_rrset*
1994local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
1995{
1996	struct local_rrset* p;
1997	type = htons(type);
1998	for(p = data->rrsets; p; p = p->next) {
1999		if(p->rrset->rk.type == type)
2000			return p;
2001		if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
2002			return p;
2003	}
2004	return NULL;
2005}
2006
2007/* based on localzone.c:local_data_answer() */
2008static inline struct dns_msg*
2009rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
2010	struct local_zone* z, struct matched_delegation_point const* match,
2011	struct auth_zone* az)
2012{
2013	struct local_data key;
2014	struct local_data* ld;
2015	struct local_rrset* rrset;
2016
2017	if(match->dname == NULL) { return NULL; }
2018
2019	key.node.key = &key;
2020	key.name = match->dname;
2021	key.namelen = match->dname_len;
2022	key.namelabs = dname_count_labels(match->dname);
2023
2024	rpz_log_dname("nsdname local data", key.name, key.namelen);
2025
2026	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2027	if(ld == NULL) {
2028		verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found");
2029		return NULL;
2030	}
2031
2032	rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
2033	if(rrset == NULL) {
2034		verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
2035		return NULL;
2036	}
2037
2038	return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
2039}
2040
2041/* like local_data_answer for qname triggers after a cname */
2042static struct dns_msg*
2043rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
2044	struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
2045{
2046	struct local_data key;
2047	struct local_data* ld;
2048	struct local_rrset* rrset;
2049	key.node.key = &key;
2050	key.name = qinfo->qname;
2051	key.namelen = qinfo->qname_len;
2052	key.namelabs = dname_count_labels(qinfo->qname);
2053	ld = (struct local_data*)rbtree_search(&z->data, &key.node);
2054	if(ld == NULL) {
2055		verbose(VERB_ALGO, "rpz: qname after cname: name not found");
2056		return NULL;
2057	}
2058	rrset = local_data_find_type(ld, qinfo->qtype, 1);
2059	if(rrset == NULL) {
2060		verbose(VERB_ALGO, "rpz: qname after cname: type not found");
2061		return NULL;
2062	}
2063	return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
2064}
2065
2066static int
2067rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
2068	struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
2069	struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
2070	struct comm_reply* repinfo, struct ub_server_stats* stats)
2071{
2072	struct local_data* ld = NULL;
2073	int ret = 0;
2074	if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
2075		qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
2076		if(qinfo->local_alias == NULL) {
2077			return 0; /* out of memory */
2078		}
2079		qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
2080								sizeof(*r->cname_override));
2081		if(qinfo->local_alias->rrset == NULL) {
2082			return 0; /* out of memory */
2083		}
2084		qinfo->local_alias->rrset->rk.dname = qinfo->qname;
2085		qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
2086		if(r->log) {
2087			log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
2088				      qinfo, repinfo, NULL, r->log_name);
2089		}
2090		stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
2091		return 0;
2092	}
2093
2094	if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
2095		edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
2096		&ld, lzt, -1, NULL, 0, NULL, 0)) {
2097		if(r->log) {
2098			log_rpz_apply("qname", z->name, NULL,
2099				localzone_type_to_rpz_action(lzt), qinfo,
2100				repinfo, NULL, r->log_name);
2101		}
2102		stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2103		return !qinfo->local_alias;
2104	}
2105
2106	ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
2107		0 /* no local data used */, lzt);
2108	if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2109		== LDNS_RCODE_NXDOMAIN)
2110		LDNS_RA_CLR(sldns_buffer_begin(buf));
2111	if(r->log) {
2112		log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
2113			      qinfo, repinfo, NULL, r->log_name);
2114	}
2115	stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
2116	return ret;
2117}
2118
2119static struct clientip_synthesized_rr*
2120rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
2121{
2122	struct delegpt_addr* cursor;
2123	struct clientip_synthesized_rr* action = NULL;
2124	if(is->dp == NULL) { return NULL; }
2125	for(cursor = is->dp->target_list;
2126	    cursor != NULL;
2127	    cursor = cursor->next_target) {
2128		if(cursor->bogus) { continue; }
2129		action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr,
2130						    cursor->addrlen, "nsip");
2131		if(action != NULL) { return action; }
2132	}
2133	return NULL;
2134}
2135
2136static struct dns_msg*
2137rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
2138	struct clientip_synthesized_rr* raddr, struct auth_zone* az)
2139{
2140	enum rpz_action action = raddr->action;
2141	struct dns_msg* ret = NULL;
2142
2143	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2144		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2145			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2146		action = r->action_override;
2147	}
2148
2149	if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
2150		verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
2151		ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2152		goto done;
2153	}
2154
2155	switch(action) {
2156	case RPZ_NXDOMAIN_ACTION:
2157		ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
2158		break;
2159	case RPZ_NODATA_ACTION:
2160		ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2161		break;
2162	case RPZ_TCP_ONLY_ACTION:
2163		/* basically a passthru here but the tcp-only will be
2164		 * honored before the query gets sent. */
2165		ms->tcp_required = 1;
2166		ret = NULL;
2167		break;
2168	case RPZ_DROP_ACTION:
2169		ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2170		ms->is_drop = 1;
2171		break;
2172	case RPZ_LOCAL_DATA_ACTION:
2173		ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
2174		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
2175		break;
2176	case RPZ_PASSTHRU_ACTION:
2177		ret = NULL;
2178		ms->rpz_passthru = 1;
2179		break;
2180	default:
2181		verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2182			rpz_action_to_string(action));
2183		ret = NULL;
2184	}
2185
2186done:
2187	if(r->log)
2188		log_rpz_apply("nsip", NULL, &raddr->node,
2189			action, &ms->qinfo, NULL, ms, r->log_name);
2190	if(ms->env->worker)
2191		ms->env->worker->stats.rpz_action[action]++;
2192	lock_rw_unlock(&raddr->lock);
2193	return ret;
2194}
2195
2196static struct dns_msg*
2197rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
2198	struct local_zone* z, struct matched_delegation_point const* match,
2199	struct auth_zone* az)
2200{
2201	struct dns_msg* ret = NULL;
2202	enum rpz_action action = localzone_type_to_rpz_action(z->type);
2203
2204	if(r->action_override != RPZ_NO_OVERRIDE_ACTION) {
2205		verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)",
2206			rpz_action_to_string(r->action_override), rpz_action_to_string(action));
2207		action = r->action_override;
2208	}
2209
2210	switch(action) {
2211	case RPZ_NXDOMAIN_ACTION:
2212		ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
2213		break;
2214	case RPZ_NODATA_ACTION:
2215		ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2216		break;
2217	case RPZ_TCP_ONLY_ACTION:
2218		/* basically a passthru here but the tcp-only will be
2219		 * honored before the query gets sent. */
2220		ms->tcp_required = 1;
2221		ret = NULL;
2222		break;
2223	case RPZ_DROP_ACTION:
2224		ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
2225		ms->is_drop = 1;
2226		break;
2227	case RPZ_LOCAL_DATA_ACTION:
2228		ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
2229		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
2230		break;
2231	case RPZ_PASSTHRU_ACTION:
2232		ret = NULL;
2233		ms->rpz_passthru = 1;
2234		break;
2235	default:
2236		verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
2237			rpz_action_to_string(action));
2238		ret = NULL;
2239	}
2240
2241	if(r->log)
2242		log_rpz_apply("nsdname", match->dname, NULL,
2243			action, &ms->qinfo, NULL, ms, r->log_name);
2244	if(ms->env->worker)
2245		ms->env->worker->stats.rpz_action[action]++;
2246	lock_rw_unlock(&z->lock);
2247	return ret;
2248}
2249
2250static struct local_zone*
2251rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
2252	uint16_t qclass,
2253	/* output parameter */
2254	struct matched_delegation_point* match)
2255{
2256	struct delegpt_ns* nameserver;
2257	struct local_zone* z = NULL;
2258
2259	/* the rpz specs match the nameserver names (NS records), not the
2260	 * name of the delegation point itself, to the nsdname triggers */
2261	for(nameserver = dp->nslist;
2262	    nameserver != NULL;
2263	    nameserver = nameserver->next) {
2264		z = rpz_find_zone(zones, nameserver->name, nameserver->namelen,
2265				  qclass, 0, 0, 0);
2266		if(z != NULL) {
2267			match->dname = nameserver->name;
2268			match->dname_len = nameserver->namelen;
2269			if(verbosity >= VERB_ALGO) {
2270				char nm[255+1], zn[255+1];
2271				dname_str(match->dname, nm);
2272				dname_str(z->name, zn);
2273				if(strcmp(nm, zn) != 0)
2274					verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s",
2275						zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2276				else
2277					verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s",
2278						nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type)));
2279			}
2280			break;
2281		}
2282	}
2283
2284	return z;
2285}
2286
2287struct dns_msg*
2288rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is)
2289{
2290	struct auth_zones* az;
2291	struct auth_zone* a;
2292	struct clientip_synthesized_rr* raddr = NULL;
2293	struct rpz* r = NULL;
2294	struct local_zone* z = NULL;
2295	struct matched_delegation_point match = {0};
2296
2297	if(ms->rpz_passthru) {
2298		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2299		return NULL;
2300	}
2301
2302	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2303
2304	az = ms->env->auth_zones;
2305
2306	verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
2307
2308	lock_rw_rdlock(&az->rpz_lock);
2309
2310	/* precedence of RPZ works, loosely, like this:
2311	 * CNAMEs in order of the CNAME chain. rpzs in the order they are
2312	 * configured. In an RPZ: first client-IP addr, then QNAME, then
2313	 * response IP, then NSDNAME, then NSIP. Longest match first. Smallest
2314	 * one from a set. */
2315	/* we use the precedence rules for the topics and triggers that
2316	 * are pertinent at this stage of the resolve processing */
2317	for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) {
2318		lock_rw_rdlock(&a->lock);
2319		r = a->rpz;
2320		if(r->disabled) {
2321			lock_rw_unlock(&a->lock);
2322			continue;
2323		}
2324
2325		/* the nsdname has precedence over the nsip triggers */
2326		z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
2327						     ms->qinfo.qclass, &match);
2328		if(z != NULL) {
2329			lock_rw_unlock(&a->lock);
2330			break;
2331		}
2332
2333		raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
2334		if(raddr != NULL) {
2335			lock_rw_unlock(&a->lock);
2336			break;
2337		}
2338		lock_rw_unlock(&a->lock);
2339	}
2340
2341	lock_rw_unlock(&az->rpz_lock);
2342
2343	if(raddr == NULL && z == NULL)
2344		return NULL;
2345
2346	if(raddr != NULL) {
2347		if(z) {
2348			lock_rw_unlock(&z->lock);
2349		}
2350		return rpz_apply_nsip_trigger(ms, r, raddr, a);
2351	}
2352	return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
2353}
2354
2355struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
2356	struct iter_qstate* is)
2357{
2358	struct auth_zones* az;
2359	struct auth_zone* a = NULL;
2360	struct rpz* r = NULL;
2361	struct local_zone* z = NULL;
2362	enum localzone_type lzt;
2363	struct dns_msg* ret = NULL;
2364
2365	if(ms->rpz_passthru) {
2366		verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
2367		return NULL;
2368	}
2369
2370	if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
2371	az = ms->env->auth_zones;
2372
2373	lock_rw_rdlock(&az->rpz_lock);
2374
2375	for(a = az->rpz_first; a; a = a->rpz_az_next) {
2376		lock_rw_rdlock(&a->lock);
2377		r = a->rpz;
2378		if(r->disabled) {
2379			lock_rw_unlock(&a->lock);
2380			continue;
2381		}
2382		z = rpz_find_zone(r->local_zones, is->qchase.qname,
2383			is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
2384		if(z && r->action_override == RPZ_DISABLED_ACTION) {
2385			if(r->log)
2386				log_rpz_apply("qname", z->name, NULL,
2387					r->action_override,
2388					&ms->qinfo, NULL, ms, r->log_name);
2389			if(ms->env->worker)
2390				ms->env->worker->stats.rpz_action[r->action_override]++;
2391			lock_rw_unlock(&z->lock);
2392			z = NULL;
2393		}
2394		if(z) {
2395			break;
2396		}
2397		/* not found in this auth_zone */
2398		lock_rw_unlock(&a->lock);
2399	}
2400	lock_rw_unlock(&az->rpz_lock);
2401
2402	if(z == NULL)
2403		return NULL;
2404	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2405		lzt = z->type;
2406	} else {
2407		lzt = rpz_action_to_localzone_type(r->action_override);
2408	}
2409
2410	if(verbosity >= VERB_ALGO) {
2411		char nm[255+1], zn[255+1];
2412		dname_str(is->qchase.qname, nm);
2413		dname_str(z->name, zn);
2414		if(strcmp(zn, nm) != 0)
2415			verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
2416				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2417		else
2418			verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
2419				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2420	}
2421	switch(localzone_type_to_rpz_action(lzt)) {
2422	case RPZ_NXDOMAIN_ACTION:
2423		ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
2424		break;
2425	case RPZ_NODATA_ACTION:
2426		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2427		break;
2428	case RPZ_TCP_ONLY_ACTION:
2429		/* basically a passthru here but the tcp-only will be
2430		 * honored before the query gets sent. */
2431		ms->tcp_required = 1;
2432		ret = NULL;
2433		break;
2434	case RPZ_DROP_ACTION:
2435		ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
2436		ms->is_drop = 1;
2437		break;
2438	case RPZ_LOCAL_DATA_ACTION:
2439		ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
2440		if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
2441		break;
2442	case RPZ_PASSTHRU_ACTION:
2443		ret = NULL;
2444		ms->rpz_passthru = 1;
2445		break;
2446	default:
2447		verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
2448			rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2449		ret = NULL;
2450	}
2451	if(r->log)
2452		log_rpz_apply("qname", (z?z->name:NULL), NULL,
2453			localzone_type_to_rpz_action(lzt),
2454			&is->qchase, NULL, ms, r->log_name);
2455	lock_rw_unlock(&z->lock);
2456	lock_rw_unlock(&a->lock);
2457	return ret;
2458}
2459
2460static int
2461rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
2462	struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo,
2463	uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
2464	sldns_buffer* buf, struct regional* temp,
2465	/* output parameters */
2466	struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
2467	int* passthru)
2468{
2469	int ret = 0;
2470	enum rpz_action client_action;
2471	struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone(
2472		az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
2473
2474	client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
2475	if(client_action == RPZ_PASSTHRU_ACTION) {
2476		*passthru = 1;
2477	}
2478	if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
2479			      client_action != RPZ_PASSTHRU_ACTION)) {
2480		if(client_action == RPZ_PASSTHRU_ACTION
2481			|| client_action == RPZ_INVALID_ACTION
2482			|| (client_action == RPZ_TCP_ONLY_ACTION
2483				&& !rpz_is_udp_query(repinfo))) {
2484			ret = 0;
2485			goto done;
2486		}
2487		stats->rpz_action[client_action]++;
2488		if(client_action == RPZ_LOCAL_DATA_ACTION) {
2489			rpz_apply_clientip_localdata_action(node, env, qinfo,
2490				edns, repinfo, buf, temp, *a_out);
2491		} else {
2492			if(*r_out && (*r_out)->log)
2493				log_rpz_apply(
2494					(node?"clientip":"qname"),
2495					((*z_out)?(*z_out)->name:NULL),
2496					(node?&node->node:NULL),
2497					client_action, qinfo, repinfo, NULL,
2498					(*r_out)->log_name);
2499			local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
2500				repinfo, buf, temp, 0 /* no local data used */,
2501				rpz_action_to_localzone_type(client_action));
2502			if(*r_out && (*r_out)->signal_nxdomain_ra &&
2503				LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
2504				== LDNS_RCODE_NXDOMAIN)
2505				LDNS_RA_CLR(sldns_buffer_begin(buf));
2506		}
2507		ret = 1;
2508		goto done;
2509	}
2510	ret = -1;
2511done:
2512	if(node != NULL) {
2513		lock_rw_unlock(&node->lock);
2514	}
2515	return ret;
2516}
2517
2518int
2519rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
2520	struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
2521	struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
2522	size_t taglen, struct ub_server_stats* stats, int* passthru)
2523{
2524	struct rpz* r = NULL;
2525	struct auth_zone* a = NULL;
2526	struct local_zone* z = NULL;
2527	int ret;
2528	enum localzone_type lzt;
2529
2530	int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
2531		edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
2532		passthru);
2533	if(clientip_trigger >= 0) {
2534		if(a) {
2535			lock_rw_unlock(&a->lock);
2536		}
2537		if(z) {
2538			lock_rw_unlock(&z->lock);
2539		}
2540		return clientip_trigger;
2541	}
2542
2543	if(z == NULL) {
2544		if(a) {
2545			lock_rw_unlock(&a->lock);
2546		}
2547		return 0;
2548	}
2549
2550	log_assert(r);
2551
2552	if(r->action_override == RPZ_NO_OVERRIDE_ACTION) {
2553		lzt = z->type;
2554	} else {
2555		lzt = rpz_action_to_localzone_type(r->action_override);
2556	}
2557	if(r->action_override == RPZ_PASSTHRU_ACTION ||
2558		lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
2559		*passthru = 1;
2560	}
2561
2562	if(verbosity >= VERB_ALGO) {
2563		char nm[255+1], zn[255+1];
2564		dname_str(qinfo->qname, nm);
2565		dname_str(z->name, zn);
2566		if(strcmp(zn, nm) != 0)
2567			verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s",
2568				zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2569		else
2570			verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s",
2571				nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
2572	}
2573
2574	ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp,
2575					     repinfo, stats);
2576
2577	lock_rw_unlock(&z->lock);
2578	lock_rw_unlock(&a->lock);
2579
2580	return ret;
2581}
2582
2583void rpz_enable(struct rpz* r)
2584{
2585    if(!r)
2586        return;
2587    r->disabled = 0;
2588}
2589
2590void rpz_disable(struct rpz* r)
2591{
2592    if(!r)
2593        return;
2594    r->disabled = 1;
2595}
2596