OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 | |
5 """ | |
6 Domain Name Server | |
7 """ | |
8 | |
9 import os, traceback | |
10 | |
11 from twisted.python import usage | |
12 from twisted.names import dns | |
13 from twisted.application import internet, service | |
14 | |
15 from twisted.names import server | |
16 from twisted.names import authority | |
17 from twisted.names import secondary | |
18 | |
19 class Options(usage.Options): | |
20 optParameters = [ | |
21 ["interface", "i", "", "The interface to which to bind"], | |
22 ["port", "p", "53", "The port on which to listen"], | |
23 ["resolv-conf", None, None, | |
24 "Override location of resolv.conf (implies --recursive)"], | |
25 ["hosts-file", None, None, "Perform lookups with a hosts file"], | |
26 ] | |
27 | |
28 optFlags = [ | |
29 ["cache", "c", "Enable record caching"], | |
30 ["recursive", "r", "Perform recursive lookups"], | |
31 ["verbose", "v", "Log verbosely"], | |
32 ] | |
33 | |
34 zones = None | |
35 zonefiles = None | |
36 | |
37 def __init__(self): | |
38 usage.Options.__init__(self) | |
39 self['verbose'] = 0 | |
40 self.bindfiles = [] | |
41 self.zonefiles = [] | |
42 self.secondaries = [] | |
43 | |
44 | |
45 def opt_pyzone(self, filename): | |
46 """Specify the filename of a Python syntax zone definition""" | |
47 if not os.path.exists(filename): | |
48 raise usage.UsageError(filename + ": No such file") | |
49 self.zonefiles.append(filename) | |
50 | |
51 def opt_bindzone(self, filename): | |
52 """Specify the filename of a BIND9 syntax zone definition""" | |
53 if not os.path.exists(filename): | |
54 raise usage.UsageError(filename + ": No such file") | |
55 self.bindfiles.append(filename) | |
56 | |
57 | |
58 def opt_secondary(self, ip_domain): | |
59 """Act as secondary for the specified domain, performing | |
60 zone transfers from the specified IP (IP/domain) | |
61 """ | |
62 args = ip_domain.split('/', 1) | |
63 if len(args) != 2: | |
64 raise usage.UsageError("Argument must be of the form IP/domain") | |
65 self.secondaries.append((args[0], [args[1]])) | |
66 | |
67 def opt_verbose(self): | |
68 """Increment verbosity level""" | |
69 self['verbose'] += 1 | |
70 | |
71 | |
72 def postOptions(self): | |
73 if self['resolv-conf']: | |
74 self['recursive'] = True | |
75 | |
76 self.svcs = [] | |
77 self.zones = [] | |
78 for f in self.zonefiles: | |
79 try: | |
80 self.zones.append(authority.PySourceAuthority(f)) | |
81 except Exception, e: | |
82 traceback.print_exc() | |
83 raise usage.UsageError("Invalid syntax in " + f) | |
84 for f in self.bindfiles: | |
85 try: | |
86 self.zones.append(authority.BindAuthority(f)) | |
87 except Exception, e: | |
88 traceback.print_exc() | |
89 raise usage.UsageError("Invalid syntax in " + f) | |
90 for f in self.secondaries: | |
91 self.svcs.append(secondary.SecondaryAuthorityService(*f)) | |
92 self.zones.append(self.svcs[-1].getAuthority()) | |
93 try: | |
94 self['port'] = int(self['port']) | |
95 except ValueError: | |
96 raise usage.UsageError("Invalid port: %r" % (self['port'],)) | |
97 | |
98 | |
99 def makeService(config): | |
100 import client, cache, hosts | |
101 | |
102 ca, cl = [], [] | |
103 if config['cache']: | |
104 ca.append(cache.CacheResolver(verbose=config['verbose'])) | |
105 if config['recursive']: | |
106 cl.append(client.createResolver(resolvconf=config['resolv-conf'])) | |
107 if config['hosts-file']: | |
108 cl.append(hosts.Resolver(file=config['hosts-file'])) | |
109 | |
110 f = server.DNSServerFactory(config.zones, ca, cl, config['verbose']) | |
111 p = dns.DNSDatagramProtocol(f) | |
112 f.noisy = 0 | |
113 ret = service.MultiService() | |
114 for (klass, arg) in [(internet.TCPServer, f), (internet.UDPServer, p)]: | |
115 s = klass(config['port'], arg, interface=config['interface']) | |
116 s.setServiceParent(ret) | |
117 for svc in config.svcs: | |
118 svc.setServiceParent(ret) | |
119 return ret | |
OLD | NEW |