Browse Source

Complete port to Python 3

master
Stephane Bortzmeyer 2 years ago
parent
commit
84e5435101
  1. 64
      DNSLG/Formatter.py
  2. 3
      DNSLG/LeakyBucket.py
  3. 12
      DNSLG/Resolver.py
  4. 56
      DNSLG/__init__.py
  5. 27
      db/dbconv.py
  6. 30
      db/test-instances.py
  7. 13
      sample-wsgi-dnslg-with-config-file.py
  8. 2
      sample-wsgi-dnslg.py
  9. 7
      setup.py
  10. 11
      test-my-resolver.py
  11. 15
      test-server-with-config-file.py
  12. 12
      test-server.py
  13. 3
      validator.py

64
DNSLG/Formatter.py

@ -6,13 +6,15 @@ import base64
import platform
import pkg_resources
import time
import sys
import struct
import io
# TODO: Accept explicit requests for DNAME?
# TODO: DANE/TLSA record type. Not yet in DNS Python release
# (committed in the upstream git repository) so not easy...
import Answer
from . import Answer
def to_hexstring(str):
result = ""
@ -24,7 +26,7 @@ def keylength(alg, key):
""" Returns the length in bits """
if alg == 5 or alg == 7 or alg == 8 or alg == 10:
# RSA, RFC 3110
firstbyte = struct.unpack("B", key[0])[0]
firstbyte = key[0].to_bytes(1, byteorder=sys.byteorder)[0]
if firstbyte > 0:
exponentlength = firstbyte + 1
else:
@ -35,7 +37,7 @@ def keylength(alg, key):
# the format of ECDSA or GOST keys.
return len(key)*8
class Formatter():
class Formatter(object):
""" This ia the base class for the various Formatters. A formatter
takes a "DNS answer" object and format it for a given output
format (JSON, XML, etc). Implementing a new format means deriving
@ -71,7 +73,7 @@ class TextFormatter(Formatter):
qclass_text = ", class %s" % qclass
else:
qclass_text = ""
self.output += "Query for: %s, type %s%s\n" % (self.domain.encode(querier.encoding),
self.output += "Query for: %s, type %s%s\n" % (self.domain,
qtype, qclass_text)
str_flags = ""
if flags & dns.flags.AD:
@ -163,7 +165,7 @@ class TextFormatter(Formatter):
platform.python_version(), platform.system())
def result(self, querier):
return self.output
return self.output.encode()
# ZONE FILE
@ -175,7 +177,7 @@ class ZoneFormatter(Formatter):
qclass_text = ", class %s" % qclass
else:
qclass_text = ""
self.output += "; Question: %s, type %s%s\n" % (self.domain.encode(querier.encoding),
self.output += "; Question: %s, type %s%s\n" % (self.domain,
qtype, qclass_text)
str_flags = ""
if flags & dns.flags.AD:
@ -194,7 +196,7 @@ class ZoneFormatter(Formatter):
for rdata in rrset:
# TODO: do not hardwire the class
if rdata.rdtype != dns.rdatatype.RRSIG:
self.output += "%s\tIN\t" % answer.qname # TODO: do not repeat the name if there is a RRset
self.output += "%s\tIN\t" % answer.qname.decode() # TODO: do not repeat the name if there is a RRset
# TODO: it could use some refactoring: most (but _not all_) of types
# use the same code.
if rdata.rdtype == dns.rdatatype.A:
@ -259,7 +261,7 @@ class ZoneFormatter(Formatter):
platform.python_version(), platform.system())
def result(self, querier):
return self.output
return self.output.encode()
# JSON
@ -371,7 +373,7 @@ class JsonFormatter(Formatter):
except AttributeError: # total_seconds appeared only with Python 2.7
delay = querier.delay
duration = (delay.days*86400) + delay.seconds + \
(float(delay.microseconds)/1000000.0)
(old_div(float(delay.microseconds),1000000.0))
self.object['Query'] = {'Server': answer.nameserver,
'Time': time.strftime("%Y-%m-%d %H:%M:%SZ",
time.gmtime(time.time())),
@ -385,7 +387,7 @@ class JsonFormatter(Formatter):
def result(self, querier):
return json.dumps(self.object, indent=True) + "\n"
return (json.dumps(self.object, indent=True) + "\n").encode()
# XML
@ -506,7 +508,7 @@ class XmlFormatter(Formatter):
except AttributeError: # total_seconds appeared only with Python 2.7
delay = querier.delay
duration = (delay.days*86400) + delay.seconds + \
(float(delay.microseconds)/1000000.0)
(old_div(float(delay.microseconds),1000000.0))
self.context.addGlobal ("duration", duration)
self.context.addGlobal ("time", time.strftime("%Y-%m-%d %H:%M:%SZ",
time.gmtime(time.time())))
@ -541,7 +543,7 @@ class XmlFormatter(Formatter):
self.acontext.addGlobal ("type", dns.rdatatype.to_text(rrset.rdtype))
for rdata in rrset:
icontext = simpleTALES.Context(allowPythonPath=False)
iresult = simpleTALUtils.FastStringOutput()
iresult = io.StringIO()
if rdata.rdtype == dns.rdatatype.A or rdata.rdtype == dns.rdatatype.AAAA:
icontext.addGlobal ("address", rdata.address)
if rdata.rdtype == dns.rdatatype.A:
@ -617,7 +619,7 @@ class XmlFormatter(Formatter):
icontext.addGlobal ("services", rdata.service)
icontext.addGlobal ("order", rdata.order)
icontext.addGlobal ("preference", rdata.preference)
regexp = unicode(rdata.regexp, "UTF-8")
regexp = str(rdata.regexp, "UTF-8")
icontext.addGlobal ("regexp",
regexp)
# Yes, there is Unicode in NAPTRs, see
@ -631,7 +633,7 @@ class XmlFormatter(Formatter):
# Yes, some people add Unicode in TXT records,
# see mailclub.tel for instance. We assume
# UTF-8
text = unicode(" ".join(rdata.strings), "UTF-8")
text = str(" ".join(rdata.strings), "UTF-8")
icontext.addGlobal ("text", text)
self.txt_template.expand (icontext, iresult,
suppressXMLDeclaration=True,
@ -689,26 +691,26 @@ class XmlFormatter(Formatter):
self.unknown_template.expand (icontext, iresult,
suppressXMLDeclaration=True,
outputEncoding=querier.encoding)
records.append(unicode(iresult.getvalue(), querier.encoding))
records.append(iresult.getvalue())
else:
pass # TODO what to send back when no data for this QTYPE?
if records:
self.acontext.addGlobal ("records", records)
self.acontext.addGlobal ("ttl", rrset.ttl)
iresult = simpleTALUtils.FastStringOutput()
iresult = io.StringIO()
self.set_template.expand (self.acontext, iresult,
suppressXMLDeclaration=True,
outputEncoding=querier.encoding)
self.rrsets.append(unicode(iresult.getvalue(), querier.encoding))
self.rrsets.append(iresult.getvalue())
else:
self.rrsets = None
def result(self, querier):
result = simpleTALUtils.FastStringOutput()
result = io.StringIO()
self.context.addGlobal("rrsets", self.rrsets)
self.xml_template.expand (self.context, result,
outputEncoding=querier.encoding)
return result.getvalue()
return result.getvalue().encode()
# HTML
@ -829,10 +831,10 @@ class HtmlFormatter(Formatter):
def pretty_duration(self, duration):
""" duration is in seconds """
weeks = duration/(86400*7)
days = (duration-(86400*7*weeks))/86400
hours = (duration-(86400*7*weeks)-(86400*days))/3600
minutes = (duration-(86400*7*weeks)-(86400*days)-(3600*hours))/60
weeks = old_div(duration,(86400*7))
days = old_div((duration-(86400*7*weeks)),86400)
hours = old_div((duration-(86400*7*weeks)-(86400*days)),3600)
minutes = old_div((duration-(86400*7*weeks)-(86400*days)-(3600*hours)),60)
seconds = duration-(86400*7*weeks)-(86400*days)-(3600*hours)-(60*minutes)
result = ""
empty_result = True
@ -919,7 +921,7 @@ class HtmlFormatter(Formatter):
self.context.addGlobal("description_html", querier.description_html)
elif querier.description:
self.context.addGlobal("description", querier.description)
iresult = simpleTALUtils.FastStringOutput()
iresult = io.StringIO()
icontext = simpleTALES.Context(allowPythonPath=False)
icontext.addGlobal("pyversion", platform.python_implementation() + " " +
platform.python_version() + " on " + platform.system())
@ -928,7 +930,7 @@ class HtmlFormatter(Formatter):
self.version_template.expand (icontext, iresult,
suppressXMLDeclaration=True,
outputEncoding=querier.encoding)
self.context.addGlobal("versions", unicode(iresult.getvalue(), querier.encoding))
self.context.addGlobal("versions", iresult.getvalue())
str_flags = ""
if flags & dns.flags.AD:
str_flags += "/ Authentic Data "
@ -944,7 +946,7 @@ class HtmlFormatter(Formatter):
for rrset in answer.answer:
records = []
for rdata in rrset:
iresult = simpleTALUtils.FastStringOutput()
iresult = io.StringIO()
if rdata.rdtype == dns.rdatatype.A or rdata.rdtype == dns.rdatatype.AAAA:
icontext.addGlobal ("address", rdata.address)
icontext.addGlobal ("path", self.link_of(rdata.address,
@ -1003,7 +1005,7 @@ class HtmlFormatter(Formatter):
suppressXMLDeclaration=True,
outputEncoding=querier.encoding)
elif rdata.rdtype == dns.rdatatype.TXT:
text = unicode(" ".join(rdata.strings), "UTF-8")
text = str(" ".join(rdata.strings), "UTF-8")
icontext.addGlobal ("text", text)
self.txt_template.expand (icontext, iresult,
suppressXMLDeclaration=True,
@ -1088,7 +1090,7 @@ class HtmlFormatter(Formatter):
icontext.addGlobal ("order", rdata.order)
icontext.addGlobal ("preference", rdata.preference)
icontext.addGlobal ("services", rdata.service)
icontext.addGlobal ("regexp", unicode(rdata.regexp,
icontext.addGlobal ("regexp", str(rdata.regexp,
"UTF-8")) # UTF-8 rdata is found in the wild
icontext.addGlobal ("replacement", rdata.replacement)
self.naptr_template.expand (icontext, iresult,
@ -1099,16 +1101,16 @@ class HtmlFormatter(Formatter):
self.unknown_template.expand (icontext, iresult,
suppressXMLDeclaration=True,
outputEncoding=querier.encoding)
records.append(unicode(iresult.getvalue(), querier.encoding))
records.append(iresult.getvalue())
self.rrsets.append({'ttl': self.pretty_duration(rrset.ttl),
'records': records})
else:
self.rrsets = None
def result(self, querier):
result = simpleTALUtils.FastStringOutput()
result = io.StringIO()
self.context.addGlobal("rrsets", self.rrsets)
self.template.expand (self.context, result,
outputEncoding=querier.encoding,
docType='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">')
return (result.getvalue() + "\n")
return ((result.getvalue() + "\n").encode())

3
DNSLG/LeakyBucket.py

@ -1,8 +1,9 @@
from builtins import object
default_bucket_size = 20
import time
class LeakyBucket():
class LeakyBucket(object):
def __init__(self, size=default_bucket_size):
self.size = size

12
DNSLG/Resolver.py

@ -1,8 +1,10 @@
from __future__ import absolute_import
from builtins import object
import copy
import dns.message
import dns.resolver
import Answer
from . import Answer
DEFAULT_EDNS_SIZE=2048
@ -36,7 +38,7 @@ class UnknownError(Exception):
def __str__(self):
return repr(self.value)
class Resolver():
class Resolver(object):
def __init__(self, nameservers=None, maximum=3, timeout=1.0,
edns_version=0, edns_payload=DEFAULT_EDNS_SIZE, do_dnssec=False):
@ -60,7 +62,9 @@ class Resolver():
self.original_nameservers = nameservers
self.edns = self.original_edns
self.payload = self.original_payload
self.nameservers = self.original_nameservers
self.nameservers = []
for i in range(0, len(self.original_nameservers)):
self.nameservers.append(self.original_nameservers[i])
self.do = self.original_do
def query(self, name, type, klass='IN', tcp=False, cd=False):
@ -69,7 +73,7 @@ class Resolver():
raise NoNameservers()
for ns in self.nameservers:
try:
message = dns.message.make_query(name, type, rdclass=klass,
message = dns.message.make_query(name.decode(), type, rdclass=klass,
use_edns=self.edns, payload=self.payload,
want_dnssec=self.do)
except TypeError: # Old DNS Python... Code here just as long as it lingers in some places

56
DNSLG/__init__.py

@ -1,8 +1,13 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Standard library
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
from cgi import escape
from urlparse import parse_qs
from urllib.parse import parse_qs
import encodings.idna
import os
from datetime import datetime
@ -19,10 +24,10 @@ import netaddr
from webob import Request
# Internal modules
import Formatter
from LeakyBucket import LeakyBucket
import Answer
import Resolver
from . import Formatter
from .LeakyBucket import LeakyBucket
from . import Answer
from . import Resolver
# If you need to change thse values, it is better to do it when
# calling the Querier() constructor.
@ -46,13 +51,13 @@ def send_response(start_response, status, output, type):
def punycode_of(domain):
labels = domain.split(".")
result = u""
result = ""
for label in labels:
if label:
result += (encodings.idna.ToASCII(label) + ".")
result += (encodings.idna.ToASCII(label).decode() + ".")
return (result)
class Querier:
class Querier(object):
def __init__(self, email_admin=None, url_doc=None, url_css=None, url_opensearch=None,
file_favicon=None,
@ -72,7 +77,7 @@ class Querier:
self.url_css = url_css
self.url_opensearch = url_opensearch
if file_favicon:
self.favicon = open(file_favicon).read()
self.favicon = open(file_favicon, 'br').read()
else:
self.favicon = None
self.encoding = encoding
@ -93,12 +98,12 @@ class Querier:
I'm the default handler, \"%s\" was called.
Are you sure of the URL?\n""" % path
send_response(start_response, '404 No such resource' , output, 'text/plain; charset=%s' % self.encoding)
return [output]
return [output.encode()]
def emptyfile(self, start_response):
output = ""
send_response(start_response, '200 OK' , output, 'text/plain')
return [output]
return [output.encode()]
def robotstxt(self, start_response):
# http://www.robotstxt.org/
@ -108,12 +113,12 @@ User-agent: *
Disallow: /
"""
send_response(start_response, '200 OK' , output, 'text/plain')
return [output]
return [output.encode()]
def notfound(self, start_response):
output = "Not found\r\n"
send_response(start_response, '404 Not Found' , output, 'text/plain')
return [output]
return [output.encode()]
def query(self, start_response, req, path, client, format="", alt_resolver=None,
do_dnssec=False, tcp=False, cd=False, edns_size=default_edns_size,
@ -140,7 +145,7 @@ Disallow: /
if not mformat:
output = "No suitable output format found\n"
send_response(start_response, '400 Bad request', output, plaintype)
return [output]
return [output.encode()]
mtype = '%s; charset=%s' % (mformat, self.encoding)
else:
if format == "TEXT" or format == "TXT":
@ -158,7 +163,7 @@ Disallow: /
else:
output = "Unsupported format \"%s\"\n" % format
send_response(start_response, '400 Bad request', output, plaintype)
return [output]
return [output.encode()]
ip_client = netaddr.IPAddress(client)
if ip_client.version == 4:
ip_prefix = netaddr.IPNetwork(client + "/28")
@ -167,9 +172,9 @@ Disallow: /
else:
output = "Unsupported address family \"%s\"\n" % ip_client.version
send_response(start_response, '400 Unknown IP version', output, plaintype)
return [output]
return [output.encode()]
if ip_client not in self.whitelist:
if self.buckets.has_key(ip_prefix.cidr):
if ip_prefix.cidr in self.buckets:
if self.buckets[ip_prefix.cidr].full():
status = '429 Too many requests'
# 429 registered by RFC 6585 in april 2012
@ -178,7 +183,7 @@ Disallow: /
# http://www.flickr.com/photos/girliemac/6509400997/in/set-72157628409467125
output = "%s sent too many requests" % client # TODO: better message
send_response(start_response, status, output, plaintype)
return [output]
return [output.encode()]
else:
self.buckets[ip_prefix.cidr].add(1)
else:
@ -219,19 +224,18 @@ Disallow: /
output = "You cannot ask for a query type other than PTR with reverse queries\n"
send_response(start_response, '400 Bad qtype with reverse',
output, plaintype)
return [output]
return [output.encode()]
# Pseudo-qtype ADDR is handled specially later
if not domain.endswith('.'):
domain += '.'
if domain == 'root.':
domain = '.'
domain = unicode(domain, self.encoding)
for forbidden in self.forbidden_suffixes:
if domain.endswith(forbidden):
output = "You cannot query local domain %s" % forbidden
send_response(start_response, '403 Local domain is private',
output, plaintype)
return [output]
return [output.encode()]
punycode_domain = punycode_of(domain)
if punycode_domain != domain:
qdomain = punycode_domain.encode("US-ASCII")
@ -280,7 +284,7 @@ Disallow: /
formatter.format(None, qtype, qclass, 0, self)
output = formatter.result(self)
send_response(start_response, '200 OK', output, mtype)
return [output]
return [output.encode()]
query_end = datetime.now()
self.delay = query_end - query_start
formatter.format(answer, qtype, qclass, answer.flags, self)
@ -334,7 +338,7 @@ Disallow: /
if environ['REQUEST_METHOD'] != 'GET':
output = environ['REQUEST_METHOD']
send_response(start_response, '405 Method not allowed', output, plaintype)
return [output]
return [output.encode()]
# If the program runs under Apache and if you use Apache
# SetEnv directives, their values can be retrieved here inside
# dictionary "environ".
@ -365,13 +369,13 @@ Disallow: /
output = "Incompatible arguments"
send_response(start_response, '400 CD is meaningful only for DNSSEC',
output, plaintype)
return [output]
return [output.encode()]
if buffersize == 0:
if do_dnssec:
output = "Buffer size = 0"
send_response(start_response, '400 DNSSEC requires EDNS',
output, plaintype)
return [output]
return [output.encode()]
edns_size = None
else:
edns_size = buffersize

27
db/dbconv.py

@ -27,6 +27,7 @@
#
# converts DNS-LG YAML database to sundry (ahem!) formats
from __future__ import print_function
import sys
import optparse
import yaml
@ -51,32 +52,32 @@ def loadf(filename):
try:
doc = yaml.load(f.read())
except:
print "Can't parse YAML in %s" % (filename)
print("Can't parse YAML in %s" % (filename))
sys.exit(1)
f.close()
return doc
except IOError, e:
except IOError as e:
sys.stderr.write("Can't open file %s: %s\n" % (filename, e))
sys.exit(1)
def dns_txt(db, origin="dns-lg"):
''' Print in DNS master zone file format for inclusion into zone '''
print "; Documentation of the existing DNS-LG instances."
print ";"
print "; Generated at %s" % (time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime()))
print ";"
print "; This file contains a TXT RRset for inclusion into a"
print "; zone master file. Each endpoint is a TXT record."
print ";"
print("; Documentation of the existing DNS-LG instances.")
print(";")
print("; Generated at %s" % (time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())))
print(";")
print("; This file contains a TXT RRset for inclusion into a")
print("; zone master file. Each endpoint is a TXT record.")
print(";")
for ep in db:
if 'endpoint' in ep and 'status' in ep and ep.get('status') != 'down':
txt = "\"%s\"" % (ep['endpoint'])
print "%-10s IN TXT %-45s ; %s" % (origin, txt, ep.get('contact', ''))
print("%-10s IN TXT %-45s ; %s" % (origin, txt, ep.get('contact', '')))
origin = '' # on continuation line
def plain_txt(db):
@ -84,7 +85,7 @@ def plain_txt(db):
for ep in db:
if 'endpoint' in ep:
print "%-50s %s" % (ep['endpoint'], ep.get('contact', ''))
print("%-50s %s" % (ep['endpoint'], ep.get('contact', '')))
def prettyprint(elem):
''' Compliments of http://www.doughellmann.com/PyMOTW/xml/etree/ElementTree/create.html '''
@ -113,7 +114,7 @@ def xml_out(db):
if 'status' in ep:
child.set('status', ep.get('status'))
print prettyprint(root)
print(prettyprint(root))
if __name__ == '__main__':
@ -166,7 +167,7 @@ if __name__ == '__main__':
elif options.xml:
xml_out(db)
elif options.json:
print json.dumps(db, indent=4)
print(json.dumps(db, indent=4))
else:
plain_txt(db)

30
db/test-instances.py

@ -4,6 +4,10 @@
# test-instances.py, Copyright (c) 2013, Jan-Piet Mens
# Test all instances of DNS-LG servers contained in YAML database.
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
import sys
import optparse
import yaml
@ -13,7 +17,7 @@ try:
except ImportError:
import simplejson as json
import time
import urllib2
import urllib.request, urllib.error, urllib.parse
import socket
DBNAME = 'dns-lg.yaml'
@ -25,14 +29,14 @@ def loadf(filename):
try:
doc = yaml.load(f.read())
except:
print "Can't parse YAML in %s" % (filename)
print("Can't parse YAML in %s" % (filename))
sys.exit(1)
f.close()
return doc
except IOError, e:
except IOError as e:
sys.stderr.write("Can't open file %s: %s\n" % (filename, e))
sys.exit(1)
@ -63,31 +67,31 @@ if __name__ == '__main__':
try:
socket.setdefaulttimeout(timeout)
req = urllib2.Request(uri)
req = urllib.request.Request(uri)
req.add_header("Accept", "application/json")
req.add_header("User-Agent", "DNS Looking Glass Checker")
resp = urllib2.urlopen(req)
resp = urllib.request.urlopen(req)
content = resp.read()
except urllib2.HTTPError, e:
print "Can't connect to %s: %s" % (endpoint, str(e))
except urllib.error.HTTPError as e:
print("Can't connect to %s: %s" % (endpoint, str(e)))
continue
except urllib2.URLError, e:
print "Can't connect to %s: %s" % (endpoint, str(e))
except urllib.error.URLError as e:
print("Can't connect to %s: %s" % (endpoint, str(e)))
continue
except socket.timeout:
print "Can't connect to %s: timeout" % (endpoint)
print("Can't connect to %s: timeout" % (endpoint))
continue
print endpoint
print(endpoint)
try:
reply = json.loads(content)
except ValueError:
print "\tCannot decode JSON: %s" % content
print("\tCannot decode JSON: %s" % content)
continue
except:
raise
if 'AnswerSection' in reply:
for ans in reply['AnswerSection']:
print "\t%s %s %s" % (ans['Name'], ans['Type'], ans['Target'])
print("\t%s %s %s" % (ans['Name'], ans['Type'], ans['Target']))

13
sample-wsgi-dnslg-with-config-file.py

@ -1,6 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import ConfigParser
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
import configparser
import sys
import string
@ -25,11 +28,11 @@ default_values = {'email_administrator': None,
}
SECTION = "DNS-LG"
config = ConfigParser.SafeConfigParser(default_values)
config = configparser.SafeConfigParser(default_values, allow_no_value=True)
try:
config_file = open(config_file_name)
except IOError:
print >>sys.stderr, "Cannot open configuration file %s" % config_file_name
print("Cannot open configuration file %s" % config_file_name, file=sys.stderr)
sys.exit(1)
config.readfp(config_file)
config.set('DEFAULT', 'forbidden_suffixes', '')
@ -49,7 +52,7 @@ description_html = config.get(SECTION, 'description_html')
google_code = config.get(SECTION, 'code_google_webmasters')
edns_size = config.get(SECTION, 'size_edns')
forbidden_str = config.get(SECTION, 'forbidden_suffixes')
forbidden = string.split(forbidden_str, ':')
forbidden = forbidden_str.split(':')
if edns_size is None or edns_size == "":
edns_size = None
else:

2
sample-wsgi-dnslg.py

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import DNSLG

7
setup.py

@ -1,12 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# distribute
from distribute_setup import use_setuptools
use_setuptools()
from setuptools import setup
setup(name='DNS-LG',
version='2013030501',
version='2020010301',
description='DNS Looking Glass',
license='BSD',
author='Stephane Bortzmeyer',

11
test-my-resolver.py

@ -1,16 +1,17 @@
#!/usr/bin/python
from __future__ import print_function
import DNSLG
import sys
resolver = DNSLG.Resolver.Resolver(["127.0.0.1", "8.8.8.8"], maximum=2)
for name in sys.argv[1:]:
result = resolver.query(name, "ANY")
print result.answer
print "From %s: " % result.nameserver
print(result.answer)
print("From %s: " % result.nameserver)
rrsets = result.answer # There is also additional, authority, etc
for rrset in rrsets:
print "%s/%s ->" % (rrset.name, rrset.rdtype)
print("%s/%s ->" % (rrset.name, rrset.rdtype))
for rr in rrset:
print "\t%s" % rr
print ""
print("\t%s" % rr)
print("")

15
test-server-with-config-file.py

@ -1,11 +1,14 @@
#!/usr/bin/env python
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
import wsgiref.simple_server as server
import os
import getopt
import sys
import string
import ConfigParser
import configparser
config_file = os.path.expanduser("~/.dnslg.ini")
@ -28,20 +31,20 @@ default_values = {'email_administrator': None,
}
def usage(msg=None):
print >>sys.stderr, "Usage: %s" % sys.argv[0]
print("Usage: %s" % sys.argv[0], file=sys.stderr)
if msg is not None:
print >>sys.stderr, msg
print(msg, file=sys.stderr)
if len(sys.argv) != 1:
usage()
sys.exit(1)
SECTION = "DNS-LG"
config = ConfigParser.SafeConfigParser(default_values)
config = configparser.SafeConfigParser(default_values)
try:
config_file = open(config_file)
except IOError:
print >>sys.stderr, "Cannot open configuration file %s" % config_file
print("Cannot open configuration file %s" % config_file, file=sys.stderr)
sys.exit(1)
config.readfp(config_file)
if not config.has_section(SECTION):
@ -76,7 +79,7 @@ querier = DNSLG.Querier(email_admin=email_admin, url_doc=url_doc, url_css=url_cs
forbidden_suffixes=forbidden)
# TODO listen on IPv6 as well
httpd = server.make_server("", port, querier.application)
print "Serving HTTP on port %i..." % port
print("Serving HTTP on port %i..." % port)
# Respond to requests until process is killed
httpd.serve_forever()

12
test-server.py

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import wsgiref.simple_server as server
import os
@ -15,9 +15,9 @@ url_doc = None
url_css = None
def usage(msg=None):
print >>sys.stderr, "Usage: %s [-p PORT] [-a email-admin] [-d url-documentation] [-c url-css]" % sys.argv[0]
print("Usage: %s [-p PORT] [-a email-admin] [-d url-documentation] [-c url-css]" % sys.argv[0], file=sys.stderr)
if msg is not None:
print >>sys.stderr, msg
print(msg, file=sys.stderr)
try:
optlist, args = getopt.getopt (sys.argv[1:], "c:d:a:p:h",
@ -38,10 +38,10 @@ try:
url_doc = value
else:
# Should never occur, it is trapped by getopt
print >>sys.stderr, "Unknown option %s" % option
print("Unknown option %s" % option, file=sys.stderr)
usage()
sys.exit(1)
except getopt.error, reason:
except getopt.error as reason:
usage(reason)
sys.exit(1)
if len(args) != 0:
@ -51,7 +51,7 @@ if len(args) != 0:
querier = DNSLG.Querier(email_admin, url_doc, url_css)
# TODO listen on IPv6 as well
httpd = server.make_server("", port, querier.application)
print "Serving HTTP on port %i..." % port
print("Serving HTTP on port %i..." % port)
# Respond to requests until process is killed
httpd.serve_forever()

3
validator.py

@ -1,5 +1,6 @@
#!/usr/bin/env python
from __future__ import print_function
from wsgiref.validate import validator
from wsgiref.simple_server import make_server
@ -12,5 +13,5 @@ querier = DNSLG.Querier()
validator_app = validator(querier.application)
httpd = make_server('', port, validator_app)
print "Listening on port %i...." % port
print("Listening on port %i...." % port)
httpd.serve_forever()

Loading…
Cancel
Save