OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 # | |
5 | |
6 """ | |
7 Twisted inetd TAP support | |
8 | |
9 Maintainer: U{Andrew Bennetts<mailto:spiv@twistedmatrix.com>} | |
10 | |
11 Future Plans: more configurability. | |
12 """ | |
13 | |
14 import os, pwd, grp, socket | |
15 | |
16 from twisted.runner import inetd, inetdconf | |
17 from twisted.python import log, usage | |
18 from twisted.internet.protocol import ServerFactory | |
19 from twisted.application import internet, service as appservice | |
20 | |
21 try: | |
22 import portmap | |
23 rpcOk = 1 | |
24 except ImportError: | |
25 rpcOk = 0 | |
26 | |
27 | |
28 # Protocol map | |
29 protocolDict = {'tcp': socket.IPPROTO_TCP, 'udp': socket.IPPROTO_UDP} | |
30 | |
31 | |
32 class Options(usage.Options): | |
33 | |
34 optParameters = [ | |
35 ['rpc', 'r', '/etc/rpc', 'RPC procedure table file'], | |
36 ['file', 'f', '/etc/inetd.conf', 'Service configuration file'] | |
37 ] | |
38 | |
39 optFlags = [['nointernal', 'i', "Don't run internal services"]] | |
40 zsh_actions = {"file" : "_files -g '*.conf'"} | |
41 | |
42 class RPCServer(internet.TCPServer): | |
43 | |
44 def __init__(self, rpcVersions, rpcConf, proto, service): | |
45 internet.TCPServer.__init__(0, ServerFactory()) | |
46 self.rpcConf = rpcConf | |
47 self.proto = proto | |
48 self.service = service | |
49 | |
50 def startService(self): | |
51 internet.TCPServer.startService(self) | |
52 import portmap | |
53 portNo = self._port.getHost()[2] | |
54 service = self.service | |
55 for version in rpcVersions: | |
56 portmap.set(self.rpcConf.services[name], version, self.proto, | |
57 portNo) | |
58 inetd.forkPassingFD(service.program, service.programArgs, | |
59 os.environ, service.user, service.group, p) | |
60 | |
61 def makeService(config): | |
62 s = appservice.MultiService() | |
63 conf = inetdconf.InetdConf() | |
64 conf.parseFile(open(config['file'])) | |
65 | |
66 rpcConf = inetdconf.RPCServicesConf() | |
67 try: | |
68 rpcConf.parseFile(open(config['rpc'])) | |
69 except: | |
70 # We'll survive even if we can't read /etc/rpc | |
71 log.deferr() | |
72 | |
73 for service in conf.services: | |
74 rpc = service.protocol.startswith('rpc/') | |
75 protocol = service.protocol | |
76 | |
77 if rpc and not rpcOk: | |
78 log.msg('Skipping rpc service due to lack of rpc support') | |
79 continue | |
80 | |
81 if rpc: | |
82 # RPC has extra options, so extract that | |
83 protocol = protocol[4:] # trim 'rpc/' | |
84 if not protocolDict.has_key(protocol): | |
85 log.msg('Bad protocol: ' + protocol) | |
86 continue | |
87 | |
88 try: | |
89 name, rpcVersions = service.name.split('/') | |
90 except ValueError: | |
91 log.msg('Bad RPC service/version: ' + service.name) | |
92 continue | |
93 | |
94 if not rpcConf.services.has_key(name): | |
95 log.msg('Unknown RPC service: ' + repr(service.name)) | |
96 continue | |
97 | |
98 try: | |
99 if '-' in rpcVersions: | |
100 start, end = map(int, rpcVersions.split('-')) | |
101 rpcVersions = range(start, end+1) | |
102 else: | |
103 rpcVersions = [int(rpcVersions)] | |
104 except ValueError: | |
105 log.msg('Bad RPC versions: ' + str(rpcVersions)) | |
106 continue | |
107 | |
108 if (protocol, service.socketType) not in [('tcp', 'stream'), | |
109 ('udp', 'dgram')]: | |
110 log.msg('Skipping unsupported type/protocol: %s/%s' | |
111 % (service.socketType, service.protocol)) | |
112 continue | |
113 | |
114 # Convert the username into a uid (if necessary) | |
115 try: | |
116 service.user = int(service.user) | |
117 except ValueError: | |
118 try: | |
119 service.user = pwd.getpwnam(service.user)[2] | |
120 except KeyError: | |
121 log.msg('Unknown user: ' + service.user) | |
122 continue | |
123 | |
124 # Convert the group name into a gid (if necessary) | |
125 if service.group is None: | |
126 # If no group was specified, use the user's primary group | |
127 service.group = pwd.getpwuid(service.user)[3] | |
128 else: | |
129 try: | |
130 service.group = int(service.group) | |
131 except ValueError: | |
132 try: | |
133 service.group = grp.getgrnam(service.group)[2] | |
134 except KeyError: | |
135 log.msg('Unknown group: ' + service.group) | |
136 continue | |
137 | |
138 if service.program == 'internal': | |
139 if config['nointernal']: | |
140 continue | |
141 | |
142 # Internal services can use a standard ServerFactory | |
143 if not inetd.internalProtocols.has_key(service.name): | |
144 log.msg('Unknown internal service: ' + service.name) | |
145 continue | |
146 factory = ServerFactory() | |
147 factory.protocol = inetd.internalProtocols[service.name] | |
148 elif rpc: | |
149 i = RPCServer(rpcVersions, rpcConf, proto, service) | |
150 i.setServiceParent(s) | |
151 continue | |
152 else: | |
153 # Non-internal non-rpc services use InetdFactory | |
154 factory = inetd.InetdFactory(service) | |
155 | |
156 if protocol == 'tcp': | |
157 internet.TCPServer(service.port, factory).setServiceParent(s) | |
158 elif protocol == 'udp': | |
159 raise RuntimeError("not supporting UDP") | |
160 return s | |
OLD | NEW |