xref: /netbsd-src/external/bsd/unbound/dist/pythonmod/pythonmod_utils.c (revision 91f7d55fb697b5e0475da4718fa34c3a3ebeac85)
13b6c3722Schristos /*
23b6c3722Schristos  * pythonmod_utils.c: utilities used by wrapper
33b6c3722Schristos  *
43b6c3722Schristos  * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
53b6c3722Schristos  *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
63b6c3722Schristos  *
73b6c3722Schristos  * This software is open source.
83b6c3722Schristos  *
93b6c3722Schristos  * Redistribution and use in source and binary forms, with or without
103b6c3722Schristos  * modification, are permitted provided that the following conditions
113b6c3722Schristos  * are met:
123b6c3722Schristos  *
133b6c3722Schristos  *    * Redistributions of source code must retain the above copyright notice,
143b6c3722Schristos  *      this list of conditions and the following disclaimer.
153b6c3722Schristos  *
163b6c3722Schristos  *    * Redistributions in binary form must reproduce the above copyright notice,
173b6c3722Schristos  *      this list of conditions and the following disclaimer in the documentation
183b6c3722Schristos  *      and/or other materials provided with the distribution.
193b6c3722Schristos  *
203b6c3722Schristos  *    * Neither the name of the organization nor the names of its
213b6c3722Schristos  *      contributors may be used to endorse or promote products derived from this
223b6c3722Schristos  *      software without specific prior written permission.
233b6c3722Schristos  *
243b6c3722Schristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
253b6c3722Schristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
263b6c3722Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
273b6c3722Schristos  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
283b6c3722Schristos  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
293b6c3722Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
303b6c3722Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
313b6c3722Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
323b6c3722Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
333b6c3722Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
343b6c3722Schristos  * POSSIBILITY OF SUCH DAMAGE.
353b6c3722Schristos  */
363b6c3722Schristos /**
373b6c3722Schristos  * \file
383b6c3722Schristos  * Utility functions for the python module that perform stores and loads and
393b6c3722Schristos  * conversions.
403b6c3722Schristos  */
413b6c3722Schristos #include "config.h"
42d0eba39bSchristos #include "pythonmod/pythonmod_utils.h"
433b6c3722Schristos #include "util/module.h"
443b6c3722Schristos #include "util/netevent.h"
453b6c3722Schristos #include "util/net_help.h"
463b6c3722Schristos #include "services/cache/dns.h"
473b6c3722Schristos #include "services/cache/rrset.h"
483b6c3722Schristos #include "util/data/msgparse.h"
493b6c3722Schristos #include "util/data/msgreply.h"
503b6c3722Schristos #include "util/storage/slabhash.h"
513b6c3722Schristos #include "util/regional.h"
523b6c3722Schristos #include "iterator/iter_delegpt.h"
533b6c3722Schristos #include "sldns/sbuffer.h"
543b6c3722Schristos 
553b6c3722Schristos #undef _POSIX_C_SOURCE
563b6c3722Schristos #undef _XOPEN_SOURCE
573b6c3722Schristos #include <Python.h>
583b6c3722Schristos 
597a540f2bSchristos /* Store the reply_info and query_info pair in message cache
607a540f2bSchristos  * (qstate->msg_cache) */
storeQueryInCache(struct module_qstate * qstate,struct query_info * qinfo,struct reply_info * msgrep,int is_referral)617a540f2bSchristos int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo,
627a540f2bSchristos 	struct reply_info* msgrep, int is_referral)
633b6c3722Schristos {
643b6c3722Schristos 	if (!msgrep)
653b6c3722Schristos 		return 0;
663b6c3722Schristos 
677a540f2bSchristos 	/* authoritative answer can't be stored in cache */
687a540f2bSchristos 	if (msgrep->authoritative) {
697a540f2bSchristos 		PyErr_SetString(PyExc_ValueError,
707a540f2bSchristos 			"Authoritative answer can't be stored");
713b6c3722Schristos 		return 0;
723b6c3722Schristos 	}
733b6c3722Schristos 
743b6c3722Schristos 	return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
757a540f2bSchristos 		qstate->prefetch_leeway, 0, NULL, qstate->query_flags,
767a540f2bSchristos 		qstate->qstarttime);
773b6c3722Schristos }
783b6c3722Schristos 
793b6c3722Schristos /* Invalidate the message associated with query_info stored in message cache */
invalidateQueryInCache(struct module_qstate * qstate,struct query_info * qinfo)807a540f2bSchristos void invalidateQueryInCache(struct module_qstate* qstate,
817a540f2bSchristos 	struct query_info* qinfo)
823b6c3722Schristos {
830cd9f4ecSchristos 	hashvalue_type h;
843b6c3722Schristos 	struct lruhash_entry* e;
853b6c3722Schristos 	struct reply_info *r;
863b6c3722Schristos 	size_t i, j;
873b6c3722Schristos 
883b6c3722Schristos 	h = query_info_hash(qinfo, qstate->query_flags);
897a540f2bSchristos 	if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) {
903b6c3722Schristos 		r = (struct reply_info*)(e->data);
917a540f2bSchristos 		if (r) {
923b6c3722Schristos 			r->ttl = 0;
933b6c3722Schristos 			if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) {
947a540f2bSchristos 				for(i=0; i< r->rrset_count; i++) {
953b6c3722Schristos 					struct packed_rrset_data* data =
963b6c3722Schristos 						(struct packed_rrset_data*) r->ref[i].key->entry.data;
973b6c3722Schristos 					if(i>0 && r->ref[i].key == r->ref[i-1].key)
983b6c3722Schristos 						continue;
993b6c3722Schristos 
1003b6c3722Schristos 					data->ttl = r->ttl;
1013b6c3722Schristos 					for(j=0; j<data->count + data->rrsig_count; j++)
1023b6c3722Schristos 						data->rr_ttl[j] = r->ttl;
1033b6c3722Schristos 				}
1043b6c3722Schristos 				rrset_array_unlock(r->ref, r->rrset_count);
1053b6c3722Schristos 			}
1063b6c3722Schristos 		}
1073b6c3722Schristos 		lock_rw_unlock(&e->lock);
1083b6c3722Schristos 	} else {
1093b6c3722Schristos 		log_info("invalidateQueryInCache: qinfo is not in cache");
1103b6c3722Schristos 	}
1113b6c3722Schristos }
1123b6c3722Schristos 
1133b6c3722Schristos /* Create response according to the ldns packet content */
createResponse(struct module_qstate * qstate,sldns_buffer * pkt)1143b6c3722Schristos int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
1153b6c3722Schristos {
1163b6c3722Schristos 	struct msg_parse* prs;
1173b6c3722Schristos 	struct edns_data edns;
1183b6c3722Schristos 
1193b6c3722Schristos 	/* parse message */
1207a540f2bSchristos 	prs = (struct msg_parse*) regional_alloc(qstate->env->scratch,
1217a540f2bSchristos 		sizeof(struct msg_parse));
1223b6c3722Schristos 	if(!prs) {
1237a540f2bSchristos 		log_err("createResponse: out of memory on incoming message");
1243b6c3722Schristos 		return 0;
1253b6c3722Schristos 	}
1263b6c3722Schristos 
1273b6c3722Schristos 	memset(prs, 0, sizeof(*prs));
1283b6c3722Schristos 	memset(&edns, 0, sizeof(edns));
1293b6c3722Schristos 
1303b6c3722Schristos 	sldns_buffer_set_position(pkt, 0);
1313b6c3722Schristos 	if(parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
1327a540f2bSchristos 		verbose(VERB_ALGO, "createResponse: parse error on reply packet");
1333b6c3722Schristos 		return 0;
1343b6c3722Schristos 	}
1353b6c3722Schristos 	/* edns is not examined, but removed from message to help cache */
1367a540f2bSchristos 	if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) !=
1373b6c3722Schristos 		LDNS_RCODE_NOERROR)
1383b6c3722Schristos 		return 0;
1393b6c3722Schristos 
1403b6c3722Schristos 	/* remove CD-bit, we asked for in case we handle validation ourself */
1413b6c3722Schristos 	prs->flags &= ~BIT_CD;
1423b6c3722Schristos 
1433b6c3722Schristos 	/* allocate response dns_msg in region */
1447a540f2bSchristos 	qstate->return_msg = (struct dns_msg*) regional_alloc(qstate->region,
1457a540f2bSchristos 		sizeof(struct dns_msg));
1463b6c3722Schristos 	if(!qstate->return_msg)
1473b6c3722Schristos 		return 0;
1483b6c3722Schristos 
1493b6c3722Schristos 	memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
1507a540f2bSchristos 	if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo,
1517a540f2bSchristos 		&(qstate->return_msg)->rep, qstate->region)) {
1527a540f2bSchristos 		log_err("createResponse: malloc failure: allocating incoming dns_msg");
1533b6c3722Schristos 		return 0;
1543b6c3722Schristos 	}
1553b6c3722Schristos 
1563b6c3722Schristos 	/* Make sure that the RA flag is set (since the presence of
1573b6c3722Schristos 	* this module means that recursion is available) */
1583b6c3722Schristos 	/* qstate->return_msg->rep->flags |= BIT_RA; */
1593b6c3722Schristos 
1603b6c3722Schristos 	/* Clear the AA flag */
1613b6c3722Schristos 	/* FIXME: does this action go here or in some other module? */
1623b6c3722Schristos 	/*qstate->return_msg->rep->flags &= ~BIT_AA; */
1633b6c3722Schristos 
1643b6c3722Schristos 	/* make sure QR flag is on */
1653b6c3722Schristos 	/*qstate->return_msg->rep->flags |= BIT_QR; */
1663b6c3722Schristos 
1673b6c3722Schristos 	if(verbosity >= VERB_ALGO)
1687a540f2bSchristos 		log_dns_msg("createResponse: packet:", &qstate->return_msg->qinfo,
1697a540f2bSchristos 			qstate->return_msg->rep);
1703b6c3722Schristos 
1713b6c3722Schristos 	return 1;
1723b6c3722Schristos }
1733b6c3722Schristos 
1743b6c3722Schristos 
175*91f7d55fSchristos /* Convert reply->client_addr to string */
reply_addr2str(struct comm_reply * reply,char * dest,int maxlen)1763b6c3722Schristos void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
1773b6c3722Schristos {
178*91f7d55fSchristos 	int af = (int)((struct sockaddr_in*) &(reply->client_addr))->sin_family;
179*91f7d55fSchristos 	void* sinaddr = &((struct sockaddr_in*) &(reply->client_addr))->sin_addr;
1803b6c3722Schristos 
1813b6c3722Schristos 	if(af == AF_INET6)
182*91f7d55fSchristos 		sinaddr = &((struct sockaddr_in6*)&(reply->client_addr))->sin6_addr;
1833b6c3722Schristos 	dest[0] = 0;
1843b6c3722Schristos 	if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
1853b6c3722Schristos 		return;
1863b6c3722Schristos 	dest[maxlen-1] = 0;
1873b6c3722Schristos }
1883b6c3722Schristos 
1893b6c3722Schristos /* Convert target->addr to string */
delegpt_addr_addr2str(struct delegpt_addr * target,char * dest,int maxlen)1903b6c3722Schristos void delegpt_addr_addr2str(struct delegpt_addr* target, char *dest, int maxlen)
1913b6c3722Schristos {
1923b6c3722Schristos 	int af = (int)((struct sockaddr_in*) &(target->addr))->sin_family;
1933b6c3722Schristos 	void* sinaddr = &((struct sockaddr_in*) &(target->addr))->sin_addr;
1943b6c3722Schristos 
1953b6c3722Schristos 	if(af == AF_INET6)
1963b6c3722Schristos 		sinaddr = &((struct sockaddr_in6*)&(target->addr))->sin6_addr;
1973b6c3722Schristos 	dest[0] = 0;
1983b6c3722Schristos 	if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
1993b6c3722Schristos 		return;
2003b6c3722Schristos 	dest[maxlen-1] = 0;
2013b6c3722Schristos }
202