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) */
storeQueryInCache(struct module_qstate * qstate,struct query_info * qinfo,struct reply_info * msgrep,int is_referral)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 }
77
78 /* Invalidate the message associated with query_info stored in message cache */
invalidateQueryInCache(struct module_qstate * qstate,struct query_info * qinfo)79 void invalidateQueryInCache(struct module_qstate* qstate,
80 struct query_info* qinfo)
81 {
82 hashvalue_type h;
83 struct lruhash_entry* e;
84 struct reply_info *r;
85 size_t i, j;
86
87 h = query_info_hash(qinfo, qstate->query_flags);
88 if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) {
89 r = (struct reply_info*)(e->data);
90 if (r) {
91 r->ttl = 0;
92 if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) {
93 for(i=0; i< r->rrset_count; i++) {
94 struct packed_rrset_data* data =
95 (struct packed_rrset_data*) r->ref[i].key->entry.data;
96 if(i>0 && r->ref[i].key == r->ref[i-1].key)
97 continue;
98
99 data->ttl = r->ttl;
100 for(j=0; j<data->count + data->rrsig_count; j++)
101 data->rr_ttl[j] = r->ttl;
102 }
103 rrset_array_unlock(r->ref, r->rrset_count);
104 }
105 }
106 lock_rw_unlock(&e->lock);
107 } else {
108 log_info("invalidateQueryInCache: qinfo is not in cache");
109 }
110 }
111
112 /* Create response according to the ldns packet content */
createResponse(struct module_qstate * qstate,sldns_buffer * pkt)113 int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
114 {
115 struct msg_parse* prs;
116 struct edns_data edns;
117
118 /* parse message */
119 prs = (struct msg_parse*) regional_alloc(qstate->env->scratch,
120 sizeof(struct msg_parse));
121 if(!prs) {
122 log_err("createResponse: out of memory on incoming message");
123 return 0;
124 }
125
126 memset(prs, 0, sizeof(*prs));
127 memset(&edns, 0, sizeof(edns));
128
129 sldns_buffer_set_position(pkt, 0);
130 if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
131 verbose(VERB_ALGO, "createResponse: parse error on reply packet");
132 return 0;
133 }
134 /* edns is not examined, but removed from message to help cache */
135 if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
136 LDNS_RCODE_NOERROR)
137 return 0;
138
139 /* remove CD-bit, we asked for in case we handle validation ourself */
140 prs->flags &= ~BIT_CD;
141
142 /* allocate response dns_msg in region */
143 qstate->return_msg = (struct dns_msg*) regional_alloc(qstate->region,
144 sizeof(struct dns_msg));
145 if(!qstate->return_msg)
146 return 0;
147
148 memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
149 if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo,
150 &(qstate->return_msg)->rep, qstate->region)) {
151 log_err("createResponse: malloc failure: allocating incoming dns_msg");
152 return 0;
153 }
154
155 /* Make sure that the RA flag is set (since the presence of
156 * this module means that recursion is available) */
157 /* qstate->return_msg->rep->flags |= BIT_RA; */
158
159 /* Clear the AA flag */
160 /* FIXME: does this action go here or in some other module? */
161 /*qstate->return_msg->rep->flags &= ~BIT_AA; */
162
163 /* make sure QR flag is on */
164 /*qstate->return_msg->rep->flags |= BIT_QR; */
165
166 if(verbosity >= VERB_ALGO)
167 log_dns_msg("createResponse: packet:", &qstate->return_msg->qinfo,
168 qstate->return_msg->rep);
169
170 return 1;
171 }
172
173
174 /* Convert reply->addr to string */
reply_addr2str(struct comm_reply * reply,char * dest,int maxlen)175 void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
176 {
177 int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
178 void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
179
180 if(af == AF_INET6)
181 sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
182 dest[0] = 0;
183 if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
184 return;
185 dest[maxlen-1] = 0;
186 }
187
188 /* Convert target->addr to string */
delegpt_addr_addr2str(struct delegpt_addr * target,char * dest,int maxlen)189 void delegpt_addr_addr2str(struct delegpt_addr* target, char *dest, int maxlen)
190 {
191 int af = (int)((struct sockaddr_in*) &(target->addr))->sin_family;
192 void* sinaddr = &((struct sockaddr_in*) &(target->addr))->sin_addr;
193
194 if(af == AF_INET6)
195 sinaddr = &((struct sockaddr_in6*)&(target->addr))->sin6_addr;
196 dest[0] = 0;
197 if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
198 return;
199 dest[maxlen-1] = 0;
200 }
201