xref: /netbsd-src/external/bsd/unbound/dist/pythonmod/interface.i (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /*
2  * interface.i: unbound python module
3  */
4 
5 %module unboundmodule
6 %{
7 /**
8  * \file
9  * This is the interface between the unbound server and a python module
10  * called to perform operations on queries.
11  */
12    #include <sys/types.h>
13    #include <sys/socket.h>
14    #include <netinet/in.h>
15    #include <arpa/inet.h>
16    #include <stdarg.h>
17    #include "config.h"
18    #include "util/log.h"
19    #include "util/module.h"
20    #include "util/netevent.h"
21    #include "util/regional.h"
22    #include "util/config_file.h"
23    #include "util/data/msgreply.h"
24    #include "util/data/packed_rrset.h"
25    #include "util/data/dname.h"
26    #include "util/storage/lruhash.h"
27    #include "services/cache/dns.h"
28    #include "services/mesh.h"
29    #include "iterator/iter_delegpt.h"
30    #include "iterator/iter_hints.h"
31    #include "iterator/iter_utils.h"
32    #include "sldns/wire2str.h"
33    #include "sldns/str2wire.h"
34    #include "sldns/pkthdr.h"
35 %}
36 
37 %include "stdint.i" // uint_16_t can be known type now
38 
39 %inline %{
40    //converts [len][data][len][data][0] string to a List of labels (PyBytes)
41    PyObject* GetNameAsLabelList(const char* name, int len) {
42      PyObject* list;
43      int cnt=0, i;
44 
45      i = 0;
46      while (i < len) {
47         i += name[i] + 1;
48         cnt++;
49      }
50 
51      list = PyList_New(cnt);
52      i = 0; cnt = 0;
53      while (i < len) {
54         PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i]));
55         i += name[i] + 1;
56         cnt++;
57      }
58      return list;
59    }
60 %}
61 
62 /* ************************************************************************************ *
63    Structure query_info
64  * ************************************************************************************ */
65 /* Query info */
66 %ignore query_info::qname;
67 %ignore query_info::qname_len;
68 
69 
70 struct query_info {
71    %immutable;
72    char* qname;
73    size_t qname_len;
74    uint16_t qtype;
75    uint16_t qclass;
76    %mutable;
77 };
78 
79 %inline %{
80    enum enum_rr_class  {
81       RR_CLASS_IN = 1,
82       RR_CLASS_CH = 3,
83       RR_CLASS_HS = 4,
84       RR_CLASS_NONE = 254,
85       RR_CLASS_ANY = 255,
86    };
87 
88    enum enum_rr_type {
89       RR_TYPE_A = 1,
90       RR_TYPE_NS = 2,
91       RR_TYPE_MD = 3,
92       RR_TYPE_MF = 4,
93       RR_TYPE_CNAME = 5,
94       RR_TYPE_SOA = 6,
95       RR_TYPE_MB = 7,
96       RR_TYPE_MG = 8,
97       RR_TYPE_MR = 9,
98       RR_TYPE_NULL = 10,
99       RR_TYPE_WKS = 11,
100       RR_TYPE_PTR = 12,
101       RR_TYPE_HINFO = 13,
102       RR_TYPE_MINFO = 14,
103       RR_TYPE_MX = 15,
104       RR_TYPE_TXT = 16,
105       RR_TYPE_RP = 17,
106       RR_TYPE_AFSDB = 18,
107       RR_TYPE_X25 = 19,
108       RR_TYPE_ISDN = 20,
109       RR_TYPE_RT = 21,
110       RR_TYPE_NSAP = 22,
111       RR_TYPE_NSAP_PTR = 23,
112       RR_TYPE_SIG = 24,
113       RR_TYPE_KEY = 25,
114       RR_TYPE_PX = 26,
115       RR_TYPE_GPOS = 27,
116       RR_TYPE_AAAA = 28,
117       RR_TYPE_LOC = 29,
118       RR_TYPE_NXT = 30,
119       RR_TYPE_EID = 31,
120       RR_TYPE_NIMLOC = 32,
121       RR_TYPE_SRV = 33,
122       RR_TYPE_ATMA = 34,
123       RR_TYPE_NAPTR = 35,
124       RR_TYPE_KX = 36,
125       RR_TYPE_CERT = 37,
126       RR_TYPE_A6 = 38,
127       RR_TYPE_DNAME = 39,
128       RR_TYPE_SINK = 40,
129       RR_TYPE_OPT = 41,
130       RR_TYPE_APL = 42,
131       RR_TYPE_DS = 43,
132       RR_TYPE_SSHFP = 44,
133       RR_TYPE_IPSECKEY = 45,
134       RR_TYPE_RRSIG = 46,
135       RR_TYPE_NSEC = 47,
136       RR_TYPE_DNSKEY = 48,
137       RR_TYPE_DHCID = 49,
138       RR_TYPE_NSEC3 = 50,
139       RR_TYPE_NSEC3PARAMS = 51,
140       RR_TYPE_UINFO = 100,
141       RR_TYPE_UID = 101,
142       RR_TYPE_GID = 102,
143       RR_TYPE_UNSPEC = 103,
144       RR_TYPE_TSIG = 250,
145       RR_TYPE_IXFR = 251,
146       RR_TYPE_AXFR = 252,
147       RR_TYPE_MAILB = 253,
148       RR_TYPE_MAILA = 254,
149       RR_TYPE_ANY = 255,
150       RR_TYPE_DLV = 32769,
151    };
152 
153    PyObject* _get_qname(struct query_info* q) {
154       return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
155    }
156 
157    PyObject* _get_qname_components(struct query_info* q) {
158       return GetNameAsLabelList((const char*)q->qname, q->qname_len);
159    }
160 %}
161 
162 %inline %{
163    PyObject* dnameAsStr(const char* dname) {
164        char buf[LDNS_MAX_DOMAINLEN+1];
165        buf[0] = '\0';
166        dname_str((uint8_t*)dname, buf);
167        return PyBytes_FromString(buf);
168    }
169 %}
170 
171 %extend query_info {
172    %pythoncode %{
173         def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
174         __swig_getmethods__["qtype_str"] = _get_qtype_str
175         if _newclass:qtype_str = _swig_property(_get_qtype_str)
176 
177         def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
178         __swig_getmethods__["qclass_str"] = _get_qclass_str
179         if _newclass:qclass_str = _swig_property(_get_qclass_str)
180 
181         __swig_getmethods__["qname"] = _unboundmodule._get_qname
182         if _newclass:qname = _swig_property(_unboundmodule._get_qname)
183 
184         __swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
185         if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
186 
187         def _get_qname_str(self): return dnameAsStr(self.qname)
188         __swig_getmethods__["qname_str"] = _get_qname_str
189         if _newclass:qname_str = _swig_property(_get_qname_str)
190    %}
191 }
192 
193 /* ************************************************************************************ *
194    Structure packed_rrset_key
195  * ************************************************************************************ */
196 %ignore packed_rrset_key::dname;
197 %ignore packed_rrset_key::dname_len;
198 
199 /* RRsets */
200 struct packed_rrset_key {
201    %immutable;
202    char*    dname;
203    size_t   dname_len;
204    uint32_t flags;
205    uint16_t type;  //rrset type in network format
206    uint16_t rrset_class; //rrset class in network format
207    %mutable;
208 };
209 
210 //This subroutine converts values between the host and network byte order.
211 //Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order.
212 uint16_t ntohs(uint16_t netshort);
213 
214 %inline %{
215    PyObject* _get_dname(struct packed_rrset_key* k) {
216       return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
217    }
218    PyObject* _get_dname_components(struct packed_rrset_key* k) {
219       return GetNameAsLabelList((char*)k->dname, k->dname_len);
220    }
221 %}
222 
223 %extend packed_rrset_key {
224    %pythoncode %{
225         def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
226         __swig_getmethods__["type_str"] = _get_type_str
227         if _newclass:type_str = _swig_property(_get_type_str)
228 
229         def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
230         __swig_getmethods__["rrset_class_str"] = _get_class_str
231         if _newclass:rrset_class_str = _swig_property(_get_class_str)
232 
233         __swig_getmethods__["dname"] = _unboundmodule._get_dname
234         if _newclass:dname = _swig_property(_unboundmodule._get_dname)
235 
236         __swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components
237         if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components)
238 
239         def _get_dname_str(self): return dnameAsStr(self.dname)
240         __swig_getmethods__["dname_str"] = _get_dname_str
241         if _newclass:dname_str = _swig_property(_get_dname_str)
242    %}
243 }
244 
245 #if defined(SWIGWORDSIZE64)
246 typedef long int                rrset_id_t;
247 #else
248 typedef long long int           rrset_id_t;
249 #endif
250 
251 struct ub_packed_rrset_key {
252    struct lruhash_entry entry;
253    rrset_id_t id;
254    struct packed_rrset_key rk;
255 };
256 
257 struct lruhash_entry {
258   lock_rw_t lock;
259   struct lruhash_entry* overflow_next;
260   struct lruhash_entry* lru_next;
261   struct lruhash_entry* lru_prev;
262   hashvalue_t hash;
263   void* key;
264   struct packed_rrset_data* data;
265 };
266 
267 %ignore packed_rrset_data::rr_len;
268 %ignore packed_rrset_data::rr_ttl;
269 %ignore packed_rrset_data::rr_data;
270 
271 struct packed_rrset_data {
272   uint32_t ttl; //TTL (in seconds like time())
273 
274   size_t count; //number of rrs
275   size_t rrsig_count; //number of rrsigs
276 
277   enum rrset_trust trust;
278   enum sec_status security;
279 
280   size_t* rr_len;   //length of every rr's rdata
281   uint32_t *rr_ttl; //ttl of every rr
282   uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat.
283 };
284 
285 %pythoncode %{
286     class RRSetData_RRLen:
287         def __init__(self, obj): self.obj = obj
288         def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index)
289         def __len__(self): return obj.count + obj.rrsig_count
290     class RRSetData_RRTTL:
291         def __init__(self, obj): self.obj = obj
292         def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index)
293         def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value)
294         def __len__(self): return obj.count + obj.rrsig_count
295     class RRSetData_RRData:
296         def __init__(self, obj): self.obj = obj
297         def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index)
298         def __len__(self): return obj.count + obj.rrsig_count
299 %}
300 
301 %inline %{
302    PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
303      if ((d != NULL) && (idx >= 0) &&
304              ((size_t)idx < (d->count+d->rrsig_count)))
305         return PyInt_FromLong(d->rr_len[idx]);
306      return Py_None;
307    }
308    void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
309    {
310      if ((d != NULL) && (idx >= 0) &&
311              ((size_t)idx < (d->count+d->rrsig_count)))
312         d->rr_ttl[idx] = ttl;
313    }
314    PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
315      if ((d != NULL) && (idx >= 0) &&
316              ((size_t)idx < (d->count+d->rrsig_count)))
317         return PyInt_FromLong(d->rr_ttl[idx]);
318      return Py_None;
319    }
320    PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
321      if ((d != NULL) && (idx >= 0) &&
322              ((size_t)idx < (d->count+d->rrsig_count)))
323         return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
324                 d->rr_len[idx]);
325      return Py_None;
326    }
327 %}
328 
329 %extend packed_rrset_data {
330    %pythoncode %{
331         def _get_data_rr_len(self): return RRSetData_RRLen(self)
332         __swig_getmethods__["rr_len"] = _get_data_rr_len
333         if _newclass:rr_len = _swig_property(_get_data_rr_len)
334         def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
335         __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
336         if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
337         def _get_data_rr_data(self): return RRSetData_RRData(self)
338         __swig_getmethods__["rr_data"] = _get_data_rr_data
339         if _newclass:rr_len = _swig_property(_get_data_rr_data)
340    %}
341 }
342 
343 /* ************************************************************************************ *
344    Structure reply_info
345  * ************************************************************************************ */
346 /* Messages */
347 %ignore reply_info::rrsets;
348 %ignore reply_info::ref;
349 
350 struct reply_info {
351    uint16_t flags;
352    uint16_t qdcount;
353    uint32_t ttl;
354    uint32_t prefetch_ttl;
355 
356    uint16_t authoritative;
357    enum sec_status security;
358 
359    size_t an_numrrsets;
360    size_t ns_numrrsets;
361    size_t ar_numrrsets;
362    size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets
363 
364    struct ub_packed_rrset_key** rrsets;
365    struct rrset_ref ref[1]; //?
366 };
367 
368 struct rrset_ref {
369    struct ub_packed_rrset_key* key;
370    rrset_id_t id;
371 };
372 
373 struct dns_msg {
374    struct query_info qinfo;
375    struct reply_info *rep;
376 };
377 
378 %pythoncode %{
379     class ReplyInfo_RRSet:
380         def __init__(self, obj): self.obj = obj
381         def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index)
382         def __len__(self): return obj.rrset_count
383 
384     class ReplyInfo_Ref:
385         def __init__(self, obj): self.obj = obj
386         def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index)
387         def __len__(self): return obj.rrset_count
388 %}
389 
390 %inline %{
391    struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
392      if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count))
393         return r->rrsets[idx];
394      return NULL;
395    }
396 
397    struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
398      if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
399 //printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key);
400              return &(r->ref[idx]);
401 //        return &(r->ref[idx]);
402      }
403 //printf("_rrset_ref_get: NULL\n");
404      return NULL;
405    }
406 %}
407 
408 %extend reply_info {
409    %pythoncode %{
410         def _rrset_ref_get(self): return ReplyInfo_Ref(self)
411         __swig_getmethods__["ref"] = _rrset_ref_get
412         if _newclass:ref = _swig_property(_rrset_ref_get)
413 
414         def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
415         __swig_getmethods__["rrsets"] = _rrset_rrsets_get
416         if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
417    %}
418 }
419 
420 /* ************************************************************************************ *
421    Structure mesh_state
422  * ************************************************************************************ */
423 struct mesh_state {
424    struct mesh_reply* reply_list;
425 };
426 
427 struct mesh_reply {
428    struct mesh_reply* next;
429    struct comm_reply query_reply;
430 };
431 
432 struct comm_reply {
433 
434 };
435 
436 %inline %{
437 
438   PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
439      char dest[64];
440      reply_addr2str(reply, dest, 64);
441      if (dest[0] == 0)
442         return Py_None;
443      return PyBytes_FromString(dest);
444   }
445 
446   PyObject* _comm_reply_family_get(struct comm_reply* reply) {
447 
448         int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
449 
450         switch(af) {
451            case AF_INET: return PyBytes_FromString("ip4");
452            case AF_INET6: return PyBytes_FromString("ip6");
453            case AF_UNIX: return PyBytes_FromString("unix");
454         }
455 
456         return Py_None;
457   }
458 
459   PyObject* _comm_reply_port_get(struct comm_reply* reply) {
460      uint16_t port;
461      port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
462      return PyInt_FromLong(port);
463   }
464 
465 %}
466 
467 %extend comm_reply {
468    %pythoncode %{
469         def _addr_get(self): return _comm_reply_addr_get(self)
470         __swig_getmethods__["addr"] = _addr_get
471         if _newclass:addr = _swig_property(_addr_get)
472 
473         def _port_get(self): return _comm_reply_port_get(self)
474         __swig_getmethods__["port"] = _port_get
475         if _newclass:port = _swig_property(_port_get)
476 
477         def _family_get(self): return _comm_reply_family_get(self)
478         __swig_getmethods__["family"] = _family_get
479         if _newclass:family = _swig_property(_family_get)
480    %}
481 }
482 /* ************************************************************************************ *
483    Structure module_qstate
484  * ************************************************************************************ */
485 %ignore module_qstate::ext_state;
486 %ignore module_qstate::minfo;
487 
488 /* Query state */
489 struct module_qstate {
490    struct query_info qinfo;
491    uint16_t query_flags; //See QF_BIT_xx constants
492    int      is_priming;
493 
494    struct comm_reply* reply;
495    struct dns_msg* return_msg;
496    int    return_rcode;
497    struct regional* region; /* unwrapped */
498 
499    int    curmod;
500 
501    enum   module_ext_state ext_state[MAX_MODULE];
502    void*  minfo[MAX_MODULE];
503 
504    struct module_env* env;         /* unwrapped */
505    struct mesh_state* mesh_info;
506 };
507 
508 %constant int MODULE_COUNT = MAX_MODULE;
509 
510 %constant int QF_BIT_CD = 0x0010;
511 %constant int QF_BIT_AD = 0x0020;
512 %constant int QF_BIT_Z  = 0x0040;
513 %constant int QF_BIT_RA = 0x0080;
514 %constant int QF_BIT_RD = 0x0100;
515 %constant int QF_BIT_TC = 0x0200;
516 %constant int QF_BIT_AA = 0x0400;
517 %constant int QF_BIT_QR = 0x8000;
518 
519 %inline %{
520  enum enum_return_rcode {
521    RCODE_NOERROR = 0,
522    RCODE_FORMERR = 1,
523    RCODE_SERVFAIL = 2,
524    RCODE_NXDOMAIN = 3,
525    RCODE_NOTIMPL = 4,
526    RCODE_REFUSED = 5,
527    RCODE_YXDOMAIN = 6,
528    RCODE_YXRRSET = 7,
529    RCODE_NXRRSET = 8,
530    RCODE_NOTAUTH = 9,
531    RCODE_NOTZONE = 10
532  };
533 %}
534 
535 %pythoncode %{
536     class ExtState:
537         def __init__(self, obj): self.obj = obj
538         def __str__(self):
539             return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)])
540         def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
541         def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
542         def __len__(self): return _unboundmodule.MODULE_COUNT
543 %}
544 
545 %inline %{
546    enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
547      if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
548         return q->ext_state[idx];
549      }
550      return 0;
551    }
552 
553    void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
554      if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
555         q->ext_state[idx] = state;
556      }
557    }
558 %}
559 
560 %extend module_qstate {
561    %pythoncode %{
562         def set_ext_state(self, id, state):
563             """Sets the ext state"""
564             _unboundmodule._ext_state_set(self, id, state)
565 
566         def __ext_state_get(self): return ExtState(self)
567         __swig_getmethods__["ext_state"] = __ext_state_get
568         if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
569    %}
570 }
571 
572 /* ************************************************************************************ *
573    Structure config_strlist
574  * ************************************************************************************ */
575 struct config_strlist {
576    struct config_strlist* next;
577    char* str;
578 };
579 
580 /* ************************************************************************************ *
581    Structure config_str2list
582  * ************************************************************************************ */
583 struct config_str2list {
584    struct config_str2list* next;
585    char* str;
586    char* str2;
587 };
588 
589 /* ************************************************************************************ *
590    Structure config_file
591  * ************************************************************************************ */
592 struct config_file {
593    int verbosity;
594    int stat_interval;
595    int stat_cumulative;
596    int stat_extended;
597    int num_threads;
598    int port;
599    int do_ip4;
600    int do_ip6;
601    int do_udp;
602    int do_tcp;
603    int outgoing_num_ports;
604    size_t outgoing_num_tcp;
605    size_t incoming_num_tcp;
606    int* outgoing_avail_ports;
607    size_t msg_buffer_size;
608    size_t msg_cache_size;
609    size_t msg_cache_slabs;
610    size_t num_queries_per_thread;
611    size_t jostle_time;
612    size_t rrset_cache_size;
613    size_t rrset_cache_slabs;
614    int host_ttl;
615    size_t infra_cache_slabs;
616    size_t infra_cache_numhosts;
617    char* target_fetch_policy;
618    int if_automatic;
619    int num_ifs;
620    char **ifs;
621    int num_out_ifs;
622    char **out_ifs;
623    struct config_strlist* root_hints;
624    struct config_stub* stubs;
625    struct config_stub* forwards;
626    struct config_strlist* donotqueryaddrs;
627    struct config_str2list* acls;
628    int donotquery_localhost;
629    int harden_short_bufsize;
630    int harden_large_queries;
631    int harden_glue;
632    int harden_dnssec_stripped;
633    int harden_referral_path;
634    int use_caps_bits_for_id;
635    struct config_strlist* private_address;
636    struct config_strlist* private_domain;
637    size_t unwanted_threshold;
638    char* chrootdir;
639    char* username;
640    char* directory;
641    char* logfile;
642    char* pidfile;
643    int use_syslog;
644    int hide_identity;
645    int hide_version;
646    char* identity;
647    char* version;
648    char* module_conf;
649    struct config_strlist* trust_anchor_file_list;
650    struct config_strlist* trust_anchor_list;
651    struct config_strlist* trusted_keys_file_list;
652    char* dlv_anchor_file;
653    struct config_strlist* dlv_anchor_list;
654    int max_ttl;
655    int32_t val_date_override;
656    int bogus_ttl;
657    int val_clean_additional;
658    int val_permissive_mode;
659    char* val_nsec3_key_iterations;
660    size_t key_cache_size;
661    size_t key_cache_slabs;
662    size_t neg_cache_size;
663    struct config_str2list* local_zones;
664    struct config_strlist* local_zones_nodefault;
665    struct config_strlist* local_data;
666    int remote_control_enable;
667    struct config_strlist* control_ifs;
668    int control_port;
669    char* server_key_file;
670    char* server_cert_file;
671    char* control_key_file;
672    char* control_cert_file;
673    int do_daemonize;
674    char* python_script;
675 };
676 
677 /* ************************************************************************************ *
678    ASN: Adding structures related to forwards_lookup and dns_cache_find_delegation
679  * ************************************************************************************ */
680 struct delegpt_ns {
681     struct delegpt_ns* next;
682     int resolved;
683     uint8_t got4;
684     uint8_t got6;
685     uint8_t lame;
686     uint8_t done_pside4;
687     uint8_t done_pside6;
688 };
689 
690 struct delegpt_addr {
691     struct delegpt_addr* next_result;
692     struct delegpt_addr* next_usable;
693     struct delegpt_addr* next_target;
694     int attempts;
695     int sel_rtt;
696     int bogus;
697     int lame;
698 };
699 
700 struct delegpt {
701     int namelabs;
702     struct delegpt_ns* nslist;
703     struct delegpt_addr* target_list;
704     struct delegpt_addr* usable_list;
705     struct delegpt_addr* result_list;
706     int bogus;
707     uint8_t has_parent_side_NS;
708     uint8_t dp_type_mlc;
709 };
710 
711 
712 %inline %{
713    PyObject* _get_dp_dname(struct delegpt* dp) {
714       return PyBytes_FromStringAndSize((char*)dp->name, dp->namelen);
715    }
716    PyObject* _get_dp_dname_components(struct delegpt* dp) {
717       return GetNameAsLabelList((char*)dp->name, dp->namelen);
718    }
719    PyObject* _get_dpns_dname(struct delegpt_ns* dpns) {
720       return PyBytes_FromStringAndSize((char*)dpns->name, dpns->namelen);
721    }
722    PyObject* _get_dpns_dname_components(struct delegpt_ns* dpns) {
723       return GetNameAsLabelList((char*)dpns->name, dpns->namelen);
724    }
725 
726   PyObject* _delegpt_addr_addr_get(struct delegpt_addr* target) {
727      char dest[64];
728      delegpt_addr_addr2str(target, dest, 64);
729      if (dest[0] == 0)
730         return Py_None;
731      return PyBytes_FromString(dest);
732   }
733 
734 %}
735 
736 %extend delegpt {
737    %pythoncode %{
738         __swig_getmethods__["dname"] = _unboundmodule._get_dp_dname
739         if _newclass:dname = _swig_property(_unboundmodule._get_dp_dname)
740 
741         __swig_getmethods__["dname_list"] = _unboundmodule._get_dp_dname_components
742         if _newclass:dname_list = _swig_property(_unboundmodule._get_dp_dname_components)
743 
744         def _get_dname_str(self): return dnameAsStr(self.dname)
745         __swig_getmethods__["dname_str"] = _get_dname_str
746         if _newclass:dname_str = _swig_property(_get_dname_str)
747    %}
748 }
749 %extend delegpt_ns {
750    %pythoncode %{
751         __swig_getmethods__["dname"] = _unboundmodule._get_dpns_dname
752         if _newclass:dname = _swig_property(_unboundmodule._get_dpns_dname)
753 
754         __swig_getmethods__["dname_list"] = _unboundmodule._get_dpns_dname_components
755         if _newclass:dname_list = _swig_property(_unboundmodule._get_dpns_dname_components)
756 
757         def _get_dname_str(self): return dnameAsStr(self.dname)
758         __swig_getmethods__["dname_str"] = _get_dname_str
759         if _newclass:dname_str = _swig_property(_get_dname_str)
760    %}
761 }
762 %extend delegpt_addr {
763    %pythoncode %{
764         def _addr_get(self): return _delegpt_addr_addr_get(self)
765         __swig_getmethods__["addr"] = _addr_get
766         if _newclass:addr = _swig_property(_addr_get)
767    %}
768 }
769 
770 /* ************************************************************************************ *
771    Enums
772  * ************************************************************************************ */
773 %rename ("MODULE_STATE_INITIAL") "module_state_initial";
774 %rename ("MODULE_WAIT_REPLY") "module_wait_reply";
775 %rename ("MODULE_WAIT_MODULE") "module_wait_module";
776 %rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
777 %rename ("MODULE_ERROR") "module_error";
778 %rename ("MODULE_FINISHED") "module_finished";
779 
780 enum module_ext_state {
781    module_state_initial = 0,
782    module_wait_reply,
783    module_wait_module,
784    module_wait_subquery,
785    module_error,
786    module_finished
787 };
788 
789 %rename ("MODULE_EVENT_NEW") "module_event_new";
790 %rename ("MODULE_EVENT_PASS") "module_event_pass";
791 %rename ("MODULE_EVENT_REPLY") "module_event_reply";
792 %rename ("MODULE_EVENT_NOREPLY") "module_event_noreply";
793 %rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail";
794 %rename ("MODULE_EVENT_MODDONE") "module_event_moddone";
795 %rename ("MODULE_EVENT_ERROR") "module_event_error";
796 
797 enum module_ev {
798    module_event_new = 0,
799    module_event_pass,
800    module_event_reply,
801    module_event_noreply,
802    module_event_capsfail,
803    module_event_moddone,
804    module_event_error
805 };
806 
807 enum sec_status {
808    sec_status_unchecked = 0,
809    sec_status_bogus,
810    sec_status_indeterminate,
811    sec_status_insecure,
812    sec_status_secure
813 };
814 
815 enum verbosity_value {
816    NO_VERBOSE = 0,
817    VERB_OPS,
818    VERB_DETAIL,
819    VERB_QUERY,
820    VERB_ALGO
821 };
822 
823 %constant uint16_t PKT_QR = 1;      /* QueRy - query flag */
824 %constant uint16_t PKT_AA = 2;      /* Authoritative Answer - server flag */
825 %constant uint16_t PKT_TC = 4;      /* TrunCated - server flag */
826 %constant uint16_t PKT_RD = 8;      /* Recursion Desired - query flag */
827 %constant uint16_t PKT_CD = 16;     /* Checking Disabled - query flag */
828 %constant uint16_t PKT_RA = 32;     /* Recursion Available - server flag */
829 %constant uint16_t PKT_AD = 64;     /* Authenticated Data - server flag */
830 
831 %{
832 int checkList(PyObject *l)
833 {
834     PyObject* item;
835     int i;
836 
837     if (l == Py_None)
838        return 1;
839 
840     if (PyList_Check(l))
841     {
842        for (i=0; i < PyList_Size(l); i++)
843        {
844            item = PyList_GetItem(l, i);
845            if (!PyBytes_Check(item))
846               return 0;
847        }
848        return 1;
849     }
850 
851     return 0;
852 }
853 
854 int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
855         size_t count_offset)
856 {
857     PyObject* item;
858     int i;
859     size_t len;
860 
861     for (i=0; i < PyList_Size(l); i++)
862     {
863         item = PyList_GetItem(l, i);
864 
865         len = sldns_buffer_remaining(qb);
866         if(qsec) {
867                 if(sldns_str2wire_rr_question_buf(PyBytes_AsString(item),
868                         sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
869                         != 0)
870                         return 0;
871         } else {
872                 if(sldns_str2wire_rr_buf(PyBytes_AsString(item),
873                         sldns_buffer_current(qb), &len, NULL, default_ttl,
874                         NULL, 0, NULL, 0) != 0)
875                         return 0;
876         }
877         sldns_buffer_skip(qb, len);
878 
879         sldns_buffer_write_u16_at(qb, count_offset,
880                 sldns_buffer_read_u16_at(qb, count_offset)+1);
881     }
882     return 1;
883 }
884 
885 int set_return_msg(struct module_qstate* qstate,
886                    const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
887                    PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)
888 {
889      sldns_buffer *qb = 0;
890      int res = 1;
891      size_t l;
892      uint16_t PKT_QR = 1;
893      uint16_t PKT_AA = 2;
894      uint16_t PKT_TC = 4;
895      uint16_t PKT_RD = 8;
896      uint16_t PKT_CD = 16;
897      uint16_t PKT_RA = 32;
898      uint16_t PKT_AD = 64;
899 
900      if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
901         return 0;
902      if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0;
903 
904      /* write header */
905      sldns_buffer_write_u16(qb, 0); /* ID */
906      sldns_buffer_write_u16(qb, 0); /* flags */
907      sldns_buffer_write_u16(qb, 1); /* qdcount */
908      sldns_buffer_write_u16(qb, 0); /* ancount */
909      sldns_buffer_write_u16(qb, 0); /* nscount */
910      sldns_buffer_write_u16(qb, 0); /* arcount */
911      if ((flags&PKT_QR)) LDNS_QR_SET(sldns_buffer_begin(qb));
912      if ((flags&PKT_AA)) LDNS_AA_SET(sldns_buffer_begin(qb));
913      if ((flags&PKT_TC)) LDNS_TC_SET(sldns_buffer_begin(qb));
914      if ((flags&PKT_RD)) LDNS_RD_SET(sldns_buffer_begin(qb));
915      if ((flags&PKT_CD)) LDNS_CD_SET(sldns_buffer_begin(qb));
916      if ((flags&PKT_RA)) LDNS_RA_SET(sldns_buffer_begin(qb));
917      if ((flags&PKT_AD)) LDNS_AD_SET(sldns_buffer_begin(qb));
918 
919      /* write the query */
920      l = sldns_buffer_remaining(qb);
921      if(sldns_str2wire_dname_buf(rr_name, sldns_buffer_current(qb), &l) != 0) {
922              sldns_buffer_free(qb);
923              return 0;
924      }
925      sldns_buffer_skip(qb, l);
926      if (rr_type == 0) { rr_type = LDNS_RR_TYPE_A; }
927      if (rr_class == 0) { rr_class = LDNS_RR_CLASS_IN; }
928      sldns_buffer_write_u16(qb, rr_type);
929      sldns_buffer_write_u16(qb, rr_class);
930 
931      /* write RR sections */
932      if(res && !pushRRList(qb, question, default_ttl, 1, LDNS_QDCOUNT_OFF))
933              res = 0;
934      if(res && !pushRRList(qb, answer, default_ttl, 0, LDNS_ANCOUNT_OFF))
935              res = 0;
936      if(res && !pushRRList(qb, authority, default_ttl, 0, LDNS_NSCOUNT_OFF))
937              res = 0;
938      if(res && !pushRRList(qb, additional, default_ttl, 0, LDNS_ARCOUNT_OFF))
939              res = 0;
940 
941      if (res) res = createResponse(qstate, qb);
942 
943      if (qb) sldns_buffer_free(qb);
944      return res;
945 }
946 %}
947 
948 int set_return_msg(struct module_qstate* qstate,
949                    const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
950                    PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
951 
952 %pythoncode %{
953     class DNSMessage:
954         def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0):
955             """Query flags is a combination of PKT_xx contants"""
956             self.rr_name = rr_name
957             self.rr_type = rr_type
958             self.rr_class = rr_class
959             self.default_ttl = default_ttl
960             self.query_flags = query_flags
961             self.question = []
962             self.answer = []
963             self.authority = []
964             self.additional = []
965 
966         def set_return_msg(self, qstate):
967             """Returns 1 if OK"""
968             status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class,
969                                            self.query_flags, self.default_ttl,
970                                            self.question, self.answer, self.authority, self.additional)
971 
972             if (status) and (PKT_AA & self.query_flags):
973                 qstate.return_msg.rep.authoritative = 1
974 
975             return status
976 
977 %}
978 /* ************************************************************************************ *
979    ASN: Delegation pointer related functions
980  * ************************************************************************************ */
981 
982 /* Functions which we will need to lookup delegations */
983 struct delegpt* dns_cache_find_delegation(struct module_env* env,
984         uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
985         struct regional* region, struct dns_msg** msg, uint32_t timenow);
986 int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
987         struct delegpt* dp);
988 struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
989         uint8_t* qname, uint16_t qclass, struct delegpt* dp);
990 
991 /* Custom function to perform logic similar to the one in daemon/cachedump.c */
992 struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen);
993 
994 %{
995 #define BIT_RD 0x100
996 
997 struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen)
998 {
999     struct delegpt *dp;
1000     struct dns_msg *msg = NULL;
1001     struct regional* region = qstate->env->scratch;
1002     char b[260];
1003     struct query_info qinfo;
1004     struct iter_hints_stub* stub;
1005     uint32_t timenow = *qstate->env->now;
1006 
1007     regional_free_all(region);
1008     qinfo.qname = (uint8_t*)nm;
1009     qinfo.qname_len = nmlen;
1010     qinfo.qtype = LDNS_RR_TYPE_A;
1011     qinfo.qclass = LDNS_RR_CLASS_IN;
1012 
1013     while(1) {
1014         dp = dns_cache_find_delegation(qstate->env, (uint8_t*)nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, timenow);
1015         if(!dp)
1016             return NULL;
1017         if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
1018             if (dname_is_root((uint8_t*)nm))
1019                 return NULL;
1020             nm = (char*)dp->name;
1021             nmlen = dp->namelen;
1022             dname_remove_label((uint8_t**)&nm, &nmlen);
1023             dname_str((uint8_t*)nm, b);
1024             continue;
1025         }
1026         stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp);
1027         if (stub) {
1028             return stub->dp;
1029         } else {
1030             return dp;
1031         }
1032     }
1033     return NULL;
1034 }
1035 %}
1036 
1037 /* ************************************************************************************ *
1038    Functions
1039  * ************************************************************************************ */
1040 
1041 // Various debuging functions
1042 void verbose(enum verbosity_value level, const char* format, ...);
1043 void log_info(const char* format, ...);
1044 void log_err(const char* format, ...);
1045 void log_warn(const char* format, ...);
1046 void log_hex(const char* msg, void* data, size_t length);
1047 void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep);
1048 void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
1049 void regional_log_stats(struct regional *r);
1050 
1051 // Free allocated memory from marked sources returning corresponding types
1052 %typemap(newfree, noblock = 1) char * {
1053   free($1);
1054 }
1055 
1056 // Mark as source returning newly allocated memory
1057 %newobject sldns_wire2str_type;
1058 %newobject sldns_wire2str_class;
1059 
1060 // LDNS functions
1061 char *sldns_wire2str_type(const uint16_t atype);
1062 char *sldns_wire2str_class(const uint16_t aclass);
1063 
1064 // Functions from pythonmod_utils
1065 int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
1066 void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
1067 
1068 // Module conversion functions
1069 const char* strextstate(enum module_ext_state s);
1070 const char* strmodulevent(enum module_ev e);
1071 
1072