]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
Add python3 support. Thanks to Zbynek Michl.
authorWillem Toorop <willem@NLnetLabs.nl>
Thu, 25 Aug 2011 13:55:43 +0000 (13:55 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Thu, 25 Aug 2011 13:55:43 +0000 (13:55 +0000)
15 files changed:
configure.ac
contrib/python/examples/python3/ldns-axfr.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-buf.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-dnssec.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-higher.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-keygen.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-mx.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-mx1.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-mx2.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-newpkt.py [new file with mode: 0755]
contrib/python/examples/python3/ldns-zone.py [new file with mode: 0755]
contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py [new file with mode: 0644]
contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py [new file with mode: 0644]
contrib/python/file_py3.i [new file with mode: 0644]
contrib/python/ldns.i

index b2e53b383b28fc6bce75b2fa4898ab4508094614..9a2d4a6c166bd8652708a1e7832375a7a4f21bed 100644 (file)
@@ -108,7 +108,7 @@ if test x_$withval != x_no; then
    if test `$PYTHON -c "import sys; \
        ver = sys.version.split()[[0]]; \
        print(ver >= '3.0.0')"` = "True"; then
-       AC_SUBST(SWIGPY3, [-py3])
+       AC_SUBST(SWIGPY3, ["-py3 -DPY3"])
    fi
 
    # check for swig
diff --git a/contrib/python/examples/python3/ldns-axfr.py b/contrib/python/examples/python3/ldns-axfr.py
new file mode 100755 (executable)
index 0000000..fb8e5cf
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+#
+# AXFR client with IDN (Internationalized Domain Names) support
+#
+
+import ldns
+import encodings.idna
+
+def utf2name(name):
+    return '.'.join([encodings.idna.ToASCII(a).decode("utf-8") for a in name.split('.')])
+def name2utf(name):
+    return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')])
+
+
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+
+#addr = ldns.ldns_get_rr_list_addr_by_name(resolver, "zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD);
+addr = resolver.get_addr_by_name("zone.nic.cz", ldns.LDNS_RR_CLASS_IN, ldns.LDNS_RD);
+if (not addr):
+    raise Exception("Can't retrieve server address")
+
+print("Addr_by_name:",str(addr).replace("\n","; "))
+
+#remove all nameservers
+while resolver.pop_nameserver(): 
+    pass
+
+#insert server addr
+for rr in addr.rrs():
+    resolver.push_nameserver_rr(rr)
+
+#AXFR transfer
+status = resolver.axfr_start(utf2name("háčkyčárky.cz"), ldns.LDNS_RR_CLASS_IN)
+if status != ldns.LDNS_STATUS_OK:
+    raise Exception("Can't start AXFR. Error: %s" % ldns.ldns_get_errorstr_by_id(status))
+
+#Print results
+while True:
+    rr = resolver.axfr_next()
+    if not rr: 
+        break
+
+    rdf = rr.owner()
+    if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME):
+        print("RDF owner: type=",rdf.get_type_str(),"data=",name2utf(str(rdf)))
+    else:
+        print("RDF owner: type=",rdf.get_type_str(),"data=",str(rdf))
+    print("   RR type=", rr.get_type_str()," ttl=",rr.ttl())
+    for rdf in rr.rdfs():
+        if (rdf.get_type() == ldns.LDNS_RDF_TYPE_DNAME):
+            print("   RDF: type=",rdf.get_type_str(),"data=",name2utf(str(rdf)))
+        else:
+            print("   RDF: type=",rdf.get_type_str(),"data=",str(rdf))
+
+    print()
diff --git a/contrib/python/examples/python3/ldns-buf.py b/contrib/python/examples/python3/ldns-buf.py
new file mode 100755 (executable)
index 0000000..498d51f
--- /dev/null
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+
+import ldns
+
+buf = ldns.ldns_buffer(1024)
+buf.printf("Test buffer")
+print(buf)
+
diff --git a/contrib/python/examples/python3/ldns-dnssec.py b/contrib/python/examples/python3/ldns-dnssec.py
new file mode 100755 (executable)
index 0000000..7dabb91
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import ldns
+import sys
+
+debug = True
+
+# Check args
+argc = len(sys.argv)
+name = "www.nic.cz"
+if argc < 2:
+   print("Usage:", sys.argv[0], "domain [resolver_addr]")
+   sys.exit(1)
+else:
+   name = sys.argv[1]
+
+# Create resolver
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+resolver.set_dnssec(True)
+
+# Custom resolver
+if argc > 2:
+   # Clear previous nameservers
+   ns = resolver.pop_nameserver()
+   while ns != None:
+      ns = resolver.pop_nameserver()
+   ip = ldns.ldns_rdf.new_frm_str(sys.argv[2], ldns.LDNS_RDF_TYPE_A)
+   resolver.push_nameserver(ip)
+
+# Resolve DNS name
+pkt = resolver.query(name, ldns.LDNS_RR_TYPE_A, ldns.LDNS_RR_CLASS_IN)
+if pkt and pkt.answer():
+
+   # Debug
+   if debug:
+      print("NS returned:", pkt.get_rcode(), "(AA: %d AD: %d)" % ( pkt.ad(), pkt.ad() ))
+
+   # SERVFAIL indicated bogus name
+   if pkt.get_rcode() is ldns.LDNS_RCODE_SERVFAIL:
+      print(name, "is bogus")
+
+   # Check AD (Authenticated) bit
+   if pkt.get_rcode() is ldns.LDNS_RCODE_NOERROR:
+      if pkt.ad(): print(name, "is secure")
+      else:        print(name, "is insecure")
diff --git a/contrib/python/examples/python3/ldns-higher.py b/contrib/python/examples/python3/ldns-higher.py
new file mode 100755 (executable)
index 0000000..8712e63
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+import ldns
+
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+
+dnn = ldns.ldns_dname("www.google.com")
+print(dnn.get_type_str(), dnn)
+
+dna = ldns.ldns_rdf.new_frm_str("74.125.43.99",ldns.LDNS_RDF_TYPE_A)
+print(dna.get_type_str(), dna)
+
+name = resolver.get_name_by_addr(dna)
+if (not name): raise Exception("Can't retrieve server name")
+for rr in name.rrs():
+    print(rr)
+
+name = resolver.get_name_by_addr("74.125.43.99")
+if (not name): raise Exception("Can't retrieve server name")
+for rr in name.rrs():
+    print(rr)
+
+addr = resolver.get_addr_by_name(dnn)
+if (not addr): raise Exception("Can't retrieve server address")
+for rr in addr.rrs():
+    print(rr)
+
+addr = resolver.get_addr_by_name("www.google.com")
+if (not addr): raise Exception("Can't retrieve server address")
+for rr in addr.rrs():
+    print(rr)
+
+hosts = ldns.ldns_rr_list.new_frm_file("/etc/hosts")
+if (not hosts): raise Exception("Can't retrieve the content of file")
+for rr in hosts.rrs():
+    print(rr)
+
diff --git a/contrib/python/examples/python3/ldns-keygen.py b/contrib/python/examples/python3/ldns-keygen.py
new file mode 100755 (executable)
index 0000000..4a5457e
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+#
+# This example shows how to generate public/private key pair
+#
+import ldns
+
+algorithm = ldns.LDNS_SIGN_DSA
+bits = 512
+
+ldns.ldns_init_random(open("/dev/random","rb"), (bits+7)//8)
+
+domain = ldns.ldns_dname("example.")
+
+#generate a new key
+key = ldns.ldns_key.new_frm_algorithm(algorithm, bits);
+print(key)
+
+#set owner
+key.set_pubkey_owner(domain)
+
+#create the public from the ldns_key
+pubkey = key.key_to_rr()
+#previous command is equivalent to
+# pubkey = ldns.ldns_key2rr(key)
+print(pubkey)
+
+#calculate and set the keytag
+key.set_keytag(ldns.ldns_calc_keytag(pubkey))
+
+#build the DS record
+ds = ldns.ldns_key_rr2ds(pubkey, ldns.LDNS_SHA1)
+print(ds)
+
+owner, tag = pubkey.owner(), key.keytag()
+
+#write public key to .key file
+fw = open("key-%s-%d.key" % (owner,tag), "wb")
+pubkey.print_to_file(fw)
+
+#write private key to .priv file
+fw = open("key-%s-%d.private" % (owner,tag), "wb")
+key.print_to_file(fw)
+
+#write DS to .ds file
+fw = open("key-%s-%d.ds" % (owner,tag), "wb")
+ds.print_to_file(fw)
diff --git a/contrib/python/examples/python3/ldns-mx.py b/contrib/python/examples/python3/ldns-mx.py
new file mode 100755 (executable)
index 0000000..1d2ba03
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+#
+# MX is a small program that prints out the mx records for a particular domain
+#
+import ldns
+
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+
+pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN)
+
+if (pkt):
+    mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER)
+    if (mx):
+       mx.sort()
+       print(mx)
diff --git a/contrib/python/examples/python3/ldns-mx1.py b/contrib/python/examples/python3/ldns-mx1.py
new file mode 100755 (executable)
index 0000000..d10863e
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/python
+#
+# MX is a small program that prints out the mx records for a particular domain
+#
+import ldns
+
+dname = ldns.ldns_dname("nic.cz")
+print(dname)
+
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+
+pkt = resolver.query(dname, ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN)
+
+if (pkt):
+    mx = pkt.rr_list_by_type(ldns.LDNS_RR_TYPE_MX, ldns.LDNS_SECTION_ANSWER)
+    if (mx):
+       mx.sort()
+       print(mx)
diff --git a/contrib/python/examples/python3/ldns-mx2.py b/contrib/python/examples/python3/ldns-mx2.py
new file mode 100755 (executable)
index 0000000..9c8b103
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+#
+# MX is a small program that prints out the mx records for a particular domain
+#
+import ldns
+
+resolver = ldns.ldns_resolver.new_frm_file("/etc/resolv.conf")
+
+pkt = resolver.query("nic.cz", ldns.LDNS_RR_TYPE_MX,ldns.LDNS_RR_CLASS_IN)
+if (pkt) and (pkt.answer()):
+
+    for rr in pkt.answer().rrs():
+        if (rr.get_type() != ldns.LDNS_RR_TYPE_MX):
+            continue
+
+        rdf = rr.owner()
+        print(rdf," ",rr.ttl()," ",rr.get_class_str()," ",rr.get_type_str()," ", end=" ")
+        print(" ".join(str(rdf) for rdf in rr.rdfs()))
+
diff --git a/contrib/python/examples/python3/ldns-newpkt.py b/contrib/python/examples/python3/ldns-newpkt.py
new file mode 100755 (executable)
index 0000000..49bad5e
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+import ldns
+
+pkt = ldns.ldns_pkt.new_query_frm_str("www.google.com",ldns.LDNS_RR_TYPE_ANY, ldns.LDNS_RR_CLASS_IN, ldns.LDNS_QR | ldns.LDNS_AA)
+
+rra = ldns.ldns_rr.new_frm_str("www.google.com. IN A 192.168.1.1",300)
+rrb = ldns.ldns_rr.new_frm_str("www.google.com. IN TXT Some\ Description",300)
+
+list = ldns.ldns_rr_list()
+if (rra): list.push_rr(rra)
+if (rrb): list.push_rr(rrb)
+
+pkt.push_rr_list(ldns.LDNS_SECTION_ANSWER, list)
+
+print("Packet:")
+print(pkt)
diff --git a/contrib/python/examples/python3/ldns-zone.py b/contrib/python/examples/python3/ldns-zone.py
new file mode 100755 (executable)
index 0000000..b465eaa
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+import ldns
+
+#Read zone from file
+zone = ldns.ldns_zone.new_frm_fp(open("../zone.txt","r"), None, 0, ldns.LDNS_RR_CLASS_IN)
+print(zone)
+
+print("SOA:", zone.soa())
+for r in zone.rrs().rrs():
+   print("RR:", r)
+
+
+zone = ldns.ldns_zone()
+#print zone
+
diff --git a/contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py b/contrib/python/examples/python3/ldns_rr_iter_frm_fp_l.demo.py
new file mode 100644 (file)
index 0000000..18edd11
--- /dev/null
@@ -0,0 +1,12 @@
+import ldns
+import sys
+
+if len(sys.argv) <= 1:
+    print("Usage: %s zone_file" % sys.argv[0])
+    sys.exit()
+
+inp = open(sys.argv[1],"r");
+for rr in ldns.ldns_rr_iter_frm_fp_l(inp):
+  print(rr)
+
+inp.close()
diff --git a/contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py b/contrib/python/examples/python3/ldns_rr_new_frm_fp_l.demo.py
new file mode 100644 (file)
index 0000000..1bd667b
--- /dev/null
@@ -0,0 +1,43 @@
+import ldns
+import sys
+
+if len(sys.argv) <= 1:
+    print("Usage: %s zone_file" % sys.argv[0])
+    sys.exit()
+
+inp = open(sys.argv[1],"r");
+# variables that preserve the parsers state
+my_ttl = 3600;
+my_origin = None
+my_prev = None
+# additional state variables
+last_pos = 0
+line_nr = 0
+
+while True:
+    ret = ldns.ldns_rr_new_frm_fp_l_(inp, my_ttl, my_origin, my_prev)
+    s, rr, line_inc, new_ttl, new_origin, new_prev = ret  # unpack the result
+    line_nr += line_inc # increase number of parsed lines
+    my_prev = new_prev  # update ref to previous owner
+
+    if s == ldns.LDNS_STATUS_SYNTAX_TTL:
+        my_ttl = new_ttl  # update default TTL
+        print("$TTL:", my_ttl)
+    elif s == ldns.LDNS_STATUS_SYNTAX_ORIGIN:
+        my_origin = new_origin  # update reference to origin
+        print("$ORIGIN:", my_origin)
+    elif s == ldns.LDNS_STATUS_SYNTAX_EMPTY:
+        if last_pos == inp.tell():
+            break  # no advance since last read - EOF
+        last_pos = inp.tell()
+    elif s != ldns.LDNS_STATUS_OK:
+        print("! parse error in line", line_nr)
+    else:
+        # we are sure to have LDNS_STATUS_OK
+        print(rr)
+
+inp.close()
+print("--------------------")
+print("Read %d lines" % line_nr)
+    
+
diff --git a/contrib/python/file_py3.i b/contrib/python/file_py3.i
new file mode 100644 (file)
index 0000000..b3f55e8
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * file_py3.i: Typemaps for FILE* for Python 3
+ *
+ * Copyright (c) 2011, Karel Slany (karel.slany AT nic.cz)
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the organization nor the names of its
+ *       contributors may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+%{
+#include <unistd.h>
+#include <fcntl.h>
+%}
+
+%types(FILE *);
+
+/* converts basic file descriptor flags onto a string */
+%fragment("fdfl_to_str", "header") {
+const char *
+fdfl_to_str(int fdfl) {
+
+  static const char * const file_mode[] = {"w+", "w", "r"};
+
+  if (fdfl & O_RDWR) {
+    return file_mode[0];
+  } else if (fdfl & O_WRONLY) {
+    return file_mode[1];
+  } else {
+    return file_mode[2];
+  }
+}
+}
+
+%fragment("obj_to_file","header", fragment="fdfl_to_str") {
+FILE *
+obj_to_file(PyObject *obj) {
+%#if PY_VERSION_HEX >= 0x03000000
+  int fd, fdfl;
+  FILE *fp;
+  if (!PyLong_Check(obj) &&                                /* is not an integer */
+      PyObject_HasAttrString(obj, "fileno") &&             /* has fileno method */
+      (PyObject_CallMethod(obj, "flush", NULL) != NULL) && /* flush() succeeded */
+      ((fd = PyObject_AsFileDescriptor(obj)) != -1) &&     /* got file descriptor */
+      ((fdfl = fcntl(fd, F_GETFL)) != -1)                  /* got descriptor flags */
+    ) {
+    fp = fdopen(dup(fd), fdfl_to_str(fdfl)); /* the FILE* must be flushed
+                                                and closed after being used */
+#ifdef SWIG_FILE3_DEBUG
+    fprintf(stderr, "opening fd %d (fl %d \"%s\") as FILE %p\n",
+            fd, fdfl, fdfl_to_str(fdfl), (void *)fp);
+#endif
+    return fp;
+  }
+%#endif
+  return NULL;
+}
+}
+
+/* returns -1 if error occurred */
+%fragment("dispose_file", "header") {
+int
+dispose_file(FILE **fp) {
+#ifdef SWIG_FILE3_DEBUG
+  fprintf(stderr, "flushing FILE %p\n", (void *)fp);
+#endif
+  if (*fp == NULL) {
+    return 0;
+  }
+  if ((fflush(*fp) == 0) &&  /* flush file */
+      (fclose(*fp) == 0)) {  /* close file */
+    *fp = NULL;
+    return 0;
+  }
+  return -1;
+}
+}
+
+%typemap(arginit, noblock = 1) FILE* {
+  $1 = NULL;
+}
+
+%typemap(check, noblock = 1) FILE* {
+  if ($1 == NULL) {
+    SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname" "', argument "
+                        "$argnum"" of type '" "$type""'");
+  }
+}
+
+%typemap(in, noblock = 1, fragment = "obj_to_file") FILE* {
+  $1 = obj_to_file($input);
+}
+
+%typemap(freearg, noblock = 1, fragment = "dispose_file") FILE* {
+  if (dispose_file(&$1) == -1) {
+    SWIG_exception_fail(SWIG_IOError, "closing file in method '" "$symname" "', argument "
+                        "$argnum"" of type '" "$type""'");
+  }
+}
index ad0f2c87a50856789fe744419bba3546e6c75d36..56faaf93c27e34b35949510c2462c0f6766c4772 100644 (file)
 %}
 
 //#define LDNS_DEBUG
+//#define SWIG_FILE3_DEBUG
 
 %include "stdint.i" // uint_16_t is known type now
+#ifdef PY3
+%include "file_py3.i" // python 3 FILE *
+#else
 %include "file.i"     // FILE * 
+#endif
 %include "typemaps.i"
 
 %inline %{