1762909a6Schristos /* 2762909a6Schristos * respip/respip.h - IP-based response modification module 3762909a6Schristos */ 4762909a6Schristos 5762909a6Schristos /** 6762909a6Schristos * \file 7762909a6Schristos * 8762909a6Schristos * This file contains a module that selectively modifies query responses 9762909a6Schristos * based on their AAAA/A IP addresses. 10762909a6Schristos */ 11762909a6Schristos 12762909a6Schristos #ifndef RESPIP_RESPIP_H 13762909a6Schristos #define RESPIP_RESPIP_H 14762909a6Schristos 15762909a6Schristos #include "util/module.h" 16762909a6Schristos #include "services/localzone.h" 17561252a2Schristos #include "util/locks.h" 18762909a6Schristos 19762909a6Schristos /** 20561252a2Schristos * Conceptual set of IP addresses for response AAAA or A records that should 21561252a2Schristos * trigger special actions. 22762909a6Schristos */ 23561252a2Schristos struct respip_set { 24561252a2Schristos struct regional* region; 25561252a2Schristos struct rbtree_type ip_tree; 26561252a2Schristos lock_rw_type lock; /* lock on the respip tree */ 27561252a2Schristos char* const* tagname; /* shallow copy of tag names, for logging */ 28561252a2Schristos int num_tags; /* number of tagname entries */ 29561252a2Schristos }; 30762909a6Schristos 31561252a2Schristos 32561252a2Schristos /** An address span with response control information */ 33561252a2Schristos struct resp_addr { 34561252a2Schristos /** node in address tree */ 35561252a2Schristos struct addr_tree_node node; 36561252a2Schristos /** lock on the node item */ 37561252a2Schristos lock_rw_type lock; 38561252a2Schristos /** tag bitlist */ 39561252a2Schristos uint8_t* taglist; 40561252a2Schristos /** length of the taglist (in bytes) */ 41561252a2Schristos size_t taglen; 42561252a2Schristos /** action for this address span */ 43561252a2Schristos enum respip_action action; 44561252a2Schristos /** "local data" for this node */ 45561252a2Schristos struct ub_packed_rrset_key* data; 46561252a2Schristos }; 47561252a2Schristos 48762909a6Schristos 49762909a6Schristos /** 50762909a6Schristos * Forward declaration for the structure that represents a tree of view data. 51762909a6Schristos */ 52561252a2Schristos 53762909a6Schristos struct views; 54762909a6Schristos 55762909a6Schristos struct respip_addr_info; 56762909a6Schristos 57762909a6Schristos /** 58762909a6Schristos * Client-specific attributes that can affect IP-based actions. 59762909a6Schristos * This is essentially a subset of acl_addr (except for respip_set) but 60762909a6Schristos * defined as a separate structure to avoid dependency on the daemon-specific 61762909a6Schristos * structure. 62762909a6Schristos * respip_set is supposed to refer to the response-ip set for the global view. 63762909a6Schristos */ 64762909a6Schristos struct respip_client_info { 65762909a6Schristos uint8_t* taglist; 66762909a6Schristos size_t taglen; 67762909a6Schristos uint8_t* tag_actions; 68762909a6Schristos size_t tag_actions_size; 69762909a6Schristos struct config_strlist** tag_datas; 70762909a6Schristos size_t tag_datas_size; 71762909a6Schristos struct view* view; 72762909a6Schristos struct respip_set* respip_set; 73762909a6Schristos }; 74762909a6Schristos 75762909a6Schristos /** 76762909a6Schristos * Data items representing the result of response-ip processing. 77762909a6Schristos * Note: this structure currently only define a few members, but exists 78762909a6Schristos * as a separate struct mainly for the convenience of custom extensions. 79762909a6Schristos */ 80762909a6Schristos struct respip_action_info { 81762909a6Schristos enum respip_action action; 82561252a2Schristos int rpz_used; 83561252a2Schristos int rpz_log; 84561252a2Schristos int rpz_disabled; 85561252a2Schristos char* log_name; 86561252a2Schristos int rpz_cname_override; 87762909a6Schristos struct respip_addr_info* addrinfo; /* set only for inform variants */ 88762909a6Schristos }; 89762909a6Schristos 90762909a6Schristos /** 91762909a6Schristos * Forward declaration for the structure that represents a node in the 92762909a6Schristos * respip_set address tree 93762909a6Schristos */ 94762909a6Schristos struct resp_addr; 95762909a6Schristos 96762909a6Schristos /** 97762909a6Schristos * Create response IP set. 98762909a6Schristos * @return new struct or NULL on error. 99762909a6Schristos */ 100762909a6Schristos struct respip_set* respip_set_create(void); 101762909a6Schristos 102762909a6Schristos /** 103762909a6Schristos * Delete response IP set. 104762909a6Schristos * @param set: to delete. 105762909a6Schristos */ 106762909a6Schristos void respip_set_delete(struct respip_set* set); 107762909a6Schristos 108762909a6Schristos /** 109762909a6Schristos * Apply response-ip config settings to the global (default) view. 110762909a6Schristos * It assumes exclusive access to set (no internal locks). 111762909a6Schristos * @param set: processed global respip config data 112762909a6Schristos * @param cfg: config data. 113762909a6Schristos * @return 1 on success, 0 on error. 114762909a6Schristos */ 115762909a6Schristos int respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg); 116762909a6Schristos 117762909a6Schristos /** 118762909a6Schristos * Apply response-ip config settings in named views. 119762909a6Schristos * @param vs: view structures with processed config data 120762909a6Schristos * @param cfg: config data. 121762909a6Schristos * @param have_view_respip_cfg: set to true if any named view has respip 122762909a6Schristos * configuration; otherwise set to false 123762909a6Schristos * @return 1 on success, 0 on error. 124762909a6Schristos */ 125762909a6Schristos int respip_views_apply_cfg(struct views* vs, struct config_file* cfg, 126762909a6Schristos int* have_view_respip_cfg); 127762909a6Schristos 128762909a6Schristos /** 129762909a6Schristos * Merge two replies to build a complete CNAME chain. 130762909a6Schristos * It appends the content of 'tgt_rep' to 'base_rep', assuming (but not 131762909a6Schristos * checking) the former ends with a CNAME and the latter resolves its target. 132762909a6Schristos * A merged new reply will be built using 'region' and *new_repp will point 133762909a6Schristos * to the new one on success. 134762909a6Schristos * If the target reply would also be subject to a response-ip action for 135762909a6Schristos * 'cinfo', this function uses 'base_rep' as the merged reply, ignoring 136762909a6Schristos * 'tgt_rep'. This is for avoiding cases like a CNAME loop or failure of 137762909a6Schristos * applying an action to an address. 138762909a6Schristos * RRSIGs in 'tgt_rep' will be excluded in the merged reply, as the resulting 139762909a6Schristos * reply is assumed to be faked due to a response-ip action and can't be 140762909a6Schristos * considered secure in terms of DNSSEC. 141762909a6Schristos * The caller must ensure that neither 'base_rep' nor 'tgt_rep' can be modified 142762909a6Schristos * until this function returns. 143762909a6Schristos * @param base_rep: the reply info containing an incomplete CNAME. 144762909a6Schristos * @param qinfo: query info corresponding to 'base_rep'. 145762909a6Schristos * @param tgt_rep: the reply info that completes the CNAME chain. 146762909a6Schristos * @param cinfo: client info corresponding to 'base_rep'. 147762909a6Schristos * @param must_validate: whether 'tgt_rep' must be DNSSEC-validated. 148762909a6Schristos * @param new_repp: pointer placeholder for the merged reply. will be intact 149762909a6Schristos * on error. 150762909a6Schristos * @param region: allocator to build *new_repp. 151561252a2Schristos * @param az: auth zones containing RPZ information. 152762909a6Schristos * @return 1 on success, 0 on error. 153762909a6Schristos */ 154762909a6Schristos int respip_merge_cname(struct reply_info* base_rep, 155762909a6Schristos const struct query_info* qinfo, const struct reply_info* tgt_rep, 156762909a6Schristos const struct respip_client_info* cinfo, int must_validate, 157561252a2Schristos struct reply_info** new_repp, struct regional* region, 158561252a2Schristos struct auth_zones* az); 159762909a6Schristos 160762909a6Schristos /** 161762909a6Schristos * See if any IP-based action should apply to any IP address of AAAA/A answer 162762909a6Schristos * record in the reply. If so, apply the action. In some cases it rewrites 163762909a6Schristos * the reply rrsets, in which case *new_repp will point to the updated reply 164762909a6Schristos * info. Depending on the action, some of the rrsets in 'rep' will be 165762909a6Schristos * shallow-copied into '*new_repp'; the caller must ensure that the rrsets 166762909a6Schristos * in 'rep' are valid throughout the lifetime of *new_repp, and it must 167762909a6Schristos * provide appropriate mutex if the rrsets can be shared by multiple threads. 168762909a6Schristos * @param qinfo: query info corresponding to the reply. 169762909a6Schristos * @param cinfo: client-specific info to identify the best matching action. 170762909a6Schristos * can be NULL. 171762909a6Schristos * @param rep: original reply info. must not be NULL. 172762909a6Schristos * @param new_repp: can be set to the rewritten reply info (intact on failure). 173762909a6Schristos * @param actinfo: result of response-ip processing 174762909a6Schristos * @param alias_rrset: must not be NULL. 175762909a6Schristos * @param search_only: if true, only check if an action would apply. actionp 176762909a6Schristos * will be set (or intact) accordingly but the modified reply won't be built. 177561252a2Schristos * @param az: auth zones containing RPZ information. 178762909a6Schristos * @param region: allocator to build *new_repp. 179*17b85d8bSchristos * @param rpz_passthru: keeps track of query state can have passthru that 180*17b85d8bSchristos * stops further rpz processing. Or NULL for cached answer processing. 181762909a6Schristos * @return 1 on success, 0 on error. 182762909a6Schristos */ 183762909a6Schristos int respip_rewrite_reply(const struct query_info* qinfo, 184762909a6Schristos const struct respip_client_info* cinfo, 185762909a6Schristos const struct reply_info *rep, struct reply_info** new_repp, 186762909a6Schristos struct respip_action_info* actinfo, 187762909a6Schristos struct ub_packed_rrset_key** alias_rrset, 188*17b85d8bSchristos int search_only, struct regional* region, struct auth_zones* az, 189*17b85d8bSchristos int* rpz_passthru); 190762909a6Schristos 191762909a6Schristos /** 192762909a6Schristos * Get the response-ip function block. 193762909a6Schristos * @return: function block with function pointers to response-ip methods. 194762909a6Schristos */ 195762909a6Schristos struct module_func_block* respip_get_funcblock(void); 196762909a6Schristos 197762909a6Schristos /** response-ip init */ 198762909a6Schristos int respip_init(struct module_env* env, int id); 199762909a6Schristos 200762909a6Schristos /** response-ip deinit */ 201762909a6Schristos void respip_deinit(struct module_env* env, int id); 202762909a6Schristos 203762909a6Schristos /** response-ip operate on a query */ 204762909a6Schristos void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, 205762909a6Schristos struct outbound_entry* outbound); 206762909a6Schristos 207762909a6Schristos /** inform response-ip super */ 208762909a6Schristos void respip_inform_super(struct module_qstate* qstate, int id, 209762909a6Schristos struct module_qstate* super); 210762909a6Schristos 211762909a6Schristos /** response-ip cleanup query state */ 212762909a6Schristos void respip_clear(struct module_qstate* qstate, int id); 213762909a6Schristos 214762909a6Schristos /** 215762909a6Schristos * returns address of the IP address tree of the specified respip set; 216762909a6Schristos * returns NULL for NULL input; exists for test purposes only 217762909a6Schristos */ 218762909a6Schristos struct rbtree_type* respip_set_get_tree(struct respip_set* set); 219762909a6Schristos 220762909a6Schristos /** 221762909a6Schristos * returns respip action for the specified node in the respip address 222762909a6Schristos * returns respip_none for NULL input; exists for test purposes only 223762909a6Schristos */ 224762909a6Schristos enum respip_action resp_addr_get_action(const struct resp_addr* addr); 225762909a6Schristos 226762909a6Schristos /** 227762909a6Schristos * returns rrset portion of the specified node in the respip address 228762909a6Schristos * tree; returns NULL for NULL input; exists for test purposes only 229762909a6Schristos */ 230762909a6Schristos struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr); 231762909a6Schristos 232762909a6Schristos /** response-ip alloc size routine */ 233762909a6Schristos size_t respip_get_mem(struct module_env* env, int id); 234762909a6Schristos 235762909a6Schristos /** 236762909a6Schristos * respip set emptiness test 237762909a6Schristos * @param set respip set to test 238762909a6Schristos * @return 0 if the specified set exists (non-NULL) and is non-empty; 239762909a6Schristos * otherwise returns 1 240762909a6Schristos */ 241762909a6Schristos int respip_set_is_empty(const struct respip_set* set); 242762909a6Schristos 243762909a6Schristos /** 244762909a6Schristos * print log information for a query subject to an inform or inform-deny 245762909a6Schristos * response-ip action. 246561252a2Schristos * @param respip_actinfo: response-ip information that causes the action 247762909a6Schristos * @param qname: query name in the context, will be ignored if local_alias is 248762909a6Schristos * non-NULL. 249762909a6Schristos * @param qtype: query type, in host byte order. 250762909a6Schristos * @param qclass: query class, in host byte order. 251762909a6Schristos * @param local_alias: set to a local alias if the query matches an alias in 252762909a6Schristos * a local zone. In this case its owner name will be considered the actual 253762909a6Schristos * query name. 254762909a6Schristos * @param repinfo: reply info containing the client's source address and port. 255762909a6Schristos */ 256561252a2Schristos void respip_inform_print(struct respip_action_info* respip_actinfo, 257561252a2Schristos uint8_t* qname, uint16_t qtype, uint16_t qclass, 258561252a2Schristos struct local_rrset* local_alias, struct comm_reply* repinfo); 259762909a6Schristos 260561252a2Schristos /** 261561252a2Schristos * Find resp_addr in tree, create and add to tree if it does not exist. 262561252a2Schristos * @param set: struct containing the tree and region to alloc new node on. 263561252a2Schristos * should hold write lock. 264561252a2Schristos * @param addr: address to look up. 265561252a2Schristos * @param addrlen: length of addr. 266561252a2Schristos * @param net: netblock to lookup. 267561252a2Schristos * @param create: create node if it does not exist when 1. 268561252a2Schristos * @param ipstr: human redable ip string, for logging. 269561252a2Schristos * @return newly created of found node, not holding lock. 270561252a2Schristos */ 271561252a2Schristos struct resp_addr* 272561252a2Schristos respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr, 273561252a2Schristos socklen_t addrlen, int net, int create, const char* ipstr); 274561252a2Schristos 275561252a2Schristos /** 276561252a2Schristos * Add RR to resp_addr's RRset. Create RRset if not existing. 277561252a2Schristos * @param region: region to alloc RR(set). 278561252a2Schristos * @param raddr: resp_addr containing RRset. Must hold write lock. 279561252a2Schristos * @param rrtype: RR type. 280561252a2Schristos * @param rrclass: RR class. 281561252a2Schristos * @param ttl: TTL. 282561252a2Schristos * @param rdata: RDATA. 283561252a2Schristos * @param rdata_len: length of rdata. 284561252a2Schristos * @param rrstr: RR as string, for logging 285561252a2Schristos * @param netblockstr: netblock as string, for logging 286561252a2Schristos * @return 0 on error 287561252a2Schristos */ 288561252a2Schristos int 289561252a2Schristos respip_enter_rr(struct regional* region, struct resp_addr* raddr, 290561252a2Schristos uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, 291561252a2Schristos size_t rdata_len, const char* rrstr, const char* netblockstr); 292561252a2Schristos 293561252a2Schristos /** 294561252a2Schristos * Delete resp_addr node from tree. 295561252a2Schristos * @param set: struct containing tree. Must hold write lock. 296561252a2Schristos * @param node: node to delete. Not locked. 297561252a2Schristos */ 298561252a2Schristos void 299561252a2Schristos respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); 300*17b85d8bSchristos 301*17b85d8bSchristos struct ub_packed_rrset_key* 302*17b85d8bSchristos respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region); 303762909a6Schristos #endif /* RESPIP_RESPIP_H */ 304