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