|
@@ -15,7 +15,7 @@
|
|
|
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
|
|
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
-import configparser, re, time, sys
|
|
|
+import configparser, re, time, socket, sys
|
|
|
from datetime import datetime
|
|
|
from optparse import OptionParser
|
|
|
|
|
@@ -215,6 +215,74 @@ class EDNS:
|
|
|
f.write('# RDLEN=%d\n' % self.rdlen)
|
|
|
f.write('%04x\n' % self.rdlen)
|
|
|
|
|
|
+class RR:
|
|
|
+ '''This is a base class for various types of RR test data.
|
|
|
+ For each RR type (A, AAAA, NS, etc), we define a derived class of RR
|
|
|
+ to dump type specific RDATA parameters. This class defines parameters
|
|
|
+ common to all types of RDATA, namely the owner name, RR class and TTL.
|
|
|
+ The dump() method of derived classes are expected to call dump_header(),
|
|
|
+ whose default implementation is provided in this class. This method
|
|
|
+ decides whether to dump the test data as an RR (with name, type, class)
|
|
|
+ or only as RDATA (with its length), and dumps the corresponding data
|
|
|
+ via the specified file object.
|
|
|
+
|
|
|
+ By convention we assume derived classes are named after the common
|
|
|
+ standard mnemonic of the corresponding RR types. For example, the
|
|
|
+ derived class for the RR type SOA should be named "SOA".
|
|
|
+
|
|
|
+ Configurable parameters are as follows:
|
|
|
+ - as_rr (bool): Whether or not the data is to be dumped as an RR. False
|
|
|
+ by default.
|
|
|
+ - rr_class (string): The RR class of the data. Only meaningful when the
|
|
|
+ data is dumped as an RR. Default is 'IN'.
|
|
|
+ - rr_ttl (integer): The TTL value of the RR. Only meaningful when the
|
|
|
+ data is dumped as an RR. Default is 86400 (1 day).
|
|
|
+ '''
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ self.as_rr = False
|
|
|
+ # only when as_rr is True, same for class/TTL:
|
|
|
+ self.rr_name = 'example.com'
|
|
|
+ self.rr_class = 'IN'
|
|
|
+ self.rr_ttl = 86400
|
|
|
+ def dump_header(self, f, rdlen):
|
|
|
+ type_txt = self.__class__.__name__
|
|
|
+ type_code = parse_value(type_txt, dict_rrtype)
|
|
|
+ if self.as_rr:
|
|
|
+ rrclass = parse_value(self.rr_class, dict_rrclass)
|
|
|
+ f.write('\n# %s RR (QNAME=%s Class=%s TTL=%d RDLEN=%d)\n' %
|
|
|
+ (type_txt, self.rr_name,
|
|
|
+ code_totext(rrclass, rdict_rrclass), self.rr_ttl, rdlen))
|
|
|
+ f.write('%s %04x %04x %08x %04x\n' %
|
|
|
+ (encode_name(self.rr_name), type_code, rrclass,
|
|
|
+ self.rr_ttl, rdlen))
|
|
|
+ else:
|
|
|
+ f.write('\n# %s RDATA (RDLEN=%d)\n' % (type_txt, rdlen))
|
|
|
+ f.write('%04x\n' % rdlen)
|
|
|
+
|
|
|
+class A(RR):
|
|
|
+ rdlen = 4 # fixed by default
|
|
|
+ address = '192.0.2.1'
|
|
|
+
|
|
|
+ def dump(self, f):
|
|
|
+ self.dump_header(f, self.rdlen)
|
|
|
+ f.write('# Address=%s\n' % (self.address))
|
|
|
+ bin_address = socket.inet_aton(self.address)
|
|
|
+ f.write('%02x%02x%02x%02x\n' % (bin_address[0], bin_address[1],
|
|
|
+ bin_address[2], bin_address[3]))
|
|
|
+
|
|
|
+class NS(RR):
|
|
|
+ rdlen = None # auto calculate
|
|
|
+ nsname = 'ns.example.com'
|
|
|
+
|
|
|
+ def dump(self, f):
|
|
|
+ nsname_wire = encode_name(self.nsname)
|
|
|
+ if self.rdlen is None:
|
|
|
+ self.rdlen = len(nsname_wire) / 2
|
|
|
+ self.dump_header(f, self.rdlen)
|
|
|
+ f.write('# NS name=%s\n' % (self.nsname))
|
|
|
+ f.write('%s\n' % nsname_wire)
|
|
|
+
|
|
|
class SOA:
|
|
|
# this currently doesn't support name compression within the RDATA.
|
|
|
rdlen = -1 # auto-calculate
|
|
@@ -432,12 +500,7 @@ class RRSIG:
|
|
|
f.write('# Tag=%d Signer=%s and Signature\n' % (self.tag, self.signer))
|
|
|
f.write('%04x %s %s\n' % (self.tag, name_wire, sig_wire))
|
|
|
|
|
|
-class TSIG:
|
|
|
- as_rr = False
|
|
|
- rr_name = 'example.com' # only when as_rr is True, same for class/TTL
|
|
|
- rr_class = 'ANY'
|
|
|
- rr_ttl = 0
|
|
|
-
|
|
|
+class TSIG(RR):
|
|
|
rdlen = None # auto-calculate
|
|
|
algorithm = 'hmac-sha256'
|
|
|
time_signed = 1286978795 # arbitrarily chosen default
|
|
@@ -449,12 +512,17 @@ class TSIG:
|
|
|
other_len = None # 6 if error is BADTIME; otherwise 0
|
|
|
other_data = None # use time_signed + fudge + 1 for BADTIME
|
|
|
dict_macsize = { 'hmac-md5' : 16, 'hmac-sha1' : 20, 'hmac-sha256' : 32 }
|
|
|
+
|
|
|
+ # TSIG has some special defaults
|
|
|
+ def __init__(self):
|
|
|
+ self.rr_class = 'ANY'
|
|
|
+ self.rr_ttl = 0
|
|
|
+
|
|
|
def dump(self, f):
|
|
|
if str(self.algorithm) == 'hmac-md5':
|
|
|
name_wire = encode_name('hmac-md5.sig-alg.reg.int')
|
|
|
else:
|
|
|
name_wire = encode_name(self.algorithm)
|
|
|
- rdlen = self.rdlen
|
|
|
mac_size = self.mac_size
|
|
|
if mac_size is None:
|
|
|
if self.algorithm in self.dict_macsize.keys():
|
|
@@ -473,20 +541,10 @@ class TSIG:
|
|
|
if self.error == 18 else ''
|
|
|
else:
|
|
|
other_data = encode_string(self.other_data, other_len)
|
|
|
- if rdlen is None:
|
|
|
- rdlen = int(len(name_wire) / 2 + 16 + len(mac) / 2 + \
|
|
|
- len(other_data) / 2)
|
|
|
- if self.as_rr:
|
|
|
- rrclass = parse_value(self.rr_class, dict_rrclass)
|
|
|
- f.write('\n# TSIG RR (QNAME=%s Class=%s TTL=%d RDLEN=%d)\n' %
|
|
|
- (self.rr_name, code_totext(rrclass, rdict_rrclass),
|
|
|
- self.rr_ttl, rdlen))
|
|
|
- f.write('%s %04x %04x %08x %04x\n' %
|
|
|
- (encode_name(self.rr_name), dict_rrtype['tsig'],
|
|
|
- rrclass, self.rr_ttl, rdlen))
|
|
|
- else:
|
|
|
- f.write('\n# TSIG RDATA (RDLEN=%d)\n' % rdlen)
|
|
|
- f.write('%04x\n' % rdlen);
|
|
|
+ if self.rdlen is None:
|
|
|
+ self.rdlen = int(len(name_wire) / 2 + 16 + len(mac) / 2 + \
|
|
|
+ len(other_data) / 2)
|
|
|
+ self.dump_header(f, self.rdlen)
|
|
|
f.write('# Algorithm=%s Time-Signed=%d Fudge=%d\n' %
|
|
|
(self.algorithm, self.time_signed, self.fudge))
|
|
|
f.write('%s %012x %04x\n' % (name_wire, self.time_signed, self.fudge))
|
|
@@ -502,7 +560,8 @@ def get_config_param(section):
|
|
|
config_param = {'name' : (Name, {}),
|
|
|
'header' : (DNSHeader, header_xtables),
|
|
|
'question' : (DNSQuestion, question_xtables),
|
|
|
- 'edns' : (EDNS, {}), 'soa' : (SOA, {}), 'txt' : (TXT, {}),
|
|
|
+ 'edns' : (EDNS, {}), 'a' : (A, {}), 'ns' : (NS, {}),
|
|
|
+ 'soa' : (SOA, {}), 'txt' : (TXT, {}),
|
|
|
'rp' : (RP, {}), 'rrsig' : (RRSIG, {}),
|
|
|
'nsec' : (NSEC, {}), 'nsec3' : (NSEC3, {}),
|
|
|
'tsig' : (TSIG, {}) }
|