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