unbound-querycachedb.py revision 356345
1#!/usr/bin/env python 2 3import hashlib 4import sys 5import struct 6import socket 7import time 8from optparse import OptionParser 9 10import dns.message 11import dns.name 12import dns.rdataclass 13import dns.rdatatype 14 15def _calc_hashkey(qname, secret, qtype): 16 qclass = 'IN' # CLASS is fixed for simplicity 17 hobj = hashlib.sha256() 18 hobj.update(dns.name.from_text(qname).to_wire()) 19 hobj.update(struct.pack('HH', 20 socket.htons(dns.rdatatype.from_text(qtype)), 21 socket.htons(dns.rdataclass.from_text(qclass)))) 22 hobj.update(secret) 23 return hobj.hexdigest().upper() 24 25def _redis_get(options, key): 26 import redis 27 return redis.Redis(options.address, int(options.port)).get(key) 28 29def _dump_value(options, qname, key, value): 30 print(';; query=%s/IN/%s' % (qname, options.qtype)) 31 print(';; key=%s' % key) 32 if value is None: 33 print(';; no value') 34 return 35 if len(value) < 16: 36 print(';; broken value, short length: %d' % len(value)) 37 return 38 now = int(time.time()) 39 timestamp = struct.unpack('!Q', value[-16:-8])[0] 40 expire = struct.unpack('!Q', value[-8:])[0] 41 print(';; Now=%d, TimeStamp=%d, Expire=%d, TTL=%d' % 42 (now, timestamp, expire, max(expire - now, 0))) 43 print(dns.message.from_wire(value[:-16])) 44 45def main(): 46 parser = OptionParser(usage='usage: %prog [options] query_name') 47 parser.add_option("-a", "--address", dest="address", action="store", 48 default='127.0.0.1', help="backend-server address", 49 metavar='ADDRESS') 50 parser.add_option("-b", "--backend", dest="backend", action="store", 51 default='redis', help="backend name", 52 metavar='BACKEND') 53 parser.add_option("-p", "--port", dest="port", action="store", 54 default='6379', help="backend-server port", 55 metavar='PORT') 56 parser.add_option("-s", "--secret", dest="secret", action="store", 57 default='default', help="secret seed", metavar='SECRET') 58 parser.add_option("-t", "--qtype", dest="qtype", action="store", 59 default='A', help="query RR type", metavar='QTYPE') 60 61 (options, args) = parser.parse_args() 62 if len(args) < 1: 63 parser.error('qname is missing') 64 if options.backend == 'redis': 65 get_func = _redis_get 66 else: 67 raise Exception('unknown backend name: %s\n' % options.backend) 68 key = _calc_hashkey(args[0], options.secret, options.qtype) 69 value = get_func(options, key) 70 _dump_value(options, args[0], key, value) 71 72if __name__ == '__main__': 73 try: 74 main() 75 except Exception as e: 76 sys.stderr.write('%s\n' % e) 77 exit(1) 78