diff options
Diffstat (limited to 'pythonmod/interface.i')
| -rw-r--r-- | pythonmod/interface.i | 889 | 
1 files changed, 889 insertions, 0 deletions
| diff --git a/pythonmod/interface.i b/pythonmod/interface.i new file mode 100644 index 000000000000..903563658b0e --- /dev/null +++ b/pythonmod/interface.i @@ -0,0 +1,889 @@ +/* + * 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 "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, PyString_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 PyString_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 ldns_rr_type2str(self.qtype) +        __swig_getmethods__["qtype_str"] = _get_qtype_str +        if _newclass:qtype_str = _swig_property(_get_qtype_str) + +        def _get_qclass_str(self): return ldns_rr_class2str(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 PyString_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 ldns_rr_type2str(_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 ldns_rr_class2str(_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 PyString_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 +}; + +%{ +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; +} + +ldns_rr_list* createRRList(PyObject *l, uint32_t default_ttl)  +{ +    PyObject* item; +    ldns_status status; +    ldns_rr_list* rr_list; +    ldns_rr* rr; +    int i; + +    if (PyList_Size(l) == 0) +       return NULL; + +    rr_list = ldns_rr_list_new(); + +    for (i=0; i < PyList_Size(l); i++)  +    { +        item = PyList_GetItem(l, i); + +        status = ldns_rr_new_frm_str(&rr, PyString_AsString(item), default_ttl, 0, 0); +        if (status != LDNS_STATUS_OK)  +            continue; + +        if (!ldns_rr_list_push_rr(rr_list, rr))  +            continue; + +    } +    return rr_list; +} + +int set_return_msg(struct module_qstate* qstate,  +                   const char* rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl, +                   PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)  +{ +     ldns_pkt* pkt = 0; +     ldns_status status; +     ldns_rr_list* rr_list = 0; +     ldns_buffer *qb = 0; +     int res = 1; +      +     if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional))) +        return 0; + +     status = ldns_pkt_query_new_frm_str(&pkt, rr_name, rr_type, rr_class, flags); +     if ((status != LDNS_STATUS_OK) || (pkt == 0)) +        return 0; + +     rr_list = createRRList(question, default_ttl); +     if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_QUESTION, rr_list); +     ldns_rr_list_free(rr_list); +     rr_list = createRRList(answer, default_ttl); +     if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ANSWER, rr_list); +     ldns_rr_list_free(rr_list); +     rr_list = createRRList(authority, default_ttl); +     if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_AUTHORITY, rr_list); +     ldns_rr_list_free(rr_list); +     rr_list = createRRList(additional, default_ttl); +     if ((rr_list) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ADDITIONAL, rr_list); +     ldns_rr_list_free(rr_list); + +     if ((res) && ((qb = ldns_buffer_new(LDNS_MIN_BUFLEN)) == 0)) res = 0; +     if ((res) && (ldns_pkt2buffer_wire(qb, pkt) != LDNS_STATUS_OK)) res = 0; + +     if (res) res = createResponse(qstate, qb); + +     if (qb) ldns_buffer_free(qb); + +     ldns_pkt_free(pkt); //this function dealocates pkt as well as rrs +     return res; +} +%} + +%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 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 ldns_rr_type2str; +%newobject ldns_rr_class2str; + +// LDNS functions +char *ldns_rr_type2str(const uint16_t atype); +char *ldns_rr_class2str(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); + | 
