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