1/*
2 * respip/respip.h - IP-based response modification module
3 */
4
5/**
6 * \file
7 *
8 * This file contains a module that selectively modifies query responses
9 * based on their AAAA/A IP addresses.
10 */
11
12#ifndef RESPIP_RESPIP_H
13#define RESPIP_RESPIP_H
14
15#include "util/module.h"
16#include "services/localzone.h"
17#include "util/locks.h"
18
19/**
20 * Conceptual set of IP addresses for response AAAA or A records that should
21 * trigger special actions.
22 */
23struct respip_set {
24	struct regional* region;
25	struct rbtree_type ip_tree;
26	lock_rw_type lock;	/* lock on the respip tree */
27	char* const* tagname;	/* shallow copy of tag names, for logging */
28	int num_tags;		/* number of tagname entries */
29};
30
31
32/** An address span with response control information */
33struct resp_addr {
34	/** node in address tree */
35	struct addr_tree_node node;
36	/** lock on the node item */
37	lock_rw_type lock;
38	/** tag bitlist */
39	uint8_t* taglist;
40	/** length of the taglist (in bytes) */
41	size_t taglen;
42	/** action for this address span */
43	enum respip_action action;
44        /** "local data" for this node */
45	struct ub_packed_rrset_key* data;
46};
47
48
49/**
50 * Forward declaration for the structure that represents a tree of view data.
51 */
52
53struct views;
54
55struct respip_addr_info;
56
57/**
58 * Client-specific attributes that can affect IP-based actions.
59 * This is essentially a subset of acl_addr (except for respip_set) but
60 * defined as a separate structure to avoid dependency on the daemon-specific
61 * structure.
62 * respip_set is supposed to refer to the response-ip set for the global view.
63 */
64struct respip_client_info {
65	uint8_t* taglist;
66	size_t taglen;
67	uint8_t* tag_actions;
68	size_t tag_actions_size;
69	struct config_strlist** tag_datas;
70	size_t tag_datas_size;
71	struct view* view;
72	struct respip_set* respip_set;
73};
74
75/**
76 * Data items representing the result of response-ip processing.
77 * Note: this structure currently only define a few members, but exists
78 * as a separate struct mainly for the convenience of custom extensions.
79 */
80struct respip_action_info {
81	enum respip_action action;
82	int rpz_used;
83	int rpz_log;
84	int rpz_disabled;
85	char* log_name;
86	int rpz_cname_override;
87	struct respip_addr_info* addrinfo; /* set only for inform variants */
88};
89
90/**
91  * Forward declaration for the structure that represents a node in the
92  * respip_set address tree
93  */
94struct resp_addr;
95
96/**
97 * Create response IP set.
98 * @return new struct or NULL on error.
99 */
100struct respip_set* respip_set_create(void);
101
102/**
103 * Delete response IP set.
104 * @param set: to delete.
105 */
106void respip_set_delete(struct respip_set* set);
107
108/**
109 * Apply response-ip config settings to the global (default) view.
110 * It assumes exclusive access to set (no internal locks).
111 * @param set: processed global respip config data
112 * @param cfg: config data.
113 * @return 1 on success, 0 on error.
114 */
115int respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg);
116
117/**
118 * Apply response-ip config settings in named views.
119 * @param vs: view structures with processed config data
120 * @param cfg: config data.
121 * @param have_view_respip_cfg: set to true if any named view has respip
122 * 	configuration; otherwise set to false
123 * @return 1 on success, 0 on error.
124 */
125int respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
126	int* have_view_respip_cfg);
127
128/**
129 * Merge two replies to build a complete CNAME chain.
130 * It appends the content of 'tgt_rep' to 'base_rep', assuming (but not
131 * checking) the former ends with a CNAME and the latter resolves its target.
132 * A merged new reply will be built using 'region' and *new_repp will point
133 * to the new one on success.
134 * If the target reply would also be subject to a response-ip action for
135 * 'cinfo', this function uses 'base_rep' as the merged reply, ignoring
136 * 'tgt_rep'.  This is for avoiding cases like a CNAME loop or failure of
137 * applying an action to an address.
138 * RRSIGs in 'tgt_rep' will be excluded in the merged reply, as the resulting
139 * reply is assumed to be faked due to a response-ip action and can't be
140 * considered secure in terms of DNSSEC.
141 * The caller must ensure that neither 'base_rep' nor 'tgt_rep' can be modified
142 * until this function returns.
143 * @param base_rep: the reply info containing an incomplete CNAME.
144 * @param qinfo: query info corresponding to 'base_rep'.
145 * @param tgt_rep: the reply info that completes the CNAME chain.
146 * @param cinfo: client info corresponding to 'base_rep'.
147 * @param must_validate: whether 'tgt_rep' must be DNSSEC-validated.
148 * @param new_repp: pointer placeholder for the merged reply.  will be intact
149 *   on error.
150 * @param region: allocator to build *new_repp.
151 * @param az: auth zones containing RPZ information.
152 * @return 1 on success, 0 on error.
153 */
154int respip_merge_cname(struct reply_info* base_rep,
155	const struct query_info* qinfo, const struct reply_info* tgt_rep,
156	const struct respip_client_info* cinfo, int must_validate,
157	struct reply_info** new_repp, struct regional* region,
158	struct auth_zones* az);
159
160/**
161 * See if any IP-based action should apply to any IP address of AAAA/A answer
162 * record in the reply.  If so, apply the action.  In some cases it rewrites
163 * the reply rrsets, in which case *new_repp will point to the updated reply
164 * info.  Depending on the action, some of the rrsets in 'rep' will be
165 * shallow-copied into '*new_repp'; the caller must ensure that the rrsets
166 * in 'rep' are valid throughout the lifetime of *new_repp, and it must
167 * provide appropriate mutex if the rrsets can be shared by multiple threads.
168 * @param qinfo: query info corresponding to the reply.
169 * @param cinfo: client-specific info to identify the best matching action.
170 *   can be NULL.
171 * @param rep: original reply info.  must not be NULL.
172 * @param new_repp: can be set to the rewritten reply info (intact on failure).
173 * @param actinfo: result of response-ip processing
174 * @param alias_rrset: must not be NULL.
175 * @param search_only: if true, only check if an action would apply.  actionp
176 *   will be set (or intact) accordingly but the modified reply won't be built.
177 * @param az: auth zones containing RPZ information.
178 * @param region: allocator to build *new_repp.
179 * @param rpz_passthru: keeps track of query state can have passthru that
180 *   stops further rpz processing. Or NULL for cached answer processing.
181 * @return 1 on success, 0 on error.
182 */
183int respip_rewrite_reply(const struct query_info* qinfo,
184	const struct respip_client_info* cinfo,
185	const struct reply_info *rep, struct reply_info** new_repp,
186	struct respip_action_info* actinfo,
187	struct ub_packed_rrset_key** alias_rrset,
188	int search_only, struct regional* region, struct auth_zones* az,
189	int* rpz_passthru);
190
191/**
192 * Get the response-ip function block.
193 * @return: function block with function pointers to response-ip methods.
194 */
195struct module_func_block* respip_get_funcblock(void);
196
197/** response-ip init */
198int respip_init(struct module_env* env, int id);
199
200/** response-ip deinit */
201void respip_deinit(struct module_env* env, int id);
202
203/** response-ip operate on a query */
204void respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
205	struct outbound_entry* outbound);
206
207/** inform response-ip super */
208void respip_inform_super(struct module_qstate* qstate, int id,
209	struct module_qstate* super);
210
211/** response-ip cleanup query state */
212void respip_clear(struct module_qstate* qstate, int id);
213
214/**
215 * returns address of the IP address tree of the specified respip set;
216 * returns NULL for NULL input; exists for test purposes only
217 */
218struct rbtree_type* respip_set_get_tree(struct respip_set* set);
219
220/**
221 * returns respip action for the specified node in the respip address
222 * returns respip_none for NULL input; exists for test purposes only
223 */
224enum respip_action resp_addr_get_action(const struct resp_addr* addr);
225
226/**
227 * returns rrset portion of the specified node in the respip address
228 * tree; returns NULL for NULL input; exists for test purposes only
229 */
230struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr);
231
232/** response-ip alloc size routine */
233size_t respip_get_mem(struct module_env* env, int id);
234
235/**
236 * respip set emptiness test
237 * @param set respip set to test
238 * @return 0 if the specified set exists (non-NULL) and is non-empty;
239 *	otherwise returns 1
240 */
241int respip_set_is_empty(const struct respip_set* set);
242
243/**
244 * print log information for a query subject to an inform or inform-deny
245 * response-ip action.
246 * @param respip_actinfo: response-ip information that causes the action
247 * @param qname: query name in the context, will be ignored if local_alias is
248 *   non-NULL.
249 * @param qtype: query type, in host byte order.
250 * @param qclass: query class, in host byte order.
251 * @param local_alias: set to a local alias if the query matches an alias in
252 *  a local zone.  In this case its owner name will be considered the actual
253 *  query name.
254 * @param addr: the client's source address and port.
255 * @param addrlen: the client's source address length.
256 */
257void respip_inform_print(struct respip_action_info* respip_actinfo,
258	uint8_t* qname, uint16_t qtype, uint16_t qclass,
259	struct local_rrset* local_alias, struct sockaddr_storage* addr,
260	socklen_t addrlen);
261
262/**
263 * Find resp_addr in tree, create and add to tree if it does not exist.
264 * @param set: struct containing the tree and region to alloc new node on.
265 * 	should hold write lock.
266 * @param addr: address to look up.
267 * @param addrlen: length of addr.
268 * @param net: netblock to lookup.
269 * @param create: create node if it does not exist when 1.
270 * @param ipstr: human redable ip string, for logging.
271 * @return newly created of found node, not holding lock.
272 */
273struct resp_addr*
274respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
275		socklen_t addrlen, int net, int create, const char* ipstr);
276
277/**
278 * Add RR to resp_addr's RRset. Create RRset if not existing.
279 * @param region: region to alloc RR(set).
280 * @param raddr: resp_addr containing RRset. Must hold write lock.
281 * @param rrtype: RR type.
282 * @param rrclass: RR class.
283 * @param ttl: TTL.
284 * @param rdata: RDATA.
285 * @param rdata_len: length of rdata.
286 * @param rrstr: RR as string, for logging
287 * @param netblockstr: netblock as string, for logging
288 * @return 0 on error
289 */
290int
291respip_enter_rr(struct regional* region, struct resp_addr* raddr,
292	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
293	size_t rdata_len, const char* rrstr, const char* netblockstr);
294
295/**
296 * Delete resp_addr node from tree.
297 * @param set: struct containing tree. Must hold write lock.
298 * @param node: node to delete. Not locked.
299 */
300void
301respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
302
303struct ub_packed_rrset_key*
304respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region);
305#endif	/* RESPIP_RESPIP_H */
306