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