xref: /freebsd/contrib/unbound/edns-subnet/subnetmod.c (revision 5fa84c6ec176d186ddad25d31f8760e50f48157f)
1 /*
2  * edns-subnet/subnetmod.c - edns subnet module. Must be called before validator
3  * and iterator.
4  *
5  * Copyright (c) 2013, NLnet Labs. All rights reserved.
6  *
7  * This software is open source.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * Redistributions of source code must retain the above copyright notice,
14  * this list of conditions and the following disclaimer.
15  *
16  * Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  *
20  * Neither the name of the NLNET LABS nor the names of its contributors may
21  * be used to endorse or promote products derived from this software without
22  * specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36  /**
37  * \file
38  * subnet module for unbound.
39  */
40 
41 #include "config.h"
42 
43 #ifdef CLIENT_SUBNET /* keeps splint happy */
44 
45 #include "edns-subnet/subnetmod.h"
46 #include "edns-subnet/edns-subnet.h"
47 #include "edns-subnet/addrtree.h"
48 #include "edns-subnet/subnet-whitelist.h"
49 
50 #include "services/mesh.h"
51 #include "services/cache/dns.h"
52 #include "util/module.h"
53 #include "util/regional.h"
54 #include "util/fptr_wlist.h"
55 #include "util/storage/slabhash.h"
56 #include "util/config_file.h"
57 #include "util/data/msgreply.h"
58 #include "sldns/sbuffer.h"
59 #include "sldns/wire2str.h"
60 #include "iterator/iter_utils.h"
61 #ifdef USE_CACHEDB
62 #include "cachedb/cachedb.h"
63 #endif
64 
65 /** externally called */
66 void
subnet_data_delete(void * d,void * ATTR_UNUSED (arg))67 subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
68 {
69 	struct subnet_msg_cache_data *r;
70 	r = (struct subnet_msg_cache_data*)d;
71 	addrtree_delete(r->tree4);
72 	addrtree_delete(r->tree6);
73 	free(r->reason_fail);
74 	free(r);
75 }
76 
77 /** externally called */
78 size_t
msg_cache_sizefunc(void * k,void * d)79 msg_cache_sizefunc(void *k, void *d)
80 {
81 	struct msgreply_entry *q = (struct msgreply_entry*)k;
82 	struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
83 	size_t s = sizeof(struct msgreply_entry)
84 		+ sizeof(struct subnet_msg_cache_data)
85 		+ q->key.qname_len + lock_get_mem(&q->entry.lock);
86 	s += addrtree_size(r->tree4);
87 	s += addrtree_size(r->tree6);
88 	if(r->reason_fail)
89 		s += strlen(r->reason_fail)+1;
90 	return s;
91 }
92 
93 /** new query for ecs module */
94 static int
subnet_new_qstate(struct module_qstate * qstate,int id)95 subnet_new_qstate(struct module_qstate *qstate, int id)
96 {
97 	struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
98 		qstate->region, sizeof(struct subnet_qstate));
99 	if(!sq)
100 		return 0;
101 	qstate->minfo[id] = sq;
102 	memset(sq, 0, sizeof(*sq));
103 	sq->started_no_cache_store = qstate->no_cache_store;
104 	sq->started_no_cache_lookup = qstate->no_cache_lookup;
105 	return 1;
106 }
107 
108 /** Add ecs struct to edns list, after parsing it to wire format. */
109 void
subnet_ecs_opt_list_append(struct ecs_data * ecs,struct edns_option ** list,struct module_qstate * qstate,struct regional * region)110 subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
111 	struct module_qstate *qstate, struct regional *region)
112 {
113 	size_t sn_octs, sn_octs_remainder;
114 	sldns_buffer* buf = qstate->env->scratch_buffer;
115 
116 	if(ecs->subnet_validdata) {
117 		log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
118 			ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
119 		log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
120 			ecs->subnet_source_mask <=  INET_SIZE*8);
121 		log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
122 			ecs->subnet_source_mask <= INET6_SIZE*8);
123 
124 		sn_octs = ecs->subnet_source_mask / 8;
125 		sn_octs_remainder =
126 			(size_t)((ecs->subnet_source_mask % 8)>0?1:0);
127 
128 		log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
129 
130 		sldns_buffer_clear(buf);
131 		sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
132 		sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
133 		sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
134 		sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
135 		if(sn_octs_remainder)
136 			sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
137 				~(0xFF >> (ecs->subnet_source_mask % 8)));
138 		sldns_buffer_flip(buf);
139 
140 		edns_opt_list_append(list,
141 				qstate->env->cfg->client_subnet_opcode,
142 				sn_octs + sn_octs_remainder + 4,
143 				sldns_buffer_begin(buf), region);
144 	}
145 }
146 
ecs_whitelist_check(struct query_info * qinfo,uint16_t ATTR_UNUSED (flags),struct module_qstate * qstate,struct sockaddr_storage * addr,socklen_t addrlen,uint8_t * ATTR_UNUSED (zone),size_t ATTR_UNUSED (zonelen),struct regional * region,int id,void * ATTR_UNUSED (cbargs))147 int ecs_whitelist_check(struct query_info* qinfo,
148 	uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
149 	struct sockaddr_storage* addr, socklen_t addrlen,
150 	uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
151 	struct regional *region, int id, void* ATTR_UNUSED(cbargs))
152 {
153 	struct subnet_qstate *sq;
154 	struct subnet_env *sn_env;
155 
156 	if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
157 		return 1;
158 	sn_env = (struct subnet_env*)qstate->env->modinfo[id];
159 
160 	if(sq->is_subquery_nonsubnet) {
161 		if(sq->is_subquery_scopezero) {
162 			/* Check if the result can be stored in the global cache,
163 			 * this is okay if the address and name are not configured
164 			 * as subnet address and subnet zone. */
165 			if(!ecs_is_whitelisted(sn_env->whitelist,
166 				addr, addrlen, qinfo->qname, qinfo->qname_len,
167 				qinfo->qclass)) {
168 				/* The stub or forward can have no_cache set.*/
169 				if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
170 					verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache");
171 				} else {
172 					verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s",
173 						(sq->started_no_cache_store?
174 						" But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":""));
175 					qstate->no_cache_store = sq->started_no_cache_store;
176 				}
177 			}
178 		}
179 		return 1;
180 	}
181 
182 	/* Cache by default, might be disabled after parsing EDNS option
183 	 * received from nameserver. */
184 	if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
185 		&& sq->ecs_client_in.subnet_validdata) {
186 		qstate->no_cache_store = 0;
187 	}
188 
189 	sq->subnet_sent_no_subnet = 0;
190 	if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
191 		qstate->env->cfg->client_subnet_always_forward) ||
192 		ecs_is_whitelisted(sn_env->whitelist,
193 		addr, addrlen, qinfo->qname, qinfo->qname_len,
194 		qinfo->qclass))) {
195 		/* Address on whitelist or client query contains ECS option, we
196 		 * want to sent out ECS. Only add option if it is not already
197 		 * set. */
198 		if(!edns_opt_list_find(qstate->edns_opts_back_out,
199 			qstate->env->cfg->client_subnet_opcode)) {
200 			/* if the client is not wanting an EDNS subnet option,
201 			 * omit it and store that we omitted it but actually
202 			 * are doing EDNS subnet to the server. */
203 			if(sq->ecs_server_out.subnet_source_mask == 0) {
204 				sq->subnet_sent_no_subnet = 1;
205 				sq->subnet_sent = 0;
206 				/* The result should end up in subnet cache,
207 				 * not in global cache. */
208 				qstate->no_cache_store = 1;
209 				return 1;
210 			}
211 			subnet_ecs_opt_list_append(&sq->ecs_server_out,
212 				&qstate->edns_opts_back_out, qstate, region);
213 		}
214 		sq->subnet_sent = 1;
215 		/* Do not store servfails in global cache, since the subnet
216 		 * option is sent out. */
217 		qstate->no_cache_store = 1;
218 	}
219 	else {
220 		/* Outgoing ECS option is set, but we don't want to sent it to
221 		 * this address, remove option. */
222 		if(edns_opt_list_find(qstate->edns_opts_back_out,
223 			qstate->env->cfg->client_subnet_opcode)) {
224 			edns_opt_list_remove(&qstate->edns_opts_back_out,
225 				qstate->env->cfg->client_subnet_opcode);
226 		}
227 		sq->subnet_sent = 0;
228 	}
229 	return 1;
230 }
231 
232 
233 void
subnet_markdel(void * key)234 subnet_markdel(void* key)
235 {
236 	struct msgreply_entry *e = (struct msgreply_entry*)key;
237 	e->key.qtype = 0;
238 	e->key.qclass = 0;
239 }
240 
241 int
subnetmod_init(struct module_env * env,int id)242 subnetmod_init(struct module_env *env, int id)
243 {
244 	struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
245 		sizeof(struct subnet_env));
246 	if(!sn_env) {
247 		log_err("malloc failure");
248 		return 0;
249 	}
250 	alloc_init(&sn_env->alloc, NULL, 0);
251 	env->modinfo[id] = (void*)sn_env;
252 
253 	/* Warn that serve-expired and prefetch do not work with the subnet
254 	 * module cache. */
255 	if(env->cfg->serve_expired)
256 		log_warn(
257 			"subnetcache: serve-expired is set but not working "
258 			"for data originating from the subnet module cache.");
259 	if(env->cfg->prefetch)
260 		log_warn(
261 			"subnetcache: prefetch is set but not working "
262 			"for data originating from the subnet module cache.");
263 	/* Copy msg_cache settings */
264 	sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
265 		HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
266 		msg_cache_sizefunc, query_info_compare, query_entry_delete,
267 		subnet_data_delete, NULL);
268 	if(!sn_env->subnet_msg_cache) {
269 		log_err("subnetcache: could not create cache");
270 		free(sn_env);
271 		env->modinfo[id] = NULL;
272 		return 0;
273 	}
274 	slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
275 	/* whitelist for edns subnet capable servers */
276 	sn_env->whitelist = ecs_whitelist_create();
277 	if(!sn_env->whitelist ||
278 		!ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
279 		log_err("subnetcache: could not create ECS whitelist");
280 		slabhash_delete(sn_env->subnet_msg_cache);
281 		free(sn_env);
282 		env->modinfo[id] = NULL;
283 		return 0;
284 	}
285 
286 	verbose(VERB_QUERY, "subnetcache: option registered (%d)",
287 		env->cfg->client_subnet_opcode);
288 	/* Create new mesh state for all queries. */
289 	env->unique_mesh = 1;
290 	if(!edns_register_option(env->cfg->client_subnet_opcode,
291 		env->cfg->client_subnet_always_forward /* bypass cache */,
292 		1 /* no aggregation */, env)) {
293 		log_err("subnetcache: could not register opcode");
294 		ecs_whitelist_delete(sn_env->whitelist);
295 		slabhash_delete(sn_env->subnet_msg_cache);
296 		free(sn_env);
297 		env->modinfo[id] = NULL;
298 		return 0;
299 	}
300 	inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
301 		env, id);
302 	inplace_cb_register((void*)ecs_edns_back_parsed,
303 		inplace_cb_edns_back_parsed, NULL, env, id);
304 	inplace_cb_register((void*)ecs_query_response,
305 		inplace_cb_query_response, NULL, env, id);
306 	lock_rw_init(&sn_env->biglock);
307 	return 1;
308 }
309 
310 void
subnetmod_deinit(struct module_env * env,int id)311 subnetmod_deinit(struct module_env *env, int id)
312 {
313 	struct subnet_env *sn_env;
314 	if(!env || !env->modinfo[id])
315 		return;
316 	sn_env = (struct subnet_env*)env->modinfo[id];
317 	lock_rw_destroy(&sn_env->biglock);
318 	inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
319 	inplace_cb_delete(env, inplace_cb_query, id);
320 	inplace_cb_delete(env, inplace_cb_query_response, id);
321 	ecs_whitelist_delete(sn_env->whitelist);
322 	slabhash_delete(sn_env->subnet_msg_cache);
323 	alloc_clear(&sn_env->alloc);
324 	free(sn_env);
325 	env->modinfo[id] = NULL;
326 }
327 
328 /** Tells client that upstream has no/improper support */
329 static void
cp_edns_bad_response(struct ecs_data * target,struct ecs_data * source)330 cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
331 {
332 	target->subnet_scope_mask  = 0;
333 	target->subnet_source_mask = source->subnet_source_mask;
334 	target->subnet_addr_fam    = source->subnet_addr_fam;
335 	memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
336 	target->subnet_validdata = 1;
337 }
338 
339 static void
delfunc(void * envptr,void * elemptr)340 delfunc(void *envptr, void *elemptr) {
341 	struct reply_info *elem = (struct reply_info *)elemptr;
342 	struct subnet_env *env = (struct subnet_env *)envptr;
343 	reply_info_parsedelete(elem, &env->alloc);
344 }
345 
346 static size_t
sizefunc(void * elemptr)347 sizefunc(void *elemptr) {
348 	struct reply_info *elem  = (struct reply_info *)elemptr;
349 	size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
350 		+ elem->rrset_count * sizeof (struct rrset_ref)
351 		+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
352 	size_t i;
353 	for (i = 0; i < elem->rrset_count; i++) {
354 		struct ub_packed_rrset_key *key = elem->rrsets[i];
355 		struct packed_rrset_data *data = key->entry.data;
356 		s += ub_rrset_sizefunc(key, data);
357 	}
358 	if(elem->reason_bogus_str)
359 		s += strlen(elem->reason_bogus_str)+1;
360 	return s;
361 }
362 
363 /**
364  * Select tree from cache entry based on edns data.
365  * If for address family not present it will create a new one.
366  * NULL on failure to create. */
367 static struct addrtree*
get_tree(struct subnet_msg_cache_data * data,struct ecs_data * edns,struct subnet_env * env,struct config_file * cfg)368 get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
369 	struct subnet_env *env, struct config_file* cfg)
370 {
371 	struct addrtree *tree;
372 	if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
373 		if (!data->tree4)
374 			data->tree4 = addrtree_create(
375 				cfg->max_client_subnet_ipv4, &delfunc,
376 				&sizefunc, env, cfg->max_ecs_tree_size_ipv4);
377 		tree = data->tree4;
378 	} else {
379 		if (!data->tree6)
380 			data->tree6 = addrtree_create(
381 				cfg->max_client_subnet_ipv6, &delfunc,
382 				&sizefunc, env, cfg->max_ecs_tree_size_ipv6);
383 		tree = data->tree6;
384 	}
385 	return tree;
386 }
387 
388 static void
update_cache(struct module_qstate * qstate,int id)389 update_cache(struct module_qstate *qstate, int id)
390 {
391 	struct msgreply_entry *mrep_entry;
392 	struct addrtree *tree;
393 	struct reply_info *rep;
394 	struct query_info qinf;
395 	struct subnet_env *sne = qstate->env->modinfo[id];
396 	struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
397 	struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
398 	struct ecs_data *edns = &sq->ecs_client_in;
399 	size_t i;
400 	int only_match_scope_zero, diff_size;
401 
402 	/* We already calculated hash upon lookup (lookup_and_reply) if we were
403 	 * allowed to look in the ECS cache */
404 	hashvalue_type h = qstate->minfo[id] &&
405 		((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
406 		((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
407 		query_info_hash(&qstate->qinfo, qstate->query_flags);
408 	/* Step 1, general qinfo lookup */
409 	struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
410 		&qstate->qinfo, 1);
411 	int need_to_insert = (lru_entry == NULL);
412 	if (!lru_entry) {
413 		void* data = calloc(1,
414 			sizeof(struct subnet_msg_cache_data));
415 		if(!data) {
416 			log_err("malloc failed");
417 			return;
418 		}
419 		qinf = qstate->qinfo;
420 		qinf.qname = memdup(qstate->qinfo.qname,
421 			qstate->qinfo.qname_len);
422 		if(!qinf.qname) {
423 			free(data);
424 			log_err("memdup failed");
425 			return;
426 		}
427 		mrep_entry = query_info_entrysetup(&qinf, data, h);
428 		free(qinf.qname); /* if qname 'consumed', it is set to NULL */
429 		if (!mrep_entry) {
430 			free(data);
431 			log_err("query_info_entrysetup failed");
432 			return;
433 		}
434 		lru_entry = &mrep_entry->entry;
435 		lock_rw_wrlock(&lru_entry->lock);
436 	}
437 	/* lru_entry->lock is locked regardless of how we got here,
438 	 * either from the slabhash_lookup, or above in the new allocated */
439 	if(!qstate->return_msg && qstate->error_response_cache) {
440 		struct subnet_msg_cache_data *data =
441 			(struct subnet_msg_cache_data*)lru_entry->data;
442 		data->ttl_servfail = *qstate->env->now + NORR_TTL;
443 		data->ede_fail = errinf_to_reason_bogus(qstate);
444 		diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0);
445 		if(qstate->errinf) {
446 			char* str = errinf_to_str_misc(qstate);
447 			free(data->reason_fail);
448 			data->reason_fail = NULL;
449 			if(str)
450 				data->reason_fail = strdup(str);
451 		}
452 		diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0)
453 			- diff_size;
454 		lock_rw_unlock(&lru_entry->lock);
455 		if (need_to_insert) {
456 			slabhash_insert(subnet_msg_cache, h, lru_entry,
457 				lru_entry->data, NULL);
458 		} else {
459 			slabhash_update_space_used(subnet_msg_cache, h, NULL,
460 				diff_size);
461 		}
462 		return;
463 	}
464 	if(!qstate->return_msg) {
465 		lock_rw_unlock(&lru_entry->lock);
466 		return;
467 	}
468 	/* Step 2, find the correct tree */
469 	if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
470 		lock_rw_unlock(&lru_entry->lock);
471 		log_err("subnetcache: cache insertion failed");
472 		return;
473 	}
474 	lock_quick_lock(&sne->alloc.lock);
475 	rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
476 	lock_quick_unlock(&sne->alloc.lock);
477 	if (!rep) {
478 		lock_rw_unlock(&lru_entry->lock);
479 		log_err("subnetcache: cache insertion failed");
480 		return;
481 	}
482 
483 	/* store RRsets */
484 	for(i=0; i<rep->rrset_count; i++) {
485 		rep->ref[i].key = rep->rrsets[i];
486 		rep->ref[i].id = rep->rrsets[i]->id;
487 	}
488 	reply_info_set_ttls(rep, *qstate->env->now);
489 	reply_info_sortref(rep);
490 	rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
491 	rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache   */
492 	if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
493 		only_match_scope_zero = 1;
494 	else only_match_scope_zero = 0;
495 	diff_size = (int)tree->size_bytes;
496 	addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
497 		edns->subnet_source_mask, sq->max_scope, rep,
498 		rep->ttl, *qstate->env->now, only_match_scope_zero);
499 	diff_size = (int)tree->size_bytes - diff_size;
500 
501 	lock_rw_unlock(&lru_entry->lock);
502 	if (need_to_insert) {
503 		slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
504 			NULL);
505 	} else {
506 		slabhash_update_space_used(subnet_msg_cache, h, NULL,
507 			diff_size);
508 	}
509 }
510 
511 /** See if there is a stored servfail, returns true if so, and sets reply. */
512 static int
lookup_check_servfail(struct module_qstate * qstate,struct subnet_msg_cache_data * data)513 lookup_check_servfail(struct module_qstate *qstate,
514 	struct subnet_msg_cache_data *data)
515 {
516 	struct module_env *env = qstate->env;
517 	if(!data)
518 		return 0;
519 	if(!data->ttl_servfail || TTL_IS_EXPIRED(data->ttl_servfail, *env->now))
520 		return 0;
521 	qstate->return_rcode = LDNS_RCODE_SERVFAIL;
522 	errinf_ede(qstate, data->reason_fail, data->ede_fail);
523 	return 1;
524 }
525 
526 /** Lookup in cache and reply true iff reply is sent. */
527 static int
lookup_and_reply(struct module_qstate * qstate,int id,struct subnet_qstate * sq,int prefetch)528 lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
529 {
530 	struct lruhash_entry *e;
531 	struct module_env *env = qstate->env;
532 	struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
533 	hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
534 	struct subnet_msg_cache_data *data;
535 	struct ecs_data *ecs = &sq->ecs_client_in;
536 	struct addrtree *tree;
537 	struct addrnode *node;
538 	uint8_t scope;
539 	int must_validate = (!(qstate->query_flags&BIT_CD)
540 		|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
541 
542 	memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
543 
544 	if (sq) {
545 		sq->qinfo_hash = h; /* Might be useful on cache miss */
546 		sq->qinfo_hash_calculated = 1;
547 	}
548 	e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
549 	if (!e) return 0; /* qinfo not in cache */
550 	data = e->data;
551 	tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
552 		data->tree4 : data->tree6;
553 	if (!tree) { /* qinfo in cache but not for this family */
554 		if(lookup_check_servfail(qstate, data)) {
555 			lock_rw_unlock(&e->lock);
556 			return 1;
557 		}
558 		lock_rw_unlock(&e->lock);
559 		return 0;
560 	}
561 	node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
562 		ecs->subnet_source_mask, *env->now);
563 	if (!node) { /* plain old cache miss */
564 		if(lookup_check_servfail(qstate, data)) {
565 			lock_rw_unlock(&e->lock);
566 			return 1;
567 		}
568 		lock_rw_unlock(&e->lock);
569 		return 0;
570 	}
571 
572 	qstate->return_msg = tomsg(NULL, &qstate->qinfo,
573 		(struct reply_info *)node->elem, qstate->region, *env->now, 0,
574 		env->scratch);
575 	scope = (uint8_t)node->scope;
576 
577 	if (!qstate->return_msg) { /* Failed allocation or expired TTL */
578 		if(lookup_check_servfail(qstate, data)) {
579 			lock_rw_unlock(&e->lock);
580 			return 1;
581 		}
582 		lock_rw_unlock(&e->lock);
583 		return 0;
584 	}
585 	lock_rw_unlock(&e->lock);
586 	if(qstate->return_msg->rep->security == sec_status_unchecked
587 		&& must_validate) {
588 		/* The message has to be validated first. */
589 		verbose(VERB_ALGO, "subnet: unchecked cache entry needs "
590 			"validation");
591 		return 0;
592 	}
593 
594 	if (sq->subnet_downstream) { /* relay to interested client */
595 		sq->ecs_client_out.subnet_scope_mask = scope;
596 		sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
597 		sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
598 		memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
599 			INET6_SIZE);
600 		sq->ecs_client_out.subnet_validdata = 1;
601 	}
602 
603 	if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) {
604 		qstate->need_refetch = 1;
605 	}
606 	return 1;
607 }
608 
609 /**
610  * Test first bits of addresses for equality. Caller is responsible
611  * for making sure that both a and b are at least net/8 octets long.
612  * @param a: first address.
613  * @param a: seconds address.
614  * @param net: Number of bits to test.
615  * @return: 1 if equal, 0 otherwise.
616  */
617 static int
common_prefix(uint8_t * a,uint8_t * b,uint8_t net)618 common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
619 {
620 	size_t n = (size_t)net / 8;
621 	return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
622 }
623 
624 /**
625  * Create sub request that looks up the query.
626  * @param qstate: query state
627  * @param id: module id.
628  * @param sq: subnet qstate
629  * @return false on failure.
630  */
631 static int
generate_sub_request(struct module_qstate * qstate,int id,struct subnet_qstate * sq)632 generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq)
633 {
634 	struct module_qstate* subq = NULL;
635 	uint16_t qflags = 0; /* OPCODE QUERY, no flags */
636 	int prime = 0;
637 	int valrec = 0;
638 	struct query_info qinf;
639 	qinf.qname = qstate->qinfo.qname;
640 	qinf.qname_len = qstate->qinfo.qname_len;
641 	qinf.qtype = qstate->qinfo.qtype;
642 	qinf.qclass = qstate->qinfo.qclass;
643 	qinf.local_alias = NULL;
644 
645 	qflags |= BIT_RD;
646 	if((qstate->query_flags & BIT_CD)!=0) {
647 		qflags |= BIT_CD;
648 		/* The valrec is left off. Leave out: valrec = 1;
649 		 * So that the cache is protected with DNSSEC validation.
650 		 * Just like the global cache. DNSSEC validation is performed
651 		 * regardless of the setting of the querier's CD flag. */
652 	}
653 
654 	fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
655 	if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info,
656 		qflags, prime, valrec, &subq)) {
657 		return 0;
658 	}
659 	if(subq) {
660 		/* It is possible to access the subquery module state. */
661 		struct subnet_qstate* subsq;
662 		if(!subnet_new_qstate(subq, id)) {
663 			verbose(VERB_ALGO, "Could not allocate new subnet qstate");
664 			return 0;
665 		}
666 		subsq = (struct subnet_qstate*)subq->minfo[id];
667 		subsq->is_subquery_nonsubnet = 1;
668 		subsq->started_no_cache_store = sq->started_no_cache_store;
669 
670 		/* When the client asks 0.0.0.0/0 and the name is not treated
671 		 * as subnet, it is to be stored in the global cache.
672 		 * Store that the client asked for that, if so. */
673 		if(sq->ecs_client_in.subnet_source_mask == 0 &&
674 			edns_opt_list_find(qstate->edns_opts_front_in,
675 				qstate->env->cfg->client_subnet_opcode)) {
676 			subq->no_cache_store = 1;
677 			subsq->is_subquery_scopezero = 1;
678 		}
679 	}
680 	return 1;
681 }
682 
683 /**
684  * Perform the query without subnet
685  * @param qstate: query state
686  * @param id: module id.
687  * @param sq: subnet qstate
688  * @return module state
689  */
690 static enum module_ext_state
generate_lookup_without_subnet(struct module_qstate * qstate,int id,struct subnet_qstate * sq)691 generate_lookup_without_subnet(struct module_qstate *qstate, int id,
692 	struct subnet_qstate* sq)
693 {
694 	verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
695 	if(!generate_sub_request(qstate, id, sq)) {
696 		verbose(VERB_ALGO, "Could not generate sub query");
697 		qstate->return_rcode = LDNS_RCODE_SERVFAIL;
698 		qstate->return_msg = NULL;
699 		return module_finished;
700 	}
701 	sq->wait_subquery = 1;
702 	return module_wait_subquery;
703 }
704 
705 static enum module_ext_state
eval_response(struct module_qstate * qstate,int id,struct subnet_qstate * sq)706 eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
707 {
708 	struct subnet_env *sne = qstate->env->modinfo[id];
709 
710 	struct ecs_data *c_in  = &sq->ecs_client_in; /* rcvd from client */
711 	struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
712 	struct ecs_data *s_in  = &sq->ecs_server_in; /* rcvd from auth */
713 	struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
714 
715 	memset(c_out, 0, sizeof(*c_out));
716 
717 	if (!qstate->return_msg) {
718 		/* already an answer and its not a message, but retain
719 		 * the actual rcode, instead of module_error, so send
720 		 * module_finished */
721 		if(qstate->error_response_cache) {
722 			verbose(VERB_ALGO, "subnet: store error response");
723 			lock_rw_wrlock(&sne->biglock);
724 			update_cache(qstate, id);
725 			lock_rw_unlock(&sne->biglock);
726 		}
727 		return module_finished;
728 	}
729 
730 	/* We have not asked for subnet data */
731 	if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
732 		if (s_in->subnet_validdata)
733 			verbose(VERB_QUERY, "subnetcache: received spurious data");
734 		if (sq->subnet_downstream) /* Copy back to client */
735 			cp_edns_bad_response(c_out, c_in);
736 		return module_finished;
737 	}
738 
739 	/* subnet sent but nothing came back */
740 	if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
741 		/* The authority indicated no support for edns subnet. As a
742 		 * consequence the answer ended up in the regular cache. It
743 		 * is still useful to put it in the edns subnet cache for
744 		 * when a client explicitly asks for subnet specific answer. */
745 		verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
746 		return generate_lookup_without_subnet(qstate, id, sq);
747 	}
748 
749 	/* Purposefully there was no sent subnet, and there is consequently
750 	 * no subnet in the answer. If there was, use the subnet in the answer
751 	 * anyway. But if there is not, treat it as a prefix 0 answer. */
752 	if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
753 		/* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
754 		s_in->subnet_addr_fam = s_out->subnet_addr_fam;
755 		s_in->subnet_source_mask = 0;
756 		s_in->subnet_scope_mask = 0;
757 		memset(s_in->subnet_addr, 0, INET6_SIZE);
758 		s_in->subnet_validdata = 1;
759 	}
760 
761 	/* Being here means we have asked for and got a subnet specific
762 	 * answer. Also, the answer from the authority is not yet cached
763 	 * anywhere. */
764 
765 	/* can we accept response? */
766 	if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
767 		s_out->subnet_source_mask != s_in->subnet_source_mask ||
768 		!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
769 			s_out->subnet_source_mask))
770 	{
771 		/* we can not accept, perform query without option */
772 		verbose(VERB_QUERY, "subnetcache: forged data");
773 		s_out->subnet_validdata = 0;
774 		(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
775 			qstate->env->cfg->client_subnet_opcode);
776 		sq->subnet_sent = 0;
777 		sq->subnet_sent_no_subnet = 0;
778 		return generate_lookup_without_subnet(qstate, id, sq);
779 	}
780 
781 	lock_rw_wrlock(&sne->biglock);
782 	if(!sq->started_no_cache_store) {
783 		update_cache(qstate, id);
784 	}
785 	sne->num_msg_nocache++;
786 	lock_rw_unlock(&sne->biglock);
787 
788 	/* If there is an expired answer in the global cache, remove that,
789 	 * because expired answers would otherwise resurface once the ecs data
790 	 * expires, giving once in a while global data responses for ecs
791 	 * domains, with serve expired enabled. */
792 	if(qstate->env->cfg->serve_expired) {
793 		msg_cache_remove(qstate->env, qstate->qinfo.qname,
794 			qstate->qinfo.qname_len, qstate->qinfo.qtype,
795 			qstate->qinfo.qclass, 0);
796 #ifdef USE_CACHEDB
797 		if(qstate->env->cachedb_enabled)
798 			cachedb_msg_remove(qstate);
799 #endif
800 	}
801 
802 	if (sq->subnet_downstream) {
803 		/* Client wants to see the answer, echo option back
804 		 * and adjust the scope. */
805 		c_out->subnet_addr_fam = c_in->subnet_addr_fam;
806 		c_out->subnet_source_mask = c_in->subnet_source_mask;
807 		memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
808 		c_out->subnet_scope_mask = sq->max_scope;
809 		/* Limit scope returned to client to scope used for caching. */
810 		if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
811 			if(c_out->subnet_scope_mask >
812 				qstate->env->cfg->max_client_subnet_ipv4) {
813 				c_out->subnet_scope_mask =
814 					qstate->env->cfg->max_client_subnet_ipv4;
815 			}
816 		}
817 		else if(c_out->subnet_scope_mask >
818 				qstate->env->cfg->max_client_subnet_ipv6) {
819 				c_out->subnet_scope_mask =
820 					qstate->env->cfg->max_client_subnet_ipv6;
821 		}
822 		c_out->subnet_validdata = 1;
823 	}
824 	return module_finished;
825 }
826 
827 /** Parse EDNS opt data containing ECS */
828 static int
parse_subnet_option(struct edns_option * ecs_option,struct ecs_data * ecs)829 parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
830 {
831 	memset(ecs, 0, sizeof(*ecs));
832 	if (ecs_option->opt_len < 4)
833 		return 0;
834 
835 	ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
836 	ecs->subnet_source_mask = ecs_option->opt_data[2];
837 	ecs->subnet_scope_mask = ecs_option->opt_data[3];
838 	/* remaining bytes indicate address */
839 
840 	/* validate input*/
841 	/* option length matches calculated length? */
842 	if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
843 		return 0;
844 	if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
845 		return 0;
846 	if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
847 		if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
848 			return 0;
849 	} else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
850 		if (ecs->subnet_source_mask > 128 ||
851 			ecs->subnet_scope_mask > 128)
852 			return 0;
853 	} else
854 		return 0;
855 
856 	/* valid ECS data, write to ecs_data */
857 	if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
858 		ecs_option->opt_len - 4, ecs->subnet_source_mask))
859 		return 0;
860 	ecs->subnet_validdata = 1;
861 	return 1;
862 }
863 
864 void
subnet_option_from_ss(struct sockaddr_storage * ss,struct ecs_data * ecs,struct config_file * cfg)865 subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
866 	struct config_file* cfg)
867 {
868 	void* sinaddr;
869 
870 	/* Construct subnet option from original query */
871 	if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
872 		ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
873 		ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
874 		sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
875 		if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
876 			(uint8_t *)sinaddr, INET_SIZE,
877 			ecs->subnet_source_mask)) {
878 			ecs->subnet_validdata = 1;
879 		}
880 	}
881 #ifdef INET6
882 	else {
883 		ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
884 		ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
885 		sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
886 		if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
887 			(uint8_t *)sinaddr, INET6_SIZE,
888 			ecs->subnet_source_mask)) {
889 			ecs->subnet_validdata = 1;
890 		}
891 	}
892 #else
893 			/* We don't know how to handle ip6, just pass */
894 #endif /* INET6 */
895 }
896 
897 int
ecs_query_response(struct module_qstate * qstate,struct dns_msg * response,int id,void * ATTR_UNUSED (cbargs))898 ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
899 	int id, void* ATTR_UNUSED(cbargs))
900 {
901 	struct subnet_qstate *sq;
902 
903 	if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
904 		return 1;
905 
906 	if(sq->subnet_sent &&
907 		FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
908 		/* REFUSED response to ECS query, remove ECS option. */
909 		edns_opt_list_remove(&qstate->edns_opts_back_out,
910 			qstate->env->cfg->client_subnet_opcode);
911 		sq->subnet_sent = 0;
912 		sq->subnet_sent_no_subnet = 0;
913 		memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
914 	} else if (!sq->track_max_scope &&
915 		FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
916 		response->rep->an_numrrsets > 0
917 		) {
918 		struct ub_packed_rrset_key* s = response->rep->rrsets[0];
919 		if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
920 			query_dname_compare(qstate->qinfo.qname,
921 			s->rk.dname) == 0) {
922 			/* CNAME response for QNAME. From now on keep track of
923 			 * longest received ECS prefix for all queries on this
924 			 * qstate. */
925 			sq->track_max_scope = 1;
926 		}
927 	}
928 	return 1;
929 }
930 
931 /** verbose print edns subnet option in pretty print */
932 static void
subnet_log_print(const char * s,struct edns_option * ecs_opt)933 subnet_log_print(const char* s, struct edns_option* ecs_opt)
934 {
935 	if(verbosity >= VERB_ALGO) {
936 		char buf[256];
937 		char* str = buf;
938 		size_t str_len = sizeof(buf);
939 		if(!ecs_opt) {
940 			verbose(VERB_ALGO, "%s (null)", s);
941 			return;
942 		}
943 		(void)sldns_wire2str_edns_subnet_print(&str, &str_len,
944 			ecs_opt->opt_data, ecs_opt->opt_len);
945 		verbose(VERB_ALGO, "%s %s", s, buf);
946 	}
947 }
948 
949 int
ecs_edns_back_parsed(struct module_qstate * qstate,int id,void * ATTR_UNUSED (cbargs))950 ecs_edns_back_parsed(struct module_qstate* qstate, int id,
951 	void* ATTR_UNUSED(cbargs))
952 {
953 	struct subnet_qstate *sq;
954 	struct edns_option* ecs_opt;
955 
956 	if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
957 		return 1;
958 	if((ecs_opt = edns_opt_list_find(
959 		qstate->edns_opts_back_in,
960 		qstate->env->cfg->client_subnet_opcode)) &&
961 		parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
962 		sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
963 			subnet_log_print("answer has edns subnet", ecs_opt);
964 			/* Only skip global cache store if we sent an ECS option
965 			 * and received one back. Answers from non-whitelisted
966 			 * servers will end up in global cache. Answers for
967 			 * queries with 0 source will not (unless nameserver
968 			 * does not support ECS). */
969 			qstate->no_cache_store = 1;
970 			if(!sq->track_max_scope || (sq->track_max_scope &&
971 				sq->ecs_server_in.subnet_scope_mask >
972 				sq->max_scope))
973 				sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
974 	} else if(sq->subnet_sent_no_subnet) {
975 		/* The answer can be stored as scope 0, not in global cache. */
976 		/* This was already set in ecs_whitelist_check */
977 		qstate->no_cache_store = 1;
978 	} else if(sq->subnet_sent) {
979 		/* Need another query to be able to store in global cache. */
980 		/* This was already set in ecs_whitelist_check */
981 		qstate->no_cache_store = 1;
982 	}
983 
984 	return 1;
985 }
986 
987 void
subnetmod_operate(struct module_qstate * qstate,enum module_ev event,int id,struct outbound_entry * outbound)988 subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
989 	int id, struct outbound_entry* outbound)
990 {
991 	struct subnet_env *sne = qstate->env->modinfo[id];
992 	struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
993 
994 	verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s "
995 		"event:%s", id, strextstate(qstate->ext_state[id]),
996 		strmodulevent(event));
997 	log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
998 
999 	if(sq && sq->wait_subquery_done) {
1000 		/* The subquery lookup returned. */
1001 		if(sq->ecs_client_in.subnet_source_mask == 0 &&
1002 			edns_opt_list_find(qstate->edns_opts_front_in,
1003 				qstate->env->cfg->client_subnet_opcode)) {
1004 			if(!sq->started_no_cache_store &&
1005 				qstate->return_msg) {
1006 				lock_rw_wrlock(&sne->biglock);
1007 				update_cache(qstate, id);
1008 				lock_rw_unlock(&sne->biglock);
1009 			}
1010 			if (sq->subnet_downstream)
1011 				cp_edns_bad_response(&sq->ecs_client_out,
1012 					&sq->ecs_client_in);
1013 			/* It is a scope zero lookup, append edns subnet
1014 			 * option to the querier. */
1015 			subnet_ecs_opt_list_append(&sq->ecs_client_out,
1016 				&qstate->edns_opts_front_out, qstate,
1017 				qstate->region);
1018 		}
1019 		sq->wait_subquery_done = 0;
1020 		qstate->ext_state[id] = module_finished;
1021 		qstate->no_cache_store = sq->started_no_cache_store;
1022 		qstate->no_cache_lookup = sq->started_no_cache_lookup;
1023 		return;
1024 	}
1025 	if((event == module_event_new || event == module_event_pass) &&
1026 		sq == NULL) {
1027 		struct edns_option* ecs_opt;
1028 		if(!subnet_new_qstate(qstate, id)) {
1029 			qstate->return_msg = NULL;
1030 			qstate->ext_state[id] = module_finished;
1031 			return;
1032 		}
1033 
1034 		sq = (struct subnet_qstate*)qstate->minfo[id];
1035 		if(sq->wait_subquery)
1036 			return; /* Wait for that subquery to return */
1037 
1038 		if((ecs_opt = edns_opt_list_find(
1039 			qstate->edns_opts_front_in,
1040 			qstate->env->cfg->client_subnet_opcode))) {
1041 			if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
1042 				/* Wrongly formatted ECS option. RFC mandates to
1043 				 * return FORMERROR. */
1044 				qstate->return_rcode = LDNS_RCODE_FORMERR;
1045 				qstate->ext_state[id] = module_finished;
1046 				return;
1047 			}
1048 			subnet_log_print("query has edns subnet", ecs_opt);
1049 			sq->subnet_downstream = 1;
1050 		}
1051 		else if(qstate->mesh_info->reply_list) {
1052 			subnet_option_from_ss(
1053 				&qstate->mesh_info->reply_list->query_reply.client_addr,
1054 				&sq->ecs_client_in, qstate->env->cfg);
1055 		}
1056 		else if(qstate->client_addr.ss_family != AF_UNSPEC) {
1057 			subnet_option_from_ss(
1058 				&qstate->client_addr,
1059 				&sq->ecs_client_in, qstate->env->cfg);
1060 		}
1061 
1062 		if(sq->ecs_client_in.subnet_validdata == 0) {
1063 			/* No clients are interested in result or we could not
1064 			 * parse it, we don't do client subnet */
1065 			sq->ecs_server_out.subnet_validdata = 0;
1066 			if(edns_opt_list_find(qstate->edns_opts_front_in,
1067 				qstate->env->cfg->client_subnet_opcode)) {
1068 				/* aggregated this deaggregated state */
1069 				qstate->ext_state[id] =
1070 					generate_lookup_without_subnet(
1071 					qstate, id, sq);
1072 				return;
1073 			}
1074 			verbose(VERB_ALGO, "subnetcache: pass to next module");
1075 			qstate->ext_state[id] = module_wait_module;
1076 			return;
1077 		}
1078 
1079 		/* Limit to minimum allowed source mask */
1080 		if(sq->ecs_client_in.subnet_source_mask != 0 && (
1081 			(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 &&
1082 			 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) ||
1083 			(sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 &&
1084 			 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) {
1085 				qstate->return_rcode = LDNS_RCODE_REFUSED;
1086 				qstate->ext_state[id] = module_finished;
1087 				return;
1088 		}
1089 
1090 		if(!sq->started_no_cache_lookup && !qstate->blacklist) {
1091 			lock_rw_wrlock(&sne->biglock);
1092 			if(qstate->mesh_info->reply_list &&
1093 				lookup_and_reply(qstate, id, sq,
1094 				qstate->env->cfg->prefetch)) {
1095 				sne->num_msg_cache++;
1096 				lock_rw_unlock(&sne->biglock);
1097 				verbose(VERB_QUERY, "subnetcache: answered from cache");
1098 				qstate->ext_state[id] = module_finished;
1099 
1100 				subnet_ecs_opt_list_append(&sq->ecs_client_out,
1101 					&qstate->edns_opts_front_out, qstate,
1102 					qstate->region);
1103 				if(verbosity >= VERB_ALGO) {
1104 					subnet_log_print("reply has edns subnet",
1105 						edns_opt_list_find(
1106 						qstate->edns_opts_front_out,
1107 						qstate->env->cfg->
1108 						client_subnet_opcode));
1109 				}
1110 				return;
1111 			}
1112 			lock_rw_unlock(&sne->biglock);
1113 		}
1114 		if(sq->ecs_client_in.subnet_source_mask == 0 &&
1115 			edns_opt_list_find(qstate->edns_opts_front_in,
1116 				qstate->env->cfg->client_subnet_opcode)) {
1117 			/* client asked for resolution without edns subnet */
1118 			qstate->ext_state[id] = generate_lookup_without_subnet(
1119 				qstate, id, sq);
1120 			return;
1121 		}
1122 
1123 		sq->ecs_server_out.subnet_addr_fam =
1124 			sq->ecs_client_in.subnet_addr_fam;
1125 		sq->ecs_server_out.subnet_source_mask =
1126 			sq->ecs_client_in.subnet_source_mask;
1127 		/* Limit source prefix to configured maximum */
1128 		if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
1129 			&& sq->ecs_server_out.subnet_source_mask >
1130 			qstate->env->cfg->max_client_subnet_ipv4)
1131 			sq->ecs_server_out.subnet_source_mask =
1132 				qstate->env->cfg->max_client_subnet_ipv4;
1133 		else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
1134 			&& sq->ecs_server_out.subnet_source_mask >
1135 			qstate->env->cfg->max_client_subnet_ipv6)
1136 			sq->ecs_server_out.subnet_source_mask =
1137 				qstate->env->cfg->max_client_subnet_ipv6;
1138 		/* Safe to copy completely, even if the source is limited by the
1139 		 * configuration. subnet_ecs_opt_list_append() will limit the address.
1140 		 * */
1141 		memcpy(&sq->ecs_server_out.subnet_addr,
1142 			sq->ecs_client_in.subnet_addr, INET6_SIZE);
1143 		sq->ecs_server_out.subnet_scope_mask = 0;
1144 		sq->ecs_server_out.subnet_validdata = 1;
1145 		if(sq->ecs_server_out.subnet_source_mask != 0 &&
1146 			qstate->env->cfg->client_subnet_always_forward &&
1147 			sq->subnet_downstream)
1148 			/* ECS specific data required, do not look at the global
1149 			 * cache in other modules. */
1150 			qstate->no_cache_lookup = 1;
1151 
1152 		/* pass request to next module */
1153 		verbose(VERB_ALGO,
1154 			"subnetcache: not found in cache. pass to next module");
1155 		qstate->ext_state[id] = module_wait_module;
1156 		return;
1157 	}
1158 	if(sq && sq->wait_subquery)
1159 		return; /* Wait for that subquery to return */
1160 	/* Query handed back by next module, we have a 'final' answer */
1161 	if(sq && event == module_event_moddone) {
1162 		qstate->ext_state[id] = eval_response(qstate, id, sq);
1163 		if(qstate->ext_state[id] == module_finished &&
1164 			qstate->return_msg) {
1165 			subnet_ecs_opt_list_append(&sq->ecs_client_out,
1166 				&qstate->edns_opts_front_out, qstate,
1167 				qstate->region);
1168 			if(verbosity >= VERB_ALGO) {
1169 				subnet_log_print("reply has edns subnet",
1170 					edns_opt_list_find(
1171 					qstate->edns_opts_front_out,
1172 					qstate->env->cfg->
1173 					client_subnet_opcode));
1174 			}
1175 		}
1176 		qstate->no_cache_store = sq->started_no_cache_store;
1177 		qstate->no_cache_lookup = sq->started_no_cache_lookup;
1178 		return;
1179 	}
1180 	if(sq && outbound) {
1181 		return;
1182 	}
1183 	/* We are being revisited */
1184 	if(event == module_event_pass || event == module_event_new) {
1185 		/* Just pass it on, we already did the work */
1186 		verbose(VERB_ALGO, "subnetcache: pass to next module");
1187 		qstate->ext_state[id] = module_wait_module;
1188 		return;
1189 	}
1190 	if(!sq && (event == module_event_moddone)) {
1191 		/* during priming, module done but we never started */
1192 		qstate->ext_state[id] = module_finished;
1193 		return;
1194 	}
1195 	log_err("subnetcache: bad event %s", strmodulevent(event));
1196 	qstate->ext_state[id] = module_error;
1197 	return;
1198 }
1199 
1200 void
subnetmod_clear(struct module_qstate * ATTR_UNUSED (qstate),int ATTR_UNUSED (id))1201 subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
1202 	int ATTR_UNUSED(id))
1203 {
1204 	/* qstate has no data outside region */
1205 }
1206 
1207 void
subnetmod_inform_super(struct module_qstate * qstate,int id,struct module_qstate * super)1208 subnetmod_inform_super(struct module_qstate *qstate, int id,
1209 	struct module_qstate *super)
1210 {
1211 	struct subnet_qstate* super_sq =
1212 		(struct subnet_qstate*)super->minfo[id];
1213 	log_query_info(VERB_ALGO, "subnetcache inform_super: query",
1214 		&super->qinfo);
1215 	super_sq->wait_subquery = 0;
1216 	super_sq->wait_subquery_done = 1;
1217 	if(qstate->return_rcode != LDNS_RCODE_NOERROR ||
1218 		!qstate->return_msg) {
1219 		super->return_msg = NULL;
1220 		super->return_rcode = LDNS_RCODE_SERVFAIL;
1221 		return;
1222 	}
1223 	super->return_rcode = LDNS_RCODE_NOERROR;
1224 	super->return_msg = dns_copy_msg(qstate->return_msg, super->region);
1225 	if(!super->return_msg) {
1226 		log_err("subnetcache: copy response, out of memory");
1227 		super->return_rcode = LDNS_RCODE_SERVFAIL;
1228 	}
1229 }
1230 
1231 size_t
subnetmod_get_mem(struct module_env * env,int id)1232 subnetmod_get_mem(struct module_env *env, int id)
1233 {
1234 	struct subnet_env *sn_env = env->modinfo[id];
1235 	if (!sn_env) return 0;
1236 	return sizeof(*sn_env) +
1237 		slabhash_get_mem(sn_env->subnet_msg_cache) +
1238 		ecs_whitelist_get_mem(sn_env->whitelist);
1239 }
1240 
1241 /**
1242  * The module function block
1243  */
1244 static struct module_func_block subnetmod_block = {
1245 	"subnetcache",
1246 	NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
1247 	&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
1248 };
1249 
1250 struct module_func_block*
subnetmod_get_funcblock(void)1251 subnetmod_get_funcblock(void)
1252 {
1253 	return &subnetmod_block;
1254 }
1255 
1256 /** Wrappers for static functions to unit test */
1257 size_t
unittest_wrapper_subnetmod_sizefunc(void * elemptr)1258 unittest_wrapper_subnetmod_sizefunc(void *elemptr)
1259 {
1260 	return sizefunc(elemptr);
1261 }
1262 
1263 #endif  /* CLIENT_SUBNET */
1264