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