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 * @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 */ 183 int 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 */ 195 struct module_func_block* respip_get_funcblock(void); 196 197 /** response-ip init */ 198 int respip_init(struct module_env* env, int id); 199 200 /** response-ip deinit */ 201 void respip_deinit(struct module_env* env, int id); 202 203 /** response-ip operate on a query */ 204 void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, 205 struct outbound_entry* outbound); 206 207 /** inform response-ip super */ 208 void respip_inform_super(struct module_qstate* qstate, int id, 209 struct module_qstate* super); 210 211 /** response-ip cleanup query state */ 212 void 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 */ 218 struct 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 */ 224 enum 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 */ 230 struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr); 231 232 /** response-ip alloc size routine */ 233 size_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 */ 241 int 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 */ 257 void 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 */ 273 struct resp_addr* 274 respip_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 */ 290 int 291 respip_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 */ 300 void 301 respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); 302 303 struct ub_packed_rrset_key* 304 respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region); 305 #endif /* RESPIP_RESPIP_H */ 306