1c7f4d7adSDag-Erling Smørgrav /* 2c7f4d7adSDag-Erling Smørgrav * ipsecmod/ipsecmod.c - facilitate opportunistic IPsec module 3c7f4d7adSDag-Erling Smørgrav * 4c7f4d7adSDag-Erling Smørgrav * Copyright (c) 2017, NLnet Labs. All rights reserved. 5c7f4d7adSDag-Erling Smørgrav * 6c7f4d7adSDag-Erling Smørgrav * This software is open source. 7c7f4d7adSDag-Erling Smørgrav * 8c7f4d7adSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9c7f4d7adSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10c7f4d7adSDag-Erling Smørgrav * are met: 11c7f4d7adSDag-Erling Smørgrav * 12c7f4d7adSDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13c7f4d7adSDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14c7f4d7adSDag-Erling Smørgrav * 15c7f4d7adSDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16c7f4d7adSDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17c7f4d7adSDag-Erling Smørgrav * and/or other materials provided with the distribution. 18c7f4d7adSDag-Erling Smørgrav * 19c7f4d7adSDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20c7f4d7adSDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21c7f4d7adSDag-Erling Smørgrav * specific prior written permission. 22c7f4d7adSDag-Erling Smørgrav * 23c7f4d7adSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24c7f4d7adSDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25c7f4d7adSDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26c7f4d7adSDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27c7f4d7adSDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28c7f4d7adSDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29c7f4d7adSDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30c7f4d7adSDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31c7f4d7adSDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32c7f4d7adSDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33c7f4d7adSDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34c7f4d7adSDag-Erling Smørgrav */ 35c7f4d7adSDag-Erling Smørgrav 36c7f4d7adSDag-Erling Smørgrav /** 37c7f4d7adSDag-Erling Smørgrav * \file 38c7f4d7adSDag-Erling Smørgrav * 39c7f4d7adSDag-Erling Smørgrav * This file contains a module that facilitates opportunistic IPsec. It does so 4024e36522SCy Schubert * by also querying for the IPSECKEY for A/AAAA queries and calling a 41c7f4d7adSDag-Erling Smørgrav * configurable hook (eg. signaling an IKE daemon) before replying. 42c7f4d7adSDag-Erling Smørgrav */ 43c7f4d7adSDag-Erling Smørgrav 44c7f4d7adSDag-Erling Smørgrav #include "config.h" 45c7f4d7adSDag-Erling Smørgrav #ifdef USE_IPSECMOD 46c7f4d7adSDag-Erling Smørgrav #include "ipsecmod/ipsecmod.h" 47c7f4d7adSDag-Erling Smørgrav #include "ipsecmod/ipsecmod-whitelist.h" 48c7f4d7adSDag-Erling Smørgrav #include "util/fptr_wlist.h" 49c7f4d7adSDag-Erling Smørgrav #include "util/regional.h" 50c7f4d7adSDag-Erling Smørgrav #include "util/net_help.h" 51c7f4d7adSDag-Erling Smørgrav #include "util/config_file.h" 52c7f4d7adSDag-Erling Smørgrav #include "services/cache/dns.h" 53c7f4d7adSDag-Erling Smørgrav #include "sldns/wire2str.h" 54c7f4d7adSDag-Erling Smørgrav 55c7f4d7adSDag-Erling Smørgrav /** Apply configuration to ipsecmod module 'global' state. */ 56c7f4d7adSDag-Erling Smørgrav static int 57c7f4d7adSDag-Erling Smørgrav ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg) 58c7f4d7adSDag-Erling Smørgrav { 59c7f4d7adSDag-Erling Smørgrav if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) { 60c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: missing ipsecmod-hook."); 61c7f4d7adSDag-Erling Smørgrav return 0; 62c7f4d7adSDag-Erling Smørgrav } 63c7f4d7adSDag-Erling Smørgrav if(cfg->ipsecmod_whitelist && 64c7f4d7adSDag-Erling Smørgrav !ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg)) 65c7f4d7adSDag-Erling Smørgrav return 0; 66c7f4d7adSDag-Erling Smørgrav return 1; 67c7f4d7adSDag-Erling Smørgrav } 68c7f4d7adSDag-Erling Smørgrav 69c7f4d7adSDag-Erling Smørgrav int 70c7f4d7adSDag-Erling Smørgrav ipsecmod_init(struct module_env* env, int id) 71c7f4d7adSDag-Erling Smørgrav { 72c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1, 73c7f4d7adSDag-Erling Smørgrav sizeof(struct ipsecmod_env)); 74c7f4d7adSDag-Erling Smørgrav if(!ipsecmod_env) { 75c7f4d7adSDag-Erling Smørgrav log_err("malloc failure"); 76c7f4d7adSDag-Erling Smørgrav return 0; 77c7f4d7adSDag-Erling Smørgrav } 78c7f4d7adSDag-Erling Smørgrav env->modinfo[id] = (void*)ipsecmod_env; 79c7f4d7adSDag-Erling Smørgrav ipsecmod_env->whitelist = NULL; 80c7f4d7adSDag-Erling Smørgrav if(!ipsecmod_apply_cfg(ipsecmod_env, env->cfg)) { 81c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: could not apply configuration settings."); 82c7f4d7adSDag-Erling Smørgrav return 0; 83c7f4d7adSDag-Erling Smørgrav } 84c7f4d7adSDag-Erling Smørgrav return 1; 85c7f4d7adSDag-Erling Smørgrav } 86c7f4d7adSDag-Erling Smørgrav 87c7f4d7adSDag-Erling Smørgrav void 88c7f4d7adSDag-Erling Smørgrav ipsecmod_deinit(struct module_env* env, int id) 89c7f4d7adSDag-Erling Smørgrav { 90c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ipsecmod_env; 91c7f4d7adSDag-Erling Smørgrav if(!env || !env->modinfo[id]) 92c7f4d7adSDag-Erling Smørgrav return; 93c7f4d7adSDag-Erling Smørgrav ipsecmod_env = (struct ipsecmod_env*)env->modinfo[id]; 94c7f4d7adSDag-Erling Smørgrav /* Free contents. */ 95c7f4d7adSDag-Erling Smørgrav ipsecmod_whitelist_delete(ipsecmod_env->whitelist); 96c7f4d7adSDag-Erling Smørgrav free(ipsecmod_env); 97c7f4d7adSDag-Erling Smørgrav env->modinfo[id] = NULL; 98c7f4d7adSDag-Erling Smørgrav } 99c7f4d7adSDag-Erling Smørgrav 100c7f4d7adSDag-Erling Smørgrav /** New query for ipsecmod. */ 101c7f4d7adSDag-Erling Smørgrav static int 102c7f4d7adSDag-Erling Smørgrav ipsecmod_new(struct module_qstate* qstate, int id) 103c7f4d7adSDag-Erling Smørgrav { 104c7f4d7adSDag-Erling Smørgrav struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc( 105c7f4d7adSDag-Erling Smørgrav qstate->region, sizeof(struct ipsecmod_qstate)); 106c7f4d7adSDag-Erling Smørgrav qstate->minfo[id] = iq; 107c7f4d7adSDag-Erling Smørgrav if(!iq) 108c7f4d7adSDag-Erling Smørgrav return 0; 109c7f4d7adSDag-Erling Smørgrav /* Initialise it. */ 1100eefd307SCy Schubert memset(iq, 0, sizeof(*iq)); 111c7f4d7adSDag-Erling Smørgrav iq->enabled = qstate->env->cfg->ipsecmod_enabled; 112c7f4d7adSDag-Erling Smørgrav iq->is_whitelisted = ipsecmod_domain_is_whitelisted( 113c7f4d7adSDag-Erling Smørgrav (struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname, 114c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qname_len, qstate->qinfo.qclass); 115c7f4d7adSDag-Erling Smørgrav return 1; 116c7f4d7adSDag-Erling Smørgrav } 117c7f4d7adSDag-Erling Smørgrav 118c7f4d7adSDag-Erling Smørgrav /** 119c7f4d7adSDag-Erling Smørgrav * Exit module with an error status. 120c7f4d7adSDag-Erling Smørgrav * @param qstate: query state 121c7f4d7adSDag-Erling Smørgrav * @param id: module id. 122c7f4d7adSDag-Erling Smørgrav */ 123c7f4d7adSDag-Erling Smørgrav static void 124c7f4d7adSDag-Erling Smørgrav ipsecmod_error(struct module_qstate* qstate, int id) 125c7f4d7adSDag-Erling Smørgrav { 126c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_error; 127c7f4d7adSDag-Erling Smørgrav qstate->return_rcode = LDNS_RCODE_SERVFAIL; 128c7f4d7adSDag-Erling Smørgrav } 129c7f4d7adSDag-Erling Smørgrav 130c7f4d7adSDag-Erling Smørgrav /** 131c7f4d7adSDag-Erling Smørgrav * Generate a request for the IPSECKEY. 132c7f4d7adSDag-Erling Smørgrav * 133c7f4d7adSDag-Erling Smørgrav * @param qstate: query state that is the parent. 134c7f4d7adSDag-Erling Smørgrav * @param id: module id. 135c7f4d7adSDag-Erling Smørgrav * @param name: what name to query for. 136c7f4d7adSDag-Erling Smørgrav * @param namelen: length of name. 137c7f4d7adSDag-Erling Smørgrav * @param qtype: query type. 138c7f4d7adSDag-Erling Smørgrav * @param qclass: query class. 139c7f4d7adSDag-Erling Smørgrav * @param flags: additional flags, such as the CD bit (BIT_CD), or 0. 140c7f4d7adSDag-Erling Smørgrav * @return false on alloc failure. 141c7f4d7adSDag-Erling Smørgrav */ 142c7f4d7adSDag-Erling Smørgrav static int 143c7f4d7adSDag-Erling Smørgrav generate_request(struct module_qstate* qstate, int id, uint8_t* name, 144c7f4d7adSDag-Erling Smørgrav size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags) 145c7f4d7adSDag-Erling Smørgrav { 146c7f4d7adSDag-Erling Smørgrav struct module_qstate* newq; 147c7f4d7adSDag-Erling Smørgrav struct query_info ask; 148c7f4d7adSDag-Erling Smørgrav ask.qname = name; 149c7f4d7adSDag-Erling Smørgrav ask.qname_len = namelen; 150c7f4d7adSDag-Erling Smørgrav ask.qtype = qtype; 151c7f4d7adSDag-Erling Smørgrav ask.qclass = qclass; 152c7f4d7adSDag-Erling Smørgrav ask.local_alias = NULL; 153c7f4d7adSDag-Erling Smørgrav log_query_info(VERB_ALGO, "ipsecmod: generate request", &ask); 1545469a995SCy Schubert 1555469a995SCy Schubert /* Explicitly check for cycle before trying to attach. Will result in 1565469a995SCy Schubert * cleaner error message. The attach_sub code also checks for cycle but the 1575469a995SCy Schubert * message will be out of memory in both cases then. */ 1585469a995SCy Schubert fptr_ok(fptr_whitelist_modenv_detect_cycle(qstate->env->detect_cycle)); 1595469a995SCy Schubert if((*qstate->env->detect_cycle)(qstate, &ask, 1605469a995SCy Schubert (uint16_t)(BIT_RD|flags), 0, 0)) { 1615469a995SCy Schubert verbose(VERB_ALGO, "Could not generate request: cycle detected"); 1625469a995SCy Schubert return 0; 1635469a995SCy Schubert } 1645469a995SCy Schubert 165c7f4d7adSDag-Erling Smørgrav fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); 166c7f4d7adSDag-Erling Smørgrav if(!(*qstate->env->attach_sub)(qstate, &ask, 167c7f4d7adSDag-Erling Smørgrav (uint16_t)(BIT_RD|flags), 0, 0, &newq)){ 168c7f4d7adSDag-Erling Smørgrav log_err("Could not generate request: out of memory"); 169c7f4d7adSDag-Erling Smørgrav return 0; 170c7f4d7adSDag-Erling Smørgrav } 171c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_wait_subquery; 172c7f4d7adSDag-Erling Smørgrav return 1; 173c7f4d7adSDag-Erling Smørgrav } 174c7f4d7adSDag-Erling Smørgrav 175c7f4d7adSDag-Erling Smørgrav /** 1760eefd307SCy Schubert * Check if the string passed is a valid domain name with safe characters to 1770eefd307SCy Schubert * pass to a shell. 1780eefd307SCy Schubert * This will only allow: 1790eefd307SCy Schubert * - digits 1800eefd307SCy Schubert * - alphas 1810eefd307SCy Schubert * - hyphen (not at the start) 1820eefd307SCy Schubert * - dot (not at the start, or the only character) 1830eefd307SCy Schubert * - underscore 1840eefd307SCy Schubert * @param s: pointer to the string. 1850eefd307SCy Schubert * @param slen: string's length. 1860eefd307SCy Schubert * @return true if s only contains safe characters; false otherwise. 1870eefd307SCy Schubert */ 1880eefd307SCy Schubert static int 1890eefd307SCy Schubert domainname_has_safe_characters(char* s, size_t slen) { 1900eefd307SCy Schubert size_t i; 1910eefd307SCy Schubert for(i = 0; i < slen; i++) { 1920eefd307SCy Schubert if(s[i] == '\0') return 1; 1930eefd307SCy Schubert if((s[i] == '-' && i != 0) 1940eefd307SCy Schubert || (s[i] == '.' && (i != 0 || s[1] == '\0')) 1950eefd307SCy Schubert || (s[i] == '_') || (s[i] >= '0' && s[i] <= '9') 1960eefd307SCy Schubert || (s[i] >= 'A' && s[i] <= 'Z') 1970eefd307SCy Schubert || (s[i] >= 'a' && s[i] <= 'z')) { 1980eefd307SCy Schubert continue; 1990eefd307SCy Schubert } 2000eefd307SCy Schubert return 0; 2010eefd307SCy Schubert } 2020eefd307SCy Schubert return 1; 2030eefd307SCy Schubert } 2040eefd307SCy Schubert 2050eefd307SCy Schubert /** 2060eefd307SCy Schubert * Check if the stringified IPSECKEY RDATA contains safe characters to pass to 2070eefd307SCy Schubert * a shell. 2080eefd307SCy Schubert * This is only relevant for checking the gateway when the gateway type is 3 2090eefd307SCy Schubert * (domainname). 2100eefd307SCy Schubert * @param s: pointer to the string. 2110eefd307SCy Schubert * @param slen: string's length. 2120eefd307SCy Schubert * @return true if s contains only safe characters; false otherwise. 2130eefd307SCy Schubert */ 2140eefd307SCy Schubert static int 2150eefd307SCy Schubert ipseckey_has_safe_characters(char* s, size_t slen) { 2160eefd307SCy Schubert int precedence, gateway_type, algorithm; 2170eefd307SCy Schubert char* gateway; 2180eefd307SCy Schubert gateway = (char*)calloc(slen, sizeof(char)); 2190eefd307SCy Schubert if(!gateway) { 2200eefd307SCy Schubert log_err("ipsecmod: out of memory when calling the hook"); 2210eefd307SCy Schubert return 0; 2220eefd307SCy Schubert } 2230eefd307SCy Schubert if(sscanf(s, "%d %d %d %s ", 2240eefd307SCy Schubert &precedence, &gateway_type, &algorithm, gateway) != 4) { 2250eefd307SCy Schubert free(gateway); 2260eefd307SCy Schubert return 0; 2270eefd307SCy Schubert } 2280eefd307SCy Schubert if(gateway_type != 3) { 2290eefd307SCy Schubert free(gateway); 2300eefd307SCy Schubert return 1; 2310eefd307SCy Schubert } 2320eefd307SCy Schubert if(domainname_has_safe_characters(gateway, slen)) { 2330eefd307SCy Schubert free(gateway); 2340eefd307SCy Schubert return 1; 2350eefd307SCy Schubert } 2360eefd307SCy Schubert free(gateway); 2370eefd307SCy Schubert return 0; 2380eefd307SCy Schubert } 2390eefd307SCy Schubert 2400eefd307SCy Schubert /** 241c7f4d7adSDag-Erling Smørgrav * Prepare the data and call the hook. 242c7f4d7adSDag-Erling Smørgrav * 243c7f4d7adSDag-Erling Smørgrav * @param qstate: query state. 244c7f4d7adSDag-Erling Smørgrav * @param iq: ipsecmod qstate. 245c7f4d7adSDag-Erling Smørgrav * @param ie: ipsecmod environment. 246c7f4d7adSDag-Erling Smørgrav * @return true on success, false otherwise. 247c7f4d7adSDag-Erling Smørgrav */ 248c7f4d7adSDag-Erling Smørgrav static int 249c7f4d7adSDag-Erling Smørgrav call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq, 250c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ATTR_UNUSED(ie)) 251c7f4d7adSDag-Erling Smørgrav { 252c7f4d7adSDag-Erling Smørgrav size_t slen, tempdata_len, tempstring_len, i; 253c7f4d7adSDag-Erling Smørgrav char str[65535], *s, *tempstring; 2540eefd307SCy Schubert int w = 0, w_temp, qtype; 255c7f4d7adSDag-Erling Smørgrav struct ub_packed_rrset_key* rrset_key; 256c7f4d7adSDag-Erling Smørgrav struct packed_rrset_data* rrset_data; 257c7f4d7adSDag-Erling Smørgrav uint8_t *tempdata; 258c7f4d7adSDag-Erling Smørgrav 259c7f4d7adSDag-Erling Smørgrav /* Check if a shell is available */ 260c7f4d7adSDag-Erling Smørgrav if(system(NULL) == 0) { 261c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: no shell available for ipsecmod-hook"); 262c7f4d7adSDag-Erling Smørgrav return 0; 263c7f4d7adSDag-Erling Smørgrav } 264c7f4d7adSDag-Erling Smørgrav 265c7f4d7adSDag-Erling Smørgrav /* Zero the buffer. */ 266c7f4d7adSDag-Erling Smørgrav s = str; 267c7f4d7adSDag-Erling Smørgrav slen = sizeof(str); 268c7f4d7adSDag-Erling Smørgrav memset(s, 0, slen); 269c7f4d7adSDag-Erling Smørgrav 270c7f4d7adSDag-Erling Smørgrav /* Copy the hook into the buffer. */ 2710eefd307SCy Schubert w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook); 272c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 2730eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 274c7f4d7adSDag-Erling Smørgrav /* Copy the qname into the buffer. */ 275c7f4d7adSDag-Erling Smørgrav tempstring = sldns_wire2str_dname(qstate->qinfo.qname, 276c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qname_len); 277c7f4d7adSDag-Erling Smørgrav if(!tempstring) { 278c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: out of memory when calling the hook"); 279c7f4d7adSDag-Erling Smørgrav return 0; 280c7f4d7adSDag-Erling Smørgrav } 2810eefd307SCy Schubert if(!domainname_has_safe_characters(tempstring, strlen(tempstring))) { 2820eefd307SCy Schubert log_err("ipsecmod: qname has unsafe characters"); 2830eefd307SCy Schubert free(tempstring); 2840eefd307SCy Schubert return 0; 2850eefd307SCy Schubert } 2860eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\"%s\"", tempstring); 287c7f4d7adSDag-Erling Smørgrav free(tempstring); 288c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 2890eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 290c7f4d7adSDag-Erling Smørgrav /* Copy the IPSECKEY TTL into the buffer. */ 291c7f4d7adSDag-Erling Smørgrav rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; 2920eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl); 293c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 2940eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 295c7f4d7adSDag-Erling Smørgrav rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo, 296c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep); 2970eefd307SCy Schubert /* Double check that the records are indeed A/AAAA. 2980eefd307SCy Schubert * This should never happen as this function is only executed for A/AAAA 2990eefd307SCy Schubert * queries but make sure we don't pass anything other than A/AAAA to the 3000eefd307SCy Schubert * shell. */ 3010eefd307SCy Schubert qtype = ntohs(rrset_key->rk.type); 3020eefd307SCy Schubert if(qtype != LDNS_RR_TYPE_AAAA && qtype != LDNS_RR_TYPE_A) { 3030eefd307SCy Schubert log_err("ipsecmod: Answer is not of A or AAAA type"); 3040eefd307SCy Schubert return 0; 3050eefd307SCy Schubert } 306c7f4d7adSDag-Erling Smørgrav rrset_data = (struct packed_rrset_data*)rrset_key->entry.data; 3070eefd307SCy Schubert /* Copy the A/AAAA record(s) into the buffer. Start and end this section 3080eefd307SCy Schubert * with a double quote. */ 3090eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\""); 310c7f4d7adSDag-Erling Smørgrav for(i=0; i<rrset_data->count; i++) { 311c7f4d7adSDag-Erling Smørgrav if(i > 0) { 312c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 3130eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 314c7f4d7adSDag-Erling Smørgrav } 315c7f4d7adSDag-Erling Smørgrav /* Ignore the first two bytes, they are the rr_data len. */ 3160eefd307SCy Schubert w_temp = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2, 317c7f4d7adSDag-Erling Smørgrav rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype); 3180eefd307SCy Schubert if(w_temp < 0) { 319c7f4d7adSDag-Erling Smørgrav /* Error in printout. */ 3200eefd307SCy Schubert log_err("ipsecmod: Error in printing IP address"); 3210eefd307SCy Schubert return 0; 3220eefd307SCy Schubert } else if((size_t)w_temp >= slen) { 323c7f4d7adSDag-Erling Smørgrav s = NULL; /* We do not want str to point outside of buffer. */ 324c7f4d7adSDag-Erling Smørgrav slen = 0; 3250eefd307SCy Schubert log_err("ipsecmod: shell command too long"); 3260eefd307SCy Schubert return 0; 327c7f4d7adSDag-Erling Smørgrav } else { 3280eefd307SCy Schubert s += w_temp; 3290eefd307SCy Schubert slen -= w_temp; 3300eefd307SCy Schubert w += w_temp; 331c7f4d7adSDag-Erling Smørgrav } 332c7f4d7adSDag-Erling Smørgrav } 3330eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\""); 334c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 3350eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 336c7f4d7adSDag-Erling Smørgrav /* Copy the IPSECKEY record(s) into the buffer. Start and end this section 337c7f4d7adSDag-Erling Smørgrav * with a double quote. */ 3380eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\""); 339c7f4d7adSDag-Erling Smørgrav rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; 340c7f4d7adSDag-Erling Smørgrav for(i=0; i<rrset_data->count; i++) { 341c7f4d7adSDag-Erling Smørgrav if(i > 0) { 342c7f4d7adSDag-Erling Smørgrav /* Put space into the buffer. */ 3430eefd307SCy Schubert w += sldns_str_print(&s, &slen, " "); 344c7f4d7adSDag-Erling Smørgrav } 345c7f4d7adSDag-Erling Smørgrav /* Ignore the first two bytes, they are the rr_data len. */ 346c7f4d7adSDag-Erling Smørgrav tempdata = rrset_data->rr_data[i] + 2; 347c7f4d7adSDag-Erling Smørgrav tempdata_len = rrset_data->rr_len[i] - 2; 348c7f4d7adSDag-Erling Smørgrav /* Save the buffer pointers. */ 349c7f4d7adSDag-Erling Smørgrav tempstring = s; tempstring_len = slen; 3500eefd307SCy Schubert w_temp = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, 3510eefd307SCy Schubert &slen, NULL, 0, NULL); 352c7f4d7adSDag-Erling Smørgrav /* There was an error when parsing the IPSECKEY; reset the buffer 353c7f4d7adSDag-Erling Smørgrav * pointers to their previous values. */ 3540eefd307SCy Schubert if(w_temp == -1) { 355c7f4d7adSDag-Erling Smørgrav s = tempstring; slen = tempstring_len; 3560eefd307SCy Schubert } else if(w_temp > 0) { 3570eefd307SCy Schubert if(!ipseckey_has_safe_characters( 3580eefd307SCy Schubert tempstring, tempstring_len - slen)) { 3590eefd307SCy Schubert log_err("ipsecmod: ipseckey has unsafe characters"); 3600eefd307SCy Schubert return 0; 3610eefd307SCy Schubert } 3620eefd307SCy Schubert w += w_temp; 363c7f4d7adSDag-Erling Smørgrav } 364c7f4d7adSDag-Erling Smørgrav } 3650eefd307SCy Schubert w += sldns_str_print(&s, &slen, "\""); 3660eefd307SCy Schubert if(w >= (int)sizeof(str)) { 3670eefd307SCy Schubert log_err("ipsecmod: shell command too long"); 3680eefd307SCy Schubert return 0; 3690eefd307SCy Schubert } 3700eefd307SCy Schubert verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str); 371c7f4d7adSDag-Erling Smørgrav /* ipsecmod-hook should return 0 on success. */ 372c7f4d7adSDag-Erling Smørgrav if(system(str) != 0) 373c7f4d7adSDag-Erling Smørgrav return 0; 374c7f4d7adSDag-Erling Smørgrav return 1; 375c7f4d7adSDag-Erling Smørgrav } 376c7f4d7adSDag-Erling Smørgrav 377c7f4d7adSDag-Erling Smørgrav /** 378c7f4d7adSDag-Erling Smørgrav * Handle an ipsecmod module event with a query 379c7f4d7adSDag-Erling Smørgrav * @param qstate: query state (from the mesh), passed between modules. 380c7f4d7adSDag-Erling Smørgrav * contains qstate->env module environment with global caches and so on. 381c7f4d7adSDag-Erling Smørgrav * @param iq: query state specific for this module. per-query. 382c7f4d7adSDag-Erling Smørgrav * @param ie: environment specific for this module. global. 383c7f4d7adSDag-Erling Smørgrav * @param id: module id. 384c7f4d7adSDag-Erling Smørgrav */ 385c7f4d7adSDag-Erling Smørgrav static void 386c7f4d7adSDag-Erling Smørgrav ipsecmod_handle_query(struct module_qstate* qstate, 387c7f4d7adSDag-Erling Smørgrav struct ipsecmod_qstate* iq, struct ipsecmod_env* ie, int id) 388c7f4d7adSDag-Erling Smørgrav { 389c7f4d7adSDag-Erling Smørgrav struct ub_packed_rrset_key* rrset_key; 390c7f4d7adSDag-Erling Smørgrav struct packed_rrset_data* rrset_data; 391c7f4d7adSDag-Erling Smørgrav size_t i; 392c7f4d7adSDag-Erling Smørgrav /* Pass to next module if we are not enabled and whitelisted. */ 393c7f4d7adSDag-Erling Smørgrav if(!(iq->enabled && iq->is_whitelisted)) { 394c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_wait_module; 395c7f4d7adSDag-Erling Smørgrav return; 396c7f4d7adSDag-Erling Smørgrav } 397c7f4d7adSDag-Erling Smørgrav /* New query, check if the query is for an A/AAAA record and disable 398c7f4d7adSDag-Erling Smørgrav * caching for other modules. */ 399c7f4d7adSDag-Erling Smørgrav if(!iq->ipseckey_done) { 400c7f4d7adSDag-Erling Smørgrav if(qstate->qinfo.qtype == LDNS_RR_TYPE_A || 401c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { 402c7f4d7adSDag-Erling Smørgrav char type[16]; 403c7f4d7adSDag-Erling Smørgrav sldns_wire2str_type_buf(qstate->qinfo.qtype, type, 404c7f4d7adSDag-Erling Smørgrav sizeof(type)); 405c7f4d7adSDag-Erling Smørgrav verbose(VERB_ALGO, "ipsecmod: query for %s; engaging", 406c7f4d7adSDag-Erling Smørgrav type); 407c7f4d7adSDag-Erling Smørgrav qstate->no_cache_store = 1; 408c7f4d7adSDag-Erling Smørgrav } 409c7f4d7adSDag-Erling Smørgrav /* Pass request to next module. */ 410c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_wait_module; 411c7f4d7adSDag-Erling Smørgrav return; 412c7f4d7adSDag-Erling Smørgrav } 413c7f4d7adSDag-Erling Smørgrav /* IPSECKEY subquery is finished. */ 414c7f4d7adSDag-Erling Smørgrav /* We have an IPSECKEY answer. */ 415c7f4d7adSDag-Erling Smørgrav if(iq->ipseckey_rrset) { 416c7f4d7adSDag-Erling Smørgrav rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data; 417c7f4d7adSDag-Erling Smørgrav if(rrset_data) { 418c7f4d7adSDag-Erling Smørgrav /* If bogus return SERVFAIL. */ 419c7f4d7adSDag-Erling Smørgrav if(!qstate->env->cfg->ipsecmod_ignore_bogus && 420c7f4d7adSDag-Erling Smørgrav rrset_data->security == sec_status_bogus) { 421c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: bogus IPSECKEY"); 4225469a995SCy Schubert errinf(qstate, "ipsecmod: bogus IPSECKEY"); 423c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 424c7f4d7adSDag-Erling Smørgrav return; 425c7f4d7adSDag-Erling Smørgrav } 426c7f4d7adSDag-Erling Smørgrav /* We have a valid IPSECKEY reply, call hook. */ 427c7f4d7adSDag-Erling Smørgrav if(!call_hook(qstate, iq, ie) && 428c7f4d7adSDag-Erling Smørgrav qstate->env->cfg->ipsecmod_strict) { 429c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: ipsecmod-hook failed"); 4305469a995SCy Schubert errinf(qstate, "ipsecmod: ipsecmod-hook failed"); 431c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 432c7f4d7adSDag-Erling Smørgrav return; 433c7f4d7adSDag-Erling Smørgrav } 434c7f4d7adSDag-Erling Smørgrav /* Make sure the A/AAAA's TTL is equal/less than the 435c7f4d7adSDag-Erling Smørgrav * ipsecmod_max_ttl. */ 436c7f4d7adSDag-Erling Smørgrav rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo, 437c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep); 438c7f4d7adSDag-Erling Smørgrav rrset_data = (struct packed_rrset_data*)rrset_key->entry.data; 439c7f4d7adSDag-Erling Smørgrav if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) { 440c7f4d7adSDag-Erling Smørgrav /* Update TTL for rrset to fixed value. */ 441c7f4d7adSDag-Erling Smørgrav rrset_data->ttl = qstate->env->cfg->ipsecmod_max_ttl; 442c7f4d7adSDag-Erling Smørgrav for(i=0; i<rrset_data->count+rrset_data->rrsig_count; i++) 443c7f4d7adSDag-Erling Smørgrav rrset_data->rr_ttl[i] = qstate->env->cfg->ipsecmod_max_ttl; 444c7f4d7adSDag-Erling Smørgrav /* Also update reply_info's TTL */ 445c7f4d7adSDag-Erling Smørgrav if(qstate->return_msg->rep->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) { 446c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep->ttl = 447c7f4d7adSDag-Erling Smørgrav qstate->env->cfg->ipsecmod_max_ttl; 448c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC( 449c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep->ttl); 4504c75e3aaSDag-Erling Smørgrav qstate->return_msg->rep->serve_expired_ttl = qstate->return_msg->rep->ttl + 4514c75e3aaSDag-Erling Smørgrav qstate->env->cfg->serve_expired_ttl; 452c7f4d7adSDag-Erling Smørgrav } 453c7f4d7adSDag-Erling Smørgrav } 454c7f4d7adSDag-Erling Smørgrav } 455c7f4d7adSDag-Erling Smørgrav } 456c7f4d7adSDag-Erling Smørgrav /* Store A/AAAA in cache. */ 457c7f4d7adSDag-Erling Smørgrav if(!dns_cache_store(qstate->env, &qstate->qinfo, 458c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep, 0, qstate->prefetch_leeway, 459*be771a7bSCy Schubert 0, qstate->region, qstate->query_flags, qstate->qstarttime, 460*be771a7bSCy Schubert qstate->is_valrec)) { 461c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: out of memory caching record"); 462c7f4d7adSDag-Erling Smørgrav } 463c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_finished; 464c7f4d7adSDag-Erling Smørgrav } 465c7f4d7adSDag-Erling Smørgrav 466c7f4d7adSDag-Erling Smørgrav /** 467c7f4d7adSDag-Erling Smørgrav * Handle an ipsecmod module event with a response from the iterator. 468c7f4d7adSDag-Erling Smørgrav * @param qstate: query state (from the mesh), passed between modules. 469c7f4d7adSDag-Erling Smørgrav * contains qstate->env module environment with global caches and so on. 470c7f4d7adSDag-Erling Smørgrav * @param iq: query state specific for this module. per-query. 471c7f4d7adSDag-Erling Smørgrav * @param ie: environment specific for this module. global. 472c7f4d7adSDag-Erling Smørgrav * @param id: module id. 473c7f4d7adSDag-Erling Smørgrav */ 474c7f4d7adSDag-Erling Smørgrav static void 475c7f4d7adSDag-Erling Smørgrav ipsecmod_handle_response(struct module_qstate* qstate, 476c7f4d7adSDag-Erling Smørgrav struct ipsecmod_qstate* ATTR_UNUSED(iq), 477c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ATTR_UNUSED(ie), int id) 478c7f4d7adSDag-Erling Smørgrav { 479c7f4d7adSDag-Erling Smørgrav /* Pass to previous module if we are not enabled and whitelisted. */ 480c7f4d7adSDag-Erling Smørgrav if(!(iq->enabled && iq->is_whitelisted)) { 481c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_finished; 482c7f4d7adSDag-Erling Smørgrav return; 483c7f4d7adSDag-Erling Smørgrav } 484c7f4d7adSDag-Erling Smørgrav /* check if the response is for an A/AAAA query. */ 485c7f4d7adSDag-Erling Smørgrav if((qstate->qinfo.qtype == LDNS_RR_TYPE_A || 486c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) && 487c7f4d7adSDag-Erling Smørgrav /* check that we had an answer for the A/AAAA query. */ 488c7f4d7adSDag-Erling Smørgrav qstate->return_msg && 489c7f4d7adSDag-Erling Smørgrav reply_find_answer_rrset(&qstate->return_msg->qinfo, 490c7f4d7adSDag-Erling Smørgrav qstate->return_msg->rep) && 491c7f4d7adSDag-Erling Smørgrav /* check that another module didn't SERVFAIL. */ 492c7f4d7adSDag-Erling Smørgrav qstate->return_rcode == LDNS_RCODE_NOERROR) { 493c7f4d7adSDag-Erling Smørgrav char type[16]; 494c7f4d7adSDag-Erling Smørgrav sldns_wire2str_type_buf(qstate->qinfo.qtype, type, 495c7f4d7adSDag-Erling Smørgrav sizeof(type)); 496c7f4d7adSDag-Erling Smørgrav verbose(VERB_ALGO, "ipsecmod: response for %s; generating IPSECKEY " 497c7f4d7adSDag-Erling Smørgrav "subquery", type); 498c7f4d7adSDag-Erling Smørgrav /* generate an IPSECKEY query. */ 499c7f4d7adSDag-Erling Smørgrav if(!generate_request(qstate, id, qstate->qinfo.qname, 500c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qname_len, LDNS_RR_TYPE_IPSECKEY, 501c7f4d7adSDag-Erling Smørgrav qstate->qinfo.qclass, 0)) { 502c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: could not generate subquery."); 5035469a995SCy Schubert errinf(qstate, "ipsecmod: could not generate subquery."); 504c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 505c7f4d7adSDag-Erling Smørgrav } 506c7f4d7adSDag-Erling Smørgrav return; 507c7f4d7adSDag-Erling Smørgrav } 508c7f4d7adSDag-Erling Smørgrav /* we are done with the query. */ 509c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_finished; 510c7f4d7adSDag-Erling Smørgrav } 511c7f4d7adSDag-Erling Smørgrav 512c7f4d7adSDag-Erling Smørgrav void 513c7f4d7adSDag-Erling Smørgrav ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id, 514c7f4d7adSDag-Erling Smørgrav struct outbound_entry* outbound) 515c7f4d7adSDag-Erling Smørgrav { 516c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ie = (struct ipsecmod_env*)qstate->env->modinfo[id]; 517c7f4d7adSDag-Erling Smørgrav struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)qstate->minfo[id]; 518c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "ipsecmod[module %d] operate: extstate:%s event:%s", 519c7f4d7adSDag-Erling Smørgrav id, strextstate(qstate->ext_state[id]), strmodulevent(event)); 520c7f4d7adSDag-Erling Smørgrav if(iq) log_query_info(VERB_QUERY, "ipsecmod operate: query", 521c7f4d7adSDag-Erling Smørgrav &qstate->qinfo); 522c7f4d7adSDag-Erling Smørgrav 523c7f4d7adSDag-Erling Smørgrav /* create ipsecmod_qstate. */ 524c7f4d7adSDag-Erling Smørgrav if((event == module_event_new || event == module_event_pass) && 525c7f4d7adSDag-Erling Smørgrav iq == NULL) { 526c7f4d7adSDag-Erling Smørgrav if(!ipsecmod_new(qstate, id)) { 5275469a995SCy Schubert errinf(qstate, "ipsecmod: could not ipsecmod_new"); 528c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 529c7f4d7adSDag-Erling Smørgrav return; 530c7f4d7adSDag-Erling Smørgrav } 531c7f4d7adSDag-Erling Smørgrav iq = (struct ipsecmod_qstate*)qstate->minfo[id]; 532c7f4d7adSDag-Erling Smørgrav } 533c7f4d7adSDag-Erling Smørgrav if(iq && (event == module_event_pass || event == module_event_new)) { 534c7f4d7adSDag-Erling Smørgrav ipsecmod_handle_query(qstate, iq, ie, id); 535c7f4d7adSDag-Erling Smørgrav return; 536c7f4d7adSDag-Erling Smørgrav } 537c7f4d7adSDag-Erling Smørgrav if(iq && (event == module_event_moddone)) { 538c7f4d7adSDag-Erling Smørgrav ipsecmod_handle_response(qstate, iq, ie, id); 539c7f4d7adSDag-Erling Smørgrav return; 540c7f4d7adSDag-Erling Smørgrav } 541c7f4d7adSDag-Erling Smørgrav if(iq && outbound) { 542c7f4d7adSDag-Erling Smørgrav /* cachedb does not need to process responses at this time 543c7f4d7adSDag-Erling Smørgrav * ignore it. 544c7f4d7adSDag-Erling Smørgrav cachedb_process_response(qstate, iq, ie, id, outbound, event); 545c7f4d7adSDag-Erling Smørgrav */ 546c7f4d7adSDag-Erling Smørgrav return; 547c7f4d7adSDag-Erling Smørgrav } 548c7f4d7adSDag-Erling Smørgrav if(event == module_event_error) { 549c7f4d7adSDag-Erling Smørgrav verbose(VERB_ALGO, "got called with event error, giving up"); 5505469a995SCy Schubert errinf(qstate, "ipsecmod: got called with event error"); 551c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 552c7f4d7adSDag-Erling Smørgrav return; 553c7f4d7adSDag-Erling Smørgrav } 554c7f4d7adSDag-Erling Smørgrav if(!iq && (event == module_event_moddone)) { 555c7f4d7adSDag-Erling Smørgrav /* during priming, module done but we never started. */ 556c7f4d7adSDag-Erling Smørgrav qstate->ext_state[id] = module_finished; 557c7f4d7adSDag-Erling Smørgrav return; 558c7f4d7adSDag-Erling Smørgrav } 559c7f4d7adSDag-Erling Smørgrav 560c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: bad event %s", strmodulevent(event)); 5615469a995SCy Schubert errinf(qstate, "ipsecmod: operate got bad event"); 562c7f4d7adSDag-Erling Smørgrav ipsecmod_error(qstate, id); 563c7f4d7adSDag-Erling Smørgrav return; 564c7f4d7adSDag-Erling Smørgrav } 565c7f4d7adSDag-Erling Smørgrav 566c7f4d7adSDag-Erling Smørgrav void 567c7f4d7adSDag-Erling Smørgrav ipsecmod_inform_super(struct module_qstate* qstate, int id, 568c7f4d7adSDag-Erling Smørgrav struct module_qstate* super) 569c7f4d7adSDag-Erling Smørgrav { 570c7f4d7adSDag-Erling Smørgrav struct ipsecmod_qstate* siq; 571c7f4d7adSDag-Erling Smørgrav log_query_info(VERB_ALGO, "ipsecmod: inform_super, sub is", 572c7f4d7adSDag-Erling Smørgrav &qstate->qinfo); 573c7f4d7adSDag-Erling Smørgrav log_query_info(VERB_ALGO, "super is", &super->qinfo); 574c7f4d7adSDag-Erling Smørgrav siq = (struct ipsecmod_qstate*)super->minfo[id]; 575c7f4d7adSDag-Erling Smørgrav if(!siq) { 576c7f4d7adSDag-Erling Smørgrav verbose(VERB_ALGO, "super has no ipsecmod state"); 577c7f4d7adSDag-Erling Smørgrav return; 578c7f4d7adSDag-Erling Smørgrav } 579c7f4d7adSDag-Erling Smørgrav 580c7f4d7adSDag-Erling Smørgrav if(qstate->return_msg) { 581c7f4d7adSDag-Erling Smørgrav struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset( 582c7f4d7adSDag-Erling Smørgrav &qstate->return_msg->qinfo, qstate->return_msg->rep); 583c7f4d7adSDag-Erling Smørgrav if(rrset_key) { 584c7f4d7adSDag-Erling Smørgrav /* We have an answer. */ 585c7f4d7adSDag-Erling Smørgrav /* Copy to super's region. */ 586c7f4d7adSDag-Erling Smørgrav rrset_key = packed_rrset_copy_region(rrset_key, super->region, 0); 587c7f4d7adSDag-Erling Smørgrav siq->ipseckey_rrset = rrset_key; 588c7f4d7adSDag-Erling Smørgrav if(!rrset_key) { 589c7f4d7adSDag-Erling Smørgrav log_err("ipsecmod: out of memory."); 590c7f4d7adSDag-Erling Smørgrav } 591c7f4d7adSDag-Erling Smørgrav } 592c7f4d7adSDag-Erling Smørgrav } 593c7f4d7adSDag-Erling Smørgrav /* Notify super to proceed. */ 594c7f4d7adSDag-Erling Smørgrav siq->ipseckey_done = 1; 595c7f4d7adSDag-Erling Smørgrav } 596c7f4d7adSDag-Erling Smørgrav 597c7f4d7adSDag-Erling Smørgrav void 598c7f4d7adSDag-Erling Smørgrav ipsecmod_clear(struct module_qstate* qstate, int id) 599c7f4d7adSDag-Erling Smørgrav { 600c7f4d7adSDag-Erling Smørgrav if(!qstate) 601c7f4d7adSDag-Erling Smørgrav return; 602c7f4d7adSDag-Erling Smørgrav qstate->minfo[id] = NULL; 603c7f4d7adSDag-Erling Smørgrav } 604c7f4d7adSDag-Erling Smørgrav 605c7f4d7adSDag-Erling Smørgrav size_t 606c7f4d7adSDag-Erling Smørgrav ipsecmod_get_mem(struct module_env* env, int id) 607c7f4d7adSDag-Erling Smørgrav { 608c7f4d7adSDag-Erling Smørgrav struct ipsecmod_env* ie = (struct ipsecmod_env*)env->modinfo[id]; 609c7f4d7adSDag-Erling Smørgrav if(!ie) 610c7f4d7adSDag-Erling Smørgrav return 0; 611c7f4d7adSDag-Erling Smørgrav return sizeof(*ie) + ipsecmod_whitelist_get_mem(ie->whitelist); 612c7f4d7adSDag-Erling Smørgrav } 613c7f4d7adSDag-Erling Smørgrav 614c7f4d7adSDag-Erling Smørgrav /** 615c7f4d7adSDag-Erling Smørgrav * The ipsecmod function block 616c7f4d7adSDag-Erling Smørgrav */ 617c7f4d7adSDag-Erling Smørgrav static struct module_func_block ipsecmod_block = { 618c7f4d7adSDag-Erling Smørgrav "ipsecmod", 61956850988SCy Schubert NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate, 620c7f4d7adSDag-Erling Smørgrav &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem 621c7f4d7adSDag-Erling Smørgrav }; 622c7f4d7adSDag-Erling Smørgrav 623c7f4d7adSDag-Erling Smørgrav struct module_func_block* 624c7f4d7adSDag-Erling Smørgrav ipsecmod_get_funcblock(void) 625c7f4d7adSDag-Erling Smørgrav { 626c7f4d7adSDag-Erling Smørgrav return &ipsecmod_block; 627c7f4d7adSDag-Erling Smørgrav } 628c7f4d7adSDag-Erling Smørgrav #endif /* USE_IPSECMOD */ 629