2 * edns-subnet/subnetmod.c - edns subnet module. Must be called before validator
5 * Copyright (c) 2013, NLnet Labs. All rights reserved.
7 * This software is open source.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
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.
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.
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.
38 * subnet module for unbound.
43 #ifdef CLIENT_SUBNET /* keeps splint happy */
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"
50 #include "services/mesh.h"
51 #include "services/cache/dns.h"
52 #include "util/module.h"
53 #include "util/regional.h"
54 #include "util/storage/slabhash.h"
55 #include "util/config_file.h"
56 #include "util/data/msgreply.h"
57 #include "sldns/sbuffer.h"
58 #include "sldns/wire2str.h"
59 #include "iterator/iter_utils.h"
61 /** externally called */
63 subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
65 struct subnet_msg_cache_data *r;
66 r = (struct subnet_msg_cache_data*)d;
67 addrtree_delete(r->tree4);
68 addrtree_delete(r->tree6);
72 /** externally called */
74 msg_cache_sizefunc(void *k, void *d)
76 struct msgreply_entry *q = (struct msgreply_entry*)k;
77 struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
78 size_t s = sizeof(struct msgreply_entry)
79 + sizeof(struct subnet_msg_cache_data)
80 + q->key.qname_len + lock_get_mem(&q->entry.lock);
81 s += addrtree_size(r->tree4);
82 s += addrtree_size(r->tree6);
86 /** new query for ecs module */
88 subnet_new_qstate(struct module_qstate *qstate, int id)
90 struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
91 qstate->region, sizeof(struct subnet_qstate));
94 qstate->minfo[id] = sq;
95 memset(sq, 0, sizeof(*sq));
96 sq->started_no_cache_store = qstate->no_cache_store;
97 sq->started_no_cache_lookup = qstate->no_cache_lookup;
101 /** Add ecs struct to edns list, after parsing it to wire format. */
103 subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
104 struct module_qstate *qstate, struct regional *region)
106 size_t sn_octs, sn_octs_remainder;
107 sldns_buffer* buf = qstate->env->scratch_buffer;
109 if(ecs->subnet_validdata) {
110 log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
111 ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
112 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
113 ecs->subnet_source_mask <= INET_SIZE*8);
114 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
115 ecs->subnet_source_mask <= INET6_SIZE*8);
117 sn_octs = ecs->subnet_source_mask / 8;
119 (size_t)((ecs->subnet_source_mask % 8)>0?1:0);
121 log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
123 sldns_buffer_clear(buf);
124 sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
125 sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
126 sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
127 sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
128 if(sn_octs_remainder)
129 sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
130 ~(0xFF >> (ecs->subnet_source_mask % 8)));
131 sldns_buffer_flip(buf);
133 edns_opt_list_append(list,
134 qstate->env->cfg->client_subnet_opcode,
135 sn_octs + sn_octs_remainder + 4,
136 sldns_buffer_begin(buf), region);
140 int ecs_whitelist_check(struct query_info* qinfo,
141 uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
142 struct sockaddr_storage* addr, socklen_t addrlen,
143 uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
144 struct regional *region, int id, void* ATTR_UNUSED(cbargs))
146 struct subnet_qstate *sq;
147 struct subnet_env *sn_env;
149 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
151 sn_env = (struct subnet_env*)qstate->env->modinfo[id];
153 /* Cache by default, might be disabled after parsing EDNS option
154 * received from nameserver. */
155 if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
156 qstate->no_cache_store = 0;
159 if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
160 qstate->env->cfg->client_subnet_always_forward) ||
161 ecs_is_whitelisted(sn_env->whitelist,
162 addr, addrlen, qinfo->qname, qinfo->qname_len,
164 /* Address on whitelist or client query contains ECS option, we
165 * want to sent out ECS. Only add option if it is not already
167 if(!edns_opt_list_find(qstate->edns_opts_back_out,
168 qstate->env->cfg->client_subnet_opcode)) {
169 subnet_ecs_opt_list_append(&sq->ecs_server_out,
170 &qstate->edns_opts_back_out, qstate, region);
175 /* Outgoing ECS option is set, but we don't want to sent it to
176 * this address, remove option. */
177 if(edns_opt_list_find(qstate->edns_opts_back_out,
178 qstate->env->cfg->client_subnet_opcode)) {
179 edns_opt_list_remove(&qstate->edns_opts_back_out,
180 qstate->env->cfg->client_subnet_opcode);
189 subnet_markdel(void* key)
191 struct msgreply_entry *e = (struct msgreply_entry*)key;
197 subnetmod_init(struct module_env *env, int id)
199 struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
200 sizeof(struct subnet_env));
202 log_err("malloc failure");
205 alloc_init(&sn_env->alloc, NULL, 0);
206 env->modinfo[id] = (void*)sn_env;
207 /* Copy msg_cache settings */
208 sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
209 HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
210 msg_cache_sizefunc, query_info_compare, query_entry_delete,
211 subnet_data_delete, NULL);
212 slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
213 if(!sn_env->subnet_msg_cache) {
214 log_err("subnetcache: could not create cache");
216 env->modinfo[id] = NULL;
219 /* whitelist for edns subnet capable servers */
220 sn_env->whitelist = ecs_whitelist_create();
221 if(!sn_env->whitelist ||
222 !ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
223 log_err("subnetcache: could not create ECS whitelist");
224 slabhash_delete(sn_env->subnet_msg_cache);
226 env->modinfo[id] = NULL;
230 verbose(VERB_QUERY, "subnetcache: option registered (%d)",
231 env->cfg->client_subnet_opcode);
232 /* Create new mesh state for all queries. */
233 env->unique_mesh = 1;
234 if(!edns_register_option(env->cfg->client_subnet_opcode,
235 env->cfg->client_subnet_always_forward /* bypass cache */,
236 1 /* no aggregation */, env)) {
237 log_err("subnetcache: could not register opcode");
238 ecs_whitelist_delete(sn_env->whitelist);
239 slabhash_delete(sn_env->subnet_msg_cache);
241 env->modinfo[id] = NULL;
244 inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
246 inplace_cb_register((void*)ecs_edns_back_parsed,
247 inplace_cb_edns_back_parsed, NULL, env, id);
248 inplace_cb_register((void*)ecs_query_response,
249 inplace_cb_query_response, NULL, env, id);
250 lock_rw_init(&sn_env->biglock);
255 subnetmod_deinit(struct module_env *env, int id)
257 struct subnet_env *sn_env;
258 if(!env || !env->modinfo[id])
260 sn_env = (struct subnet_env*)env->modinfo[id];
261 lock_rw_destroy(&sn_env->biglock);
262 inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
263 inplace_cb_delete(env, inplace_cb_query, id);
264 inplace_cb_delete(env, inplace_cb_query_response, id);
265 ecs_whitelist_delete(sn_env->whitelist);
266 slabhash_delete(sn_env->subnet_msg_cache);
267 alloc_clear(&sn_env->alloc);
269 env->modinfo[id] = NULL;
272 /** Tells client that upstream has no/improper support */
274 cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
276 target->subnet_scope_mask = 0;
277 target->subnet_source_mask = source->subnet_source_mask;
278 target->subnet_addr_fam = source->subnet_addr_fam;
279 memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
280 target->subnet_validdata = 1;
284 delfunc(void *envptr, void *elemptr) {
285 struct reply_info *elem = (struct reply_info *)elemptr;
286 struct subnet_env *env = (struct subnet_env *)envptr;
287 reply_info_parsedelete(elem, &env->alloc);
291 sizefunc(void *elemptr) {
292 struct reply_info *elem = (struct reply_info *)elemptr;
293 return sizeof (struct reply_info) - sizeof (struct rrset_ref)
294 + elem->rrset_count * sizeof (struct rrset_ref)
295 + elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
299 * Select tree from cache entry based on edns data.
300 * If for address family not present it will create a new one.
301 * NULL on failure to create. */
302 static struct addrtree*
303 get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
304 struct subnet_env *env, struct config_file* cfg)
306 struct addrtree *tree;
307 if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
309 data->tree4 = addrtree_create(
310 cfg->max_client_subnet_ipv4, &delfunc,
311 &sizefunc, env, cfg->max_ecs_tree_size_ipv4);
315 data->tree6 = addrtree_create(
316 cfg->max_client_subnet_ipv6, &delfunc,
317 &sizefunc, env, cfg->max_ecs_tree_size_ipv6);
324 update_cache(struct module_qstate *qstate, int id)
326 struct msgreply_entry *mrep_entry;
327 struct addrtree *tree;
328 struct reply_info *rep;
329 struct query_info qinf;
330 struct subnet_env *sne = qstate->env->modinfo[id];
331 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
332 struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
333 struct ecs_data *edns = &sq->ecs_client_in;
335 int only_match_scope_zero;
337 /* We already calculated hash upon lookup (lookup_and_reply) if we were
338 * allowed to look in the ECS cache */
339 hashvalue_type h = qstate->minfo[id] &&
340 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
341 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
342 query_info_hash(&qstate->qinfo, qstate->query_flags);
343 /* Step 1, general qinfo lookup */
344 struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
346 int need_to_insert = (lru_entry == NULL);
348 void* data = calloc(1,
349 sizeof(struct subnet_msg_cache_data));
351 log_err("malloc failed");
354 qinf = qstate->qinfo;
355 qinf.qname = memdup(qstate->qinfo.qname,
356 qstate->qinfo.qname_len);
359 log_err("memdup failed");
362 mrep_entry = query_info_entrysetup(&qinf, data, h);
363 free(qinf.qname); /* if qname 'consumed', it is set to NULL */
366 log_err("query_info_entrysetup failed");
369 lru_entry = &mrep_entry->entry;
370 lock_rw_wrlock(&lru_entry->lock);
372 /* lru_entry->lock is locked regardless of how we got here,
373 * either from the slabhash_lookup, or above in the new allocated */
374 /* Step 2, find the correct tree */
375 if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
376 lock_rw_unlock(&lru_entry->lock);
377 log_err("subnetcache: cache insertion failed");
380 lock_quick_lock(&sne->alloc.lock);
381 rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
382 lock_quick_unlock(&sne->alloc.lock);
384 lock_rw_unlock(&lru_entry->lock);
385 log_err("subnetcache: cache insertion failed");
390 for(i=0; i<rep->rrset_count; i++) {
391 rep->ref[i].key = rep->rrsets[i];
392 rep->ref[i].id = rep->rrsets[i]->id;
394 reply_info_set_ttls(rep, *qstate->env->now);
395 rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
396 rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
397 if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
398 only_match_scope_zero = 1;
399 else only_match_scope_zero = 0;
400 addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
401 edns->subnet_source_mask, sq->max_scope, rep,
402 rep->ttl, *qstate->env->now, only_match_scope_zero);
404 lock_rw_unlock(&lru_entry->lock);
405 if (need_to_insert) {
406 slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
411 /** Lookup in cache and reply true iff reply is sent. */
413 lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
415 struct lruhash_entry *e;
416 struct module_env *env = qstate->env;
417 struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
418 hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
419 struct subnet_msg_cache_data *data;
420 struct ecs_data *ecs = &sq->ecs_client_in;
421 struct addrtree *tree;
422 struct addrnode *node;
425 memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
428 sq->qinfo_hash = h; /* Might be useful on cache miss */
429 sq->qinfo_hash_calculated = 1;
431 e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
432 if (!e) return 0; /* qinfo not in cache */
434 tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
435 data->tree4 : data->tree6;
436 if (!tree) { /* qinfo in cache but not for this family */
437 lock_rw_unlock(&e->lock);
440 node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
441 ecs->subnet_source_mask, *env->now);
442 if (!node) { /* plain old cache miss */
443 lock_rw_unlock(&e->lock);
447 qstate->return_msg = tomsg(NULL, &qstate->qinfo,
448 (struct reply_info *)node->elem, qstate->region, *env->now, 0,
450 scope = (uint8_t)node->scope;
451 lock_rw_unlock(&e->lock);
453 if (!qstate->return_msg) { /* Failed allocation or expired TTL */
457 if (sq->subnet_downstream) { /* relay to interested client */
458 sq->ecs_client_out.subnet_scope_mask = scope;
459 sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
460 sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
461 memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
463 sq->ecs_client_out.subnet_validdata = 1;
469 * Test first bits of addresses for equality. Caller is responsible
470 * for making sure that both a and b are at least net/8 octets long.
471 * @param a: first address.
472 * @param a: seconds address.
473 * @param net: Number of bits to test.
474 * @return: 1 if equal, 0 otherwise.
477 common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
479 size_t n = (size_t)net / 8;
480 return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
483 static enum module_ext_state
484 eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
486 struct subnet_env *sne = qstate->env->modinfo[id];
488 struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */
489 struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
490 struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */
491 struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
493 memset(c_out, 0, sizeof(*c_out));
495 if (!qstate->return_msg) {
496 /* already an answer and its not a message, but retain
497 * the actual rcode, instead of module_error, so send
499 return module_finished;
502 /* We have not asked for subnet data */
503 if (!sq->subnet_sent) {
504 if (s_in->subnet_validdata)
505 verbose(VERB_QUERY, "subnetcache: received spurious data");
506 if (sq->subnet_downstream) /* Copy back to client */
507 cp_edns_bad_response(c_out, c_in);
508 return module_finished;
511 /* subnet sent but nothing came back */
512 if (!s_in->subnet_validdata) {
513 /* The authority indicated no support for edns subnet. As a
514 * consequence the answer ended up in the regular cache. It
515 * is still useful to put it in the edns subnet cache for
516 * when a client explicitly asks for subnet specific answer. */
517 verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
518 if(!sq->started_no_cache_store) {
519 lock_rw_wrlock(&sne->biglock);
520 update_cache(qstate, id);
521 lock_rw_unlock(&sne->biglock);
523 if (sq->subnet_downstream)
524 cp_edns_bad_response(c_out, c_in);
525 return module_finished;
528 /* Being here means we have asked for and got a subnet specific
529 * answer. Also, the answer from the authority is not yet cached
532 /* can we accept response? */
533 if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
534 s_out->subnet_source_mask != s_in->subnet_source_mask ||
535 !common_prefix(s_out->subnet_addr, s_in->subnet_addr,
536 s_out->subnet_source_mask))
538 /* we can not accept, restart query without option */
539 verbose(VERB_QUERY, "subnetcache: forged data");
540 s_out->subnet_validdata = 0;
541 (void)edns_opt_list_remove(&qstate->edns_opts_back_out,
542 qstate->env->cfg->client_subnet_opcode);
544 return module_restart_next;
547 lock_rw_wrlock(&sne->biglock);
548 if(!sq->started_no_cache_store) {
549 update_cache(qstate, id);
551 sne->num_msg_nocache++;
552 lock_rw_unlock(&sne->biglock);
554 if (sq->subnet_downstream) {
555 /* Client wants to see the answer, echo option back
556 * and adjust the scope. */
557 c_out->subnet_addr_fam = c_in->subnet_addr_fam;
558 c_out->subnet_source_mask = c_in->subnet_source_mask;
559 memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
560 c_out->subnet_scope_mask = sq->max_scope;
561 /* Limit scope returned to client to scope used for caching. */
562 if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
563 if(c_out->subnet_scope_mask >
564 qstate->env->cfg->max_client_subnet_ipv4) {
565 c_out->subnet_scope_mask =
566 qstate->env->cfg->max_client_subnet_ipv4;
569 else if(c_out->subnet_scope_mask >
570 qstate->env->cfg->max_client_subnet_ipv6) {
571 c_out->subnet_scope_mask =
572 qstate->env->cfg->max_client_subnet_ipv6;
574 c_out->subnet_validdata = 1;
576 return module_finished;
579 /** Parse EDNS opt data containing ECS */
581 parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
583 memset(ecs, 0, sizeof(*ecs));
584 if (ecs_option->opt_len < 4)
587 ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
588 ecs->subnet_source_mask = ecs_option->opt_data[2];
589 ecs->subnet_scope_mask = ecs_option->opt_data[3];
590 /* remaining bytes indicate address */
593 /* option length matches calculated length? */
594 if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
596 if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
598 if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
599 if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
601 } else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
602 if (ecs->subnet_source_mask > 128 ||
603 ecs->subnet_scope_mask > 128)
608 /* valid ECS data, write to ecs_data */
609 if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
610 ecs_option->opt_len - 4, ecs->subnet_source_mask))
612 ecs->subnet_validdata = 1;
617 subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
618 struct config_file* cfg)
622 /* Construct subnet option from original query */
623 if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
624 ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
625 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
626 sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
627 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
628 (uint8_t *)sinaddr, INET_SIZE,
629 ecs->subnet_source_mask)) {
630 ecs->subnet_validdata = 1;
635 ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
636 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
637 sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
638 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
639 (uint8_t *)sinaddr, INET6_SIZE,
640 ecs->subnet_source_mask)) {
641 ecs->subnet_validdata = 1;
645 /* We don't know how to handle ip6, just pass */
650 ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
651 int id, void* ATTR_UNUSED(cbargs))
653 struct subnet_qstate *sq;
655 if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
658 if(sq->subnet_sent &&
659 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
660 /* REFUSED response to ECS query, remove ECS option. */
661 edns_opt_list_remove(&qstate->edns_opts_back_out,
662 qstate->env->cfg->client_subnet_opcode);
664 memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
665 } else if (!sq->track_max_scope &&
666 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
667 response->rep->an_numrrsets > 0
669 struct ub_packed_rrset_key* s = response->rep->rrsets[0];
670 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
671 query_dname_compare(qstate->qinfo.qname,
673 /* CNAME response for QNAME. From now on keep track of
674 * longest received ECS prefix for all queries on this
676 sq->track_max_scope = 1;
682 /** verbose print edns subnet option in pretty print */
684 subnet_log_print(const char* s, struct edns_option* ecs_opt)
686 if(verbosity >= VERB_ALGO) {
689 size_t str_len = sizeof(buf);
691 verbose(VERB_ALGO, "%s (null)", s);
694 (void)sldns_wire2str_edns_subnet_print(&str, &str_len,
695 ecs_opt->opt_data, ecs_opt->opt_len);
696 verbose(VERB_ALGO, "%s %s", s, buf);
701 ecs_edns_back_parsed(struct module_qstate* qstate, int id,
702 void* ATTR_UNUSED(cbargs))
704 struct subnet_qstate *sq;
705 struct edns_option* ecs_opt;
707 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
709 if((ecs_opt = edns_opt_list_find(
710 qstate->edns_opts_back_in,
711 qstate->env->cfg->client_subnet_opcode)) &&
712 parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
713 sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
714 subnet_log_print("answer has edns subnet", ecs_opt);
715 /* Only skip global cache store if we sent an ECS option
716 * and received one back. Answers from non-whitelisted
717 * servers will end up in global cache. Answers for
718 * queries with 0 source will not (unless nameserver
719 * does not support ECS). */
720 qstate->no_cache_store = 1;
721 if(!sq->track_max_scope || (sq->track_max_scope &&
722 sq->ecs_server_in.subnet_scope_mask >
724 sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
731 subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
732 int id, struct outbound_entry* outbound)
734 struct subnet_env *sne = qstate->env->modinfo[id];
735 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
737 verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s "
738 "event:%s", id, strextstate(qstate->ext_state[id]),
739 strmodulevent(event));
740 log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
742 if((event == module_event_new || event == module_event_pass) &&
744 struct edns_option* ecs_opt;
745 if(!subnet_new_qstate(qstate, id)) {
746 qstate->return_msg = NULL;
747 qstate->ext_state[id] = module_finished;
751 sq = (struct subnet_qstate*)qstate->minfo[id];
753 if((ecs_opt = edns_opt_list_find(
754 qstate->edns_opts_front_in,
755 qstate->env->cfg->client_subnet_opcode))) {
756 if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
757 /* Wrongly formatted ECS option. RFC mandates to
758 * return FORMERROR. */
759 qstate->return_rcode = LDNS_RCODE_FORMERR;
760 qstate->ext_state[id] = module_finished;
763 subnet_log_print("query has edns subnet", ecs_opt);
764 sq->subnet_downstream = 1;
766 else if(qstate->mesh_info->reply_list) {
767 subnet_option_from_ss(
768 &qstate->mesh_info->reply_list->query_reply.client_addr,
769 &sq->ecs_client_in, qstate->env->cfg);
772 if(sq->ecs_client_in.subnet_validdata == 0) {
773 /* No clients are interested in result or we could not
774 * parse it, we don't do client subnet */
775 sq->ecs_server_out.subnet_validdata = 0;
776 verbose(VERB_ALGO, "subnetcache: pass to next module");
777 qstate->ext_state[id] = module_wait_module;
781 /* Limit to minimum allowed source mask */
782 if(sq->ecs_client_in.subnet_source_mask != 0 && (
783 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 &&
784 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) ||
785 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 &&
786 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) {
787 qstate->return_rcode = LDNS_RCODE_REFUSED;
788 qstate->ext_state[id] = module_finished;
792 if(!sq->started_no_cache_lookup && !qstate->blacklist) {
793 lock_rw_wrlock(&sne->biglock);
794 if(lookup_and_reply(qstate, id, sq)) {
795 sne->num_msg_cache++;
796 lock_rw_unlock(&sne->biglock);
797 verbose(VERB_QUERY, "subnetcache: answered from cache");
798 qstate->ext_state[id] = module_finished;
800 subnet_ecs_opt_list_append(&sq->ecs_client_out,
801 &qstate->edns_opts_front_out, qstate,
803 if(verbosity >= VERB_ALGO) {
804 subnet_log_print("reply has edns subnet",
806 qstate->edns_opts_front_out,
808 client_subnet_opcode));
812 lock_rw_unlock(&sne->biglock);
815 sq->ecs_server_out.subnet_addr_fam =
816 sq->ecs_client_in.subnet_addr_fam;
817 sq->ecs_server_out.subnet_source_mask =
818 sq->ecs_client_in.subnet_source_mask;
819 /* Limit source prefix to configured maximum */
820 if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
821 && sq->ecs_server_out.subnet_source_mask >
822 qstate->env->cfg->max_client_subnet_ipv4)
823 sq->ecs_server_out.subnet_source_mask =
824 qstate->env->cfg->max_client_subnet_ipv4;
825 else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
826 && sq->ecs_server_out.subnet_source_mask >
827 qstate->env->cfg->max_client_subnet_ipv6)
828 sq->ecs_server_out.subnet_source_mask =
829 qstate->env->cfg->max_client_subnet_ipv6;
830 /* Safe to copy completely, even if the source is limited by the
831 * configuration. subnet_ecs_opt_list_append() will limit the address.
833 memcpy(&sq->ecs_server_out.subnet_addr,
834 sq->ecs_client_in.subnet_addr, INET6_SIZE);
835 sq->ecs_server_out.subnet_scope_mask = 0;
836 sq->ecs_server_out.subnet_validdata = 1;
837 if(sq->ecs_server_out.subnet_source_mask != 0 &&
838 qstate->env->cfg->client_subnet_always_forward &&
839 sq->subnet_downstream)
840 /* ECS specific data required, do not look at the global
841 * cache in other modules. */
842 qstate->no_cache_lookup = 1;
844 /* pass request to next module */
846 "subnetcache: not found in cache. pass to next module");
847 qstate->ext_state[id] = module_wait_module;
850 /* Query handed back by next module, we have a 'final' answer */
851 if(sq && event == module_event_moddone) {
852 qstate->ext_state[id] = eval_response(qstate, id, sq);
853 if(qstate->ext_state[id] == module_finished &&
854 qstate->return_msg) {
855 subnet_ecs_opt_list_append(&sq->ecs_client_out,
856 &qstate->edns_opts_front_out, qstate,
858 if(verbosity >= VERB_ALGO) {
859 subnet_log_print("reply has edns subnet",
861 qstate->edns_opts_front_out,
863 client_subnet_opcode));
866 qstate->no_cache_store = sq->started_no_cache_store;
867 qstate->no_cache_lookup = sq->started_no_cache_lookup;
873 /* We are being revisited */
874 if(event == module_event_pass || event == module_event_new) {
875 /* Just pass it on, we already did the work */
876 verbose(VERB_ALGO, "subnetcache: pass to next module");
877 qstate->ext_state[id] = module_wait_module;
880 if(!sq && (event == module_event_moddone)) {
881 /* during priming, module done but we never started */
882 qstate->ext_state[id] = module_finished;
885 log_err("subnetcache: bad event %s", strmodulevent(event));
886 qstate->ext_state[id] = module_error;
891 subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
894 /* qstate has no data outside region */
898 subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
899 int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
905 subnetmod_get_mem(struct module_env *env, int id)
907 struct subnet_env *sn_env = env->modinfo[id];
908 if (!sn_env) return 0;
909 return sizeof(*sn_env) +
910 slabhash_get_mem(sn_env->subnet_msg_cache) +
911 ecs_whitelist_get_mem(sn_env->whitelist);
915 * The module function block
917 static struct module_func_block subnetmod_block = {
918 "subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
919 &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
922 struct module_func_block*
923 subnetmod_get_funcblock(void)
925 return &subnetmod_block;
928 /** Wrappers for static functions to unit test */
930 unittest_wrapper_subnetmod_sizefunc(void *elemptr)
932 return sizefunc(elemptr);
935 #endif /* CLIENT_SUBNET */