165b390aaSDag-Erling Smørgrav /* 265b390aaSDag-Erling Smørgrav * respip/respip.h - IP-based response modification module 365b390aaSDag-Erling Smørgrav */ 465b390aaSDag-Erling Smørgrav 565b390aaSDag-Erling Smørgrav /** 665b390aaSDag-Erling Smørgrav * \file 765b390aaSDag-Erling Smørgrav * 865b390aaSDag-Erling Smørgrav * This file contains a module that selectively modifies query responses 965b390aaSDag-Erling Smørgrav * based on their AAAA/A IP addresses. 1065b390aaSDag-Erling Smørgrav */ 1165b390aaSDag-Erling Smørgrav 1265b390aaSDag-Erling Smørgrav #ifndef RESPIP_RESPIP_H 1365b390aaSDag-Erling Smørgrav #define RESPIP_RESPIP_H 1465b390aaSDag-Erling Smørgrav 1565b390aaSDag-Erling Smørgrav #include "util/module.h" 1665b390aaSDag-Erling Smørgrav #include "services/localzone.h" 17091e9e46SCy Schubert #include "util/locks.h" 1865b390aaSDag-Erling Smørgrav 1965b390aaSDag-Erling Smørgrav /** 20091e9e46SCy Schubert * Conceptual set of IP addresses for response AAAA or A records that should 21091e9e46SCy Schubert * trigger special actions. 2265b390aaSDag-Erling Smørgrav */ 23091e9e46SCy Schubert struct respip_set { 24091e9e46SCy Schubert struct regional* region; 25091e9e46SCy Schubert struct rbtree_type ip_tree; 26091e9e46SCy Schubert lock_rw_type lock; /* lock on the respip tree */ 27091e9e46SCy Schubert char* const* tagname; /* shallow copy of tag names, for logging */ 28091e9e46SCy Schubert int num_tags; /* number of tagname entries */ 29091e9e46SCy Schubert }; 3065b390aaSDag-Erling Smørgrav 31091e9e46SCy Schubert 32091e9e46SCy Schubert /** An address span with response control information */ 33091e9e46SCy Schubert struct resp_addr { 34091e9e46SCy Schubert /** node in address tree */ 35091e9e46SCy Schubert struct addr_tree_node node; 36091e9e46SCy Schubert /** lock on the node item */ 37091e9e46SCy Schubert lock_rw_type lock; 38091e9e46SCy Schubert /** tag bitlist */ 39091e9e46SCy Schubert uint8_t* taglist; 40091e9e46SCy Schubert /** length of the taglist (in bytes) */ 41091e9e46SCy Schubert size_t taglen; 42091e9e46SCy Schubert /** action for this address span */ 43091e9e46SCy Schubert enum respip_action action; 44091e9e46SCy Schubert /** "local data" for this node */ 45091e9e46SCy Schubert struct ub_packed_rrset_key* data; 46091e9e46SCy Schubert }; 47091e9e46SCy Schubert 4865b390aaSDag-Erling Smørgrav 4965b390aaSDag-Erling Smørgrav /** 5065b390aaSDag-Erling Smørgrav * Forward declaration for the structure that represents a tree of view data. 5165b390aaSDag-Erling Smørgrav */ 52091e9e46SCy Schubert 5365b390aaSDag-Erling Smørgrav struct views; 5465b390aaSDag-Erling Smørgrav 5565b390aaSDag-Erling Smørgrav struct respip_addr_info; 5665b390aaSDag-Erling Smørgrav 5765b390aaSDag-Erling Smørgrav /** 5865b390aaSDag-Erling Smørgrav * Client-specific attributes that can affect IP-based actions. 5965b390aaSDag-Erling Smørgrav * This is essentially a subset of acl_addr (except for respip_set) but 6065b390aaSDag-Erling Smørgrav * defined as a separate structure to avoid dependency on the daemon-specific 6165b390aaSDag-Erling Smørgrav * structure. 6265b390aaSDag-Erling Smørgrav * respip_set is supposed to refer to the response-ip set for the global view. 6365b390aaSDag-Erling Smørgrav */ 6465b390aaSDag-Erling Smørgrav struct respip_client_info { 6565b390aaSDag-Erling Smørgrav uint8_t* taglist; 6665b390aaSDag-Erling Smørgrav size_t taglen; 6765b390aaSDag-Erling Smørgrav uint8_t* tag_actions; 6865b390aaSDag-Erling Smørgrav size_t tag_actions_size; 6965b390aaSDag-Erling Smørgrav struct config_strlist** tag_datas; 7065b390aaSDag-Erling Smørgrav size_t tag_datas_size; 7165b390aaSDag-Erling Smørgrav struct view* view; 7265b390aaSDag-Erling Smørgrav struct respip_set* respip_set; 7365b390aaSDag-Erling Smørgrav }; 7465b390aaSDag-Erling Smørgrav 7565b390aaSDag-Erling Smørgrav /** 7665b390aaSDag-Erling Smørgrav * Data items representing the result of response-ip processing. 7765b390aaSDag-Erling Smørgrav * Note: this structure currently only define a few members, but exists 7865b390aaSDag-Erling Smørgrav * as a separate struct mainly for the convenience of custom extensions. 7965b390aaSDag-Erling Smørgrav */ 8065b390aaSDag-Erling Smørgrav struct respip_action_info { 8165b390aaSDag-Erling Smørgrav enum respip_action action; 82091e9e46SCy Schubert int rpz_used; 83091e9e46SCy Schubert int rpz_log; 84091e9e46SCy Schubert int rpz_disabled; 85091e9e46SCy Schubert char* log_name; 86091e9e46SCy Schubert int rpz_cname_override; 8765b390aaSDag-Erling Smørgrav struct respip_addr_info* addrinfo; /* set only for inform variants */ 8865b390aaSDag-Erling Smørgrav }; 8965b390aaSDag-Erling Smørgrav 9065b390aaSDag-Erling Smørgrav /** 9165b390aaSDag-Erling Smørgrav * Forward declaration for the structure that represents a node in the 9265b390aaSDag-Erling Smørgrav * respip_set address tree 9365b390aaSDag-Erling Smørgrav */ 9465b390aaSDag-Erling Smørgrav struct resp_addr; 9565b390aaSDag-Erling Smørgrav 9665b390aaSDag-Erling Smørgrav /** 9765b390aaSDag-Erling Smørgrav * Create response IP set. 9865b390aaSDag-Erling Smørgrav * @return new struct or NULL on error. 9965b390aaSDag-Erling Smørgrav */ 10065b390aaSDag-Erling Smørgrav struct respip_set* respip_set_create(void); 10165b390aaSDag-Erling Smørgrav 10265b390aaSDag-Erling Smørgrav /** 10365b390aaSDag-Erling Smørgrav * Delete response IP set. 10465b390aaSDag-Erling Smørgrav * @param set: to delete. 10565b390aaSDag-Erling Smørgrav */ 10665b390aaSDag-Erling Smørgrav void respip_set_delete(struct respip_set* set); 10765b390aaSDag-Erling Smørgrav 10865b390aaSDag-Erling Smørgrav /** 10965b390aaSDag-Erling Smørgrav * Apply response-ip config settings to the global (default) view. 11065b390aaSDag-Erling Smørgrav * It assumes exclusive access to set (no internal locks). 11165b390aaSDag-Erling Smørgrav * @param set: processed global respip config data 11265b390aaSDag-Erling Smørgrav * @param cfg: config data. 11365b390aaSDag-Erling Smørgrav * @return 1 on success, 0 on error. 11465b390aaSDag-Erling Smørgrav */ 11565b390aaSDag-Erling Smørgrav int respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg); 11665b390aaSDag-Erling Smørgrav 11765b390aaSDag-Erling Smørgrav /** 11865b390aaSDag-Erling Smørgrav * Apply response-ip config settings in named views. 11965b390aaSDag-Erling Smørgrav * @param vs: view structures with processed config data 12065b390aaSDag-Erling Smørgrav * @param cfg: config data. 12165b390aaSDag-Erling Smørgrav * @param have_view_respip_cfg: set to true if any named view has respip 12265b390aaSDag-Erling Smørgrav * configuration; otherwise set to false 12365b390aaSDag-Erling Smørgrav * @return 1 on success, 0 on error. 12465b390aaSDag-Erling Smørgrav */ 12565b390aaSDag-Erling Smørgrav int respip_views_apply_cfg(struct views* vs, struct config_file* cfg, 12665b390aaSDag-Erling Smørgrav int* have_view_respip_cfg); 12765b390aaSDag-Erling Smørgrav 12865b390aaSDag-Erling Smørgrav /** 12965b390aaSDag-Erling Smørgrav * Merge two replies to build a complete CNAME chain. 13065b390aaSDag-Erling Smørgrav * It appends the content of 'tgt_rep' to 'base_rep', assuming (but not 13165b390aaSDag-Erling Smørgrav * checking) the former ends with a CNAME and the latter resolves its target. 13265b390aaSDag-Erling Smørgrav * A merged new reply will be built using 'region' and *new_repp will point 13365b390aaSDag-Erling Smørgrav * to the new one on success. 13465b390aaSDag-Erling Smørgrav * If the target reply would also be subject to a response-ip action for 13565b390aaSDag-Erling Smørgrav * 'cinfo', this function uses 'base_rep' as the merged reply, ignoring 13665b390aaSDag-Erling Smørgrav * 'tgt_rep'. This is for avoiding cases like a CNAME loop or failure of 13765b390aaSDag-Erling Smørgrav * applying an action to an address. 13865b390aaSDag-Erling Smørgrav * RRSIGs in 'tgt_rep' will be excluded in the merged reply, as the resulting 13965b390aaSDag-Erling Smørgrav * reply is assumed to be faked due to a response-ip action and can't be 14065b390aaSDag-Erling Smørgrav * considered secure in terms of DNSSEC. 14165b390aaSDag-Erling Smørgrav * The caller must ensure that neither 'base_rep' nor 'tgt_rep' can be modified 14265b390aaSDag-Erling Smørgrav * until this function returns. 14365b390aaSDag-Erling Smørgrav * @param base_rep: the reply info containing an incomplete CNAME. 14465b390aaSDag-Erling Smørgrav * @param qinfo: query info corresponding to 'base_rep'. 14565b390aaSDag-Erling Smørgrav * @param tgt_rep: the reply info that completes the CNAME chain. 14665b390aaSDag-Erling Smørgrav * @param cinfo: client info corresponding to 'base_rep'. 14765b390aaSDag-Erling Smørgrav * @param must_validate: whether 'tgt_rep' must be DNSSEC-validated. 14865b390aaSDag-Erling Smørgrav * @param new_repp: pointer placeholder for the merged reply. will be intact 14965b390aaSDag-Erling Smørgrav * on error. 15065b390aaSDag-Erling Smørgrav * @param region: allocator to build *new_repp. 151091e9e46SCy Schubert * @param az: auth zones containing RPZ information. 15265b390aaSDag-Erling Smørgrav * @return 1 on success, 0 on error. 15365b390aaSDag-Erling Smørgrav */ 15465b390aaSDag-Erling Smørgrav int respip_merge_cname(struct reply_info* base_rep, 15565b390aaSDag-Erling Smørgrav const struct query_info* qinfo, const struct reply_info* tgt_rep, 15665b390aaSDag-Erling Smørgrav const struct respip_client_info* cinfo, int must_validate, 157091e9e46SCy Schubert struct reply_info** new_repp, struct regional* region, 158091e9e46SCy Schubert struct auth_zones* az); 15965b390aaSDag-Erling Smørgrav 16065b390aaSDag-Erling Smørgrav /** 16165b390aaSDag-Erling Smørgrav * See if any IP-based action should apply to any IP address of AAAA/A answer 16265b390aaSDag-Erling Smørgrav * record in the reply. If so, apply the action. In some cases it rewrites 16365b390aaSDag-Erling Smørgrav * the reply rrsets, in which case *new_repp will point to the updated reply 16465b390aaSDag-Erling Smørgrav * info. Depending on the action, some of the rrsets in 'rep' will be 16565b390aaSDag-Erling Smørgrav * shallow-copied into '*new_repp'; the caller must ensure that the rrsets 16665b390aaSDag-Erling Smørgrav * in 'rep' are valid throughout the lifetime of *new_repp, and it must 16765b390aaSDag-Erling Smørgrav * provide appropriate mutex if the rrsets can be shared by multiple threads. 16865b390aaSDag-Erling Smørgrav * @param qinfo: query info corresponding to the reply. 16965b390aaSDag-Erling Smørgrav * @param cinfo: client-specific info to identify the best matching action. 17065b390aaSDag-Erling Smørgrav * can be NULL. 17165b390aaSDag-Erling Smørgrav * @param rep: original reply info. must not be NULL. 17265b390aaSDag-Erling Smørgrav * @param new_repp: can be set to the rewritten reply info (intact on failure). 17365b390aaSDag-Erling Smørgrav * @param actinfo: result of response-ip processing 17465b390aaSDag-Erling Smørgrav * @param alias_rrset: must not be NULL. 17565b390aaSDag-Erling Smørgrav * @param search_only: if true, only check if an action would apply. actionp 17665b390aaSDag-Erling Smørgrav * will be set (or intact) accordingly but the modified reply won't be built. 177091e9e46SCy Schubert * @param az: auth zones containing RPZ information. 17865b390aaSDag-Erling Smørgrav * @param region: allocator to build *new_repp. 179a39a5a69SCy Schubert * @param rpz_passthru: keeps track of query state can have passthru that 180a39a5a69SCy Schubert * stops further rpz processing. Or NULL for cached answer processing. 18165b390aaSDag-Erling Smørgrav * @return 1 on success, 0 on error. 18265b390aaSDag-Erling Smørgrav */ 18365b390aaSDag-Erling Smørgrav int respip_rewrite_reply(const struct query_info* qinfo, 18465b390aaSDag-Erling Smørgrav const struct respip_client_info* cinfo, 18565b390aaSDag-Erling Smørgrav const struct reply_info *rep, struct reply_info** new_repp, 18665b390aaSDag-Erling Smørgrav struct respip_action_info* actinfo, 18765b390aaSDag-Erling Smørgrav struct ub_packed_rrset_key** alias_rrset, 188a39a5a69SCy Schubert int search_only, struct regional* region, struct auth_zones* az, 189a39a5a69SCy Schubert int* rpz_passthru); 19065b390aaSDag-Erling Smørgrav 19165b390aaSDag-Erling Smørgrav /** 19265b390aaSDag-Erling Smørgrav * Get the response-ip function block. 19365b390aaSDag-Erling Smørgrav * @return: function block with function pointers to response-ip methods. 19465b390aaSDag-Erling Smørgrav */ 19565b390aaSDag-Erling Smørgrav struct module_func_block* respip_get_funcblock(void); 19665b390aaSDag-Erling Smørgrav 19765b390aaSDag-Erling Smørgrav /** response-ip init */ 19865b390aaSDag-Erling Smørgrav int respip_init(struct module_env* env, int id); 19965b390aaSDag-Erling Smørgrav 20065b390aaSDag-Erling Smørgrav /** response-ip deinit */ 20165b390aaSDag-Erling Smørgrav void respip_deinit(struct module_env* env, int id); 20265b390aaSDag-Erling Smørgrav 20365b390aaSDag-Erling Smørgrav /** response-ip operate on a query */ 20465b390aaSDag-Erling Smørgrav void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, 20565b390aaSDag-Erling Smørgrav struct outbound_entry* outbound); 20665b390aaSDag-Erling Smørgrav 20765b390aaSDag-Erling Smørgrav /** inform response-ip super */ 20865b390aaSDag-Erling Smørgrav void respip_inform_super(struct module_qstate* qstate, int id, 20965b390aaSDag-Erling Smørgrav struct module_qstate* super); 21065b390aaSDag-Erling Smørgrav 21165b390aaSDag-Erling Smørgrav /** response-ip cleanup query state */ 21265b390aaSDag-Erling Smørgrav void respip_clear(struct module_qstate* qstate, int id); 21365b390aaSDag-Erling Smørgrav 21465b390aaSDag-Erling Smørgrav /** 21565b390aaSDag-Erling Smørgrav * returns address of the IP address tree of the specified respip set; 21665b390aaSDag-Erling Smørgrav * returns NULL for NULL input; exists for test purposes only 21765b390aaSDag-Erling Smørgrav */ 21865b390aaSDag-Erling Smørgrav struct rbtree_type* respip_set_get_tree(struct respip_set* set); 21965b390aaSDag-Erling Smørgrav 22065b390aaSDag-Erling Smørgrav /** 22165b390aaSDag-Erling Smørgrav * returns respip action for the specified node in the respip address 22265b390aaSDag-Erling Smørgrav * returns respip_none for NULL input; exists for test purposes only 22365b390aaSDag-Erling Smørgrav */ 22465b390aaSDag-Erling Smørgrav enum respip_action resp_addr_get_action(const struct resp_addr* addr); 22565b390aaSDag-Erling Smørgrav 22665b390aaSDag-Erling Smørgrav /** 22765b390aaSDag-Erling Smørgrav * returns rrset portion of the specified node in the respip address 22865b390aaSDag-Erling Smørgrav * tree; returns NULL for NULL input; exists for test purposes only 22965b390aaSDag-Erling Smørgrav */ 23065b390aaSDag-Erling Smørgrav struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr); 23165b390aaSDag-Erling Smørgrav 23265b390aaSDag-Erling Smørgrav /** response-ip alloc size routine */ 23365b390aaSDag-Erling Smørgrav size_t respip_get_mem(struct module_env* env, int id); 23465b390aaSDag-Erling Smørgrav 23565b390aaSDag-Erling Smørgrav /** 23665b390aaSDag-Erling Smørgrav * respip set emptiness test 23765b390aaSDag-Erling Smørgrav * @param set respip set to test 23865b390aaSDag-Erling Smørgrav * @return 0 if the specified set exists (non-NULL) and is non-empty; 23965b390aaSDag-Erling Smørgrav * otherwise returns 1 24065b390aaSDag-Erling Smørgrav */ 24165b390aaSDag-Erling Smørgrav int respip_set_is_empty(const struct respip_set* set); 24265b390aaSDag-Erling Smørgrav 24365b390aaSDag-Erling Smørgrav /** 24465b390aaSDag-Erling Smørgrav * print log information for a query subject to an inform or inform-deny 24565b390aaSDag-Erling Smørgrav * response-ip action. 246091e9e46SCy Schubert * @param respip_actinfo: response-ip information that causes the action 24765b390aaSDag-Erling Smørgrav * @param qname: query name in the context, will be ignored if local_alias is 24865b390aaSDag-Erling Smørgrav * non-NULL. 24965b390aaSDag-Erling Smørgrav * @param qtype: query type, in host byte order. 25065b390aaSDag-Erling Smørgrav * @param qclass: query class, in host byte order. 25165b390aaSDag-Erling Smørgrav * @param local_alias: set to a local alias if the query matches an alias in 25265b390aaSDag-Erling Smørgrav * a local zone. In this case its owner name will be considered the actual 25365b390aaSDag-Erling Smørgrav * query name. 254*865f46b2SCy Schubert * @param addr: the client's source address and port. 255*865f46b2SCy Schubert * @param addrlen: the client's source address length. 25665b390aaSDag-Erling Smørgrav */ 257091e9e46SCy Schubert void respip_inform_print(struct respip_action_info* respip_actinfo, 258091e9e46SCy Schubert uint8_t* qname, uint16_t qtype, uint16_t qclass, 259*865f46b2SCy Schubert struct local_rrset* local_alias, struct sockaddr_storage* addr, 260*865f46b2SCy Schubert socklen_t addrlen); 26165b390aaSDag-Erling Smørgrav 262091e9e46SCy Schubert /** 263091e9e46SCy Schubert * Find resp_addr in tree, create and add to tree if it does not exist. 264091e9e46SCy Schubert * @param set: struct containing the tree and region to alloc new node on. 265091e9e46SCy Schubert * should hold write lock. 266091e9e46SCy Schubert * @param addr: address to look up. 267091e9e46SCy Schubert * @param addrlen: length of addr. 268091e9e46SCy Schubert * @param net: netblock to lookup. 269091e9e46SCy Schubert * @param create: create node if it does not exist when 1. 270091e9e46SCy Schubert * @param ipstr: human redable ip string, for logging. 271091e9e46SCy Schubert * @return newly created of found node, not holding lock. 272091e9e46SCy Schubert */ 273091e9e46SCy Schubert struct resp_addr* 274091e9e46SCy Schubert respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr, 275091e9e46SCy Schubert socklen_t addrlen, int net, int create, const char* ipstr); 276091e9e46SCy Schubert 277091e9e46SCy Schubert /** 278091e9e46SCy Schubert * Add RR to resp_addr's RRset. Create RRset if not existing. 279091e9e46SCy Schubert * @param region: region to alloc RR(set). 280091e9e46SCy Schubert * @param raddr: resp_addr containing RRset. Must hold write lock. 281091e9e46SCy Schubert * @param rrtype: RR type. 282091e9e46SCy Schubert * @param rrclass: RR class. 283091e9e46SCy Schubert * @param ttl: TTL. 284091e9e46SCy Schubert * @param rdata: RDATA. 285091e9e46SCy Schubert * @param rdata_len: length of rdata. 286091e9e46SCy Schubert * @param rrstr: RR as string, for logging 287091e9e46SCy Schubert * @param netblockstr: netblock as string, for logging 288091e9e46SCy Schubert * @return 0 on error 289091e9e46SCy Schubert */ 290091e9e46SCy Schubert int 291091e9e46SCy Schubert respip_enter_rr(struct regional* region, struct resp_addr* raddr, 292091e9e46SCy Schubert uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, 293091e9e46SCy Schubert size_t rdata_len, const char* rrstr, const char* netblockstr); 294091e9e46SCy Schubert 295091e9e46SCy Schubert /** 296091e9e46SCy Schubert * Delete resp_addr node from tree. 297091e9e46SCy Schubert * @param set: struct containing tree. Must hold write lock. 298091e9e46SCy Schubert * @param node: node to delete. Not locked. 299091e9e46SCy Schubert */ 300091e9e46SCy Schubert void 301091e9e46SCy Schubert respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); 30224e36522SCy Schubert 30324e36522SCy Schubert struct ub_packed_rrset_key* 30424e36522SCy Schubert respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region); 30565b390aaSDag-Erling Smørgrav #endif /* RESPIP_RESPIP_H */ 306