]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/libunbound/python/libunbound.i
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / unbound / libunbound / python / libunbound.i
1 /*
2  * libounbound.i: pyUnbound module (libunbound wrapper for Python)
3  * 
4  * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
5  *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
6  *
7  * This software is open source.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 
13  *    * Redistributions of source code must retain the above copyright notice,
14  *      this list of conditions and the following disclaimer.
15  * 
16  *    * Redistributions in binary form must reproduce the above copyright notice,
17  *      this list of conditions and the following disclaimer in the documentation
18  *      and/or other materials provided with the distribution.
19  * 
20  *    * Neither the name of the organization nor the names of its
21  *      contributors may be used to endorse or promote products derived from this
22  *      software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
28  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 %module unbound
37 %{
38    #include <sys/types.h>
39    #include <sys/socket.h>
40    #include <netinet/in.h>
41    #include <arpa/inet.h>
42    #include "libunbound/unbound.h"
43 %}
44
45 %pythoncode %{
46    import encodings.idna
47    try:
48        import builtins
49    except ImportError:
50        import __builtin__ as builtins
51
52    # Ensure compatibility with older python versions
53    if 'bytes' not in vars():
54        bytes = str
55
56    def ord(s):
57        if isinstance(s, int):
58            return s
59        return builtins.ord(s)
60 %}
61
62 //%include "doc.i"
63 %include "file.i"
64
65 %feature("docstring") strerror "Convert error value to a human readable string."
66
67 // ================================================================================
68 // ub_resolve - perform resolution and validation
69 // ================================================================================
70 %typemap(in,numinputs=0,noblock=1) (struct ub_result** result)  
71
72    struct ub_result* newubr;
73    $1 = &newubr;
74
75   
76 /* result generation */
77 %typemap(argout,noblock=1) (struct ub_result** result)
78 {
79   if(1) { /* new code block for variable on stack */
80     PyObject* tuple;
81     tuple = PyTuple_New(2);
82     PyTuple_SetItem(tuple, 0, $result);
83     if (result == 0) {
84        PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(newubr), SWIGTYPE_p_ub_result, SWIG_POINTER_OWN |  0 ));
85     } else {
86        PyTuple_SetItem(tuple, 1, Py_None);
87     }
88     $result = tuple;
89   }
90 }
91
92                        
93 // ================================================================================
94 // ub_ctx - validation context
95 // ================================================================================
96 %nodefaultctor ub_ctx; //no default constructor & destructor
97 %nodefaultdtor ub_ctx;
98
99 %newobject ub_ctx_create;
100 %delobject ub_ctx_delete;
101 %rename(_ub_ctx_delete) ub_ctx_delete;
102
103 %newobject ub_resolve;
104
105 %inline %{
106   void ub_ctx_free_dbg (struct ub_ctx* c) {
107     printf("******** UB_CTX free 0x%lX ************\n", (long unsigned int)c);
108     ub_ctx_delete(c);
109   }
110
111   //RR types
112   enum enum_rr_type
113   {
114     /**  a host address */
115     RR_TYPE_A = 1, 
116     /**  an authoritative name server */
117     RR_TYPE_NS = 2, 
118     /**  a mail destination (Obsolete - use MX) */
119     RR_TYPE_MD = 3, 
120     /**  a mail forwarder (Obsolete - use MX) */
121     RR_TYPE_MF = 4, 
122     /**  the canonical name for an alias */
123     RR_TYPE_CNAME = 5, 
124     /**  marks the start of a zone of authority */
125     RR_TYPE_SOA = 6, 
126     /**  a mailbox domain name (EXPERIMENTAL) */
127     RR_TYPE_MB = 7, 
128     /**  a mail group member (EXPERIMENTAL) */
129     RR_TYPE_MG = 8, 
130     /**  a mail rename domain name (EXPERIMENTAL) */
131     RR_TYPE_MR = 9, 
132     /**  a null RR (EXPERIMENTAL) */
133     RR_TYPE_NULL = 10,
134     /**  a well known service description */
135     RR_TYPE_WKS = 11,
136     /**  a domain name pointer */
137     RR_TYPE_PTR = 12,
138     /**  host information */
139     RR_TYPE_HINFO = 13,
140     /**  mailbox or mail list information */
141     RR_TYPE_MINFO = 14,
142     /**  mail exchange */
143     RR_TYPE_MX = 15,
144     /**  text strings */
145     RR_TYPE_TXT = 16,
146     /**  RFC1183 */
147     RR_TYPE_RP = 17,
148     /**  RFC1183 */
149     RR_TYPE_AFSDB = 18,
150     /**  RFC1183 */
151     RR_TYPE_X25 = 19,
152     /**  RFC1183 */
153     RR_TYPE_ISDN = 20,
154     /**  RFC1183 */
155     RR_TYPE_RT = 21,
156     /**  RFC1706 */
157     RR_TYPE_NSAP = 22,
158     /**  RFC1348 */
159     RR_TYPE_NSAP_PTR = 23,
160     /**  2535typecode */
161     RR_TYPE_SIG = 24,
162     /**  2535typecode */
163     RR_TYPE_KEY = 25,
164     /**  RFC2163 */
165     RR_TYPE_PX = 26,
166     /**  RFC1712 */
167     RR_TYPE_GPOS = 27,
168     /**  ipv6 address */
169     RR_TYPE_AAAA = 28,
170     /**  LOC record  RFC1876 */
171     RR_TYPE_LOC = 29,
172     /**  2535typecode */
173     RR_TYPE_NXT = 30,
174     /**  draft-ietf-nimrod-dns-01.txt */
175     RR_TYPE_EID = 31,
176     /**  draft-ietf-nimrod-dns-01.txt */
177     RR_TYPE_NIMLOC = 32,
178     /**  SRV record RFC2782 */
179     RR_TYPE_SRV = 33,
180     /**  http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
181     RR_TYPE_ATMA = 34,
182     /**  RFC2915 */
183     RR_TYPE_NAPTR = 35,
184     /**  RFC2230 */
185     RR_TYPE_KX = 36,
186     /**  RFC2538 */
187     RR_TYPE_CERT = 37,
188     /**  RFC2874 */
189     RR_TYPE_A6 = 38,
190     /**  RFC2672 */
191     RR_TYPE_DNAME = 39,
192     /**  dnsind-kitchen-sink-02.txt */
193     RR_TYPE_SINK = 40,
194     /**  Pseudo OPT record... */
195     RR_TYPE_OPT = 41,
196     /**  RFC3123 */
197     RR_TYPE_APL = 42,
198     /**  draft-ietf-dnsext-delegation */
199     RR_TYPE_DS = 43,
200     /**  SSH Key Fingerprint */
201     RR_TYPE_SSHFP = 44,
202     /**  draft-richardson-ipseckey-rr-11.txt */
203     RR_TYPE_IPSECKEY = 45,
204     /**  draft-ietf-dnsext-dnssec-25 */
205     RR_TYPE_RRSIG = 46,
206     RR_TYPE_NSEC = 47,      
207     RR_TYPE_DNSKEY = 48,
208     RR_TYPE_DHCID = 49,
209
210     RR_TYPE_NSEC3 = 50,
211     RR_TYPE_NSEC3PARAMS = 51,
212
213     RR_TYPE_UINFO = 100,
214     RR_TYPE_UID = 101,
215     RR_TYPE_GID = 102,
216     RR_TYPE_UNSPEC = 103,
217
218     RR_TYPE_TSIG = 250,
219     RR_TYPE_IXFR = 251,
220     RR_TYPE_AXFR = 252,
221     /**  A request for mailbox-related records (MB, MG or MR) */
222     RR_TYPE_MAILB = 253,
223     /**  A request for mail agent RRs (Obsolete - see MX) */
224     RR_TYPE_MAILA = 254,
225     /**  any type (wildcard) */
226     RR_TYPE_ANY = 255,
227
228     /* RFC 4431, 5074, DNSSEC Lookaside Validation */
229     RR_TYPE_DLV = 32769,
230   };
231
232   // RR classes
233   enum enum_rr_class
234   { 
235     /** the Internet */
236     RR_CLASS_IN = 1,
237     /** Chaos class */
238     RR_CLASS_CH = 3,
239     /** Hesiod (Dyer 87) */
240     RR_CLASS_HS = 4,
241     /** None class, dynamic update */
242     RR_CLASS_NONE = 254,
243     /** Any class */
244     RR_CLASS_ANY = 255,
245   };
246 %} 
247
248 %feature("docstring") ub_ctx "Unbound resolving and validation context. 
249
250 The validation context is created to hold the resolver status, validation keys and a small cache (containing messages, rrsets, roundtrip times, trusted keys, lameness information).
251
252 **Usage**
253
254 >>> import unbound
255 >>> ctx = unbound.ub_ctx()
256 >>> ctx.resolvconf(\"/etc/resolv.conf\")
257 >>> status, result = ctx.resolve(\"www.google.com\", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
258 >>> if status==0 and result.havedata:
259 >>>    print \"Result:\",result.data.address_list
260 Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
261 "
262
263 %extend ub_ctx
264 {
265  %pythoncode %{
266         def __init__(self):
267             """Creates a resolving and validation context.
268                
269                An exception is invoked if the process of creation an ub_ctx instance fails.
270             """
271             self.this = _unbound.ub_ctx_create()
272             if not self.this:
273                 raise Exception("Fatal error: unbound context initialization failed")
274
275         #__swig_destroy__ = _unbound.ub_ctx_free_dbg
276         __swig_destroy__ = _unbound._ub_ctx_delete
277
278         #UB_CTX_METHODS_#   
279         def add_ta(self,ta):
280             """Add a trust anchor to the given context.
281                
282                The trust anchor is a string, on one line, that holds a valid DNSKEY or DS RR.
283                
284                :param ta:
285                    string, with zone-format RR on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
286                :returns: (int) 0 if OK, else error.
287             """
288             return _unbound.ub_ctx_add_ta(self,ta)
289             #parameters: struct ub_ctx *,char *,
290             #retvals: int
291
292         def add_ta_file(self,fname):
293             """Add trust anchors to the given context.
294                
295                Pass name of a file with DS and DNSKEY records (like from dig or drill).
296                
297                :param fname:
298                    filename of file with keyfile with trust anchors.
299                :returns: (int) 0 if OK, else error.
300             """
301             return _unbound.ub_ctx_add_ta_file(self,fname)
302             #parameters: struct ub_ctx *,char *,
303             #retvals: int
304
305         def config(self,fname):
306             """setup configuration for the given context.
307                
308                :param fname:
309                    unbound config file (not all settings applicable). This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist.
310                :returns: (int) 0 if OK, else error.
311             """
312             return _unbound.ub_ctx_config(self,fname)
313             #parameters: struct ub_ctx *,char *,
314             #retvals: int
315
316         def debuglevel(self,d):
317             """Set debug verbosity for the context Output is directed to stderr.
318                
319                :param d:
320                    debug level, 0 is off, 1 is very minimal, 2 is detailed, and 3 is lots.
321                :returns: (int) 0 if OK, else error.
322             """
323             return _unbound.ub_ctx_debuglevel(self,d)
324             #parameters: struct ub_ctx *,int,
325             #retvals: int
326
327         def debugout(self,out):
328             """Set debug output (and error output) to the specified stream.
329                
330                Pass None to disable. Default is stderr.
331                
332                :param out:
333                    File stream to log to.
334                :returns: (int) 0 if OK, else error.
335
336                **Usage:**
337
338                   In order to log into file, use
339
340                   ::
341
342                     ctx = unbound.ub_ctx()
343                     fw = fopen("debug.log")
344                     ctx.debuglevel(3)
345                     ctx.debugout(fw)
346
347                   Another option is to print the debug informations to stderr output
348
349                   ::
350
351                     ctx = unbound.ub_ctx()
352                     ctx.debuglevel(10)
353                     ctx.debugout(sys.stderr) 
354             """
355             return _unbound.ub_ctx_debugout(self,out)
356             #parameters: struct ub_ctx *,void *,
357             #retvals: int
358
359         def hosts(self,fname="/etc/hosts"):
360             """Read list of hosts from the filename given.
361                
362                Usually "/etc/hosts". These addresses are not flagged as DNSSEC secure when queried for.
363                
364                :param fname:
365                    file name string. If None "/etc/hosts" is used.
366                :returns: (int) 0 if OK, else error.
367             """
368             return _unbound.ub_ctx_hosts(self,fname)
369             #parameters: struct ub_ctx *,char *,
370             #retvals: int
371
372         def print_local_zones(self):
373             """Print the local zones and their content (RR data) to the debug output.
374                
375                :returns: (int) 0 if OK, else error.
376             """
377             return _unbound.ub_ctx_print_local_zones(self)
378             #parameters: struct ub_ctx *,
379             #retvals: int
380
381         def resolvconf(self,fname="/etc/resolv.conf"):
382             """Read list of nameservers to use from the filename given.
383                
384                Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. If they do not support DNSSEC, validation may fail.
385                
386                Only nameservers are picked up, the searchdomain, ndots and other settings from resolv.conf(5) are ignored.
387                
388                :param fname:
389                    file name string. If None "/etc/resolv.conf" is used.
390                :returns: (int) 0 if OK, else error.
391             """
392             return _unbound.ub_ctx_resolvconf(self,fname)
393             #parameters: struct ub_ctx *,char *,
394             #retvals: int
395
396         def set_async(self,dothread):
397             """Set a context behaviour for asynchronous action.
398                
399                :param dothread:
400                    if True, enables threading and a call to :meth:`resolve_async` creates a thread to handle work in the background. 
401                    If False, a process is forked to handle work in the background. 
402                    Changes to this setting after :meth:`async` calls have been made have no effect (delete and re-create the context to change).
403                :returns: (int) 0 if OK, else error.
404             """
405             return _unbound.ub_ctx_async(self,dothread)
406             #parameters: struct ub_ctx *,int,
407             #retvals: int
408
409         def set_fwd(self,addr):
410             """Set machine to forward DNS queries to, the caching resolver to use.
411                
412                IP4 or IP6 address. Forwards all DNS requests to that machine, which is expected to run a recursive resolver. If the  is not DNSSEC-capable, validation may fail. Can be called several times, in that case the addresses are used as backup servers.
413                
414                To read the list of nameservers from /etc/resolv.conf (from DHCP or so), use the call :meth:`resolvconf`.
415                
416                :param addr:
417                    address, IP4 or IP6 in string format. If the addr is None, forwarding is disabled.
418                :returns: (int) 0 if OK, else error.
419             """
420             return _unbound.ub_ctx_set_fwd(self,addr)
421             #parameters: struct ub_ctx *,char *,
422             #retvals: int
423
424         def set_option(self,opt,val):
425             """Set an option for the context.
426
427                Changes to the options after :meth:`resolve`, :meth:`resolve_async`, :meth:`zone_add`, :meth:`zone_remove`, :meth:`data_add` or :meth:`data_remove` have no effect (you have to delete and re-create the context).
428                
429                :param opt:
430                    option name from the unbound.conf config file format. (not all settings applicable). The name includes the trailing ':' for example set_option("logfile:", "mylog.txt"); This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist.
431                :param val:
432                    value of the option.
433                :returns: (int) 0 if OK, else error.
434             """
435             return _unbound.ub_ctx_set_option(self,opt,val)
436             #parameters: struct ub_ctx *,char *,char *,
437             #retvals: int
438
439         def trustedkeys(self,fname):
440             """Add trust anchors to the given context.
441                
442                Pass the name of a bind-style config file with trusted-keys{}.
443                
444                :param fname:
445                    filename of file with bind-style config entries with trust anchors.
446                :returns: (int) 0 if OK, else error.
447             """
448             return _unbound.ub_ctx_trustedkeys(self,fname)
449             #parameters: struct ub_ctx *,char *,
450             #retvals: int
451         #_UB_CTX_METHODS#   
452         
453         def zone_print(self):
454             """Print local zones using debougout"""            
455             _unbound.ub_ctx_print_local_zones(self)
456
457         def zone_add(self,zonename,zonetype):
458             """Add new local zone
459
460                :param zonename: zone domain name (e.g. myzone.)
461                :param zonetype: type of the zone ("static",...) 
462                :returns: (int) 0 if OK, else error. 
463             """ 
464             return _unbound.ub_ctx_zone_add(self,zonename, zonetype)
465             #parameters: struct ub_ctx *,char*, char*
466             #retvals: int
467
468         def zone_remove(self,zonename):
469             """Remove local zone
470             
471                If exists, removes local zone with all the RRs.
472
473                :param zonename: zone domain name
474                :returns: (int) 0 if OK, else error. 
475             """ 
476             return _unbound.ub_ctx_zone_remove(self,zonename)
477             #parameters: struct ub_ctx *,char*
478             #retvals: int
479
480         def data_add(self,rrdata):
481             """Add new local RR data
482
483                :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
484                :returns: (int) 0 if OK, else error. 
485
486                **Usage**
487                   The local data ...
488
489                   ::
490
491                     >>> ctx = unbound.ub_ctx()
492                     >>> ctx.zone_add("mydomain.net.","static")
493                     0
494                     >>> status = ctx.data_add("test.mydomain.net. IN A 192.168.1.1")
495                     0
496                     >>> status, result = ctx.resolve("test.mydomain.net")
497                     >>> if status==0 and result.havedata:
498                     >>>    print \"Result:\",result.data.address_list
499                     Result: ['192.168.1.1']
500
501             """ 
502             return _unbound.ub_ctx_data_add(self,rrdata)
503             #parameters: struct ub_ctx *,char*
504             #retvals: int
505
506         def data_remove(self,rrdata):
507             """Remove local RR data
508
509                If exists, remove resource record from local zone
510
511                :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
512                :returns: (int) 0 if OK, else error. 
513             """ 
514             return _unbound.ub_ctx_data_remove(self,rrdata)
515             #parameters: struct ub_ctx *,char*
516             #retvals: int
517
518         #UB_METHODS_#
519         def cancel(self,async_id):
520             """Cancel an async query in progress.
521                
522                Its callback will not be called.
523                
524                :param async_id:
525                    which query to cancel.
526                :returns: (int) 0 if OK, else error.
527             """
528             return _unbound.ub_cancel(self,async_id)
529             #parameters: struct ub_ctx *,int,
530             #retvals: int
531
532         def get_fd(self):
533             """Get file descriptor.
534                
535                Wait for it to become readable, at this point answers are returned from the asynchronous validating resolver. Then call the ub_process to continue processing. This routine works immediately after context creation, the fd does not change.
536                
537                :returns: (int) -1 on error, or file descriptor to use select(2) with.
538             """
539             return _unbound.ub_fd(self)
540             #parameters: struct ub_ctx *,
541             #retvals: int
542
543         def poll(self):
544             """Poll a context to see if it has any new results Do not poll in a loop, instead extract the fd below to poll for readiness, and then check, or wait using the wait routine.
545                
546                :returns: (int) 0 if nothing to read, or nonzero if a result is available. If nonzero, call ctx_process() to do callbacks.
547             """
548             return _unbound.ub_poll(self)
549             #parameters: struct ub_ctx *,
550             #retvals: int
551
552         def process(self):
553             """Call this routine to continue processing results from the validating resolver (when the fd becomes readable).
554                
555                Will perform necessary callbacks.
556                
557                :returns: (int) 0 if OK, else error.
558             """
559             return _unbound.ub_process(self)
560             #parameters: struct ub_ctx *,
561             #retvals: int
562
563         def resolve(self,name,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN):
564             """Perform resolution and validation of the target name. 
565                
566                :param name:
567                    domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string.
568                :param rrtype:
569                    type of RR in host order (optional argument). Default value is RR_TYPE_A (A class).
570                :param rrclass:
571                    class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet).
572                :returns: * (int) 0 if OK, else error.
573                          * (:class:`ub_result`) the result data is returned in a newly allocated result structure. May be None on return, return value is set to an error in that case (out of memory).
574             """
575             if isinstance(name, bytes): #probably IDN
576                 return _unbound.ub_resolve(self,name,rrtype,rrclass)
577             else:
578                 return _unbound.ub_resolve(self,idn2dname(name),rrtype,rrclass)
579             #parameters: struct ub_ctx *,char *,int,int,
580             #retvals: int,struct ub_result **
581
582         def resolve_async(self,name,mydata,callback,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN):
583             """Perform resolution and validation of the target name.
584                
585                Asynchronous, after a while, the callback will be called with your data and the result. 
586                If an error happens during processing, your callback will be called with error set to a nonzero value (and result==None).
587                
588                :param name:
589                    domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string.
590                :param mydata:
591                    this data is your own data (you can pass arbitrary python object or None) which are passed on to the callback function.
592                :param callback:
593                    call-back function which is called on completion of the resolution. 
594                :param rrtype:
595                    type of RR in host order (optional argument). Default value is RR_TYPE_A (A class).
596                :param rrclass:
597                    class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet).
598                :returns: * (int) 0 if OK, else error.
599                          * (int) async_id, an identifier number is returned for the query as it is in progress. It can be used to cancel the query.
600
601                **Call-back function:**
602                     The call-back function looks as the follows::
603                     
604                         def call_back(mydata, status, result):
605                             pass
606
607                     **Parameters:** 
608                         * `mydata` - mydata object
609                         * `status` - 0 when a result has been found
610                         * `result` - the result structure. The result may be None, in that case err is set.
611
612             """
613             if isinstance(name, bytes): #probably IDN
614                 return _unbound._ub_resolve_async(self,name,rrtype,rrclass,mydata,callback)
615             else:
616                 return _unbound._ub_resolve_async(self,idn2dname(name),rrtype,rrclass,mydata,callback)
617             #parameters: struct ub_ctx *,char *,int,int,void *,ub_callback_t,
618             #retvals: int, int
619
620         def wait(self):
621             """Wait for a context to finish with results.
622                
623                Calls  after the wait for you. After the wait, there are no more outstanding asynchronous queries.
624                
625                :returns: (int) 0 if OK, else error.
626             """
627             return _unbound.ub_wait(self)
628             #parameters: struct ub_ctx *,
629             #retvals: int
630
631         #_UB_METHODS#
632  %}
633 }
634
635
636 // ================================================================================
637 // ub_result - validation and resolution results
638 // ================================================================================
639 %nodefaultctor ub_result; //no default constructor & destructor
640 %nodefaultdtor ub_result;
641
642 %delobject ub_resolve_free;
643 %rename(_ub_resolve_free) ub_resolve_free;
644  
645 %inline %{
646   void ub_resolve_free_dbg (struct ub_result* r) {
647     printf("******** UB_RESOLVE free 0x%lX ************\n", (long unsigned int)r);
648     ub_resolve_free(r);
649   }
650 %} 
651
652 %feature("docstring") ub_result "The validation and resolution results."
653
654 //ub_result.rcode
655 %inline %{
656   enum result_enum_rcode {
657     RCODE_NOERROR = 0,
658     RCODE_FORMERR = 1,
659     RCODE_SERVFAIL = 2,
660     RCODE_NXDOMAIN = 3,
661     RCODE_NOTIMPL = 4,
662     RCODE_REFUSED = 5,
663     RCODE_YXDOMAIN = 6,
664     RCODE_YXRRSET = 7,
665     RCODE_NXRRSET = 8,
666     RCODE_NOTAUTH = 9,
667     RCODE_NOTZONE = 10
668   };
669 %}
670
671 %pythoncode %{
672    class ub_data:
673       """Class which makes the resolution results accessible"""
674       def __init__(self, data):
675          """Creates ub_data class
676             :param data: a list of the result data in RAW format
677          """
678          if data == None:
679             raise Exception("ub_data init: No data")
680          self.data = data
681
682       def __str__(self):
683          """Represents data as string"""
684          return ';'.join([' '.join(map(lambda x:"%02X" % ord(x),a)) for a in self.data])
685
686       @staticmethod
687       def dname2str(s, ofs=0, maxlen=0):
688          """Parses DNAME and produces a list of labels
689         
690             :param ofs: where the conversion should start to parse data
691             :param maxlen: maximum length (0 means parse to the end)
692             :returns: list of labels (string)
693          """
694          if not s:
695             return []
696
697          res = []
698          slen = len(s)
699          if maxlen > 0:
700             slen = min(slen, maxlen)
701
702          idx = ofs
703          while (idx < slen):
704             complen = ord(s[idx])
705             # In python 3.x `str()` converts the string to unicode which is the expected text string type
706             res.append(str(s[idx+1:idx+1+complen].decode()))
707             idx += complen + 1
708
709          return res
710
711       def as_raw_data(self):
712          """Returns a list of RAW strings"""
713          return self.data
714
715       raw = property(as_raw_data, doc="Returns RAW data (a list of binary encoded strings). See :meth:`as_raw_data`")
716
717       def as_mx_list(self):
718          """Represents data as a list of MX records (query for RR_TYPE_MX)
719         
720             :returns: list of tuples (priority, dname)
721          """
722          return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([a for a in self.dname2str(rdf,2)])) for rdf in self.data]
723       
724       mx_list = property(as_mx_list, doc="Returns a list of tuples containing priority and domain names. See :meth:`as_mx_list`")
725
726       def as_idn_mx_list(self):
727          """Represents data as a list of MX records (query for RR_TYPE_MX)
728         
729             :returns: list of tuples (priority, unicode dname)
730          """
731          return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(rdf,2)])) for rdf in self.data]
732
733       mx_list_idn = property(as_idn_mx_list, doc="Returns a list of tuples containing priority and IDN domain names. See :meth:`as_idn_mx_list`")
734
735       def as_address_list(self):
736          """Represents data as a list of IP addresses (query for RR_TYPE_PTR)
737         
738             :returns: list of strings
739          """
740          return ['.'.join(map(lambda x:str(ord(x)),a)) for a in self.data]
741
742       address_list = property(as_address_list, doc="Returns a list of IP addresses. See :meth:`as_address_list`")
743
744       def as_domain_list(self):
745          """Represents data as a list of domain names (query for RR_TYPE_A)
746
747             :returns: list of strings
748          """
749          return map(lambda x:'.'.join(self.dname2str(x)), self.data)
750
751       domain_list = property(as_domain_list, doc="Returns a list of domain names. See :meth:`as_domain_list`")
752
753       def as_idn_domain_list(self):
754          """Represents data as a list of unicode domain names (query for RR_TYPE_A)
755
756             :returns: list of strings
757          """
758          return map(lambda x: '.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(x)]), self.data)
759
760       domain_list_idn = property(as_idn_domain_list, doc="Returns a list of IDN domain names. See :meth:`as_idn_domain_list`")
761 %}
762         
763 %extend ub_result
764 {
765
766   %rename(_data) data;
767   
768   PyObject* _ub_result_data(struct ub_result* result) {
769     PyObject  *list;
770      int i,cnt;
771      (void)self;
772      if ((result == 0) || (!result->havedata) || (result->data == 0))
773         return Py_None;
774
775      for (cnt=0,i=0;;i++,cnt++) 
776          if (result->data[i] == 0)
777             break;
778      
779      list = PyList_New(cnt);
780      for (i=0;i<cnt;i++) 
781          PyList_SetItem(list, i, PyBytes_FromStringAndSize(result->data[i],result->len[i]));
782      
783      return list;
784   }
785
786   PyObject* _packet() {
787       return PyBytes_FromStringAndSize($self->answer_packet, $self->answer_len);
788   }
789   
790  %pythoncode %{
791    def __init__(self):
792        raise Exception("This class can't be created directly.")
793
794    #__swig_destroy__ = _unbound.ub_resolve_free_dbg
795    __swig_destroy__ = _unbound._ub_resolve_free
796
797    #havedata = property(_unbound.ub_result_havedata_get, _unbound.ub_result_havedata_set, "Havedata property")
798
799    rcode2str = {RCODE_NOERROR:'no error', RCODE_FORMERR:'form error', RCODE_SERVFAIL:'serv fail', RCODE_NXDOMAIN:'nx domain', RCODE_NOTIMPL:'not implemented', RCODE_REFUSED:'refused', RCODE_YXDOMAIN:'yxdomain', RCODE_YXRRSET:'yxrrset', RCODE_NXRRSET:'nxrrset', RCODE_NOTAUTH:'not auth', RCODE_NOTZONE:'not zone'}
800
801    def _get_rcode_str(self):
802        """Returns rcode in display representation form
803
804           :returns: string
805        """
806        return self.rcode2str[self.rcode]
807
808    __swig_getmethods__["rcode_str"] = _get_rcode_str
809    if _newclass:rcode_str = _swig_property(_get_rcode_str)
810
811    def _get_raw_data(self):
812        """Result data, a list of network order DNS rdata items. 
813
814           Data are represented as a list of strings. To decode RAW data to the list of IP addresses use :attr:`data` attribute which returns an :class:`ub_data` instance containing conversion function.
815        """
816        return self._ub_result_data(self)
817
818    __swig_getmethods__["rawdata"] = _get_raw_data
819    rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.")
820
821    def _get_data(self):
822        if not self.havedata: return None
823        return ub_data(self._ub_result_data(self))
824   
825    __swig_getmethods__["data"] = _get_data
826    __swig_getmethods__["packet"] = _packet
827    data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
828
829 %}
830              
831 }
832
833 %exception ub_resolve
834 %{ 
835   //printf("resolve_start(%lX)\n",(long unsigned int)arg1);
836   Py_BEGIN_ALLOW_THREADS 
837   $function 
838   Py_END_ALLOW_THREADS 
839   //printf("resolve_stop()\n");
840 %} 
841
842 %include "libunbound/unbound.h"
843
844 %inline %{
845   //SWIG will see the ub_ctx as a class
846   struct ub_ctx {
847   };
848 %}
849
850 //ub_ctx_debugout void* parameter correction
851 int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
852
853 // ================================================================================
854 // ub_resolve_async - perform asynchronous resolution and validation
855 // ================================================================================
856
857 %typemap(in,numinputs=0,noblock=1) (int* async_id)  
858
859    int asyncid = -1;
860    $1 = &asyncid;
861
862
863 %apply PyObject* {void* mydata}
864        
865 /* result generation */
866 %typemap(argout,noblock=1) (int* async_id)
867 {
868   if(1) { /* new code block for variable on stack */
869     PyObject* tuple;
870     tuple = PyTuple_New(2);
871     PyTuple_SetItem(tuple, 0, $result);
872     PyTuple_SetItem(tuple, 1, SWIG_From_int(asyncid));
873     $result = tuple;
874   }
875 }
876
877 // Grab a Python function object as a Python object.
878 %typemap(in) (PyObject *pyfunc) {
879   if (!PyCallable_Check($input)) 
880   {
881      PyErr_SetString(PyExc_TypeError, "Need a callable object!");
882      return NULL;
883   }
884   $1 = $input;
885 }
886    
887 // Python callback workaround
888 int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, void* mydata, PyObject *pyfunc, int* async_id);
889
890 %{
891    struct cb_data {
892       PyObject* data;
893       PyObject* func;
894    };
895
896    static void PythonCallBack(void* iddata, int status, struct ub_result* result)
897    {
898       PyObject *arglist;
899       PyObject *fresult;
900       struct cb_data* id;
901       id = (struct cb_data*) iddata;
902       arglist = Py_BuildValue("(OiO)",id->data,status, SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_result, 0 |  0 ));   // Build argument list
903       fresult = PyEval_CallObject(id->func,arglist);     // Call Python
904       Py_DECREF(id->func);
905       Py_DECREF(id->data);
906       free(id);
907       ub_resolve_free(result);                  //free ub_result
908       //ub_resolve_free_dbg(result);                  //free ub_result
909       Py_DECREF(arglist);                           // Trash arglist
910       Py_XDECREF(fresult);
911    }
912
913    int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, PyObject* mydata, PyObject *pyfunc, int* async_id) {
914       int r;
915       struct cb_data* id;
916       id = (struct cb_data*) malloc(sizeof(struct cb_data));
917       id->data = mydata;
918       id->func = pyfunc;
919    
920       r = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id);
921       Py_INCREF(mydata);
922       Py_INCREF(pyfunc);
923       return r;
924    }
925
926 %}
927
928 %pythoncode %{
929     ub_resolve_async = _unbound._ub_resolve_async
930
931     def reverse(domain):
932         """Reverse domain name
933         
934            Usable for reverse lookups when the IP address should be reversed
935         """
936         return '.'.join([a for a in domain.split(".")][::-1])
937
938     def idn2dname(idnname):
939         """Converts domain name in IDN format to canonic domain name
940
941            :param idnname: (unicode string) IDN name
942            :returns: (string) domain name
943         """
944         return '.'.join([encodings.idna.ToASCII(a) for a in idnname.split('.')])
945
946     def dname2idn(name):
947         """Converts canonic domain name in IDN format to unicode string
948
949             :param name: (string) domain name
950             :returns: (unicode string) domain name
951         """
952         return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')])
953
954 %}
955