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