]> git.saurik.com Git - apple/network_cmds.git/blobdiff - unbound/pythonmod/interface.i
network_cmds-480.tar.gz
[apple/network_cmds.git] / unbound / pythonmod / interface.i
diff --git a/unbound/pythonmod/interface.i b/unbound/pythonmod/interface.i
new file mode 100644 (file)
index 0000000..4f1a25f
--- /dev/null
@@ -0,0 +1,916 @@
+/*
+ * interface.i: unbound python module
+ */
+
+%module unboundmodule
+%{
+/**
+ * \file 
+ * This is the interface between the unbound server and a python module
+ * called to perform operations on queries.
+ */
+   #include <sys/types.h>
+   #include <sys/socket.h>
+   #include <netinet/in.h>
+   #include <arpa/inet.h>
+   #include <stdarg.h>
+   #include "config.h"
+   #include "util/log.h"
+   #include "util/module.h"
+   #include "util/netevent.h"
+   #include "util/regional.h"
+   #include "util/config_file.h"
+   #include "util/data/msgreply.h"
+   #include "util/data/packed_rrset.h"
+   #include "util/data/dname.h"
+   #include "util/storage/lruhash.h"
+   #include "services/cache/dns.h"
+   #include "services/mesh.h"
+   #include "ldns/wire2str.h"
+   #include "ldns/str2wire.h"
+   #include "ldns/pkthdr.h"
+%}
+
+%include "stdint.i" // uint_16_t can be known type now
+
+%inline %{
+   //converts [len][data][len][data][0] string to a List of labels (PyStrings)
+   PyObject* GetNameAsLabelList(const char* name, int len) {
+     PyObject* list;
+     int cnt=0, i;
+
+     i = 0;
+     while (i < len) {
+        i += name[i] + 1;
+        cnt++;
+     }
+
+     list = PyList_New(cnt);
+     i = 0; cnt = 0;
+     while (i < len) {
+        PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i]));
+        i += name[i] + 1;
+        cnt++;
+     }
+     return list;
+   }
+%}
+
+/* ************************************************************************************ * 
+   Structure query_info
+ * ************************************************************************************ */
+/* Query info */
+%ignore query_info::qname;
+%ignore query_info::qname_len;
+
+
+struct query_info {
+   %immutable;
+   char* qname;
+   size_t qname_len;
+   uint16_t qtype;
+   uint16_t qclass;
+   %mutable;
+};
+
+%inline %{
+   enum enum_rr_class  { 
+      RR_CLASS_IN = 1,
+      RR_CLASS_CH      = 3,
+      RR_CLASS_HS      = 4,
+      RR_CLASS_NONE = 254,
+      RR_CLASS_ANY = 255,
+   };
+   
+   enum enum_rr_type {
+      RR_TYPE_A = 1, 
+      RR_TYPE_NS = 2, 
+      RR_TYPE_MD = 3, 
+      RR_TYPE_MF = 4, 
+      RR_TYPE_CNAME = 5, 
+      RR_TYPE_SOA = 6, 
+      RR_TYPE_MB = 7, 
+      RR_TYPE_MG = 8, 
+      RR_TYPE_MR = 9, 
+      RR_TYPE_NULL = 10,
+      RR_TYPE_WKS = 11,
+      RR_TYPE_PTR = 12,
+      RR_TYPE_HINFO = 13,
+      RR_TYPE_MINFO = 14,
+      RR_TYPE_MX = 15,
+      RR_TYPE_TXT = 16,
+      RR_TYPE_RP = 17,
+      RR_TYPE_AFSDB = 18,
+      RR_TYPE_X25 = 19,
+      RR_TYPE_ISDN = 20,
+      RR_TYPE_RT = 21,
+      RR_TYPE_NSAP = 22,
+      RR_TYPE_NSAP_PTR = 23,
+      RR_TYPE_SIG = 24,
+      RR_TYPE_KEY = 25,
+      RR_TYPE_PX = 26,
+      RR_TYPE_GPOS = 27,
+      RR_TYPE_AAAA = 28,
+      RR_TYPE_LOC = 29,
+      RR_TYPE_NXT = 30,
+      RR_TYPE_EID = 31,
+      RR_TYPE_NIMLOC = 32,
+      RR_TYPE_SRV = 33,
+      RR_TYPE_ATMA = 34,
+      RR_TYPE_NAPTR = 35,
+      RR_TYPE_KX = 36,
+      RR_TYPE_CERT = 37,
+      RR_TYPE_A6 = 38,
+      RR_TYPE_DNAME = 39,
+      RR_TYPE_SINK = 40,
+      RR_TYPE_OPT = 41,
+      RR_TYPE_APL = 42,
+      RR_TYPE_DS = 43,
+      RR_TYPE_SSHFP = 44,
+      RR_TYPE_IPSECKEY = 45,
+      RR_TYPE_RRSIG = 46,
+      RR_TYPE_NSEC = 47,      
+      RR_TYPE_DNSKEY = 48,
+      RR_TYPE_DHCID = 49,
+      RR_TYPE_NSEC3 = 50,
+      RR_TYPE_NSEC3PARAMS = 51,
+      RR_TYPE_UINFO = 100,
+      RR_TYPE_UID = 101,
+      RR_TYPE_GID = 102,
+      RR_TYPE_UNSPEC = 103,
+      RR_TYPE_TSIG = 250,
+      RR_TYPE_IXFR = 251,
+      RR_TYPE_AXFR = 252,
+      RR_TYPE_MAILB = 253,
+      RR_TYPE_MAILA = 254,
+      RR_TYPE_ANY = 255,
+      RR_TYPE_DLV = 32769,
+   };
+
+   PyObject* _get_qname(struct query_info* q) {
+      return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
+   } 
+
+   PyObject* _get_qname_components(struct query_info* q) {
+      return GetNameAsLabelList((const char*)q->qname, q->qname_len);
+   }
+%}
+
+%inline %{
+   PyObject* dnameAsStr(const char* dname) {
+       char buf[LDNS_MAX_DOMAINLEN+1];
+       buf[0] = '\0';
+       dname_str((uint8_t*)dname, buf);
+       return PyString_FromString(buf);
+   }
+%}
+
+%extend query_info {
+   %pythoncode %{
+        def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
+        __swig_getmethods__["qtype_str"] = _get_qtype_str
+        if _newclass:qtype_str = _swig_property(_get_qtype_str)
+
+        def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
+        __swig_getmethods__["qclass_str"] = _get_qclass_str
+        if _newclass:qclass_str = _swig_property(_get_qclass_str)
+
+        __swig_getmethods__["qname"] = _unboundmodule._get_qname
+        if _newclass:qname = _swig_property(_unboundmodule._get_qname)
+        
+        __swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
+        if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
+
+        def _get_qname_str(self): return dnameAsStr(self.qname)
+        __swig_getmethods__["qname_str"] = _get_qname_str
+        if _newclass:qname_str = _swig_property(_get_qname_str)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure packed_rrset_key
+ * ************************************************************************************ */
+%ignore packed_rrset_key::dname;
+%ignore packed_rrset_key::dname_len;
+
+/* RRsets */
+struct packed_rrset_key {
+   %immutable;
+   char*    dname;
+   size_t   dname_len;
+   uint32_t flags; 
+   uint16_t type;  //rrset type in network format
+   uint16_t rrset_class; //rrset class in network format
+   %mutable;
+};
+
+//This subroutine converts values between the host and network byte order. 
+//Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order.
+uint16_t ntohs(uint16_t netshort);
+
+%inline %{
+   PyObject* _get_dname(struct packed_rrset_key* k) {
+      return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
+   } 
+   PyObject* _get_dname_components(struct packed_rrset_key* k) {
+      return GetNameAsLabelList((char*)k->dname, k->dname_len);
+   }
+%}
+
+%extend packed_rrset_key {
+   %pythoncode %{
+        def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
+        __swig_getmethods__["type_str"] = _get_type_str
+        if _newclass:type_str = _swig_property(_get_type_str)
+
+        def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
+        __swig_getmethods__["rrset_class_str"] = _get_class_str
+        if _newclass:rrset_class_str = _swig_property(_get_class_str)
+
+        __swig_getmethods__["dname"] = _unboundmodule._get_dname
+        if _newclass:dname = _swig_property(_unboundmodule._get_dname)
+
+        __swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components
+        if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components)
+
+        def _get_dname_str(self): return dnameAsStr(self.dname)
+        __swig_getmethods__["dname_str"] = _get_dname_str
+        if _newclass:dname_str = _swig_property(_get_dname_str)
+   %}
+}
+
+#if defined(SWIGWORDSIZE64) 
+typedef long int                rrset_id_t;
+#else 
+typedef long long int           rrset_id_t;
+#endif 
+
+struct ub_packed_rrset_key {
+   struct lruhash_entry entry;
+   rrset_id_t id;
+   struct packed_rrset_key rk;
+};
+
+struct lruhash_entry {
+  lock_rw_t lock;
+  struct lruhash_entry* overflow_next;
+  struct lruhash_entry* lru_next;
+  struct lruhash_entry* lru_prev;
+  hashvalue_t hash;
+  void* key;
+  struct packed_rrset_data* data;
+};
+
+%ignore packed_rrset_data::rr_len;
+%ignore packed_rrset_data::rr_ttl;
+%ignore packed_rrset_data::rr_data;
+
+struct packed_rrset_data {
+  uint32_t ttl; //TTL (in seconds like time())
+
+  size_t count; //number of rrs
+  size_t rrsig_count; //number of rrsigs
+
+  enum rrset_trust trust; 
+  enum sec_status security;
+
+  size_t* rr_len;   //length of every rr's rdata
+  uint32_t *rr_ttl; //ttl of every rr
+  uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat. 
+};
+
+%pythoncode %{
+    class RRSetData_RRLen:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index)
+        def __len__(self): return obj.count + obj.rrsig_count
+    class RRSetData_RRTTL:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index)
+        def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value)
+        def __len__(self): return obj.count + obj.rrsig_count
+    class RRSetData_RRData:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index)
+        def __len__(self): return obj.count + obj.rrsig_count
+%}
+
+%inline %{
+   PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && 
+             ((size_t)idx < (d->count+d->rrsig_count))) 
+        return PyInt_FromLong(d->rr_len[idx]);
+     return Py_None;
+   }
+   void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
+   {
+     if ((d != NULL) && (idx >= 0) && 
+             ((size_t)idx < (d->count+d->rrsig_count))) 
+        d->rr_ttl[idx] = ttl;
+   }
+   PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && 
+             ((size_t)idx < (d->count+d->rrsig_count))) 
+        return PyInt_FromLong(d->rr_ttl[idx]);
+     return Py_None;
+   }
+   PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && 
+             ((size_t)idx < (d->count+d->rrsig_count))) 
+        return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
+                d->rr_len[idx]);
+     return Py_None;
+   }
+%}
+
+%extend packed_rrset_data {
+   %pythoncode %{
+        def _get_data_rr_len(self): return RRSetData_RRLen(self)
+        __swig_getmethods__["rr_len"] = _get_data_rr_len
+        if _newclass:rr_len = _swig_property(_get_data_rr_len)
+        def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
+        __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
+        if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
+        def _get_data_rr_data(self): return RRSetData_RRData(self)
+        __swig_getmethods__["rr_data"] = _get_data_rr_data
+        if _newclass:rr_len = _swig_property(_get_data_rr_data)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure reply_info
+ * ************************************************************************************ */
+/* Messages */
+%ignore reply_info::rrsets;
+%ignore reply_info::ref;
+
+struct reply_info {
+   uint16_t flags;
+   uint16_t qdcount;
+   uint32_t ttl;
+   uint32_t prefetch_ttl;
+
+   uint16_t authoritative;
+   enum sec_status security;
+
+   size_t an_numrrsets;
+   size_t ns_numrrsets;
+   size_t ar_numrrsets;
+   size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets
+
+   struct ub_packed_rrset_key** rrsets;
+   struct rrset_ref ref[1]; //?
+};
+
+struct rrset_ref {
+   struct ub_packed_rrset_key* key;
+   rrset_id_t id;
+};
+
+struct dns_msg {
+   struct query_info qinfo;
+   struct reply_info *rep;
+};
+
+%pythoncode %{
+    class ReplyInfo_RRSet:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index)
+        def __len__(self): return obj.rrset_count
+
+    class ReplyInfo_Ref:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index)
+        def __len__(self): return obj.rrset_count
+%}
+
+%inline %{
+   struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
+     if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count))
+        return r->rrsets[idx];
+     return NULL;
+   }
+
+   struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
+     if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
+//printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key);
+             return &(r->ref[idx]);
+//        return &(r->ref[idx]);
+     }
+//printf("_rrset_ref_get: NULL\n");
+     return NULL;
+   }
+%}
+
+%extend reply_info {
+   %pythoncode %{
+        def _rrset_ref_get(self): return ReplyInfo_Ref(self)
+        __swig_getmethods__["ref"] = _rrset_ref_get
+        if _newclass:ref = _swig_property(_rrset_ref_get)
+
+        def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
+        __swig_getmethods__["rrsets"] = _rrset_rrsets_get
+        if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure mesh_state
+ * ************************************************************************************ */
+struct mesh_state {
+   struct mesh_reply* reply_list;
+};
+
+struct mesh_reply {
+   struct mesh_reply* next;
+   struct comm_reply query_reply;
+};
+
+struct comm_reply {
+   
+};
+
+%inline %{
+
+  PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
+     char dest[64];
+     reply_addr2str(reply, dest, 64);
+     if (dest[0] == 0)
+        return Py_None;
+     return PyString_FromString(dest);
+  }
+
+  PyObject* _comm_reply_family_get(struct comm_reply* reply) {
+
+        int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
+
+        switch(af) {
+           case AF_INET: return PyString_FromString("ip4");
+           case AF_INET6: return PyString_FromString("ip6"); 
+           case AF_UNIX: return PyString_FromString("unix");
+        }
+
+        return Py_None;
+  }
+
+  PyObject* _comm_reply_port_get(struct comm_reply* reply) {
+     uint16_t port;
+     port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
+     return PyInt_FromLong(port);
+  }
+
+%}
+
+%extend comm_reply {
+   %pythoncode %{
+        def _addr_get(self): return _comm_reply_addr_get(self)
+        __swig_getmethods__["addr"] = _addr_get
+        if _newclass:addr = _swig_property(_addr_get)
+
+        def _port_get(self): return _comm_reply_port_get(self)
+        __swig_getmethods__["port"] = _port_get
+        if _newclass:port = _swig_property(_port_get)
+
+        def _family_get(self): return _comm_reply_family_get(self)
+        __swig_getmethods__["family"] = _family_get
+        if _newclass:family = _swig_property(_family_get)
+   %}
+}
+/* ************************************************************************************ * 
+   Structure module_qstate
+ * ************************************************************************************ */
+%ignore module_qstate::ext_state;
+%ignore module_qstate::minfo;
+
+/* Query state */
+struct module_qstate {
+   struct query_info qinfo;
+   uint16_t query_flags; //See QF_BIT_xx constants
+   int      is_priming;
+
+   struct comm_reply* reply;
+   struct dns_msg* return_msg;
+   int    return_rcode;
+   struct regional* region; /* unwrapped */
+
+   int    curmod;
+
+   enum   module_ext_state ext_state[MAX_MODULE];
+   void*  minfo[MAX_MODULE];
+
+   struct module_env* env;         /* unwrapped */
+   struct mesh_state* mesh_info;
+};
+
+%constant int MODULE_COUNT = MAX_MODULE;
+
+%constant int QF_BIT_CD = 0x0010;
+%constant int QF_BIT_AD = 0x0020;
+%constant int QF_BIT_Z  = 0x0040;
+%constant int QF_BIT_RA = 0x0080;
+%constant int QF_BIT_RD = 0x0100;
+%constant int QF_BIT_TC = 0x0200;
+%constant int QF_BIT_AA = 0x0400;
+%constant int QF_BIT_QR = 0x8000;
+
+%inline %{
+ enum enum_return_rcode {
+   RCODE_NOERROR = 0,
+   RCODE_FORMERR = 1,
+   RCODE_SERVFAIL = 2,
+   RCODE_NXDOMAIN = 3,
+   RCODE_NOTIMPL = 4,
+   RCODE_REFUSED = 5,
+   RCODE_YXDOMAIN = 6,
+   RCODE_YXRRSET = 7,
+   RCODE_NXRRSET = 8,
+   RCODE_NOTAUTH = 9,
+   RCODE_NOTZONE = 10
+ };
+%}
+
+%pythoncode %{
+    class ExtState:
+        def __init__(self, obj): self.obj = obj
+        def __str__(self):
+            return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)])
+        def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
+        def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
+        def __len__(self): return _unboundmodule.MODULE_COUNT
+%}
+
+%inline %{
+   enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
+     if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
+        return q->ext_state[idx];
+     } 
+     return 0;
+   }
+  
+   void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
+     if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
+        q->ext_state[idx] = state;
+     } 
+   }
+%}
+
+%extend module_qstate {
+   %pythoncode %{
+        def set_ext_state(self, id, state):
+            """Sets the ext state"""
+            _unboundmodule._ext_state_set(self, id, state)
+
+        def __ext_state_get(self): return ExtState(self)
+        __swig_getmethods__["ext_state"] = __ext_state_get
+        if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure config_strlist
+ * ************************************************************************************ */
+struct config_strlist {
+   struct config_strlist* next;
+   char* str;
+};
+
+/* ************************************************************************************ * 
+   Structure config_str2list
+ * ************************************************************************************ */
+struct config_str2list {
+   struct config_str2list* next;
+   char* str;
+   char* str2;
+};
+
+/* ************************************************************************************ * 
+   Structure config_file
+ * ************************************************************************************ */
+struct config_file {
+   int verbosity;
+   int stat_interval;
+   int stat_cumulative;
+   int stat_extended;
+   int num_threads;
+   int port;
+   int do_ip4;
+   int do_ip6;
+   int do_udp;
+   int do_tcp;
+   int outgoing_num_ports;
+   size_t outgoing_num_tcp;
+   size_t incoming_num_tcp;
+   int* outgoing_avail_ports;
+   size_t msg_buffer_size;
+   size_t msg_cache_size;
+   size_t msg_cache_slabs;
+   size_t num_queries_per_thread;
+   size_t jostle_time;
+   size_t rrset_cache_size;
+   size_t rrset_cache_slabs;
+   int host_ttl;
+   size_t infra_cache_slabs;
+   size_t infra_cache_numhosts;
+   char* target_fetch_policy;
+   int if_automatic;
+   int num_ifs;
+   char **ifs;
+   int num_out_ifs;
+   char **out_ifs;
+   struct config_strlist* root_hints;
+   struct config_stub* stubs;
+   struct config_stub* forwards;
+   struct config_strlist* donotqueryaddrs;
+   struct config_str2list* acls;
+   int donotquery_localhost;
+   int harden_short_bufsize;
+   int harden_large_queries;
+   int harden_glue;
+   int harden_dnssec_stripped;
+   int harden_referral_path;
+   int use_caps_bits_for_id;
+   struct config_strlist* private_address;
+   struct config_strlist* private_domain;
+   size_t unwanted_threshold;
+   char* chrootdir;
+   char* username;
+   char* directory;
+   char* logfile;
+   char* pidfile;
+   int use_syslog;
+   int hide_identity;
+   int hide_version;
+   char* identity;
+   char* version;
+   char* module_conf;
+   struct config_strlist* trust_anchor_file_list;
+   struct config_strlist* trust_anchor_list;
+   struct config_strlist* trusted_keys_file_list;
+   char* dlv_anchor_file;
+   struct config_strlist* dlv_anchor_list;
+   int max_ttl;
+   int32_t val_date_override;
+   int bogus_ttl; 
+   int val_clean_additional;
+   int val_permissive_mode;
+   char* val_nsec3_key_iterations;
+   size_t key_cache_size;
+   size_t key_cache_slabs;
+   size_t neg_cache_size;
+   struct config_str2list* local_zones;
+   struct config_strlist* local_zones_nodefault;
+   struct config_strlist* local_data;
+   int remote_control_enable;
+   struct config_strlist* control_ifs;
+   int control_port;
+   char* server_key_file;
+   char* server_cert_file;
+   char* control_key_file;
+   char* control_cert_file;
+   int do_daemonize;
+   char* python_script;
+};
+
+/* ************************************************************************************ * 
+   Enums
+ * ************************************************************************************ */
+%rename ("MODULE_STATE_INITIAL") "module_state_initial";
+%rename ("MODULE_WAIT_REPLY") "module_wait_reply";
+%rename ("MODULE_WAIT_MODULE") "module_wait_module";
+%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
+%rename ("MODULE_ERROR") "module_error";
+%rename ("MODULE_FINISHED") "module_finished";
+
+enum module_ext_state {
+   module_state_initial = 0,
+   module_wait_reply,
+   module_wait_module,
+   module_wait_subquery,
+   module_error,
+   module_finished
+};
+
+%rename ("MODULE_EVENT_NEW") "module_event_new";
+%rename ("MODULE_EVENT_PASS") "module_event_pass";
+%rename ("MODULE_EVENT_REPLY") "module_event_reply";
+%rename ("MODULE_EVENT_NOREPLY") "module_event_noreply";
+%rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail";
+%rename ("MODULE_EVENT_MODDONE") "module_event_moddone";
+%rename ("MODULE_EVENT_ERROR") "module_event_error";
+
+enum module_ev {
+   module_event_new = 0,
+   module_event_pass,
+   module_event_reply,
+   module_event_noreply,
+   module_event_capsfail,
+   module_event_moddone,
+   module_event_error
+};
+
+enum sec_status {
+   sec_status_unchecked = 0,
+   sec_status_bogus,
+   sec_status_indeterminate,
+   sec_status_insecure,
+   sec_status_secure
+};
+
+enum verbosity_value {
+   NO_VERBOSE = 0,
+   VERB_OPS,
+   VERB_DETAIL,
+   VERB_QUERY,
+   VERB_ALGO
+};
+
+%constant uint16_t PKT_QR = 1;      /* QueRy - query flag */
+%constant uint16_t PKT_AA = 2;      /* Authoritative Answer - server flag */
+%constant uint16_t PKT_TC = 4;      /* TrunCated - server flag */
+%constant uint16_t PKT_RD = 8;      /* Recursion Desired - query flag */
+%constant uint16_t PKT_CD = 16;     /* Checking Disabled - query flag */
+%constant uint16_t PKT_RA = 32;     /* Recursion Available - server flag */
+%constant uint16_t PKT_AD = 64;     /* Authenticated Data - server flag */
+
+%{
+int checkList(PyObject *l) 
+{
+    PyObject* item;
+    int i;
+
+    if (l == Py_None) 
+       return 1;
+
+    if (PyList_Check(l)) 
+    {
+       for (i=0; i < PyList_Size(l); i++) 
+       {
+           item = PyList_GetItem(l, i);
+           if (!PyString_Check(item))
+              return 0;
+       }
+       return 1;
+    }
+
+    return 0;
+}
+
+int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
+        size_t count_offset)
+{
+    PyObject* item;
+    int i;
+    size_t len;
+
+    for (i=0; i < PyList_Size(l); i++) 
+    {
+        item = PyList_GetItem(l, i);
+
+        len = sldns_buffer_remaining(qb);
+        if(qsec) {
+                if(sldns_str2wire_rr_question_buf(PyString_AsString(item),
+                        sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
+                        != 0)
+                        return 0;
+        } else {
+                if(sldns_str2wire_rr_buf(PyString_AsString(item),
+                        sldns_buffer_current(qb), &len, NULL, default_ttl,
+                        NULL, 0, NULL, 0) != 0)
+                        return 0;
+        }
+        sldns_buffer_skip(qb, len);
+
+        sldns_buffer_write_u16_at(qb, count_offset,
+                sldns_buffer_read_u16_at(qb, count_offset)+1);
+    }
+    return 1;
+}
+
+int set_return_msg(struct module_qstate* qstate, 
+                   const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
+                   PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional) 
+{
+     sldns_buffer *qb = 0;
+     int res = 1;
+     size_t l;
+     uint16_t PKT_QR = 1;
+     uint16_t PKT_AA = 2;
+     uint16_t PKT_TC = 4;
+     uint16_t PKT_RD = 8;
+     uint16_t PKT_CD = 16;
+     uint16_t PKT_RA = 32;
+     uint16_t PKT_AD = 64;
+     if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
+        return 0;
+     if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0;
+
+     /* write header */
+     sldns_buffer_write_u16(qb, 0); /* ID */
+     sldns_buffer_write_u16(qb, 0); /* flags */
+     sldns_buffer_write_u16(qb, 1); /* qdcount */
+     sldns_buffer_write_u16(qb, 0); /* ancount */
+     sldns_buffer_write_u16(qb, 0); /* nscount */
+     sldns_buffer_write_u16(qb, 0); /* arcount */
+     if ((flags&PKT_QR)) LDNS_QR_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_AA)) LDNS_AA_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_TC)) LDNS_TC_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_RD)) LDNS_RD_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_CD)) LDNS_CD_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_RA)) LDNS_RA_SET(sldns_buffer_begin(qb));
+     if ((flags&PKT_AD)) LDNS_AD_SET(sldns_buffer_begin(qb));
+
+     /* write the query */
+     l = sldns_buffer_remaining(qb);
+     if(sldns_str2wire_dname_buf(rr_name, sldns_buffer_current(qb), &l) != 0) {
+             sldns_buffer_free(qb);
+             return 0;
+     }
+     sldns_buffer_skip(qb, l);
+     if (rr_type == 0) { rr_type = LDNS_RR_TYPE_A; }
+     if (rr_class == 0) { rr_class = LDNS_RR_CLASS_IN; }
+     sldns_buffer_write_u16(qb, rr_type);
+     sldns_buffer_write_u16(qb, rr_class);
+
+     /* write RR sections */
+     if(res && !pushRRList(qb, question, default_ttl, 1, LDNS_QDCOUNT_OFF))
+             res = 0;
+     if(res && !pushRRList(qb, answer, default_ttl, 0, LDNS_ANCOUNT_OFF))
+             res = 0;
+     if(res && !pushRRList(qb, authority, default_ttl, 0, LDNS_NSCOUNT_OFF))
+             res = 0;
+     if(res && !pushRRList(qb, additional, default_ttl, 0, LDNS_ARCOUNT_OFF))
+             res = 0;
+
+     if (res) res = createResponse(qstate, qb);
+
+     if (qb) sldns_buffer_free(qb);
+     return res;
+}
+%}
+
+int set_return_msg(struct module_qstate* qstate, 
+                   const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
+                   PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
+
+%pythoncode %{
+    class DNSMessage:
+        def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0):
+            """Query flags is a combination of PKT_xx contants"""
+            self.rr_name = rr_name
+            self.rr_type = rr_type
+            self.rr_class = rr_class
+            self.default_ttl = default_ttl
+            self.query_flags = query_flags
+            self.question = []
+            self.answer = []
+            self.authority = []
+            self.additional = []
+
+        def set_return_msg(self, qstate):
+            """Returns 1 if OK"""
+            status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class, 
+                                           self.query_flags, self.default_ttl,
+                                           self.question, self.answer, self.authority, self.additional)
+
+            if (status) and (PKT_AA & self.query_flags):
+                qstate.return_msg.rep.authoritative = 1
+
+            return status 
+
+%}
+/* ************************************************************************************ * 
+   Functions
+ * ************************************************************************************ */
+
+// Various debuging functions
+void verbose(enum verbosity_value level, const char* format, ...);
+void log_info(const char* format, ...);
+void log_err(const char* format, ...);
+void log_warn(const char* format, ...);
+void log_hex(const char* msg, void* data, size_t length);
+void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep);
+void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
+void regional_log_stats(struct regional *r);
+
+// Free allocated memory from marked sources returning corresponding types
+%typemap(newfree, noblock = 1) char * {
+  free($1);
+}
+
+// Mark as source returning newly allocated memory
+%newobject sldns_wire2str_type;
+%newobject sldns_wire2str_class;
+
+// LDNS functions
+char *sldns_wire2str_type(const uint16_t atype);
+char *sldns_wire2str_class(const uint16_t aclass);
+
+// Functions from pythonmod_utils
+int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
+void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
+
+// Module conversion functions
+const char* strextstate(enum module_ext_state s);
+const char* strmodulevent(enum module_ev e);
+