823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# This Source Code Form is subject to the terms of the Mozilla Public
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# License, v. 2.0. If a copy of the MPL was not distributed with this
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# file, You can obtain one at http://mozilla.org/MPL/2.0/.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# ans.py: See README.anspy for details.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom __future__ import print_function
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport os
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport sys
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport signal
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport socket
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport select
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom datetime import datetime, timedelta
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrewsimport functools
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntimport dns, dns.message, dns.query
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom dns.rdatatype import *
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom dns.rdataclass import *
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom dns.rcode import *
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntfrom dns.name import *
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# set up the RRs to be returned in the next answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the message contains up to two pipe-separated ('|') fields.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the first field of the message is a comma-separated list
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# of actions indicating what to put into the answer set
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# (e.g., a dname, a cname, another cname, etc)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# supported actions:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - cname (cname from the current name to a new one in the same domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - dname (dname to a new domain, plus a synthesized cname)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# - xname ("external" cname, to a new name in a new domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# example: xname, dname, cname represents a CNAME to an external
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# domain which is then answered by a DNAME and synthesized
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# CNAME pointing to yet another domain, which is then answered
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# by a CNAME within the same domain, and finally an answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# to the query. each RR in the answer set has a corresponding
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# RRSIG. these signatures are not valid, but will exercise the
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# response parser.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the second field is a comma-separated list of which RRs in the
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# answer set to include in the answer, in which order. if prepended
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# with 's', the number indicates which signature to include.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# examples: for the answer set "cname, cname, cname", an rr set
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# '1, s1, 2, s2, 3, s3, 4, s4' indicates that all four RRs should
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# be included in the answer, with siagntures, in the origninal
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# order, while 4, s4, 3, s3, 2, s2, 1, s1' indicates the order
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# should be reversed, 's3, s3, s3, s3' indicates that the third
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# RRSIG should be repeated four times and everything else should
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# be omitted, and so on.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# if there is no second field (i.e., no pipe symbol appears in
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the line) , the default is to send all answers and signatures.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# if a pipe symbol exists but the second field is empty, then
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# nothing is sent at all.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntactions = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntrrs = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntdef ctl_channel(msg):
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt global actions, rrs
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt msg = msg.splitlines().pop(0)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('received control message: %s' % msg)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews msg = msg.split(b'|')
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if len(msg) == 0:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt return
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews actions = [x.strip() for x in msg[0].split(b',')]
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews n = functools.reduce(lambda n, act: (n + (2 if act == b'dname' else 1)), [0] + actions)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if len(msg) == 1:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrs = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for i in range(n):
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for b in [False, True]:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrs.append((i, b))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt return
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews rlist = [x.strip() for x in msg[1].split(b',')]
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrs = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for item in rlist:
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if item[0] == b's'[0]:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i = int(item[1:].strip()) - 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if i > n:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('invalid index %d' + (i + 1))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrs.append((int(item[1:]) - 1, True))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt else:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i = int(item) - 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if i > n:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('invalid index %d' % (i + 1))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrs.append((i, False))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Respond to a DNS query.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntdef create_response(msg):
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt m = dns.message.from_wire(msg)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt qname = m.question[0].name.to_text()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt labels = qname.lower().split('.')
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt wantsigs = True if m.ednsflags & dns.flags.DO else False
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # get qtype
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrtype = m.question[0].rdtype
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt typename = dns.rdatatype.to_text(rrtype)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # for 'www.example.com.'...
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - name is 'www'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - domain is 'example.com.'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - sld is 'example'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # - tld is 'com.'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt name = labels.pop(0)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt domain = '.'.join(labels)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sld = labels.pop(0)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt tld = '.'.join(labels)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('query: ' + qname + '/' + typename)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('domain: ' + domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # default answers, depending on QTYPE.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # currently only A, AAAA, TXT and NS are supported.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt ttl = 86400
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt additionalA = '10.53.0.4'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt additionalAAAA = 'fd92:7065:b8e:ffff::4'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if typename == 'A':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt final = '10.53.0.4'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt elif typename == 'AAAA':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt final = 'fd92:7065:b8e:ffff::4'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt elif typename == 'TXT':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt final = 'Some\ text\ here'
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt elif typename == 'NS':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt domain = qname
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt final = ('ns1.%s' % domain)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt else:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt final = None
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # RRSIG rdata - won't validate but will exercise response parsing
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt t = datetime.now()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt delta = timedelta(30)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt t1 = t - delta
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt t2 = t + delta
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt inception=t1.strftime('%Y%m%d000000')
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt expiry=t2.strftime('%Y%m%d000000')
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigdata='OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso='
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # construct answer set.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs = []
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curdom = domain
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curname = name
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i = 0
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for action in actions:
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if name != 'test':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if action == b'xname':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt owner = curname + '.' + curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt newname = 'cname%d' % i
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i += 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt newdom = 'domain%d.%s' % (i, tld)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i += 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt target = newname + '.' + newdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add external CNAME %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add external RRISG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curname = newname
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curdom = newdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if action == b'cname':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt owner = curname + '.' + curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt newname = 'cname%d' % i
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt target = newname + '.' + curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i += 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add CNAME %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add RRSIG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curname = newname
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if action == b'dname':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt owner = curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt newdom = 'domain%d.%s' % (i, tld)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt i += 1
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add DNAME %s to %s' % (owner, newdom))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrsig = 'DNAME 5 3 %d %s %s 12345 %s %s' % \
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add RRSIG(DNAME) %s to %s' % (owner, newdom))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt owner = curname + '.' + curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt target = curname + '.' + newdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add synthesized CNAME %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ('add synthesized RRSIG(CNAME) %s to %s' % (owner, target))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt curdom = newdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # now add the final answer
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt owner = curname + '.' + curdom
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rrsig = '%s 5 3 %d %s %s 12345 %s %s' % \
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (typename, ttl, expiry, inception, domain, sigdata)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # prepare the response and convert to wire format
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r = dns.message.make_response(m)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews if name != 'test':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.answer.append(answers[-1])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if wantsigs:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.answer.append(sigs[-1])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt else:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for (i, sig) in rrs:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if sig and not wantsigs:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt continue
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt elif sig:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.answer.append(sigs[i])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt else:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.answer.append(answers[i])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if typename != 'NS':
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.authority.append(dns.rrset.from_text(domain, ttl, IN, "NS",
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt ("ns1.%s" % domain)))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400,
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt IN, A, additionalA))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400,
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt IN, AAAA, additionalAAAA))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.flags |= dns.flags.AA
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt r.use_edns()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt return r.to_wire()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntdef sigterm(signum, frame):
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Shutting down now...")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt os.remove('ans.pid')
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews running = False
5228a394571cb8297b16c6ef1801a31728332d9fMark Andrews sys.exit(0)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Main
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt#
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# Set up responder and control channel, open the pid file, and start
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# the main loop, listening for queries on the query channel or commands
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt# on the control channel and acting on them.
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt############################################################################
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntip4 = "10.53.0.4"
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntip6 = "fd92:7065:b8e:ffff::4"
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntsock = 5300
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntquery4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntquery4_socket.bind((ip4, sock))
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewshavev6 = True
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewstry:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews try:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews query6_socket.bind((ip6, sock))
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews except:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews query6_socket.close()
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews havev6 = False
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewsexcept:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews havev6 = False
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntctrl_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntctrl_socket.bind((ip4, sock + 1))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntctrl_socket.listen(5)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntsignal.signal(signal.SIGTERM, sigterm)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntf = open('ans.pid', 'w')
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntpid = os.getpid()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint (pid, file=f)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntf.close()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewsrunning = True
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint ("Listening on %s port %d" % (ip4, sock))
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewsif havev6:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews print ("Listening on %s port %d" % (ip6, sock))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint ("Control channel on %s port %d" % (ip4, sock + 1))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntprint ("Ctrl-c to quit")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewsif havev6:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews input = [query4_socket, query6_socket, ctrl_socket]
a55438eda32ecebf43ead45b216662b7923a465fMark Andrewselse:
a55438eda32ecebf43ead45b216662b7923a465fMark Andrews input = [query4_socket, ctrl_socket]
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Huntwhile running:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt try:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt inputready, outputready, exceptready = select.select(input, [], [])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt except select.error as e:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt break
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt except socket.error as e:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt break
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt except KeyboardInterrupt:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt break
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt for s in inputready:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if s == ctrl_socket:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # Handle control channel input
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt conn, addr = s.accept()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Control channel connected")
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt while True:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt msg = conn.recv(65535)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if not msg:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt break
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt ctl_channel(msg)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt conn.close()
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if s == query4_socket or s == query6_socket:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt print ("Query received on %s" %
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt (ip4 if s == query4_socket else ip6))
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt # Handle incoming queries
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt msg = s.recvfrom(65535)
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt rsp = create_response(msg[0])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if rsp:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt s.sendto(rsp, msg[1])
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt if not running:
823ccd1f02802966395d58c916e9f988320fd6eeEvan Hunt break