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