~ubuntu-branches/ubuntu/wily/prewikka/wily

« back to all changes in this revision

Viewing changes to prewikka/resolve.py

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2008-07-02 16:49:06 UTC
  • mfrom: (6.1.2 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080702164906-q2bkfn6i40hd95tt
Tags: 0.9.14-2
* Update watch file
* Bump Standards version to 3.8.0 (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008 PreludeIDS Technologies. All Rights Reserved.
 
2
# Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
 
3
#
 
4
# This file is part of the Prewikka program.
 
5
#
 
6
# This program is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2, or (at your option)
 
9
# any later version.
 
10
#
 
11
# This program is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with this program; see the file COPYING.  If not, write to
 
18
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
import time
 
21
import socket
 
22
 
 
23
resolver = None
 
24
import_fail = None
 
25
 
 
26
try:
 
27
    from twisted.internet import reactor
 
28
    from twisted.names import client, dns, hosts, cache, resolve
 
29
except Exception, err:
 
30
    import_fail = err
 
31
 
 
32
try:
 
33
    from threading import Lock
 
34
except ImportError:
 
35
    from dummy_threading import Lock
 
36
 
 
37
class DNSResolver:
 
38
    def __init__(self):
 
39
        self._query = 0
 
40
        self._lock = Lock()
 
41
 
 
42
        self._cache = cache.CacheResolver()
 
43
        rlist = [ self._cache, client.Resolver('/etc/resolv.conf') ]
 
44
        self._resolve = resolve.ResolverChain(rlist)
 
45
 
 
46
    def _error_cb(self, failure):
 
47
        self._query -= 1
 
48
 
 
49
        if failure.check(dns.DomainError, dns.AuthoritativeDomainError):
 
50
            return
 
51
 
 
52
    def _resolve_cb(self, (ans, auth, add), ptr, resolve_cb):
 
53
        self._query -= 1
 
54
 
 
55
        resolve_cb(str(ans[0].payload.name))
 
56
 
 
57
        q = dns.Query(str(ans[0].name), ans[0].type, ans[0].cls)
 
58
        self._cache.cacheResult(q, (ans, auth, add))
 
59
 
 
60
    def _ip_reverse(self, addr):
 
61
        try:
 
62
            parts = list(socket.inet_pton(socket.AF_INET6, addr).encode('hex_codec'))
 
63
            origin = ".ip6.arpa"
 
64
        except:
 
65
            parts = ["%d" % ord(byte) for byte in socket.inet_aton(addr)]
 
66
            origin = ".in-addr.arpa"
 
67
 
 
68
        parts.reverse()
 
69
        return '.'.join(parts) + origin
 
70
 
 
71
    def process(self, timeout=0):
 
72
        end = now = time.time()
 
73
        final = now + timeout
 
74
 
 
75
        while True:
 
76
            self._lock.acquire()
 
77
 
 
78
            if self._query == 0:
 
79
                self._lock.release()
 
80
                break
 
81
 
 
82
            reactor.runUntilCurrent();
 
83
            reactor.doIteration(timeout)
 
84
 
 
85
            self._lock.release()
 
86
 
 
87
            end = time.time()
 
88
            if end >= final:
 
89
                break
 
90
 
 
91
        #print "max=%f elapsed:%f" % (timeout, end-now)
 
92
 
 
93
    def doQuery(self, addr, resolve_cb):
 
94
        self._lock.acquire()
 
95
 
 
96
        self._query += 1
 
97
        self._resolve.lookupPointer(addr).addCallback(self._resolve_cb, addr, resolve_cb).addErrback(self._error_cb)
 
98
 
 
99
        self._lock.release()
 
100
        self.process()
 
101
 
 
102
    def resolve(self, addr, resolve_cb):
 
103
        try:
 
104
            addr = self._ip_reverse(addr)
 
105
        except:
 
106
            return
 
107
 
 
108
        self.doQuery(addr, resolve_cb)
 
109
        self.process()
 
110
 
 
111
 
 
112
class AddressResolve:
 
113
    def _resolve_cb(self, value):
 
114
        self._name = value
 
115
 
 
116
    def __init__(self, addr):
 
117
        global resolver
 
118
 
 
119
        self._addr = addr
 
120
        self._name = None
 
121
 
 
122
        if resolver:
 
123
            resolver.resolve(addr, self._resolve_cb)
 
124
 
 
125
    def __len__(self):
 
126
        return len(str(self))
 
127
 
 
128
    def __str__(self):
 
129
        if resolver:
 
130
            resolver.process()
 
131
 
 
132
        return self._name or self._addr
 
133
 
 
134
    def __repr__(self):
 
135
        return str(self)
 
136
 
 
137
 
 
138
def process(timeout=0):
 
139
    global resolver
 
140
 
 
141
    if resolver:
 
142
        resolver.process(timeout)
 
143
 
 
144
 
 
145
def init(env):
 
146
    global resolver
 
147
 
 
148
    if env.dns_max_delay == -1:
 
149
        return
 
150
 
 
151
    if import_fail:
 
152
       env.log.warning("Asynchronous DNS resolution disabled: twisted.names and twisted.internet required: %s" % err)
 
153
       return
 
154
 
 
155
    resolver = DNSResolver()
 
156