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/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"
60 #ifdef USE_CACHEDB
61 #include "cachedb/cachedb.h"
62 #endif
63
64 /** externally called */
65 void
subnet_data_delete(void * d,void * ATTR_UNUSED (arg))66 subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
67 {
68 struct subnet_msg_cache_data *r;
69 r = (struct subnet_msg_cache_data*)d;
70 addrtree_delete(r->tree4);
71 addrtree_delete(r->tree6);
72 free(r);
73 }
74
75 /** externally called */
76 size_t
msg_cache_sizefunc(void * k,void * d)77 msg_cache_sizefunc(void *k, void *d)
78 {
79 struct msgreply_entry *q = (struct msgreply_entry*)k;
80 struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
81 size_t s = sizeof(struct msgreply_entry)
82 + sizeof(struct subnet_msg_cache_data)
83 + q->key.qname_len + lock_get_mem(&q->entry.lock);
84 s += addrtree_size(r->tree4);
85 s += addrtree_size(r->tree6);
86 return s;
87 }
88
89 /** new query for ecs module */
90 static int
subnet_new_qstate(struct module_qstate * qstate,int id)91 subnet_new_qstate(struct module_qstate *qstate, int id)
92 {
93 struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
94 qstate->region, sizeof(struct subnet_qstate));
95 if(!sq)
96 return 0;
97 qstate->minfo[id] = sq;
98 memset(sq, 0, sizeof(*sq));
99 sq->started_no_cache_store = qstate->no_cache_store;
100 sq->started_no_cache_lookup = qstate->no_cache_lookup;
101 return 1;
102 }
103
104 /** Add ecs struct to edns list, after parsing it to wire format. */
105 void
subnet_ecs_opt_list_append(struct ecs_data * ecs,struct edns_option ** list,struct module_qstate * qstate,struct regional * region)106 subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
107 struct module_qstate *qstate, struct regional *region)
108 {
109 size_t sn_octs, sn_octs_remainder;
110 sldns_buffer* buf = qstate->env->scratch_buffer;
111
112 if(ecs->subnet_validdata) {
113 log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
114 ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
115 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
116 ecs->subnet_source_mask <= INET_SIZE*8);
117 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
118 ecs->subnet_source_mask <= INET6_SIZE*8);
119
120 sn_octs = ecs->subnet_source_mask / 8;
121 sn_octs_remainder =
122 (size_t)((ecs->subnet_source_mask % 8)>0?1:0);
123
124 log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
125
126 sldns_buffer_clear(buf);
127 sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
128 sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
129 sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
130 sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
131 if(sn_octs_remainder)
132 sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
133 ~(0xFF >> (ecs->subnet_source_mask % 8)));
134 sldns_buffer_flip(buf);
135
136 edns_opt_list_append(list,
137 qstate->env->cfg->client_subnet_opcode,
138 sn_octs + sn_octs_remainder + 4,
139 sldns_buffer_begin(buf), region);
140 }
141 }
142
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))143 int ecs_whitelist_check(struct query_info* qinfo,
144 uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
145 struct sockaddr_storage* addr, socklen_t addrlen,
146 uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
147 struct regional *region, int id, void* ATTR_UNUSED(cbargs))
148 {
149 struct subnet_qstate *sq;
150 struct subnet_env *sn_env;
151
152 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
153 return 1;
154 sn_env = (struct subnet_env*)qstate->env->modinfo[id];
155
156 /* Cache by default, might be disabled after parsing EDNS option
157 * received from nameserver. */
158 if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
159 qstate->no_cache_store = 0;
160 }
161
162 sq->subnet_sent_no_subnet = 0;
163 if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
164 qstate->env->cfg->client_subnet_always_forward) ||
165 ecs_is_whitelisted(sn_env->whitelist,
166 addr, addrlen, qinfo->qname, qinfo->qname_len,
167 qinfo->qclass))) {
168 /* Address on whitelist or client query contains ECS option, we
169 * want to sent out ECS. Only add option if it is not already
170 * set. */
171 if(!edns_opt_list_find(qstate->edns_opts_back_out,
172 qstate->env->cfg->client_subnet_opcode)) {
173 /* if the client is not wanting an EDNS subnet option,
174 * omit it and store that we omitted it but actually
175 * are doing EDNS subnet to the server. */
176 if(sq->ecs_server_out.subnet_source_mask == 0) {
177 sq->subnet_sent_no_subnet = 1;
178 sq->subnet_sent = 0;
179 return 1;
180 }
181 subnet_ecs_opt_list_append(&sq->ecs_server_out,
182 &qstate->edns_opts_back_out, qstate, region);
183 }
184 sq->subnet_sent = 1;
185 }
186 else {
187 /* Outgoing ECS option is set, but we don't want to sent it to
188 * this address, remove option. */
189 if(edns_opt_list_find(qstate->edns_opts_back_out,
190 qstate->env->cfg->client_subnet_opcode)) {
191 edns_opt_list_remove(&qstate->edns_opts_back_out,
192 qstate->env->cfg->client_subnet_opcode);
193 }
194 sq->subnet_sent = 0;
195 }
196 return 1;
197 }
198
199
200 void
subnet_markdel(void * key)201 subnet_markdel(void* key)
202 {
203 struct msgreply_entry *e = (struct msgreply_entry*)key;
204 e->key.qtype = 0;
205 e->key.qclass = 0;
206 }
207
208 int
subnetmod_init(struct module_env * env,int id)209 subnetmod_init(struct module_env *env, int id)
210 {
211 struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
212 sizeof(struct subnet_env));
213 if(!sn_env) {
214 log_err("malloc failure");
215 return 0;
216 }
217 alloc_init(&sn_env->alloc, NULL, 0);
218 env->modinfo[id] = (void*)sn_env;
219
220 /* Warn that serve-expired and prefetch do not work with the subnet
221 * module cache. */
222 if(env->cfg->serve_expired)
223 log_warn(
224 "subnetcache: serve-expired is set but not working "
225 "for data originating from the subnet module cache.");
226 if(env->cfg->prefetch)
227 log_warn(
228 "subnetcache: prefetch is set but not working "
229 "for data originating from the subnet module cache.");
230 /* Copy msg_cache settings */
231 sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
232 HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
233 msg_cache_sizefunc, query_info_compare, query_entry_delete,
234 subnet_data_delete, NULL);
235 slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
236 if(!sn_env->subnet_msg_cache) {
237 log_err("subnetcache: could not create cache");
238 free(sn_env);
239 env->modinfo[id] = NULL;
240 return 0;
241 }
242 /* whitelist for edns subnet capable servers */
243 sn_env->whitelist = ecs_whitelist_create();
244 if(!sn_env->whitelist ||
245 !ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) {
246 log_err("subnetcache: could not create ECS whitelist");
247 slabhash_delete(sn_env->subnet_msg_cache);
248 free(sn_env);
249 env->modinfo[id] = NULL;
250 return 0;
251 }
252
253 verbose(VERB_QUERY, "subnetcache: option registered (%d)",
254 env->cfg->client_subnet_opcode);
255 /* Create new mesh state for all queries. */
256 env->unique_mesh = 1;
257 if(!edns_register_option(env->cfg->client_subnet_opcode,
258 env->cfg->client_subnet_always_forward /* bypass cache */,
259 1 /* no aggregation */, env)) {
260 log_err("subnetcache: could not register opcode");
261 ecs_whitelist_delete(sn_env->whitelist);
262 slabhash_delete(sn_env->subnet_msg_cache);
263 free(sn_env);
264 env->modinfo[id] = NULL;
265 return 0;
266 }
267 inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
268 env, id);
269 inplace_cb_register((void*)ecs_edns_back_parsed,
270 inplace_cb_edns_back_parsed, NULL, env, id);
271 inplace_cb_register((void*)ecs_query_response,
272 inplace_cb_query_response, NULL, env, id);
273 lock_rw_init(&sn_env->biglock);
274 return 1;
275 }
276
277 void
subnetmod_deinit(struct module_env * env,int id)278 subnetmod_deinit(struct module_env *env, int id)
279 {
280 struct subnet_env *sn_env;
281 if(!env || !env->modinfo[id])
282 return;
283 sn_env = (struct subnet_env*)env->modinfo[id];
284 lock_rw_destroy(&sn_env->biglock);
285 inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
286 inplace_cb_delete(env, inplace_cb_query, id);
287 inplace_cb_delete(env, inplace_cb_query_response, id);
288 ecs_whitelist_delete(sn_env->whitelist);
289 slabhash_delete(sn_env->subnet_msg_cache);
290 alloc_clear(&sn_env->alloc);
291 free(sn_env);
292 env->modinfo[id] = NULL;
293 }
294
295 /** Tells client that upstream has no/improper support */
296 static void
cp_edns_bad_response(struct ecs_data * target,struct ecs_data * source)297 cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
298 {
299 target->subnet_scope_mask = 0;
300 target->subnet_source_mask = source->subnet_source_mask;
301 target->subnet_addr_fam = source->subnet_addr_fam;
302 memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
303 target->subnet_validdata = 1;
304 }
305
306 static void
delfunc(void * envptr,void * elemptr)307 delfunc(void *envptr, void *elemptr) {
308 struct reply_info *elem = (struct reply_info *)elemptr;
309 struct subnet_env *env = (struct subnet_env *)envptr;
310 reply_info_parsedelete(elem, &env->alloc);
311 }
312
313 static size_t
sizefunc(void * elemptr)314 sizefunc(void *elemptr) {
315 struct reply_info *elem = (struct reply_info *)elemptr;
316 size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
317 + elem->rrset_count * sizeof (struct rrset_ref)
318 + elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
319 size_t i;
320 for (i = 0; i < elem->rrset_count; i++) {
321 struct ub_packed_rrset_key *key = elem->rrsets[i];
322 struct packed_rrset_data *data = key->entry.data;
323 s += ub_rrset_sizefunc(key, data);
324 }
325 if(elem->reason_bogus_str)
326 s += strlen(elem->reason_bogus_str)+1;
327 return s;
328 }
329
330 /**
331 * Select tree from cache entry based on edns data.
332 * If for address family not present it will create a new one.
333 * NULL on failure to create. */
334 static struct addrtree*
get_tree(struct subnet_msg_cache_data * data,struct ecs_data * edns,struct subnet_env * env,struct config_file * cfg)335 get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
336 struct subnet_env *env, struct config_file* cfg)
337 {
338 struct addrtree *tree;
339 if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
340 if (!data->tree4)
341 data->tree4 = addrtree_create(
342 cfg->max_client_subnet_ipv4, &delfunc,
343 &sizefunc, env, cfg->max_ecs_tree_size_ipv4);
344 tree = data->tree4;
345 } else {
346 if (!data->tree6)
347 data->tree6 = addrtree_create(
348 cfg->max_client_subnet_ipv6, &delfunc,
349 &sizefunc, env, cfg->max_ecs_tree_size_ipv6);
350 tree = data->tree6;
351 }
352 return tree;
353 }
354
355 static void
update_cache(struct module_qstate * qstate,int id)356 update_cache(struct module_qstate *qstate, int id)
357 {
358 struct msgreply_entry *mrep_entry;
359 struct addrtree *tree;
360 struct reply_info *rep;
361 struct query_info qinf;
362 struct subnet_env *sne = qstate->env->modinfo[id];
363 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
364 struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
365 struct ecs_data *edns = &sq->ecs_client_in;
366 size_t i;
367 int only_match_scope_zero, diff_size;
368
369 /* We already calculated hash upon lookup (lookup_and_reply) if we were
370 * allowed to look in the ECS cache */
371 hashvalue_type h = qstate->minfo[id] &&
372 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
373 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
374 query_info_hash(&qstate->qinfo, qstate->query_flags);
375 /* Step 1, general qinfo lookup */
376 struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
377 &qstate->qinfo, 1);
378 int need_to_insert = (lru_entry == NULL);
379 if (!lru_entry) {
380 void* data = calloc(1,
381 sizeof(struct subnet_msg_cache_data));
382 if(!data) {
383 log_err("malloc failed");
384 return;
385 }
386 qinf = qstate->qinfo;
387 qinf.qname = memdup(qstate->qinfo.qname,
388 qstate->qinfo.qname_len);
389 if(!qinf.qname) {
390 free(data);
391 log_err("memdup failed");
392 return;
393 }
394 mrep_entry = query_info_entrysetup(&qinf, data, h);
395 free(qinf.qname); /* if qname 'consumed', it is set to NULL */
396 if (!mrep_entry) {
397 free(data);
398 log_err("query_info_entrysetup failed");
399 return;
400 }
401 lru_entry = &mrep_entry->entry;
402 lock_rw_wrlock(&lru_entry->lock);
403 }
404 /* lru_entry->lock is locked regardless of how we got here,
405 * either from the slabhash_lookup, or above in the new allocated */
406 /* Step 2, find the correct tree */
407 if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
408 lock_rw_unlock(&lru_entry->lock);
409 log_err("subnetcache: cache insertion failed");
410 return;
411 }
412 lock_quick_lock(&sne->alloc.lock);
413 rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
414 lock_quick_unlock(&sne->alloc.lock);
415 if (!rep) {
416 lock_rw_unlock(&lru_entry->lock);
417 log_err("subnetcache: cache insertion failed");
418 return;
419 }
420
421 /* store RRsets */
422 for(i=0; i<rep->rrset_count; i++) {
423 rep->ref[i].key = rep->rrsets[i];
424 rep->ref[i].id = rep->rrsets[i]->id;
425 }
426 reply_info_set_ttls(rep, *qstate->env->now);
427 reply_info_sortref(rep);
428 rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
429 rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
430 if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
431 only_match_scope_zero = 1;
432 else only_match_scope_zero = 0;
433 diff_size = (int)tree->size_bytes;
434 addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
435 edns->subnet_source_mask, sq->max_scope, rep,
436 rep->ttl, *qstate->env->now, only_match_scope_zero);
437 diff_size = (int)tree->size_bytes - diff_size;
438
439 lock_rw_unlock(&lru_entry->lock);
440 if (need_to_insert) {
441 slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
442 NULL);
443 } else {
444 slabhash_update_space_used(subnet_msg_cache, h, NULL,
445 diff_size);
446 }
447 }
448
449 /** Lookup in cache and reply true iff reply is sent. */
450 static int
lookup_and_reply(struct module_qstate * qstate,int id,struct subnet_qstate * sq,int prefetch)451 lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
452 {
453 struct lruhash_entry *e;
454 struct module_env *env = qstate->env;
455 struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
456 hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
457 struct subnet_msg_cache_data *data;
458 struct ecs_data *ecs = &sq->ecs_client_in;
459 struct addrtree *tree;
460 struct addrnode *node;
461 uint8_t scope;
462
463 memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
464
465 if (sq) {
466 sq->qinfo_hash = h; /* Might be useful on cache miss */
467 sq->qinfo_hash_calculated = 1;
468 }
469 e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
470 if (!e) return 0; /* qinfo not in cache */
471 data = e->data;
472 tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
473 data->tree4 : data->tree6;
474 if (!tree) { /* qinfo in cache but not for this family */
475 lock_rw_unlock(&e->lock);
476 return 0;
477 }
478 node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
479 ecs->subnet_source_mask, *env->now);
480 if (!node) { /* plain old cache miss */
481 lock_rw_unlock(&e->lock);
482 return 0;
483 }
484
485 qstate->return_msg = tomsg(NULL, &qstate->qinfo,
486 (struct reply_info *)node->elem, qstate->region, *env->now, 0,
487 env->scratch);
488 scope = (uint8_t)node->scope;
489 lock_rw_unlock(&e->lock);
490
491 if (!qstate->return_msg) { /* Failed allocation or expired TTL */
492 return 0;
493 }
494
495 if (sq->subnet_downstream) { /* relay to interested client */
496 sq->ecs_client_out.subnet_scope_mask = scope;
497 sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
498 sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
499 memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
500 INET6_SIZE);
501 sq->ecs_client_out.subnet_validdata = 1;
502 }
503
504 if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) {
505 qstate->need_refetch = 1;
506 }
507 return 1;
508 }
509
510 /**
511 * Test first bits of addresses for equality. Caller is responsible
512 * for making sure that both a and b are at least net/8 octets long.
513 * @param a: first address.
514 * @param a: seconds address.
515 * @param net: Number of bits to test.
516 * @return: 1 if equal, 0 otherwise.
517 */
518 static int
common_prefix(uint8_t * a,uint8_t * b,uint8_t net)519 common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
520 {
521 size_t n = (size_t)net / 8;
522 return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
523 }
524
525 static enum module_ext_state
eval_response(struct module_qstate * qstate,int id,struct subnet_qstate * sq)526 eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
527 {
528 struct subnet_env *sne = qstate->env->modinfo[id];
529
530 struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */
531 struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
532 struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */
533 struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
534
535 memset(c_out, 0, sizeof(*c_out));
536
537 if (!qstate->return_msg) {
538 /* already an answer and its not a message, but retain
539 * the actual rcode, instead of module_error, so send
540 * module_finished */
541 return module_finished;
542 }
543
544 /* We have not asked for subnet data */
545 if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
546 if (s_in->subnet_validdata)
547 verbose(VERB_QUERY, "subnetcache: received spurious data");
548 if (sq->subnet_downstream) /* Copy back to client */
549 cp_edns_bad_response(c_out, c_in);
550 return module_finished;
551 }
552
553 /* subnet sent but nothing came back */
554 if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
555 /* The authority indicated no support for edns subnet. As a
556 * consequence the answer ended up in the regular cache. It
557 * is still useful to put it in the edns subnet cache for
558 * when a client explicitly asks for subnet specific answer. */
559 verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
560 if(!sq->started_no_cache_store) {
561 lock_rw_wrlock(&sne->biglock);
562 update_cache(qstate, id);
563 lock_rw_unlock(&sne->biglock);
564 }
565 if (sq->subnet_downstream)
566 cp_edns_bad_response(c_out, c_in);
567 return module_finished;
568 }
569
570 /* Purposefully there was no sent subnet, and there is consequently
571 * no subnet in the answer. If there was, use the subnet in the answer
572 * anyway. But if there is not, treat it as a prefix 0 answer. */
573 if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
574 /* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
575 s_in->subnet_addr_fam = s_out->subnet_addr_fam;
576 s_in->subnet_source_mask = 0;
577 s_in->subnet_scope_mask = 0;
578 memset(s_in->subnet_addr, 0, INET6_SIZE);
579 s_in->subnet_validdata = 1;
580 }
581
582 /* Being here means we have asked for and got a subnet specific
583 * answer. Also, the answer from the authority is not yet cached
584 * anywhere. */
585
586 /* can we accept response? */
587 if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
588 s_out->subnet_source_mask != s_in->subnet_source_mask ||
589 !common_prefix(s_out->subnet_addr, s_in->subnet_addr,
590 s_out->subnet_source_mask))
591 {
592 /* we can not accept, restart query without option */
593 verbose(VERB_QUERY, "subnetcache: forged data");
594 s_out->subnet_validdata = 0;
595 (void)edns_opt_list_remove(&qstate->edns_opts_back_out,
596 qstate->env->cfg->client_subnet_opcode);
597 sq->subnet_sent = 0;
598 sq->subnet_sent_no_subnet = 0;
599 return module_restart_next;
600 }
601
602 lock_rw_wrlock(&sne->biglock);
603 if(!sq->started_no_cache_store) {
604 update_cache(qstate, id);
605 }
606 sne->num_msg_nocache++;
607 lock_rw_unlock(&sne->biglock);
608
609 /* If there is an expired answer in the global cache, remove that,
610 * because expired answers would otherwise resurface once the ecs data
611 * expires, giving once in a while global data responses for ecs
612 * domains, with serve expired enabled. */
613 if(qstate->env->cfg->serve_expired) {
614 msg_cache_remove(qstate->env, qstate->qinfo.qname,
615 qstate->qinfo.qname_len, qstate->qinfo.qtype,
616 qstate->qinfo.qclass, 0);
617 #ifdef USE_CACHEDB
618 if(qstate->env->cachedb_enabled)
619 cachedb_msg_remove(qstate);
620 #endif
621 }
622
623 if (sq->subnet_downstream) {
624 /* Client wants to see the answer, echo option back
625 * and adjust the scope. */
626 c_out->subnet_addr_fam = c_in->subnet_addr_fam;
627 c_out->subnet_source_mask = c_in->subnet_source_mask;
628 memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
629 c_out->subnet_scope_mask = sq->max_scope;
630 /* Limit scope returned to client to scope used for caching. */
631 if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
632 if(c_out->subnet_scope_mask >
633 qstate->env->cfg->max_client_subnet_ipv4) {
634 c_out->subnet_scope_mask =
635 qstate->env->cfg->max_client_subnet_ipv4;
636 }
637 }
638 else if(c_out->subnet_scope_mask >
639 qstate->env->cfg->max_client_subnet_ipv6) {
640 c_out->subnet_scope_mask =
641 qstate->env->cfg->max_client_subnet_ipv6;
642 }
643 c_out->subnet_validdata = 1;
644 }
645 return module_finished;
646 }
647
648 /** Parse EDNS opt data containing ECS */
649 static int
parse_subnet_option(struct edns_option * ecs_option,struct ecs_data * ecs)650 parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
651 {
652 memset(ecs, 0, sizeof(*ecs));
653 if (ecs_option->opt_len < 4)
654 return 0;
655
656 ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
657 ecs->subnet_source_mask = ecs_option->opt_data[2];
658 ecs->subnet_scope_mask = ecs_option->opt_data[3];
659 /* remaining bytes indicate address */
660
661 /* validate input*/
662 /* option length matches calculated length? */
663 if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
664 return 0;
665 if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
666 return 0;
667 if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
668 if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
669 return 0;
670 } else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
671 if (ecs->subnet_source_mask > 128 ||
672 ecs->subnet_scope_mask > 128)
673 return 0;
674 } else
675 return 0;
676
677 /* valid ECS data, write to ecs_data */
678 if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
679 ecs_option->opt_len - 4, ecs->subnet_source_mask))
680 return 0;
681 ecs->subnet_validdata = 1;
682 return 1;
683 }
684
685 void
subnet_option_from_ss(struct sockaddr_storage * ss,struct ecs_data * ecs,struct config_file * cfg)686 subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
687 struct config_file* cfg)
688 {
689 void* sinaddr;
690
691 /* Construct subnet option from original query */
692 if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
693 ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
694 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
695 sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
696 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
697 (uint8_t *)sinaddr, INET_SIZE,
698 ecs->subnet_source_mask)) {
699 ecs->subnet_validdata = 1;
700 }
701 }
702 #ifdef INET6
703 else {
704 ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
705 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
706 sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
707 if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
708 (uint8_t *)sinaddr, INET6_SIZE,
709 ecs->subnet_source_mask)) {
710 ecs->subnet_validdata = 1;
711 }
712 }
713 #else
714 /* We don't know how to handle ip6, just pass */
715 #endif /* INET6 */
716 }
717
718 int
ecs_query_response(struct module_qstate * qstate,struct dns_msg * response,int id,void * ATTR_UNUSED (cbargs))719 ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
720 int id, void* ATTR_UNUSED(cbargs))
721 {
722 struct subnet_qstate *sq;
723
724 if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
725 return 1;
726
727 if(sq->subnet_sent &&
728 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
729 /* REFUSED response to ECS query, remove ECS option. */
730 edns_opt_list_remove(&qstate->edns_opts_back_out,
731 qstate->env->cfg->client_subnet_opcode);
732 sq->subnet_sent = 0;
733 sq->subnet_sent_no_subnet = 0;
734 memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
735 } else if (!sq->track_max_scope &&
736 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
737 response->rep->an_numrrsets > 0
738 ) {
739 struct ub_packed_rrset_key* s = response->rep->rrsets[0];
740 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
741 query_dname_compare(qstate->qinfo.qname,
742 s->rk.dname) == 0) {
743 /* CNAME response for QNAME. From now on keep track of
744 * longest received ECS prefix for all queries on this
745 * qstate. */
746 sq->track_max_scope = 1;
747 }
748 }
749 return 1;
750 }
751
752 /** verbose print edns subnet option in pretty print */
753 static void
subnet_log_print(const char * s,struct edns_option * ecs_opt)754 subnet_log_print(const char* s, struct edns_option* ecs_opt)
755 {
756 if(verbosity >= VERB_ALGO) {
757 char buf[256];
758 char* str = buf;
759 size_t str_len = sizeof(buf);
760 if(!ecs_opt) {
761 verbose(VERB_ALGO, "%s (null)", s);
762 return;
763 }
764 (void)sldns_wire2str_edns_subnet_print(&str, &str_len,
765 ecs_opt->opt_data, ecs_opt->opt_len);
766 verbose(VERB_ALGO, "%s %s", s, buf);
767 }
768 }
769
770 int
ecs_edns_back_parsed(struct module_qstate * qstate,int id,void * ATTR_UNUSED (cbargs))771 ecs_edns_back_parsed(struct module_qstate* qstate, int id,
772 void* ATTR_UNUSED(cbargs))
773 {
774 struct subnet_qstate *sq;
775 struct edns_option* ecs_opt;
776
777 if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
778 return 1;
779 if((ecs_opt = edns_opt_list_find(
780 qstate->edns_opts_back_in,
781 qstate->env->cfg->client_subnet_opcode)) &&
782 parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
783 sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
784 subnet_log_print("answer has edns subnet", ecs_opt);
785 /* Only skip global cache store if we sent an ECS option
786 * and received one back. Answers from non-whitelisted
787 * servers will end up in global cache. Answers for
788 * queries with 0 source will not (unless nameserver
789 * does not support ECS). */
790 qstate->no_cache_store = 1;
791 if(!sq->track_max_scope || (sq->track_max_scope &&
792 sq->ecs_server_in.subnet_scope_mask >
793 sq->max_scope))
794 sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
795 } else if(sq->subnet_sent_no_subnet) {
796 /* The answer can be stored as scope 0, not in global cache. */
797 qstate->no_cache_store = 1;
798 }
799
800 return 1;
801 }
802
803 void
subnetmod_operate(struct module_qstate * qstate,enum module_ev event,int id,struct outbound_entry * outbound)804 subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
805 int id, struct outbound_entry* outbound)
806 {
807 struct subnet_env *sne = qstate->env->modinfo[id];
808 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
809
810 verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s "
811 "event:%s", id, strextstate(qstate->ext_state[id]),
812 strmodulevent(event));
813 log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
814
815 if((event == module_event_new || event == module_event_pass) &&
816 sq == NULL) {
817 struct edns_option* ecs_opt;
818 if(!subnet_new_qstate(qstate, id)) {
819 qstate->return_msg = NULL;
820 qstate->ext_state[id] = module_finished;
821 return;
822 }
823
824 sq = (struct subnet_qstate*)qstate->minfo[id];
825
826 if((ecs_opt = edns_opt_list_find(
827 qstate->edns_opts_front_in,
828 qstate->env->cfg->client_subnet_opcode))) {
829 if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
830 /* Wrongly formatted ECS option. RFC mandates to
831 * return FORMERROR. */
832 qstate->return_rcode = LDNS_RCODE_FORMERR;
833 qstate->ext_state[id] = module_finished;
834 return;
835 }
836 subnet_log_print("query has edns subnet", ecs_opt);
837 sq->subnet_downstream = 1;
838 }
839 else if(qstate->mesh_info->reply_list) {
840 subnet_option_from_ss(
841 &qstate->mesh_info->reply_list->query_reply.client_addr,
842 &sq->ecs_client_in, qstate->env->cfg);
843 }
844 else if(qstate->client_addr.ss_family != AF_UNSPEC) {
845 subnet_option_from_ss(
846 &qstate->client_addr,
847 &sq->ecs_client_in, qstate->env->cfg);
848 }
849
850 if(sq->ecs_client_in.subnet_validdata == 0) {
851 /* No clients are interested in result or we could not
852 * parse it, we don't do client subnet */
853 sq->ecs_server_out.subnet_validdata = 0;
854 verbose(VERB_ALGO, "subnetcache: pass to next module");
855 qstate->ext_state[id] = module_wait_module;
856 return;
857 }
858
859 /* Limit to minimum allowed source mask */
860 if(sq->ecs_client_in.subnet_source_mask != 0 && (
861 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 &&
862 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) ||
863 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 &&
864 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) {
865 qstate->return_rcode = LDNS_RCODE_REFUSED;
866 qstate->ext_state[id] = module_finished;
867 return;
868 }
869
870 if(!sq->started_no_cache_lookup && !qstate->blacklist) {
871 lock_rw_wrlock(&sne->biglock);
872 if(qstate->mesh_info->reply_list &&
873 lookup_and_reply(qstate, id, sq,
874 qstate->env->cfg->prefetch)) {
875 sne->num_msg_cache++;
876 lock_rw_unlock(&sne->biglock);
877 verbose(VERB_QUERY, "subnetcache: answered from cache");
878 qstate->ext_state[id] = module_finished;
879
880 subnet_ecs_opt_list_append(&sq->ecs_client_out,
881 &qstate->edns_opts_front_out, qstate,
882 qstate->region);
883 if(verbosity >= VERB_ALGO) {
884 subnet_log_print("reply has edns subnet",
885 edns_opt_list_find(
886 qstate->edns_opts_front_out,
887 qstate->env->cfg->
888 client_subnet_opcode));
889 }
890 return;
891 }
892 lock_rw_unlock(&sne->biglock);
893 }
894
895 sq->ecs_server_out.subnet_addr_fam =
896 sq->ecs_client_in.subnet_addr_fam;
897 sq->ecs_server_out.subnet_source_mask =
898 sq->ecs_client_in.subnet_source_mask;
899 /* Limit source prefix to configured maximum */
900 if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
901 && sq->ecs_server_out.subnet_source_mask >
902 qstate->env->cfg->max_client_subnet_ipv4)
903 sq->ecs_server_out.subnet_source_mask =
904 qstate->env->cfg->max_client_subnet_ipv4;
905 else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
906 && sq->ecs_server_out.subnet_source_mask >
907 qstate->env->cfg->max_client_subnet_ipv6)
908 sq->ecs_server_out.subnet_source_mask =
909 qstate->env->cfg->max_client_subnet_ipv6;
910 /* Safe to copy completely, even if the source is limited by the
911 * configuration. subnet_ecs_opt_list_append() will limit the address.
912 * */
913 memcpy(&sq->ecs_server_out.subnet_addr,
914 sq->ecs_client_in.subnet_addr, INET6_SIZE);
915 sq->ecs_server_out.subnet_scope_mask = 0;
916 sq->ecs_server_out.subnet_validdata = 1;
917 if(sq->ecs_server_out.subnet_source_mask != 0 &&
918 qstate->env->cfg->client_subnet_always_forward &&
919 sq->subnet_downstream)
920 /* ECS specific data required, do not look at the global
921 * cache in other modules. */
922 qstate->no_cache_lookup = 1;
923
924 /* pass request to next module */
925 verbose(VERB_ALGO,
926 "subnetcache: not found in cache. pass to next module");
927 qstate->ext_state[id] = module_wait_module;
928 return;
929 }
930 /* Query handed back by next module, we have a 'final' answer */
931 if(sq && event == module_event_moddone) {
932 qstate->ext_state[id] = eval_response(qstate, id, sq);
933 if(qstate->ext_state[id] == module_finished &&
934 qstate->return_msg) {
935 subnet_ecs_opt_list_append(&sq->ecs_client_out,
936 &qstate->edns_opts_front_out, qstate,
937 qstate->region);
938 if(verbosity >= VERB_ALGO) {
939 subnet_log_print("reply has edns subnet",
940 edns_opt_list_find(
941 qstate->edns_opts_front_out,
942 qstate->env->cfg->
943 client_subnet_opcode));
944 }
945 }
946 qstate->no_cache_store = sq->started_no_cache_store;
947 qstate->no_cache_lookup = sq->started_no_cache_lookup;
948 return;
949 }
950 if(sq && outbound) {
951 return;
952 }
953 /* We are being revisited */
954 if(event == module_event_pass || event == module_event_new) {
955 /* Just pass it on, we already did the work */
956 verbose(VERB_ALGO, "subnetcache: pass to next module");
957 qstate->ext_state[id] = module_wait_module;
958 return;
959 }
960 if(!sq && (event == module_event_moddone)) {
961 /* during priming, module done but we never started */
962 qstate->ext_state[id] = module_finished;
963 return;
964 }
965 log_err("subnetcache: bad event %s", strmodulevent(event));
966 qstate->ext_state[id] = module_error;
967 return;
968 }
969
970 void
subnetmod_clear(struct module_qstate * ATTR_UNUSED (qstate),int ATTR_UNUSED (id))971 subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
972 int ATTR_UNUSED(id))
973 {
974 /* qstate has no data outside region */
975 }
976
977 void
subnetmod_inform_super(struct module_qstate * ATTR_UNUSED (qstate),int ATTR_UNUSED (id),struct module_qstate * ATTR_UNUSED (super))978 subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
979 int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
980 {
981 /* Not used */
982 }
983
984 size_t
subnetmod_get_mem(struct module_env * env,int id)985 subnetmod_get_mem(struct module_env *env, int id)
986 {
987 struct subnet_env *sn_env = env->modinfo[id];
988 if (!sn_env) return 0;
989 return sizeof(*sn_env) +
990 slabhash_get_mem(sn_env->subnet_msg_cache) +
991 ecs_whitelist_get_mem(sn_env->whitelist);
992 }
993
994 /**
995 * The module function block
996 */
997 static struct module_func_block subnetmod_block = {
998 "subnetcache",
999 NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
1000 &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
1001 };
1002
1003 struct module_func_block*
subnetmod_get_funcblock(void)1004 subnetmod_get_funcblock(void)
1005 {
1006 return &subnetmod_block;
1007 }
1008
1009 /** Wrappers for static functions to unit test */
1010 size_t
unittest_wrapper_subnetmod_sizefunc(void * elemptr)1011 unittest_wrapper_subnetmod_sizefunc(void *elemptr)
1012 {
1013 return sizefunc(elemptr);
1014 }
1015
1016 #endif /* CLIENT_SUBNET */
1017