1 /* 2 * edns-subnet/subnetmod.h - 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 #ifndef SUBNETMOD_H 42 #define SUBNETMOD_H 43 #include "util/module.h" 44 #include "services/outbound_list.h" 45 #include "util/alloc.h" 46 #include "util/net_help.h" 47 #include "util/storage/slabhash.h" 48 #include "util/data/dname.h" 49 #include "edns-subnet/addrtree.h" 50 #include "edns-subnet/edns-subnet.h" 51 52 /** 53 * Global state for the subnet module. 54 */ 55 struct subnet_env { 56 /** shared message cache 57 * key: struct query_info* 58 * data: struct subnet_msg_cache_data* */ 59 struct slabhash* subnet_msg_cache; 60 /** access control, which upstream servers we send client address */ 61 struct ecs_whitelist* whitelist; 62 /** allocation service */ 63 struct alloc_cache alloc; 64 lock_rw_type biglock; 65 /** number of messages from cache */ 66 size_t num_msg_cache; 67 /** number of messages not from cache */ 68 size_t num_msg_nocache; 69 }; 70 71 struct subnet_msg_cache_data { 72 /** Tree for nodes with IPv4 subnets. */ 73 struct addrtree* tree4; 74 /** Tree for nodes with IPv6 subnets. */ 75 struct addrtree* tree6; 76 /** If servfail is stored, for how long. Abs time in seconds. 77 * This protects against too much recusion on the item when 78 * resolution fails, for a couple of seconds. */ 79 time_t ttl_servfail; 80 /** servfail ede */ 81 sldns_ede_code ede_fail; 82 /** servfail reason */ 83 char* reason_fail; 84 }; 85 86 struct subnet_qstate { 87 /** We need the hash for both cache lookup and insert */ 88 hashvalue_type qinfo_hash; 89 int qinfo_hash_calculated; 90 /** ecs_data for client communication */ 91 struct ecs_data ecs_client_in; 92 struct ecs_data ecs_client_out; 93 /** ecss data for server communication */ 94 struct ecs_data ecs_server_in; 95 struct ecs_data ecs_server_out; 96 int subnet_downstream; 97 int subnet_sent; 98 /** 99 * If there was no subnet sent because the client used source prefix 100 * length 0 for omitting the information. Then the answer is cached 101 * like subnet was a /0 scope. Like the subnet_sent flag, but when 102 * the EDNS subnet option is omitted because the client asked. 103 */ 104 int subnet_sent_no_subnet; 105 /** keep track of longest received scope, set after receiving CNAME for 106 * incoming QNAME. */ 107 int track_max_scope; 108 /** longest received scope mask since track_max_scope is set. This value 109 * is used for caching and answereing to client. */ 110 uint8_t max_scope; 111 /** has the subnet module been started with no_cache_store? */ 112 int started_no_cache_store; 113 /** has the subnet module been started with no_cache_lookup? */ 114 int started_no_cache_lookup; 115 /** Wait for subquery that has been started for nonsubnet lookup. */ 116 int wait_subquery; 117 /** The subquery waited for is done. */ 118 int wait_subquery_done; 119 /** The subnet state is a subquery state for nonsubnet lookup. */ 120 int is_subquery_nonsubnet; 121 /** This is a subquery, and it is made due to a scope zero request. */ 122 int is_subquery_scopezero; 123 }; 124 125 void subnet_data_delete(void* d, void* ATTR_UNUSED(arg)); 126 size_t msg_cache_sizefunc(void* k, void* d); 127 128 /** 129 * Get the module function block. 130 * @return: function block with function pointers to module methods. 131 */ 132 struct module_func_block* subnetmod_get_funcblock(void); 133 134 /** subnet module init */ 135 int subnetmod_init(struct module_env* env, int id); 136 137 /** subnet module deinit */ 138 void subnetmod_deinit(struct module_env* env, int id); 139 140 /** subnet module operate on a query */ 141 void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, 142 int id, struct outbound_entry* outbound); 143 144 /** subnet module */ 145 void subnetmod_inform_super(struct module_qstate* qstate, int id, 146 struct module_qstate* super); 147 148 /** subnet module cleanup query state */ 149 void subnetmod_clear(struct module_qstate* qstate, int id); 150 151 /** subnet module alloc size routine */ 152 size_t subnetmod_get_mem(struct module_env* env, int id); 153 154 /** Wrappers for static functions to unit test */ 155 size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr); 156 157 /** Whitelist check, called just before query is sent upstream. */ 158 int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags, 159 struct module_qstate* qstate, struct sockaddr_storage* addr, 160 socklen_t addrlen, uint8_t* zone, size_t zonelen, 161 struct regional* region, int id, void* cbargs); 162 163 /** Check whether response from server contains ECS record, if so, skip cache 164 * store. Called just after parsing EDNS data from server. */ 165 int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs); 166 167 /** Remove ECS record from back_out when query resulted in REFUSED response. */ 168 int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, 169 int id, void* cbargs); 170 171 /** mark subnet msg to be deleted */ 172 void subnet_markdel(void* key); 173 174 /** Add ecs struct to edns list, after parsing it to wire format. */ 175 void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list, 176 struct module_qstate *qstate, struct regional *region); 177 178 /** Create ecs_data from the sockaddr_storage information. */ 179 void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, 180 struct config_file* cfg); 181 #endif /* SUBNETMOD_H */ 182