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"
59 #define ECS_MAX_TREESIZE 100
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));
99 /** Add ecs struct to edns list, after parsing it to wire format. */
101 ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
102 struct module_qstate *qstate)
104 size_t sn_octs, sn_octs_remainder;
105 sldns_buffer* buf = qstate->env->scratch_buffer;
107 if(ecs->subnet_validdata) {
108 log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
109 ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
110 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
111 ecs->subnet_source_mask <= INET_SIZE*8);
112 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
113 ecs->subnet_source_mask <= INET6_SIZE*8);
115 sn_octs = ecs->subnet_source_mask / 8;
117 (size_t)((ecs->subnet_source_mask % 8)>0?1:0);
119 log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
121 sldns_buffer_clear(buf);
122 sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
123 sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
124 sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
125 sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
126 if(sn_octs_remainder)
127 sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
128 ~(0xFF >> (ecs->subnet_source_mask % 8)));
129 sldns_buffer_flip(buf);
131 edns_opt_list_append(list,
132 qstate->env->cfg->client_subnet_opcode,
133 sn_octs + sn_octs_remainder + 4,
134 sldns_buffer_begin(buf), qstate->region);
138 int ecs_whitelist_check(struct query_info* qinfo,
139 uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
140 struct sockaddr_storage* addr, socklen_t addrlen,
141 uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
142 struct regional* ATTR_UNUSED(region), int id, void* ATTR_UNUSED(cbargs))
144 struct subnet_qstate *sq;
145 struct subnet_env *sn_env;
147 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
149 sn_env = (struct subnet_env*)qstate->env->modinfo[id];
151 /* Cache by default, might be disabled after parsing EDNS option
152 * received from nameserver. */
153 qstate->no_cache_store = 0;
155 if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
156 qstate->env->cfg->client_subnet_always_forward) ||
157 ecs_is_whitelisted(sn_env->whitelist,
158 addr, addrlen, qinfo->qname, qinfo->qname_len,
160 /* Address on whitelist or client query contains ECS option, we
161 * want to sent out ECS. Only add option if it is not already
163 if(!(sq->subnet_sent)) {
164 ecs_opt_list_append(&sq->ecs_server_out,
165 &qstate->edns_opts_back_out, qstate);
169 else if(sq->subnet_sent) {
170 /* Outgoing ECS option is set, but we don't want to sent it to
171 * this address, remove option. */
172 edns_opt_list_remove(&qstate->edns_opts_back_out,
173 qstate->env->cfg->client_subnet_opcode);
181 subnetmod_init(struct module_env *env, int id)
183 struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
184 sizeof(struct subnet_env));
186 log_err("malloc failure");
189 alloc_init(&sn_env->alloc, NULL, 0);
190 env->modinfo[id] = (void*)sn_env;
191 /* Copy msg_cache settings */
192 sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
193 HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
194 msg_cache_sizefunc, query_info_compare, query_entry_delete,
195 subnet_data_delete, NULL);
196 if(!sn_env->subnet_msg_cache) {
197 log_err("subnet: could not create cache");
199 env->modinfo[id] = NULL;
202 /* whitelist for edns subnet capable servers */
203 sn_env->whitelist = ecs_whitelist_create();
204 if(!sn_env->whitelist ||
205 !ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
206 log_err("subnet: could not create ECS whitelist");
207 slabhash_delete(sn_env->subnet_msg_cache);
209 env->modinfo[id] = NULL;
213 verbose(VERB_QUERY, "subnet: option registered (%d)",
214 env->cfg->client_subnet_opcode);
215 /* Create new mesh state for all queries. */
216 env->unique_mesh = 1;
217 if(!edns_register_option(env->cfg->client_subnet_opcode,
218 env->cfg->client_subnet_always_forward /* bypass cache */,
219 0 /* no aggregation */, env)) {
220 log_err("subnet: could not register opcode");
221 ecs_whitelist_delete(sn_env->whitelist);
222 slabhash_delete(sn_env->subnet_msg_cache);
224 env->modinfo[id] = NULL;
227 inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
229 inplace_cb_register((void*)ecs_edns_back_parsed,
230 inplace_cb_edns_back_parsed, NULL, env, id);
231 inplace_cb_register((void*)ecs_query_response,
232 inplace_cb_query_response, NULL, env, id);
233 lock_rw_init(&sn_env->biglock);
238 subnetmod_deinit(struct module_env *env, int id)
240 struct subnet_env *sn_env;
241 if(!env || !env->modinfo[id])
243 sn_env = (struct subnet_env*)env->modinfo[id];
244 lock_rw_destroy(&sn_env->biglock);
245 inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
246 inplace_cb_delete(env, inplace_cb_query, id);
247 inplace_cb_delete(env, inplace_cb_query_response, id);
248 ecs_whitelist_delete(sn_env->whitelist);
249 slabhash_delete(sn_env->subnet_msg_cache);
250 alloc_clear(&sn_env->alloc);
252 env->modinfo[id] = NULL;
255 /** Tells client that upstream has no/improper support */
257 cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
259 target->subnet_scope_mask = 0;
260 target->subnet_source_mask = source->subnet_source_mask;
261 target->subnet_addr_fam = source->subnet_addr_fam;
262 memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
263 target->subnet_validdata = 1;
267 delfunc(void *envptr, void *elemptr) {
268 struct reply_info *elem = (struct reply_info *)elemptr;
269 struct subnet_env *env = (struct subnet_env *)envptr;
270 reply_info_parsedelete(elem, &env->alloc);
274 sizefunc(void *elemptr) {
275 struct reply_info *elem = (struct reply_info *)elemptr;
276 return sizeof (struct reply_info) - sizeof (struct rrset_ref)
277 + elem->rrset_count * sizeof (struct rrset_ref)
278 + elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
282 * Select tree from cache entry based on edns data.
283 * If for address family not present it will create a new one.
284 * NULL on failure to create. */
285 static struct addrtree*
286 get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
287 struct subnet_env *env, struct config_file* cfg)
289 struct addrtree *tree;
290 if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
292 data->tree4 = addrtree_create(
293 cfg->max_client_subnet_ipv4, &delfunc,
294 &sizefunc, env, ECS_MAX_TREESIZE);
298 data->tree6 = addrtree_create(
299 cfg->max_client_subnet_ipv6, &delfunc,
300 &sizefunc, env, ECS_MAX_TREESIZE);
307 update_cache(struct module_qstate *qstate, int id)
309 struct msgreply_entry *mrep_entry;
310 struct addrtree *tree;
311 struct reply_info *rep;
312 struct query_info qinf;
313 struct subnet_env *sne = qstate->env->modinfo[id];
314 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
315 struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
316 struct ecs_data *edns = &sq->ecs_client_in;
319 /* We already calculated hash upon lookup */
320 hashvalue_type h = qstate->minfo[id] ?
321 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
322 query_info_hash(&qstate->qinfo, qstate->query_flags);
323 /* Step 1, general qinfo lookup */
324 struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
326 int acquired_lock = (lru_entry != NULL);
328 qinf = qstate->qinfo;
329 qinf.qname = memdup(qstate->qinfo.qname,
330 qstate->qinfo.qname_len);
332 log_err("memdup failed");
335 mrep_entry = query_info_entrysetup(&qinf, NULL, h);
336 free(qinf.qname); /* if qname 'consumed', it is set to NULL */
338 log_err("query_info_entrysetup failed");
341 lru_entry = &mrep_entry->entry;
342 lock_rw_wrlock(&lru_entry->lock);
343 lru_entry->data = calloc(1,
344 sizeof(struct subnet_msg_cache_data));
345 if (!lru_entry->data) {
346 log_err("malloc failed");
350 /* Step 2, find the correct tree */
351 if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
352 if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
353 log_err("Subnet cache insertion failed");
356 lock_quick_lock(&sne->alloc.lock);
357 rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
358 lock_quick_unlock(&sne->alloc.lock);
360 if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
361 log_err("Subnet cache insertion failed");
366 for(i=0; i<rep->rrset_count; i++) {
367 rep->ref[i].key = rep->rrsets[i];
368 rep->ref[i].id = rep->rrsets[i]->id;
370 reply_info_set_ttls(rep, *qstate->env->now);
371 rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
372 rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
373 addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
374 edns->subnet_source_mask,
375 sq->ecs_server_in.subnet_scope_mask, rep,
376 rep->ttl, *qstate->env->now);
378 lock_rw_unlock(&lru_entry->lock);
380 lock_rw_unlock(&lru_entry->lock);
381 slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
386 /** Lookup in cache and reply true iff reply is sent. */
388 lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
390 struct lruhash_entry *e;
391 struct module_env *env = qstate->env;
392 struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
393 hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
394 struct subnet_msg_cache_data *data;
395 struct ecs_data *ecs = &sq->ecs_client_in;
396 struct addrtree *tree;
397 struct addrnode *node;
400 memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
402 if (sq) sq->qinfo_hash = h; /* Might be useful on cache miss */
403 e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
404 if (!e) return 0; /* qinfo not in cache */
406 tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
407 data->tree4 : data->tree6;
408 if (!tree) { /* qinfo in cache but not for this family */
409 lock_rw_unlock(&e->lock);
412 node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
413 ecs->subnet_source_mask, *env->now);
414 if (!node) { /* plain old cache miss */
415 lock_rw_unlock(&e->lock);
419 qstate->return_msg = tomsg(NULL, &qstate->qinfo,
420 (struct reply_info *)node->elem, qstate->region, *env->now,
422 scope = (uint8_t)node->scope;
423 lock_rw_unlock(&e->lock);
425 if (!qstate->return_msg) { /* Failed allocation or expired TTL */
429 if (sq->subnet_downstream) { /* relay to interested client */
430 sq->ecs_client_out.subnet_scope_mask = scope;
431 sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
432 sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
433 memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
435 sq->ecs_client_out.subnet_validdata = 1;
441 * Test first bits of addresses for equality. Caller is responsible
442 * for making sure that both a and b are at least net/8 octets long.
443 * @param a: first address.
444 * @param a: seconds address.
445 * @param net: Number of bits to test.
446 * @return: 1 if equal, 0 otherwise.
449 common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
451 size_t n = (size_t)net / 8;
452 return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
455 static enum module_ext_state
456 eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
458 struct subnet_env *sne = qstate->env->modinfo[id];
460 struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */
461 struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
462 struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */
463 struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
465 memset(c_out, 0, sizeof(*c_out));
467 if (!qstate->return_msg) {
468 /* already an answer and its not a message, but retain
469 * the actual rcode, instead of module_error, so send
471 return module_finished;
474 /* We have not asked for subnet data */
475 if (!sq->subnet_sent) {
476 if (s_in->subnet_validdata)
477 verbose(VERB_QUERY, "subnet: received spurious data");
478 if (sq->subnet_downstream) /* Copy back to client */
479 cp_edns_bad_response(c_out, c_in);
480 return module_finished;
483 /* subnet sent but nothing came back */
484 if (!s_in->subnet_validdata) {
485 /* The authority indicated no support for edns subnet. As a
486 * consequence the answer ended up in the regular cache. It
487 * is still usefull to put it in the edns subnet cache for
488 * when a client explicitly asks for subnet specific answer. */
489 verbose(VERB_QUERY, "subnet: Authority indicates no support");
490 lock_rw_wrlock(&sne->biglock);
491 update_cache(qstate, id);
492 lock_rw_unlock(&sne->biglock);
493 if (sq->subnet_downstream)
494 cp_edns_bad_response(c_out, c_in);
495 return module_finished;
498 /* Being here means we have asked for and got a subnet specific
499 * answer. Also, the answer from the authority is not yet cached
502 /* can we accept response? */
503 if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
504 s_out->subnet_source_mask != s_in->subnet_source_mask ||
505 !common_prefix(s_out->subnet_addr, s_in->subnet_addr,
506 s_out->subnet_source_mask))
508 /* we can not accept, restart query without option */
509 verbose(VERB_QUERY, "subnet: forged data");
510 s_out->subnet_validdata = 0;
511 (void)edns_opt_list_remove(&qstate->edns_opts_back_out,
512 qstate->env->cfg->client_subnet_opcode);
514 return module_restart_next;
517 lock_rw_wrlock(&sne->biglock);
518 update_cache(qstate, id);
519 sne->num_msg_nocache++;
520 lock_rw_unlock(&sne->biglock);
522 if (sq->subnet_downstream) {
523 /* Client wants to see the answer, echo option back
524 * and adjust the scope. */
525 c_out->subnet_addr_fam = c_in->subnet_addr_fam;
526 c_out->subnet_source_mask = c_in->subnet_source_mask;
527 memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
528 c_out->subnet_scope_mask = s_in->subnet_scope_mask;
529 c_out->subnet_validdata = 1;
531 return module_finished;
534 /** Parse EDNS opt data containing ECS */
536 parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
538 memset(ecs, 0, sizeof(*ecs));
539 if (ecs_option->opt_len < 4)
542 ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
543 ecs->subnet_source_mask = ecs_option->opt_data[2];
544 ecs->subnet_scope_mask = ecs_option->opt_data[3];
545 /* remaining bytes indicate address */
548 /* option length matches calculated length? */
549 if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
551 if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
553 if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
554 if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
556 } else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
557 if (ecs->subnet_source_mask > 128 ||
558 ecs->subnet_scope_mask > 128)
563 /* valid ECS data, write to ecs_data */
564 if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
565 ecs_option->opt_len - 4, ecs->subnet_source_mask))
567 ecs->subnet_validdata = 1;
572 subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
573 struct config_file* cfg)
577 /* Construct subnet option from original query */
578 if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
579 ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
580 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
581 sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
582 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
583 (uint8_t *)sinaddr, INET_SIZE,
584 ecs->subnet_source_mask)) {
585 ecs->subnet_validdata = 1;
590 ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
591 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
592 sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
593 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
594 (uint8_t *)sinaddr, INET6_SIZE,
595 ecs->subnet_source_mask)) {
596 ecs->subnet_validdata = 1;
600 /* We don't know how to handle ip6, just pass */
605 ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
606 int id, void* ATTR_UNUSED(cbargs))
608 struct subnet_qstate *sq;
610 if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
613 if(sq->subnet_sent &&
614 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
615 /* REFUSED response to ECS query, remove ECS option. */
616 edns_opt_list_remove(&qstate->edns_opts_back_out,
617 qstate->env->cfg->client_subnet_opcode);
619 memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
625 ecs_edns_back_parsed(struct module_qstate* qstate, int id,
626 void* ATTR_UNUSED(cbargs))
628 struct subnet_qstate *sq;
629 struct edns_option* ecs_opt;
631 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
633 if((ecs_opt = edns_opt_list_find(
634 qstate->edns_opts_back_in,
635 qstate->env->cfg->client_subnet_opcode))) {
636 if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
638 sq->ecs_server_in.subnet_validdata)
639 /* Only skip global cache store if we sent an ECS option
640 * and received one back. Answers from non-whitelisted
641 * servers will end up in global cache. Answers for
642 * queries with 0 source will not (unless nameserver
643 * does not support ECS). */
644 qstate->no_cache_store = 1;
651 subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
652 int id, struct outbound_entry* outbound)
654 struct subnet_env *sne = qstate->env->modinfo[id];
655 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
657 verbose(VERB_QUERY, "subnet[module %d] operate: extstate:%s "
658 "event:%s", id, strextstate(qstate->ext_state[id]),
659 strmodulevent(event));
660 log_query_info(VERB_QUERY, "subnet operate: query", &qstate->qinfo);
662 if((event == module_event_new || event == module_event_pass) &&
664 struct edns_option* ecs_opt;
665 if(!subnet_new_qstate(qstate, id)) {
666 qstate->return_msg = NULL;
667 qstate->ext_state[id] = module_finished;
671 sq = (struct subnet_qstate*)qstate->minfo[id];
673 if((ecs_opt = edns_opt_list_find(
674 qstate->edns_opts_front_in,
675 qstate->env->cfg->client_subnet_opcode))) {
676 if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
677 /* Wrongly formatted ECS option. RFC mandates to
678 * return FORMERROR. */
679 qstate->return_rcode = LDNS_RCODE_FORMERR;
680 qstate->ext_state[id] = module_finished;
683 sq->subnet_downstream = 1;
685 else if(qstate->mesh_info->reply_list) {
686 subnet_option_from_ss(
687 &qstate->mesh_info->reply_list->query_reply.addr,
688 &sq->ecs_client_in, qstate->env->cfg);
691 if(sq->ecs_client_in.subnet_validdata == 0) {
692 /* No clients are interested in result or we could not
693 * parse it, we don't do client subnet */
694 sq->ecs_server_out.subnet_validdata = 0;
695 verbose(VERB_ALGO, "subnet: pass to next module");
696 qstate->ext_state[id] = module_wait_module;
700 lock_rw_wrlock(&sne->biglock);
701 if (lookup_and_reply(qstate, id, sq)) {
702 sne->num_msg_cache++;
703 lock_rw_unlock(&sne->biglock);
704 verbose(VERB_QUERY, "subnet: answered from cache");
705 qstate->ext_state[id] = module_finished;
707 ecs_opt_list_append(&sq->ecs_client_out,
708 &qstate->edns_opts_front_out, qstate);
711 lock_rw_unlock(&sne->biglock);
713 sq->ecs_server_out.subnet_addr_fam =
714 sq->ecs_client_in.subnet_addr_fam;
715 sq->ecs_server_out.subnet_source_mask =
716 sq->ecs_client_in.subnet_source_mask;
717 /* Limit source prefix to configured maximum */
718 if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
719 && sq->ecs_server_out.subnet_source_mask >
720 qstate->env->cfg->max_client_subnet_ipv4)
721 sq->ecs_server_out.subnet_source_mask =
722 qstate->env->cfg->max_client_subnet_ipv4;
723 else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
724 && sq->ecs_server_out.subnet_source_mask >
725 qstate->env->cfg->max_client_subnet_ipv6)
726 sq->ecs_server_out.subnet_source_mask =
727 qstate->env->cfg->max_client_subnet_ipv6;
728 /* Safe to copy completely, even if the source is limited by the
729 * configuration. ecs_opt_list_append() will limit the address.
731 memcpy(&sq->ecs_server_out.subnet_addr,
732 sq->ecs_client_in.subnet_addr, INET6_SIZE);
733 sq->ecs_server_out.subnet_scope_mask = 0;
734 sq->ecs_server_out.subnet_validdata = 1;
735 if(sq->ecs_server_out.subnet_source_mask != 0 &&
736 qstate->env->cfg->client_subnet_always_forward &&
737 sq->subnet_downstream)
738 /* ECS specific data required, do not look at the global
739 * cache in other modules. */
740 qstate->no_cache_lookup = 1;
742 /* pass request to next module */
744 "subnet: not found in cache. pass to next module");
745 qstate->ext_state[id] = module_wait_module;
748 /* Query handed back by next module, we have a 'final' answer */
749 if(sq && event == module_event_moddone) {
750 qstate->ext_state[id] = eval_response(qstate, id, sq);
751 if(qstate->ext_state[id] == module_finished &&
752 qstate->return_msg) {
753 ecs_opt_list_append(&sq->ecs_client_out,
754 &qstate->edns_opts_front_out, qstate);
761 /* We are being revisited */
762 if(event == module_event_pass || event == module_event_new) {
763 /* Just pass it on, we already did the work */
764 verbose(VERB_ALGO, "subnet: pass to next module");
765 qstate->ext_state[id] = module_wait_module;
768 if(!sq && (event == module_event_moddone)) {
769 /* during priming, module done but we never started */
770 qstate->ext_state[id] = module_finished;
773 log_err("subnet: bad event %s", strmodulevent(event));
774 qstate->ext_state[id] = module_error;
779 subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
782 /* qstate has no data outside region */
786 subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
787 int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
793 subnetmod_get_mem(struct module_env *env, int id)
795 struct subnet_env *sn_env = env->modinfo[id];
796 if (!sn_env) return 0;
797 return sizeof(*sn_env) +
798 slabhash_get_mem(sn_env->subnet_msg_cache) +
799 ecs_whitelist_get_mem(sn_env->whitelist);
803 * The module function block
805 static struct module_func_block subnetmod_block = {
806 "subnet", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
807 &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
810 struct module_func_block*
811 subnetmod_get_funcblock(void)
813 return &subnetmod_block;
816 /** Wrappers for static functions to unit test */
818 unittest_wrapper_subnetmod_sizefunc(void *elemptr)
820 return sizefunc(elemptr);
823 #endif /* CLIENT_SUBNET */