xref: /freebsd/contrib/unbound/respip/respip.h (revision 43a5ec4eb41567cc92586503212743d89686d78f)
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 */
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 */
33 struct 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 
53 struct views;
54 
55 struct 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  */
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 	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  */
80 struct 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   */
94 struct resp_addr;
95 
96 /**
97  * Create response IP set.
98  * @return new struct or NULL on error.
99  */
100 struct respip_set* respip_set_create(void);
101 
102 /**
103  * Delete response IP set.
104  * @param set: to delete.
105  */
106 void 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  */
115 int 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  */
125 int 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  */
154 int 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  * @return 1 on success, 0 on error.
180  */
181 int respip_rewrite_reply(const struct query_info* qinfo,
182 	const struct respip_client_info* cinfo,
183 	const struct reply_info *rep, struct reply_info** new_repp,
184 	struct respip_action_info* actinfo,
185 	struct ub_packed_rrset_key** alias_rrset,
186 	int search_only, struct regional* region, struct auth_zones* az);
187 
188 /**
189  * Get the response-ip function block.
190  * @return: function block with function pointers to response-ip methods.
191  */
192 struct module_func_block* respip_get_funcblock(void);
193 
194 /** response-ip init */
195 int respip_init(struct module_env* env, int id);
196 
197 /** response-ip deinit */
198 void respip_deinit(struct module_env* env, int id);
199 
200 /** response-ip operate on a query */
201 void respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
202 	struct outbound_entry* outbound);
203 
204 /** inform response-ip super */
205 void respip_inform_super(struct module_qstate* qstate, int id,
206 	struct module_qstate* super);
207 
208 /** response-ip cleanup query state */
209 void respip_clear(struct module_qstate* qstate, int id);
210 
211 /**
212  * returns address of the IP address tree of the specified respip set;
213  * returns NULL for NULL input; exists for test purposes only
214  */
215 struct rbtree_type* respip_set_get_tree(struct respip_set* set);
216 
217 /**
218  * returns respip action for the specified node in the respip address
219  * returns respip_none for NULL input; exists for test purposes only
220  */
221 enum respip_action resp_addr_get_action(const struct resp_addr* addr);
222 
223 /**
224  * returns rrset portion of the specified node in the respip address
225  * tree; returns NULL for NULL input; exists for test purposes only
226  */
227 struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr);
228 
229 /** response-ip alloc size routine */
230 size_t respip_get_mem(struct module_env* env, int id);
231 
232 /**
233  * respip set emptiness test
234  * @param set respip set to test
235  * @return 0 if the specified set exists (non-NULL) and is non-empty;
236  *	otherwise returns 1
237  */
238 int respip_set_is_empty(const struct respip_set* set);
239 
240 /**
241  * print log information for a query subject to an inform or inform-deny
242  * response-ip action.
243  * @param respip_actinfo: response-ip information that causes the action
244  * @param qname: query name in the context, will be ignored if local_alias is
245  *   non-NULL.
246  * @param qtype: query type, in host byte order.
247  * @param qclass: query class, in host byte order.
248  * @param local_alias: set to a local alias if the query matches an alias in
249  *  a local zone.  In this case its owner name will be considered the actual
250  *  query name.
251  * @param repinfo: reply info containing the client's source address and port.
252  */
253 void respip_inform_print(struct respip_action_info* respip_actinfo,
254 	uint8_t* qname, uint16_t qtype, uint16_t qclass,
255 	struct local_rrset* local_alias, struct comm_reply* repinfo);
256 
257 /**
258  * Find resp_addr in tree, create and add to tree if it does not exist.
259  * @param set: struct containing the tree and region to alloc new node on.
260  * 	should hold write lock.
261  * @param addr: address to look up.
262  * @param addrlen: length of addr.
263  * @param net: netblock to lookup.
264  * @param create: create node if it does not exist when 1.
265  * @param ipstr: human redable ip string, for logging.
266  * @return newly created of found node, not holding lock.
267  */
268 struct resp_addr*
269 respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
270 		socklen_t addrlen, int net, int create, const char* ipstr);
271 
272 /**
273  * Add RR to resp_addr's RRset. Create RRset if not existing.
274  * @param region: region to alloc RR(set).
275  * @param raddr: resp_addr containing RRset. Must hold write lock.
276  * @param rrtype: RR type.
277  * @param rrclass: RR class.
278  * @param ttl: TTL.
279  * @param rdata: RDATA.
280  * @param rdata_len: length of rdata.
281  * @param rrstr: RR as string, for logging
282  * @param netblockstr: netblock as string, for logging
283  * @return 0 on error
284  */
285 int
286 respip_enter_rr(struct regional* region, struct resp_addr* raddr,
287 	uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
288 	size_t rdata_len, const char* rrstr, const char* netblockstr);
289 
290 /**
291  * Delete resp_addr node from tree.
292  * @param set: struct containing tree. Must hold write lock.
293  * @param node: node to delete. Not locked.
294  */
295 void
296 respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
297 
298 struct ub_packed_rrset_key*
299 respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region);
300 #endif	/* RESPIP_RESPIP_H */
301