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