mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-05-10 19:14:49 +02:00
Refactor debug, log and Fatal messages.
This commit rewrites the log() function so that it will append a newline at the end of the message if none is present. It doesn't make sense to print a log message without a newline since the next log message (which will write a prefix) expects to be starting at the beginning of a line. Although it isn't strictly necessary, this commit also removes any newlines at the ends of messages. If I missed any, including the newline at the end of the message will continue to work as it did before. Previously, some calls were missing the newline at the end even though including it was necessary for subsequent messages to appear correctly. This code also cleans up some redundant prefixes. The log() method will prepend the prefix and the different processes should set their prefix as soon as they start. Multiline messages are still supported (although the prefix for the additional lines was changed to match the length of the prefix used for the first line).
This commit is contained in:
parent
563f41478a
commit
7fc33c0020
@ -41,7 +41,7 @@ _extra_fd = os.open(os.devnull, os.O_RDONLY)
|
|||||||
|
|
||||||
|
|
||||||
def got_signal(signum, frame):
|
def got_signal(signum, frame):
|
||||||
log('exiting on signal %d\n' % signum)
|
log('exiting on signal %d' % signum)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ def check_daemon(pidfile):
|
|||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
return # no pidfile, ok
|
return # no pidfile, ok
|
||||||
else:
|
else:
|
||||||
raise Fatal("c : can't read %s: %s" % (_pidname, e))
|
raise Fatal("can't read %s: %s" % (_pidname, e))
|
||||||
if not oldpid:
|
if not oldpid:
|
||||||
os.unlink(_pidname)
|
os.unlink(_pidname)
|
||||||
return # invalid pidfile, ok
|
return # invalid pidfile, ok
|
||||||
@ -177,12 +177,12 @@ class MultiListener:
|
|||||||
assert(self.bind_called)
|
assert(self.bind_called)
|
||||||
if self.v6:
|
if self.v6:
|
||||||
listenip = self.v6.getsockname()
|
listenip = self.v6.getsockname()
|
||||||
debug1('%s listening on %r.\n' % (what, listenip))
|
debug1('%s listening on %r.' % (what, listenip))
|
||||||
debug2('%s listening with %r.\n' % (what, self.v6))
|
debug2('%s listening with %r.' % (what, self.v6))
|
||||||
if self.v4:
|
if self.v4:
|
||||||
listenip = self.v4.getsockname()
|
listenip = self.v4.getsockname()
|
||||||
debug1('%s listening on %r.\n' % (what, listenip))
|
debug1('%s listening on %r.' % (what, listenip))
|
||||||
debug2('%s listening with %r.\n' % (what, self.v4))
|
debug2('%s listening with %r.' % (what, self.v4))
|
||||||
|
|
||||||
|
|
||||||
class FirewallClient:
|
class FirewallClient:
|
||||||
@ -233,7 +233,7 @@ class FirewallClient:
|
|||||||
# No env: Talking to `FirewallClient.start`, which has no i18n.
|
# No env: Talking to `FirewallClient.start`, which has no i18n.
|
||||||
break
|
break
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
log('Spawning firewall manager: %r\n' % argv)
|
log('Spawning firewall manager: %r' % argv)
|
||||||
raise Fatal(e)
|
raise Fatal(e)
|
||||||
self.argv = argv
|
self.argv = argv
|
||||||
s1.close()
|
s1.close()
|
||||||
@ -326,23 +326,23 @@ def expire_connections(now, mux):
|
|||||||
remove = []
|
remove = []
|
||||||
for chan, timeout in dnsreqs.items():
|
for chan, timeout in dnsreqs.items():
|
||||||
if timeout < now:
|
if timeout < now:
|
||||||
debug3('expiring dnsreqs channel=%d\n' % chan)
|
debug3('expiring dnsreqs channel=%d' % chan)
|
||||||
remove.append(chan)
|
remove.append(chan)
|
||||||
del mux.channels[chan]
|
del mux.channels[chan]
|
||||||
for chan in remove:
|
for chan in remove:
|
||||||
del dnsreqs[chan]
|
del dnsreqs[chan]
|
||||||
debug3('Remaining DNS requests: %d\n' % len(dnsreqs))
|
debug3('Remaining DNS requests: %d' % len(dnsreqs))
|
||||||
|
|
||||||
remove = []
|
remove = []
|
||||||
for peer, (chan, timeout) in udp_by_src.items():
|
for peer, (chan, timeout) in udp_by_src.items():
|
||||||
if timeout < now:
|
if timeout < now:
|
||||||
debug3('expiring UDP channel channel=%d peer=%r\n' % (chan, peer))
|
debug3('expiring UDP channel channel=%d peer=%r' % (chan, peer))
|
||||||
mux.send(chan, ssnet.CMD_UDP_CLOSE, b'')
|
mux.send(chan, ssnet.CMD_UDP_CLOSE, b'')
|
||||||
remove.append(peer)
|
remove.append(peer)
|
||||||
del mux.channels[chan]
|
del mux.channels[chan]
|
||||||
for peer in remove:
|
for peer in remove:
|
||||||
del udp_by_src[peer]
|
del udp_by_src[peer]
|
||||||
debug3('Remaining UDP channels: %d\n' % len(udp_by_src))
|
debug3('Remaining UDP channels: %d' % len(udp_by_src))
|
||||||
|
|
||||||
|
|
||||||
def onaccept_tcp(listener, method, mux, handlers):
|
def onaccept_tcp(listener, method, mux, handlers):
|
||||||
@ -351,7 +351,7 @@ def onaccept_tcp(listener, method, mux, handlers):
|
|||||||
sock, srcip = listener.accept()
|
sock, srcip = listener.accept()
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
||||||
debug1('Rejected incoming connection: too many open files!\n')
|
debug1('Rejected incoming connection: too many open files!')
|
||||||
# free up an fd so we can eat the connection
|
# free up an fd so we can eat the connection
|
||||||
os.close(_extra_fd)
|
os.close(_extra_fd)
|
||||||
try:
|
try:
|
||||||
@ -364,15 +364,15 @@ def onaccept_tcp(listener, method, mux, handlers):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
dstip = method.get_tcp_dstip(sock)
|
dstip = method.get_tcp_dstip(sock)
|
||||||
debug1('Accept TCP: %s:%r -> %s:%r.\n' % (srcip[0], srcip[1],
|
debug1('Accept TCP: %s:%r -> %s:%r.' % (srcip[0], srcip[1],
|
||||||
dstip[0], dstip[1]))
|
dstip[0], dstip[1]))
|
||||||
if dstip[1] == sock.getsockname()[1] and islocal(dstip[0], sock.family):
|
if dstip[1] == sock.getsockname()[1] and islocal(dstip[0], sock.family):
|
||||||
debug1("-- ignored: that's my address!\n")
|
debug1("-- ignored: that's my address!")
|
||||||
sock.close()
|
sock.close()
|
||||||
return
|
return
|
||||||
chan = mux.next_channel()
|
chan = mux.next_channel()
|
||||||
if not chan:
|
if not chan:
|
||||||
log('warning: too many open channels. Discarded connection.\n')
|
log('warning: too many open channels. Discarded connection.')
|
||||||
sock.close()
|
sock.close()
|
||||||
return
|
return
|
||||||
mux.send(chan, ssnet.CMD_TCP_CONNECT, b'%d,%s,%d' %
|
mux.send(chan, ssnet.CMD_TCP_CONNECT, b'%d,%s,%d' %
|
||||||
@ -385,7 +385,7 @@ def onaccept_tcp(listener, method, mux, handlers):
|
|||||||
def udp_done(chan, data, method, sock, dstip):
|
def udp_done(chan, data, method, sock, dstip):
|
||||||
(src, srcport, data) = data.split(b",", 2)
|
(src, srcport, data) = data.split(b",", 2)
|
||||||
srcip = (src, int(srcport))
|
srcip = (src, int(srcport))
|
||||||
debug3('doing send from %r to %r\n' % (srcip, dstip,))
|
debug3('doing send from %r to %r' % (srcip, dstip,))
|
||||||
method.send_udp(sock, srcip, dstip, data)
|
method.send_udp(sock, srcip, dstip, data)
|
||||||
|
|
||||||
|
|
||||||
@ -395,7 +395,7 @@ def onaccept_udp(listener, method, mux, handlers):
|
|||||||
if t is None:
|
if t is None:
|
||||||
return
|
return
|
||||||
srcip, dstip, data = t
|
srcip, dstip, data = t
|
||||||
debug1('Accept UDP: %r -> %r.\n' % (srcip, dstip,))
|
debug1('Accept UDP: %r -> %r.' % (srcip, dstip,))
|
||||||
if srcip in udp_by_src:
|
if srcip in udp_by_src:
|
||||||
chan, _ = udp_by_src[srcip]
|
chan, _ = udp_by_src[srcip]
|
||||||
else:
|
else:
|
||||||
@ -412,7 +412,7 @@ def onaccept_udp(listener, method, mux, handlers):
|
|||||||
|
|
||||||
|
|
||||||
def dns_done(chan, data, method, sock, srcip, dstip, mux):
|
def dns_done(chan, data, method, sock, srcip, dstip, mux):
|
||||||
debug3('dns_done: channel=%d src=%r dst=%r\n' % (chan, srcip, dstip))
|
debug3('dns_done: channel=%d src=%r dst=%r' % (chan, srcip, dstip))
|
||||||
del mux.channels[chan]
|
del mux.channels[chan]
|
||||||
del dnsreqs[chan]
|
del dnsreqs[chan]
|
||||||
method.send_udp(sock, srcip, dstip, data)
|
method.send_udp(sock, srcip, dstip, data)
|
||||||
@ -427,9 +427,9 @@ def ondns(listener, method, mux, handlers):
|
|||||||
# dstip is None if we are using a method where we can't determine
|
# dstip is None if we are using a method where we can't determine
|
||||||
# the destination IP of the DNS request that we captured from the client.
|
# the destination IP of the DNS request that we captured from the client.
|
||||||
if dstip is None:
|
if dstip is None:
|
||||||
debug1('DNS request from %r: %d bytes\n' % (srcip, len(data)))
|
debug1('DNS request from %r: %d bytes' % (srcip, len(data)))
|
||||||
else:
|
else:
|
||||||
debug1('DNS request from %r to %r: %d bytes\n' %
|
debug1('DNS request from %r to %r: %d bytes' %
|
||||||
(srcip, dstip, len(data)))
|
(srcip, dstip, len(data)))
|
||||||
chan = mux.next_channel()
|
chan = mux.next_channel()
|
||||||
dnsreqs[chan] = now + 30
|
dnsreqs[chan] = now + 30
|
||||||
@ -445,13 +445,13 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
to_nameserver):
|
to_nameserver):
|
||||||
|
|
||||||
helpers.logprefix = 'c : '
|
helpers.logprefix = 'c : '
|
||||||
debug1('Starting client with Python version %s\n'
|
debug1('Starting client with Python version %s'
|
||||||
% platform.python_version())
|
% platform.python_version())
|
||||||
|
|
||||||
method = fw.method
|
method = fw.method
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
debug1('Connecting to server...\n')
|
debug1('Connecting to server...')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
(serverproc, serversock) = ssh.connect(
|
(serverproc, serversock) = ssh.connect(
|
||||||
@ -463,7 +463,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
auto_nets=auto_nets))
|
auto_nets=auto_nets))
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.args[0] == errno.EPIPE:
|
if e.args[0] == errno.EPIPE:
|
||||||
raise Fatal("c : failed to establish ssh session (1)")
|
raise Fatal("failed to establish ssh session (1)")
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
mux = Mux(serversock.makefile("rb"), serversock.makefile("wb"))
|
mux = Mux(serversock.makefile("rb"), serversock.makefile("wb"))
|
||||||
@ -481,22 +481,22 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
initstring = serversock.recv(len(expected))
|
initstring = serversock.recv(len(expected))
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.args[0] == errno.ECONNRESET:
|
if e.args[0] == errno.ECONNRESET:
|
||||||
raise Fatal("c : failed to establish ssh session (2)")
|
raise Fatal("failed to establish ssh session (2)")
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
rv = serverproc.poll()
|
rv = serverproc.poll()
|
||||||
if rv:
|
if rv:
|
||||||
raise Fatal('c : server died with error code %d' % rv)
|
raise Fatal('server died with error code %d' % rv)
|
||||||
|
|
||||||
if initstring != expected:
|
if initstring != expected:
|
||||||
raise Fatal('c : expected server init string %r; got %r'
|
raise Fatal('expected server init string %r; got %r'
|
||||||
% (expected, initstring))
|
% (expected, initstring))
|
||||||
log('Connected to server.\n')
|
log('Connected to server.')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
if daemon:
|
if daemon:
|
||||||
daemonize()
|
daemonize()
|
||||||
log('daemonizing (%s).\n' % _pidname)
|
log('daemonizing (%s).' % _pidname)
|
||||||
|
|
||||||
def onroutes(routestr):
|
def onroutes(routestr):
|
||||||
if auto_nets:
|
if auto_nets:
|
||||||
@ -508,11 +508,11 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
width = int(width)
|
width = int(width)
|
||||||
ip = ip.decode("ASCII")
|
ip = ip.decode("ASCII")
|
||||||
if family == socket.AF_INET6 and tcp_listener.v6 is None:
|
if family == socket.AF_INET6 and tcp_listener.v6 is None:
|
||||||
debug2("Ignored auto net %d/%s/%d\n" % (family, ip, width))
|
debug2("Ignored auto net %d/%s/%d" % (family, ip, width))
|
||||||
if family == socket.AF_INET and tcp_listener.v4 is None:
|
if family == socket.AF_INET and tcp_listener.v4 is None:
|
||||||
debug2("Ignored auto net %d/%s/%d\n" % (family, ip, width))
|
debug2("Ignored auto net %d/%s/%d" % (family, ip, width))
|
||||||
else:
|
else:
|
||||||
debug2("Adding auto net %d/%s/%d\n" % (family, ip, width))
|
debug2("Adding auto net %d/%s/%d" % (family, ip, width))
|
||||||
fw.auto_nets.append((family, ip, width, 0, 0))
|
fw.auto_nets.append((family, ip, width, 0, 0))
|
||||||
|
|
||||||
# we definitely want to do this *after* starting ssh, or we might end
|
# we definitely want to do this *after* starting ssh, or we might end
|
||||||
@ -532,7 +532,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
sdnotify.send(sdnotify.ready(), sdnotify.status('Connected'))
|
sdnotify.send(sdnotify.ready(), sdnotify.status('Connected'))
|
||||||
|
|
||||||
def onhostlist(hostlist):
|
def onhostlist(hostlist):
|
||||||
debug2('got host list: %r\n' % hostlist)
|
debug2('got host list: %r' % hostlist)
|
||||||
for line in hostlist.strip().split():
|
for line in hostlist.strip().split():
|
||||||
if line:
|
if line:
|
||||||
name, ip = line.split(b',', 1)
|
name, ip = line.split(b',', 1)
|
||||||
@ -548,7 +548,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
|||||||
dns_listener.add_handler(handlers, ondns, method, mux)
|
dns_listener.add_handler(handlers, ondns, method, mux)
|
||||||
|
|
||||||
if seed_hosts is not None:
|
if seed_hosts is not None:
|
||||||
debug1('seed_hosts: %r\n' % seed_hosts)
|
debug1('seed_hosts: %r' % seed_hosts)
|
||||||
mux.send(0, ssnet.CMD_HOST_REQ, str.encode('\n'.join(seed_hosts)))
|
mux.send(0, ssnet.CMD_HOST_REQ, str.encode('\n'.join(seed_hosts)))
|
||||||
|
|
||||||
def check_ssh_alive():
|
def check_ssh_alive():
|
||||||
@ -588,9 +588,9 @@ def main(listenip_v6, listenip_v4,
|
|||||||
try:
|
try:
|
||||||
check_daemon(pidfile)
|
check_daemon(pidfile)
|
||||||
except Fatal as e:
|
except Fatal as e:
|
||||||
log("%s\n" % e)
|
log("%s" % e)
|
||||||
return 5
|
return 5
|
||||||
debug1('Starting sshuttle proxy (version %s).\n' % __version__)
|
debug1('Starting sshuttle proxy (version %s).' % __version__)
|
||||||
helpers.logprefix = 'c : '
|
helpers.logprefix = 'c : '
|
||||||
|
|
||||||
fw = FirewallClient(method_name, sudo_pythonpath)
|
fw = FirewallClient(method_name, sudo_pythonpath)
|
||||||
@ -643,14 +643,14 @@ def main(listenip_v6, listenip_v4,
|
|||||||
# "auto" when listen address is unspecified.
|
# "auto" when listen address is unspecified.
|
||||||
# The user specified address if provided by user
|
# The user specified address if provided by user
|
||||||
if listenip_v6 is None:
|
if listenip_v6 is None:
|
||||||
debug1("IPv6 disabled by --disable-ipv6\n")
|
debug1("IPv6 disabled by --disable-ipv6")
|
||||||
if listenip_v6 == "auto":
|
if listenip_v6 == "auto":
|
||||||
if avail.ipv6:
|
if avail.ipv6:
|
||||||
debug1("IPv6 enabled: Using default IPv6 listen address ::1\n")
|
debug1("IPv6 enabled: Using default IPv6 listen address ::1")
|
||||||
listenip_v6 = ('::1', 0)
|
listenip_v6 = ('::1', 0)
|
||||||
else:
|
else:
|
||||||
debug1("IPv6 disabled since it isn't supported by method "
|
debug1("IPv6 disabled since it isn't supported by method "
|
||||||
"%s.\n" % fw.method.name)
|
"%s." % fw.method.name)
|
||||||
listenip_v6 = None
|
listenip_v6 = None
|
||||||
|
|
||||||
# Make final decision about enabling IPv6:
|
# Make final decision about enabling IPv6:
|
||||||
@ -722,9 +722,9 @@ def main(listenip_v6, listenip_v4,
|
|||||||
msg += "(available)"
|
msg += "(available)"
|
||||||
else:
|
else:
|
||||||
msg += "(not available with %s method)" % fw.method.name
|
msg += "(not available with %s method)" % fw.method.name
|
||||||
debug1(msg + "\n")
|
debug1(msg)
|
||||||
|
|
||||||
debug1("Method: %s\n" % fw.method.name)
|
debug1("Method: %s" % fw.method.name)
|
||||||
feature_status("IPv4", required.ipv4, avail.ipv4)
|
feature_status("IPv4", required.ipv4, avail.ipv4)
|
||||||
feature_status("IPv6", required.ipv6, avail.ipv6)
|
feature_status("IPv6", required.ipv6, avail.ipv6)
|
||||||
feature_status("UDP ", required.udp, avail.udp)
|
feature_status("UDP ", required.udp, avail.udp)
|
||||||
@ -744,20 +744,20 @@ def main(listenip_v6, listenip_v4,
|
|||||||
# because we do that below when we have identified the ports to
|
# because we do that below when we have identified the ports to
|
||||||
# listen on.
|
# listen on.
|
||||||
debug1("Subnets to forward through remote host (type, IP, cidr mask "
|
debug1("Subnets to forward through remote host (type, IP, cidr mask "
|
||||||
"width, startPort, endPort):\n")
|
"width, startPort, endPort):")
|
||||||
for i in subnets_include:
|
for i in subnets_include:
|
||||||
debug1(" "+str(i)+"\n")
|
debug1(" "+str(i))
|
||||||
if auto_nets:
|
if auto_nets:
|
||||||
debug1("NOTE: Additional subnets to forward may be added below by "
|
debug1("NOTE: Additional subnets to forward may be added below by "
|
||||||
"--auto-nets.\n")
|
"--auto-nets.")
|
||||||
debug1("Subnets to exclude from forwarding:\n")
|
debug1("Subnets to exclude from forwarding:")
|
||||||
for i in subnets_exclude:
|
for i in subnets_exclude:
|
||||||
debug1(" "+str(i)+"\n")
|
debug1(" "+str(i))
|
||||||
if required.dns:
|
if required.dns:
|
||||||
debug1("DNS requests normally directed at these servers will be "
|
debug1("DNS requests normally directed at these servers will be "
|
||||||
"redirected to remote:\n")
|
"redirected to remote:")
|
||||||
for i in nslist:
|
for i in nslist:
|
||||||
debug1(" "+str(i)+"\n")
|
debug1(" "+str(i))
|
||||||
|
|
||||||
if listenip_v6 and listenip_v6[1] and listenip_v4 and listenip_v4[1]:
|
if listenip_v6 and listenip_v6[1] and listenip_v4 and listenip_v4[1]:
|
||||||
# if both ports given, no need to search for a spare port
|
# if both ports given, no need to search for a spare port
|
||||||
@ -775,7 +775,7 @@ def main(listenip_v6, listenip_v4,
|
|||||||
redirectport_v4 = 0
|
redirectport_v4 = 0
|
||||||
bound = False
|
bound = False
|
||||||
for port in ports:
|
for port in ports:
|
||||||
debug2('Trying to bind redirector on port %d\n' % port)
|
debug2('Trying to bind redirector on port %d' % port)
|
||||||
tcp_listener = MultiListener()
|
tcp_listener = MultiListener()
|
||||||
|
|
||||||
if required.udp:
|
if required.udp:
|
||||||
@ -830,7 +830,7 @@ def main(listenip_v6, listenip_v4,
|
|||||||
# search for spare port for DNS
|
# search for spare port for DNS
|
||||||
ports = range(12300, 9000, -1)
|
ports = range(12300, 9000, -1)
|
||||||
for port in ports:
|
for port in ports:
|
||||||
debug2('Trying to bind DNS redirector on port %d\n' % port)
|
debug2('Trying to bind DNS redirector on port %d' % port)
|
||||||
if port in used_ports:
|
if port in used_ports:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -117,9 +117,9 @@ def main():
|
|||||||
return return_code
|
return return_code
|
||||||
|
|
||||||
except Fatal as e:
|
except Fatal as e:
|
||||||
log('fatal: %s\n' % e)
|
log('fatal: %s' % e)
|
||||||
return 99
|
return 99
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log('\n')
|
log('\n')
|
||||||
log('Keyboard interrupt: exiting.\n')
|
log('Keyboard interrupt: exiting.')
|
||||||
return 1
|
return 1
|
||||||
|
@ -51,15 +51,14 @@ def rewrite_etc_hosts(hostmap, port):
|
|||||||
def restore_etc_hosts(hostmap, port):
|
def restore_etc_hosts(hostmap, port):
|
||||||
# Only restore if we added hosts to /etc/hosts previously.
|
# Only restore if we added hosts to /etc/hosts previously.
|
||||||
if len(hostmap) > 0:
|
if len(hostmap) > 0:
|
||||||
debug2('undoing /etc/hosts changes.\n')
|
debug2('undoing /etc/hosts changes.')
|
||||||
rewrite_etc_hosts({}, port)
|
rewrite_etc_hosts({}, port)
|
||||||
|
|
||||||
|
|
||||||
# Isolate function that needs to be replaced for tests
|
# Isolate function that needs to be replaced for tests
|
||||||
def setup_daemon():
|
def setup_daemon():
|
||||||
if os.getuid() != 0:
|
if os.getuid() != 0:
|
||||||
raise Fatal('fw: '
|
raise Fatal('You must be root (or enable su/sudo) to set the firewall')
|
||||||
'You must be root (or enable su/sudo) to set the firewall')
|
|
||||||
|
|
||||||
# don't disappear if our controlling terminal or stdout/stderr
|
# don't disappear if our controlling terminal or stdout/stderr
|
||||||
# disappears; we still have to clean up.
|
# disappears; we still have to clean up.
|
||||||
@ -99,10 +98,10 @@ def subnet_weight(s):
|
|||||||
# supercede it in the transproxy list, at least, so the leftover rules
|
# supercede it in the transproxy list, at least, so the leftover rules
|
||||||
# are hopefully harmless.
|
# are hopefully harmless.
|
||||||
def main(method_name, syslog):
|
def main(method_name, syslog):
|
||||||
|
helpers.logprefix = 'fw: '
|
||||||
stdin, stdout = setup_daemon()
|
stdin, stdout = setup_daemon()
|
||||||
hostmap = {}
|
hostmap = {}
|
||||||
helpers.logprefix = 'fw: '
|
debug1('Starting firewall with Python version %s'
|
||||||
debug1('Starting firewall with Python version %s\n'
|
|
||||||
% platform.python_version())
|
% platform.python_version())
|
||||||
|
|
||||||
if method_name == "auto":
|
if method_name == "auto":
|
||||||
@ -119,7 +118,7 @@ def main(method_name, syslog):
|
|||||||
"Check that the appropriate programs are in your "
|
"Check that the appropriate programs are in your "
|
||||||
"PATH." % method_name)
|
"PATH." % method_name)
|
||||||
|
|
||||||
debug1('ready method name %s.\n' % method.name)
|
debug1('ready method name %s.' % method.name)
|
||||||
stdout.write('READY %s\n' % method.name)
|
stdout.write('READY %s\n' % method.name)
|
||||||
stdout.flush()
|
stdout.flush()
|
||||||
|
|
||||||
@ -136,14 +135,14 @@ def main(method_name, syslog):
|
|||||||
while 1:
|
while 1:
|
||||||
line = stdin.readline(128)
|
line = stdin.readline(128)
|
||||||
if not line:
|
if not line:
|
||||||
raise Fatal('fw: expected route but got %r' % line)
|
raise Fatal('expected route but got %r' % line)
|
||||||
elif line.startswith("NSLIST\n"):
|
elif line.startswith("NSLIST\n"):
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
(family, width, exclude, ip, fport, lport) = \
|
(family, width, exclude, ip, fport, lport) = \
|
||||||
line.strip().split(',', 5)
|
line.strip().split(',', 5)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
raise Fatal('fw: expected route or NSLIST but got %r' % line)
|
raise Fatal('expected route or NSLIST but got %r' % line)
|
||||||
subnets.append((
|
subnets.append((
|
||||||
int(family),
|
int(family),
|
||||||
int(width),
|
int(width),
|
||||||
@ -151,31 +150,31 @@ def main(method_name, syslog):
|
|||||||
ip,
|
ip,
|
||||||
int(fport),
|
int(fport),
|
||||||
int(lport)))
|
int(lport)))
|
||||||
debug2('Got subnets: %r\n' % subnets)
|
debug2('Got subnets: %r' % subnets)
|
||||||
|
|
||||||
nslist = []
|
nslist = []
|
||||||
if line != 'NSLIST\n':
|
if line != 'NSLIST\n':
|
||||||
raise Fatal('fw: expected NSLIST but got %r' % line)
|
raise Fatal('expected NSLIST but got %r' % line)
|
||||||
while 1:
|
while 1:
|
||||||
line = stdin.readline(128)
|
line = stdin.readline(128)
|
||||||
if not line:
|
if not line:
|
||||||
raise Fatal('fw: expected nslist but got %r' % line)
|
raise Fatal('expected nslist but got %r' % line)
|
||||||
elif line.startswith("PORTS "):
|
elif line.startswith("PORTS "):
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
(family, ip) = line.strip().split(',', 1)
|
(family, ip) = line.strip().split(',', 1)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
raise Fatal('fw: expected nslist or PORTS but got %r' % line)
|
raise Fatal('expected nslist or PORTS but got %r' % line)
|
||||||
nslist.append((int(family), ip))
|
nslist.append((int(family), ip))
|
||||||
debug2('Got partial nslist: %r\n' % nslist)
|
debug2('Got partial nslist: %r' % nslist)
|
||||||
debug2('Got nslist: %r\n' % nslist)
|
debug2('Got nslist: %r' % nslist)
|
||||||
|
|
||||||
if not line.startswith('PORTS '):
|
if not line.startswith('PORTS '):
|
||||||
raise Fatal('fw: expected PORTS but got %r' % line)
|
raise Fatal('expected PORTS but got %r' % line)
|
||||||
_, _, ports = line.partition(" ")
|
_, _, ports = line.partition(" ")
|
||||||
ports = ports.split(",")
|
ports = ports.split(",")
|
||||||
if len(ports) != 4:
|
if len(ports) != 4:
|
||||||
raise Fatal('fw: expected 4 ports but got %d' % len(ports))
|
raise Fatal('expected 4 ports but got %d' % len(ports))
|
||||||
port_v6 = int(ports[0])
|
port_v6 = int(ports[0])
|
||||||
port_v4 = int(ports[1])
|
port_v4 = int(ports[1])
|
||||||
dnsport_v6 = int(ports[2])
|
dnsport_v6 = int(ports[2])
|
||||||
@ -190,21 +189,21 @@ def main(method_name, syslog):
|
|||||||
assert(dnsport_v4 >= 0)
|
assert(dnsport_v4 >= 0)
|
||||||
assert(dnsport_v4 <= 65535)
|
assert(dnsport_v4 <= 65535)
|
||||||
|
|
||||||
debug2('Got ports: %d,%d,%d,%d\n'
|
debug2('Got ports: %d,%d,%d,%d'
|
||||||
% (port_v6, port_v4, dnsport_v6, dnsport_v4))
|
% (port_v6, port_v4, dnsport_v6, dnsport_v4))
|
||||||
|
|
||||||
line = stdin.readline(128)
|
line = stdin.readline(128)
|
||||||
if not line:
|
if not line:
|
||||||
raise Fatal('fw: expected GO but got %r' % line)
|
raise Fatal('expected GO but got %r' % line)
|
||||||
elif not line.startswith("GO "):
|
elif not line.startswith("GO "):
|
||||||
raise Fatal('fw: expected GO but got %r' % line)
|
raise Fatal('expected GO but got %r' % line)
|
||||||
|
|
||||||
_, _, args = line.partition(" ")
|
_, _, args = line.partition(" ")
|
||||||
udp, user = args.strip().split(" ", 1)
|
udp, user = args.strip().split(" ", 1)
|
||||||
udp = bool(int(udp))
|
udp = bool(int(udp))
|
||||||
if user == '-':
|
if user == '-':
|
||||||
user = None
|
user = None
|
||||||
debug2('Got udp: %r, user: %r\n' % (udp, user))
|
debug2('Got udp: %r, user: %r' % (udp, user))
|
||||||
|
|
||||||
subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6]
|
subnets_v6 = [i for i in subnets if i[0] == socket.AF_INET6]
|
||||||
nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6]
|
nslist_v6 = [i for i in nslist if i[0] == socket.AF_INET6]
|
||||||
@ -212,17 +211,17 @@ def main(method_name, syslog):
|
|||||||
nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET]
|
nslist_v4 = [i for i in nslist if i[0] == socket.AF_INET]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
debug1('setting up.\n')
|
debug1('setting up.')
|
||||||
|
|
||||||
if subnets_v6 or nslist_v6:
|
if subnets_v6 or nslist_v6:
|
||||||
debug2('setting up IPv6.\n')
|
debug2('setting up IPv6.')
|
||||||
method.setup_firewall(
|
method.setup_firewall(
|
||||||
port_v6, dnsport_v6, nslist_v6,
|
port_v6, dnsport_v6, nslist_v6,
|
||||||
socket.AF_INET6, subnets_v6, udp,
|
socket.AF_INET6, subnets_v6, udp,
|
||||||
user)
|
user)
|
||||||
|
|
||||||
if subnets_v4 or nslist_v4:
|
if subnets_v4 or nslist_v4:
|
||||||
debug2('setting up IPv4.\n')
|
debug2('setting up IPv4.')
|
||||||
method.setup_firewall(
|
method.setup_firewall(
|
||||||
port_v4, dnsport_v4, nslist_v4,
|
port_v4, dnsport_v4, nslist_v4,
|
||||||
socket.AF_INET, subnets_v4, udp,
|
socket.AF_INET, subnets_v4, udp,
|
||||||
@ -245,40 +244,38 @@ def main(method_name, syslog):
|
|||||||
if line.startswith('HOST '):
|
if line.startswith('HOST '):
|
||||||
(name, ip) = line[5:].strip().split(',', 1)
|
(name, ip) = line[5:].strip().split(',', 1)
|
||||||
hostmap[name] = ip
|
hostmap[name] = ip
|
||||||
debug2('setting up /etc/hosts.\n')
|
debug2('setting up /etc/hosts.')
|
||||||
rewrite_etc_hosts(hostmap, port_v6 or port_v4)
|
rewrite_etc_hosts(hostmap, port_v6 or port_v4)
|
||||||
elif line:
|
elif line:
|
||||||
if not method.firewall_command(line):
|
if not method.firewall_command(line):
|
||||||
raise Fatal('fw: expected command, got %r' % line)
|
raise Fatal('expected command, got %r' % line)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
finally:
|
finally:
|
||||||
try:
|
try:
|
||||||
debug1('undoing changes.\n')
|
debug1('undoing changes.')
|
||||||
except BaseException:
|
except BaseException:
|
||||||
debug2('An error occurred, ignoring it.')
|
debug2('An error occurred, ignoring it.')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if subnets_v6 or nslist_v6:
|
if subnets_v6 or nslist_v6:
|
||||||
debug2('undoing IPv6 changes.\n')
|
debug2('undoing IPv6 changes.')
|
||||||
method.restore_firewall(port_v6, socket.AF_INET6, udp, user)
|
method.restore_firewall(port_v6, socket.AF_INET6, udp, user)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
try:
|
try:
|
||||||
debug1("Error trying to undo IPv6 firewall.\n")
|
debug1("Error trying to undo IPv6 firewall.")
|
||||||
for line in traceback.format_exc().splitlines():
|
debug1(traceback.format_exc())
|
||||||
debug1("---> %s\n" % line)
|
|
||||||
except BaseException:
|
except BaseException:
|
||||||
debug2('An error occurred, ignoring it.')
|
debug2('An error occurred, ignoring it.')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if subnets_v4 or nslist_v4:
|
if subnets_v4 or nslist_v4:
|
||||||
debug2('undoing IPv4 changes.\n')
|
debug2('undoing IPv4 changes.')
|
||||||
method.restore_firewall(port_v4, socket.AF_INET, udp, user)
|
method.restore_firewall(port_v4, socket.AF_INET, udp, user)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
try:
|
try:
|
||||||
debug1("Error trying to undo IPv4 firewall.\n")
|
debug1("Error trying to undo IPv4 firewall.")
|
||||||
for line in traceback.format_exc().splitlines():
|
debug1(traceback.format_exc())
|
||||||
debug1("---> %s\n" % line)
|
|
||||||
except BaseException:
|
except BaseException:
|
||||||
debug2('An error occurred, ignoring it.')
|
debug2('An error occurred, ignoring it.')
|
||||||
|
|
||||||
@ -287,8 +284,7 @@ def main(method_name, syslog):
|
|||||||
restore_etc_hosts(hostmap, port_v6 or port_v4)
|
restore_etc_hosts(hostmap, port_v6 or port_v4)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
try:
|
try:
|
||||||
debug1("Error trying to undo /etc/hosts changes.\n")
|
debug1("Error trying to undo /etc/hosts changes.")
|
||||||
for line in traceback.format_exc().splitlines():
|
debug1(traceback.format_exc())
|
||||||
debug1("---> %s\n" % line)
|
|
||||||
except BaseException:
|
except BaseException:
|
||||||
debug2('An error occurred, ignoring it.')
|
debug2('An error occurred, ignoring it.')
|
||||||
|
@ -15,12 +15,16 @@ def log(s):
|
|||||||
global logprefix
|
global logprefix
|
||||||
try:
|
try:
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
# Put newline at end of string if line doesn't have one.
|
||||||
|
if not s.endswith("\n"):
|
||||||
|
s = s+"\n"
|
||||||
|
# Allow multi-line messages
|
||||||
if s.find("\n") != -1:
|
if s.find("\n") != -1:
|
||||||
prefix = logprefix
|
prefix = logprefix
|
||||||
s = s.rstrip("\n")
|
s = s.rstrip("\n")
|
||||||
for line in s.split("\n"):
|
for line in s.split("\n"):
|
||||||
sys.stderr.write(prefix + line + "\n")
|
sys.stderr.write(prefix + line + "\n")
|
||||||
prefix = "---> "
|
prefix = " "
|
||||||
else:
|
else:
|
||||||
sys.stderr.write(logprefix + s)
|
sys.stderr.write(logprefix + s)
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
@ -91,11 +95,11 @@ def resolvconf_nameservers(systemd_resolved):
|
|||||||
words = line.lower().split()
|
words = line.lower().split()
|
||||||
if len(words) >= 2 and words[0] == 'nameserver':
|
if len(words) >= 2 and words[0] == 'nameserver':
|
||||||
this_file_nsservers.append(family_ip_tuple(words[1]))
|
this_file_nsservers.append(family_ip_tuple(words[1]))
|
||||||
debug2("Found DNS servers in %s: %s\n" %
|
debug2("Found DNS servers in %s: %s" %
|
||||||
(f, [n[1] for n in this_file_nsservers]))
|
(f, [n[1] for n in this_file_nsservers]))
|
||||||
nsservers += this_file_nsservers
|
nsservers += this_file_nsservers
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
debug3("Failed to read %s when looking for DNS servers: %s\n" %
|
debug3("Failed to read %s when looking for DNS servers: %s" %
|
||||||
(f, e.strerror))
|
(f, e.strerror))
|
||||||
|
|
||||||
return nsservers
|
return nsservers
|
||||||
@ -215,7 +219,7 @@ def which(file, mode=os.F_OK | os.X_OK):
|
|||||||
path = get_path()
|
path = get_path()
|
||||||
rv = _which(file, mode, path)
|
rv = _which(file, mode, path)
|
||||||
if rv:
|
if rv:
|
||||||
debug2("which() found '%s' at %s\n" % (file, rv))
|
debug2("which() found '%s' at %s" % (file, rv))
|
||||||
else:
|
else:
|
||||||
debug2("which() could not find '%s' in %s\n" % (file, path))
|
debug2("which() could not find '%s' in %s" % (file, path))
|
||||||
return rv
|
return rv
|
||||||
|
@ -24,7 +24,7 @@ try:
|
|||||||
null = open(os.devnull, 'wb')
|
null = open(os.devnull, 'wb')
|
||||||
except IOError:
|
except IOError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log('warning: %s\n' % e)
|
log('warning: %s' % e)
|
||||||
null = os.popen("sh -c 'while read x; do :; done'", 'wb', 4096)
|
null = os.popen("sh -c 'while read x; do :; done'", 'wb', 4096)
|
||||||
|
|
||||||
|
|
||||||
@ -80,13 +80,13 @@ def found_host(name, ip):
|
|||||||
oldip = hostnames.get(name)
|
oldip = hostnames.get(name)
|
||||||
if oldip != ip:
|
if oldip != ip:
|
||||||
hostnames[name] = ip
|
hostnames[name] = ip
|
||||||
debug1('Found: %s: %s\n' % (name, ip))
|
debug1('Found: %s: %s' % (name, ip))
|
||||||
sys.stdout.write('%s,%s\n' % (name, ip))
|
sys.stdout.write('%s,%s\n' % (name, ip))
|
||||||
write_host_cache()
|
write_host_cache()
|
||||||
|
|
||||||
|
|
||||||
def _check_etc_hosts():
|
def _check_etc_hosts():
|
||||||
debug2(' > hosts\n')
|
debug2(' > hosts')
|
||||||
for line in open('/etc/hosts'):
|
for line in open('/etc/hosts'):
|
||||||
line = re.sub(r'#.*', '', line)
|
line = re.sub(r'#.*', '', line)
|
||||||
words = line.strip().split()
|
words = line.strip().split()
|
||||||
@ -95,17 +95,17 @@ def _check_etc_hosts():
|
|||||||
ip = words[0]
|
ip = words[0]
|
||||||
names = words[1:]
|
names = words[1:]
|
||||||
if _is_ip(ip):
|
if _is_ip(ip):
|
||||||
debug3('< %s %r\n' % (ip, names))
|
debug3('< %s %r' % (ip, names))
|
||||||
for n in names:
|
for n in names:
|
||||||
check_host(n)
|
check_host(n)
|
||||||
found_host(n, ip)
|
found_host(n, ip)
|
||||||
|
|
||||||
|
|
||||||
def _check_revdns(ip):
|
def _check_revdns(ip):
|
||||||
debug2(' > rev: %s\n' % ip)
|
debug2(' > rev: %s' % ip)
|
||||||
try:
|
try:
|
||||||
r = socket.gethostbyaddr(ip)
|
r = socket.gethostbyaddr(ip)
|
||||||
debug3('< %s\n' % r[0])
|
debug3('< %s' % r[0])
|
||||||
check_host(r[0])
|
check_host(r[0])
|
||||||
found_host(r[0], ip)
|
found_host(r[0], ip)
|
||||||
except (socket.herror, UnicodeError):
|
except (socket.herror, UnicodeError):
|
||||||
@ -113,10 +113,10 @@ def _check_revdns(ip):
|
|||||||
|
|
||||||
|
|
||||||
def _check_dns(hostname):
|
def _check_dns(hostname):
|
||||||
debug2(' > dns: %s\n' % hostname)
|
debug2(' > dns: %s' % hostname)
|
||||||
try:
|
try:
|
||||||
ip = socket.gethostbyname(hostname)
|
ip = socket.gethostbyname(hostname)
|
||||||
debug3('< %s\n' % ip)
|
debug3('< %s' % ip)
|
||||||
check_host(ip)
|
check_host(ip)
|
||||||
found_host(hostname, ip)
|
found_host(hostname, ip)
|
||||||
except (socket.gaierror, UnicodeError):
|
except (socket.gaierror, UnicodeError):
|
||||||
@ -124,7 +124,7 @@ def _check_dns(hostname):
|
|||||||
|
|
||||||
|
|
||||||
def _check_netstat():
|
def _check_netstat():
|
||||||
debug2(' > netstat\n')
|
debug2(' > netstat')
|
||||||
argv = ['netstat', '-n']
|
argv = ['netstat', '-n']
|
||||||
try:
|
try:
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
||||||
@ -133,11 +133,11 @@ def _check_netstat():
|
|||||||
p.wait()
|
p.wait()
|
||||||
except OSError:
|
except OSError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log('%r failed: %r\n' % (argv, e))
|
log('%r failed: %r' % (argv, e))
|
||||||
return
|
return
|
||||||
|
|
||||||
for ip in re.findall(r'\d+\.\d+\.\d+\.\d+', content):
|
for ip in re.findall(r'\d+\.\d+\.\d+\.\d+', content):
|
||||||
debug3('< %s\n' % ip)
|
debug3('< %s' % ip)
|
||||||
check_host(ip)
|
check_host(ip)
|
||||||
|
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ def _check_smb(hostname):
|
|||||||
global _smb_ok
|
global _smb_ok
|
||||||
if not _smb_ok:
|
if not _smb_ok:
|
||||||
return
|
return
|
||||||
debug2(' > smb: %s\n' % hostname)
|
debug2(' > smb: %s' % hostname)
|
||||||
argv = ['smbclient', '-U', '%', '-L', hostname]
|
argv = ['smbclient', '-U', '%', '-L', hostname]
|
||||||
try:
|
try:
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
||||||
@ -155,7 +155,7 @@ def _check_smb(hostname):
|
|||||||
p.wait()
|
p.wait()
|
||||||
except OSError:
|
except OSError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log('%r failed: %r\n' % (argv, e))
|
log('%r failed: %r' % (argv, e))
|
||||||
_smb_ok = False
|
_smb_ok = False
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ def _check_smb(hostname):
|
|||||||
break
|
break
|
||||||
words = line.split()
|
words = line.split()
|
||||||
hostname = words[0].lower()
|
hostname = words[0].lower()
|
||||||
debug3('< %s\n' % hostname)
|
debug3('< %s' % hostname)
|
||||||
check_host(hostname)
|
check_host(hostname)
|
||||||
|
|
||||||
# workgroup list section:
|
# workgroup list section:
|
||||||
@ -192,7 +192,7 @@ def _check_smb(hostname):
|
|||||||
break
|
break
|
||||||
words = line.split()
|
words = line.split()
|
||||||
(workgroup, hostname) = (words[0].lower(), words[1].lower())
|
(workgroup, hostname) = (words[0].lower(), words[1].lower())
|
||||||
debug3('< group(%s) -> %s\n' % (workgroup, hostname))
|
debug3('< group(%s) -> %s' % (workgroup, hostname))
|
||||||
check_host(hostname)
|
check_host(hostname)
|
||||||
check_workgroup(workgroup)
|
check_workgroup(workgroup)
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ def _check_nmb(hostname, is_workgroup, is_master):
|
|||||||
global _nmb_ok
|
global _nmb_ok
|
||||||
if not _nmb_ok:
|
if not _nmb_ok:
|
||||||
return
|
return
|
||||||
debug2(' > n%d%d: %s\n' % (is_workgroup, is_master, hostname))
|
debug2(' > n%d%d: %s' % (is_workgroup, is_master, hostname))
|
||||||
argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname]
|
argv = ['nmblookup'] + ['-M'] * is_master + ['--', hostname]
|
||||||
try:
|
try:
|
||||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE, stderr=null,
|
||||||
@ -214,18 +214,18 @@ def _check_nmb(hostname, is_workgroup, is_master):
|
|||||||
rv = p.wait()
|
rv = p.wait()
|
||||||
except OSError:
|
except OSError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log('%r failed: %r\n' % (argv, e))
|
log('%r failed: %r' % (argv, e))
|
||||||
_nmb_ok = False
|
_nmb_ok = False
|
||||||
return
|
return
|
||||||
if rv:
|
if rv:
|
||||||
log('%r returned %d\n' % (argv, rv))
|
log('%r returned %d' % (argv, rv))
|
||||||
return
|
return
|
||||||
for line in lines:
|
for line in lines:
|
||||||
m = re.match(r'(\d+\.\d+\.\d+\.\d+) (\w+)<\w\w>\n', line)
|
m = re.match(r'(\d+\.\d+\.\d+\.\d+) (\w+)<\w\w>\n', line)
|
||||||
if m:
|
if m:
|
||||||
g = m.groups()
|
g = m.groups()
|
||||||
(ip, name) = (g[0], g[1].lower())
|
(ip, name) = (g[0], g[1].lower())
|
||||||
debug3('< %s -> %s\n' % (name, ip))
|
debug3('< %s -> %s' % (name, ip))
|
||||||
if is_workgroup:
|
if is_workgroup:
|
||||||
_enqueue(_check_smb, ip)
|
_enqueue(_check_smb, ip)
|
||||||
else:
|
else:
|
||||||
@ -263,12 +263,9 @@ def _stdin_still_ok(timeout):
|
|||||||
|
|
||||||
|
|
||||||
def hw_main(seed_hosts, auto_hosts):
|
def hw_main(seed_hosts, auto_hosts):
|
||||||
if helpers.verbose >= 2:
|
helpers.logprefix = 'HH: '
|
||||||
helpers.logprefix = 'HH: '
|
|
||||||
else:
|
|
||||||
helpers.logprefix = 'hostwatch: '
|
|
||||||
|
|
||||||
debug1('Starting hostwatch with Python version %s\n'
|
debug1('Starting hostwatch with Python version %s'
|
||||||
% platform.python_version())
|
% platform.python_version())
|
||||||
|
|
||||||
for h in seed_hosts:
|
for h in seed_hosts:
|
||||||
|
@ -7,7 +7,7 @@ def nonfatal(func, *args):
|
|||||||
try:
|
try:
|
||||||
func(*args)
|
func(*args)
|
||||||
except Fatal as e:
|
except Fatal as e:
|
||||||
log('fw: error: %s\n' % e)
|
log('error: %s' % e)
|
||||||
|
|
||||||
|
|
||||||
def ipt_chain_exists(family, table, name):
|
def ipt_chain_exists(family, table, name):
|
||||||
@ -24,7 +24,7 @@ def ipt_chain_exists(family, table, name):
|
|||||||
if line.startswith('Chain %s ' % name):
|
if line.startswith('Chain %s ' % name):
|
||||||
return True
|
return True
|
||||||
except ssubprocess.CalledProcessError as e:
|
except ssubprocess.CalledProcessError as e:
|
||||||
raise Fatal('fw: %r returned %d' % (argv, e.returncode))
|
raise Fatal('%r returned %d' % (argv, e.returncode))
|
||||||
|
|
||||||
|
|
||||||
def ipt(family, table, *args):
|
def ipt(family, table, *args):
|
||||||
@ -34,10 +34,10 @@ def ipt(family, table, *args):
|
|||||||
argv = ['iptables', '-t', table] + list(args)
|
argv = ['iptables', '-t', table] + list(args)
|
||||||
else:
|
else:
|
||||||
raise Exception('Unsupported family "%s"' % family_to_string(family))
|
raise Exception('Unsupported family "%s"' % family_to_string(family))
|
||||||
debug1('%s\n' % ' '.join(argv))
|
debug1('%s' % ' '.join(argv))
|
||||||
rv = ssubprocess.call(argv, env=get_env())
|
rv = ssubprocess.call(argv, env=get_env())
|
||||||
if rv:
|
if rv:
|
||||||
raise Fatal('fw: %r returned %d' % (argv, rv))
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
|
||||||
|
|
||||||
def nft(family, table, action, *args):
|
def nft(family, table, action, *args):
|
||||||
@ -45,10 +45,10 @@ def nft(family, table, action, *args):
|
|||||||
argv = ['nft', action, 'inet', table] + list(args)
|
argv = ['nft', action, 'inet', table] + list(args)
|
||||||
else:
|
else:
|
||||||
raise Exception('Unsupported family "%s"' % family_to_string(family))
|
raise Exception('Unsupported family "%s"' % family_to_string(family))
|
||||||
debug1('%s\n' % ' '.join(argv))
|
debug1('%s' % ' '.join(argv))
|
||||||
rv = ssubprocess.call(argv, env=get_env())
|
rv = ssubprocess.call(argv, env=get_env())
|
||||||
if rv:
|
if rv:
|
||||||
raise Fatal('fw: %r returned %d' % (argv, rv))
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
|
||||||
|
|
||||||
_no_ttl_module = False
|
_no_ttl_module = False
|
||||||
@ -66,8 +66,8 @@ def ipt_ttl(family, *args):
|
|||||||
except Fatal:
|
except Fatal:
|
||||||
ipt(family, *args)
|
ipt(family, *args)
|
||||||
# we only get here if the non-ttl attempt succeeds
|
# we only get here if the non-ttl attempt succeeds
|
||||||
log('fw: WARNING: your iptables is missing '
|
log('WARNING: your iptables is missing '
|
||||||
'the ttl module.\n')
|
'the ttl module.')
|
||||||
_no_ttl_module = True
|
_no_ttl_module = True
|
||||||
else:
|
else:
|
||||||
ipt(family, *args)
|
ipt(family, *args)
|
||||||
|
@ -66,7 +66,7 @@ class BaseMethod(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def recv_udp(udp_listener, bufsize):
|
def recv_udp(udp_listener, bufsize):
|
||||||
debug3('Accept UDP using recvfrom.\n')
|
debug3('Accept UDP using recvfrom.')
|
||||||
data, srcip = udp_listener.recvfrom(bufsize)
|
data, srcip = udp_listener.recvfrom(bufsize)
|
||||||
return (srcip, None, data)
|
return (srcip, None, data)
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class BaseMethod(object):
|
|||||||
for key in ["udp", "dns", "ipv6", "ipv4", "user"]:
|
for key in ["udp", "dns", "ipv6", "ipv4", "user"]:
|
||||||
if getattr(features, key) and not getattr(avail, key):
|
if getattr(features, key) and not getattr(avail, key):
|
||||||
raise Fatal(
|
raise Fatal(
|
||||||
"Feature %s not supported with method %s.\n" %
|
"Feature %s not supported with method %s." %
|
||||||
(key, self.name))
|
(key, self.name))
|
||||||
|
|
||||||
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
def setup_firewall(self, port, dnsport, nslist, family, subnets, udp,
|
||||||
@ -108,13 +108,13 @@ def get_method(method_name):
|
|||||||
|
|
||||||
|
|
||||||
def get_auto_method():
|
def get_auto_method():
|
||||||
debug3("Selecting a method automatically...\n")
|
debug3("Selecting a method automatically...")
|
||||||
# Try these methods, in order:
|
# Try these methods, in order:
|
||||||
methods_to_try = ["nat", "nft", "pf", "ipfw"]
|
methods_to_try = ["nat", "nft", "pf", "ipfw"]
|
||||||
for m in methods_to_try:
|
for m in methods_to_try:
|
||||||
method = get_method(m)
|
method = get_method(m)
|
||||||
if method.is_supported():
|
if method.is_supported():
|
||||||
debug3("Method '%s' was automatically selected.\n" % m)
|
debug3("Method '%s' was automatically selected." % m)
|
||||||
return method
|
return method
|
||||||
|
|
||||||
raise Fatal("Unable to automatically find a supported method. Check that "
|
raise Fatal("Unable to automatically find a supported method. Check that "
|
||||||
|
@ -28,7 +28,7 @@ IPV6_RECVDSTADDR = 74
|
|||||||
|
|
||||||
if recvmsg == "python":
|
if recvmsg == "python":
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP python using recvmsg.\n')
|
debug3('Accept UDP python using recvmsg.')
|
||||||
data, ancdata, _, srcip = listener.recvmsg(4096,
|
data, ancdata, _, srcip = listener.recvmsg(4096,
|
||||||
socket.CMSG_SPACE(4))
|
socket.CMSG_SPACE(4))
|
||||||
dstip = None
|
dstip = None
|
||||||
@ -41,7 +41,7 @@ if recvmsg == "python":
|
|||||||
return (srcip, dstip, data)
|
return (srcip, dstip, data)
|
||||||
elif recvmsg == "socket_ext":
|
elif recvmsg == "socket_ext":
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP using socket_ext recvmsg.\n')
|
debug3('Accept UDP using socket_ext recvmsg.')
|
||||||
srcip, data, adata, _ = listener.recvmsg((bufsize,),
|
srcip, data, adata, _ = listener.recvmsg((bufsize,),
|
||||||
socket.CMSG_SPACE(4))
|
socket.CMSG_SPACE(4))
|
||||||
dstip = None
|
dstip = None
|
||||||
@ -54,7 +54,7 @@ elif recvmsg == "socket_ext":
|
|||||||
return (srcip, dstip, data[0])
|
return (srcip, dstip, data[0])
|
||||||
else:
|
else:
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP using recvfrom.\n')
|
debug3('Accept UDP using recvfrom.')
|
||||||
data, srcip = listener.recvfrom(bufsize)
|
data, srcip = listener.recvfrom(bufsize)
|
||||||
return (srcip, None, data)
|
return (srcip, None, data)
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ def ipfw_rule_exists(n):
|
|||||||
for line in p.stdout:
|
for line in p.stdout:
|
||||||
if line.startswith(b'%05d ' % n):
|
if line.startswith(b'%05d ' % n):
|
||||||
if not ('ipttl 63' in line or 'check-state' in line):
|
if not ('ipttl 63' in line or 'check-state' in line):
|
||||||
log('non-sshuttle ipfw rule: %r\n' % line.strip())
|
log('non-sshuttle ipfw rule: %r' % line.strip())
|
||||||
raise Fatal('non-sshuttle ipfw rule #%d already exists!' % n)
|
raise Fatal('non-sshuttle ipfw rule #%d already exists!' % n)
|
||||||
found = True
|
found = True
|
||||||
rv = p.wait()
|
rv = p.wait()
|
||||||
@ -96,7 +96,7 @@ def _fill_oldctls(prefix):
|
|||||||
|
|
||||||
def _sysctl_set(name, val):
|
def _sysctl_set(name, val):
|
||||||
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
|
argv = ['sysctl', '-w', '%s=%s' % (name, val)]
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
debug1('>> %s' % ' '.join(argv))
|
||||||
return ssubprocess.call(argv, stdout=open(os.devnull, 'w'), env=get_env())
|
return ssubprocess.call(argv, stdout=open(os.devnull, 'w'), env=get_env())
|
||||||
# No env: No output. (Or error that won't be parsed.)
|
# No env: No output. (Or error that won't be parsed.)
|
||||||
|
|
||||||
@ -111,13 +111,13 @@ def sysctl_set(name, val, permanent=False):
|
|||||||
if not _oldctls:
|
if not _oldctls:
|
||||||
_fill_oldctls(PREFIX)
|
_fill_oldctls(PREFIX)
|
||||||
if not (name in _oldctls):
|
if not (name in _oldctls):
|
||||||
debug1('>> No such sysctl: %r\n' % name)
|
debug1('>> No such sysctl: %r' % name)
|
||||||
return False
|
return False
|
||||||
oldval = _oldctls[name]
|
oldval = _oldctls[name]
|
||||||
if val != oldval:
|
if val != oldval:
|
||||||
rv = _sysctl_set(name, val)
|
rv = _sysctl_set(name, val)
|
||||||
if rv == 0 and permanent:
|
if rv == 0 and permanent:
|
||||||
debug1('>> ...saving permanently in /etc/sysctl.conf\n')
|
debug1('>> ...saving permanently in /etc/sysctl.conf')
|
||||||
f = open('/etc/sysctl.conf', 'a')
|
f = open('/etc/sysctl.conf', 'a')
|
||||||
f.write('\n'
|
f.write('\n'
|
||||||
'# Added by sshuttle\n'
|
'# Added by sshuttle\n'
|
||||||
@ -130,7 +130,7 @@ def sysctl_set(name, val, permanent=False):
|
|||||||
|
|
||||||
def ipfw(*args):
|
def ipfw(*args):
|
||||||
argv = ['ipfw', '-q'] + list(args)
|
argv = ['ipfw', '-q'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
debug1('>> %s' % ' '.join(argv))
|
||||||
rv = ssubprocess.call(argv, env=get_env())
|
rv = ssubprocess.call(argv, env=get_env())
|
||||||
# No env: No output. (Or error that won't be parsed.)
|
# No env: No output. (Or error that won't be parsed.)
|
||||||
if rv:
|
if rv:
|
||||||
@ -139,7 +139,7 @@ def ipfw(*args):
|
|||||||
|
|
||||||
def ipfw_noexit(*args):
|
def ipfw_noexit(*args):
|
||||||
argv = ['ipfw', '-q'] + list(args)
|
argv = ['ipfw', '-q'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
debug1('>> %s' % ' '.join(argv))
|
||||||
ssubprocess.call(argv, env=get_env())
|
ssubprocess.call(argv, env=get_env())
|
||||||
# No env: No output. (Or error that won't be parsed.)
|
# No env: No output. (Or error that won't be parsed.)
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ class Method(BaseMethod):
|
|||||||
if not dstip:
|
if not dstip:
|
||||||
debug1(
|
debug1(
|
||||||
"-- ignored UDP from %r: "
|
"-- ignored UDP from %r: "
|
||||||
"couldn't determine destination IP address\n" % (srcip,))
|
"couldn't determine destination IP address" % (srcip,))
|
||||||
return None
|
return None
|
||||||
return srcip, dstip, data
|
return srcip, dstip, data
|
||||||
|
|
||||||
@ -169,10 +169,10 @@ class Method(BaseMethod):
|
|||||||
if not srcip:
|
if not srcip:
|
||||||
debug1(
|
debug1(
|
||||||
"-- ignored UDP to %r: "
|
"-- ignored UDP to %r: "
|
||||||
"couldn't determine source IP address\n" % (dstip,))
|
"couldn't determine source IP address" % (dstip,))
|
||||||
return
|
return
|
||||||
|
|
||||||
# debug3('Sending SRC: %r DST: %r\n' % (srcip, dstip))
|
# debug3('Sending SRC: %r DST: %r' % (srcip, dstip))
|
||||||
sender = socket.socket(sock.family, socket.SOCK_DGRAM)
|
sender = socket.socket(sock.family, socket.SOCK_DGRAM)
|
||||||
sender.setsockopt(socket.SOL_IP, IP_BINDANY, 1)
|
sender.setsockopt(socket.SOL_IP, IP_BINDANY, 1)
|
||||||
sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
sender.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
@ -258,5 +258,5 @@ class Method(BaseMethod):
|
|||||||
if which("ipfw"):
|
if which("ipfw"):
|
||||||
return True
|
return True
|
||||||
debug2("ipfw method not supported because 'ipfw' command is "
|
debug2("ipfw method not supported because 'ipfw' command is "
|
||||||
"missing.\n")
|
"missing.")
|
||||||
return False
|
return False
|
||||||
|
@ -129,5 +129,5 @@ class Method(BaseMethod):
|
|||||||
if which("iptables"):
|
if which("iptables"):
|
||||||
return True
|
return True
|
||||||
debug2("nat method not supported because 'iptables' command "
|
debug2("nat method not supported because 'iptables' command "
|
||||||
"is missing.\n")
|
"is missing.")
|
||||||
return False
|
return False
|
||||||
|
@ -118,5 +118,5 @@ class Method(BaseMethod):
|
|||||||
def is_supported(self):
|
def is_supported(self):
|
||||||
if which("nft"):
|
if which("nft"):
|
||||||
return True
|
return True
|
||||||
debug2("nft method not supported because 'nft' command is missing.\n")
|
debug2("nft method not supported because 'nft' command is missing.")
|
||||||
return False
|
return False
|
||||||
|
@ -386,7 +386,7 @@ else:
|
|||||||
|
|
||||||
def pfctl(args, stdin=None):
|
def pfctl(args, stdin=None):
|
||||||
argv = ['pfctl'] + shlex.split(args)
|
argv = ['pfctl'] + shlex.split(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
debug1('>> %s' % ' '.join(argv))
|
||||||
p = ssubprocess.Popen(argv, stdin=ssubprocess.PIPE,
|
p = ssubprocess.Popen(argv, stdin=ssubprocess.PIPE,
|
||||||
stdout=ssubprocess.PIPE,
|
stdout=ssubprocess.PIPE,
|
||||||
stderr=ssubprocess.PIPE,
|
stderr=ssubprocess.PIPE,
|
||||||
@ -495,5 +495,5 @@ class Method(BaseMethod):
|
|||||||
def is_supported(self):
|
def is_supported(self):
|
||||||
if which("pfctl"):
|
if which("pfctl"):
|
||||||
return True
|
return True
|
||||||
debug2("pf method not supported because 'pfctl' command is missing.\n")
|
debug2("pf method not supported because 'pfctl' command is missing.")
|
||||||
return False
|
return False
|
||||||
|
@ -32,7 +32,7 @@ IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
|
|||||||
|
|
||||||
if recvmsg == "python":
|
if recvmsg == "python":
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP python using recvmsg.\n')
|
debug3('Accept UDP python using recvmsg.')
|
||||||
data, ancdata, _, srcip = listener.recvmsg(
|
data, ancdata, _, srcip = listener.recvmsg(
|
||||||
4096, socket.CMSG_SPACE(24))
|
4096, socket.CMSG_SPACE(24))
|
||||||
dstip = None
|
dstip = None
|
||||||
@ -63,7 +63,7 @@ if recvmsg == "python":
|
|||||||
return (srcip, dstip, data)
|
return (srcip, dstip, data)
|
||||||
elif recvmsg == "socket_ext":
|
elif recvmsg == "socket_ext":
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP using socket_ext recvmsg.\n')
|
debug3('Accept UDP using socket_ext recvmsg.')
|
||||||
srcip, data, adata, _ = listener.recvmsg(
|
srcip, data, adata, _ = listener.recvmsg(
|
||||||
(bufsize,), socket.CMSG_SPACE(24))
|
(bufsize,), socket.CMSG_SPACE(24))
|
||||||
dstip = None
|
dstip = None
|
||||||
@ -96,7 +96,7 @@ elif recvmsg == "socket_ext":
|
|||||||
return (srcip, dstip, data[0])
|
return (srcip, dstip, data[0])
|
||||||
else:
|
else:
|
||||||
def recv_udp(listener, bufsize):
|
def recv_udp(listener, bufsize):
|
||||||
debug3('Accept UDP using recvfrom.\n')
|
debug3('Accept UDP using recvfrom.')
|
||||||
data, srcip = listener.recvfrom(bufsize)
|
data, srcip = listener.recvfrom(bufsize)
|
||||||
return (srcip, None, data)
|
return (srcip, None, data)
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ def _notify(message):
|
|||||||
try:
|
try:
|
||||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
debug1("Error creating socket to notify systemd: %s\n" % e)
|
debug1("Error creating socket to notify systemd: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not message:
|
if not message:
|
||||||
@ -37,7 +37,7 @@ def _notify(message):
|
|||||||
try:
|
try:
|
||||||
return (sock.sendto(message, addr) > 0)
|
return (sock.sendto(message, addr) > 0)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
debug1("Error notifying systemd: %s\n" % e)
|
debug1("Error notifying systemd: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ def _list_routes(argv, extract_route):
|
|||||||
(socket.AF_INET, socket.inet_ntoa(struct.pack('!I', ip)), width))
|
(socket.AF_INET, socket.inet_ntoa(struct.pack('!I', ip)), width))
|
||||||
rv = p.wait()
|
rv = p.wait()
|
||||||
if rv != 0:
|
if rv != 0:
|
||||||
log('WARNING: %r returned %d\n' % (argv, rv))
|
log('WARNING: %r returned %d' % (argv, rv))
|
||||||
|
|
||||||
return routes
|
return routes
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ def list_routes():
|
|||||||
routes = _list_routes(['netstat', '-rn'], _route_netstat)
|
routes = _list_routes(['netstat', '-rn'], _route_netstat)
|
||||||
else:
|
else:
|
||||||
log('WARNING: Neither "ip" nor "netstat" were found on the server. '
|
log('WARNING: Neither "ip" nor "netstat" were found on the server. '
|
||||||
'--auto-nets feature will not work.\n')
|
'--auto-nets feature will not work.')
|
||||||
routes = []
|
routes = []
|
||||||
|
|
||||||
for (family, ip, width) in routes:
|
for (family, ip, width) in routes:
|
||||||
@ -135,7 +135,7 @@ def start_hostwatch(seed_hosts, auto_hosts):
|
|||||||
s1.close()
|
s1.close()
|
||||||
rv = hostwatch.hw_main(seed_hosts, auto_hosts) or 0
|
rv = hostwatch.hw_main(seed_hosts, auto_hosts) or 0
|
||||||
except Exception:
|
except Exception:
|
||||||
log('%s\n' % _exc_dump())
|
log('%s' % _exc_dump())
|
||||||
rv = 98
|
rv = 98
|
||||||
finally:
|
finally:
|
||||||
os._exit(rv)
|
os._exit(rv)
|
||||||
@ -196,7 +196,7 @@ class DnsProxy(Handler):
|
|||||||
|
|
||||||
self.peers[sock] = peer
|
self.peers[sock] = peer
|
||||||
|
|
||||||
debug2('DNS: sending to %r:%d (try %d)\n' % (peer, port, self.tries))
|
debug2('DNS: sending to %r:%d (try %d)' % (peer, port, self.tries))
|
||||||
try:
|
try:
|
||||||
sock.send(self.request)
|
sock.send(self.request)
|
||||||
self.socks.append(sock)
|
self.socks.append(sock)
|
||||||
@ -206,11 +206,11 @@ class DnsProxy(Handler):
|
|||||||
# might have been spurious; try again.
|
# might have been spurious; try again.
|
||||||
# Note: these errors sometimes are reported by recv(),
|
# Note: these errors sometimes are reported by recv(),
|
||||||
# and sometimes by send(). We have to catch both.
|
# and sometimes by send(). We have to catch both.
|
||||||
debug2('DNS send to %r: %s\n' % (peer, e))
|
debug2('DNS send to %r: %s' % (peer, e))
|
||||||
self.try_send()
|
self.try_send()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
log('DNS send to %r: %s\n' % (peer, e))
|
log('DNS send to %r: %s' % (peer, e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def callback(self, sock):
|
def callback(self, sock):
|
||||||
@ -227,13 +227,13 @@ class DnsProxy(Handler):
|
|||||||
# might have been spurious; try again.
|
# might have been spurious; try again.
|
||||||
# Note: these errors sometimes are reported by recv(),
|
# Note: these errors sometimes are reported by recv(),
|
||||||
# and sometimes by send(). We have to catch both.
|
# and sometimes by send(). We have to catch both.
|
||||||
debug2('DNS recv from %r: %s\n' % (peer, e))
|
debug2('DNS recv from %r: %s' % (peer, e))
|
||||||
self.try_send()
|
self.try_send()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
log('DNS recv from %r: %s\n' % (peer, e))
|
log('DNS recv from %r: %s' % (peer, e))
|
||||||
return
|
return
|
||||||
debug2('DNS response: %d bytes\n' % len(data))
|
debug2('DNS response: %d bytes' % len(data))
|
||||||
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
|
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)
|
||||||
self.ok = False
|
self.ok = False
|
||||||
|
|
||||||
@ -251,12 +251,12 @@ class UdpProxy(Handler):
|
|||||||
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 63)
|
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 63)
|
||||||
|
|
||||||
def send(self, dstip, data):
|
def send(self, dstip, data):
|
||||||
debug2(' s: UDP: sending to %r port %d\n' % dstip)
|
debug2('UDP: sending to %r port %d' % dstip)
|
||||||
try:
|
try:
|
||||||
self.sock.sendto(data, dstip)
|
self.sock.sendto(data, dstip)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log(' s: UDP send to %r port %d: %s\n' % (dstip[0], dstip[1], e))
|
log('UDP send to %r port %d: %s' % (dstip[0], dstip[1], e))
|
||||||
return
|
return
|
||||||
|
|
||||||
def callback(self, sock):
|
def callback(self, sock):
|
||||||
@ -264,19 +264,19 @@ class UdpProxy(Handler):
|
|||||||
data, peer = sock.recvfrom(4096)
|
data, peer = sock.recvfrom(4096)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
log(' s: UDP recv from %r port %d: %s\n' % (peer[0], peer[1], e))
|
log('UDP recv from %r port %d: %s' % (peer[0], peer[1], e))
|
||||||
return
|
return
|
||||||
debug2(' s: UDP response: %d bytes\n' % len(data))
|
debug2('UDP response: %d bytes' % len(data))
|
||||||
hdr = b("%s,%r," % (peer[0], peer[1]))
|
hdr = b("%s,%r," % (peer[0], peer[1]))
|
||||||
self.mux.send(self.chan, ssnet.CMD_UDP_DATA, hdr + data)
|
self.mux.send(self.chan, ssnet.CMD_UDP_DATA, hdr + data)
|
||||||
|
|
||||||
|
|
||||||
def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
||||||
debug1(' s: Starting server with Python version %s\n'
|
|
||||||
% platform.python_version())
|
|
||||||
|
|
||||||
helpers.logprefix = ' s: '
|
helpers.logprefix = ' s: '
|
||||||
debug1('latency control setting = %r\n' % latency_control)
|
|
||||||
|
debug1('Starting server with Python version %s'
|
||||||
|
% platform.python_version())
|
||||||
|
debug1('latency control setting = %r' % latency_control)
|
||||||
|
|
||||||
# synchronization header
|
# synchronization header
|
||||||
sys.stdout.write('\0\0SSHUTTLE0001')
|
sys.stdout.write('\0\0SSHUTTLE0001')
|
||||||
@ -286,12 +286,12 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
mux = Mux(sys.stdin, sys.stdout)
|
mux = Mux(sys.stdin, sys.stdout)
|
||||||
handlers.append(mux)
|
handlers.append(mux)
|
||||||
|
|
||||||
debug1('auto-nets:' + str(auto_nets) + '\n')
|
debug1('auto-nets:' + str(auto_nets))
|
||||||
if auto_nets:
|
if auto_nets:
|
||||||
routes = list(list_routes())
|
routes = list(list_routes())
|
||||||
debug1('available routes:\n')
|
debug1('available routes:')
|
||||||
for r in routes:
|
for r in routes:
|
||||||
debug1(' %d/%s/%d\n' % r)
|
debug1(' %d/%s/%d' % r)
|
||||||
else:
|
else:
|
||||||
routes = []
|
routes = []
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
hw.leftover = b('')
|
hw.leftover = b('')
|
||||||
mux.send(0, ssnet.CMD_HOST_LIST, b('\n').join(lines))
|
mux.send(0, ssnet.CMD_HOST_LIST, b('\n').join(lines))
|
||||||
else:
|
else:
|
||||||
raise Fatal(' s: hostwatch process died')
|
raise Fatal('hostwatch process died')
|
||||||
|
|
||||||
def got_host_req(data):
|
def got_host_req(data):
|
||||||
if not hw.pid:
|
if not hw.pid:
|
||||||
@ -343,7 +343,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
dnshandlers = {}
|
dnshandlers = {}
|
||||||
|
|
||||||
def dns_req(channel, data):
|
def dns_req(channel, data):
|
||||||
debug2('Incoming DNS request channel=%d.\n' % channel)
|
debug2('Incoming DNS request channel=%d.' % channel)
|
||||||
h = DnsProxy(mux, channel, data, to_nameserver)
|
h = DnsProxy(mux, channel, data, to_nameserver)
|
||||||
handlers.append(h)
|
handlers.append(h)
|
||||||
dnshandlers[channel] = h
|
dnshandlers[channel] = h
|
||||||
@ -352,25 +352,25 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
udphandlers = {}
|
udphandlers = {}
|
||||||
|
|
||||||
def udp_req(channel, cmd, data):
|
def udp_req(channel, cmd, data):
|
||||||
debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
|
debug2('Incoming UDP request channel=%d, cmd=%d' % (channel, cmd))
|
||||||
if cmd == ssnet.CMD_UDP_DATA:
|
if cmd == ssnet.CMD_UDP_DATA:
|
||||||
(dstip, dstport, data) = data.split(b(','), 2)
|
(dstip, dstport, data) = data.split(b(','), 2)
|
||||||
dstport = int(dstport)
|
dstport = int(dstport)
|
||||||
debug2('is incoming UDP data. %r %d.\n' % (dstip, dstport))
|
debug2('is incoming UDP data. %r %d.' % (dstip, dstport))
|
||||||
h = udphandlers[channel]
|
h = udphandlers[channel]
|
||||||
h.send((dstip, dstport), data)
|
h.send((dstip, dstport), data)
|
||||||
elif cmd == ssnet.CMD_UDP_CLOSE:
|
elif cmd == ssnet.CMD_UDP_CLOSE:
|
||||||
debug2('is incoming UDP close\n')
|
debug2('is incoming UDP close')
|
||||||
h = udphandlers[channel]
|
h = udphandlers[channel]
|
||||||
h.ok = False
|
h.ok = False
|
||||||
del mux.channels[channel]
|
del mux.channels[channel]
|
||||||
|
|
||||||
def udp_open(channel, data):
|
def udp_open(channel, data):
|
||||||
debug2('Incoming UDP open.\n')
|
debug2('Incoming UDP open.')
|
||||||
family = int(data)
|
family = int(data)
|
||||||
mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
|
mux.channels[channel] = lambda cmd, data: udp_req(channel, cmd, data)
|
||||||
if channel in udphandlers:
|
if channel in udphandlers:
|
||||||
raise Fatal(' s: UDP connection channel %d already open' % channel)
|
raise Fatal('UDP connection channel %d already open' % channel)
|
||||||
else:
|
else:
|
||||||
h = UdpProxy(mux, channel, family)
|
h = UdpProxy(mux, channel, family)
|
||||||
handlers.append(h)
|
handlers.append(h)
|
||||||
@ -383,7 +383,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
(rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
|
(rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
|
||||||
if rpid:
|
if rpid:
|
||||||
raise Fatal(
|
raise Fatal(
|
||||||
'hostwatch exited unexpectedly: code 0x%04x\n' % rv)
|
'hostwatch exited unexpectedly: code 0x%04x' % rv)
|
||||||
|
|
||||||
ssnet.runonce(handlers, mux)
|
ssnet.runonce(handlers, mux)
|
||||||
if latency_control:
|
if latency_control:
|
||||||
@ -394,7 +394,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
remove = []
|
remove = []
|
||||||
for channel, h in dnshandlers.items():
|
for channel, h in dnshandlers.items():
|
||||||
if h.timeout < now or not h.ok:
|
if h.timeout < now or not h.ok:
|
||||||
debug3('expiring dnsreqs channel=%d\n' % channel)
|
debug3('expiring dnsreqs channel=%d' % channel)
|
||||||
remove.append(channel)
|
remove.append(channel)
|
||||||
h.ok = False
|
h.ok = False
|
||||||
for channel in remove:
|
for channel in remove:
|
||||||
@ -403,7 +403,7 @@ def main(latency_control, auto_hosts, to_nameserver, auto_nets):
|
|||||||
remove = []
|
remove = []
|
||||||
for channel, h in udphandlers.items():
|
for channel, h in udphandlers.items():
|
||||||
if not h.ok:
|
if not h.ok:
|
||||||
debug3('expiring UDP channel=%d\n' % channel)
|
debug3('expiring UDP channel=%d' % channel)
|
||||||
remove.append(channel)
|
remove.append(channel)
|
||||||
h.ok = False
|
h.ok = False
|
||||||
for channel in remove:
|
for channel in remove:
|
||||||
|
@ -160,7 +160,7 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
|||||||
s1a, s1b = os.dup(s1.fileno()), os.dup(s1.fileno())
|
s1a, s1b = os.dup(s1.fileno()), os.dup(s1.fileno())
|
||||||
s1.close()
|
s1.close()
|
||||||
|
|
||||||
debug2('executing: %r\n' % argv)
|
debug2('executing: %r' % argv)
|
||||||
p = ssubprocess.Popen(argv, stdin=s1a, stdout=s1b, preexec_fn=setup,
|
p = ssubprocess.Popen(argv, stdin=s1a, stdout=s1b, preexec_fn=setup,
|
||||||
close_fds=True, stderr=stderr)
|
close_fds=True, stderr=stderr)
|
||||||
os.close(s1a)
|
os.close(s1a)
|
||||||
|
@ -83,7 +83,7 @@ def _nb_clean(func, *args):
|
|||||||
if e.errno not in (errno.EWOULDBLOCK, errno.EAGAIN):
|
if e.errno not in (errno.EWOULDBLOCK, errno.EAGAIN):
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
debug3('%s: err was: %s\n' % (func.__name__, e))
|
debug3('%s: err was: %s' % (func.__name__, e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class SockWrapper:
|
|||||||
def __init__(self, rsock, wsock, connect_to=None, peername=None):
|
def __init__(self, rsock, wsock, connect_to=None, peername=None):
|
||||||
global _swcount
|
global _swcount
|
||||||
_swcount += 1
|
_swcount += 1
|
||||||
debug3('creating new SockWrapper (%d now exist)\n' % _swcount)
|
debug3('creating new SockWrapper (%d now exist)' % _swcount)
|
||||||
self.exc = None
|
self.exc = None
|
||||||
self.rsock = rsock
|
self.rsock = rsock
|
||||||
self.wsock = wsock
|
self.wsock = wsock
|
||||||
@ -124,9 +124,9 @@ class SockWrapper:
|
|||||||
def __del__(self):
|
def __del__(self):
|
||||||
global _swcount
|
global _swcount
|
||||||
_swcount -= 1
|
_swcount -= 1
|
||||||
debug1('%r: deleting (%d remain)\n' % (self, _swcount))
|
debug1('%r: deleting (%d remain)' % (self, _swcount))
|
||||||
if self.exc:
|
if self.exc:
|
||||||
debug1('%r: error was: %s\n' % (self, self.exc))
|
debug1('%r: error was: %s' % (self, self.exc))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.rsock == self.wsock:
|
if self.rsock == self.wsock:
|
||||||
@ -148,14 +148,14 @@ class SockWrapper:
|
|||||||
if not self.connect_to:
|
if not self.connect_to:
|
||||||
return # already connected
|
return # already connected
|
||||||
self.rsock.setblocking(False)
|
self.rsock.setblocking(False)
|
||||||
debug3('%r: trying connect to %r\n' % (self, self.connect_to))
|
debug3('%r: trying connect to %r' % (self, self.connect_to))
|
||||||
try:
|
try:
|
||||||
self.rsock.connect(self.connect_to)
|
self.rsock.connect(self.connect_to)
|
||||||
# connected successfully (Linux)
|
# connected successfully (Linux)
|
||||||
self.connect_to = None
|
self.connect_to = None
|
||||||
except socket.error:
|
except socket.error:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
debug3('%r: connect result: %s\n' % (self, e))
|
debug3('%r: connect result: %s' % (self, e))
|
||||||
if e.args[0] == errno.EINVAL:
|
if e.args[0] == errno.EINVAL:
|
||||||
# this is what happens when you call connect() on a socket
|
# this is what happens when you call connect() on a socket
|
||||||
# that is now connected but returned EINPROGRESS last time,
|
# that is now connected but returned EINPROGRESS last time,
|
||||||
@ -165,7 +165,7 @@ class SockWrapper:
|
|||||||
realerr = self.rsock.getsockopt(socket.SOL_SOCKET,
|
realerr = self.rsock.getsockopt(socket.SOL_SOCKET,
|
||||||
socket.SO_ERROR)
|
socket.SO_ERROR)
|
||||||
e = socket.error(realerr, os.strerror(realerr))
|
e = socket.error(realerr, os.strerror(realerr))
|
||||||
debug3('%r: fixed connect result: %s\n' % (self, e))
|
debug3('%r: fixed connect result: %s' % (self, e))
|
||||||
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
if e.args[0] in [errno.EINPROGRESS, errno.EALREADY]:
|
||||||
pass # not connected yet
|
pass # not connected yet
|
||||||
elif e.args[0] == 0:
|
elif e.args[0] == 0:
|
||||||
@ -191,13 +191,13 @@ class SockWrapper:
|
|||||||
|
|
||||||
def noread(self):
|
def noread(self):
|
||||||
if not self.shut_read:
|
if not self.shut_read:
|
||||||
debug2('%r: done reading\n' % self)
|
debug2('%r: done reading' % self)
|
||||||
self.shut_read = True
|
self.shut_read = True
|
||||||
# self.rsock.shutdown(SHUT_RD) # doesn't do anything anyway
|
# self.rsock.shutdown(SHUT_RD) # doesn't do anything anyway
|
||||||
|
|
||||||
def nowrite(self):
|
def nowrite(self):
|
||||||
if not self.shut_write:
|
if not self.shut_write:
|
||||||
debug2('%r: done writing\n' % self)
|
debug2('%r: done writing' % self)
|
||||||
self.shut_write = True
|
self.shut_write = True
|
||||||
try:
|
try:
|
||||||
self.wsock.shutdown(SHUT_WR)
|
self.wsock.shutdown(SHUT_WR)
|
||||||
@ -218,7 +218,7 @@ class SockWrapper:
|
|||||||
except OSError:
|
except OSError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
if e.errno == errno.EPIPE:
|
if e.errno == errno.EPIPE:
|
||||||
debug1('%r: uwrite: got EPIPE\n' % self)
|
debug1('%r: uwrite: got EPIPE' % self)
|
||||||
self.nowrite()
|
self.nowrite()
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
@ -275,12 +275,12 @@ class Handler:
|
|||||||
_add(r, i)
|
_add(r, i)
|
||||||
|
|
||||||
def callback(self, sock):
|
def callback(self, sock):
|
||||||
log('--no callback defined-- %r\n' % self)
|
log('--no callback defined-- %r' % self)
|
||||||
(r, _, _) = select.select(self.socks, [], [], 0)
|
(r, _, _) = select.select(self.socks, [], [], 0)
|
||||||
for s in r:
|
for s in r:
|
||||||
v = s.recv(4096)
|
v = s.recv(4096)
|
||||||
if not v:
|
if not v:
|
||||||
log('--closed-- %r\n' % self)
|
log('--closed-- %r' % self)
|
||||||
self.socks = []
|
self.socks = []
|
||||||
self.ok = False
|
self.ok = False
|
||||||
|
|
||||||
@ -377,7 +377,7 @@ class Mux(Handler):
|
|||||||
# for b in self.outbuf:
|
# for b in self.outbuf:
|
||||||
# (s1,s2,c) = struct.unpack('!ccH', b[:4])
|
# (s1,s2,c) = struct.unpack('!ccH', b[:4])
|
||||||
# ob.append(c)
|
# ob.append(c)
|
||||||
# log('outbuf: %d %r\n' % (self.amount_queued(), ob))
|
# log('outbuf: %d %r' % (self.amount_queued(), ob))
|
||||||
|
|
||||||
def send(self, channel, cmd, data):
|
def send(self, channel, cmd, data):
|
||||||
assert isinstance(data, bytes)
|
assert isinstance(data, bytes)
|
||||||
@ -385,18 +385,18 @@ class Mux(Handler):
|
|||||||
p = struct.pack('!ccHHH', b('S'), b('S'), channel, cmd, len(data)) \
|
p = struct.pack('!ccHHH', b('S'), b('S'), channel, cmd, len(data)) \
|
||||||
+ data
|
+ data
|
||||||
self.outbuf.append(p)
|
self.outbuf.append(p)
|
||||||
debug2(' > channel=%d cmd=%s len=%d (fullness=%d)\n'
|
debug2(' > channel=%d cmd=%s len=%d (fullness=%d)'
|
||||||
% (channel, cmd_to_name.get(cmd, hex(cmd)),
|
% (channel, cmd_to_name.get(cmd, hex(cmd)),
|
||||||
len(data), self.fullness))
|
len(data), self.fullness))
|
||||||
self.fullness += len(data)
|
self.fullness += len(data)
|
||||||
|
|
||||||
def got_packet(self, channel, cmd, data):
|
def got_packet(self, channel, cmd, data):
|
||||||
debug2('< channel=%d cmd=%s len=%d\n'
|
debug2('< channel=%d cmd=%s len=%d'
|
||||||
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
||||||
if cmd == CMD_PING:
|
if cmd == CMD_PING:
|
||||||
self.send(0, CMD_PONG, data)
|
self.send(0, CMD_PONG, data)
|
||||||
elif cmd == CMD_PONG:
|
elif cmd == CMD_PONG:
|
||||||
debug2('received PING response\n')
|
debug2('received PING response')
|
||||||
self.too_full = False
|
self.too_full = False
|
||||||
self.fullness = 0
|
self.fullness = 0
|
||||||
elif cmd == CMD_EXIT:
|
elif cmd == CMD_EXIT:
|
||||||
@ -431,7 +431,7 @@ class Mux(Handler):
|
|||||||
else:
|
else:
|
||||||
callback = self.channels.get(channel)
|
callback = self.channels.get(channel)
|
||||||
if not callback:
|
if not callback:
|
||||||
log('warning: closed channel %d got cmd=%s len=%d\n'
|
log('warning: closed channel %d got cmd=%s len=%d'
|
||||||
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
% (channel, cmd_to_name.get(cmd, hex(cmd)), len(data)))
|
||||||
else:
|
else:
|
||||||
callback(cmd, data)
|
callback(cmd, data)
|
||||||
@ -446,7 +446,7 @@ class Mux(Handler):
|
|||||||
flags = fcntl.fcntl(self.wfile.fileno(), fcntl.F_SETFL, flags)
|
flags = fcntl.fcntl(self.wfile.fileno(), fcntl.F_SETFL, flags)
|
||||||
if self.outbuf and self.outbuf[0]:
|
if self.outbuf and self.outbuf[0]:
|
||||||
wrote = _nb_clean(os.write, self.wfile.fileno(), self.outbuf[0])
|
wrote = _nb_clean(os.write, self.wfile.fileno(), self.outbuf[0])
|
||||||
debug2('mux wrote: %r/%d\n' % (wrote, len(self.outbuf[0])))
|
debug2('mux wrote: %r/%d' % (wrote, len(self.outbuf[0])))
|
||||||
if wrote:
|
if wrote:
|
||||||
self.outbuf[0] = self.outbuf[0][wrote:]
|
self.outbuf[0] = self.outbuf[0][wrote:]
|
||||||
while self.outbuf and not self.outbuf[0]:
|
while self.outbuf and not self.outbuf[0]:
|
||||||
@ -465,7 +465,7 @@ class Mux(Handler):
|
|||||||
except OSError:
|
except OSError:
|
||||||
_, e = sys.exc_info()[:2]
|
_, e = sys.exc_info()[:2]
|
||||||
raise Fatal('other end: %r' % e)
|
raise Fatal('other end: %r' % e)
|
||||||
# log('<<< %r\n' % b)
|
# log('<<< %r' % b)
|
||||||
if read == b(''): # EOF
|
if read == b(''): # EOF
|
||||||
self.ok = False
|
self.ok = False
|
||||||
if read:
|
if read:
|
||||||
@ -473,7 +473,7 @@ class Mux(Handler):
|
|||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
self.fill()
|
self.fill()
|
||||||
# log('inbuf is: (%d,%d) %r\n'
|
# log('inbuf is: (%d,%d) %r'
|
||||||
# % (self.want, len(self.inbuf), self.inbuf))
|
# % (self.want, len(self.inbuf), self.inbuf))
|
||||||
while 1:
|
while 1:
|
||||||
if len(self.inbuf) >= (self.want or HDR_LEN):
|
if len(self.inbuf) >= (self.want or HDR_LEN):
|
||||||
@ -511,7 +511,7 @@ class MuxWrapper(SockWrapper):
|
|||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.mux.channels[channel] = self.got_packet
|
self.mux.channels[channel] = self.got_packet
|
||||||
self.socks = []
|
self.socks = []
|
||||||
debug2('new channel: %d\n' % channel)
|
debug2('new channel: %d' % channel)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.nowrite()
|
self.nowrite()
|
||||||
@ -527,7 +527,7 @@ class MuxWrapper(SockWrapper):
|
|||||||
|
|
||||||
def setnoread(self):
|
def setnoread(self):
|
||||||
if not self.shut_read:
|
if not self.shut_read:
|
||||||
debug2('%r: done reading\n' % self)
|
debug2('%r: done reading' % self)
|
||||||
self.shut_read = True
|
self.shut_read = True
|
||||||
self.maybe_close()
|
self.maybe_close()
|
||||||
|
|
||||||
@ -538,13 +538,13 @@ class MuxWrapper(SockWrapper):
|
|||||||
|
|
||||||
def setnowrite(self):
|
def setnowrite(self):
|
||||||
if not self.shut_write:
|
if not self.shut_write:
|
||||||
debug2('%r: done writing\n' % self)
|
debug2('%r: done writing' % self)
|
||||||
self.shut_write = True
|
self.shut_write = True
|
||||||
self.maybe_close()
|
self.maybe_close()
|
||||||
|
|
||||||
def maybe_close(self):
|
def maybe_close(self):
|
||||||
if self.shut_read and self.shut_write:
|
if self.shut_read and self.shut_write:
|
||||||
debug2('%r: closing connection\n' % self)
|
debug2('%r: closing connection' % self)
|
||||||
# remove the mux's reference to us. The python garbage collector
|
# remove the mux's reference to us. The python garbage collector
|
||||||
# will then be able to reap our object.
|
# will then be able to reap our object.
|
||||||
self.mux.channels[self.channel] = None
|
self.mux.channels[self.channel] = None
|
||||||
@ -581,7 +581,7 @@ class MuxWrapper(SockWrapper):
|
|||||||
|
|
||||||
|
|
||||||
def connect_dst(family, ip, port):
|
def connect_dst(family, ip, port):
|
||||||
debug2('Connecting to %s:%d\n' % (ip, port))
|
debug2('Connecting to %s:%d' % (ip, port))
|
||||||
outsock = socket.socket(family)
|
outsock = socket.socket(family)
|
||||||
outsock.setsockopt(socket.SOL_IP, socket.IP_TTL, 63)
|
outsock.setsockopt(socket.SOL_IP, socket.IP_TTL, 63)
|
||||||
return SockWrapper(outsock, outsock,
|
return SockWrapper(outsock, outsock,
|
||||||
@ -599,11 +599,11 @@ def runonce(handlers, mux):
|
|||||||
|
|
||||||
for s in handlers:
|
for s in handlers:
|
||||||
s.pre_select(r, w, x)
|
s.pre_select(r, w, x)
|
||||||
debug2('Waiting: %d r=%r w=%r x=%r (fullness=%d/%d)\n'
|
debug2('Waiting: %d r=%r w=%r x=%r (fullness=%d/%d)'
|
||||||
% (len(handlers), _fds(r), _fds(w), _fds(x),
|
% (len(handlers), _fds(r), _fds(w), _fds(x),
|
||||||
mux.fullness, mux.too_full))
|
mux.fullness, mux.too_full))
|
||||||
(r, w, x) = select.select(r, w, x)
|
(r, w, x) = select.select(r, w, x)
|
||||||
debug2(' Ready: %d r=%r w=%r x=%r\n'
|
debug2(' Ready: %d r=%r w=%r x=%r'
|
||||||
% (len(handlers), _fds(r), _fds(w), _fds(x)))
|
% (len(handlers), _fds(r), _fds(w), _fds(x)))
|
||||||
ready = r + w + x
|
ready = r + w + x
|
||||||
did = {}
|
did = {}
|
||||||
|
@ -45,11 +45,11 @@ def save_config(content, file_name):
|
|||||||
returncode = process.returncode
|
returncode = process.returncode
|
||||||
|
|
||||||
if returncode:
|
if returncode:
|
||||||
log('Failed updating sudoers file.\n')
|
log('Failed updating sudoers file.')
|
||||||
debug1(streamdata)
|
debug1(streamdata)
|
||||||
exit(returncode)
|
exit(returncode)
|
||||||
else:
|
else:
|
||||||
log('Success, sudoers file update.\n')
|
log('Success, sudoers file update.')
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,19 +24,19 @@ def test_log(mock_stderr, mock_stdout):
|
|||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
assert mock_stderr.mock_calls == [
|
assert mock_stderr.mock_calls == [
|
||||||
call.write('prefix: message'),
|
call.write('prefix: message\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
call.write('prefix: abc'),
|
call.write('prefix: abc\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
call.write('prefix: message 1\n'),
|
call.write('prefix: message 1\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
call.write('prefix: message 2\n'),
|
call.write('prefix: message 2\n'),
|
||||||
call.write('---> line2\n'),
|
call.write(' line2\n'),
|
||||||
call.write('---> line3\n'),
|
call.write(' line3\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
call.write('prefix: message 3\n'),
|
call.write('prefix: message 3\n'),
|
||||||
call.write('---> line2\n'),
|
call.write(' line2\n'),
|
||||||
call.write('---> line3\n'),
|
call.write(' line3\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ def test_debug1(mock_stderr, mock_stdout):
|
|||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
assert mock_stderr.mock_calls == [
|
assert mock_stderr.mock_calls == [
|
||||||
call.write('prefix: message'),
|
call.write('prefix: message\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ def test_debug2(mock_stderr, mock_stdout):
|
|||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
assert mock_stderr.mock_calls == [
|
assert mock_stderr.mock_calls == [
|
||||||
call.write('prefix: message'),
|
call.write('prefix: message\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ def test_debug3(mock_stderr, mock_stdout):
|
|||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
assert mock_stderr.mock_calls == [
|
assert mock_stderr.mock_calls == [
|
||||||
call.write('prefix: message'),
|
call.write('prefix: message\n'),
|
||||||
call.flush(),
|
call.flush(),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user