Home | History | Annotate | Line # | Download | only in edns-subnet
      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