root / trunk / twisted / names / common.py

Revision 24505, 7.6 kB (checked in by exarkun, 1 year ago)

Merge names-naptr-2276-2

Author: agatonsax, exarkun
Reviewer: exarkun, therve
Fixes: #2276

Add support for the NAPTR record type to twisted.names.

Line 
1 # -*- test-case-name: twisted.names.test -*-
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5
6 import socket
7
8 from twisted.names import dns
9 from twisted.internet import defer, error
10 from twisted.python import failure
11
12 EMPTY_RESULT = (), (), ()
13
14 class ResolverBase:
15     typeToMethod = None
16
17     def __init__(self):
18         self.typeToMethod = {}
19         for (k, v) in typeToMethod.items():
20             self.typeToMethod[k] = getattr(self, v)
21
22     def query(self, query, timeout = None):
23         try:
24             return self.typeToMethod[query.type](str(query.name), timeout)
25         except KeyError, e:
26             return defer.fail(failure.Failure(NotImplementedError(str(self.__class__) + " " + str(query.type))))
27
28     def _lookup(self, name, cls, type, timeout):
29         return defer.fail(NotImplementedError("ResolverBase._lookup"))
30
31     def lookupAddress(self, name, timeout = None):
32         """
33         @see: twisted.names.client.lookupAddress
34         """
35         return self._lookup(name, dns.IN, dns.A, timeout)
36
37     def lookupIPV6Address(self, name, timeout = None):
38         """
39         @see: twisted.names.client.lookupIPV6Address
40         """
41         return self._lookup(name, dns.IN, dns.AAAA, timeout)
42
43     def lookupAddress6(self, name, timeout = None):
44         """
45         @see: twisted.names.client.lookupAddress6
46         """
47         return self._lookup(name, dns.IN, dns.A6, timeout)
48
49     def lookupMailExchange(self, name, timeout = None):
50         """
51         @see: twisted.names.client.lookupMailExchange
52         """
53         return self._lookup(name, dns.IN, dns.MX, timeout)
54
55     def lookupNameservers(self, name, timeout = None):
56         """
57         @see: twisted.names.client.lookupNameservers
58         """
59         return self._lookup(name, dns.IN, dns.NS, timeout)
60
61     def lookupCanonicalName(self, name, timeout = None):
62         """
63         @see: twisted.names.client.lookupCanonicalName
64         """
65         return self._lookup(name, dns.IN, dns.CNAME, timeout)
66
67     def lookupMailBox(self, name, timeout = None):
68         """
69         @see: twisted.names.client.lookupMailBox
70         """
71         return self._lookup(name, dns.IN, dns.MB, timeout)
72
73     def lookupMailGroup(self, name, timeout = None):
74         """
75         @see: twisted.names.client.lookupMailGroup
76         """
77         return self._lookup(name, dns.IN, dns.MG, timeout)
78
79     def lookupMailRename(self, name, timeout = None):
80         """
81         @see: twisted.names.client.lookupMailRename
82         """
83         return self._lookup(name, dns.IN, dns.MR, timeout)
84
85     def lookupPointer(self, name, timeout = None):
86         """
87         @see: twisted.names.client.lookupPointer
88         """
89         return self._lookup(name, dns.IN, dns.PTR, timeout)
90
91     def lookupAuthority(self, name, timeout = None):
92         """
93         @see: twisted.names.client.lookupAuthority
94         """
95         return self._lookup(name, dns.IN, dns.SOA, timeout)
96
97     def lookupNull(self, name, timeout = None):
98         """
99         @see: twisted.names.client.lookupNull
100         """
101         return self._lookup(name, dns.IN, dns.NULL, timeout)
102
103     def lookupWellKnownServices(self, name, timeout = None):
104         """
105         @see: twisted.names.client.lookupWellKnownServices
106         """
107         return self._lookup(name, dns.IN, dns.WKS, timeout)
108
109     def lookupService(self, name, timeout = None):
110         """
111         @see: twisted.names.client.lookupService
112         """
113         return self._lookup(name, dns.IN, dns.SRV, timeout)
114
115     def lookupHostInfo(self, name, timeout = None):
116         """
117         @see: twisted.names.client.lookupHostInfo
118         """
119         return self._lookup(name, dns.IN, dns.HINFO, timeout)
120
121     def lookupMailboxInfo(self, name, timeout = None):
122         """
123         @see: twisted.names.client.lookupMailboxInfo
124         """
125         return self._lookup(name, dns.IN, dns.MINFO, timeout)
126
127     def lookupText(self, name, timeout = None):
128         """
129         @see: twisted.names.client.lookupText
130         """
131         return self._lookup(name, dns.IN, dns.TXT, timeout)
132
133     def lookupResponsibility(self, name, timeout = None):
134         """
135         @see: twisted.names.client.lookupResponsibility
136         """
137         return self._lookup(name, dns.IN, dns.RP, timeout)
138
139     def lookupAFSDatabase(self, name, timeout = None):
140         """
141         @see: twisted.names.client.lookupAFSDatabase
142         """
143         return self._lookup(name, dns.IN, dns.AFSDB, timeout)
144
145     def lookupZone(self, name, timeout = None):
146         """
147         @see: twisted.names.client.lookupZone
148         """
149         return self._lookup(name, dns.IN, dns.AXFR, timeout)
150
151
152     def lookupNamingAuthorityPointer(self, name, timeout=None):
153         """
154         @see: twisted.names.client.lookupNamingAuthorityPointer
155         """
156         return self._lookup(name, dns.IN, dns.NAPTR, timeout)
157
158
159     def lookupAllRecords(self, name, timeout = None):
160         """
161         @see: twisted.names.client.lookupAllRecords
162         """
163         return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout)
164
165     def getHostByName(self, name, timeout = None, effort = 10):
166         """
167         @see: twisted.names.client.getHostByName
168         """
169         # XXX - respect timeout
170         return self.lookupAllRecords(name, timeout
171             ).addCallback(self._cbRecords, name, effort
172             )
173
174     def _cbRecords(self, (ans, auth, add), name, effort):
175         result = extractRecord(self, dns.Name(name), ans + auth + add, effort)
176         if not result:
177             raise error.DNSLookupError(name)
178         return result
179
180 def extractRecord(resolver, name, answers, level = 10):
181     if not level:
182         return None
183     if hasattr(socket, 'inet_ntop'):
184         for r in answers:
185             if r.name == name and r.type == dns.A6:
186                 return socket.inet_ntop(socket.AF_INET6, r.payload.address)
187         for r in answers:
188             if r.name == name and r.type == dns.AAAA:
189                 return socket.inet_ntop(socket.AF_INET6, r.payload.address)
190     for r in answers:
191         if r.name == name and r.type == dns.A:
192             return socket.inet_ntop(socket.AF_INET, r.payload.address)
193     for r in answers:
194         if r.name == name and r.type == dns.CNAME:
195             result = extractRecord(resolver, r.payload.name, answers, level - 1)
196             if not result:
197                 return resolver.getHostByName(str(r.payload.name), effort=level-1)
198             return result
199     # No answers, but maybe there's a hint at who we should be asking about this
200     for r in answers:
201         if r.type == dns.NS:
202             from twisted.names import client
203             r = client.Resolver(servers=[(str(r.payload.name), dns.PORT)])
204             return r.lookupAddress(str(name)
205                 ).addCallback(lambda (ans, auth, add): extractRecord(r, name, ans + auth + add, level - 1)
206                 ).addBoth(lambda passthrough: (r.protocol.transport.stopListening(), passthrough)[1])
207
208 typeToMethod = {
209     dns.A:     'lookupAddress',
210     dns.AAAA:  'lookupIPV6Address',
211     dns.A6:    'lookupAddress6',
212     dns.NS:    'lookupNameservers',
213     dns.CNAME: 'lookupCanonicalName',
214     dns.SOA:   'lookupAuthority',
215     dns.MB:    'lookupMailBox',
216     dns.MG:    'lookupMailGroup',
217     dns.MR:    'lookupMailRename',
218     dns.NULL:  'lookupNull',
219     dns.WKS:   'lookupWellKnownServices',
220     dns.PTR:   'lookupPointer',
221     dns.HINFO: 'lookupHostInfo',
222     dns.MINFO: 'lookupMailboxInfo',
223     dns.MX:    'lookupMailExchange',
224     dns.TXT:   'lookupText',
225
226     dns.RP:    'lookupResponsibility',
227     dns.AFSDB: 'lookupAFSDatabase',
228     dns.SRV:   'lookupService',
229     dns.NAPTR: 'lookupNamingAuthorityPointer',
230     dns.AXFR:         'lookupZone',
231     dns.ALL_RECORDS:  'lookupAllRecords',
232 }
Note: See TracBrowser for help on using the browser.