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