diff options
-rwxr-xr-x | src/lib/dns/tests/testdata/gen-wiredata.py.in | 105 |
1 files changed, 82 insertions, 23 deletions
diff --git a/src/lib/dns/tests/testdata/gen-wiredata.py.in b/src/lib/dns/tests/testdata/gen-wiredata.py.in index fc8975712b..6f181b4e0c 100755 --- a/src/lib/dns/tests/testdata/gen-wiredata.py.in +++ b/src/lib/dns/tests/testdata/gen-wiredata.py.in @@ -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, {}) } |