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