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 	struct addrtree* tree4;
73 	struct addrtree* tree6;
74 };
75 
76 struct subnet_qstate {
77 	/** We need the hash for both cache lookup and insert */
78 	hashvalue_type qinfo_hash;
79 	int qinfo_hash_calculated;
80 	/** ecs_data for client communication */
81 	struct ecs_data	ecs_client_in;
82 	struct ecs_data	ecs_client_out;
83 	/** ecss data for server communication */
84 	struct ecs_data	ecs_server_in;
85 	struct ecs_data	ecs_server_out;
86 	int subnet_downstream;
87 	int subnet_sent;
88 	/** keep track of longest received scope, set after receiving CNAME for
89 	 * incoming QNAME. */
90 	int track_max_scope;
91 	/** longest received scope mask since track_max_scope is set. This value
92 	 * is used for caching and answereing to client. */
93 	uint8_t max_scope;
94 	/** has the subnet module been started with no_cache_store? */
95 	int started_no_cache_store;
96 	/** has the subnet module been started with no_cache_lookup? */
97 	int started_no_cache_lookup;
98 };
99 
100 void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
101 size_t msg_cache_sizefunc(void* k, void* d);
102 
103 /**
104  * Get the module function block.
105  * @return: function block with function pointers to module methods.
106  */
107 struct module_func_block* subnetmod_get_funcblock(void);
108 
109 /** subnet module init */
110 int subnetmod_init(struct module_env* env, int id);
111 
112 /** subnet module deinit */
113 void subnetmod_deinit(struct module_env* env, int id);
114 
115 /** subnet module operate on a query */
116 void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
117 	int id, struct outbound_entry* outbound);
118 
119 /** subnet module  */
120 void subnetmod_inform_super(struct module_qstate* qstate, int id,
121 	struct module_qstate* super);
122 
123 /** subnet module cleanup query state */
124 void subnetmod_clear(struct module_qstate* qstate, int id);
125 
126 /** subnet module alloc size routine */
127 size_t subnetmod_get_mem(struct module_env* env, int id);
128 
129 /** Wrappers for static functions to unit test */
130 size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
131 
132 /** Whitelist check, called just before query is sent upstream. */
133 int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
134 	struct module_qstate* qstate, struct sockaddr_storage* addr,
135 	socklen_t addrlen, uint8_t* zone, size_t zonelen,
136 	struct regional* region, int id, void* cbargs);
137 
138 /** Check whether response from server contains ECS record, if so, skip cache
139  * store. Called just after parsing EDNS data from server. */
140 int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
141 
142 /** Remove ECS record from back_out when query resulted in REFUSED response. */
143 int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
144 	int id, void* cbargs);
145 
146 /** mark subnet msg to be deleted */
147 void subnet_markdel(void* key);
148 
149 /** Add ecs struct to edns list, after parsing it to wire format. */
150 void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
151 	struct module_qstate *qstate, struct regional *region);
152 
153 /** Create ecs_data from the sockaddr_storage information. */
154 void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
155 	struct config_file* cfg);
156 #endif /* SUBNETMOD_H */
157