1 /* 2 * pythonmod_utils.c: utilities used by wrapper 3 * 4 * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz) 5 * Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz) 6 * 7 * This software is open source. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * * Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 16 * * Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 20 * * Neither the name of the organization nor the names of its 21 * contributors may be used to endorse or promote products derived from this 22 * software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 /** 37 * \file 38 * Utility functions for the python module that perform stores and loads and 39 * conversions. 40 */ 41 #include "config.h" 42 #include "pythonmod/pythonmod_utils.h" 43 #include "util/module.h" 44 #include "util/netevent.h" 45 #include "util/net_help.h" 46 #include "services/cache/dns.h" 47 #include "services/cache/rrset.h" 48 #include "util/data/msgparse.h" 49 #include "util/data/msgreply.h" 50 #include "util/storage/slabhash.h" 51 #include "util/regional.h" 52 #include "iterator/iter_delegpt.h" 53 #include "sldns/sbuffer.h" 54 55 #undef _POSIX_C_SOURCE 56 #undef _XOPEN_SOURCE 57 #include <Python.h> 58 59 /* Store the reply_info and query_info pair in message cache 60 * (qstate->msg_cache) */ 61 int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, 62 struct reply_info* msgrep, int is_referral) 63 { 64 if (!msgrep) 65 return 0; 66 67 /* authoritative answer can't be stored in cache */ 68 if (msgrep->authoritative) { 69 PyErr_SetString(PyExc_ValueError, 70 "Authoritative answer can't be stored"); 71 return 0; 72 } 73 74 return dns_cache_store(qstate->env, qinfo, msgrep, is_referral, 75 qstate->prefetch_leeway, 0, NULL, qstate->query_flags, 76 qstate->qstarttime); 77 } 78 79 /* Invalidate the message associated with query_info stored in message cache */ 80 void invalidateQueryInCache(struct module_qstate* qstate, 81 struct query_info* qinfo) 82 { 83 hashvalue_type h; 84 struct lruhash_entry* e; 85 struct reply_info *r; 86 size_t i, j; 87 88 h = query_info_hash(qinfo, qstate->query_flags); 89 if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) { 90 r = (struct reply_info*)(e->data); 91 if (r) { 92 r->ttl = 0; 93 if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) { 94 for(i=0; i< r->rrset_count; i++) { 95 struct packed_rrset_data* data = 96 (struct packed_rrset_data*) r->ref[i].key->entry.data; 97 if(i>0 && r->ref[i].key == r->ref[i-1].key) 98 continue; 99 100 data->ttl = r->ttl; 101 for(j=0; j<data->count + data->rrsig_count; j++) 102 data->rr_ttl[j] = r->ttl; 103 } 104 rrset_array_unlock(r->ref, r->rrset_count); 105 } 106 } 107 lock_rw_unlock(&e->lock); 108 } else { 109 log_info("invalidateQueryInCache: qinfo is not in cache"); 110 } 111 } 112 113 /* Create response according to the ldns packet content */ 114 int createResponse(struct module_qstate* qstate, sldns_buffer* pkt) 115 { 116 struct msg_parse* prs; 117 struct edns_data edns; 118 119 /* parse message */ 120 prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, 121 sizeof(struct msg_parse)); 122 if(!prs) { 123 log_err("createResponse: out of memory on incoming message"); 124 return 0; 125 } 126 127 memset(prs, 0, sizeof(*prs)); 128 memset(&edns, 0, sizeof(edns)); 129 130 sldns_buffer_set_position(pkt, 0); 131 if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) { 132 verbose(VERB_ALGO, "createResponse: parse error on reply packet"); 133 return 0; 134 } 135 /* edns is not examined, but removed from message to help cache */ 136 if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) != 137 LDNS_RCODE_NOERROR) 138 return 0; 139 140 /* remove CD-bit, we asked for in case we handle validation ourself */ 141 prs->flags &= ~BIT_CD; 142 143 /* allocate response dns_msg in region */ 144 qstate->return_msg = (struct dns_msg*) regional_alloc(qstate->region, 145 sizeof(struct dns_msg)); 146 if(!qstate->return_msg) 147 return 0; 148 149 memset(qstate->return_msg, 0, sizeof(*qstate->return_msg)); 150 if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, 151 &(qstate->return_msg)->rep, qstate->region)) { 152 log_err("createResponse: malloc failure: allocating incoming dns_msg"); 153 return 0; 154 } 155 156 /* Make sure that the RA flag is set (since the presence of 157 * this module means that recursion is available) */ 158 /* qstate->return_msg->rep->flags |= BIT_RA; */ 159 160 /* Clear the AA flag */ 161 /* FIXME: does this action go here or in some other module? */ 162 /*qstate->return_msg->rep->flags &= ~BIT_AA; */ 163 164 /* make sure QR flag is on */ 165 /*qstate->return_msg->rep->flags |= BIT_QR; */ 166 167 if(verbosity >= VERB_ALGO) 168 log_dns_msg("createResponse: packet:", &qstate->return_msg->qinfo, 169 qstate->return_msg->rep); 170 171 return 1; 172 } 173 174 175 /* Convert reply->client_addr to string */ 176 void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen) 177 { 178 int af = (int)((struct sockaddr_in*) &(reply->client_addr))->sin_family; 179 void* sinaddr = &((struct sockaddr_in*) &(reply->client_addr))->sin_addr; 180 181 if(af == AF_INET6) 182 sinaddr = &((struct sockaddr_in6*)&(reply->client_addr))->sin6_addr; 183 dest[0] = 0; 184 if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0) 185 return; 186 dest[maxlen-1] = 0; 187 } 188 189 /* Convert target->addr to string */ 190 void delegpt_addr_addr2str(struct delegpt_addr* target, char *dest, int maxlen) 191 { 192 int af = (int)((struct sockaddr_in*) &(target->addr))->sin_family; 193 void* sinaddr = &((struct sockaddr_in*) &(target->addr))->sin_addr; 194 195 if(af == AF_INET6) 196 sinaddr = &((struct sockaddr_in6*)&(target->addr))->sin6_addr; 197 dest[0] = 0; 198 if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0) 199 return; 200 dest[maxlen-1] = 0; 201 } 202