165b390aaSDag-Erling Smørgrav /*
265b390aaSDag-Erling Smørgrav  * edns-subnet/subnetmod.h - edns subnet module. Must be called before validator
365b390aaSDag-Erling Smørgrav  * and iterator.
465b390aaSDag-Erling Smørgrav  *
565b390aaSDag-Erling Smørgrav  * Copyright (c) 2013, NLnet Labs. All rights reserved.
665b390aaSDag-Erling Smørgrav  *
765b390aaSDag-Erling Smørgrav  * This software is open source.
865b390aaSDag-Erling Smørgrav  *
965b390aaSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
1065b390aaSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
1165b390aaSDag-Erling Smørgrav  * are met:
1265b390aaSDag-Erling Smørgrav  *
1365b390aaSDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
1465b390aaSDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
1565b390aaSDag-Erling Smørgrav  *
1665b390aaSDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
1765b390aaSDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
1865b390aaSDag-Erling Smørgrav  * and/or other materials provided with the distribution.
1965b390aaSDag-Erling Smørgrav  *
2065b390aaSDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
2165b390aaSDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
2265b390aaSDag-Erling Smørgrav  * specific prior written permission.
2365b390aaSDag-Erling Smørgrav  *
2465b390aaSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2565b390aaSDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2665b390aaSDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2765b390aaSDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2865b390aaSDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2965b390aaSDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
3065b390aaSDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3165b390aaSDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3265b390aaSDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3365b390aaSDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3465b390aaSDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3565b390aaSDag-Erling Smørgrav  */
3665b390aaSDag-Erling Smørgrav /**
3765b390aaSDag-Erling Smørgrav  * \file
3865b390aaSDag-Erling Smørgrav  * subnet module for unbound.
3965b390aaSDag-Erling Smørgrav  */
4065b390aaSDag-Erling Smørgrav 
4165b390aaSDag-Erling Smørgrav #ifndef SUBNETMOD_H
4265b390aaSDag-Erling Smørgrav #define SUBNETMOD_H
4365b390aaSDag-Erling Smørgrav #include "util/module.h"
4465b390aaSDag-Erling Smørgrav #include "services/outbound_list.h"
4565b390aaSDag-Erling Smørgrav #include "util/alloc.h"
4665b390aaSDag-Erling Smørgrav #include "util/net_help.h"
4765b390aaSDag-Erling Smørgrav #include "util/storage/slabhash.h"
4825039b37SCy Schubert #include "util/data/dname.h"
4965b390aaSDag-Erling Smørgrav #include "edns-subnet/addrtree.h"
5065b390aaSDag-Erling Smørgrav #include "edns-subnet/edns-subnet.h"
5165b390aaSDag-Erling Smørgrav 
5265b390aaSDag-Erling Smørgrav /**
5365b390aaSDag-Erling Smørgrav  * Global state for the subnet module.
5465b390aaSDag-Erling Smørgrav  */
5565b390aaSDag-Erling Smørgrav struct subnet_env {
5665b390aaSDag-Erling Smørgrav 	/** shared message cache
5765b390aaSDag-Erling Smørgrav 	 * key: struct query_info*
5865b390aaSDag-Erling Smørgrav 	 * data: struct subnet_msg_cache_data* */
5965b390aaSDag-Erling Smørgrav 	struct slabhash* subnet_msg_cache;
6065b390aaSDag-Erling Smørgrav 	/** access control, which upstream servers we send client address */
61c7f4d7adSDag-Erling Smørgrav 	struct ecs_whitelist* whitelist;
6265b390aaSDag-Erling Smørgrav 	/** allocation service */
6365b390aaSDag-Erling Smørgrav 	struct alloc_cache alloc;
6465b390aaSDag-Erling Smørgrav 	lock_rw_type biglock;
654c75e3aaSDag-Erling Smørgrav 	/** number of messages from cache */
664c75e3aaSDag-Erling Smørgrav 	size_t num_msg_cache;
674c75e3aaSDag-Erling Smørgrav 	/** number of messages not from cache */
684c75e3aaSDag-Erling Smørgrav 	size_t num_msg_nocache;
6965b390aaSDag-Erling Smørgrav };
7065b390aaSDag-Erling Smørgrav 
7165b390aaSDag-Erling Smørgrav struct subnet_msg_cache_data {
7265b390aaSDag-Erling Smørgrav 	struct addrtree* tree4;
7365b390aaSDag-Erling Smørgrav 	struct addrtree* tree6;
7465b390aaSDag-Erling Smørgrav };
7565b390aaSDag-Erling Smørgrav 
7665b390aaSDag-Erling Smørgrav struct subnet_qstate {
7765b390aaSDag-Erling Smørgrav 	/** We need the hash for both cache lookup and insert */
7865b390aaSDag-Erling Smørgrav 	hashvalue_type qinfo_hash;
790a92a9fcSCy Schubert 	int qinfo_hash_calculated;
8065b390aaSDag-Erling Smørgrav 	/** ecs_data for client communication */
8165b390aaSDag-Erling Smørgrav 	struct ecs_data	ecs_client_in;
8265b390aaSDag-Erling Smørgrav 	struct ecs_data	ecs_client_out;
8365b390aaSDag-Erling Smørgrav 	/** ecss data for server communication */
8465b390aaSDag-Erling Smørgrav 	struct ecs_data	ecs_server_in;
8565b390aaSDag-Erling Smørgrav 	struct ecs_data	ecs_server_out;
8665b390aaSDag-Erling Smørgrav 	int subnet_downstream;
8765b390aaSDag-Erling Smørgrav 	int subnet_sent;
88*103ba509SCy Schubert 	/**
89*103ba509SCy Schubert 	 * If there was no subnet sent because the client used source prefix
90*103ba509SCy Schubert 	 * length 0 for omitting the information. Then the answer is cached
91*103ba509SCy Schubert 	 * like subnet was a /0 scope. Like the subnet_sent flag, but when
92*103ba509SCy Schubert 	 * the EDNS subnet option is omitted because the client asked.
93*103ba509SCy Schubert 	 */
94*103ba509SCy Schubert 	int subnet_sent_no_subnet;
9525039b37SCy Schubert 	/** keep track of longest received scope, set after receiving CNAME for
9625039b37SCy Schubert 	 * incoming QNAME. */
9725039b37SCy Schubert 	int track_max_scope;
9825039b37SCy Schubert 	/** longest received scope mask since track_max_scope is set. This value
9925039b37SCy Schubert 	 * is used for caching and answereing to client. */
10025039b37SCy Schubert 	uint8_t max_scope;
101e86b9096SDag-Erling Smørgrav 	/** has the subnet module been started with no_cache_store? */
102e86b9096SDag-Erling Smørgrav 	int started_no_cache_store;
1030a92a9fcSCy Schubert 	/** has the subnet module been started with no_cache_lookup? */
1040a92a9fcSCy Schubert 	int started_no_cache_lookup;
10565b390aaSDag-Erling Smørgrav };
10665b390aaSDag-Erling Smørgrav 
10765b390aaSDag-Erling Smørgrav void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
10865b390aaSDag-Erling Smørgrav size_t msg_cache_sizefunc(void* k, void* d);
10965b390aaSDag-Erling Smørgrav 
11065b390aaSDag-Erling Smørgrav /**
11165b390aaSDag-Erling Smørgrav  * Get the module function block.
11265b390aaSDag-Erling Smørgrav  * @return: function block with function pointers to module methods.
11365b390aaSDag-Erling Smørgrav  */
11465b390aaSDag-Erling Smørgrav struct module_func_block* subnetmod_get_funcblock(void);
11565b390aaSDag-Erling Smørgrav 
11665b390aaSDag-Erling Smørgrav /** subnet module init */
11765b390aaSDag-Erling Smørgrav int subnetmod_init(struct module_env* env, int id);
11865b390aaSDag-Erling Smørgrav 
11965b390aaSDag-Erling Smørgrav /** subnet module deinit */
12065b390aaSDag-Erling Smørgrav void subnetmod_deinit(struct module_env* env, int id);
12165b390aaSDag-Erling Smørgrav 
12265b390aaSDag-Erling Smørgrav /** subnet module operate on a query */
12365b390aaSDag-Erling Smørgrav void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
12465b390aaSDag-Erling Smørgrav 	int id, struct outbound_entry* outbound);
12565b390aaSDag-Erling Smørgrav 
12665b390aaSDag-Erling Smørgrav /** subnet module  */
12765b390aaSDag-Erling Smørgrav void subnetmod_inform_super(struct module_qstate* qstate, int id,
12865b390aaSDag-Erling Smørgrav 	struct module_qstate* super);
12965b390aaSDag-Erling Smørgrav 
13065b390aaSDag-Erling Smørgrav /** subnet module cleanup query state */
13165b390aaSDag-Erling Smørgrav void subnetmod_clear(struct module_qstate* qstate, int id);
13265b390aaSDag-Erling Smørgrav 
13365b390aaSDag-Erling Smørgrav /** subnet module alloc size routine */
13465b390aaSDag-Erling Smørgrav size_t subnetmod_get_mem(struct module_env* env, int id);
13565b390aaSDag-Erling Smørgrav 
13665b390aaSDag-Erling Smørgrav /** Wrappers for static functions to unit test */
13765b390aaSDag-Erling Smørgrav size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
13865b390aaSDag-Erling Smørgrav 
13965b390aaSDag-Erling Smørgrav /** Whitelist check, called just before query is sent upstream. */
14065b390aaSDag-Erling Smørgrav int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
14165b390aaSDag-Erling Smørgrav 	struct module_qstate* qstate, struct sockaddr_storage* addr,
14265b390aaSDag-Erling Smørgrav 	socklen_t addrlen, uint8_t* zone, size_t zonelen,
14365b390aaSDag-Erling Smørgrav 	struct regional* region, int id, void* cbargs);
14465b390aaSDag-Erling Smørgrav 
1458a384985SDag-Erling Smørgrav /** Check whether response from server contains ECS record, if so, skip cache
14665b390aaSDag-Erling Smørgrav  * store. Called just after parsing EDNS data from server. */
14765b390aaSDag-Erling Smørgrav int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
14865b390aaSDag-Erling Smørgrav 
14965b390aaSDag-Erling Smørgrav /** Remove ECS record from back_out when query resulted in REFUSED response. */
15065b390aaSDag-Erling Smørgrav int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
15165b390aaSDag-Erling Smørgrav 	int id, void* cbargs);
15265b390aaSDag-Erling Smørgrav 
153e86b9096SDag-Erling Smørgrav /** mark subnet msg to be deleted */
154e86b9096SDag-Erling Smørgrav void subnet_markdel(void* key);
155e86b9096SDag-Erling Smørgrav 
156a39a5a69SCy Schubert /** Add ecs struct to edns list, after parsing it to wire format. */
157a39a5a69SCy Schubert void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
1580a92a9fcSCy Schubert 	struct module_qstate *qstate, struct regional *region);
159a39a5a69SCy Schubert 
160a39a5a69SCy Schubert /** Create ecs_data from the sockaddr_storage information. */
161a39a5a69SCy Schubert void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
162a39a5a69SCy Schubert 	struct config_file* cfg);
16365b390aaSDag-Erling Smørgrav #endif /* SUBNETMOD_H */
164