]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - pythonmod/pythonmod_utils.c
Apply upstream fix 08968baec1122a58bb90d8f97ad948a75f8a5d69:
[FreeBSD/FreeBSD.git] / pythonmod / pythonmod_utils.c
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 "util/module.h"
43 #include "util/netevent.h"
44 #include "util/net_help.h"
45 #include "services/cache/dns.h"
46 #include "services/cache/rrset.h"
47 #include "util/data/msgparse.h"
48 #include "util/data/msgreply.h"
49 #include "util/storage/slabhash.h"
50 #include "util/regional.h"
51 #include "iterator/iter_delegpt.h"
52 #include "sldns/sbuffer.h"
53
54 #undef _POSIX_C_SOURCE
55 #undef _XOPEN_SOURCE
56 #include <Python.h>
57
58 /* Store the reply_info and query_info pair in message cache (qstate->msg_cache) */
59 int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral)
60 {
61     if (!msgrep) 
62        return 0;
63
64     if (msgrep->authoritative) /*authoritative answer can't be stored in cache*/
65     {
66        PyErr_SetString(PyExc_ValueError, "Authoritative answer can't be stored");
67        return 0;
68     }
69
70     return dns_cache_store(qstate->env, qinfo, msgrep, is_referral, 
71         qstate->prefetch_leeway, 0, NULL, qstate->query_flags);
72 }
73
74 /*  Invalidate the message associated with query_info stored in message cache */
75 void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo)
76
77     hashvalue_type h;
78     struct lruhash_entry* e;
79     struct reply_info *r;
80     size_t i, j;
81
82     h = query_info_hash(qinfo, qstate->query_flags);
83     if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) 
84     {
85         r = (struct reply_info*)(e->data);
86         if (r) 
87         {
88            r->ttl = 0;
89            if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) {
90                    for(i=0; i< r->rrset_count; i++) 
91                    {
92                        struct packed_rrset_data* data = 
93                         (struct packed_rrset_data*) r->ref[i].key->entry.data;
94                        if(i>0 && r->ref[i].key == r->ref[i-1].key)
95                            continue;
96               
97                        data->ttl = r->ttl;
98                        for(j=0; j<data->count + data->rrsig_count; j++)
99                            data->rr_ttl[j] = r->ttl;
100                    }
101                    rrset_array_unlock(r->ref, r->rrset_count);
102            }
103         }
104         lock_rw_unlock(&e->lock);
105     } else {
106         log_info("invalidateQueryInCache: qinfo is not in cache");
107     }
108 }
109
110 /* Create response according to the ldns packet content */
111 int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
112 {
113     struct msg_parse* prs;
114     struct edns_data edns;
115     
116     /* parse message */
117     prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse));
118     if (!prs) {
119         log_err("storeResponse: out of memory on incoming message");
120         return 0;
121     }
122
123     memset(prs, 0, sizeof(*prs));
124     memset(&edns, 0, sizeof(edns));
125
126     sldns_buffer_set_position(pkt, 0);
127     if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
128         verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
129         return 0;
130     }
131     /* edns is not examined, but removed from message to help cache */
132     if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
133             LDNS_RCODE_NOERROR)
134         return 0;
135
136     /* remove CD-bit, we asked for in case we handle validation ourself */
137     prs->flags &= ~BIT_CD;
138
139     /* allocate response dns_msg in region */
140     qstate->return_msg = (struct dns_msg*)regional_alloc(qstate->region, sizeof(struct dns_msg));
141     if (!qstate->return_msg)
142        return 0;
143
144     memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
145     if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) {
146         log_err("storeResponse: malloc failure: allocating incoming dns_msg");
147         return 0;
148     }
149     
150     /* Make sure that the RA flag is set (since the presence of 
151      * this module means that recursion is available) */
152     /* qstate->return_msg->rep->flags |= BIT_RA; */
153
154     /* Clear the AA flag */
155     /* FIXME: does this action go here or in some other module? */
156     /*qstate->return_msg->rep->flags &= ~BIT_AA; */
157
158     /* make sure QR flag is on */
159     /*qstate->return_msg->rep->flags |= BIT_QR; */
160
161     if(verbosity >= VERB_ALGO)
162         log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);
163
164     return 1;
165 }
166
167
168 /* Convert reply->addr to string */
169 void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
170 {
171         int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
172         void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
173
174         if(af == AF_INET6)
175                 sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
176         dest[0] = 0;
177         if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
178            return;
179         dest[maxlen-1] = 0;
180 }
181
182 /* Convert target->addr to string */
183 void delegpt_addr_addr2str(struct delegpt_addr* target, char *dest, int maxlen)
184 {
185         int af = (int)((struct sockaddr_in*) &(target->addr))->sin_family;
186         void* sinaddr = &((struct sockaddr_in*) &(target->addr))->sin_addr;
187
188         if(af == AF_INET6)
189                 sinaddr = &((struct sockaddr_in6*)&(target->addr))->sin6_addr;
190         dest[0] = 0;
191         if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
192            return;
193         dest[maxlen-1] = 0;
194 }