xref: /openbsd-src/usr.sbin/unbound/edns-subnet/subnetmod.h (revision d896b9629c03f816499323ea77d6aca50268e4e0)
12be9e038Ssthen /*
22be9e038Ssthen  * edns-subnet/subnetmod.h - edns subnet module. Must be called before validator
32be9e038Ssthen  * and iterator.
42be9e038Ssthen  *
52be9e038Ssthen  * Copyright (c) 2013, NLnet Labs. All rights reserved.
62be9e038Ssthen  *
72be9e038Ssthen  * This software is open source.
82be9e038Ssthen  *
92be9e038Ssthen  * Redistribution and use in source and binary forms, with or without
102be9e038Ssthen  * modification, are permitted provided that the following conditions
112be9e038Ssthen  * are met:
122be9e038Ssthen  *
132be9e038Ssthen  * Redistributions of source code must retain the above copyright notice,
142be9e038Ssthen  * this list of conditions and the following disclaimer.
152be9e038Ssthen  *
162be9e038Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
172be9e038Ssthen  * this list of conditions and the following disclaimer in the documentation
182be9e038Ssthen  * and/or other materials provided with the distribution.
192be9e038Ssthen  *
202be9e038Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
212be9e038Ssthen  * be used to endorse or promote products derived from this software without
222be9e038Ssthen  * specific prior written permission.
232be9e038Ssthen  *
242be9e038Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
252be9e038Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
262be9e038Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
272be9e038Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
282be9e038Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
292be9e038Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
302be9e038Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
312be9e038Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
322be9e038Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
332be9e038Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
342be9e038Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
352be9e038Ssthen  */
362be9e038Ssthen /**
372be9e038Ssthen  * \file
382be9e038Ssthen  * subnet module for unbound.
392be9e038Ssthen  */
402be9e038Ssthen 
412be9e038Ssthen #ifndef SUBNETMOD_H
422be9e038Ssthen #define SUBNETMOD_H
432be9e038Ssthen #include "util/module.h"
442be9e038Ssthen #include "services/outbound_list.h"
452be9e038Ssthen #include "util/alloc.h"
462be9e038Ssthen #include "util/net_help.h"
472be9e038Ssthen #include "util/storage/slabhash.h"
48a3167c07Ssthen #include "util/data/dname.h"
492be9e038Ssthen #include "edns-subnet/addrtree.h"
502be9e038Ssthen #include "edns-subnet/edns-subnet.h"
512be9e038Ssthen 
522be9e038Ssthen /**
532be9e038Ssthen  * Global state for the subnet module.
542be9e038Ssthen  */
552be9e038Ssthen struct subnet_env {
562be9e038Ssthen 	/** shared message cache
572be9e038Ssthen 	 * key: struct query_info*
582be9e038Ssthen 	 * data: struct subnet_msg_cache_data* */
592be9e038Ssthen 	struct slabhash* subnet_msg_cache;
602be9e038Ssthen 	/** access control, which upstream servers we send client address */
612be9e038Ssthen 	struct ecs_whitelist* whitelist;
622be9e038Ssthen 	/** allocation service */
632be9e038Ssthen 	struct alloc_cache alloc;
642be9e038Ssthen 	lock_rw_type biglock;
652308e98cSsthen 	/** number of messages from cache */
662308e98cSsthen 	size_t num_msg_cache;
672308e98cSsthen 	/** number of messages not from cache */
682308e98cSsthen 	size_t num_msg_nocache;
692be9e038Ssthen };
702be9e038Ssthen 
712be9e038Ssthen struct subnet_msg_cache_data {
722be9e038Ssthen 	struct addrtree* tree4;
732be9e038Ssthen 	struct addrtree* tree6;
742be9e038Ssthen };
752be9e038Ssthen 
762be9e038Ssthen struct subnet_qstate {
772be9e038Ssthen 	/** We need the hash for both cache lookup and insert */
782be9e038Ssthen 	hashvalue_type qinfo_hash;
79d1e2768aSsthen 	int qinfo_hash_calculated;
802be9e038Ssthen 	/** ecs_data for client communication */
812be9e038Ssthen 	struct ecs_data	ecs_client_in;
822be9e038Ssthen 	struct ecs_data	ecs_client_out;
832be9e038Ssthen 	/** ecss data for server communication */
842be9e038Ssthen 	struct ecs_data	ecs_server_in;
852be9e038Ssthen 	struct ecs_data	ecs_server_out;
862be9e038Ssthen 	int subnet_downstream;
872be9e038Ssthen 	int subnet_sent;
88*d896b962Ssthen 	/**
89*d896b962Ssthen 	 * If there was no subnet sent because the client used source prefix
90*d896b962Ssthen 	 * length 0 for omitting the information. Then the answer is cached
91*d896b962Ssthen 	 * like subnet was a /0 scope. Like the subnet_sent flag, but when
92*d896b962Ssthen 	 * the EDNS subnet option is omitted because the client asked.
93*d896b962Ssthen 	 */
94*d896b962Ssthen 	int subnet_sent_no_subnet;
95a3167c07Ssthen 	/** keep track of longest received scope, set after receiving CNAME for
96a3167c07Ssthen 	 * incoming QNAME. */
97a3167c07Ssthen 	int track_max_scope;
98a3167c07Ssthen 	/** longest received scope mask since track_max_scope is set. This value
99a3167c07Ssthen 	 * is used for caching and answereing to client. */
100a3167c07Ssthen 	uint8_t max_scope;
1013150e5f6Ssthen 	/** has the subnet module been started with no_cache_store? */
1023150e5f6Ssthen 	int started_no_cache_store;
103d1e2768aSsthen 	/** has the subnet module been started with no_cache_lookup? */
104d1e2768aSsthen 	int started_no_cache_lookup;
1052be9e038Ssthen };
1062be9e038Ssthen 
1072be9e038Ssthen void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
1082be9e038Ssthen size_t msg_cache_sizefunc(void* k, void* d);
1092be9e038Ssthen 
1102be9e038Ssthen /**
1112be9e038Ssthen  * Get the module function block.
1122be9e038Ssthen  * @return: function block with function pointers to module methods.
1132be9e038Ssthen  */
1142be9e038Ssthen struct module_func_block* subnetmod_get_funcblock(void);
1152be9e038Ssthen 
1162be9e038Ssthen /** subnet module init */
1172be9e038Ssthen int subnetmod_init(struct module_env* env, int id);
1182be9e038Ssthen 
1192be9e038Ssthen /** subnet module deinit */
1202be9e038Ssthen void subnetmod_deinit(struct module_env* env, int id);
1212be9e038Ssthen 
1222be9e038Ssthen /** subnet module operate on a query */
1232be9e038Ssthen void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
1242be9e038Ssthen 	int id, struct outbound_entry* outbound);
1252be9e038Ssthen 
1262be9e038Ssthen /** subnet module  */
1272be9e038Ssthen void subnetmod_inform_super(struct module_qstate* qstate, int id,
1282be9e038Ssthen 	struct module_qstate* super);
1292be9e038Ssthen 
1302be9e038Ssthen /** subnet module cleanup query state */
1312be9e038Ssthen void subnetmod_clear(struct module_qstate* qstate, int id);
1322be9e038Ssthen 
1332be9e038Ssthen /** subnet module alloc size routine */
1342be9e038Ssthen size_t subnetmod_get_mem(struct module_env* env, int id);
1352be9e038Ssthen 
1362be9e038Ssthen /** Wrappers for static functions to unit test */
1372be9e038Ssthen size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
1382be9e038Ssthen 
1392be9e038Ssthen /** Whitelist check, called just before query is sent upstream. */
1402be9e038Ssthen int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
1412be9e038Ssthen 	struct module_qstate* qstate, struct sockaddr_storage* addr,
1422be9e038Ssthen 	socklen_t addrlen, uint8_t* zone, size_t zonelen,
1432be9e038Ssthen 	struct regional* region, int id, void* cbargs);
1442be9e038Ssthen 
145bdfc4d55Sflorian /** Check whether response from server contains ECS record, if so, skip cache
1462be9e038Ssthen  * store. Called just after parsing EDNS data from server. */
1472be9e038Ssthen int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
1482be9e038Ssthen 
1492be9e038Ssthen /** Remove ECS record from back_out when query resulted in REFUSED response. */
1502be9e038Ssthen int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
1512be9e038Ssthen 	int id, void* cbargs);
1522be9e038Ssthen 
1533150e5f6Ssthen /** mark subnet msg to be deleted */
1543150e5f6Ssthen void subnet_markdel(void* key);
1553150e5f6Ssthen 
1560bdb4f62Ssthen /** Add ecs struct to edns list, after parsing it to wire format. */
1570bdb4f62Ssthen void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
158d1e2768aSsthen 	struct module_qstate *qstate, struct regional *region);
1590bdb4f62Ssthen 
1600bdb4f62Ssthen /** Create ecs_data from the sockaddr_storage information. */
1610bdb4f62Ssthen void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
1620bdb4f62Ssthen 	struct config_file* cfg);
1632be9e038Ssthen #endif /* SUBNETMOD_H */
164