xref: /freebsd/contrib/unbound/pythonmod/interface.i (revision be771a7b7f4580a30d99e41a5bb1b93a385a119d)
1*be771a7bSCy Schubert /*
2*be771a7bSCy Schubert  * interface.i: unbound python module
3*be771a7bSCy Schubert  */
4*be771a7bSCy Schubert %begin %{
5*be771a7bSCy Schubert /* store state of warning output, restored at later pop */
6*be771a7bSCy Schubert #pragma GCC diagnostic push
7*be771a7bSCy Schubert /* ignore warnings for pragma below, where for older GCC it can produce a
8*be771a7bSCy Schubert    warning if the cast-function-type warning is absent. */
9*be771a7bSCy Schubert #pragma GCC diagnostic ignored "-Wpragmas"
10*be771a7bSCy Schubert /* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
11*be771a7bSCy Schubert #pragma GCC diagnostic ignored "-Wcast-function-type"
12*be771a7bSCy Schubert %}
13*be771a7bSCy Schubert %module unboundmodule
14*be771a7bSCy Schubert %{
15*be771a7bSCy Schubert /* restore state of warning output, remove the functioncast ignore */
16*be771a7bSCy Schubert #pragma GCC diagnostic pop
17*be771a7bSCy Schubert /**
18*be771a7bSCy Schubert  * \file
19*be771a7bSCy Schubert  * This is the interface between the unbound server and a python module
20*be771a7bSCy Schubert  * called to perform operations on queries.
21*be771a7bSCy Schubert  */
22*be771a7bSCy Schubert    #include <sys/types.h>
23*be771a7bSCy Schubert    #include <time.h>
24*be771a7bSCy Schubert    #ifdef HAVE_SYS_SOCKET_H
25*be771a7bSCy Schubert    #include <sys/socket.h>
26*be771a7bSCy Schubert    #endif
27*be771a7bSCy Schubert    #ifdef HAVE_NETINET_IN_H
28*be771a7bSCy Schubert    #include <netinet/in.h>
29*be771a7bSCy Schubert    #endif
30*be771a7bSCy Schubert    #ifdef HAVE_ARPA_INET_H
31*be771a7bSCy Schubert    #include <arpa/inet.h>
32*be771a7bSCy Schubert    #endif
33*be771a7bSCy Schubert    #ifdef HAVE_NETDB_H
34*be771a7bSCy Schubert    #include <netdb.h>
35*be771a7bSCy Schubert    #endif
36*be771a7bSCy Schubert    #ifdef HAVE_SYS_UN_H
37*be771a7bSCy Schubert    #include <sys/un.h>
38*be771a7bSCy Schubert    #endif
39*be771a7bSCy Schubert    #include <stdarg.h>
40*be771a7bSCy Schubert    #include "config.h"
41*be771a7bSCy Schubert    #include "util/log.h"
42*be771a7bSCy Schubert    #include "util/module.h"
43*be771a7bSCy Schubert    #include "util/netevent.h"
44*be771a7bSCy Schubert    #include "util/regional.h"
45*be771a7bSCy Schubert    #include "util/config_file.h"
46*be771a7bSCy Schubert    #include "util/data/msgreply.h"
47*be771a7bSCy Schubert    #include "util/data/packed_rrset.h"
48*be771a7bSCy Schubert    #include "util/data/dname.h"
49*be771a7bSCy Schubert    #include "util/storage/lruhash.h"
50*be771a7bSCy Schubert    #include "services/cache/dns.h"
51*be771a7bSCy Schubert    #include "services/mesh.h"
52*be771a7bSCy Schubert    #include "iterator/iter_delegpt.h"
53*be771a7bSCy Schubert    #include "iterator/iter_hints.h"
54*be771a7bSCy Schubert    #include "iterator/iter_utils.h"
55*be771a7bSCy Schubert    #include "sldns/wire2str.h"
56*be771a7bSCy Schubert    #include "sldns/str2wire.h"
57*be771a7bSCy Schubert    #include "sldns/pkthdr.h"
58*be771a7bSCy Schubert %}
59*be771a7bSCy Schubert 
60*be771a7bSCy Schubert %include "stdint.i"  /* uint_16_t can be known type now */
61*be771a7bSCy Schubert 
62*be771a7bSCy Schubert %inline %{
63*be771a7bSCy Schubert    /* converts [len][data][len][data][0] string to a List of labels (PyBytes) */
64*be771a7bSCy Schubert    PyObject* GetNameAsLabelList(const char* name, int len) {
65*be771a7bSCy Schubert      PyObject* list;
66*be771a7bSCy Schubert      int cnt=0, i;
67*be771a7bSCy Schubert 
68*be771a7bSCy Schubert      i = 0;
69*be771a7bSCy Schubert      while (i < len) {
70*be771a7bSCy Schubert         i += ((unsigned int)name[i]) + 1;
71*be771a7bSCy Schubert         cnt++;
72*be771a7bSCy Schubert      }
73*be771a7bSCy Schubert 
74*be771a7bSCy Schubert      list = PyList_New(cnt);
75*be771a7bSCy Schubert      i = 0; cnt = 0;
76*be771a7bSCy Schubert      while (i < len) {
77*be771a7bSCy Schubert         char buf[LDNS_MAX_LABELLEN+1];
78*be771a7bSCy Schubert         if(((unsigned int)name[i])+1 <= (unsigned int)sizeof(buf) &&
79*be771a7bSCy Schubert                 i+(int)((unsigned int)name[i]) < len) {
80*be771a7bSCy Schubert                 memmove(buf, name + i + 1, (unsigned int)name[i]);
81*be771a7bSCy Schubert                 buf[(unsigned int)name[i]] = 0;
82*be771a7bSCy Schubert                 PyList_SetItem(list, cnt, PyString_FromString(buf));
83*be771a7bSCy Schubert         }
84*be771a7bSCy Schubert         i += ((unsigned int)name[i]) + 1;
85*be771a7bSCy Schubert         cnt++;
86*be771a7bSCy Schubert      }
87*be771a7bSCy Schubert      return list;
88*be771a7bSCy Schubert    }
89*be771a7bSCy Schubert 
90*be771a7bSCy Schubert    /* converts an array of strings (char**) to a List of strings */
91*be771a7bSCy Schubert    PyObject* CharArrayAsStringList(char** array, int len) {
92*be771a7bSCy Schubert      PyObject* list;
93*be771a7bSCy Schubert      int i;
94*be771a7bSCy Schubert 
95*be771a7bSCy Schubert      if(!array||len==0) return PyList_New(0);
96*be771a7bSCy Schubert 
97*be771a7bSCy Schubert      list = PyList_New(len);
98*be771a7bSCy Schubert      for (i=0; i < len; i++) {
99*be771a7bSCy Schubert             PyList_SET_ITEM(list, i, PyString_FromString(array[i]));
100*be771a7bSCy Schubert      }
101*be771a7bSCy Schubert      return list;
102*be771a7bSCy Schubert    }
103*be771a7bSCy Schubert %}
104*be771a7bSCy Schubert 
105*be771a7bSCy Schubert /* ************************************************************************************ *
106*be771a7bSCy Schubert    Structure query_info
107*be771a7bSCy Schubert  * ************************************************************************************ */
108*be771a7bSCy Schubert /* Query info */
109*be771a7bSCy Schubert %ignore query_info::qname;
110*be771a7bSCy Schubert %ignore query_info::qname_len;
111*be771a7bSCy Schubert 
112*be771a7bSCy Schubert 
113*be771a7bSCy Schubert struct query_info {
114*be771a7bSCy Schubert    %immutable;
115*be771a7bSCy Schubert    char* qname;
116*be771a7bSCy Schubert    size_t qname_len;
117*be771a7bSCy Schubert    uint16_t qtype;
118*be771a7bSCy Schubert    uint16_t qclass;
119*be771a7bSCy Schubert    %mutable;
120*be771a7bSCy Schubert };
121*be771a7bSCy Schubert 
122*be771a7bSCy Schubert %inline %{
123*be771a7bSCy Schubert    enum enum_rr_class  {
124*be771a7bSCy Schubert       RR_CLASS_IN = 1,
125*be771a7bSCy Schubert       RR_CLASS_CH = 3,
126*be771a7bSCy Schubert       RR_CLASS_HS = 4,
127*be771a7bSCy Schubert       RR_CLASS_NONE = 254,
128*be771a7bSCy Schubert       RR_CLASS_ANY = 255,
129*be771a7bSCy Schubert    };
130*be771a7bSCy Schubert 
131*be771a7bSCy Schubert    enum enum_rr_type {
132*be771a7bSCy Schubert       RR_TYPE_A = 1,
133*be771a7bSCy Schubert       RR_TYPE_NS = 2,
134*be771a7bSCy Schubert       RR_TYPE_MD = 3,
135*be771a7bSCy Schubert       RR_TYPE_MF = 4,
136*be771a7bSCy Schubert       RR_TYPE_CNAME = 5,
137*be771a7bSCy Schubert       RR_TYPE_SOA = 6,
138*be771a7bSCy Schubert       RR_TYPE_MB = 7,
139*be771a7bSCy Schubert       RR_TYPE_MG = 8,
140*be771a7bSCy Schubert       RR_TYPE_MR = 9,
141*be771a7bSCy Schubert       RR_TYPE_NULL = 10,
142*be771a7bSCy Schubert       RR_TYPE_WKS = 11,
143*be771a7bSCy Schubert       RR_TYPE_PTR = 12,
144*be771a7bSCy Schubert       RR_TYPE_HINFO = 13,
145*be771a7bSCy Schubert       RR_TYPE_MINFO = 14,
146*be771a7bSCy Schubert       RR_TYPE_MX = 15,
147*be771a7bSCy Schubert       RR_TYPE_TXT = 16,
148*be771a7bSCy Schubert       RR_TYPE_RP = 17,
149*be771a7bSCy Schubert       RR_TYPE_AFSDB = 18,
150*be771a7bSCy Schubert       RR_TYPE_X25 = 19,
151*be771a7bSCy Schubert       RR_TYPE_ISDN = 20,
152*be771a7bSCy Schubert       RR_TYPE_RT = 21,
153*be771a7bSCy Schubert       RR_TYPE_NSAP = 22,
154*be771a7bSCy Schubert       RR_TYPE_NSAP_PTR = 23,
155*be771a7bSCy Schubert       RR_TYPE_SIG = 24,
156*be771a7bSCy Schubert       RR_TYPE_KEY = 25,
157*be771a7bSCy Schubert       RR_TYPE_PX = 26,
158*be771a7bSCy Schubert       RR_TYPE_GPOS = 27,
159*be771a7bSCy Schubert       RR_TYPE_AAAA = 28,
160*be771a7bSCy Schubert       RR_TYPE_LOC = 29,
161*be771a7bSCy Schubert       RR_TYPE_NXT = 30,
162*be771a7bSCy Schubert       RR_TYPE_EID = 31,
163*be771a7bSCy Schubert       RR_TYPE_NIMLOC = 32,
164*be771a7bSCy Schubert       RR_TYPE_SRV = 33,
165*be771a7bSCy Schubert       RR_TYPE_ATMA = 34,
166*be771a7bSCy Schubert       RR_TYPE_NAPTR = 35,
167*be771a7bSCy Schubert       RR_TYPE_KX = 36,
168*be771a7bSCy Schubert       RR_TYPE_CERT = 37,
169*be771a7bSCy Schubert       RR_TYPE_A6 = 38,
170*be771a7bSCy Schubert       RR_TYPE_DNAME = 39,
171*be771a7bSCy Schubert       RR_TYPE_SINK = 40,
172*be771a7bSCy Schubert       RR_TYPE_OPT = 41,
173*be771a7bSCy Schubert       RR_TYPE_APL = 42,
174*be771a7bSCy Schubert       RR_TYPE_DS = 43,
175*be771a7bSCy Schubert       RR_TYPE_SSHFP = 44,
176*be771a7bSCy Schubert       RR_TYPE_IPSECKEY = 45,
177*be771a7bSCy Schubert       RR_TYPE_RRSIG = 46,
178*be771a7bSCy Schubert       RR_TYPE_NSEC = 47,
179*be771a7bSCy Schubert       RR_TYPE_DNSKEY = 48,
180*be771a7bSCy Schubert       RR_TYPE_DHCID = 49,
181*be771a7bSCy Schubert       RR_TYPE_NSEC3 = 50,
182*be771a7bSCy Schubert       RR_TYPE_NSEC3PARAMS = 51,
183*be771a7bSCy Schubert       RR_TYPE_UINFO = 100,
184*be771a7bSCy Schubert       RR_TYPE_UID = 101,
185*be771a7bSCy Schubert       RR_TYPE_GID = 102,
186*be771a7bSCy Schubert       RR_TYPE_UNSPEC = 103,
187*be771a7bSCy Schubert       RR_TYPE_TSIG = 250,
188*be771a7bSCy Schubert       RR_TYPE_IXFR = 251,
189*be771a7bSCy Schubert       RR_TYPE_AXFR = 252,
190*be771a7bSCy Schubert       RR_TYPE_MAILB = 253,
191*be771a7bSCy Schubert       RR_TYPE_MAILA = 254,
192*be771a7bSCy Schubert       RR_TYPE_ANY = 255,
193*be771a7bSCy Schubert       RR_TYPE_DLV = 32769,
194*be771a7bSCy Schubert    };
195*be771a7bSCy Schubert 
196*be771a7bSCy Schubert    PyObject* _get_qname(struct query_info* q) {
197*be771a7bSCy Schubert       return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
198*be771a7bSCy Schubert    }
199*be771a7bSCy Schubert 
200*be771a7bSCy Schubert    PyObject* _get_qname_components(struct query_info* q) {
201*be771a7bSCy Schubert       return GetNameAsLabelList((const char*)q->qname, q->qname_len);
202*be771a7bSCy Schubert    }
203*be771a7bSCy Schubert %}
204*be771a7bSCy Schubert 
205*be771a7bSCy Schubert %inline %{
206*be771a7bSCy Schubert    PyObject* dnameAsStr(PyObject* dname) {
207*be771a7bSCy Schubert        char buf[LDNS_MAX_DOMAINLEN];
208*be771a7bSCy Schubert        buf[0] = '\0';
209*be771a7bSCy Schubert        dname_str((uint8_t*)PyBytes_AsString(dname), buf);
210*be771a7bSCy Schubert        return PyString_FromString(buf);
211*be771a7bSCy Schubert    }
212*be771a7bSCy Schubert %}
213*be771a7bSCy Schubert 
214*be771a7bSCy Schubert %extend query_info {
215*be771a7bSCy Schubert    %pythoncode %{
216*be771a7bSCy Schubert         def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
217*be771a7bSCy Schubert         qtype_str = property(_get_qtype_str)
218*be771a7bSCy Schubert 
219*be771a7bSCy Schubert         def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
220*be771a7bSCy Schubert         qclass_str = property(_get_qclass_str)
221*be771a7bSCy Schubert 
222*be771a7bSCy Schubert         qname = property(_unboundmodule._get_qname)
223*be771a7bSCy Schubert 
224*be771a7bSCy Schubert         qname_list = property(_unboundmodule._get_qname_components)
225*be771a7bSCy Schubert 
226*be771a7bSCy Schubert         def _get_qname_str(self): return dnameAsStr(self.qname)
227*be771a7bSCy Schubert         qname_str = property(_get_qname_str)
228*be771a7bSCy Schubert    %}
229*be771a7bSCy Schubert }
230*be771a7bSCy Schubert 
231*be771a7bSCy Schubert /* ************************************************************************************ *
232*be771a7bSCy Schubert    Structure packed_rrset_key
233*be771a7bSCy Schubert  * ************************************************************************************ */
234*be771a7bSCy Schubert %ignore packed_rrset_key::dname;
235*be771a7bSCy Schubert %ignore packed_rrset_key::dname_len;
236*be771a7bSCy Schubert 
237*be771a7bSCy Schubert /* RRsets */
238*be771a7bSCy Schubert struct packed_rrset_key {
239*be771a7bSCy Schubert    %immutable;
240*be771a7bSCy Schubert    char*    dname;
241*be771a7bSCy Schubert    size_t   dname_len;
242*be771a7bSCy Schubert    uint32_t flags;
243*be771a7bSCy Schubert    uint16_t type;  /* rrset type in network format */
244*be771a7bSCy Schubert    uint16_t rrset_class;  /* rrset class in network format */
245*be771a7bSCy Schubert    %mutable;
246*be771a7bSCy Schubert };
247*be771a7bSCy Schubert 
248*be771a7bSCy Schubert /**
249*be771a7bSCy Schubert  * This subroutine converts values between the host and network byte order.
250*be771a7bSCy Schubert  * Specifically, ntohs() converts 16-bit quantities from network byte order to
251*be771a7bSCy Schubert  * host byte order.
252*be771a7bSCy Schubert  */
253*be771a7bSCy Schubert uint16_t ntohs(uint16_t netshort);
254*be771a7bSCy Schubert 
255*be771a7bSCy Schubert %inline %{
256*be771a7bSCy Schubert    PyObject* _get_dname(struct packed_rrset_key* k) {
257*be771a7bSCy Schubert       return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
258*be771a7bSCy Schubert    }
259*be771a7bSCy Schubert    PyObject* _get_dname_components(struct packed_rrset_key* k) {
260*be771a7bSCy Schubert       return GetNameAsLabelList((char*)k->dname, k->dname_len);
261*be771a7bSCy Schubert    }
262*be771a7bSCy Schubert %}
263*be771a7bSCy Schubert 
264*be771a7bSCy Schubert %extend packed_rrset_key {
265*be771a7bSCy Schubert    %pythoncode %{
266*be771a7bSCy Schubert         def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
267*be771a7bSCy Schubert         type_str = property(_get_type_str)
268*be771a7bSCy Schubert 
269*be771a7bSCy Schubert         def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
270*be771a7bSCy Schubert         rrset_class_str = property(_get_class_str)
271*be771a7bSCy Schubert 
272*be771a7bSCy Schubert         dname = property(_unboundmodule._get_dname)
273*be771a7bSCy Schubert 
274*be771a7bSCy Schubert         dname_list = property(_unboundmodule._get_dname_components)
275*be771a7bSCy Schubert 
276*be771a7bSCy Schubert         def _get_dname_str(self): return dnameAsStr(self.dname)
277*be771a7bSCy Schubert         dname_str = property(_get_dname_str)
278*be771a7bSCy Schubert    %}
279*be771a7bSCy Schubert }
280*be771a7bSCy Schubert 
281*be771a7bSCy Schubert #if defined(SWIGWORDSIZE64)
282*be771a7bSCy Schubert typedef long int                rrset_id_type;
283*be771a7bSCy Schubert #else
284*be771a7bSCy Schubert typedef long long int           rrset_id_type;
285*be771a7bSCy Schubert #endif
286*be771a7bSCy Schubert 
287*be771a7bSCy Schubert struct ub_packed_rrset_key {
288*be771a7bSCy Schubert    struct lruhash_entry entry;
289*be771a7bSCy Schubert    rrset_id_type id;
290*be771a7bSCy Schubert    struct packed_rrset_key rk;
291*be771a7bSCy Schubert };
292*be771a7bSCy Schubert 
293*be771a7bSCy Schubert struct lruhash_entry {
294*be771a7bSCy Schubert   lock_rw_type lock;
295*be771a7bSCy Schubert   struct lruhash_entry* overflow_next;
296*be771a7bSCy Schubert   struct lruhash_entry* lru_next;
297*be771a7bSCy Schubert   struct lruhash_entry* lru_prev;
298*be771a7bSCy Schubert   hashvalue_type hash;
299*be771a7bSCy Schubert   void* key;
300*be771a7bSCy Schubert   struct packed_rrset_data* data;
301*be771a7bSCy Schubert };
302*be771a7bSCy Schubert 
303*be771a7bSCy Schubert %ignore packed_rrset_data::rr_len;
304*be771a7bSCy Schubert %ignore packed_rrset_data::rr_ttl;
305*be771a7bSCy Schubert %ignore packed_rrset_data::rr_data;
306*be771a7bSCy Schubert 
307*be771a7bSCy Schubert struct packed_rrset_data {
308*be771a7bSCy Schubert   /* TTL (in seconds like time()) */
309*be771a7bSCy Schubert   uint32_t ttl;
310*be771a7bSCy Schubert 
311*be771a7bSCy Schubert   /* number of rrs */
312*be771a7bSCy Schubert   size_t count;
313*be771a7bSCy Schubert   /* number of rrsigs */
314*be771a7bSCy Schubert   size_t rrsig_count;
315*be771a7bSCy Schubert 
316*be771a7bSCy Schubert   enum rrset_trust trust;
317*be771a7bSCy Schubert   enum sec_status security;
318*be771a7bSCy Schubert 
319*be771a7bSCy Schubert   /* length of every rr's rdata */
320*be771a7bSCy Schubert   size_t* rr_len;
321*be771a7bSCy Schubert   /* ttl of every rr */
322*be771a7bSCy Schubert   uint32_t *rr_ttl;
323*be771a7bSCy Schubert   /* array of pointers to every rr's rdata. The rr_data[i] rdata is stored in
324*be771a7bSCy Schubert    * uncompressed wireformat. */
325*be771a7bSCy Schubert   uint8_t** rr_data;
326*be771a7bSCy Schubert };
327*be771a7bSCy Schubert 
328*be771a7bSCy Schubert %pythoncode %{
329*be771a7bSCy Schubert     class RRSetData_RRLen:
330*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
331*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index)
332*be771a7bSCy Schubert         def __len__(self): return self.obj.count + self.obj.rrsig_count
333*be771a7bSCy Schubert     class RRSetData_RRTTL:
334*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
335*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index)
336*be771a7bSCy Schubert         def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value)
337*be771a7bSCy Schubert         def __len__(self): return self.obj.count + self.obj.rrsig_count
338*be771a7bSCy Schubert     class RRSetData_RRData:
339*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
340*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index)
341*be771a7bSCy Schubert         def __len__(self): return self.obj.count + self.obj.rrsig_count
342*be771a7bSCy Schubert %}
343*be771a7bSCy Schubert 
344*be771a7bSCy Schubert %inline %{
345*be771a7bSCy Schubert    PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
346*be771a7bSCy Schubert      if ((d != NULL) && (idx >= 0) &&
347*be771a7bSCy Schubert              ((size_t)idx < (d->count+d->rrsig_count)))
348*be771a7bSCy Schubert         return PyInt_FromLong(d->rr_len[idx]);
349*be771a7bSCy Schubert      return Py_None;
350*be771a7bSCy Schubert    }
351*be771a7bSCy Schubert    void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
352*be771a7bSCy Schubert    {
353*be771a7bSCy Schubert      if ((d != NULL) && (idx >= 0) &&
354*be771a7bSCy Schubert              ((size_t)idx < (d->count+d->rrsig_count)))
355*be771a7bSCy Schubert         d->rr_ttl[idx] = ttl;
356*be771a7bSCy Schubert    }
357*be771a7bSCy Schubert    PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
358*be771a7bSCy Schubert      if ((d != NULL) && (idx >= 0) &&
359*be771a7bSCy Schubert              ((size_t)idx < (d->count+d->rrsig_count)))
360*be771a7bSCy Schubert         return PyInt_FromLong(d->rr_ttl[idx]);
361*be771a7bSCy Schubert      return Py_None;
362*be771a7bSCy Schubert    }
363*be771a7bSCy Schubert    PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
364*be771a7bSCy Schubert      if ((d != NULL) && (idx >= 0) &&
365*be771a7bSCy Schubert              ((size_t)idx < (d->count+d->rrsig_count)))
366*be771a7bSCy Schubert         return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
367*be771a7bSCy Schubert                 d->rr_len[idx]);
368*be771a7bSCy Schubert      return Py_None;
369*be771a7bSCy Schubert    }
370*be771a7bSCy Schubert %}
371*be771a7bSCy Schubert 
372*be771a7bSCy Schubert %extend packed_rrset_data {
373*be771a7bSCy Schubert    %pythoncode %{
374*be771a7bSCy Schubert         def _get_data_rr_len(self): return RRSetData_RRLen(self)
375*be771a7bSCy Schubert         rr_len = property(_get_data_rr_len)
376*be771a7bSCy Schubert         def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
377*be771a7bSCy Schubert         rr_ttl = property(_get_data_rr_ttl)
378*be771a7bSCy Schubert         def _get_data_rr_data(self): return RRSetData_RRData(self)
379*be771a7bSCy Schubert         rr_data = property(_get_data_rr_data)
380*be771a7bSCy Schubert    %}
381*be771a7bSCy Schubert }
382*be771a7bSCy Schubert 
383*be771a7bSCy Schubert /* ************************************************************************************ *
384*be771a7bSCy Schubert    Structure reply_info
385*be771a7bSCy Schubert  * ************************************************************************************ */
386*be771a7bSCy Schubert /* Messages */
387*be771a7bSCy Schubert %ignore reply_info::rrsets;
388*be771a7bSCy Schubert %ignore reply_info::ref;
389*be771a7bSCy Schubert 
390*be771a7bSCy Schubert struct reply_info {
391*be771a7bSCy Schubert    uint16_t flags;
392*be771a7bSCy Schubert    uint16_t qdcount;
393*be771a7bSCy Schubert    uint32_t ttl;
394*be771a7bSCy Schubert    uint32_t prefetch_ttl;
395*be771a7bSCy Schubert 
396*be771a7bSCy Schubert    uint16_t authoritative;
397*be771a7bSCy Schubert    enum sec_status security;
398*be771a7bSCy Schubert 
399*be771a7bSCy Schubert    size_t an_numrrsets;
400*be771a7bSCy Schubert    size_t ns_numrrsets;
401*be771a7bSCy Schubert    size_t ar_numrrsets;
402*be771a7bSCy Schubert    size_t rrset_count;  /* an_numrrsets + ns_numrrsets + ar_numrrsets */
403*be771a7bSCy Schubert 
404*be771a7bSCy Schubert    struct ub_packed_rrset_key** rrsets;
405*be771a7bSCy Schubert    struct rrset_ref ref[1];  /* ? */
406*be771a7bSCy Schubert };
407*be771a7bSCy Schubert 
408*be771a7bSCy Schubert struct rrset_ref {
409*be771a7bSCy Schubert    struct ub_packed_rrset_key* key;
410*be771a7bSCy Schubert    rrset_id_type id;
411*be771a7bSCy Schubert };
412*be771a7bSCy Schubert 
413*be771a7bSCy Schubert struct dns_msg {
414*be771a7bSCy Schubert    struct query_info qinfo;
415*be771a7bSCy Schubert    struct reply_info *rep;
416*be771a7bSCy Schubert };
417*be771a7bSCy Schubert 
418*be771a7bSCy Schubert %pythoncode %{
419*be771a7bSCy Schubert     class ReplyInfo_RRSet:
420*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
421*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index)
422*be771a7bSCy Schubert         def __len__(self): return self.obj.rrset_count
423*be771a7bSCy Schubert 
424*be771a7bSCy Schubert     class ReplyInfo_Ref:
425*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
426*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index)
427*be771a7bSCy Schubert         def __len__(self): return self.obj.rrset_count
428*be771a7bSCy Schubert %}
429*be771a7bSCy Schubert 
430*be771a7bSCy Schubert %inline %{
431*be771a7bSCy Schubert    struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
432*be771a7bSCy Schubert      if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count))
433*be771a7bSCy Schubert         return r->rrsets[idx];
434*be771a7bSCy Schubert      return NULL;
435*be771a7bSCy Schubert    }
436*be771a7bSCy Schubert 
437*be771a7bSCy Schubert    struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
438*be771a7bSCy Schubert      if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
439*be771a7bSCy Schubert /* printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key); */
440*be771a7bSCy Schubert              return &(r->ref[idx]);
441*be771a7bSCy Schubert /*        return &(r->ref[idx]); */
442*be771a7bSCy Schubert      }
443*be771a7bSCy Schubert /* printf("_rrset_ref_get: NULL\n"); */
444*be771a7bSCy Schubert      return NULL;
445*be771a7bSCy Schubert    }
446*be771a7bSCy Schubert %}
447*be771a7bSCy Schubert 
448*be771a7bSCy Schubert %extend reply_info {
449*be771a7bSCy Schubert    %pythoncode %{
450*be771a7bSCy Schubert         def _rrset_ref_get(self): return ReplyInfo_Ref(self)
451*be771a7bSCy Schubert         ref = property(_rrset_ref_get)
452*be771a7bSCy Schubert 
453*be771a7bSCy Schubert         def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
454*be771a7bSCy Schubert         rrsets = property(_rrset_rrsets_get)
455*be771a7bSCy Schubert    %}
456*be771a7bSCy Schubert }
457*be771a7bSCy Schubert 
458*be771a7bSCy Schubert /* ************************************************************************************ *
459*be771a7bSCy Schubert    Structure sockaddr_storage
460*be771a7bSCy Schubert  * ************************************************************************************ */
461*be771a7bSCy Schubert 
462*be771a7bSCy Schubert struct sockaddr_storage {};
463*be771a7bSCy Schubert 
464*be771a7bSCy Schubert %inline %{
465*be771a7bSCy Schubert     static size_t _sockaddr_storage_len(const struct sockaddr_storage *ss) {
466*be771a7bSCy Schubert         if (ss == NULL) {
467*be771a7bSCy Schubert             return 0;
468*be771a7bSCy Schubert         }
469*be771a7bSCy Schubert 
470*be771a7bSCy Schubert         switch (ss->ss_family) {
471*be771a7bSCy Schubert         case AF_INET:  return sizeof(struct sockaddr_in);
472*be771a7bSCy Schubert         case AF_INET6: return sizeof(struct sockaddr_in6);
473*be771a7bSCy Schubert #ifdef HAVE_SYS_UN_H
474*be771a7bSCy Schubert         case AF_UNIX:  return sizeof(struct sockaddr_un);
475*be771a7bSCy Schubert #endif
476*be771a7bSCy Schubert         default:
477*be771a7bSCy Schubert             return 0;
478*be771a7bSCy Schubert         }
479*be771a7bSCy Schubert     }
480*be771a7bSCy Schubert 
481*be771a7bSCy Schubert     PyObject *_sockaddr_storage_family(const struct sockaddr_storage *ss) {
482*be771a7bSCy Schubert         if (ss == NULL) {
483*be771a7bSCy Schubert             return Py_None;
484*be771a7bSCy Schubert         }
485*be771a7bSCy Schubert 
486*be771a7bSCy Schubert         switch (ss->ss_family) {
487*be771a7bSCy Schubert         case AF_INET:  return PyUnicode_FromString("ip4");
488*be771a7bSCy Schubert         case AF_INET6: return PyUnicode_FromString("ip6");
489*be771a7bSCy Schubert         case AF_UNIX:  return PyUnicode_FromString("unix");
490*be771a7bSCy Schubert         default:
491*be771a7bSCy Schubert             return Py_None;
492*be771a7bSCy Schubert         }
493*be771a7bSCy Schubert     }
494*be771a7bSCy Schubert 
495*be771a7bSCy Schubert     PyObject *_sockaddr_storage_addr(const struct sockaddr_storage *ss) {
496*be771a7bSCy Schubert         const struct sockaddr *sa;
497*be771a7bSCy Schubert         size_t sa_len;
498*be771a7bSCy Schubert         char name[NI_MAXHOST] = {0};
499*be771a7bSCy Schubert 
500*be771a7bSCy Schubert         if (ss == NULL) {
501*be771a7bSCy Schubert             return Py_None;
502*be771a7bSCy Schubert         }
503*be771a7bSCy Schubert 
504*be771a7bSCy Schubert         sa = (struct sockaddr *)ss;
505*be771a7bSCy Schubert         sa_len = _sockaddr_storage_len(ss);
506*be771a7bSCy Schubert         if (sa_len == 0) {
507*be771a7bSCy Schubert             return Py_None;
508*be771a7bSCy Schubert         }
509*be771a7bSCy Schubert 
510*be771a7bSCy Schubert         if (getnameinfo(sa, sa_len, name, sizeof(name), NULL, 0, NI_NUMERICHOST) != 0) {
511*be771a7bSCy Schubert             return Py_None;
512*be771a7bSCy Schubert         }
513*be771a7bSCy Schubert 
514*be771a7bSCy Schubert         return PyUnicode_FromString(name);
515*be771a7bSCy Schubert     }
516*be771a7bSCy Schubert 
517*be771a7bSCy Schubert     PyObject *_sockaddr_storage_raw_addr(const struct sockaddr_storage *ss) {
518*be771a7bSCy Schubert         size_t sa_len;
519*be771a7bSCy Schubert 
520*be771a7bSCy Schubert         if (ss == NULL) {
521*be771a7bSCy Schubert             return Py_None;
522*be771a7bSCy Schubert         }
523*be771a7bSCy Schubert 
524*be771a7bSCy Schubert         sa_len = _sockaddr_storage_len(ss);
525*be771a7bSCy Schubert         if (sa_len == 0) {
526*be771a7bSCy Schubert             return Py_None;
527*be771a7bSCy Schubert         }
528*be771a7bSCy Schubert 
529*be771a7bSCy Schubert         if (ss->ss_family == AF_INET) {
530*be771a7bSCy Schubert             const struct sockaddr_in *sa = (struct sockaddr_in *)ss;
531*be771a7bSCy Schubert             const struct in_addr *raw = (struct in_addr *)&sa->sin_addr;
532*be771a7bSCy Schubert             return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
533*be771a7bSCy Schubert         }
534*be771a7bSCy Schubert 
535*be771a7bSCy Schubert         if (ss->ss_family == AF_INET6) {
536*be771a7bSCy Schubert             const struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss;
537*be771a7bSCy Schubert             const struct in6_addr *raw = (struct in6_addr *)&sa->sin6_addr;
538*be771a7bSCy Schubert             return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
539*be771a7bSCy Schubert         }
540*be771a7bSCy Schubert 
541*be771a7bSCy Schubert #ifdef HAVE_SYS_UN_H
542*be771a7bSCy Schubert         if (ss->ss_family == AF_UNIX) {
543*be771a7bSCy Schubert             const struct sockaddr_un *sa = (struct sockaddr_un *)ss;
544*be771a7bSCy Schubert             return PyBytes_FromString(sa->sun_path);
545*be771a7bSCy Schubert         }
546*be771a7bSCy Schubert #endif
547*be771a7bSCy Schubert 
548*be771a7bSCy Schubert         return Py_None;
549*be771a7bSCy Schubert     }
550*be771a7bSCy Schubert 
551*be771a7bSCy Schubert     PyObject *_sockaddr_storage_port(const struct sockaddr_storage *ss) {
552*be771a7bSCy Schubert         if (ss == NULL) {
553*be771a7bSCy Schubert             return Py_None;
554*be771a7bSCy Schubert         }
555*be771a7bSCy Schubert 
556*be771a7bSCy Schubert         if (ss->ss_family == AF_INET) {
557*be771a7bSCy Schubert             const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
558*be771a7bSCy Schubert             return PyInt_FromLong(ntohs(sa4->sin_port));
559*be771a7bSCy Schubert         }
560*be771a7bSCy Schubert 
561*be771a7bSCy Schubert         if (ss->ss_family == AF_INET6) {
562*be771a7bSCy Schubert             const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
563*be771a7bSCy Schubert             return PyInt_FromLong(ntohs(sa6->sin6_port));
564*be771a7bSCy Schubert         }
565*be771a7bSCy Schubert 
566*be771a7bSCy Schubert         return Py_None;
567*be771a7bSCy Schubert     }
568*be771a7bSCy Schubert 
569*be771a7bSCy Schubert     PyObject *_sockaddr_storage_flowinfo(const struct sockaddr_storage *ss) {
570*be771a7bSCy Schubert         const struct sockaddr_in6 *sa6;
571*be771a7bSCy Schubert 
572*be771a7bSCy Schubert         if (ss == NULL || ss->ss_family != AF_INET6) {
573*be771a7bSCy Schubert             return Py_None;
574*be771a7bSCy Schubert         }
575*be771a7bSCy Schubert 
576*be771a7bSCy Schubert         sa6 = (struct sockaddr_in6 *)ss;
577*be771a7bSCy Schubert         return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
578*be771a7bSCy Schubert     }
579*be771a7bSCy Schubert 
580*be771a7bSCy Schubert     PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
581*be771a7bSCy Schubert         const struct sockaddr_in6 *sa6;
582*be771a7bSCy Schubert 
583*be771a7bSCy Schubert         if (ss == NULL || ss->ss_family != AF_INET6) {
584*be771a7bSCy Schubert             return Py_None;
585*be771a7bSCy Schubert         }
586*be771a7bSCy Schubert 
587*be771a7bSCy Schubert         sa6 = (struct sockaddr_in6 *)ss;
588*be771a7bSCy Schubert         return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
589*be771a7bSCy Schubert     }
590*be771a7bSCy Schubert %}
591*be771a7bSCy Schubert 
592*be771a7bSCy Schubert %extend sockaddr_storage {
593*be771a7bSCy Schubert    %pythoncode %{
594*be771a7bSCy Schubert         def _family_get(self): return _sockaddr_storage_family(self)
595*be771a7bSCy Schubert         family = property(_family_get)
596*be771a7bSCy Schubert 
597*be771a7bSCy Schubert         def _addr_get(self): return _sockaddr_storage_addr(self)
598*be771a7bSCy Schubert         addr = property(_addr_get)
599*be771a7bSCy Schubert 
600*be771a7bSCy Schubert         def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
601*be771a7bSCy Schubert         raw_addr = property(_raw_addr_get)
602*be771a7bSCy Schubert 
603*be771a7bSCy Schubert         def _port_get(self): return _sockaddr_storage_port(self)
604*be771a7bSCy Schubert         port = property(_port_get)
605*be771a7bSCy Schubert 
606*be771a7bSCy Schubert         def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
607*be771a7bSCy Schubert         flowinfo = property(_flowinfo_get)
608*be771a7bSCy Schubert 
609*be771a7bSCy Schubert         def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
610*be771a7bSCy Schubert         scope_id = property(_scope_id_get)
611*be771a7bSCy Schubert    %}
612*be771a7bSCy Schubert }
613*be771a7bSCy Schubert 
614*be771a7bSCy Schubert /* ************************************************************************************ *
615*be771a7bSCy Schubert    Structure mesh_state
616*be771a7bSCy Schubert  * ************************************************************************************ */
617*be771a7bSCy Schubert struct mesh_state {
618*be771a7bSCy Schubert    struct mesh_reply* reply_list;
619*be771a7bSCy Schubert };
620*be771a7bSCy Schubert 
621*be771a7bSCy Schubert struct mesh_reply {
622*be771a7bSCy Schubert    struct mesh_reply* next;
623*be771a7bSCy Schubert    struct comm_reply query_reply;
624*be771a7bSCy Schubert };
625*be771a7bSCy Schubert 
626*be771a7bSCy Schubert %rename(_addr) comm_reply::client_addr;
627*be771a7bSCy Schubert struct comm_reply {
628*be771a7bSCy Schubert    struct sockaddr_storage client_addr;
629*be771a7bSCy Schubert };
630*be771a7bSCy Schubert 
631*be771a7bSCy Schubert %extend comm_reply {
632*be771a7bSCy Schubert    %pythoncode %{
633*be771a7bSCy Schubert         def _addr_get(self): return _sockaddr_storage_addr(self._addr)
634*be771a7bSCy Schubert         addr = property(_addr_get)
635*be771a7bSCy Schubert 
636*be771a7bSCy Schubert         def _port_get(self): return _sockaddr_storage_port(self._addr)
637*be771a7bSCy Schubert         port = property(_port_get)
638*be771a7bSCy Schubert 
639*be771a7bSCy Schubert         def _family_get(self): return _sockaddr_storage_family(self._addr)
640*be771a7bSCy Schubert         family = property(_family_get)
641*be771a7bSCy Schubert    %}
642*be771a7bSCy Schubert }
643*be771a7bSCy Schubert 
644*be771a7bSCy Schubert /* ************************************************************************************ *
645*be771a7bSCy Schubert    Structure edns_option
646*be771a7bSCy Schubert  * ************************************************************************************ */
647*be771a7bSCy Schubert /* Rename the members to follow the python convention of marking them as
648*be771a7bSCy Schubert  * private. Access to the opt_code and opt_data members is given by the later
649*be771a7bSCy Schubert  * python defined code and data members respectively. */
650*be771a7bSCy Schubert %rename(_next) edns_option::next;
651*be771a7bSCy Schubert %rename(_opt_code) edns_option::opt_code;
652*be771a7bSCy Schubert %rename(_opt_len) edns_option::opt_len;
653*be771a7bSCy Schubert %rename(_opt_data) edns_option::opt_data;
654*be771a7bSCy Schubert struct edns_option {
655*be771a7bSCy Schubert     struct edns_option* next;
656*be771a7bSCy Schubert     uint16_t opt_code;
657*be771a7bSCy Schubert     size_t opt_len;
658*be771a7bSCy Schubert     uint8_t* opt_data;
659*be771a7bSCy Schubert };
660*be771a7bSCy Schubert 
661*be771a7bSCy Schubert %inline %{
662*be771a7bSCy Schubert     PyObject* _edns_option_opt_code_get(struct edns_option* option) {
663*be771a7bSCy Schubert         uint16_t opt_code = option->opt_code;
664*be771a7bSCy Schubert         return PyInt_FromLong(opt_code);
665*be771a7bSCy Schubert     }
666*be771a7bSCy Schubert 
667*be771a7bSCy Schubert     PyObject* _edns_option_opt_data_get(struct edns_option* option) {
668*be771a7bSCy Schubert         return PyByteArray_FromStringAndSize((void*)option->opt_data,
669*be771a7bSCy Schubert             option->opt_len);
670*be771a7bSCy Schubert     }
671*be771a7bSCy Schubert %}
672*be771a7bSCy Schubert %extend edns_option {
673*be771a7bSCy Schubert     %pythoncode %{
674*be771a7bSCy Schubert         def _opt_code_get(self): return _edns_option_opt_code_get(self)
675*be771a7bSCy Schubert         code = property(_opt_code_get)
676*be771a7bSCy Schubert 
677*be771a7bSCy Schubert         def _opt_data_get(self): return _edns_option_opt_data_get(self)
678*be771a7bSCy Schubert         data = property(_opt_data_get)
679*be771a7bSCy Schubert     %}
680*be771a7bSCy Schubert }
681*be771a7bSCy Schubert 
682*be771a7bSCy Schubert /* ************************************************************************************ *
683*be771a7bSCy Schubert    Structure edns_data
684*be771a7bSCy Schubert  * ************************************************************************************ */
685*be771a7bSCy Schubert /* This is ignored because we will pass a double pointer of this to Python
686*be771a7bSCy Schubert  * with custom getmethods. This is done to bypass Swig's behavior to pass NULL
687*be771a7bSCy Schubert  * pointers as None. */
688*be771a7bSCy Schubert %ignore edns_data::opt_list;
689*be771a7bSCy Schubert struct edns_data {
690*be771a7bSCy Schubert     int edns_present;
691*be771a7bSCy Schubert     uint8_t ext_rcode;
692*be771a7bSCy Schubert     uint8_t edns_version;
693*be771a7bSCy Schubert     uint16_t bits;
694*be771a7bSCy Schubert     uint16_t udp_size;
695*be771a7bSCy Schubert     struct edns_option* opt_list_in;
696*be771a7bSCy Schubert     struct edns_option* opt_list_out;
697*be771a7bSCy Schubert     struct edns_option* opt_list_inplace_cb_out;
698*be771a7bSCy Schubert     uint16_t padding_block_size;
699*be771a7bSCy Schubert };
700*be771a7bSCy Schubert %inline %{
701*be771a7bSCy Schubert     struct edns_option** _edns_data_opt_list_get(struct edns_data* edns) {
702*be771a7bSCy Schubert        return &edns->opt_list_in;
703*be771a7bSCy Schubert     }
704*be771a7bSCy Schubert %}
705*be771a7bSCy Schubert %extend edns_data {
706*be771a7bSCy Schubert     %pythoncode %{
707*be771a7bSCy Schubert         def _opt_list_iter(self): return EdnsOptsListIter(self.opt_list)
708*be771a7bSCy Schubert         opt_list_iter = property(_opt_list_iter)
709*be771a7bSCy Schubert         def _opt_list(self): return _edns_data_opt_list_get(self)
710*be771a7bSCy Schubert         opt_list = property(_opt_list)
711*be771a7bSCy Schubert     %}
712*be771a7bSCy Schubert }
713*be771a7bSCy Schubert 
714*be771a7bSCy Schubert /* ************************************************************************************ *
715*be771a7bSCy Schubert    Structure module_env
716*be771a7bSCy Schubert  * ************************************************************************************ */
717*be771a7bSCy Schubert %rename(_now) module_env::now;
718*be771a7bSCy Schubert %rename(_now_tv) module_env::now_tv;
719*be771a7bSCy Schubert struct module_env {
720*be771a7bSCy Schubert     struct config_file* cfg;
721*be771a7bSCy Schubert     struct slabhash* msg_cache;
722*be771a7bSCy Schubert     struct rrset_cache* rrset_cache;
723*be771a7bSCy Schubert     struct infra_cache* infra_cache;
724*be771a7bSCy Schubert     struct key_cache* key_cache;
725*be771a7bSCy Schubert 
726*be771a7bSCy Schubert     /* --- services --- */
727*be771a7bSCy Schubert     struct outbound_entry* (*send_query)(struct query_info* qinfo,
728*be771a7bSCy Schubert         uint16_t flags, int dnssec, int want_dnssec, int nocaps,
729*be771a7bSCy Schubert         int check_ratelimit,
730*be771a7bSCy Schubert         struct sockaddr_storage* addr, socklen_t addrlen,
731*be771a7bSCy Schubert         uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
732*be771a7bSCy Schubert         char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
733*be771a7bSCy Schubert     void (*detach_subs)(struct module_qstate* qstate);
734*be771a7bSCy Schubert     int (*attach_sub)(struct module_qstate* qstate,
735*be771a7bSCy Schubert         struct query_info* qinfo, uint16_t qflags, int prime,
736*be771a7bSCy Schubert         int valrec, struct module_qstate** newq);
737*be771a7bSCy Schubert     void (*kill_sub)(struct module_qstate* newq);
738*be771a7bSCy Schubert     int (*detect_cycle)(struct module_qstate* qstate,
739*be771a7bSCy Schubert         struct query_info* qinfo, uint16_t flags, int prime,
740*be771a7bSCy Schubert         int valrec);
741*be771a7bSCy Schubert 
742*be771a7bSCy Schubert     struct regional* scratch;
743*be771a7bSCy Schubert     struct sldns_buffer* scratch_buffer;
744*be771a7bSCy Schubert     struct worker* worker;
745*be771a7bSCy Schubert     struct mesh_area* mesh;
746*be771a7bSCy Schubert     struct alloc_cache* alloc;
747*be771a7bSCy Schubert     struct ub_randstate* rnd;
748*be771a7bSCy Schubert     time_t* now;
749*be771a7bSCy Schubert     struct timeval* now_tv;
750*be771a7bSCy Schubert     int need_to_validate;
751*be771a7bSCy Schubert     struct val_anchors* anchors;
752*be771a7bSCy Schubert     struct val_neg_cache* neg_cache;
753*be771a7bSCy Schubert     struct comm_timer* probe_timer;
754*be771a7bSCy Schubert     struct iter_forwards* fwds;
755*be771a7bSCy Schubert     struct iter_hints* hints;
756*be771a7bSCy Schubert     void* modinfo[MAX_MODULE];
757*be771a7bSCy Schubert 
758*be771a7bSCy Schubert     void* inplace_cb_lists[inplace_cb_types_total];
759*be771a7bSCy Schubert     struct edns_known_option* edns_known_options;
760*be771a7bSCy Schubert     size_t edns_known_options_num;
761*be771a7bSCy Schubert };
762*be771a7bSCy Schubert 
763*be771a7bSCy Schubert %inline %{
764*be771a7bSCy Schubert     PyObject* _module_env_now_get(struct module_env* env) {
765*be771a7bSCy Schubert         double ts = env->now_tv->tv_sec + env->now_tv->tv_usec / 1e6;
766*be771a7bSCy Schubert         return PyFloat_FromDouble(ts);
767*be771a7bSCy Schubert     }
768*be771a7bSCy Schubert %}
769*be771a7bSCy Schubert %extend module_env {
770*be771a7bSCy Schubert     %pythoncode %{
771*be771a7bSCy Schubert         def _now_get(self): return _module_env_now_get(self)
772*be771a7bSCy Schubert         now = property(_now_get)
773*be771a7bSCy Schubert     %}
774*be771a7bSCy Schubert }
775*be771a7bSCy Schubert 
776*be771a7bSCy Schubert /* ************************************************************************************ *
777*be771a7bSCy Schubert    Structure module_qstate
778*be771a7bSCy Schubert  * ************************************************************************************ */
779*be771a7bSCy Schubert %ignore module_qstate::ext_state;
780*be771a7bSCy Schubert %ignore module_qstate::minfo;
781*be771a7bSCy Schubert 
782*be771a7bSCy Schubert /* These are ignored because we will pass a double pointer of them to Python
783*be771a7bSCy Schubert  * with custom getmethods. This is done to bypass Swig's behavior to pass NULL
784*be771a7bSCy Schubert  * pointers as None. */
785*be771a7bSCy Schubert %ignore module_qstate::edns_opts_front_in;
786*be771a7bSCy Schubert %ignore module_qstate::edns_opts_back_out;
787*be771a7bSCy Schubert %ignore module_qstate::edns_opts_back_in;
788*be771a7bSCy Schubert %ignore module_qstate::edns_opts_front_out;
789*be771a7bSCy Schubert 
790*be771a7bSCy Schubert /* Query state */
791*be771a7bSCy Schubert struct module_qstate {
792*be771a7bSCy Schubert    struct query_info qinfo;
793*be771a7bSCy Schubert    uint16_t query_flags;  /* See QF_BIT_xx constants */
794*be771a7bSCy Schubert    int is_priming;
795*be771a7bSCy Schubert    int is_valrec;
796*be771a7bSCy Schubert 
797*be771a7bSCy Schubert    struct comm_reply* reply;
798*be771a7bSCy Schubert    struct dns_msg* return_msg;
799*be771a7bSCy Schubert    int return_rcode;
800*be771a7bSCy Schubert    struct regional* region; /* unwrapped */
801*be771a7bSCy Schubert 
802*be771a7bSCy Schubert    int curmod;
803*be771a7bSCy Schubert 
804*be771a7bSCy Schubert    enum module_ext_state ext_state[MAX_MODULE];
805*be771a7bSCy Schubert    void* minfo[MAX_MODULE];
806*be771a7bSCy Schubert    time_t prefetch_leeway;
807*be771a7bSCy Schubert 
808*be771a7bSCy Schubert    struct module_env* env;         /* unwrapped */
809*be771a7bSCy Schubert    struct mesh_state* mesh_info;
810*be771a7bSCy Schubert 
811*be771a7bSCy Schubert    struct edns_option* edns_opts_front_in;
812*be771a7bSCy Schubert    struct edns_option* edns_opts_back_out;
813*be771a7bSCy Schubert    struct edns_option* edns_opts_back_in;
814*be771a7bSCy Schubert    struct edns_option* edns_opts_front_out;
815*be771a7bSCy Schubert    int no_cache_lookup;
816*be771a7bSCy Schubert    int no_cache_store;
817*be771a7bSCy Schubert };
818*be771a7bSCy Schubert 
819*be771a7bSCy Schubert %constant int MODULE_COUNT = MAX_MODULE;
820*be771a7bSCy Schubert 
821*be771a7bSCy Schubert %constant int QF_BIT_CD = 0x0010;
822*be771a7bSCy Schubert %constant int QF_BIT_AD = 0x0020;
823*be771a7bSCy Schubert %constant int QF_BIT_Z  = 0x0040;
824*be771a7bSCy Schubert %constant int QF_BIT_RA = 0x0080;
825*be771a7bSCy Schubert %constant int QF_BIT_RD = 0x0100;
826*be771a7bSCy Schubert %constant int QF_BIT_TC = 0x0200;
827*be771a7bSCy Schubert %constant int QF_BIT_AA = 0x0400;
828*be771a7bSCy Schubert %constant int QF_BIT_QR = 0x8000;
829*be771a7bSCy Schubert 
830*be771a7bSCy Schubert %inline %{
831*be771a7bSCy Schubert  enum enum_return_rcode {
832*be771a7bSCy Schubert    RCODE_NOERROR = 0,
833*be771a7bSCy Schubert    RCODE_FORMERR = 1,
834*be771a7bSCy Schubert    RCODE_SERVFAIL = 2,
835*be771a7bSCy Schubert    RCODE_NXDOMAIN = 3,
836*be771a7bSCy Schubert    RCODE_NOTIMPL = 4,
837*be771a7bSCy Schubert    RCODE_REFUSED = 5,
838*be771a7bSCy Schubert    RCODE_YXDOMAIN = 6,
839*be771a7bSCy Schubert    RCODE_YXRRSET = 7,
840*be771a7bSCy Schubert    RCODE_NXRRSET = 8,
841*be771a7bSCy Schubert    RCODE_NOTAUTH = 9,
842*be771a7bSCy Schubert    RCODE_NOTZONE = 10
843*be771a7bSCy Schubert  };
844*be771a7bSCy Schubert %}
845*be771a7bSCy Schubert 
846*be771a7bSCy Schubert %pythoncode %{
847*be771a7bSCy Schubert     class ExtState:
848*be771a7bSCy Schubert         def __init__(self, obj): self.obj = obj
849*be771a7bSCy Schubert         def __str__(self):
850*be771a7bSCy Schubert             return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)])
851*be771a7bSCy Schubert         def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
852*be771a7bSCy Schubert         def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
853*be771a7bSCy Schubert         def __len__(self): return _unboundmodule.MODULE_COUNT
854*be771a7bSCy Schubert 
855*be771a7bSCy Schubert     class EdnsOptsListIter:
856*be771a7bSCy Schubert         def __init__(self, obj):
857*be771a7bSCy Schubert             self._current = obj
858*be771a7bSCy Schubert             self._temp = None
859*be771a7bSCy Schubert         def __iter__(self): return self
860*be771a7bSCy Schubert         def __next__(self):
861*be771a7bSCy Schubert             """Python 3 compatibility"""
862*be771a7bSCy Schubert             return self._get_next()
863*be771a7bSCy Schubert         def next(self):
864*be771a7bSCy Schubert             """Python 2 compatibility"""
865*be771a7bSCy Schubert             return self._get_next()
866*be771a7bSCy Schubert         def _get_next(self):
867*be771a7bSCy Schubert             if not edns_opt_list_is_empty(self._current):
868*be771a7bSCy Schubert                 self._temp = self._current
869*be771a7bSCy Schubert                 self._current = _p_p_edns_option_get_next(self._current)
870*be771a7bSCy Schubert                 return _dereference_edns_option(self._temp)
871*be771a7bSCy Schubert             else:
872*be771a7bSCy Schubert                 raise StopIteration
873*be771a7bSCy Schubert %}
874*be771a7bSCy Schubert 
875*be771a7bSCy Schubert %inline %{
876*be771a7bSCy Schubert    enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
877*be771a7bSCy Schubert      if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
878*be771a7bSCy Schubert         return q->ext_state[idx];
879*be771a7bSCy Schubert      }
880*be771a7bSCy Schubert      return 0;
881*be771a7bSCy Schubert    }
882*be771a7bSCy Schubert 
883*be771a7bSCy Schubert    void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
884*be771a7bSCy Schubert      if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
885*be771a7bSCy Schubert         q->ext_state[idx] = state;
886*be771a7bSCy Schubert      }
887*be771a7bSCy Schubert    }
888*be771a7bSCy Schubert 
889*be771a7bSCy Schubert    int edns_opt_list_is_empty(struct edns_option** opt) {
890*be771a7bSCy Schubert         if (!opt || !(*opt)) return 1;
891*be771a7bSCy Schubert         return 0;
892*be771a7bSCy Schubert    }
893*be771a7bSCy Schubert 
894*be771a7bSCy Schubert    struct edns_option* _dereference_edns_option(struct edns_option** opt) {
895*be771a7bSCy Schubert         if (!opt) return NULL;
896*be771a7bSCy Schubert         return *opt;
897*be771a7bSCy Schubert    }
898*be771a7bSCy Schubert 
899*be771a7bSCy Schubert    struct edns_option** _p_p_edns_option_get_next(struct edns_option** opt) {
900*be771a7bSCy Schubert         return &(*opt)->next;
901*be771a7bSCy Schubert    }
902*be771a7bSCy Schubert 
903*be771a7bSCy Schubert    struct edns_option** _edns_opts_front_in_get(struct module_qstate* q) {
904*be771a7bSCy Schubert         return &q->edns_opts_front_in;
905*be771a7bSCy Schubert    }
906*be771a7bSCy Schubert 
907*be771a7bSCy Schubert    struct edns_option** _edns_opts_back_out_get(struct module_qstate* q) {
908*be771a7bSCy Schubert         return &q->edns_opts_back_out;
909*be771a7bSCy Schubert    }
910*be771a7bSCy Schubert 
911*be771a7bSCy Schubert    struct edns_option** _edns_opts_back_in_get(struct module_qstate* q) {
912*be771a7bSCy Schubert         return &q->edns_opts_back_in;
913*be771a7bSCy Schubert    }
914*be771a7bSCy Schubert 
915*be771a7bSCy Schubert    struct edns_option** _edns_opts_front_out_get(struct module_qstate* q) {
916*be771a7bSCy Schubert         return &q->edns_opts_front_out;
917*be771a7bSCy Schubert    }
918*be771a7bSCy Schubert %}
919*be771a7bSCy Schubert 
920*be771a7bSCy Schubert %extend module_qstate {
921*be771a7bSCy Schubert    %pythoncode %{
922*be771a7bSCy Schubert         def set_ext_state(self, id, state):
923*be771a7bSCy Schubert             """Sets the ext state"""
924*be771a7bSCy Schubert             _unboundmodule._ext_state_set(self, id, state)
925*be771a7bSCy Schubert 
926*be771a7bSCy Schubert         def __ext_state_get(self): return ExtState(self)
927*be771a7bSCy Schubert         ext_state = property(__ext_state_get) #, __ext_state_set
928*be771a7bSCy Schubert 
929*be771a7bSCy Schubert         def _edns_opts_front_in_iter(self): return EdnsOptsListIter(self.edns_opts_front_in)
930*be771a7bSCy Schubert         edns_opts_front_in_iter = property(_edns_opts_front_in_iter)
931*be771a7bSCy Schubert         def _edns_opts_back_out_iter(self): return EdnsOptsListIter(self.edns_opts_back_out)
932*be771a7bSCy Schubert         edns_opts_back_out_iter = property(_edns_opts_back_out_iter)
933*be771a7bSCy Schubert         def _edns_opts_back_in_iter(self): return EdnsOptsListIter(self.edns_opts_back_in)
934*be771a7bSCy Schubert         edns_opts_back_in_iter = property(_edns_opts_back_in_iter)
935*be771a7bSCy Schubert         def _edns_opts_front_out_iter(self): return EdnsOptsListIter(self.edns_opts_front_out)
936*be771a7bSCy Schubert         edns_opts_front_out_iter = property(_edns_opts_front_out_iter)
937*be771a7bSCy Schubert 
938*be771a7bSCy Schubert         def _edns_opts_front_in(self): return _edns_opts_front_in_get(self)
939*be771a7bSCy Schubert         edns_opts_front_in = property(_edns_opts_front_in)
940*be771a7bSCy Schubert         def _edns_opts_back_out(self): return _edns_opts_back_out_get(self)
941*be771a7bSCy Schubert         edns_opts_back_out = property(_edns_opts_back_out)
942*be771a7bSCy Schubert         def _edns_opts_back_in(self): return _edns_opts_back_in_get(self)
943*be771a7bSCy Schubert         edns_opts_back_in = property(_edns_opts_back_in)
944*be771a7bSCy Schubert         def _edns_opts_front_out(self): return _edns_opts_front_out_get(self)
945*be771a7bSCy Schubert         edns_opts_front_out = property(_edns_opts_front_out)
946*be771a7bSCy Schubert    %}
947*be771a7bSCy Schubert }
948*be771a7bSCy Schubert 
949*be771a7bSCy Schubert /* ************************************************************************************ *
950*be771a7bSCy Schubert    Structure config_strlist
951*be771a7bSCy Schubert  * ************************************************************************************ */
952*be771a7bSCy Schubert struct config_strlist {
953*be771a7bSCy Schubert    struct config_strlist* next;
954*be771a7bSCy Schubert    char* str;
955*be771a7bSCy Schubert };
956*be771a7bSCy Schubert 
957*be771a7bSCy Schubert /* ************************************************************************************ *
958*be771a7bSCy Schubert    Structure config_str2list
959*be771a7bSCy Schubert  * ************************************************************************************ */
960*be771a7bSCy Schubert struct config_str2list {
961*be771a7bSCy Schubert    struct config_str2list* next;
962*be771a7bSCy Schubert    char* str;
963*be771a7bSCy Schubert    char* str2;
964*be771a7bSCy Schubert };
965*be771a7bSCy Schubert 
966*be771a7bSCy Schubert /* ************************************************************************************ *
967*be771a7bSCy Schubert    Structure config_file
968*be771a7bSCy Schubert  * ************************************************************************************ */
969*be771a7bSCy Schubert %ignore config_file::ifs;
970*be771a7bSCy Schubert %ignore config_file::out_ifs;
971*be771a7bSCy Schubert %ignore config_file::python_script;
972*be771a7bSCy Schubert struct config_file {
973*be771a7bSCy Schubert    int verbosity;
974*be771a7bSCy Schubert    int stat_interval;
975*be771a7bSCy Schubert    int stat_cumulative;
976*be771a7bSCy Schubert    int stat_extended;
977*be771a7bSCy Schubert    int num_threads;
978*be771a7bSCy Schubert    int port;
979*be771a7bSCy Schubert    int do_ip4;
980*be771a7bSCy Schubert    int do_ip6;
981*be771a7bSCy Schubert    int do_udp;
982*be771a7bSCy Schubert    int do_tcp;
983*be771a7bSCy Schubert    int outgoing_num_ports;
984*be771a7bSCy Schubert    size_t outgoing_num_tcp;
985*be771a7bSCy Schubert    size_t incoming_num_tcp;
986*be771a7bSCy Schubert    int* outgoing_avail_ports;
987*be771a7bSCy Schubert    size_t msg_buffer_size;
988*be771a7bSCy Schubert    size_t msg_cache_size;
989*be771a7bSCy Schubert    size_t msg_cache_slabs;
990*be771a7bSCy Schubert    size_t num_queries_per_thread;
991*be771a7bSCy Schubert    size_t jostle_time;
992*be771a7bSCy Schubert    size_t rrset_cache_size;
993*be771a7bSCy Schubert    size_t rrset_cache_slabs;
994*be771a7bSCy Schubert    int host_ttl;
995*be771a7bSCy Schubert    size_t infra_cache_slabs;
996*be771a7bSCy Schubert    size_t infra_cache_numhosts;
997*be771a7bSCy Schubert    char* target_fetch_policy;
998*be771a7bSCy Schubert    int if_automatic;
999*be771a7bSCy Schubert    int num_ifs;
1000*be771a7bSCy Schubert    char **ifs;
1001*be771a7bSCy Schubert    int num_out_ifs;
1002*be771a7bSCy Schubert    char **out_ifs;
1003*be771a7bSCy Schubert    struct config_strlist* root_hints;
1004*be771a7bSCy Schubert    struct config_stub* stubs;
1005*be771a7bSCy Schubert    struct config_stub* forwards;
1006*be771a7bSCy Schubert    struct config_strlist* donotqueryaddrs;
1007*be771a7bSCy Schubert    struct config_str2list* acls;
1008*be771a7bSCy Schubert    int donotquery_localhost;
1009*be771a7bSCy Schubert    int harden_short_bufsize;
1010*be771a7bSCy Schubert    int harden_large_queries;
1011*be771a7bSCy Schubert    int harden_glue;
1012*be771a7bSCy Schubert    int harden_unverified_glue;
1013*be771a7bSCy Schubert    int harden_dnssec_stripped;
1014*be771a7bSCy Schubert    int harden_referral_path;
1015*be771a7bSCy Schubert    int use_caps_bits_for_id;
1016*be771a7bSCy Schubert    struct config_strlist* private_address;
1017*be771a7bSCy Schubert    struct config_strlist* private_domain;
1018*be771a7bSCy Schubert    size_t unwanted_threshold;
1019*be771a7bSCy Schubert    char* chrootdir;
1020*be771a7bSCy Schubert    char* username;
1021*be771a7bSCy Schubert    char* directory;
1022*be771a7bSCy Schubert    char* logfile;
1023*be771a7bSCy Schubert    char* pidfile;
1024*be771a7bSCy Schubert    int use_syslog;
1025*be771a7bSCy Schubert    int hide_identity;
1026*be771a7bSCy Schubert    int hide_version;
1027*be771a7bSCy Schubert    char* identity;
1028*be771a7bSCy Schubert    char* version;
1029*be771a7bSCy Schubert    char* module_conf;
1030*be771a7bSCy Schubert    struct config_strlist* trust_anchor_file_list;
1031*be771a7bSCy Schubert    struct config_strlist* trust_anchor_list;
1032*be771a7bSCy Schubert    struct config_strlist* trusted_keys_file_list;
1033*be771a7bSCy Schubert    int max_ttl;
1034*be771a7bSCy Schubert    int32_t val_date_override;
1035*be771a7bSCy Schubert    int bogus_ttl;
1036*be771a7bSCy Schubert    int val_clean_additional;
1037*be771a7bSCy Schubert    int val_permissive_mode;
1038*be771a7bSCy Schubert    char* val_nsec3_key_iterations;
1039*be771a7bSCy Schubert    size_t key_cache_size;
1040*be771a7bSCy Schubert    size_t key_cache_slabs;
1041*be771a7bSCy Schubert    size_t neg_cache_size;
1042*be771a7bSCy Schubert    struct config_str2list* local_zones;
1043*be771a7bSCy Schubert    struct config_strlist* local_zones_nodefault;
1044*be771a7bSCy Schubert    struct config_strlist* local_data;
1045*be771a7bSCy Schubert    int remote_control_enable;
1046*be771a7bSCy Schubert    struct config_strlist_head control_ifs;
1047*be771a7bSCy Schubert    int control_port;
1048*be771a7bSCy Schubert    char* server_key_file;
1049*be771a7bSCy Schubert    char* server_cert_file;
1050*be771a7bSCy Schubert    char* control_key_file;
1051*be771a7bSCy Schubert    char* control_cert_file;
1052*be771a7bSCy Schubert    int do_daemonize;
1053*be771a7bSCy Schubert    struct config_strlist* python_script;
1054*be771a7bSCy Schubert };
1055*be771a7bSCy Schubert 
1056*be771a7bSCy Schubert %inline %{
1057*be771a7bSCy Schubert    PyObject* _get_ifs_tuple(struct config_file* cfg) {
1058*be771a7bSCy Schubert       return CharArrayAsStringList(cfg->ifs, cfg->num_ifs);
1059*be771a7bSCy Schubert    }
1060*be771a7bSCy Schubert    PyObject* _get_ifs_out_tuple(struct config_file* cfg) {
1061*be771a7bSCy Schubert       return CharArrayAsStringList(cfg->out_ifs, cfg->num_out_ifs);
1062*be771a7bSCy Schubert    }
1063*be771a7bSCy Schubert %}
1064*be771a7bSCy Schubert 
1065*be771a7bSCy Schubert %extend config_file {
1066*be771a7bSCy Schubert    %pythoncode %{
1067*be771a7bSCy Schubert         ifs = property(_unboundmodule._get_ifs_tuple)
1068*be771a7bSCy Schubert         out_ifs = property(_unboundmodule._get_ifs_out_tuple)
1069*be771a7bSCy Schubert 
1070*be771a7bSCy Schubert         def _deprecated_python_script(self): return "cfg.python_script is deprecated, you can use `mod_env['script']` instead."
1071*be771a7bSCy Schubert         python_script = property(_deprecated_python_script)
1072*be771a7bSCy Schubert    %}
1073*be771a7bSCy Schubert }
1074*be771a7bSCy Schubert 
1075*be771a7bSCy Schubert /* ************************************************************************************ *
1076*be771a7bSCy Schubert    ASN: Adding structures related to forwards_lookup and dns_cache_find_delegation
1077*be771a7bSCy Schubert  * ************************************************************************************ */
1078*be771a7bSCy Schubert struct delegpt_ns {
1079*be771a7bSCy Schubert     struct delegpt_ns* next;
1080*be771a7bSCy Schubert     int resolved;
1081*be771a7bSCy Schubert     uint8_t got4;
1082*be771a7bSCy Schubert     uint8_t got6;
1083*be771a7bSCy Schubert     uint8_t lame;
1084*be771a7bSCy Schubert     uint8_t done_pside4;
1085*be771a7bSCy Schubert     uint8_t done_pside6;
1086*be771a7bSCy Schubert };
1087*be771a7bSCy Schubert 
1088*be771a7bSCy Schubert struct delegpt_addr {
1089*be771a7bSCy Schubert     struct delegpt_addr* next_result;
1090*be771a7bSCy Schubert     struct delegpt_addr* next_usable;
1091*be771a7bSCy Schubert     struct delegpt_addr* next_target;
1092*be771a7bSCy Schubert     int attempts;
1093*be771a7bSCy Schubert     int sel_rtt;
1094*be771a7bSCy Schubert     int bogus;
1095*be771a7bSCy Schubert     int lame;
1096*be771a7bSCy Schubert };
1097*be771a7bSCy Schubert 
1098*be771a7bSCy Schubert struct delegpt {
1099*be771a7bSCy Schubert     int namelabs;
1100*be771a7bSCy Schubert     struct delegpt_ns* nslist;
1101*be771a7bSCy Schubert     struct delegpt_addr* target_list;
1102*be771a7bSCy Schubert     struct delegpt_addr* usable_list;
1103*be771a7bSCy Schubert     struct delegpt_addr* result_list;
1104*be771a7bSCy Schubert     int bogus;
1105*be771a7bSCy Schubert     uint8_t has_parent_side_NS;
1106*be771a7bSCy Schubert     uint8_t dp_type_mlc;
1107*be771a7bSCy Schubert };
1108*be771a7bSCy Schubert 
1109*be771a7bSCy Schubert 
1110*be771a7bSCy Schubert %inline %{
1111*be771a7bSCy Schubert    PyObject* _get_dp_dname(struct delegpt* dp) {
1112*be771a7bSCy Schubert       return PyBytes_FromStringAndSize((char*)dp->name, dp->namelen);
1113*be771a7bSCy Schubert    }
1114*be771a7bSCy Schubert    PyObject* _get_dp_dname_components(struct delegpt* dp) {
1115*be771a7bSCy Schubert       return GetNameAsLabelList((char*)dp->name, dp->namelen);
1116*be771a7bSCy Schubert    }
1117*be771a7bSCy Schubert    PyObject* _get_dpns_dname(struct delegpt_ns* dpns) {
1118*be771a7bSCy Schubert       return PyBytes_FromStringAndSize((char*)dpns->name, dpns->namelen);
1119*be771a7bSCy Schubert    }
1120*be771a7bSCy Schubert    PyObject* _get_dpns_dname_components(struct delegpt_ns* dpns) {
1121*be771a7bSCy Schubert       return GetNameAsLabelList((char*)dpns->name, dpns->namelen);
1122*be771a7bSCy Schubert    }
1123*be771a7bSCy Schubert 
1124*be771a7bSCy Schubert   PyObject* _delegpt_addr_addr_get(struct delegpt_addr* target) {
1125*be771a7bSCy Schubert      char dest[64];
1126*be771a7bSCy Schubert      delegpt_addr_addr2str(target, dest, 64);
1127*be771a7bSCy Schubert      if (dest[0] == 0)
1128*be771a7bSCy Schubert         return Py_None;
1129*be771a7bSCy Schubert      return PyBytes_FromString(dest);
1130*be771a7bSCy Schubert   }
1131*be771a7bSCy Schubert 
1132*be771a7bSCy Schubert %}
1133*be771a7bSCy Schubert 
1134*be771a7bSCy Schubert %extend delegpt {
1135*be771a7bSCy Schubert    %pythoncode %{
1136*be771a7bSCy Schubert         dname = property(_unboundmodule._get_dp_dname)
1137*be771a7bSCy Schubert 
1138*be771a7bSCy Schubert         dname_list = property(_unboundmodule._get_dp_dname_components)
1139*be771a7bSCy Schubert 
1140*be771a7bSCy Schubert         def _get_dname_str(self): return dnameAsStr(self.dname)
1141*be771a7bSCy Schubert         dname_str = property(_get_dname_str)
1142*be771a7bSCy Schubert    %}
1143*be771a7bSCy Schubert }
1144*be771a7bSCy Schubert %extend delegpt_ns {
1145*be771a7bSCy Schubert    %pythoncode %{
1146*be771a7bSCy Schubert         dname = property(_unboundmodule._get_dpns_dname)
1147*be771a7bSCy Schubert 
1148*be771a7bSCy Schubert         dname_list = property(_unboundmodule._get_dpns_dname_components)
1149*be771a7bSCy Schubert 
1150*be771a7bSCy Schubert         def _get_dname_str(self): return dnameAsStr(self.dname)
1151*be771a7bSCy Schubert         dname_str = property(_get_dname_str)
1152*be771a7bSCy Schubert    %}
1153*be771a7bSCy Schubert }
1154*be771a7bSCy Schubert %extend delegpt_addr {
1155*be771a7bSCy Schubert    %pythoncode %{
1156*be771a7bSCy Schubert         def _addr_get(self): return _delegpt_addr_addr_get(self)
1157*be771a7bSCy Schubert         addr = property(_addr_get)
1158*be771a7bSCy Schubert    %}
1159*be771a7bSCy Schubert }
1160*be771a7bSCy Schubert 
1161*be771a7bSCy Schubert /* ************************************************************************************ *
1162*be771a7bSCy Schubert    Enums
1163*be771a7bSCy Schubert  * ************************************************************************************ */
1164*be771a7bSCy Schubert %rename ("MODULE_STATE_INITIAL") "module_state_initial";
1165*be771a7bSCy Schubert %rename ("MODULE_WAIT_REPLY") "module_wait_reply";
1166*be771a7bSCy Schubert %rename ("MODULE_WAIT_MODULE") "module_wait_module";
1167*be771a7bSCy Schubert %rename ("MODULE_RESTART_NEXT") "module_restart_next";
1168*be771a7bSCy Schubert %rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
1169*be771a7bSCy Schubert %rename ("MODULE_ERROR") "module_error";
1170*be771a7bSCy Schubert %rename ("MODULE_FINISHED") "module_finished";
1171*be771a7bSCy Schubert 
1172*be771a7bSCy Schubert enum module_ext_state {
1173*be771a7bSCy Schubert    module_state_initial = 0,
1174*be771a7bSCy Schubert    module_wait_reply,
1175*be771a7bSCy Schubert    module_wait_module,
1176*be771a7bSCy Schubert    module_restart_next,
1177*be771a7bSCy Schubert    module_wait_subquery,
1178*be771a7bSCy Schubert    module_error,
1179*be771a7bSCy Schubert    module_finished
1180*be771a7bSCy Schubert };
1181*be771a7bSCy Schubert 
1182*be771a7bSCy Schubert %rename ("MODULE_EVENT_NEW") "module_event_new";
1183*be771a7bSCy Schubert %rename ("MODULE_EVENT_PASS") "module_event_pass";
1184*be771a7bSCy Schubert %rename ("MODULE_EVENT_REPLY") "module_event_reply";
1185*be771a7bSCy Schubert %rename ("MODULE_EVENT_NOREPLY") "module_event_noreply";
1186*be771a7bSCy Schubert %rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail";
1187*be771a7bSCy Schubert %rename ("MODULE_EVENT_MODDONE") "module_event_moddone";
1188*be771a7bSCy Schubert %rename ("MODULE_EVENT_ERROR") "module_event_error";
1189*be771a7bSCy Schubert 
1190*be771a7bSCy Schubert enum module_ev {
1191*be771a7bSCy Schubert    module_event_new = 0,
1192*be771a7bSCy Schubert    module_event_pass,
1193*be771a7bSCy Schubert    module_event_reply,
1194*be771a7bSCy Schubert    module_event_noreply,
1195*be771a7bSCy Schubert    module_event_capsfail,
1196*be771a7bSCy Schubert    module_event_moddone,
1197*be771a7bSCy Schubert    module_event_error
1198*be771a7bSCy Schubert };
1199*be771a7bSCy Schubert 
1200*be771a7bSCy Schubert enum sec_status {
1201*be771a7bSCy Schubert    sec_status_unchecked = 0,
1202*be771a7bSCy Schubert    sec_status_bogus,
1203*be771a7bSCy Schubert    sec_status_indeterminate,
1204*be771a7bSCy Schubert    sec_status_insecure,
1205*be771a7bSCy Schubert    sec_status_secure
1206*be771a7bSCy Schubert };
1207*be771a7bSCy Schubert 
1208*be771a7bSCy Schubert enum verbosity_value {
1209*be771a7bSCy Schubert    NO_VERBOSE = 0,
1210*be771a7bSCy Schubert    VERB_OPS,
1211*be771a7bSCy Schubert    VERB_DETAIL,
1212*be771a7bSCy Schubert    VERB_QUERY,
1213*be771a7bSCy Schubert    VERB_ALGO
1214*be771a7bSCy Schubert };
1215*be771a7bSCy Schubert 
1216*be771a7bSCy Schubert enum inplace_cb_list_type {
1217*be771a7bSCy Schubert     /* Inplace callbacks for when a resolved reply is ready to be sent to the
1218*be771a7bSCy Schubert      * front.*/
1219*be771a7bSCy Schubert     inplace_cb_reply = 0,
1220*be771a7bSCy Schubert     /* Inplace callbacks for when a reply is given from the cache. */
1221*be771a7bSCy Schubert     inplace_cb_reply_cache,
1222*be771a7bSCy Schubert     /* Inplace callbacks for when a reply is given with local data
1223*be771a7bSCy Schubert      * (or Chaos reply). */
1224*be771a7bSCy Schubert     inplace_cb_reply_local,
1225*be771a7bSCy Schubert     /* Inplace callbacks for when the reply is servfail. */
1226*be771a7bSCy Schubert     inplace_cb_reply_servfail,
1227*be771a7bSCy Schubert     /* Inplace callbacks for when a query is ready to be sent to the back.*/
1228*be771a7bSCy Schubert     inplace_cb_query,
1229*be771a7bSCy Schubert     /* Inplace callback for when a reply is received from the back. */
1230*be771a7bSCy Schubert     inplace_cb_edns_back_parsed,
1231*be771a7bSCy Schubert     /* Total number of types. Used for array initialization.
1232*be771a7bSCy Schubert      * Should always be last. */
1233*be771a7bSCy Schubert     inplace_cb_types_total
1234*be771a7bSCy Schubert };
1235*be771a7bSCy Schubert 
1236*be771a7bSCy Schubert %constant uint16_t PKT_QR = 1;      /* QueRy - query flag */
1237*be771a7bSCy Schubert %constant uint16_t PKT_AA = 2;      /* Authoritative Answer - server flag */
1238*be771a7bSCy Schubert %constant uint16_t PKT_TC = 4;      /* TrunCated - server flag */
1239*be771a7bSCy Schubert %constant uint16_t PKT_RD = 8;      /* Recursion Desired - query flag */
1240*be771a7bSCy Schubert %constant uint16_t PKT_CD = 16;     /* Checking Disabled - query flag */
1241*be771a7bSCy Schubert %constant uint16_t PKT_RA = 32;     /* Recursion Available - server flag */
1242*be771a7bSCy Schubert %constant uint16_t PKT_AD = 64;     /* Authenticated Data - server flag */
1243*be771a7bSCy Schubert 
1244*be771a7bSCy Schubert %{
1245*be771a7bSCy Schubert int checkList(PyObject *l)
1246*be771a7bSCy Schubert {
1247*be771a7bSCy Schubert     PyObject* item;
1248*be771a7bSCy Schubert     int i;
1249*be771a7bSCy Schubert 
1250*be771a7bSCy Schubert     if (l == Py_None)
1251*be771a7bSCy Schubert        return 1;
1252*be771a7bSCy Schubert 
1253*be771a7bSCy Schubert     if (PyList_Check(l))
1254*be771a7bSCy Schubert     {
1255*be771a7bSCy Schubert        for (i=0; i < PyList_Size(l); i++)
1256*be771a7bSCy Schubert        {
1257*be771a7bSCy Schubert            item = PyList_GetItem(l, i);
1258*be771a7bSCy Schubert            if (!PyBytes_Check(item) && !PyUnicode_Check(item))
1259*be771a7bSCy Schubert               return 0;
1260*be771a7bSCy Schubert        }
1261*be771a7bSCy Schubert        return 1;
1262*be771a7bSCy Schubert     }
1263*be771a7bSCy Schubert 
1264*be771a7bSCy Schubert     return 0;
1265*be771a7bSCy Schubert }
1266*be771a7bSCy Schubert 
1267*be771a7bSCy Schubert int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
1268*be771a7bSCy Schubert         size_t count_offset)
1269*be771a7bSCy Schubert {
1270*be771a7bSCy Schubert     PyObject* item;
1271*be771a7bSCy Schubert     int i;
1272*be771a7bSCy Schubert     size_t len;
1273*be771a7bSCy Schubert     char* s;
1274*be771a7bSCy Schubert     PyObject* ascstr;
1275*be771a7bSCy Schubert 
1276*be771a7bSCy Schubert     for (i=0; i < PyList_Size(l); i++)
1277*be771a7bSCy Schubert     {
1278*be771a7bSCy Schubert         ascstr = NULL;
1279*be771a7bSCy Schubert         item = PyList_GetItem(l, i);
1280*be771a7bSCy Schubert         if(PyObject_TypeCheck(item, &PyBytes_Type)) {
1281*be771a7bSCy Schubert                 s = PyBytes_AsString(item);
1282*be771a7bSCy Schubert         } else {
1283*be771a7bSCy Schubert                 ascstr = PyUnicode_AsASCIIString(item);
1284*be771a7bSCy Schubert                 s = PyBytes_AsString(ascstr);
1285*be771a7bSCy Schubert         }
1286*be771a7bSCy Schubert 
1287*be771a7bSCy Schubert         len = sldns_buffer_remaining(qb);
1288*be771a7bSCy Schubert         if(qsec) {
1289*be771a7bSCy Schubert                 if(sldns_str2wire_rr_question_buf(s,
1290*be771a7bSCy Schubert                         sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
1291*be771a7bSCy Schubert                         != 0) {
1292*be771a7bSCy Schubert                         if(ascstr)
1293*be771a7bSCy Schubert                             Py_DECREF(ascstr);
1294*be771a7bSCy Schubert                         return 0;
1295*be771a7bSCy Schubert                 }
1296*be771a7bSCy Schubert         } else {
1297*be771a7bSCy Schubert                 if(sldns_str2wire_rr_buf(s,
1298*be771a7bSCy Schubert                         sldns_buffer_current(qb), &len, NULL, default_ttl,
1299*be771a7bSCy Schubert                         NULL, 0, NULL, 0) != 0) {
1300*be771a7bSCy Schubert                         if(ascstr)
1301*be771a7bSCy Schubert                             Py_DECREF(ascstr);
1302*be771a7bSCy Schubert                         return 0;
1303*be771a7bSCy Schubert                 }
1304*be771a7bSCy Schubert         }
1305*be771a7bSCy Schubert         if(ascstr)
1306*be771a7bSCy Schubert             Py_DECREF(ascstr);
1307*be771a7bSCy Schubert         sldns_buffer_skip(qb, len);
1308*be771a7bSCy Schubert 
1309*be771a7bSCy Schubert         sldns_buffer_write_u16_at(qb, count_offset,
1310*be771a7bSCy Schubert                 sldns_buffer_read_u16_at(qb, count_offset)+1);
1311*be771a7bSCy Schubert     }
1312*be771a7bSCy Schubert     return 1;
1313*be771a7bSCy Schubert }
1314*be771a7bSCy Schubert 
1315*be771a7bSCy Schubert int set_return_msg(struct module_qstate* qstate,
1316*be771a7bSCy Schubert                    const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
1317*be771a7bSCy Schubert                    PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)
1318*be771a7bSCy Schubert {
1319*be771a7bSCy Schubert      sldns_buffer *qb = 0;
1320*be771a7bSCy Schubert      int res = 1;
1321*be771a7bSCy Schubert      size_t l;
1322*be771a7bSCy Schubert      uint16_t PKT_QR = 1;
1323*be771a7bSCy Schubert      uint16_t PKT_AA = 2;
1324*be771a7bSCy Schubert      uint16_t PKT_TC = 4;
1325*be771a7bSCy Schubert      uint16_t PKT_RD = 8;
1326*be771a7bSCy Schubert      uint16_t PKT_CD = 16;
1327*be771a7bSCy Schubert      uint16_t PKT_RA = 32;
1328*be771a7bSCy Schubert      uint16_t PKT_AD = 64;
1329*be771a7bSCy Schubert 
1330*be771a7bSCy Schubert      if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
1331*be771a7bSCy Schubert         return 0;
1332*be771a7bSCy Schubert      if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0;
1333*be771a7bSCy Schubert 
1334*be771a7bSCy Schubert      /* write header */
1335*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 0); /* ID */
1336*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 0); /* flags */
1337*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 1); /* qdcount */
1338*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 0); /* ancount */
1339*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 0); /* nscount */
1340*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, 0); /* arcount */
1341*be771a7bSCy Schubert      if ((flags&PKT_QR)) LDNS_QR_SET(sldns_buffer_begin(qb));
1342*be771a7bSCy Schubert      if ((flags&PKT_AA)) LDNS_AA_SET(sldns_buffer_begin(qb));
1343*be771a7bSCy Schubert      if ((flags&PKT_TC)) LDNS_TC_SET(sldns_buffer_begin(qb));
1344*be771a7bSCy Schubert      if ((flags&PKT_RD)) LDNS_RD_SET(sldns_buffer_begin(qb));
1345*be771a7bSCy Schubert      if ((flags&PKT_CD)) LDNS_CD_SET(sldns_buffer_begin(qb));
1346*be771a7bSCy Schubert      if ((flags&PKT_RA)) LDNS_RA_SET(sldns_buffer_begin(qb));
1347*be771a7bSCy Schubert      if ((flags&PKT_AD)) LDNS_AD_SET(sldns_buffer_begin(qb));
1348*be771a7bSCy Schubert 
1349*be771a7bSCy Schubert      /* write the query */
1350*be771a7bSCy Schubert      l = sldns_buffer_remaining(qb);
1351*be771a7bSCy Schubert      if(sldns_str2wire_dname_buf(rr_name, sldns_buffer_current(qb), &l) != 0) {
1352*be771a7bSCy Schubert              sldns_buffer_free(qb);
1353*be771a7bSCy Schubert              return 0;
1354*be771a7bSCy Schubert      }
1355*be771a7bSCy Schubert      sldns_buffer_skip(qb, l);
1356*be771a7bSCy Schubert      if (rr_type == 0) { rr_type = LDNS_RR_TYPE_A; }
1357*be771a7bSCy Schubert      if (rr_class == 0) { rr_class = LDNS_RR_CLASS_IN; }
1358*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, rr_type);
1359*be771a7bSCy Schubert      sldns_buffer_write_u16(qb, rr_class);
1360*be771a7bSCy Schubert 
1361*be771a7bSCy Schubert      /* write RR sections */
1362*be771a7bSCy Schubert      if(res && !pushRRList(qb, question, default_ttl, 1, LDNS_QDCOUNT_OFF))
1363*be771a7bSCy Schubert              res = 0;
1364*be771a7bSCy Schubert      if(res && !pushRRList(qb, answer, default_ttl, 0, LDNS_ANCOUNT_OFF))
1365*be771a7bSCy Schubert              res = 0;
1366*be771a7bSCy Schubert      if(res && !pushRRList(qb, authority, default_ttl, 0, LDNS_NSCOUNT_OFF))
1367*be771a7bSCy Schubert              res = 0;
1368*be771a7bSCy Schubert      if(res && !pushRRList(qb, additional, default_ttl, 0, LDNS_ARCOUNT_OFF))
1369*be771a7bSCy Schubert              res = 0;
1370*be771a7bSCy Schubert 
1371*be771a7bSCy Schubert      if (res) res = createResponse(qstate, qb);
1372*be771a7bSCy Schubert 
1373*be771a7bSCy Schubert      if (qb) sldns_buffer_free(qb);
1374*be771a7bSCy Schubert      return res;
1375*be771a7bSCy Schubert }
1376*be771a7bSCy Schubert %}
1377*be771a7bSCy Schubert 
1378*be771a7bSCy Schubert int set_return_msg(struct module_qstate* qstate,
1379*be771a7bSCy Schubert                    const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
1380*be771a7bSCy Schubert                    PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
1381*be771a7bSCy Schubert 
1382*be771a7bSCy Schubert %pythoncode %{
1383*be771a7bSCy Schubert     class DNSMessage:
1384*be771a7bSCy Schubert         def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0):
1385*be771a7bSCy Schubert             """Query flags is a combination of PKT_xx constants"""
1386*be771a7bSCy Schubert             self.rr_name = rr_name
1387*be771a7bSCy Schubert             self.rr_type = rr_type
1388*be771a7bSCy Schubert             self.rr_class = rr_class
1389*be771a7bSCy Schubert             self.default_ttl = default_ttl
1390*be771a7bSCy Schubert             self.query_flags = query_flags
1391*be771a7bSCy Schubert             self.question = []
1392*be771a7bSCy Schubert             self.answer = []
1393*be771a7bSCy Schubert             self.authority = []
1394*be771a7bSCy Schubert             self.additional = []
1395*be771a7bSCy Schubert 
1396*be771a7bSCy Schubert         def set_return_msg(self, qstate):
1397*be771a7bSCy Schubert             """Returns 1 if OK"""
1398*be771a7bSCy Schubert             status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class,
1399*be771a7bSCy Schubert                                            self.query_flags, self.default_ttl,
1400*be771a7bSCy Schubert                                            self.question, self.answer, self.authority, self.additional)
1401*be771a7bSCy Schubert 
1402*be771a7bSCy Schubert             if (status) and (PKT_AA & self.query_flags):
1403*be771a7bSCy Schubert                 qstate.return_msg.rep.authoritative = 1
1404*be771a7bSCy Schubert 
1405*be771a7bSCy Schubert             return status
1406*be771a7bSCy Schubert 
1407*be771a7bSCy Schubert %}
1408*be771a7bSCy Schubert /* ************************************************************************************ *
1409*be771a7bSCy Schubert    ASN: Delegation pointer related functions
1410*be771a7bSCy Schubert  * ************************************************************************************ */
1411*be771a7bSCy Schubert 
1412*be771a7bSCy Schubert /* Functions which we will need to lookup delegations */
1413*be771a7bSCy Schubert struct delegpt* dns_cache_find_delegation(struct module_env* env,
1414*be771a7bSCy Schubert         uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
1415*be771a7bSCy Schubert         struct regional* region, struct dns_msg** msg, uint32_t timenow,
1416*be771a7bSCy Schubert         int noexpiredabove, uint8_t* expiretop, size_t expiretoplen);
1417*be771a7bSCy Schubert int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
1418*be771a7bSCy Schubert         struct delegpt* dp, int supports_ipv4, int supports_ipv6, int use_nat64);
1419*be771a7bSCy Schubert struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
1420*be771a7bSCy Schubert         uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
1421*be771a7bSCy Schubert 
1422*be771a7bSCy Schubert /* Custom function to perform logic similar to the one in daemon/cachedump.c */
1423*be771a7bSCy Schubert struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen);
1424*be771a7bSCy Schubert 
1425*be771a7bSCy Schubert %{
1426*be771a7bSCy Schubert #define BIT_RD 0x100
1427*be771a7bSCy Schubert 
1428*be771a7bSCy Schubert struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen)
1429*be771a7bSCy Schubert {
1430*be771a7bSCy Schubert     struct delegpt *dp;
1431*be771a7bSCy Schubert     struct dns_msg *msg = NULL;
1432*be771a7bSCy Schubert     struct regional* region = qstate->env->scratch;
1433*be771a7bSCy Schubert     char b[260];
1434*be771a7bSCy Schubert     struct query_info qinfo;
1435*be771a7bSCy Schubert     struct iter_hints_stub* stub;
1436*be771a7bSCy Schubert     uint32_t timenow = *qstate->env->now;
1437*be771a7bSCy Schubert     int nolock = 0;
1438*be771a7bSCy Schubert 
1439*be771a7bSCy Schubert     regional_free_all(region);
1440*be771a7bSCy Schubert     qinfo.qname = (uint8_t*)nm;
1441*be771a7bSCy Schubert     qinfo.qname_len = nmlen;
1442*be771a7bSCy Schubert     qinfo.qtype = LDNS_RR_TYPE_A;
1443*be771a7bSCy Schubert     qinfo.qclass = LDNS_RR_CLASS_IN;
1444*be771a7bSCy Schubert 
1445*be771a7bSCy Schubert     while(1) {
1446*be771a7bSCy Schubert         dp = dns_cache_find_delegation(qstate->env, (uint8_t*)nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, timenow, 0, NULL, 0);
1447*be771a7bSCy Schubert         if(!dp)
1448*be771a7bSCy Schubert             return NULL;
1449*be771a7bSCy Schubert         if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
1450*be771a7bSCy Schubert                 qstate->env->cfg->do_ip4, qstate->env->cfg->do_ip6,
1451*be771a7bSCy Schubert                 qstate->env->cfg->do_nat64)) {
1452*be771a7bSCy Schubert             if (dname_is_root((uint8_t*)nm))
1453*be771a7bSCy Schubert                 return NULL;
1454*be771a7bSCy Schubert             nm = (char*)dp->name;
1455*be771a7bSCy Schubert             nmlen = dp->namelen;
1456*be771a7bSCy Schubert             dname_remove_label((uint8_t**)&nm, &nmlen);
1457*be771a7bSCy Schubert             dname_str((uint8_t*)nm, b);
1458*be771a7bSCy Schubert             continue;
1459*be771a7bSCy Schubert         }
1460*be771a7bSCy Schubert         stub = hints_lookup_stub(qstate->env->hints, qinfo.qname,
1461*be771a7bSCy Schubert             qinfo.qclass, dp, nolock);
1462*be771a7bSCy Schubert         if (stub) {
1463*be771a7bSCy Schubert             struct delegpt* stubdp = delegpt_copy(stub->dp, region);
1464*be771a7bSCy Schubert             lock_rw_unlock(&qstate->env->hints->lock);
1465*be771a7bSCy Schubert             return stubdp;
1466*be771a7bSCy Schubert         } else {
1467*be771a7bSCy Schubert             return dp;
1468*be771a7bSCy Schubert         }
1469*be771a7bSCy Schubert     }
1470*be771a7bSCy Schubert     return NULL;
1471*be771a7bSCy Schubert }
1472*be771a7bSCy Schubert %}
1473*be771a7bSCy Schubert 
1474*be771a7bSCy Schubert /* ************************************************************************************ *
1475*be771a7bSCy Schubert    Functions
1476*be771a7bSCy Schubert  * ************************************************************************************ */
1477*be771a7bSCy Schubert /******************************
1478*be771a7bSCy Schubert  * Various debugging functions *
1479*be771a7bSCy Schubert  ******************************/
1480*be771a7bSCy Schubert 
1481*be771a7bSCy Schubert /* rename the variadic functions because python does the formatting already*/
1482*be771a7bSCy Schubert %rename (unbound_log_info) log_info;
1483*be771a7bSCy Schubert %rename (unbound_log_err) log_err;
1484*be771a7bSCy Schubert %rename (unbound_log_warn) log_warn;
1485*be771a7bSCy Schubert %rename (unbound_verbose) verbose;
1486*be771a7bSCy Schubert /* provide functions that take one string as argument, so python can cook
1487*be771a7bSCy Schubert the string */
1488*be771a7bSCy Schubert %rename (log_info) pymod_log_info;
1489*be771a7bSCy Schubert %rename (log_warn) pymod_log_warn;
1490*be771a7bSCy Schubert %rename (log_err) pymod_log_err;
1491*be771a7bSCy Schubert %rename (verbose) pymod_verbose;
1492*be771a7bSCy Schubert 
1493*be771a7bSCy Schubert void verbose(enum verbosity_value level, const char* format, ...);
1494*be771a7bSCy Schubert void log_info(const char* format, ...);
1495*be771a7bSCy Schubert void log_err(const char* format, ...);
1496*be771a7bSCy Schubert void log_warn(const char* format, ...);
1497*be771a7bSCy Schubert void log_hex(const char* msg, void* data, size_t length);
1498*be771a7bSCy Schubert void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep);
1499*be771a7bSCy Schubert void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
1500*be771a7bSCy Schubert void regional_log_stats(struct regional *r);
1501*be771a7bSCy Schubert 
1502*be771a7bSCy Schubert /* the one argument string log functions */
1503*be771a7bSCy Schubert void pymod_log_info(const char* str);
1504*be771a7bSCy Schubert void pymod_log_err(const char* str);
1505*be771a7bSCy Schubert void pymod_log_warn(const char* str);
1506*be771a7bSCy Schubert void pymod_verbose(enum verbosity_value level, const char* str);
1507*be771a7bSCy Schubert %{
1508*be771a7bSCy Schubert void pymod_log_info(const char* str) { log_info("%s", str); }
1509*be771a7bSCy Schubert void pymod_log_err(const char* str) { log_err("%s", str); }
1510*be771a7bSCy Schubert void pymod_log_warn(const char* str) { log_warn("%s", str); }
1511*be771a7bSCy Schubert void pymod_verbose(enum verbosity_value level, const char* str) {
1512*be771a7bSCy Schubert         verbose(level, "%s", str); }
1513*be771a7bSCy Schubert %}
1514*be771a7bSCy Schubert 
1515*be771a7bSCy Schubert /***************************************************************************
1516*be771a7bSCy Schubert  * Free allocated memory from marked sources returning corresponding types *
1517*be771a7bSCy Schubert  ***************************************************************************/
1518*be771a7bSCy Schubert %typemap(newfree, noblock = 1) char * {
1519*be771a7bSCy Schubert   free($1);
1520*be771a7bSCy Schubert }
1521*be771a7bSCy Schubert 
1522*be771a7bSCy Schubert /***************************************************
1523*be771a7bSCy Schubert  * Mark as source returning newly allocated memory *
1524*be771a7bSCy Schubert  ***************************************************/
1525*be771a7bSCy Schubert %newobject sldns_wire2str_type;
1526*be771a7bSCy Schubert %newobject sldns_wire2str_class;
1527*be771a7bSCy Schubert 
1528*be771a7bSCy Schubert /******************
1529*be771a7bSCy Schubert  * LDNS functions *
1530*be771a7bSCy Schubert  ******************/
1531*be771a7bSCy Schubert char *sldns_wire2str_type(const uint16_t atype);
1532*be771a7bSCy Schubert char *sldns_wire2str_class(const uint16_t aclass);
1533*be771a7bSCy Schubert 
1534*be771a7bSCy Schubert /**********************************
1535*be771a7bSCy Schubert  * Functions from pythonmod_utils *
1536*be771a7bSCy Schubert  **********************************/
1537*be771a7bSCy Schubert int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
1538*be771a7bSCy Schubert void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
1539*be771a7bSCy Schubert 
1540*be771a7bSCy Schubert /*******************************
1541*be771a7bSCy Schubert  * Module conversion functions *
1542*be771a7bSCy Schubert  *******************************/
1543*be771a7bSCy Schubert const char* strextstate(enum module_ext_state s);
1544*be771a7bSCy Schubert const char* strmodulevent(enum module_ev e);
1545*be771a7bSCy Schubert 
1546*be771a7bSCy Schubert /**************************
1547*be771a7bSCy Schubert  * Edns related functions *
1548*be771a7bSCy Schubert  **************************/
1549*be771a7bSCy Schubert struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
1550*be771a7bSCy Schubert int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
1551*be771a7bSCy Schubert     int no_aggregation, struct module_env* env);
1552*be771a7bSCy Schubert 
1553*be771a7bSCy Schubert %pythoncode %{
1554*be771a7bSCy Schubert     def register_edns_option(env, code, bypass_cache_stage=False,
1555*be771a7bSCy Schubert                              no_aggregation=False):
1556*be771a7bSCy Schubert         """Wrapper function to provide keyword attributes."""
1557*be771a7bSCy Schubert         return edns_register_option(code, bypass_cache_stage,
1558*be771a7bSCy Schubert                                     no_aggregation, env)
1559*be771a7bSCy Schubert %}
1560*be771a7bSCy Schubert 
1561*be771a7bSCy Schubert /******************************
1562*be771a7bSCy Schubert  * Callback related functions *
1563*be771a7bSCy Schubert  ******************************/
1564*be771a7bSCy Schubert /* typemap to check if argument is callable */
1565*be771a7bSCy Schubert %typemap(in) PyObject *py_cb {
1566*be771a7bSCy Schubert   if (!PyCallable_Check($input)) {
1567*be771a7bSCy Schubert       SWIG_exception_fail(SWIG_TypeError, "Need a callable object!");
1568*be771a7bSCy Schubert       return NULL;
1569*be771a7bSCy Schubert   }
1570*be771a7bSCy Schubert   $1 = $input;
1571*be771a7bSCy Schubert }
1572*be771a7bSCy Schubert /* typemap to get content/size from a bytearray  */
1573*be771a7bSCy Schubert %typemap(in) (size_t len, uint8_t* py_bytearray_data) {
1574*be771a7bSCy Schubert     if (!PyByteArray_CheckExact($input)) {
1575*be771a7bSCy Schubert         SWIG_exception_fail(SWIG_TypeError, "Expected bytearray!");
1576*be771a7bSCy Schubert         return NULL;
1577*be771a7bSCy Schubert     }
1578*be771a7bSCy Schubert     $2 = (void*)PyByteArray_AsString($input);
1579*be771a7bSCy Schubert     $1 = PyByteArray_Size($input);
1580*be771a7bSCy Schubert }
1581*be771a7bSCy Schubert 
1582*be771a7bSCy Schubert int edns_opt_list_remove(struct edns_option** list, uint16_t code);
1583*be771a7bSCy Schubert int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
1584*be771a7bSCy Schubert     uint8_t* py_bytearray_data, struct regional* region);
1585*be771a7bSCy Schubert 
1586*be771a7bSCy Schubert %{
1587*be771a7bSCy Schubert     /* This function is called by unbound in order to call the python
1588*be771a7bSCy Schubert      * callback function. */
1589*be771a7bSCy Schubert     int python_inplace_cb_reply_generic(struct query_info* qinfo,
1590*be771a7bSCy Schubert         struct module_qstate* qstate, struct reply_info* rep, int rcode,
1591*be771a7bSCy Schubert         struct edns_data* edns, struct edns_option** opt_list_out,
1592*be771a7bSCy Schubert         struct comm_reply* repinfo, struct regional* region,
1593*be771a7bSCy Schubert         struct timeval* start_time, int id, void* python_callback)
1594*be771a7bSCy Schubert     {
1595*be771a7bSCy Schubert         PyObject *func = NULL, *py_edns = NULL, *py_qstate = NULL;
1596*be771a7bSCy Schubert         PyObject *py_opt_list_out = NULL, *py_qinfo = NULL;
1597*be771a7bSCy Schubert         PyObject *py_rep = NULL, *py_repinfo = NULL, *py_region = NULL;
1598*be771a7bSCy Schubert         PyObject *py_args = NULL, *py_kwargs = NULL, *result = NULL;
1599*be771a7bSCy Schubert         int res = 0;
1600*be771a7bSCy Schubert         double py_start_time = ((double)start_time->tv_sec) + ((double)start_time->tv_usec) / 1.0e6;
1601*be771a7bSCy Schubert 
1602*be771a7bSCy Schubert         PyGILState_STATE gstate = PyGILState_Ensure();
1603*be771a7bSCy Schubert 
1604*be771a7bSCy Schubert         func = (PyObject *) python_callback;
1605*be771a7bSCy Schubert         py_edns = SWIG_NewPointerObj((void*) edns, SWIGTYPE_p_edns_data, 0);
1606*be771a7bSCy Schubert         py_qstate = SWIG_NewPointerObj((void*) qstate,
1607*be771a7bSCy Schubert             SWIGTYPE_p_module_qstate, 0);
1608*be771a7bSCy Schubert         py_opt_list_out = SWIG_NewPointerObj((void*) opt_list_out,
1609*be771a7bSCy Schubert             SWIGTYPE_p_p_edns_option, 0);
1610*be771a7bSCy Schubert         py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
1611*be771a7bSCy Schubert         py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_info, 0);
1612*be771a7bSCy Schubert         py_repinfo = SWIG_NewPointerObj((void*) repinfo, SWIGTYPE_p_comm_reply, 0);
1613*be771a7bSCy Schubert         py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
1614*be771a7bSCy Schubert         if(!(py_qinfo && py_qstate && py_rep && py_edns && py_opt_list_out
1615*be771a7bSCy Schubert                 && py_region && py_repinfo)) {
1616*be771a7bSCy Schubert                 log_err("pythonmod: swig pointer failure in python_inplace_cb_reply_generic");
1617*be771a7bSCy Schubert                 goto out;
1618*be771a7bSCy Schubert         }
1619*be771a7bSCy Schubert         py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
1620*be771a7bSCy Schubert                 rcode, py_edns, py_opt_list_out, py_region);
1621*be771a7bSCy Schubert         py_kwargs = Py_BuildValue("{s:O,s:d}", "repinfo", py_repinfo, "start_time",
1622*be771a7bSCy Schubert                 py_start_time);
1623*be771a7bSCy Schubert         if(!(py_args && py_kwargs)) {
1624*be771a7bSCy Schubert                 log_err("pythonmod: BuildValue failure in python_inplace_cb_reply_generic");
1625*be771a7bSCy Schubert                 goto out;
1626*be771a7bSCy Schubert         }
1627*be771a7bSCy Schubert         result = PyObject_Call(func, py_args, py_kwargs);
1628*be771a7bSCy Schubert         if (result) {
1629*be771a7bSCy Schubert             res = PyInt_AsLong(result);
1630*be771a7bSCy Schubert         }
1631*be771a7bSCy Schubert out:
1632*be771a7bSCy Schubert         Py_XDECREF(py_edns);
1633*be771a7bSCy Schubert         Py_XDECREF(py_qstate);
1634*be771a7bSCy Schubert         Py_XDECREF(py_opt_list_out);
1635*be771a7bSCy Schubert         Py_XDECREF(py_qinfo);
1636*be771a7bSCy Schubert         Py_XDECREF(py_rep);
1637*be771a7bSCy Schubert         Py_XDECREF(py_repinfo);
1638*be771a7bSCy Schubert         Py_XDECREF(py_region);
1639*be771a7bSCy Schubert         Py_XDECREF(py_args);
1640*be771a7bSCy Schubert         Py_XDECREF(py_kwargs);
1641*be771a7bSCy Schubert         Py_XDECREF(result);
1642*be771a7bSCy Schubert         PyGILState_Release(gstate);
1643*be771a7bSCy Schubert         return res;
1644*be771a7bSCy Schubert     }
1645*be771a7bSCy Schubert 
1646*be771a7bSCy Schubert     /* register a callback */
1647*be771a7bSCy Schubert     static int python_inplace_cb_register(enum inplace_cb_list_type type,
1648*be771a7bSCy Schubert         PyObject* py_cb, struct module_env* env, int id)
1649*be771a7bSCy Schubert     {
1650*be771a7bSCy Schubert         int ret = inplace_cb_register(python_inplace_cb_reply_generic,
1651*be771a7bSCy Schubert                 type, (void*) py_cb, env, id);
1652*be771a7bSCy Schubert         if (ret) Py_INCREF(py_cb);
1653*be771a7bSCy Schubert         return ret;
1654*be771a7bSCy Schubert     }
1655*be771a7bSCy Schubert 
1656*be771a7bSCy Schubert     /* Swig implementations for Python */
1657*be771a7bSCy Schubert     static int register_inplace_cb_reply(PyObject* py_cb,
1658*be771a7bSCy Schubert         struct module_env* env, int id)
1659*be771a7bSCy Schubert     {
1660*be771a7bSCy Schubert         return python_inplace_cb_register(inplace_cb_reply, py_cb, env, id);
1661*be771a7bSCy Schubert     }
1662*be771a7bSCy Schubert     static int register_inplace_cb_reply_cache(PyObject* py_cb,
1663*be771a7bSCy Schubert         struct module_env* env, int id)
1664*be771a7bSCy Schubert     {
1665*be771a7bSCy Schubert         return python_inplace_cb_register(inplace_cb_reply_cache, py_cb, env, id);
1666*be771a7bSCy Schubert     }
1667*be771a7bSCy Schubert     static int register_inplace_cb_reply_local(PyObject* py_cb,
1668*be771a7bSCy Schubert         struct module_env* env, int id)
1669*be771a7bSCy Schubert     {
1670*be771a7bSCy Schubert         return python_inplace_cb_register(inplace_cb_reply_local, py_cb, env, id);
1671*be771a7bSCy Schubert     }
1672*be771a7bSCy Schubert     static int register_inplace_cb_reply_servfail(PyObject* py_cb,
1673*be771a7bSCy Schubert         struct module_env* env, int id)
1674*be771a7bSCy Schubert     {
1675*be771a7bSCy Schubert         return python_inplace_cb_register(inplace_cb_reply_servfail,
1676*be771a7bSCy Schubert                 py_cb, env, id);
1677*be771a7bSCy Schubert     }
1678*be771a7bSCy Schubert 
1679*be771a7bSCy Schubert     int python_inplace_cb_query_generic(
1680*be771a7bSCy Schubert         struct query_info* qinfo, uint16_t flags, struct module_qstate* qstate,
1681*be771a7bSCy Schubert         struct sockaddr_storage* addr, socklen_t addrlen,
1682*be771a7bSCy Schubert         uint8_t* zone, size_t zonelen, struct regional* region, int id,
1683*be771a7bSCy Schubert         void* python_callback)
1684*be771a7bSCy Schubert     {
1685*be771a7bSCy Schubert         int res = 0;
1686*be771a7bSCy Schubert         PyObject *func = python_callback;
1687*be771a7bSCy Schubert         PyObject *py_args = NULL, *py_kwargs = NULL, *result = NULL;
1688*be771a7bSCy Schubert         PyObject *py_qinfo = NULL;
1689*be771a7bSCy Schubert         PyObject *py_qstate = NULL;
1690*be771a7bSCy Schubert         PyObject *py_addr = NULL;
1691*be771a7bSCy Schubert         PyObject *py_zone = NULL;
1692*be771a7bSCy Schubert         PyObject *py_region = NULL;
1693*be771a7bSCy Schubert 
1694*be771a7bSCy Schubert         PyGILState_STATE gstate = PyGILState_Ensure();
1695*be771a7bSCy Schubert 
1696*be771a7bSCy Schubert         py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
1697*be771a7bSCy Schubert         py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
1698*be771a7bSCy Schubert         py_addr = SWIG_NewPointerObj((void *) addr, SWIGTYPE_p_sockaddr_storage, 0);
1699*be771a7bSCy Schubert         py_zone = PyBytes_FromStringAndSize((const char *)zone, zonelen);
1700*be771a7bSCy Schubert         py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
1701*be771a7bSCy Schubert         if(!(py_qinfo && py_qstate && py_addr && py_zone && py_region)) {
1702*be771a7bSCy Schubert                 log_err("pythonmod: swig pointer failure in python_inplace_cb_query_generic");
1703*be771a7bSCy Schubert                 goto out;
1704*be771a7bSCy Schubert         }
1705*be771a7bSCy Schubert         py_args = Py_BuildValue("(OiOOOO)", py_qinfo, flags, py_qstate, py_addr, py_zone, py_region);
1706*be771a7bSCy Schubert         py_kwargs = Py_BuildValue("{}");
1707*be771a7bSCy Schubert         if(!(py_args && py_kwargs)) {
1708*be771a7bSCy Schubert                 log_err("pythonmod: BuildValue failure in python_inplace_cb_query_generic");
1709*be771a7bSCy Schubert                 goto out;
1710*be771a7bSCy Schubert         }
1711*be771a7bSCy Schubert         result = PyObject_Call(func, py_args, py_kwargs);
1712*be771a7bSCy Schubert         if (result) {
1713*be771a7bSCy Schubert             res = PyInt_AsLong(result);
1714*be771a7bSCy Schubert         }
1715*be771a7bSCy Schubert out:
1716*be771a7bSCy Schubert         Py_XDECREF(py_qinfo);
1717*be771a7bSCy Schubert         Py_XDECREF(py_qstate);
1718*be771a7bSCy Schubert         Py_XDECREF(py_addr);
1719*be771a7bSCy Schubert         Py_XDECREF(py_zone);
1720*be771a7bSCy Schubert         Py_XDECREF(py_region);
1721*be771a7bSCy Schubert 
1722*be771a7bSCy Schubert         Py_XDECREF(py_args);
1723*be771a7bSCy Schubert         Py_XDECREF(py_kwargs);
1724*be771a7bSCy Schubert         Py_XDECREF(result);
1725*be771a7bSCy Schubert 
1726*be771a7bSCy Schubert         PyGILState_Release(gstate);
1727*be771a7bSCy Schubert 
1728*be771a7bSCy Schubert         return res;
1729*be771a7bSCy Schubert     }
1730*be771a7bSCy Schubert 
1731*be771a7bSCy Schubert     static int register_inplace_cb_query(PyObject* py_cb,
1732*be771a7bSCy Schubert         struct module_env* env, int id)
1733*be771a7bSCy Schubert     {
1734*be771a7bSCy Schubert         int ret = inplace_cb_register(python_inplace_cb_query_generic,
1735*be771a7bSCy Schubert                 inplace_cb_query, (void*) py_cb, env, id);
1736*be771a7bSCy Schubert         if (ret) Py_INCREF(py_cb);
1737*be771a7bSCy Schubert         return ret;
1738*be771a7bSCy Schubert     }
1739*be771a7bSCy Schubert 
1740*be771a7bSCy Schubert     int python_inplace_cb_query_response(struct module_qstate* qstate,
1741*be771a7bSCy Schubert         struct dns_msg* response, int id, void* python_callback)
1742*be771a7bSCy Schubert     {
1743*be771a7bSCy Schubert         int res = 0;
1744*be771a7bSCy Schubert         PyObject *func = python_callback;
1745*be771a7bSCy Schubert         PyObject *py_qstate = NULL;
1746*be771a7bSCy Schubert         PyObject *py_response = NULL;
1747*be771a7bSCy Schubert         PyObject *py_args = NULL;
1748*be771a7bSCy Schubert         PyObject *py_kwargs = NULL;
1749*be771a7bSCy Schubert         PyObject *result = NULL;
1750*be771a7bSCy Schubert 
1751*be771a7bSCy Schubert         PyGILState_STATE gstate = PyGILState_Ensure();
1752*be771a7bSCy Schubert 
1753*be771a7bSCy Schubert         py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
1754*be771a7bSCy Schubert         py_response = SWIG_NewPointerObj((void*) response, SWIGTYPE_p_dns_msg, 0);
1755*be771a7bSCy Schubert         if(!(py_qstate && py_response)) {
1756*be771a7bSCy Schubert                 log_err("pythonmod: swig pointer failure in python_inplace_cb_query_response");
1757*be771a7bSCy Schubert                 goto out;
1758*be771a7bSCy Schubert         }
1759*be771a7bSCy Schubert         py_args = Py_BuildValue("(OO)", py_qstate, py_response);
1760*be771a7bSCy Schubert         py_kwargs = Py_BuildValue("{}");
1761*be771a7bSCy Schubert         if(!(py_args && py_kwargs)) {
1762*be771a7bSCy Schubert                 log_err("pythonmod: BuildValue failure in python_inplace_cb_query_response");
1763*be771a7bSCy Schubert                 goto out;
1764*be771a7bSCy Schubert         }
1765*be771a7bSCy Schubert         result = PyObject_Call(func, py_args, py_kwargs);
1766*be771a7bSCy Schubert         if (result) {
1767*be771a7bSCy Schubert             res = PyInt_AsLong(result);
1768*be771a7bSCy Schubert         }
1769*be771a7bSCy Schubert out:
1770*be771a7bSCy Schubert         Py_XDECREF(py_qstate);
1771*be771a7bSCy Schubert         Py_XDECREF(py_response);
1772*be771a7bSCy Schubert 
1773*be771a7bSCy Schubert         Py_XDECREF(py_args);
1774*be771a7bSCy Schubert         Py_XDECREF(py_kwargs);
1775*be771a7bSCy Schubert         Py_XDECREF(result);
1776*be771a7bSCy Schubert 
1777*be771a7bSCy Schubert         PyGILState_Release(gstate);
1778*be771a7bSCy Schubert 
1779*be771a7bSCy Schubert         return res;
1780*be771a7bSCy Schubert     }
1781*be771a7bSCy Schubert 
1782*be771a7bSCy Schubert     static int register_inplace_cb_query_response(PyObject* py_cb,
1783*be771a7bSCy Schubert         struct module_env* env, int id)
1784*be771a7bSCy Schubert     {
1785*be771a7bSCy Schubert         int ret = inplace_cb_register(python_inplace_cb_query_response,
1786*be771a7bSCy Schubert             inplace_cb_query_response, (void*) py_cb, env, id);
1787*be771a7bSCy Schubert         if (ret) Py_INCREF(py_cb);
1788*be771a7bSCy Schubert         return ret;
1789*be771a7bSCy Schubert     }
1790*be771a7bSCy Schubert 
1791*be771a7bSCy Schubert     int python_inplace_cb_edns_back_parsed_call(struct module_qstate* qstate,
1792*be771a7bSCy Schubert         int id, void* python_callback)
1793*be771a7bSCy Schubert     {
1794*be771a7bSCy Schubert         int res = 0;
1795*be771a7bSCy Schubert         PyObject *func = python_callback;
1796*be771a7bSCy Schubert         PyObject *py_qstate = NULL;
1797*be771a7bSCy Schubert         PyObject *py_args = NULL;
1798*be771a7bSCy Schubert         PyObject *py_kwargs = NULL;
1799*be771a7bSCy Schubert         PyObject *result = NULL;
1800*be771a7bSCy Schubert 
1801*be771a7bSCy Schubert         PyGILState_STATE gstate = PyGILState_Ensure();
1802*be771a7bSCy Schubert 
1803*be771a7bSCy Schubert         py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
1804*be771a7bSCy Schubert         if(!py_qstate) {
1805*be771a7bSCy Schubert                 log_err("pythonmod: swig pointer failure in python_inplace_cb_edns_back_parsed_call");
1806*be771a7bSCy Schubert                 goto out;
1807*be771a7bSCy Schubert         }
1808*be771a7bSCy Schubert         py_args = Py_BuildValue("(O)", py_qstate);
1809*be771a7bSCy Schubert         py_kwargs = Py_BuildValue("{}");
1810*be771a7bSCy Schubert         if(!(py_args && py_kwargs)) {
1811*be771a7bSCy Schubert                 log_err("pythonmod: BuildValue failure in python_inplace_cb_edns_back_parsed_call");
1812*be771a7bSCy Schubert                 goto out;
1813*be771a7bSCy Schubert         }
1814*be771a7bSCy Schubert         result = PyObject_Call(func, py_args, py_kwargs);
1815*be771a7bSCy Schubert         if (result) {
1816*be771a7bSCy Schubert             res = PyInt_AsLong(result);
1817*be771a7bSCy Schubert         }
1818*be771a7bSCy Schubert out:
1819*be771a7bSCy Schubert         Py_XDECREF(py_qstate);
1820*be771a7bSCy Schubert 
1821*be771a7bSCy Schubert         Py_XDECREF(py_args);
1822*be771a7bSCy Schubert         Py_XDECREF(py_kwargs);
1823*be771a7bSCy Schubert         Py_XDECREF(result);
1824*be771a7bSCy Schubert 
1825*be771a7bSCy Schubert         PyGILState_Release(gstate);
1826*be771a7bSCy Schubert 
1827*be771a7bSCy Schubert         return res;
1828*be771a7bSCy Schubert     }
1829*be771a7bSCy Schubert 
1830*be771a7bSCy Schubert     static int register_inplace_cb_edns_back_parsed_call(PyObject* py_cb,
1831*be771a7bSCy Schubert         struct module_env* env, int id)
1832*be771a7bSCy Schubert     {
1833*be771a7bSCy Schubert         int ret = inplace_cb_register(python_inplace_cb_edns_back_parsed_call,
1834*be771a7bSCy Schubert             inplace_cb_edns_back_parsed, (void*) py_cb, env, id);
1835*be771a7bSCy Schubert         if (ret) Py_INCREF(py_cb);
1836*be771a7bSCy Schubert         return ret;
1837*be771a7bSCy Schubert     }
1838*be771a7bSCy Schubert %}
1839*be771a7bSCy Schubert /* C declarations */
1840*be771a7bSCy Schubert int inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
1841*be771a7bSCy Schubert     struct module_env* env, int id);
1842*be771a7bSCy Schubert 
1843*be771a7bSCy Schubert /* Swig declarations */
1844*be771a7bSCy Schubert static int register_inplace_cb_reply(PyObject* py_cb,
1845*be771a7bSCy Schubert     struct module_env* env, int id);
1846*be771a7bSCy Schubert static int register_inplace_cb_reply_cache(PyObject* py_cb,
1847*be771a7bSCy Schubert     struct module_env* env, int id);
1848*be771a7bSCy Schubert static int register_inplace_cb_reply_local(PyObject* py_cb,
1849*be771a7bSCy Schubert     struct module_env* env, int id);
1850*be771a7bSCy Schubert static int register_inplace_cb_reply_servfail(PyObject* py_cb,
1851*be771a7bSCy Schubert     struct module_env* env, int id);
1852*be771a7bSCy Schubert static int register_inplace_cb_query(PyObject *py_cb,
1853*be771a7bSCy Schubert     struct module_env* env, int id);
1854*be771a7bSCy Schubert static int register_inplace_cb_query_response(PyObject *py_cb,
1855*be771a7bSCy Schubert     struct module_env* env, int id);
1856*be771a7bSCy Schubert static int register_inplace_cb_edns_back_parsed_call(PyObject *py_cb,
1857*be771a7bSCy Schubert     struct module_env* env, int id);
1858