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