mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-07-04 08:40:30 +02:00
Compare commits
47 Commits
sshuttle-0
...
sshuttle-0
Author | SHA1 | Date | |
---|---|---|---|
e737f4b944 | |||
d9f761a8a3 | |||
bd20841782 | |||
4c1a505e37 | |||
41d1f73dc2 | |||
cbc32ff8d8 | |||
6698992f4f | |||
e2c682084c | |||
89e914e9d1 | |||
2268e76771 | |||
a8b71f6387 | |||
4bfcd7091d | |||
bd489b3319 | |||
8ab5ef283d | |||
e67208a294 | |||
7859be13c2 | |||
f313d50690 | |||
15e26d2e0e | |||
e2ec475de3 | |||
57e744dadd | |||
c13be0b817 | |||
da2c6273f6 | |||
7712c60c36 | |||
65b0390fe9 | |||
c5834a9773 | |||
e2474543fc | |||
8636378870 | |||
f5eed4c809 | |||
783d33cada | |||
94241b938b | |||
9031de1527 | |||
cfb2592346 | |||
2e8381ecda | |||
7d35690e41 | |||
141d9760b9 | |||
0658c85ffe | |||
90a55a33a2 | |||
c3399595d2 | |||
6ef9ae1796 | |||
1ca8aa5b89 | |||
a62975e0ce | |||
4fde980f46 | |||
621997b279 | |||
ca7d38dc1a | |||
a81972b2b5 | |||
a238f7636c | |||
62e1ac4b46 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*~
|
*~
|
||||||
*.8
|
*.8
|
||||||
|
/.do_built
|
||||||
|
/.do_built.dir
|
||||||
|
/.redo
|
||||||
|
3
Documentation/.gitignore
vendored
Normal file
3
Documentation/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.8
|
||||||
|
/md-to-man
|
||||||
|
/*.md.tmp
|
5
Documentation/all.do
Normal file
5
Documentation/all.do
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/bin/ls *.md |
|
||||||
|
sed 's/\.md/.8/' |
|
||||||
|
xargs redo-ifchange
|
||||||
|
|
||||||
|
redo-always
|
1
Documentation/clean.do
Normal file
1
Documentation/clean.do
Normal file
@ -0,0 +1 @@
|
|||||||
|
rm -f *~ .*~ *.8 t/*.8 md-to-man *.tmp t/*.tmp
|
2
Documentation/default.8.do
Normal file
2
Documentation/default.8.do
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
redo-ifchange md-to-man $2.md.tmp
|
||||||
|
. ./md-to-man $1 $2 $3
|
3
Documentation/default.md.tmp.do
Normal file
3
Documentation/default.md.tmp.do
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
redo-ifchange ../version/vars $2.md
|
||||||
|
. ../version/vars
|
||||||
|
sed -e "s/%VERSION%/$TAG/" -e "s/%DATE%/$DATE/" $2.md
|
8
Documentation/md-to-man.do
Normal file
8
Documentation/md-to-man.do
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
redo-ifchange md2man.py
|
||||||
|
if ./md2man.py </dev/null >/dev/null; then
|
||||||
|
echo './md2man.py $2.md.tmp'
|
||||||
|
else
|
||||||
|
echo "Warning: md2man.py missing modules; can't generate manpages." >&2
|
||||||
|
echo "Warning: try this: sudo easy_install markdown BeautifulSoup" >&2
|
||||||
|
echo 'echo Skipping: $2.1 >&2'
|
||||||
|
fi
|
278
Documentation/md2man.py
Executable file
278
Documentation/md2man.py
Executable file
@ -0,0 +1,278 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import sys, os, markdown, re
|
||||||
|
from BeautifulSoup import BeautifulSoup
|
||||||
|
|
||||||
|
def _split_lines(s):
|
||||||
|
return re.findall(r'([^\n]*\n?)', s)
|
||||||
|
|
||||||
|
|
||||||
|
class Writer:
|
||||||
|
def __init__(self):
|
||||||
|
self.started = False
|
||||||
|
self.indent = 0
|
||||||
|
self.last_wrote = '\n'
|
||||||
|
|
||||||
|
def _write(self, s):
|
||||||
|
if s:
|
||||||
|
self.last_wrote = s
|
||||||
|
sys.stdout.write(s)
|
||||||
|
|
||||||
|
def writeln(self, s):
|
||||||
|
if s:
|
||||||
|
self.linebreak()
|
||||||
|
self._write('%s\n' % s)
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
if s:
|
||||||
|
self.para()
|
||||||
|
for line in _split_lines(s):
|
||||||
|
if line.startswith('.'):
|
||||||
|
self._write('\\&' + line)
|
||||||
|
else:
|
||||||
|
self._write(line)
|
||||||
|
|
||||||
|
def linebreak(self):
|
||||||
|
if not self.last_wrote.endswith('\n'):
|
||||||
|
self._write('\n')
|
||||||
|
|
||||||
|
def para(self, bullet=None):
|
||||||
|
if not self.started:
|
||||||
|
if not bullet:
|
||||||
|
bullet = ' '
|
||||||
|
if not self.indent:
|
||||||
|
self.writeln(_macro('.PP'))
|
||||||
|
else:
|
||||||
|
assert(self.indent >= 2)
|
||||||
|
prefix = ' '*(self.indent-2) + bullet + ' '
|
||||||
|
self.writeln('.IP "%s" %d' % (prefix, self.indent))
|
||||||
|
self.started = True
|
||||||
|
|
||||||
|
def end_para(self):
|
||||||
|
self.linebreak()
|
||||||
|
self.started = False
|
||||||
|
|
||||||
|
def start_bullet(self):
|
||||||
|
self.indent += 3
|
||||||
|
self.para(bullet='\\[bu]')
|
||||||
|
|
||||||
|
def end_bullet(self):
|
||||||
|
self.indent -= 3
|
||||||
|
self.end_para()
|
||||||
|
|
||||||
|
w = Writer()
|
||||||
|
|
||||||
|
|
||||||
|
def _macro(name, *args):
|
||||||
|
if not name.startswith('.'):
|
||||||
|
raise ValueError('macro names must start with "."')
|
||||||
|
fixargs = []
|
||||||
|
for i in args:
|
||||||
|
i = str(i)
|
||||||
|
i = i.replace('\\', '')
|
||||||
|
i = i.replace('"', "'")
|
||||||
|
if (' ' in i) or not i:
|
||||||
|
i = '"%s"' % i
|
||||||
|
fixargs.append(i)
|
||||||
|
return ' '.join([name] + list(fixargs))
|
||||||
|
|
||||||
|
|
||||||
|
def macro(name, *args):
|
||||||
|
w.writeln(_macro(name, *args))
|
||||||
|
|
||||||
|
|
||||||
|
def _force_string(owner, tag):
|
||||||
|
if tag.string:
|
||||||
|
return tag.string
|
||||||
|
else:
|
||||||
|
out = ''
|
||||||
|
for i in tag:
|
||||||
|
if not (i.string or i.name in ['a', 'br']):
|
||||||
|
raise ValueError('"%s" tags must contain only strings: '
|
||||||
|
'got %r: %r' % (owner.name, tag.name, tag))
|
||||||
|
out += _force_string(owner, i)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _clean(s):
|
||||||
|
s = s.replace('\\', '\\\\')
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _bitlist(tag):
|
||||||
|
if getattr(tag, 'contents', None) == None:
|
||||||
|
for i in _split_lines(str(tag)):
|
||||||
|
yield None,_clean(i)
|
||||||
|
else:
|
||||||
|
for e in tag:
|
||||||
|
name = getattr(e, 'name', None)
|
||||||
|
if name in ['a', 'br']:
|
||||||
|
name = None # just treat as simple text
|
||||||
|
s = _force_string(tag, e)
|
||||||
|
if name:
|
||||||
|
yield name,_clean(s)
|
||||||
|
else:
|
||||||
|
for i in _split_lines(s):
|
||||||
|
yield None,_clean(i)
|
||||||
|
|
||||||
|
|
||||||
|
def _bitlist_simple(tag):
|
||||||
|
for typ,text in _bitlist(tag):
|
||||||
|
if typ and not typ in ['em', 'strong', 'code']:
|
||||||
|
raise ValueError('unexpected tag %r inside %r' % (typ, tag.name))
|
||||||
|
yield text
|
||||||
|
|
||||||
|
|
||||||
|
def _text(bitlist):
|
||||||
|
out = ''
|
||||||
|
for typ,text in bitlist:
|
||||||
|
if not typ:
|
||||||
|
out += text
|
||||||
|
elif typ == 'em':
|
||||||
|
out += '\\fI%s\\fR' % text
|
||||||
|
elif typ in ['strong', 'code']:
|
||||||
|
out += '\\fB%s\\fR' % text
|
||||||
|
else:
|
||||||
|
raise ValueError('unexpected tag %r inside %r' % (typ, tag.name))
|
||||||
|
out = out.strip()
|
||||||
|
out = re.sub(re.compile(r'^\s+', re.M), '', out)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def text(tag):
|
||||||
|
w.write(_text(_bitlist(tag)))
|
||||||
|
|
||||||
|
|
||||||
|
# This is needed because .BI (and .BR, .RB, etc) are weird little state
|
||||||
|
# machines that alternate between two fonts. So if someone says something
|
||||||
|
# like foo<b>chicken</b><b>wicken</b>dicken we have to convert that to
|
||||||
|
# .BI foo chickenwicken dicken
|
||||||
|
def _boldline(l):
|
||||||
|
out = ['']
|
||||||
|
last_bold = False
|
||||||
|
for typ,text in l:
|
||||||
|
nonzero = not not typ
|
||||||
|
if nonzero != last_bold:
|
||||||
|
last_bold = not last_bold
|
||||||
|
out.append('')
|
||||||
|
out[-1] += re.sub(r'\s+', ' ', text)
|
||||||
|
macro('.BI', *out)
|
||||||
|
|
||||||
|
|
||||||
|
def do_definition(tag):
|
||||||
|
w.end_para()
|
||||||
|
macro('.TP')
|
||||||
|
w.started = True
|
||||||
|
split = 0
|
||||||
|
pre = []
|
||||||
|
post = []
|
||||||
|
for typ,text in _bitlist(tag):
|
||||||
|
if split:
|
||||||
|
post.append((typ,text))
|
||||||
|
elif text.lstrip().startswith(': '):
|
||||||
|
split = 1
|
||||||
|
post.append((typ,text.lstrip()[2:].lstrip()))
|
||||||
|
else:
|
||||||
|
pre.append((typ,text))
|
||||||
|
_boldline(pre)
|
||||||
|
w.write(_text(post))
|
||||||
|
|
||||||
|
|
||||||
|
def do_list(tag):
|
||||||
|
for i in tag:
|
||||||
|
name = getattr(i, 'name', '').lower()
|
||||||
|
if not name and not str(i).strip():
|
||||||
|
pass
|
||||||
|
elif name != 'li':
|
||||||
|
raise ValueError('only <li> is allowed inside <ul>: got %r' % i)
|
||||||
|
else:
|
||||||
|
w.start_bullet()
|
||||||
|
for xi in i:
|
||||||
|
do(xi)
|
||||||
|
w.end_para()
|
||||||
|
w.end_bullet()
|
||||||
|
|
||||||
|
|
||||||
|
def do(tag):
|
||||||
|
name = getattr(tag, 'name', '').lower()
|
||||||
|
if not name:
|
||||||
|
text(tag)
|
||||||
|
elif name == 'h1':
|
||||||
|
macro('.SH', _force_string(tag, tag).upper())
|
||||||
|
w.started = True
|
||||||
|
elif name == 'h2':
|
||||||
|
macro('.SS', _force_string(tag, tag))
|
||||||
|
w.started = True
|
||||||
|
elif name.startswith('h') and len(name)==2:
|
||||||
|
raise ValueError('%r invalid - man page headers must be h1 or h2'
|
||||||
|
% name)
|
||||||
|
elif name == 'pre':
|
||||||
|
t = _force_string(tag.code, tag.code)
|
||||||
|
if t.strip():
|
||||||
|
macro('.RS', '+4n')
|
||||||
|
macro('.nf')
|
||||||
|
w.write(_clean(t).rstrip())
|
||||||
|
macro('.fi')
|
||||||
|
macro('.RE')
|
||||||
|
w.end_para()
|
||||||
|
elif name == 'p' or name == 'br':
|
||||||
|
g = re.match(re.compile(r'([^\n]*)\n +: +(.*)', re.S), str(tag))
|
||||||
|
if g:
|
||||||
|
# it's a definition list (which some versions of python-markdown
|
||||||
|
# don't support, including the one in Debian-lenny, so we can't
|
||||||
|
# enable that markdown extension). Fake it up.
|
||||||
|
do_definition(tag)
|
||||||
|
else:
|
||||||
|
text(tag)
|
||||||
|
w.end_para()
|
||||||
|
elif name == 'ul':
|
||||||
|
do_list(tag)
|
||||||
|
else:
|
||||||
|
raise ValueError('non-man-compatible html tag %r' % name)
|
||||||
|
|
||||||
|
|
||||||
|
PROD='Untitled'
|
||||||
|
VENDOR='Vendor Name'
|
||||||
|
SECTION='9'
|
||||||
|
GROUPNAME='User Commands'
|
||||||
|
DATE=''
|
||||||
|
AUTHOR=''
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
for n in sys.argv[1:]:
|
||||||
|
lines += open(n).read().decode('utf8').split('\n')
|
||||||
|
else:
|
||||||
|
lines += sys.stdin.read().decode('utf8').split('\n')
|
||||||
|
|
||||||
|
# parse pandoc-style document headers (not part of markdown)
|
||||||
|
g = re.match(r'^%\s+(.*?)\((.*?)\)\s+(.*)$', lines[0])
|
||||||
|
if g:
|
||||||
|
PROD = g.group(1)
|
||||||
|
SECTION = g.group(2)
|
||||||
|
VENDOR = g.group(3)
|
||||||
|
lines.pop(0)
|
||||||
|
g = re.match(r'^%\s+(.*?)$', lines[0])
|
||||||
|
if g:
|
||||||
|
AUTHOR = g.group(1)
|
||||||
|
lines.pop(0)
|
||||||
|
g = re.match(r'^%\s+(.*?)$', lines[0])
|
||||||
|
if g:
|
||||||
|
DATE = g.group(1)
|
||||||
|
lines.pop(0)
|
||||||
|
g = re.match(r'^%\s+(.*?)$', lines[0])
|
||||||
|
if g:
|
||||||
|
GROUPNAME = g.group(1)
|
||||||
|
lines.pop(0)
|
||||||
|
|
||||||
|
inp = '\n'.join(lines)
|
||||||
|
if AUTHOR:
|
||||||
|
inp += ('\n# AUTHOR\n\n%s\n' % AUTHOR).replace('<', '\\<')
|
||||||
|
|
||||||
|
html = markdown.markdown(inp)
|
||||||
|
soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)
|
||||||
|
|
||||||
|
macro('.TH', PROD.upper(), SECTION, DATE, VENDOR, GROUPNAME)
|
||||||
|
macro('.ad', 'l') # left justified
|
||||||
|
macro('.nh') # disable hyphenation
|
||||||
|
for e in soup:
|
||||||
|
do(e)
|
@ -1,6 +1,6 @@
|
|||||||
% sshuttle(8) Sshuttle 0.46
|
% sshuttle(8) Sshuttle %VERSION%
|
||||||
% Avery Pennarun <apenwarr@gmail.com>
|
% Avery Pennarun <apenwarr@gmail.com>
|
||||||
% 2011-01-25
|
% %DATE%
|
||||||
|
|
||||||
# NAME
|
# NAME
|
||||||
|
|
||||||
@ -253,6 +253,17 @@ between the two separate streams, so a tcp-based tunnel is
|
|||||||
fine.
|
fine.
|
||||||
|
|
||||||
|
|
||||||
|
# BUGS
|
||||||
|
|
||||||
|
On MacOS 10.6 (at least up to 10.6.6), your network will
|
||||||
|
stop responding about 10 minutes after the first time you
|
||||||
|
start sshuttle, because of a MacOS kernel bug relating to
|
||||||
|
arp and the net.inet.ip.scopedroute sysctl. To fix it,
|
||||||
|
just switch your wireless off and on. Sshuttle makes the
|
||||||
|
kernel setting it changes permanent, so this won't happen
|
||||||
|
again, even after a reboot.
|
||||||
|
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
`ssh`(1), `python`(1)
|
`ssh`(1), `python`(1)
|
21
Makefile
21
Makefile
@ -1,19 +1,10 @@
|
|||||||
PANDOC:=$(shell \
|
all:
|
||||||
if pandoc </dev/null 2>/dev/null; then \
|
|
||||||
echo pandoc; \
|
|
||||||
else \
|
|
||||||
echo "Warning: pandoc not installed; can't generate manpages." >&2; \
|
|
||||||
echo '@echo Skipping: pandoc'; \
|
|
||||||
fi)
|
|
||||||
|
|
||||||
default: all
|
Makefile:
|
||||||
|
@
|
||||||
|
|
||||||
all: sshuttle.8
|
%: FORCE
|
||||||
|
+./do $@
|
||||||
|
|
||||||
sshuttle.8: sshuttle.md
|
.PHONY: FORCE
|
||||||
|
|
||||||
%.8: %.md
|
|
||||||
$(PANDOC) -s -r markdown -w man -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc
|
|
||||||
|
25
README.md
25
README.md
@ -1,3 +1,14 @@
|
|||||||
|
|
||||||
|
WARNING:
|
||||||
|
On MacOS 10.6 (at least up to 10.6.6), your network will
|
||||||
|
stop responding about 10 minutes after the first time you
|
||||||
|
start sshuttle, because of a MacOS kernel bug relating to
|
||||||
|
arp and the net.inet.ip.scopedroute sysctl. To fix it,
|
||||||
|
just switch your wireless off and on. Sshuttle makes the
|
||||||
|
kernel setting it changes permanent, so this won't happen
|
||||||
|
again, even after a reboot.
|
||||||
|
|
||||||
|
|
||||||
sshuttle: where transparent proxy meets VPN meets ssh
|
sshuttle: where transparent proxy meets VPN meets ssh
|
||||||
=====================================================
|
=====================================================
|
||||||
|
|
||||||
@ -52,7 +63,19 @@ This is how you use it:
|
|||||||
on your client machine. You'll need root or sudo
|
on your client machine. You'll need root or sudo
|
||||||
access, and python needs to be installed.
|
access, and python needs to be installed.
|
||||||
|
|
||||||
- <tt>./sshuttle -r username@sshserver 0.0.0.0/0 -vv</tt>
|
- The most basic use of sshuttle looks like:
|
||||||
|
<tt>./sshuttle -r username@sshserver 0.0.0.0/0 -vv</tt>
|
||||||
|
|
||||||
|
- There is a shortcut for 0.0.0.0/0 for those that value
|
||||||
|
their wrists
|
||||||
|
<tt>./sshuttle -r username@sshserver 0/0 -vv</tt>
|
||||||
|
|
||||||
|
- If you would also like your DNS queries to be proxied
|
||||||
|
through the DNS server of the server you are connect to:
|
||||||
|
<tt>./sshuttle --dns -vvr username@sshserver 0/0</tt>
|
||||||
|
|
||||||
|
The above is probably what you want to use to prevent
|
||||||
|
local network attacks such as Firesheep and friends.
|
||||||
|
|
||||||
(You may be prompted for one or more passwords; first, the
|
(You may be prompted for one or more passwords; first, the
|
||||||
local password to become root using either sudo or su, and
|
local password to become root using either sudo or su, and
|
||||||
|
11
all.do
Normal file
11
all.do
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
exec >&2
|
||||||
|
UI=
|
||||||
|
[ "$(uname)" = "Darwin" ] && UI=ui-macos/all
|
||||||
|
redo-ifchange Documentation/all version/all $UI
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "What now?"
|
||||||
|
[ -z "$UI" ] || echo "- Try the MacOS GUI: open ui-macos/Sshuttle*.app"
|
||||||
|
echo "- Run sshuttle: ./sshuttle --dns -r HOSTNAME 0/0"
|
||||||
|
echo "- Read the README: less README.md"
|
||||||
|
echo "- Read the man page: less Documentation/sshuttle.md"
|
2
clean.do
Normal file
2
clean.do
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
redo ui-macos/clean Documentation/clean
|
||||||
|
rm -f *~ */*~ .*~ */.*~ *.8 *.tmp */*.tmp *.pyc */*.pyc
|
125
client.py
125
client.py
@ -102,7 +102,7 @@ class FirewallClient:
|
|||||||
self.subnets_include = subnets_include
|
self.subnets_include = subnets_include
|
||||||
self.subnets_exclude = subnets_exclude
|
self.subnets_exclude = subnets_exclude
|
||||||
self.dnsport = dnsport
|
self.dnsport = dnsport
|
||||||
argvbase = ([sys.argv[0]] +
|
argvbase = ([sys.argv[1], sys.argv[0], sys.argv[1]] +
|
||||||
['-v'] * (helpers.verbose or 0) +
|
['-v'] * (helpers.verbose or 0) +
|
||||||
['--firewall', str(port), str(dnsport)])
|
['--firewall', str(port), str(dnsport)])
|
||||||
if ssyslog._p:
|
if ssyslog._p:
|
||||||
@ -171,10 +171,71 @@ class FirewallClient:
|
|||||||
def done(self):
|
def done(self):
|
||||||
self.pfile.close()
|
self.pfile.close()
|
||||||
rv = self.p.wait()
|
rv = self.p.wait()
|
||||||
if rv:
|
if rv == EXITCODE_NEEDS_REBOOT:
|
||||||
|
raise FatalNeedsReboot()
|
||||||
|
elif rv:
|
||||||
raise Fatal('cleanup: %r returned %d' % (self.argv, rv))
|
raise Fatal('cleanup: %r returned %d' % (self.argv, rv))
|
||||||
|
|
||||||
|
|
||||||
|
def onaccept(listener, mux, handlers):
|
||||||
|
global _extra_fd
|
||||||
|
try:
|
||||||
|
sock,srcip = listener.accept()
|
||||||
|
except socket.error, e:
|
||||||
|
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
||||||
|
debug1('Rejected incoming connection: too many open files!\n')
|
||||||
|
# free up an fd so we can eat the connection
|
||||||
|
os.close(_extra_fd)
|
||||||
|
try:
|
||||||
|
sock,srcip = listener.accept()
|
||||||
|
sock.close()
|
||||||
|
finally:
|
||||||
|
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
dstip = original_dst(sock)
|
||||||
|
debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1],
|
||||||
|
dstip[0],dstip[1]))
|
||||||
|
if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]):
|
||||||
|
debug1("-- ignored: that's my address!\n")
|
||||||
|
sock.close()
|
||||||
|
return
|
||||||
|
chan = mux.next_channel()
|
||||||
|
if not chan:
|
||||||
|
log('warning: too many open channels. Discarded connection.\n')
|
||||||
|
sock.close()
|
||||||
|
return
|
||||||
|
mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip)
|
||||||
|
outwrap = MuxWrapper(mux, chan)
|
||||||
|
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
|
||||||
|
|
||||||
|
|
||||||
|
dnsreqs = {}
|
||||||
|
def dns_done(chan, data):
|
||||||
|
peer,sock,timeout = dnsreqs.get(chan) or (None,None,None)
|
||||||
|
debug3('dns_done: channel=%r peer=%r\n' % (chan, peer))
|
||||||
|
if peer:
|
||||||
|
del dnsreqs[chan]
|
||||||
|
debug3('doing sendto %r\n' % (peer,))
|
||||||
|
sock.sendto(data, peer)
|
||||||
|
|
||||||
|
|
||||||
|
def ondns(listener, mux, handlers):
|
||||||
|
pkt,peer = listener.recvfrom(4096)
|
||||||
|
now = time.time()
|
||||||
|
if pkt:
|
||||||
|
debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt)))
|
||||||
|
chan = mux.next_channel()
|
||||||
|
dnsreqs[chan] = peer,listener,now+30
|
||||||
|
mux.send(chan, ssnet.CMD_DNS_REQ, pkt)
|
||||||
|
mux.channels[chan] = lambda cmd,data: dns_done(chan,data)
|
||||||
|
for chan,(peer,sock,timeout) in dnsreqs.items():
|
||||||
|
if timeout < now:
|
||||||
|
del dnsreqs[chan]
|
||||||
|
debug3('Remaining DNS requests: %d\n' % len(dnsreqs))
|
||||||
|
|
||||||
|
|
||||||
def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
||||||
dnslistener, seed_hosts, auto_nets,
|
dnslistener, seed_hosts, auto_nets,
|
||||||
syslog, daemon):
|
syslog, daemon):
|
||||||
@ -198,7 +259,14 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
|||||||
handlers.append(mux)
|
handlers.append(mux)
|
||||||
|
|
||||||
expected = 'SSHUTTLE0001'
|
expected = 'SSHUTTLE0001'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
v = 'x'
|
||||||
|
while v and v != '\0':
|
||||||
|
v = serversock.recv(1)
|
||||||
|
v = 'x'
|
||||||
|
while v and v != '\0':
|
||||||
|
v = serversock.recv(1)
|
||||||
initstring = serversock.recv(len(expected))
|
initstring = serversock.recv(len(expected))
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
if e.args[0] == errno.ECONNRESET:
|
if e.args[0] == errno.ECONNRESET:
|
||||||
@ -248,59 +316,10 @@ def _main(listener, fw, ssh_cmd, remotename, python, latency_control,
|
|||||||
fw.sethostip(name, ip)
|
fw.sethostip(name, ip)
|
||||||
mux.got_host_list = onhostlist
|
mux.got_host_list = onhostlist
|
||||||
|
|
||||||
def onaccept():
|
handlers.append(Handler([listener], lambda: onaccept(listener, mux, handlers)))
|
||||||
global _extra_fd
|
|
||||||
try:
|
|
||||||
sock,srcip = listener.accept()
|
|
||||||
except socket.error, e:
|
|
||||||
if e.args[0] in [errno.EMFILE, errno.ENFILE]:
|
|
||||||
debug1('Rejected incoming connection: too many open files!\n')
|
|
||||||
# free up an fd so we can eat the connection
|
|
||||||
os.close(_extra_fd)
|
|
||||||
try:
|
|
||||||
sock,srcip = listener.accept()
|
|
||||||
sock.close()
|
|
||||||
finally:
|
|
||||||
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
dstip = original_dst(sock)
|
|
||||||
debug1('Accept: %s:%r -> %s:%r.\n' % (srcip[0],srcip[1],
|
|
||||||
dstip[0],dstip[1]))
|
|
||||||
if dstip[1] == listener.getsockname()[1] and islocal(dstip[0]):
|
|
||||||
debug1("-- ignored: that's my address!\n")
|
|
||||||
sock.close()
|
|
||||||
return
|
|
||||||
chan = mux.next_channel()
|
|
||||||
mux.send(chan, ssnet.CMD_CONNECT, '%s,%s' % dstip)
|
|
||||||
outwrap = MuxWrapper(mux, chan)
|
|
||||||
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
|
|
||||||
handlers.append(Handler([listener], onaccept))
|
|
||||||
|
|
||||||
dnsreqs = {}
|
|
||||||
def dns_done(chan, data):
|
|
||||||
peer,timeout = dnsreqs.get(chan) or (None,None)
|
|
||||||
debug3('dns_done: channel=%r peer=%r\n' % (chan, peer))
|
|
||||||
if peer:
|
|
||||||
del dnsreqs[chan]
|
|
||||||
debug3('doing sendto %r\n' % (peer,))
|
|
||||||
dnslistener.sendto(data, peer)
|
|
||||||
def ondns():
|
|
||||||
pkt,peer = dnslistener.recvfrom(4096)
|
|
||||||
now = time.time()
|
|
||||||
if pkt:
|
|
||||||
debug1('DNS request from %r: %d bytes\n' % (peer, len(pkt)))
|
|
||||||
chan = mux.next_channel()
|
|
||||||
dnsreqs[chan] = peer,now+30
|
|
||||||
mux.send(chan, ssnet.CMD_DNS_REQ, pkt)
|
|
||||||
mux.channels[chan] = lambda cmd,data: dns_done(chan,data)
|
|
||||||
for chan,(peer,timeout) in dnsreqs.items():
|
|
||||||
if timeout < now:
|
|
||||||
del dnsreqs[chan]
|
|
||||||
debug3('Remaining DNS requests: %d\n' % len(dnsreqs))
|
|
||||||
if dnslistener:
|
if dnslistener:
|
||||||
handlers.append(Handler([dnslistener], ondns))
|
handlers.append(Handler([dnslistener], lambda: ondns(dnslistener, mux, handlers)))
|
||||||
|
|
||||||
if seed_hosts != None:
|
if seed_hosts != None:
|
||||||
debug1('seed_hosts: %r\n' % seed_hosts)
|
debug1('seed_hosts: %r\n' % seed_hosts)
|
||||||
|
7
default.8.do
Normal file
7
default.8.do
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
exec >&2
|
||||||
|
if pandoc </dev/null 2>/dev/null; then
|
||||||
|
pandoc -s -r markdown -w man -o $3 $2.md
|
||||||
|
else
|
||||||
|
echo "Warning: pandoc not installed; can't generate manpages."
|
||||||
|
redo-always
|
||||||
|
fi
|
175
do
Executable file
175
do
Executable file
@ -0,0 +1,175 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# A minimal alternative to djb redo that doesn't support incremental builds.
|
||||||
|
# For the full version, visit http://github.com/apenwarr/redo
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source file and hereby places it in
|
||||||
|
# the public domain. (2010 12 14)
|
||||||
|
#
|
||||||
|
|
||||||
|
# By default, no output coloring.
|
||||||
|
green=""
|
||||||
|
bold=""
|
||||||
|
plain=""
|
||||||
|
|
||||||
|
if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
|
||||||
|
green="$(printf '\033[32m')"
|
||||||
|
bold="$(printf '\033[1m')"
|
||||||
|
plain="$(printf '\033[m')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_dirsplit()
|
||||||
|
{
|
||||||
|
base=${1##*/}
|
||||||
|
dir=${1%$base}
|
||||||
|
}
|
||||||
|
|
||||||
|
dirname()
|
||||||
|
(
|
||||||
|
_dirsplit "$1"
|
||||||
|
dir=${dir%/}
|
||||||
|
echo "${dir:-.}"
|
||||||
|
)
|
||||||
|
|
||||||
|
_dirsplit "$0"
|
||||||
|
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
|
||||||
|
|
||||||
|
DO_TOP=
|
||||||
|
if [ -z "$DO_BUILT" ]; then
|
||||||
|
DO_TOP=1
|
||||||
|
[ -n "$*" ] || set all # only toplevel redo has a default target
|
||||||
|
export DO_BUILT=$PWD/.do_built
|
||||||
|
: >>"$DO_BUILT"
|
||||||
|
echo "Removing previously built files..." >&2
|
||||||
|
sort -u "$DO_BUILT" | tee "$DO_BUILT.new" |
|
||||||
|
while read f; do printf "%s\0%s.did\0" "$f" "$f"; done |
|
||||||
|
xargs -0 rm -f 2>/dev/null
|
||||||
|
mv "$DO_BUILT.new" "$DO_BUILT"
|
||||||
|
DO_PATH=$DO_BUILT.dir
|
||||||
|
export PATH=$DO_PATH:$PATH
|
||||||
|
rm -rf "$DO_PATH"
|
||||||
|
mkdir "$DO_PATH"
|
||||||
|
for d in redo redo-ifchange; do
|
||||||
|
ln -s "$REDO" "$DO_PATH/$d";
|
||||||
|
done
|
||||||
|
[ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true
|
||||||
|
for d in redo-ifcreate redo-stamp redo-always; do
|
||||||
|
ln -s $TRUE "$DO_PATH/$d";
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
_find_dofile_pwd()
|
||||||
|
{
|
||||||
|
dofile=default.$1.do
|
||||||
|
while :; do
|
||||||
|
dofile=default.${dofile#default.*.}
|
||||||
|
[ -e "$dofile" -o "$dofile" = default.do ] && break
|
||||||
|
done
|
||||||
|
ext=${dofile#default}
|
||||||
|
ext=${ext%.do}
|
||||||
|
base=${1%$ext}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_find_dofile()
|
||||||
|
{
|
||||||
|
local prefix=
|
||||||
|
while :; do
|
||||||
|
_find_dofile_pwd "$1"
|
||||||
|
[ -e "$dofile" ] && break
|
||||||
|
[ "$PWD" = "/" ] && break
|
||||||
|
target=${PWD##*/}/$target
|
||||||
|
tmp=${PWD##*/}/$tmp
|
||||||
|
prefix=${PWD##*/}/$prefix
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
base=$prefix$base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_run_dofile()
|
||||||
|
{
|
||||||
|
export DO_DEPTH="$DO_DEPTH "
|
||||||
|
export REDO_TARGET=$PWD/$target
|
||||||
|
local line1
|
||||||
|
set -e
|
||||||
|
read line1 <"$PWD/$dofile"
|
||||||
|
cmd=${line1#"#!/"}
|
||||||
|
if [ "$cmd" != "$line1" ]; then
|
||||||
|
/$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
|
||||||
|
else
|
||||||
|
:; . "$PWD/$dofile" >"$tmp.tmp2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_do()
|
||||||
|
{
|
||||||
|
local dir=$1 target=$2 tmp=$3
|
||||||
|
if [ ! -e "$target" ] || [ -d "$target" -a ! -e "$target.did" ]; then
|
||||||
|
printf '%sdo %s%s%s%s\n' \
|
||||||
|
"$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
|
||||||
|
echo "$PWD/$target" >>"$DO_BUILT"
|
||||||
|
dofile=$target.do
|
||||||
|
base=$target
|
||||||
|
ext=
|
||||||
|
[ -e "$target.do" ] || _find_dofile "$target"
|
||||||
|
if [ ! -e "$dofile" ]; then
|
||||||
|
echo "do: $target: no .do file" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
[ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] ||
|
||||||
|
: >>"$target.did"
|
||||||
|
( _run_dofile "$target" "$base" "$tmp.tmp" )
|
||||||
|
rv=$?
|
||||||
|
if [ $rv != 0 ]; then
|
||||||
|
printf "do: %s%s\n" "$DO_DEPTH" \
|
||||||
|
"$dir$target: got exit code $rv" >&2
|
||||||
|
rm -f "$tmp.tmp" "$tmp.tmp2"
|
||||||
|
return $rv
|
||||||
|
fi
|
||||||
|
mv "$tmp.tmp" "$target" 2>/dev/null ||
|
||||||
|
! test -s "$tmp.tmp2" ||
|
||||||
|
mv "$tmp.tmp2" "$target" 2>/dev/null
|
||||||
|
rm -f "$tmp.tmp2"
|
||||||
|
else
|
||||||
|
echo "do $DO_DEPTH$target exists." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Make corrections for directories that don't actually exist yet.
|
||||||
|
_dir_shovel()
|
||||||
|
{
|
||||||
|
local dir base
|
||||||
|
xdir=$1 xbase=$2 xbasetmp=$2
|
||||||
|
while [ ! -d "$xdir" -a -n "$xdir" ]; do
|
||||||
|
_dirsplit "${xdir%/}"
|
||||||
|
xbasetmp=${base}__$xbase
|
||||||
|
xdir=$dir xbase=$base/$xbase
|
||||||
|
echo "xbasetmp='$xbasetmp'" >&2
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
redo()
|
||||||
|
{
|
||||||
|
for i in "$@"; do
|
||||||
|
_dirsplit "$i"
|
||||||
|
_dir_shovel "$dir" "$base"
|
||||||
|
dir=$xdir base=$xbase basetmp=$xbasetmp
|
||||||
|
( cd "$dir" && _do "$dir" "$base" "$basetmp" ) || return 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
set -e
|
||||||
|
redo "$@"
|
||||||
|
|
||||||
|
if [ -n "$DO_TOP" ]; then
|
||||||
|
echo "Removing stamp files..." >&2
|
||||||
|
[ ! -e "$DO_BUILT" ] ||
|
||||||
|
while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
|
||||||
|
xargs -0 rm -f 2>/dev/null
|
||||||
|
fi
|
145
firewall.py
145
firewall.py
@ -1,4 +1,4 @@
|
|||||||
import re, errno, socket, select, struct
|
import re, errno, socket, select, signal, struct
|
||||||
import compat.ssubprocess as ssubprocess
|
import compat.ssubprocess as ssubprocess
|
||||||
import helpers, ssyslog
|
import helpers, ssyslog
|
||||||
from helpers import *
|
from helpers import *
|
||||||
@ -6,6 +6,27 @@ from helpers import *
|
|||||||
# python doesn't have a definition for this
|
# python doesn't have a definition for this
|
||||||
IPPROTO_DIVERT = 254
|
IPPROTO_DIVERT = 254
|
||||||
|
|
||||||
|
# return values from sysctl_set
|
||||||
|
SUCCESS = 0
|
||||||
|
SAME = 1
|
||||||
|
FAILED = -1
|
||||||
|
NONEXIST = -2
|
||||||
|
|
||||||
|
|
||||||
|
def nonfatal(func, *args):
|
||||||
|
try:
|
||||||
|
func(*args)
|
||||||
|
except Fatal, e:
|
||||||
|
log('error: %s\n' % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _call(argv):
|
||||||
|
debug1('>> %s\n' % ' '.join(argv))
|
||||||
|
rv = ssubprocess.call(argv)
|
||||||
|
if rv:
|
||||||
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
def ipt_chain_exists(name):
|
def ipt_chain_exists(name):
|
||||||
argv = ['iptables', '-t', 'nat', '-nL']
|
argv = ['iptables', '-t', 'nat', '-nL']
|
||||||
@ -20,10 +41,7 @@ def ipt_chain_exists(name):
|
|||||||
|
|
||||||
def ipt(*args):
|
def ipt(*args):
|
||||||
argv = ['iptables', '-t', 'nat'] + list(args)
|
argv = ['iptables', '-t', 'nat'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
_call(argv)
|
||||||
rv = ssubprocess.call(argv)
|
|
||||||
if rv:
|
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
|
||||||
|
|
||||||
|
|
||||||
_no_ttl_module = False
|
_no_ttl_module = False
|
||||||
@ -57,9 +75,9 @@ def do_iptables(port, dnsport, subnets):
|
|||||||
|
|
||||||
# basic cleanup/setup of chains
|
# basic cleanup/setup of chains
|
||||||
if ipt_chain_exists(chain):
|
if ipt_chain_exists(chain):
|
||||||
ipt('-D', 'OUTPUT', '-j', chain)
|
nonfatal(ipt, '-D', 'OUTPUT', '-j', chain)
|
||||||
ipt('-D', 'PREROUTING', '-j', chain)
|
nonfatal(ipt, '-D', 'PREROUTING', '-j', chain)
|
||||||
ipt('-F', chain)
|
nonfatal(ipt, '-F', chain)
|
||||||
ipt('-X', chain)
|
ipt('-X', chain)
|
||||||
|
|
||||||
if subnets or dnsport:
|
if subnets or dnsport:
|
||||||
@ -128,14 +146,50 @@ def _fill_oldctls(prefix):
|
|||||||
raise Fatal('%r returned no data' % (argv,))
|
raise Fatal('%r returned no data' % (argv,))
|
||||||
|
|
||||||
|
|
||||||
|
KERNEL_FLAGS_PATH = '/Library/Preferences/SystemConfiguration/com.apple.Boot'
|
||||||
|
KERNEL_FLAGS_NAME = 'Kernel Flags'
|
||||||
|
def _defaults_read_kernel_flags():
|
||||||
|
argv = ['defaults', 'read', KERNEL_FLAGS_PATH, KERNEL_FLAGS_NAME]
|
||||||
|
debug1('>> %s\n' % ' '.join(argv))
|
||||||
|
p = ssubprocess.Popen(argv, stdout = ssubprocess.PIPE)
|
||||||
|
flagstr = p.stdout.read().strip()
|
||||||
|
rv = p.wait()
|
||||||
|
if rv:
|
||||||
|
raise Fatal('%r returned %d' % (argv, rv))
|
||||||
|
flags = flagstr and flagstr.split(' ') or []
|
||||||
|
return flags
|
||||||
|
|
||||||
|
|
||||||
|
def _defaults_write_kernel_flags(flags):
|
||||||
|
flagstr = ' '.join(flags)
|
||||||
|
argv = ['defaults', 'write', KERNEL_FLAGS_PATH, KERNEL_FLAGS_NAME,
|
||||||
|
flagstr]
|
||||||
|
_call(argv)
|
||||||
|
argv = ['plutil', '-convert', 'xml1', KERNEL_FLAGS_PATH + '.plist']
|
||||||
|
_call(argv)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def defaults_write_kernel_flag(name, val):
|
||||||
|
flags = _defaults_read_kernel_flags()
|
||||||
|
found = 0
|
||||||
|
for i in range(len(flags)):
|
||||||
|
if flags[i].startswith('%s=' % name):
|
||||||
|
found += 1
|
||||||
|
flags[i] = '%s=%s' % (name, val)
|
||||||
|
if not found:
|
||||||
|
flags.insert(0, '%s=%s' % (name, val))
|
||||||
|
_defaults_write_kernel_flags(flags)
|
||||||
|
|
||||||
|
|
||||||
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\n' % ' '.join(argv))
|
||||||
rv = ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
|
return ssubprocess.call(argv, stdout = open('/dev/null', 'w'))
|
||||||
|
|
||||||
|
|
||||||
_changedctls = []
|
_changedctls = []
|
||||||
def sysctl_set(name, val):
|
def sysctl_set(name, val, permanent=False):
|
||||||
PREFIX = 'net.inet.ip'
|
PREFIX = 'net.inet.ip'
|
||||||
assert(name.startswith(PREFIX + '.'))
|
assert(name.startswith(PREFIX + '.'))
|
||||||
val = str(val)
|
val = str(val)
|
||||||
@ -143,11 +197,24 @@ def sysctl_set(name, val):
|
|||||||
_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\n' % name)
|
||||||
return
|
return NONEXIST
|
||||||
oldval = _oldctls[name]
|
oldval = _oldctls[name]
|
||||||
if val != oldval:
|
if val == oldval:
|
||||||
|
return SAME
|
||||||
|
|
||||||
|
rv = _sysctl_set(name, val)
|
||||||
|
if rv != 0:
|
||||||
|
return FAILED
|
||||||
|
if permanent:
|
||||||
|
debug1('>> ...saving permanently in /etc/sysctl.conf\n')
|
||||||
|
f = open('/etc/sysctl.conf', 'a')
|
||||||
|
f.write('\n'
|
||||||
|
'# Added by sshuttle\n'
|
||||||
|
'%s=%s\n' % (name, val))
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
_changedctls.append(name)
|
_changedctls.append(name)
|
||||||
return _sysctl_set(name, val)
|
return SUCCESS
|
||||||
|
|
||||||
|
|
||||||
def _udp_unpack(p):
|
def _udp_unpack(p):
|
||||||
@ -185,10 +252,7 @@ def _handle_diversion(divertsock, dnsport):
|
|||||||
|
|
||||||
def ipfw(*args):
|
def ipfw(*args):
|
||||||
argv = ['ipfw', '-q'] + list(args)
|
argv = ['ipfw', '-q'] + list(args)
|
||||||
debug1('>> %s\n' % ' '.join(argv))
|
_call(argv)
|
||||||
rv = ssubprocess.call(argv)
|
|
||||||
if rv:
|
|
||||||
raise Fatal('%r returned %d' % (argv, rv))
|
|
||||||
|
|
||||||
|
|
||||||
def do_ipfw(port, dnsport, subnets):
|
def do_ipfw(port, dnsport, subnets):
|
||||||
@ -206,7 +270,39 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
|
|
||||||
if subnets or dnsport:
|
if subnets or dnsport:
|
||||||
sysctl_set('net.inet.ip.fw.enable', 1)
|
sysctl_set('net.inet.ip.fw.enable', 1)
|
||||||
sysctl_set('net.inet.ip.scopedroute', 0)
|
|
||||||
|
# This seems to be needed on MacOS 10.6 and 10.7. For more
|
||||||
|
# information, see:
|
||||||
|
# http://groups.google.com/group/sshuttle/browse_thread/thread/bc32562e17987b25/6d3aa2bb30a1edab
|
||||||
|
# and
|
||||||
|
# http://serverfault.com/questions/138622/transparent-proxying-leaves-sockets-with-syn-rcvd-in-macos-x-10-6-snow-leopard
|
||||||
|
changeflag = sysctl_set('net.inet.ip.scopedroute', 0, permanent=True)
|
||||||
|
if changeflag == SUCCESS:
|
||||||
|
log("\n"
|
||||||
|
" WARNING: ONE-TIME NETWORK DISRUPTION:\n"
|
||||||
|
" =====================================\n"
|
||||||
|
"sshuttle has changed a MacOS kernel setting to work around\n"
|
||||||
|
"a bug in MacOS 10.6. This will cause your network to drop\n"
|
||||||
|
"within 5-10 minutes unless you restart your network\n"
|
||||||
|
"interface (change wireless networks or unplug/plug the\n"
|
||||||
|
"ethernet port) NOW, then restart sshuttle. The fix is\n"
|
||||||
|
"permanent; you only have to do this once.\n\n")
|
||||||
|
sys.exit(1)
|
||||||
|
elif changeflag == FAILED:
|
||||||
|
# On MacOS 10.7, the scopedroute sysctl became read-only, so
|
||||||
|
# we have to fix it using a kernel boot parameter instead,
|
||||||
|
# which requires rebooting. For more, see:
|
||||||
|
# http://groups.google.com/group/sshuttle/browse_thread/thread/a42505ca33e1de80/e5e8f3e5a92d25f7
|
||||||
|
log('Updating kernel boot flags.\n')
|
||||||
|
defaults_write_kernel_flag('net.inet.ip.scopedroute', 0)
|
||||||
|
log("\n"
|
||||||
|
" YOU MUST REBOOT TO USE SSHUTTLE\n"
|
||||||
|
" ===============================\n"
|
||||||
|
"sshuttle has changed a MacOS kernel boot-time setting\n"
|
||||||
|
"to work around a bug in MacOS 10.7 Lion. You will need\n"
|
||||||
|
"to reboot before it takes effect. You only have to\n"
|
||||||
|
"do this once.\n\n")
|
||||||
|
sys.exit(EXITCODE_NEEDS_REBOOT)
|
||||||
|
|
||||||
ipfw('add', sport, 'check-state', 'ip',
|
ipfw('add', sport, 'check-state', 'ip',
|
||||||
'from', 'any', 'to', 'any')
|
'from', 'any', 'to', 'any')
|
||||||
@ -216,11 +312,11 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
for swidth,sexclude,snet in sorted(subnets, reverse=True):
|
for swidth,sexclude,snet in sorted(subnets, reverse=True):
|
||||||
if sexclude:
|
if sexclude:
|
||||||
ipfw('add', sport, 'skipto', xsport,
|
ipfw('add', sport, 'skipto', xsport,
|
||||||
'log', 'tcp',
|
'tcp',
|
||||||
'from', 'any', 'to', '%s/%s' % (snet,swidth))
|
'from', 'any', 'to', '%s/%s' % (snet,swidth))
|
||||||
else:
|
else:
|
||||||
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
|
ipfw('add', sport, 'fwd', '127.0.0.1,%d' % port,
|
||||||
'log', 'tcp',
|
'tcp',
|
||||||
'from', 'any', 'to', '%s/%s' % (snet,swidth),
|
'from', 'any', 'to', '%s/%s' % (snet,swidth),
|
||||||
'not', 'ipttl', '42', 'keep-state', 'setup')
|
'not', 'ipttl', '42', 'keep-state', 'setup')
|
||||||
|
|
||||||
@ -262,12 +358,12 @@ def do_ipfw(port, dnsport, subnets):
|
|||||||
for ip in nslist:
|
for ip in nslist:
|
||||||
# relabel and then catch outgoing DNS requests
|
# relabel and then catch outgoing DNS requests
|
||||||
ipfw('add', sport, 'divert', sport,
|
ipfw('add', sport, 'divert', sport,
|
||||||
'log', 'udp',
|
'udp',
|
||||||
'from', 'any', 'to', '%s/32' % ip, '53',
|
'from', 'any', 'to', '%s/32' % ip, '53',
|
||||||
'not', 'ipttl', '42')
|
'not', 'ipttl', '42')
|
||||||
# relabel DNS responses
|
# relabel DNS responses
|
||||||
ipfw('add', sport, 'divert', sport,
|
ipfw('add', sport, 'divert', sport,
|
||||||
'log', 'udp',
|
'udp',
|
||||||
'from', 'any', str(dnsport), 'to', 'any',
|
'from', 'any', str(dnsport), 'to', 'any',
|
||||||
'not', 'ipttl', '42')
|
'not', 'ipttl', '42')
|
||||||
|
|
||||||
@ -371,6 +467,11 @@ def main(port, dnsport, syslog):
|
|||||||
sys.stdout.write('READY\n')
|
sys.stdout.write('READY\n')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
# don't disappear if our controlling terminal or stdout/stderr
|
||||||
|
# disappears; we still have to clean up.
|
||||||
|
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
||||||
|
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
|
||||||
|
|
||||||
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
|
# ctrl-c shouldn't be passed along to me. When the main sshuttle dies,
|
||||||
# I'll die automatically.
|
# I'll die automatically.
|
||||||
os.setsid()
|
os.setsid()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import sys, os, socket
|
import sys, os, socket, errno
|
||||||
|
|
||||||
logprefix = ''
|
logprefix = ''
|
||||||
verbose = 0
|
verbose = 0
|
||||||
@ -30,6 +30,11 @@ class Fatal(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
EXITCODE_NEEDS_REBOOT = 111
|
||||||
|
class FatalNeedsReboot(Fatal):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def list_contains_any(l, sub):
|
def list_contains_any(l, sub):
|
||||||
for i in sub:
|
for i in sub:
|
||||||
if i in l:
|
if i in l:
|
||||||
|
@ -13,7 +13,11 @@ _nmb_ok = True
|
|||||||
_smb_ok = True
|
_smb_ok = True
|
||||||
hostnames = {}
|
hostnames = {}
|
||||||
queue = {}
|
queue = {}
|
||||||
null = open('/dev/null', 'rb+')
|
try:
|
||||||
|
null = open('/dev/null', 'wb')
|
||||||
|
except IOError, e:
|
||||||
|
log('warning: %s\n' % e)
|
||||||
|
null = os.popen("sh -c 'while read x; do :; done'", 'wb', 4096)
|
||||||
|
|
||||||
|
|
||||||
def _is_ip(s):
|
def _is_ip(s):
|
||||||
|
17
main.py
17
main.py
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys, os, re
|
import sys, os, re
|
||||||
import helpers, options, client, server, firewall, hostwatch
|
import helpers, options, client, server, firewall, hostwatch
|
||||||
import compat.ssubprocess as ssubprocess
|
import compat.ssubprocess as ssubprocess
|
||||||
@ -55,14 +54,16 @@ l,listen= transproxy to this ip address and port number [127.0.0.1:0]
|
|||||||
H,auto-hosts scan for remote hostnames and update local /etc/hosts
|
H,auto-hosts scan for remote hostnames and update local /etc/hosts
|
||||||
N,auto-nets automatically determine subnets to route
|
N,auto-nets automatically determine subnets to route
|
||||||
dns capture local DNS requests and forward to the remote DNS server
|
dns capture local DNS requests and forward to the remote DNS server
|
||||||
python= path to python interpreter on the remote server [python]
|
python= path to python interpreter on the remote server
|
||||||
r,remote= ssh hostname (and optional username) of remote sshuttle server
|
r,remote= ssh hostname (and optional username) of remote sshuttle server
|
||||||
x,exclude= exclude this subnet (can be used more than once)
|
x,exclude= exclude this subnet (can be used more than once)
|
||||||
v,verbose increase debug message verbosity
|
v,verbose increase debug message verbosity
|
||||||
e,ssh-cmd= the command to use to connect to the remote [ssh]
|
e,ssh-cmd= the command to use to connect to the remote [ssh]
|
||||||
seed-hosts= with -H, use these hostnames for initial scan (comma-separated)
|
seed-hosts= with -H, use these hostnames for initial scan (comma-separated)
|
||||||
no-latency-control sacrifice latency to improve bandwidth benchmarks
|
no-latency-control sacrifice latency to improve bandwidth benchmarks
|
||||||
|
wrap= restart counting channel numbers after this number (for testing)
|
||||||
D,daemon run in the background as a daemon
|
D,daemon run in the background as a daemon
|
||||||
|
V,version print sshuttle's version number
|
||||||
syslog send log messages to syslog (default if you use --daemon)
|
syslog send log messages to syslog (default if you use --daemon)
|
||||||
pidfile= pidfile name (only if using --daemon) [./sshuttle.pid]
|
pidfile= pidfile name (only if using --daemon) [./sshuttle.pid]
|
||||||
server (internal use only)
|
server (internal use only)
|
||||||
@ -70,10 +71,17 @@ firewall (internal use only)
|
|||||||
hostwatch (internal use only)
|
hostwatch (internal use only)
|
||||||
"""
|
"""
|
||||||
o = options.Options(optspec)
|
o = options.Options(optspec)
|
||||||
(opt, flags, extra) = o.parse(sys.argv[1:])
|
(opt, flags, extra) = o.parse(sys.argv[2:])
|
||||||
|
|
||||||
|
if opt.version:
|
||||||
|
import version
|
||||||
|
print version.TAG
|
||||||
|
sys.exit(0)
|
||||||
if opt.daemon:
|
if opt.daemon:
|
||||||
opt.syslog = 1
|
opt.syslog = 1
|
||||||
|
if opt.wrap:
|
||||||
|
import ssnet
|
||||||
|
ssnet.MAX_CHANNEL = int(opt.wrap)
|
||||||
helpers.verbose = opt.verbose
|
helpers.verbose = opt.verbose
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -118,6 +126,9 @@ try:
|
|||||||
parse_subnets(includes),
|
parse_subnets(includes),
|
||||||
parse_subnets(excludes),
|
parse_subnets(excludes),
|
||||||
opt.syslog, opt.daemon, opt.pidfile))
|
opt.syslog, opt.daemon, opt.pidfile))
|
||||||
|
except FatalNeedsReboot, e:
|
||||||
|
log('You must reboot before using sshuttle.\n')
|
||||||
|
sys.exit(EXITCODE_NEEDS_REBOOT)
|
||||||
except Fatal, e:
|
except Fatal, e:
|
||||||
log('fatal: %s\n' % e)
|
log('fatal: %s\n' % e)
|
||||||
sys.exit(99)
|
sys.exit(99)
|
||||||
|
45
server.py
45
server.py
@ -110,16 +110,51 @@ class DnsProxy(Handler):
|
|||||||
def __init__(self, mux, chan, request):
|
def __init__(self, mux, chan, request):
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
Handler.__init__(self, [sock])
|
Handler.__init__(self, [sock])
|
||||||
self.sock = sock
|
|
||||||
self.timeout = time.time()+30
|
self.timeout = time.time()+30
|
||||||
self.mux = mux
|
self.mux = mux
|
||||||
self.chan = chan
|
self.chan = chan
|
||||||
|
self.tries = 0
|
||||||
|
self.peer = None
|
||||||
|
self.request = request
|
||||||
|
self.sock = sock
|
||||||
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
|
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
|
||||||
self.sock.connect((resolvconf_random_nameserver(), 53))
|
self.try_send()
|
||||||
self.sock.send(request)
|
|
||||||
|
def try_send(self):
|
||||||
|
if self.tries >= 3:
|
||||||
|
return
|
||||||
|
self.tries += 1
|
||||||
|
self.peer = resolvconf_random_nameserver()
|
||||||
|
self.sock.connect((self.peer, 53))
|
||||||
|
debug2('DNS: sending to %r\n' % self.peer)
|
||||||
|
try:
|
||||||
|
self.sock.send(self.request)
|
||||||
|
except socket.error, e:
|
||||||
|
if e.args[0] in ssnet.NET_ERRS:
|
||||||
|
# might have been spurious; try again.
|
||||||
|
# Note: these errors sometimes are reported by recv(),
|
||||||
|
# and sometimes by send(). We have to catch both.
|
||||||
|
debug2('DNS send to %r: %s\n' % (self.peer, e))
|
||||||
|
self.try_send()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log('DNS send to %r: %s\n' % (self.peer, e))
|
||||||
|
return
|
||||||
|
|
||||||
def callback(self):
|
def callback(self):
|
||||||
data = self.sock.recv(4096)
|
try:
|
||||||
|
data = self.sock.recv(4096)
|
||||||
|
except socket.error, e:
|
||||||
|
if e.args[0] in ssnet.NET_ERRS:
|
||||||
|
# might have been spurious; try again.
|
||||||
|
# Note: these errors sometimes are reported by recv(),
|
||||||
|
# and sometimes by send(). We have to catch both.
|
||||||
|
debug2('DNS recv from %r: %s\n' % (self.peer, e))
|
||||||
|
self.try_send()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log('DNS recv from %r: %s\n' % (self.peer, e))
|
||||||
|
return
|
||||||
debug2('DNS response: %d bytes\n' % len(data))
|
debug2('DNS response: %d bytes\n' % 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
|
||||||
@ -138,7 +173,7 @@ def main():
|
|||||||
debug1(' %s/%d\n' % r)
|
debug1(' %s/%d\n' % r)
|
||||||
|
|
||||||
# synchronization header
|
# synchronization header
|
||||||
sys.stdout.write('SSHUTTLE0001')
|
sys.stdout.write('\0\0SSHUTTLE0001')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
|
11
ssh.py
11
ssh.py
@ -73,16 +73,23 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
|||||||
|
|
||||||
|
|
||||||
if not rhost:
|
if not rhost:
|
||||||
argv = [python, '-c', pyscript]
|
# ignore the --python argument when running locally; we already know
|
||||||
|
# which python version works.
|
||||||
|
argv = [sys.argv[1], '-c', pyscript]
|
||||||
else:
|
else:
|
||||||
if ssh_cmd:
|
if ssh_cmd:
|
||||||
sshl = ssh_cmd.split(' ')
|
sshl = ssh_cmd.split(' ')
|
||||||
else:
|
else:
|
||||||
sshl = ['ssh']
|
sshl = ['ssh']
|
||||||
|
if python:
|
||||||
|
pycmd = "'%s' -c '%s'" % (python, pyscript)
|
||||||
|
else:
|
||||||
|
pycmd = ("P=python2; $P -V 2>/dev/null || P=python; "
|
||||||
|
"exec \"$P\" -c '%s'") % pyscript
|
||||||
argv = (sshl +
|
argv = (sshl +
|
||||||
portl +
|
portl +
|
||||||
ipv6flag +
|
ipv6flag +
|
||||||
[rhost, '--', "'%s' -c '%s'" % (python, pyscript)])
|
[rhost, '--', pycmd])
|
||||||
(s1,s2) = socket.socketpair()
|
(s1,s2) = socket.socketpair()
|
||||||
def setup():
|
def setup():
|
||||||
# runs in the child process
|
# runs in the child process
|
||||||
|
12
sshuttle
Executable file
12
sshuttle
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
EXE=$0
|
||||||
|
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||||
|
[ -L "$EXE" ] || break
|
||||||
|
EXE=$(readlink "$EXE")
|
||||||
|
done
|
||||||
|
DIR=$(dirname "$EXE")
|
||||||
|
if python2 -V 2>/dev/null; then
|
||||||
|
exec python2 "$DIR/main.py" python2 "$@"
|
||||||
|
else
|
||||||
|
exec python "$DIR/main.py" python "$@"
|
||||||
|
fi
|
47
ssnet.py
47
ssnet.py
@ -1,6 +1,8 @@
|
|||||||
import struct, socket, errno, select
|
import struct, socket, errno, select
|
||||||
if not globals().get('skip_imports'):
|
if not globals().get('skip_imports'):
|
||||||
from helpers import *
|
from helpers import *
|
||||||
|
|
||||||
|
MAX_CHANNEL = 65535
|
||||||
|
|
||||||
# these don't exist in the socket module in python 2.3!
|
# these don't exist in the socket module in python 2.3!
|
||||||
SHUT_RD = 0
|
SHUT_RD = 0
|
||||||
@ -38,7 +40,11 @@ cmd_to_name = {
|
|||||||
CMD_DNS_REQ: 'DNS_REQ',
|
CMD_DNS_REQ: 'DNS_REQ',
|
||||||
CMD_DNS_RESPONSE: 'DNS_RESPONSE',
|
CMD_DNS_RESPONSE: 'DNS_RESPONSE',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NET_ERRS = [errno.ECONNREFUSED, errno.ETIMEDOUT,
|
||||||
|
errno.EHOSTUNREACH, errno.ENETUNREACH,
|
||||||
|
errno.EHOSTDOWN, errno.ENETDOWN]
|
||||||
|
|
||||||
|
|
||||||
def _add(l, elem):
|
def _add(l, elem):
|
||||||
@ -84,7 +90,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)\n' % _swcount)
|
||||||
self.exc = None
|
self.exc = None
|
||||||
self.rsock = rsock
|
self.rsock = rsock
|
||||||
self.wsock = wsock
|
self.wsock = wsock
|
||||||
@ -99,7 +105,7 @@ class SockWrapper:
|
|||||||
_swcount -= 1
|
_swcount -= 1
|
||||||
debug1('%r: deleting (%d remain)\n' % (self, _swcount))
|
debug1('%r: deleting (%d remain)\n' % (self, _swcount))
|
||||||
if self.exc:
|
if self.exc:
|
||||||
debug1('%r: error was: %r\n' % (self, self.exc))
|
debug1('%r: error was: %s\n' % (self, self.exc))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.rsock == self.wsock:
|
if self.rsock == self.wsock:
|
||||||
@ -122,20 +128,45 @@ class SockWrapper:
|
|||||||
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\n' % (self, self.connect_to))
|
||||||
|
if socket.inet_aton(self.connect_to[0])[0] == '\0':
|
||||||
|
self.seterr(Exception("Can't connect to %r: "
|
||||||
|
"IP address starts with zero\n"
|
||||||
|
% (self.connect_to,)))
|
||||||
|
self.connect_to = None
|
||||||
|
return
|
||||||
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, e:
|
except socket.error, e:
|
||||||
debug3('%r: connect result: %r\n' % (self, e))
|
debug3('%r: connect result: %s\n' % (self, e))
|
||||||
|
if e.args[0] == errno.EINVAL:
|
||||||
|
# this is what happens when you call connect() on a socket
|
||||||
|
# that is now connected but returned EINPROGRESS last time,
|
||||||
|
# on BSD, on python pre-2.5.1. We need to use getsockopt()
|
||||||
|
# to get the "real" error. Later pythons do this
|
||||||
|
# automatically, so this code won't run.
|
||||||
|
realerr = self.rsock.getsockopt(socket.SOL_SOCKET,
|
||||||
|
socket.SO_ERROR)
|
||||||
|
e = socket.error(realerr, os.strerror(realerr))
|
||||||
|
debug3('%r: fixed connect result: %s\n' % (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:
|
||||||
|
# connected successfully (weird Linux bug?)
|
||||||
|
# Sometimes Linux seems to return EINVAL when it isn't
|
||||||
|
# invalid. This *may* be caused by a race condition
|
||||||
|
# between connect() and getsockopt(SO_ERROR) (ie. it
|
||||||
|
# finishes connecting in between the two, so there is no
|
||||||
|
# longer an error). However, I'm not sure of that.
|
||||||
|
#
|
||||||
|
# I did get at least one report that the problem went away
|
||||||
|
# when we added this, however.
|
||||||
|
self.connect_to = None
|
||||||
elif e.args[0] == errno.EISCONN:
|
elif e.args[0] == errno.EISCONN:
|
||||||
# connected successfully (BSD)
|
# connected successfully (BSD)
|
||||||
self.connect_to = None
|
self.connect_to = None
|
||||||
elif e.args[0] in [errno.ECONNREFUSED, errno.ETIMEDOUT,
|
elif e.args[0] in NET_ERRS + [errno.EACCES, errno.EPERM]:
|
||||||
errno.EHOSTUNREACH, errno.ENETUNREACH,
|
|
||||||
errno.EACCES, errno.EPERM]:
|
|
||||||
# a "normal" kind of error
|
# a "normal" kind of error
|
||||||
self.connect_to = None
|
self.connect_to = None
|
||||||
self.seterr(e)
|
self.seterr(e)
|
||||||
@ -300,7 +331,7 @@ class Mux(Handler):
|
|||||||
# channel 0 is special, so we never allocate it
|
# channel 0 is special, so we never allocate it
|
||||||
for timeout in xrange(1024):
|
for timeout in xrange(1024):
|
||||||
self.chani += 1
|
self.chani += 1
|
||||||
if self.chani > 65535:
|
if self.chani > MAX_CHANNEL:
|
||||||
self.chani = 1
|
self.chani = 1
|
||||||
if not self.channels.get(self.chani):
|
if not self.channels.get(self.chani):
|
||||||
return self.chani
|
return self.chani
|
||||||
|
86
stresstest.py
Executable file
86
stresstest.py
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import sys, os, socket, select, struct, time
|
||||||
|
|
||||||
|
listener = socket.socket()
|
||||||
|
listener.bind(('127.0.0.1', 0))
|
||||||
|
listener.listen(500)
|
||||||
|
|
||||||
|
servers = []
|
||||||
|
clients = []
|
||||||
|
remain = {}
|
||||||
|
|
||||||
|
NUMCLIENTS = 50
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
if len(clients) < NUMCLIENTS:
|
||||||
|
c = socket.socket()
|
||||||
|
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
c.bind(('0.0.0.0', 0))
|
||||||
|
c.connect(listener.getsockname())
|
||||||
|
count += 1
|
||||||
|
if count >= 16384:
|
||||||
|
count = 1
|
||||||
|
print 'cli CREATING %d' % count
|
||||||
|
b = struct.pack('I', count) + 'x'*count
|
||||||
|
remain[c] = count
|
||||||
|
print 'cli >> %r' % len(b)
|
||||||
|
c.send(b)
|
||||||
|
c.shutdown(socket.SHUT_WR)
|
||||||
|
clients.append(c)
|
||||||
|
r = [listener]
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
r = [listener]+servers+clients
|
||||||
|
print 'select(%d)' % len(r)
|
||||||
|
r,w,x = select.select(r, [], [], 5)
|
||||||
|
assert(r)
|
||||||
|
for i in r:
|
||||||
|
if i == listener:
|
||||||
|
s,addr = listener.accept()
|
||||||
|
servers.append(s)
|
||||||
|
elif i in servers:
|
||||||
|
b = i.recv(4096)
|
||||||
|
print 'srv << %r' % len(b)
|
||||||
|
if not i in remain:
|
||||||
|
assert(len(b) >= 4)
|
||||||
|
want = struct.unpack('I', b[:4])[0]
|
||||||
|
b = b[4:]
|
||||||
|
#i.send('y'*want)
|
||||||
|
else:
|
||||||
|
want = remain[i]
|
||||||
|
if want < len(b):
|
||||||
|
print 'weird wanted %d bytes, got %d: %r' % (want, len(b), b)
|
||||||
|
assert(want >= len(b))
|
||||||
|
want -= len(b)
|
||||||
|
remain[i] = want
|
||||||
|
if not b: # EOF
|
||||||
|
if want:
|
||||||
|
print 'weird: eof but wanted %d more' % want
|
||||||
|
assert(want == 0)
|
||||||
|
i.close()
|
||||||
|
servers.remove(i)
|
||||||
|
del remain[i]
|
||||||
|
else:
|
||||||
|
print 'srv >> %r' % len(b)
|
||||||
|
i.send('y'*len(b))
|
||||||
|
if not want:
|
||||||
|
i.shutdown(socket.SHUT_WR)
|
||||||
|
elif i in clients:
|
||||||
|
b = i.recv(4096)
|
||||||
|
print 'cli << %r' % len(b)
|
||||||
|
want = remain[i]
|
||||||
|
if want < len(b):
|
||||||
|
print 'weird wanted %d bytes, got %d: %r' % (want, len(b), b)
|
||||||
|
assert(want >= len(b))
|
||||||
|
want -= len(b)
|
||||||
|
remain[i] = want
|
||||||
|
if not b: # EOF
|
||||||
|
if want:
|
||||||
|
print 'weird: eof but wanted %d more' % want
|
||||||
|
assert(want == 0)
|
||||||
|
i.close()
|
||||||
|
clients.remove(i)
|
||||||
|
del remain[i]
|
||||||
|
listener.accept()
|
@ -2,17 +2,17 @@
|
|||||||
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
|
||||||
<data>
|
<data>
|
||||||
<int key="IBDocument.SystemTarget">1060</int>
|
<int key="IBDocument.SystemTarget">1060</int>
|
||||||
<string key="IBDocument.SystemVersion">10H574</string>
|
<string key="IBDocument.SystemVersion">10J567</string>
|
||||||
<string key="IBDocument.InterfaceBuilderVersion">762</string>
|
<string key="IBDocument.InterfaceBuilderVersion">762</string>
|
||||||
<string key="IBDocument.AppKitVersion">1038.35</string>
|
<string key="IBDocument.AppKitVersion">1038.35</string>
|
||||||
<string key="IBDocument.HIToolboxVersion">461.00</string>
|
<string key="IBDocument.HIToolboxVersion">462.00</string>
|
||||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="NS.object.0">762</string>
|
<string key="NS.object.0">762</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<integer value="233"/>
|
<integer value="237"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSArray" key="IBDocument.PluginDependencies">
|
<object class="NSArray" key="IBDocument.PluginDependencies">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
@ -41,9 +41,9 @@
|
|||||||
<string key="NSClassName">NSApplication</string>
|
<string key="NSClassName">NSApplication</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSWindowTemplate" id="411825121">
|
<object class="NSWindowTemplate" id="411825121">
|
||||||
<int key="NSWindowStyleMask">3</int>
|
<int key="NSWindowStyleMask">11</int>
|
||||||
<int key="NSWindowBacking">2</int>
|
<int key="NSWindowBacking">2</int>
|
||||||
<string key="NSWindowRect">{{157, 116}, {611, 369}}</string>
|
<string key="NSWindowRect">{{324, 171}, {611, 469}}</string>
|
||||||
<int key="NSWTFlags">1886913536</int>
|
<int key="NSWTFlags">1886913536</int>
|
||||||
<string key="NSWindowTitle">Sshuttle VPN Preferences</string>
|
<string key="NSWindowTitle">Sshuttle VPN Preferences</string>
|
||||||
<string key="NSWindowClass">NSWindow</string>
|
<string key="NSWindowClass">NSWindow</string>
|
||||||
@ -51,16 +51,16 @@
|
|||||||
<characters key="NS.bytes">View</characters>
|
<characters key="NS.bytes">View</characters>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
|
<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
|
||||||
<string key="NSWindowContentMinSize">{213, 107}</string>
|
<string key="NSWindowContentMinSize">{611, 469}</string>
|
||||||
<object class="NSView" key="NSWindowView" id="174067038">
|
<object class="NSView" key="NSWindowView" id="174067038">
|
||||||
<reference key="NSNextResponder"/>
|
<reference key="NSNextResponder"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">274</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSTabView" id="389252804">
|
<object class="NSTabView" id="389252804">
|
||||||
<reference key="NSNextResponder" ref="174067038"/>
|
<reference key="NSNextResponder" ref="174067038"/>
|
||||||
<int key="NSvFlags">12</int>
|
<int key="NSvFlags">18</int>
|
||||||
<string key="NSFrame">{{-8, -10}, {627, 373}}</string>
|
<string key="NSFrame">{{-8, -10}, {627, 473}}</string>
|
||||||
<reference key="NSSuperview" ref="174067038"/>
|
<reference key="NSSuperview" ref="174067038"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<object class="NSMutableArray" key="NSTabViewItems">
|
<object class="NSMutableArray" key="NSTabViewItems">
|
||||||
@ -68,13 +68,13 @@
|
|||||||
<object class="NSTabViewItem" id="762265164">
|
<object class="NSTabViewItem" id="762265164">
|
||||||
<string key="NSIdentifier">1</string>
|
<string key="NSIdentifier">1</string>
|
||||||
<object class="NSView" key="NSView" id="60314308">
|
<object class="NSView" key="NSView" id="60314308">
|
||||||
<nil key="NSNextResponder"/>
|
<reference key="NSNextResponder" ref="389252804"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">274</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSButton" id="26015719">
|
<object class="NSButton" id="26015719">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">292</int>
|
||||||
<string key="NSFrame">{{17, 17}, {25, 23}}</string>
|
<string key="NSFrame">{{17, 17}, {25, 23}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -103,7 +103,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSButton" id="244571541">
|
<object class="NSButton" id="244571541">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">292</int>
|
||||||
<string key="NSFrame">{{41, 17}, {25, 23}}</string>
|
<string key="NSFrame">{{41, 17}, {25, 23}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -128,7 +128,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSScrollView" id="776974664">
|
<object class="NSScrollView" id="776974664">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">274</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSClipView" id="8658574">
|
<object class="NSClipView" id="8658574">
|
||||||
@ -139,7 +139,7 @@
|
|||||||
<object class="NSTableView" id="849333466">
|
<object class="NSTableView" id="849333466">
|
||||||
<reference key="NSNextResponder" ref="8658574"/>
|
<reference key="NSNextResponder" ref="8658574"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">256</int>
|
||||||
<string key="NSFrameSize">{224, 282}</string>
|
<string key="NSFrameSize">{224, 372}</string>
|
||||||
<reference key="NSSuperview" ref="8658574"/>
|
<reference key="NSSuperview" ref="8658574"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -275,7 +275,7 @@
|
|||||||
<int key="NSTableViewDraggingDestinationStyle">0</int>
|
<int key="NSTableViewDraggingDestinationStyle">0</int>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{1, 1}, {223, 282}}</string>
|
<string key="NSFrame">{{1, 1}, {223, 372}}</string>
|
||||||
<reference key="NSSuperview" ref="776974664"/>
|
<reference key="NSSuperview" ref="776974664"/>
|
||||||
<reference key="NSNextKeyView" ref="849333466"/>
|
<reference key="NSNextKeyView" ref="849333466"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -306,7 +306,7 @@
|
|||||||
<double key="NSPercent">0.91812865497076024</double>
|
<double key="NSPercent">0.91812865497076024</double>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{17, 40}, {225, 284}}</string>
|
<string key="NSFrame">{{17, 40}, {225, 374}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<reference key="NSNextKeyView" ref="8658574"/>
|
<reference key="NSNextKeyView" ref="8658574"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -318,8 +318,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSButton" id="538356055">
|
<object class="NSButton" id="538356055">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">265</int>
|
||||||
<string key="NSFrame">{{296, 254}, {273, 18}}</string>
|
<string key="NSFrame">{{291, 356}, {273, 18}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -341,8 +341,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSTextField" id="889877302">
|
<object class="NSTextField" id="889877302">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">265</int>
|
||||||
<string key="NSFrame">{{341, 292}, {249, 22}}</string>
|
<string key="NSFrame">{{341, 392}, {249, 22}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -369,8 +369,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSPopUpButton" id="801412726">
|
<object class="NSPopUpButton" id="801412726">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">265</int>
|
||||||
<string key="NSFrame">{{273, 185}, {320, 26}}</string>
|
<string key="NSFrame">{{273, 193}, {320, 26}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -440,10 +440,77 @@
|
|||||||
<int key="NSArrowPosition">2</int>
|
<int key="NSArrowPosition">2</int>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="NSPopUpButton" id="451647466">
|
||||||
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
|
<int key="NSvFlags">265</int>
|
||||||
|
<string key="NSFrame">{{273, 257}, {320, 26}}</string>
|
||||||
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
|
<bool key="NSEnabled">YES</bool>
|
||||||
|
<object class="NSPopUpButtonCell" key="NSCell" id="970826243">
|
||||||
|
<int key="NSCellFlags">-2076049856</int>
|
||||||
|
<int key="NSCellFlags2">2048</int>
|
||||||
|
<reference key="NSSupport" ref="696441443"/>
|
||||||
|
<reference key="NSControlView" ref="451647466"/>
|
||||||
|
<int key="NSButtonFlags">112869631</int>
|
||||||
|
<int key="NSButtonFlags2">129</int>
|
||||||
|
<string key="NSAlternateContents"/>
|
||||||
|
<string key="NSKeyEquivalent"/>
|
||||||
|
<int key="NSPeriodicDelay">400</int>
|
||||||
|
<int key="NSPeriodicInterval">75</int>
|
||||||
|
<object class="NSMenuItem" key="NSMenuItem" id="903120255">
|
||||||
|
<reference key="NSMenu" ref="790880658"/>
|
||||||
|
<string key="NSTitle">Choose one</string>
|
||||||
|
<string key="NSKeyEquiv"/>
|
||||||
|
<int key="NSKeyEquivModMask">1048576</int>
|
||||||
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
|
<int key="NSState">1</int>
|
||||||
|
<reference key="NSOnImage" ref="615977438"/>
|
||||||
|
<reference key="NSMixedImage" ref="445532764"/>
|
||||||
|
<string key="NSAction">_popUpItemAction:</string>
|
||||||
|
<reference key="NSTarget" ref="970826243"/>
|
||||||
|
</object>
|
||||||
|
<bool key="NSMenuItemRespectAlignment">YES</bool>
|
||||||
|
<object class="NSMenu" key="NSMenu" id="790880658">
|
||||||
|
<string key="NSTitle">OtherViews</string>
|
||||||
|
<object class="NSMutableArray" key="NSMenuItems">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="903120255"/>
|
||||||
|
<object class="NSMenuItem" id="778262848">
|
||||||
|
<reference key="NSMenu" ref="790880658"/>
|
||||||
|
<string key="NSTitle">Item 2</string>
|
||||||
|
<string key="NSKeyEquiv"/>
|
||||||
|
<int key="NSKeyEquivModMask">1048576</int>
|
||||||
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
|
<reference key="NSOnImage" ref="615977438"/>
|
||||||
|
<reference key="NSMixedImage" ref="445532764"/>
|
||||||
|
<string key="NSAction">_popUpItemAction:</string>
|
||||||
|
<reference key="NSTarget" ref="970826243"/>
|
||||||
|
</object>
|
||||||
|
<object class="NSMenuItem" id="195135854">
|
||||||
|
<reference key="NSMenu" ref="790880658"/>
|
||||||
|
<string key="NSTitle">Item 3</string>
|
||||||
|
<string key="NSKeyEquiv"/>
|
||||||
|
<int key="NSKeyEquivModMask">1048576</int>
|
||||||
|
<int key="NSMnemonicLoc">2147483647</int>
|
||||||
|
<reference key="NSOnImage" ref="615977438"/>
|
||||||
|
<reference key="NSMixedImage" ref="445532764"/>
|
||||||
|
<string key="NSAction">_popUpItemAction:</string>
|
||||||
|
<reference key="NSTarget" ref="970826243"/>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<reference key="NSMenuFont" ref="696441443"/>
|
||||||
|
</object>
|
||||||
|
<int key="NSPreferredEdge">1</int>
|
||||||
|
<bool key="NSUsesItemFromMenu">YES</bool>
|
||||||
|
<bool key="NSAltersState">YES</bool>
|
||||||
|
<int key="NSArrowPosition">2</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
<object class="NSTextField" id="753545988">
|
<object class="NSTextField" id="753545988">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">265</int>
|
||||||
<string key="NSFrame">{{261, 294}, {75, 17}}</string>
|
<string key="NSFrame">{{261, 394}, {75, 17}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -459,8 +526,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSTextField" id="840157770">
|
<object class="NSTextField" id="840157770">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">265</int>
|
||||||
<string key="NSFrame">{{261, 217}, {105, 17}}</string>
|
<string key="NSFrame">{{261, 226}, {105, 17}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -474,9 +541,26 @@
|
|||||||
<reference key="NSTextColor" ref="399750419"/>
|
<reference key="NSTextColor" ref="399750419"/>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="NSTextField" id="459566505">
|
||||||
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
|
<int key="NSvFlags">265</int>
|
||||||
|
<string key="NSFrame">{{261, 290}, {105, 17}}</string>
|
||||||
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
|
<bool key="NSEnabled">YES</bool>
|
||||||
|
<object class="NSTextFieldCell" key="NSCell" id="534245320">
|
||||||
|
<int key="NSCellFlags">68288064</int>
|
||||||
|
<int key="NSCellFlags2">272630784</int>
|
||||||
|
<string key="NSContents">Optimize for:</string>
|
||||||
|
<reference key="NSSupport" ref="696441443"/>
|
||||||
|
<reference key="NSControlView" ref="459566505"/>
|
||||||
|
<reference key="NSBackgroundColor" ref="965844506"/>
|
||||||
|
<reference key="NSTextColor" ref="399750419"/>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
<object class="NSButton" id="962924480">
|
<object class="NSButton" id="962924480">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">289</int>
|
||||||
<string key="NSFrame">{{276, 40}, {25, 23}}</string>
|
<string key="NSFrame">{{276, 40}, {25, 23}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -498,7 +582,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSButton" id="705215911">
|
<object class="NSButton" id="705215911">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">289</int>
|
||||||
<string key="NSFrame">{{300, 40}, {25, 23}}</string>
|
<string key="NSFrame">{{300, 40}, {25, 23}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -520,7 +604,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSScrollView" id="610703353">
|
<object class="NSScrollView" id="610703353">
|
||||||
<reference key="NSNextResponder" ref="60314308"/>
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">273</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSClipView" id="844110079">
|
<object class="NSClipView" id="844110079">
|
||||||
@ -531,7 +615,7 @@
|
|||||||
<object class="NSTableView" id="714838401">
|
<object class="NSTableView" id="714838401">
|
||||||
<reference key="NSNextResponder" ref="844110079"/>
|
<reference key="NSNextResponder" ref="844110079"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">256</int>
|
||||||
<string key="NSFrameSize">{312, 95}</string>
|
<string key="NSFrameSize">{312, 102}</string>
|
||||||
<reference key="NSSuperview" ref="844110079"/>
|
<reference key="NSSuperview" ref="844110079"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -623,7 +707,7 @@
|
|||||||
<int key="NSTableViewDraggingDestinationStyle">0</int>
|
<int key="NSTableViewDraggingDestinationStyle">0</int>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{1, 17}, {312, 95}}</string>
|
<string key="NSFrame">{{1, 17}, {312, 102}}</string>
|
||||||
<reference key="NSSuperview" ref="610703353"/>
|
<reference key="NSSuperview" ref="610703353"/>
|
||||||
<reference key="NSNextKeyView" ref="714838401"/>
|
<reference key="NSNextKeyView" ref="714838401"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -639,7 +723,7 @@
|
|||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<reference key="NSTarget" ref="610703353"/>
|
<reference key="NSTarget" ref="610703353"/>
|
||||||
<string key="NSAction">_doScroller:</string>
|
<string key="NSAction">_doScroller:</string>
|
||||||
<double key="NSPercent">0.8529411764705882</double>
|
<double key="NSPercent">0.96938775510204078</double>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSScroller" id="522064761">
|
<object class="NSScroller" id="522064761">
|
||||||
<reference key="NSNextResponder" ref="610703353"/>
|
<reference key="NSNextResponder" ref="610703353"/>
|
||||||
@ -669,7 +753,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<reference ref="188199142"/>
|
<reference ref="188199142"/>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{276, 63}, {314, 113}}</string>
|
<string key="NSFrame">{{276, 63}, {314, 120}}</string>
|
||||||
<reference key="NSSuperview" ref="60314308"/>
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
<reference key="NSNextKeyView" ref="844110079"/>
|
<reference key="NSNextKeyView" ref="844110079"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -681,8 +765,32 @@
|
|||||||
<reference key="NSCornerView" ref="188199142"/>
|
<reference key="NSCornerView" ref="188199142"/>
|
||||||
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
|
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="NSButton" id="160987209">
|
||||||
|
<reference key="NSNextResponder" ref="60314308"/>
|
||||||
|
<int key="NSvFlags">265</int>
|
||||||
|
<string key="NSFrame">{{291, 323}, {285, 18}}</string>
|
||||||
|
<reference key="NSSuperview" ref="60314308"/>
|
||||||
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
|
<bool key="NSEnabled">YES</bool>
|
||||||
|
<object class="NSButtonCell" key="NSCell" id="565787077">
|
||||||
|
<int key="NSCellFlags">-2080244224</int>
|
||||||
|
<int key="NSCellFlags2">0</int>
|
||||||
|
<string key="NSContents">Send DNS requests through this server</string>
|
||||||
|
<reference key="NSSupport" ref="696441443"/>
|
||||||
|
<reference key="NSControlView" ref="160987209"/>
|
||||||
|
<int key="NSButtonFlags">1211912703</int>
|
||||||
|
<int key="NSButtonFlags2">2</int>
|
||||||
|
<reference key="NSNormalImage" ref="581816235"/>
|
||||||
|
<reference key="NSAlternateImage" ref="753862261"/>
|
||||||
|
<string key="NSAlternateContents"/>
|
||||||
|
<string key="NSKeyEquivalent"/>
|
||||||
|
<int key="NSPeriodicDelay">200</int>
|
||||||
|
<int key="NSPeriodicInterval">25</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
|
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
|
||||||
|
<reference key="NSSuperview" ref="389252804"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSLabel">SSH Servers</string>
|
<string key="NSLabel">SSH Servers</string>
|
||||||
@ -692,14 +800,14 @@
|
|||||||
<object class="NSTabViewItem" id="740075218">
|
<object class="NSTabViewItem" id="740075218">
|
||||||
<string key="NSIdentifier">2</string>
|
<string key="NSIdentifier">2</string>
|
||||||
<object class="NSView" key="NSView" id="187214803">
|
<object class="NSView" key="NSView" id="187214803">
|
||||||
<reference key="NSNextResponder" ref="389252804"/>
|
<nil key="NSNextResponder"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">274</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSButton" id="625816566">
|
<object class="NSButton" id="625816566">
|
||||||
<reference key="NSNextResponder" ref="187214803"/>
|
<reference key="NSNextResponder" ref="187214803"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">269</int>
|
||||||
<string key="NSFrame">{{189, 287}, {177, 29}}</string>
|
<string key="NSFrame">{{195, 374}, {236, 29}}</string>
|
||||||
<reference key="NSSuperview" ref="187214803"/>
|
<reference key="NSSuperview" ref="187214803"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -721,8 +829,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSButton" id="633518934">
|
<object class="NSButton" id="633518934">
|
||||||
<reference key="NSNextResponder" ref="187214803"/>
|
<reference key="NSNextResponder" ref="187214803"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">269</int>
|
||||||
<string key="NSFrame">{{189, 256}, {270, 29}}</string>
|
<string key="NSFrame">{{195, 343}, {236, 29}}</string>
|
||||||
<reference key="NSSuperview" ref="187214803"/>
|
<reference key="NSSuperview" ref="187214803"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -744,15 +852,15 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="NSButton" id="625121428">
|
<object class="NSButton" id="625121428">
|
||||||
<reference key="NSNextResponder" ref="187214803"/>
|
<reference key="NSNextResponder" ref="187214803"/>
|
||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">269</int>
|
||||||
<string key="NSFrame">{{189, 225}, {270, 29}}</string>
|
<string key="NSFrame">{{195, 312}, {236, 29}}</string>
|
||||||
<reference key="NSSuperview" ref="187214803"/>
|
<reference key="NSSuperview" ref="187214803"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
<object class="NSButtonCell" key="NSCell" id="132399775">
|
<object class="NSButtonCell" key="NSCell" id="132399775">
|
||||||
<int key="NSCellFlags">67239424</int>
|
<int key="NSCellFlags">67239424</int>
|
||||||
<int key="NSCellFlags2">0</int>
|
<int key="NSCellFlags2">0</int>
|
||||||
<string key="NSContents">Send debug information to log</string>
|
<string key="NSContents">Enable debug messages</string>
|
||||||
<reference key="NSSupport" ref="696441443"/>
|
<reference key="NSSupport" ref="696441443"/>
|
||||||
<reference key="NSControlView" ref="625121428"/>
|
<reference key="NSControlView" ref="625121428"/>
|
||||||
<int key="NSButtonFlags">1211912703</int>
|
<int key="NSButtonFlags">1211912703</int>
|
||||||
@ -766,8 +874,7 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
|
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
|
||||||
<reference key="NSSuperview" ref="389252804"/>
|
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSLabel">Options</string>
|
<string key="NSLabel">Options</string>
|
||||||
@ -783,7 +890,7 @@
|
|||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSScrollView" id="486362220">
|
<object class="NSScrollView" id="486362220">
|
||||||
<reference key="NSNextResponder" ref="311013698"/>
|
<reference key="NSNextResponder" ref="311013698"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">274</int>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<object class="NSClipView" id="708990027">
|
<object class="NSClipView" id="708990027">
|
||||||
@ -794,7 +901,7 @@
|
|||||||
<object class="NSTextView" id="758761310">
|
<object class="NSTextView" id="758761310">
|
||||||
<reference key="NSNextResponder" ref="708990027"/>
|
<reference key="NSNextResponder" ref="708990027"/>
|
||||||
<int key="NSvFlags">2322</int>
|
<int key="NSvFlags">2322</int>
|
||||||
<string key="NSFrameSize">{596, 14}</string>
|
<string key="NSFrameSize">{596, 114}</string>
|
||||||
<reference key="NSSuperview" ref="708990027"/>
|
<reference key="NSSuperview" ref="708990027"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<object class="NSTextContainer" key="NSTextContainer" id="548968659">
|
<object class="NSTextContainer" key="NSTextContainer" id="548968659">
|
||||||
@ -874,7 +981,7 @@
|
|||||||
<nil key="NSDelegate"/>
|
<nil key="NSDelegate"/>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{1, 1}, {596, 310}}</string>
|
<string key="NSFrame">{{1, 1}, {596, 410}}</string>
|
||||||
<reference key="NSSuperview" ref="486362220"/>
|
<reference key="NSSuperview" ref="486362220"/>
|
||||||
<reference key="NSNextKeyView" ref="758761310"/>
|
<reference key="NSNextKeyView" ref="758761310"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -889,7 +996,7 @@
|
|||||||
<object class="NSScroller" id="794963499">
|
<object class="NSScroller" id="794963499">
|
||||||
<reference key="NSNextResponder" ref="486362220"/>
|
<reference key="NSNextResponder" ref="486362220"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">256</int>
|
||||||
<string key="NSFrame">{{597, 1}, {15, 310}}</string>
|
<string key="NSFrame">{{597, 1}, {15, 410}}</string>
|
||||||
<reference key="NSSuperview" ref="486362220"/>
|
<reference key="NSSuperview" ref="486362220"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<reference key="NSTarget" ref="486362220"/>
|
<reference key="NSTarget" ref="486362220"/>
|
||||||
@ -900,7 +1007,7 @@
|
|||||||
<object class="NSScroller" id="324242772">
|
<object class="NSScroller" id="324242772">
|
||||||
<reference key="NSNextResponder" ref="486362220"/>
|
<reference key="NSNextResponder" ref="486362220"/>
|
||||||
<int key="NSvFlags">256</int>
|
<int key="NSvFlags">256</int>
|
||||||
<string key="NSFrame">{{1, 311}, {596, 15}}</string>
|
<string key="NSFrame">{{1, 411}, {596, 15}}</string>
|
||||||
<reference key="NSSuperview" ref="486362220"/>
|
<reference key="NSSuperview" ref="486362220"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<int key="NSsFlags">1</int>
|
<int key="NSsFlags">1</int>
|
||||||
@ -910,7 +1017,7 @@
|
|||||||
<double key="NSPercent">0.94565218687057495</double>
|
<double key="NSPercent">0.94565218687057495</double>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{-3, -3}, {613, 327}}</string>
|
<string key="NSFrame">{{-3, -3}, {613, 427}}</string>
|
||||||
<reference key="NSSuperview" ref="311013698"/>
|
<reference key="NSSuperview" ref="311013698"/>
|
||||||
<reference key="NSNextKeyView" ref="708990027"/>
|
<reference key="NSNextKeyView" ref="708990027"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
@ -920,7 +1027,7 @@
|
|||||||
<reference key="NSContentView" ref="708990027"/>
|
<reference key="NSContentView" ref="708990027"/>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrame">{{10, 33}, {607, 327}}</string>
|
<string key="NSFrame">{{10, 33}, {607, 427}}</string>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSLabel">Log Messages</string>
|
<string key="NSLabel">Log Messages</string>
|
||||||
@ -928,17 +1035,17 @@
|
|||||||
<reference key="NSTabView" ref="389252804"/>
|
<reference key="NSTabView" ref="389252804"/>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<reference key="NSSelectedTabViewItem" ref="740075218"/>
|
<reference key="NSSelectedTabViewItem" ref="762265164"/>
|
||||||
<reference key="NSFont" ref="696441443"/>
|
<reference key="NSFont" ref="696441443"/>
|
||||||
<int key="NSTvFlags">0</int>
|
<int key="NSTvFlags">0</int>
|
||||||
<bool key="NSDrawsBackground">YES</bool>
|
<bool key="NSDrawsBackground">YES</bool>
|
||||||
<object class="NSMutableArray" key="NSSubviews">
|
<object class="NSMutableArray" key="NSSubviews">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<reference ref="187214803"/>
|
<reference ref="60314308"/>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSFrameSize">{611, 369}</string>
|
<string key="NSFrameSize">{611, 469}</string>
|
||||||
<reference key="NSSuperview"/>
|
<reference key="NSSuperview"/>
|
||||||
<object class="NSDictionary" key="NSViewAnimations">
|
<object class="NSDictionary" key="NSViewAnimations">
|
||||||
<string key="NS.key.0">subviews</string>
|
<string key="NS.key.0">subviews</string>
|
||||||
@ -962,8 +1069,8 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSScreenRect">{{0, 0}, {800, 578}}</string>
|
<string key="NSScreenRect">{{0, 0}, {1280, 778}}</string>
|
||||||
<string key="NSMinSize">{213, 129}</string>
|
<string key="NSMinSize">{611, 491}</string>
|
||||||
<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
|
<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSArrayController" id="678105904">
|
<object class="NSArrayController" id="678105904">
|
||||||
@ -979,10 +1086,6 @@
|
|||||||
<string key="NSClassName">SshuttleController</string>
|
<string key="NSClassName">SshuttleController</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSUserDefaultsController" id="582889489">
|
<object class="NSUserDefaultsController" id="582889489">
|
||||||
<object class="NSMutableArray" key="NSDeclaredKeys">
|
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
|
||||||
<string>debug</string>
|
|
||||||
</object>
|
|
||||||
<bool key="NSSharedInstance">YES</bool>
|
<bool key="NSSharedInstance">YES</bool>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSCustomObject" id="735871403">
|
<object class="NSCustomObject" id="735871403">
|
||||||
@ -1000,6 +1103,9 @@
|
|||||||
<string>statusMsg</string>
|
<string>statusMsg</string>
|
||||||
<string>status</string>
|
<string>status</string>
|
||||||
<string>isValid</string>
|
<string>isValid</string>
|
||||||
|
<string>useDns</string>
|
||||||
|
<string>title</string>
|
||||||
|
<string>latencyControl</string>
|
||||||
</object>
|
</object>
|
||||||
<string key="NSObjectClassName">SshuttleServer</string>
|
<string key="NSObjectClassName">SshuttleServer</string>
|
||||||
<bool key="NSEditable">YES</bool>
|
<bool key="NSEditable">YES</bool>
|
||||||
@ -1109,35 +1215,6 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">480</int>
|
<int key="connectionID">480</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBConnectionRecord">
|
|
||||||
<object class="IBBindingConnection" key="connection">
|
|
||||||
<string key="label">value: arrangedObjects.host</string>
|
|
||||||
<reference key="source" ref="807059746"/>
|
|
||||||
<reference key="destination" ref="59237012"/>
|
|
||||||
<object class="NSNibBindingConnector" key="connector">
|
|
||||||
<reference key="NSSource" ref="807059746"/>
|
|
||||||
<reference key="NSDestination" ref="59237012"/>
|
|
||||||
<string key="NSLabel">value: arrangedObjects.host</string>
|
|
||||||
<string key="NSBinding">value</string>
|
|
||||||
<string key="NSKeyPath">arrangedObjects.host</string>
|
|
||||||
<object class="NSDictionary" key="NSOptions">
|
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
|
||||||
<object class="NSArray" key="dict.sortedKeys">
|
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
|
||||||
<string>NSConditionallySetsEditable</string>
|
|
||||||
<string>NSNullPlaceholder</string>
|
|
||||||
</object>
|
|
||||||
<object class="NSMutableArray" key="dict.values">
|
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
|
||||||
<boolean value="YES"/>
|
|
||||||
<string>Untitled</string>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
<int key="NSNibBindingConnectorVersion">2</int>
|
|
||||||
</object>
|
|
||||||
</object>
|
|
||||||
<int key="connectionID">495</int>
|
|
||||||
</object>
|
|
||||||
<object class="IBConnectionRecord">
|
<object class="IBConnectionRecord">
|
||||||
<object class="IBBindingConnection" key="connection">
|
<object class="IBBindingConnection" key="connection">
|
||||||
<string key="label">selectedIndex: selection.autoNets</string>
|
<string key="label">selectedIndex: selection.autoNets</string>
|
||||||
@ -1454,6 +1531,83 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">557</int>
|
<int key="connectionID">557</int>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBBindingConnection" key="connection">
|
||||||
|
<string key="label">value: selection.useDns</string>
|
||||||
|
<reference key="source" ref="160987209"/>
|
||||||
|
<reference key="destination" ref="59237012"/>
|
||||||
|
<object class="NSNibBindingConnector" key="connector">
|
||||||
|
<reference key="NSSource" ref="160987209"/>
|
||||||
|
<reference key="NSDestination" ref="59237012"/>
|
||||||
|
<string key="NSLabel">value: selection.useDns</string>
|
||||||
|
<string key="NSBinding">value</string>
|
||||||
|
<string key="NSKeyPath">selection.useDns</string>
|
||||||
|
<object class="NSDictionary" key="NSOptions">
|
||||||
|
<string key="NS.key.0">NSNoSelectionPlaceholder</string>
|
||||||
|
<integer value="0" key="NS.object.0"/>
|
||||||
|
</object>
|
||||||
|
<int key="NSNibBindingConnectorVersion">2</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">572</int>
|
||||||
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBBindingConnection" key="connection">
|
||||||
|
<string key="label">value: arrangedObjects.title</string>
|
||||||
|
<reference key="source" ref="807059746"/>
|
||||||
|
<reference key="destination" ref="59237012"/>
|
||||||
|
<object class="NSNibBindingConnector" key="connector">
|
||||||
|
<reference key="NSSource" ref="807059746"/>
|
||||||
|
<reference key="NSDestination" ref="59237012"/>
|
||||||
|
<string key="NSLabel">value: arrangedObjects.title</string>
|
||||||
|
<string key="NSBinding">value</string>
|
||||||
|
<string key="NSKeyPath">arrangedObjects.title</string>
|
||||||
|
<object class="NSDictionary" key="NSOptions">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<object class="NSArray" key="dict.sortedKeys">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<string>NSConditionallySetsEditable</string>
|
||||||
|
<string>NSNullPlaceholder</string>
|
||||||
|
</object>
|
||||||
|
<object class="NSMutableArray" key="dict.values">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<boolean value="YES"/>
|
||||||
|
<string>Untitled</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<int key="NSNibBindingConnectorVersion">2</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">573</int>
|
||||||
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBBindingConnection" key="connection">
|
||||||
|
<string key="label">selectedIndex: selection.latencyControl</string>
|
||||||
|
<reference key="source" ref="451647466"/>
|
||||||
|
<reference key="destination" ref="59237012"/>
|
||||||
|
<object class="NSNibBindingConnector" key="connector">
|
||||||
|
<reference key="NSSource" ref="451647466"/>
|
||||||
|
<reference key="NSDestination" ref="59237012"/>
|
||||||
|
<string key="NSLabel">selectedIndex: selection.latencyControl</string>
|
||||||
|
<string key="NSBinding">selectedIndex</string>
|
||||||
|
<string key="NSKeyPath">selection.latencyControl</string>
|
||||||
|
<object class="NSDictionary" key="NSOptions">
|
||||||
|
<string key="NS.key.0">NSNoSelectionPlaceholder</string>
|
||||||
|
<real value="1" key="NS.object.0"/>
|
||||||
|
</object>
|
||||||
|
<int key="NSNibBindingConnectorVersion">2</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">581</int>
|
||||||
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBOutletConnection" key="connection">
|
||||||
|
<string key="label">latencyControlField</string>
|
||||||
|
<reference key="source" ref="307402018"/>
|
||||||
|
<reference key="destination" ref="451647466"/>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">582</int>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBMutableOrderedSet" key="objectRecords">
|
<object class="IBMutableOrderedSet" key="objectRecords">
|
||||||
<object class="NSArray" key="orderedObjects">
|
<object class="NSArray" key="orderedObjects">
|
||||||
@ -1554,15 +1708,18 @@
|
|||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<reference ref="889877302"/>
|
<reference ref="889877302"/>
|
||||||
<reference ref="753545988"/>
|
<reference ref="753545988"/>
|
||||||
|
<reference ref="26015719"/>
|
||||||
|
<reference ref="244571541"/>
|
||||||
|
<reference ref="776974664"/>
|
||||||
|
<reference ref="962924480"/>
|
||||||
|
<reference ref="705215911"/>
|
||||||
|
<reference ref="610703353"/>
|
||||||
|
<reference ref="160987209"/>
|
||||||
<reference ref="801412726"/>
|
<reference ref="801412726"/>
|
||||||
<reference ref="840157770"/>
|
<reference ref="840157770"/>
|
||||||
<reference ref="538356055"/>
|
<reference ref="538356055"/>
|
||||||
<reference ref="776974664"/>
|
<reference ref="451647466"/>
|
||||||
<reference ref="610703353"/>
|
<reference ref="459566505"/>
|
||||||
<reference ref="26015719"/>
|
|
||||||
<reference ref="244571541"/>
|
|
||||||
<reference ref="962924480"/>
|
|
||||||
<reference ref="705215911"/>
|
|
||||||
</object>
|
</object>
|
||||||
<reference key="parent" ref="762265164"/>
|
<reference key="parent" ref="762265164"/>
|
||||||
</object>
|
</object>
|
||||||
@ -1962,6 +2119,78 @@
|
|||||||
<reference key="object" ref="132399775"/>
|
<reference key="object" ref="132399775"/>
|
||||||
<reference key="parent" ref="625121428"/>
|
<reference key="parent" ref="625121428"/>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">561</int>
|
||||||
|
<reference key="object" ref="160987209"/>
|
||||||
|
<object class="NSMutableArray" key="children">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="565787077"/>
|
||||||
|
</object>
|
||||||
|
<reference key="parent" ref="60314308"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">562</int>
|
||||||
|
<reference key="object" ref="565787077"/>
|
||||||
|
<reference key="parent" ref="160987209"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">574</int>
|
||||||
|
<reference key="object" ref="451647466"/>
|
||||||
|
<object class="NSMutableArray" key="children">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="970826243"/>
|
||||||
|
</object>
|
||||||
|
<reference key="parent" ref="60314308"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">575</int>
|
||||||
|
<reference key="object" ref="970826243"/>
|
||||||
|
<object class="NSMutableArray" key="children">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="790880658"/>
|
||||||
|
</object>
|
||||||
|
<reference key="parent" ref="451647466"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">576</int>
|
||||||
|
<reference key="object" ref="790880658"/>
|
||||||
|
<object class="NSMutableArray" key="children">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="195135854"/>
|
||||||
|
<reference ref="778262848"/>
|
||||||
|
<reference ref="903120255"/>
|
||||||
|
</object>
|
||||||
|
<reference key="parent" ref="970826243"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">577</int>
|
||||||
|
<reference key="object" ref="195135854"/>
|
||||||
|
<reference key="parent" ref="790880658"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">578</int>
|
||||||
|
<reference key="object" ref="778262848"/>
|
||||||
|
<reference key="parent" ref="790880658"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">579</int>
|
||||||
|
<reference key="object" ref="903120255"/>
|
||||||
|
<reference key="parent" ref="790880658"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">583</int>
|
||||||
|
<reference key="object" ref="459566505"/>
|
||||||
|
<object class="NSMutableArray" key="children">
|
||||||
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
|
<reference ref="534245320"/>
|
||||||
|
</object>
|
||||||
|
<reference key="parent" ref="60314308"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">584</int>
|
||||||
|
<reference key="object" ref="534245320"/>
|
||||||
|
<reference key="parent" ref="459566505"/>
|
||||||
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableDictionary" key="flattenedProperties">
|
<object class="NSMutableDictionary" key="flattenedProperties">
|
||||||
@ -2055,6 +2284,18 @@
|
|||||||
<string>552.IBAttributePlaceholdersKey</string>
|
<string>552.IBAttributePlaceholdersKey</string>
|
||||||
<string>552.IBPluginDependency</string>
|
<string>552.IBPluginDependency</string>
|
||||||
<string>553.IBPluginDependency</string>
|
<string>553.IBPluginDependency</string>
|
||||||
|
<string>561.IBAttributePlaceholdersKey</string>
|
||||||
|
<string>561.IBPluginDependency</string>
|
||||||
|
<string>562.IBPluginDependency</string>
|
||||||
|
<string>574.IBAttributePlaceholdersKey</string>
|
||||||
|
<string>574.IBPluginDependency</string>
|
||||||
|
<string>575.IBPluginDependency</string>
|
||||||
|
<string>576.IBPluginDependency</string>
|
||||||
|
<string>577.IBPluginDependency</string>
|
||||||
|
<string>578.IBPluginDependency</string>
|
||||||
|
<string>579.IBPluginDependency</string>
|
||||||
|
<string>583.IBPluginDependency</string>
|
||||||
|
<string>584.IBPluginDependency</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableArray" key="dict.values">
|
<object class="NSMutableArray" key="dict.values">
|
||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
@ -2062,13 +2303,13 @@
|
|||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>{{317, 387}, {611, 369}}</string>
|
<string>{{324, 171}, {611, 469}}</string>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string>{{317, 387}, {611, 369}}</string>
|
<string>{{324, 171}, {611, 469}}</string>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<boolean value="NO"/>
|
<boolean value="NO"/>
|
||||||
<boolean value="YES"/>
|
<boolean value="YES"/>
|
||||||
<string>{213, 107}</string>
|
<string>{611, 469}</string>
|
||||||
<object class="NSMutableDictionary">
|
<object class="NSMutableDictionary">
|
||||||
<string key="NS.key.0">ToolTip</string>
|
<string key="NS.key.0">ToolTip</string>
|
||||||
<object class="IBToolTipAttribute" key="NS.object.0">
|
<object class="IBToolTipAttribute" key="NS.object.0">
|
||||||
@ -2232,6 +2473,32 @@
|
|||||||
</object>
|
</object>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<object class="NSMutableDictionary">
|
||||||
|
<string key="NS.key.0">ToolTip</string>
|
||||||
|
<object class="IBToolTipAttribute" key="NS.object.0">
|
||||||
|
<string key="name">ToolTip</string>
|
||||||
|
<reference key="object" ref="160987209"/>
|
||||||
|
<string key="toolTip">Search for server names on the remote end and add them to your computer's /etc/hosts file.</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<object class="NSMutableDictionary">
|
||||||
|
<string key="NS.key.0">ToolTip</string>
|
||||||
|
<object class="IBToolTipAttribute" key="NS.object.0">
|
||||||
|
<string key="name">ToolTip</string>
|
||||||
|
<reference key="object" ref="451647466"/>
|
||||||
|
<string key="toolTip">Choose which network traffic should be routed over the VPN.</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
<object class="NSMutableDictionary" key="unlocalizedProperties">
|
||||||
@ -2250,7 +2517,7 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<nil key="sourceID"/>
|
<nil key="sourceID"/>
|
||||||
<int key="maxID">557</int>
|
<int key="maxID">584</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||||
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||||
@ -2280,6 +2547,7 @@
|
|||||||
<bool key="EncodedWithXMLCoder">YES</bool>
|
<bool key="EncodedWithXMLCoder">YES</bool>
|
||||||
<string>autoReconnectField</string>
|
<string>autoReconnectField</string>
|
||||||
<string>debugField</string>
|
<string>debugField</string>
|
||||||
|
<string>latencyControlField</string>
|
||||||
<string>logField</string>
|
<string>logField</string>
|
||||||
<string>prefsWindow</string>
|
<string>prefsWindow</string>
|
||||||
<string>routingField</string>
|
<string>routingField</string>
|
||||||
@ -2295,6 +2563,7 @@
|
|||||||
<string>id</string>
|
<string>id</string>
|
||||||
<string>id</string>
|
<string>id</string>
|
||||||
<string>id</string>
|
<string>id</string>
|
||||||
|
<string>id</string>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
exec >&2
|
exec >&2
|
||||||
redo-ifchange runpython.c
|
redo-ifchange runpython.c
|
||||||
gcc -Wall -o $3 runpython.c \
|
ARCHES=""
|
||||||
|
printf "Platforms: "
|
||||||
|
for d in /usr/libexec/gcc/darwin/*; do
|
||||||
|
PLAT=$(basename "$d")
|
||||||
|
[ "$PLAT" != "ppc64" ] || continue # fails for some reason on my Mac
|
||||||
|
ARCHES="$ARCHES -arch $PLAT"
|
||||||
|
printf "$PLAT "
|
||||||
|
done
|
||||||
|
printf "\n"
|
||||||
|
gcc $ARCHES \
|
||||||
|
-Wall -o $3 runpython.c \
|
||||||
-I/usr/include/python2.5 \
|
-I/usr/include/python2.5 \
|
||||||
-lpython2.5
|
-lpython2.5
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
exec >&2
|
exec >&2
|
||||||
find -name '*~' | xargs rm -f
|
find . -name '*~' | xargs rm -f
|
||||||
rm -rf *.app *.zip *.tar.gz
|
rm -rf *.app *.zip *.tar.gz
|
||||||
rm -f bits/runpython *.nib sources.list
|
rm -f bits/runpython *.nib sources.list
|
||||||
|
@ -3,9 +3,9 @@ redo-ifchange sources.list
|
|||||||
redo-ifchange Info.plist bits/runpython \
|
redo-ifchange Info.plist bits/runpython \
|
||||||
$(while read name newname; do echo "$name"; done <sources.list)
|
$(while read name newname; do echo "$name"; done <sources.list)
|
||||||
|
|
||||||
rm -rf "$1.app"
|
rm -rf "$2.app"
|
||||||
mkdir "$1.app" "$1.app/Contents"
|
mkdir "$2.app" "$2.app/Contents"
|
||||||
cd "$1.app/Contents"
|
cd "$2.app/Contents"
|
||||||
|
|
||||||
cp "$TOP/Info.plist" .
|
cp "$TOP/Info.plist" .
|
||||||
|
|
||||||
@ -18,11 +18,11 @@ cd "$TOP"
|
|||||||
while read name newname; do
|
while read name newname; do
|
||||||
[ -z "$name" ] && continue
|
[ -z "$name" ] && continue
|
||||||
: "${newname:=$name}"
|
: "${newname:=$name}"
|
||||||
outname=$1.app/Contents/Resources/$newname
|
outname=$2.app/Contents/Resources/$newname
|
||||||
outdir=$(dirname "$outname")
|
outdir=$(dirname "$outname")
|
||||||
[ -d "$outdir" ] || mkdir "$outdir"
|
[ -d "$outdir" ] || mkdir "$outdir"
|
||||||
cp "${name-$newname}" "$outname"
|
cp "${name-$newname}" "$outname"
|
||||||
done <sources.list
|
done <sources.list
|
||||||
|
|
||||||
cd "$1.app"
|
cd "$2.app"
|
||||||
redo-ifchange $(find . -type f)
|
redo-ifchange $(find . -type f)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
exec >&2
|
exec >&2
|
||||||
IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
redo-ifchange $1.app
|
redo-ifchange $2.app
|
||||||
tar -czf $3 $1.app/
|
tar -czf $3 $2.app/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
exec >&2
|
exec >&2
|
||||||
IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
redo-ifchange $1.app
|
redo-ifchange $2.app
|
||||||
zip -q -r $3 $1.app/
|
zip -q -r $3 $2.app/
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
redo-ifchange $1.xib
|
redo-ifchange $2.xib
|
||||||
ibtool --compile $3 $1.xib
|
ibtool --compile $3 $2.xib
|
||||||
|
@ -2,7 +2,8 @@ import sys, os, pty
|
|||||||
from AppKit import *
|
from AppKit import *
|
||||||
import my, models, askpass
|
import my, models, askpass
|
||||||
|
|
||||||
def sshuttle_args(host, auto_nets, auto_hosts, nets, debug):
|
def sshuttle_args(host, auto_nets, auto_hosts, dns, nets, debug,
|
||||||
|
no_latency_control):
|
||||||
argv = [my.bundle_path('sshuttle/sshuttle', ''), '-r', host]
|
argv = [my.bundle_path('sshuttle/sshuttle', ''), '-r', host]
|
||||||
assert(argv[0])
|
assert(argv[0])
|
||||||
if debug:
|
if debug:
|
||||||
@ -11,6 +12,10 @@ def sshuttle_args(host, auto_nets, auto_hosts, nets, debug):
|
|||||||
argv.append('--auto-nets')
|
argv.append('--auto-nets')
|
||||||
if auto_hosts:
|
if auto_hosts:
|
||||||
argv.append('--auto-hosts')
|
argv.append('--auto-hosts')
|
||||||
|
if dns:
|
||||||
|
argv.append('--dns')
|
||||||
|
if no_latency_control:
|
||||||
|
argv.append('--no-latency-control')
|
||||||
argv += nets
|
argv += nets
|
||||||
return argv
|
return argv
|
||||||
|
|
||||||
@ -73,6 +78,11 @@ class Runner:
|
|||||||
if pid == self.pid:
|
if pid == self.pid:
|
||||||
if os.WIFEXITED(code):
|
if os.WIFEXITED(code):
|
||||||
self.rv = os.WEXITSTATUS(code)
|
self.rv = os.WEXITSTATUS(code)
|
||||||
|
if self.rv == 111:
|
||||||
|
NSRunAlertPanel('Sshuttle',
|
||||||
|
'Please restart your computer to finish '
|
||||||
|
'installing Sshuttle.',
|
||||||
|
'Restart Later', None, None)
|
||||||
else:
|
else:
|
||||||
self.rv = -os.WSTOPSIG(code)
|
self.rv = -os.WSTOPSIG(code)
|
||||||
self.serverobj.setConnected_(False)
|
self.serverobj.setConnected_(False)
|
||||||
@ -82,7 +92,10 @@ class Runner:
|
|||||||
return self.rv
|
return self.rv
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
return self._try_wait(0)
|
rv = None
|
||||||
|
while rv is None:
|
||||||
|
self.gotdata(None)
|
||||||
|
rv = self._try_wait(os.WNOHANG)
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
return self._try_wait(os.WNOHANG)
|
return self._try_wait(os.WNOHANG)
|
||||||
@ -131,6 +144,7 @@ class SshuttleController(NSObject):
|
|||||||
prefsWindow = objc.IBOutlet()
|
prefsWindow = objc.IBOutlet()
|
||||||
serversController = objc.IBOutlet()
|
serversController = objc.IBOutlet()
|
||||||
logField = objc.IBOutlet()
|
logField = objc.IBOutlet()
|
||||||
|
latencyControlField = objc.IBOutlet()
|
||||||
|
|
||||||
servers = []
|
servers = []
|
||||||
conns = {}
|
conns = {}
|
||||||
@ -156,11 +170,14 @@ class SshuttleController(NSObject):
|
|||||||
manual_nets = ['0/0']
|
manual_nets = ['0/0']
|
||||||
else:
|
else:
|
||||||
manual_nets = []
|
manual_nets = []
|
||||||
|
noLatencyControl = (server.latencyControl() != models.LAT_INTERACTIVE)
|
||||||
conn = Runner(sshuttle_args(host,
|
conn = Runner(sshuttle_args(host,
|
||||||
auto_nets = nets_mode == models.NET_AUTO,
|
auto_nets = nets_mode == models.NET_AUTO,
|
||||||
auto_hosts = server.autoHosts(),
|
auto_hosts = server.autoHosts(),
|
||||||
|
dns = server.useDns(),
|
||||||
nets = manual_nets,
|
nets = manual_nets,
|
||||||
debug = self.debugField.state()),
|
debug = self.debugField.state(),
|
||||||
|
no_latency_control = noLatencyControl),
|
||||||
logfunc=logfunc, promptfunc=promptfunc,
|
logfunc=logfunc, promptfunc=promptfunc,
|
||||||
serverobj=server)
|
serverobj=server)
|
||||||
self.conns[host] = conn
|
self.conns[host] = conn
|
||||||
@ -213,6 +230,7 @@ class SshuttleController(NSObject):
|
|||||||
if len(self.servers):
|
if len(self.servers):
|
||||||
for i in self.servers:
|
for i in self.servers:
|
||||||
host = i.host()
|
host = i.host()
|
||||||
|
title = i.title()
|
||||||
want = i.wantConnect()
|
want = i.wantConnect()
|
||||||
connected = i.connected()
|
connected = i.connected()
|
||||||
numnets = len(list(i.nets()))
|
numnets = len(list(i.nets()))
|
||||||
@ -222,9 +240,9 @@ class SshuttleController(NSObject):
|
|||||||
additem('Connect %s (no routes)' % host, None, i)
|
additem('Connect %s (no routes)' % host, None, i)
|
||||||
elif want:
|
elif want:
|
||||||
any_conn = i
|
any_conn = i
|
||||||
additem('Disconnect %s' % host, self.cmd_disconnect, i)
|
additem('Disconnect %s' % title, self.cmd_disconnect, i)
|
||||||
else:
|
else:
|
||||||
additem('Connect %s' % host, self.cmd_connect, i)
|
additem('Connect %s' % title, self.cmd_connect, i)
|
||||||
if not want:
|
if not want:
|
||||||
msg = 'Off'
|
msg = 'Off'
|
||||||
elif i.error():
|
elif i.error():
|
||||||
@ -236,12 +254,6 @@ class SshuttleController(NSObject):
|
|||||||
msg = 'Connecting...'
|
msg = 'Connecting...'
|
||||||
any_inprogress = i
|
any_inprogress = i
|
||||||
addnote(' State: %s' % msg)
|
addnote(' State: %s' % msg)
|
||||||
if i.autoNets() == 0:
|
|
||||||
addnote(' Routes: All')
|
|
||||||
elif i.autoNets() == 2:
|
|
||||||
addnote(' Routes: Auto')
|
|
||||||
else:
|
|
||||||
addnote(' Routes: Custom')
|
|
||||||
else:
|
else:
|
||||||
addnote('No servers defined yet')
|
addnote('No servers defined yet')
|
||||||
|
|
||||||
@ -279,13 +291,17 @@ class SshuttleController(NSObject):
|
|||||||
net.setWidth_(width)
|
net.setWidth_(width)
|
||||||
nl.append(net)
|
nl.append(net)
|
||||||
|
|
||||||
autoNets = s.get('autoNets', 1)
|
autoNets = s.get('autoNets', models.NET_AUTO)
|
||||||
autoHosts = s.get('autoHosts', 1)
|
autoHosts = s.get('autoHosts', True)
|
||||||
|
useDns = s.get('useDns', autoNets == models.NET_ALL)
|
||||||
|
latencyControl = s.get('latencyControl', models.LAT_INTERACTIVE)
|
||||||
srv = models.SshuttleServer.alloc().init()
|
srv = models.SshuttleServer.alloc().init()
|
||||||
srv.setHost_(host)
|
srv.setHost_(host)
|
||||||
srv.setAutoNets_(autoNets)
|
srv.setAutoNets_(autoNets)
|
||||||
srv.setAutoHosts_(autoHosts)
|
srv.setAutoHosts_(autoHosts)
|
||||||
srv.setNets_(nl)
|
srv.setNets_(nl)
|
||||||
|
srv.setUseDns_(useDns)
|
||||||
|
srv.setLatencyControl_(latencyControl)
|
||||||
sl.append(srv)
|
sl.append(srv)
|
||||||
self.serversController.addObjects_(sl)
|
self.serversController.addObjects_(sl)
|
||||||
self.serversController.setSelectionIndex_(0)
|
self.serversController.setSelectionIndex_(0)
|
||||||
@ -303,7 +319,9 @@ class SshuttleController(NSObject):
|
|||||||
d = dict(host=s.host(),
|
d = dict(host=s.host(),
|
||||||
nets=nets,
|
nets=nets,
|
||||||
autoNets=s.autoNets(),
|
autoNets=s.autoNets(),
|
||||||
autoHosts=s.autoHosts())
|
autoHosts=s.autoHosts(),
|
||||||
|
useDns=s.useDns(),
|
||||||
|
latencyControl=s.latencyControl())
|
||||||
l.append(d)
|
l.append(d)
|
||||||
my.Defaults().setObject_forKey_(l, 'servers')
|
my.Defaults().setObject_forKey_(l, 'servers')
|
||||||
self.fill_menu()
|
self.fill_menu()
|
||||||
@ -315,6 +333,11 @@ class SshuttleController(NSObject):
|
|||||||
tf('Determine automatically')
|
tf('Determine automatically')
|
||||||
tf('Custom...')
|
tf('Custom...')
|
||||||
|
|
||||||
|
self.latencyControlField.removeAllItems()
|
||||||
|
tf = self.latencyControlField.addItemWithTitle_
|
||||||
|
tf('Fast transfer')
|
||||||
|
tf('Low latency')
|
||||||
|
|
||||||
# Hmm, even when I mark this as !enabled in the .nib, it still comes
|
# Hmm, even when I mark this as !enabled in the .nib, it still comes
|
||||||
# through as enabled. So let's just disable it here (since we don't
|
# through as enabled. So let's just disable it here (since we don't
|
||||||
# support this feature yet).
|
# support this feature yet).
|
||||||
|
@ -3,6 +3,7 @@ import my
|
|||||||
|
|
||||||
|
|
||||||
configchange_callback = setconnect_callback = None
|
configchange_callback = setconnect_callback = None
|
||||||
|
objc_validator = objc.signature('@@:N^@o^@')
|
||||||
|
|
||||||
|
|
||||||
def config_changed():
|
def config_changed():
|
||||||
@ -39,7 +40,7 @@ class SshuttleNet(NSObject):
|
|||||||
def setSubnet_(self, v):
|
def setSubnet_(self, v):
|
||||||
self._k_subnet = v
|
self._k_subnet = v
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateSubnet_error_(self, value, error):
|
def validateSubnet_error_(self, value, error):
|
||||||
#print 'validateSubnet!'
|
#print 'validateSubnet!'
|
||||||
return True, _validate_ip(value), error
|
return True, _validate_ip(value), error
|
||||||
@ -49,7 +50,7 @@ class SshuttleNet(NSObject):
|
|||||||
def setWidth_(self, v):
|
def setWidth_(self, v):
|
||||||
self._k_width = v
|
self._k_width = v
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateWidth_error_(self, value, error):
|
def validateWidth_error_(self, value, error):
|
||||||
#print 'validateWidth!'
|
#print 'validateWidth!'
|
||||||
return True, _validate_width(value), error
|
return True, _validate_width(value), error
|
||||||
@ -58,6 +59,9 @@ NET_ALL = 0
|
|||||||
NET_AUTO = 1
|
NET_AUTO = 1
|
||||||
NET_MANUAL = 2
|
NET_MANUAL = 2
|
||||||
|
|
||||||
|
LAT_BANDWIDTH = 0
|
||||||
|
LAT_INTERACTIVE = 1
|
||||||
|
|
||||||
class SshuttleServer(NSObject):
|
class SshuttleServer(NSObject):
|
||||||
def init(self):
|
def init(self):
|
||||||
self = super(SshuttleServer, self).init()
|
self = super(SshuttleServer, self).init()
|
||||||
@ -92,13 +96,30 @@ class SshuttleServer(NSObject):
|
|||||||
if self.autoNets() == NET_MANUAL and not len(list(self.nets())):
|
if self.autoNets() == NET_MANUAL and not len(list(self.nets())):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def title(self):
|
||||||
|
host = self.host()
|
||||||
|
if not host:
|
||||||
|
return host
|
||||||
|
an = self.autoNets()
|
||||||
|
suffix = ""
|
||||||
|
if an == NET_ALL:
|
||||||
|
suffix = " (all traffic)"
|
||||||
|
elif an == NET_MANUAL:
|
||||||
|
n = self.nets()
|
||||||
|
suffix = ' (%d subnet%s)' % (len(n), len(n)!=1 and 's' or '')
|
||||||
|
return self.host() + suffix
|
||||||
|
def setTitle_(self, v):
|
||||||
|
# title is always auto-generated
|
||||||
|
config_changed()
|
||||||
|
|
||||||
def host(self):
|
def host(self):
|
||||||
return getattr(self, '_k_host', None)
|
return getattr(self, '_k_host', None)
|
||||||
def setHost_(self, v):
|
def setHost_(self, v):
|
||||||
self._k_host = v
|
self._k_host = v
|
||||||
|
self.setTitle_(None)
|
||||||
config_changed()
|
config_changed()
|
||||||
@objc.accessor
|
@objc_validator
|
||||||
def validateHost_error_(self, value, error):
|
def validateHost_error_(self, value, error):
|
||||||
#print 'validatehost! %r %r %r' % (self, value, error)
|
#print 'validatehost! %r %r %r' % (self, value, error)
|
||||||
while value.startswith('-'):
|
while value.startswith('-'):
|
||||||
@ -109,6 +130,7 @@ class SshuttleServer(NSObject):
|
|||||||
return getattr(self, '_k_nets', [])
|
return getattr(self, '_k_nets', [])
|
||||||
def setNets_(self, v):
|
def setNets_(self, v):
|
||||||
self._k_nets = v
|
self._k_nets = v
|
||||||
|
self.setTitle_(None)
|
||||||
config_changed()
|
config_changed()
|
||||||
def netsHidden(self):
|
def netsHidden(self):
|
||||||
#print 'checking netsHidden'
|
#print 'checking netsHidden'
|
||||||
@ -122,6 +144,8 @@ class SshuttleServer(NSObject):
|
|||||||
def setAutoNets_(self, v):
|
def setAutoNets_(self, v):
|
||||||
self._k_autoNets = v
|
self._k_autoNets = v
|
||||||
self.setNetsHidden_(-1)
|
self.setNetsHidden_(-1)
|
||||||
|
self.setUseDns_(v == NET_ALL)
|
||||||
|
self.setTitle_(None)
|
||||||
config_changed()
|
config_changed()
|
||||||
|
|
||||||
def autoHosts(self):
|
def autoHosts(self):
|
||||||
@ -129,3 +153,15 @@ class SshuttleServer(NSObject):
|
|||||||
def setAutoHosts_(self, v):
|
def setAutoHosts_(self, v):
|
||||||
self._k_autoHosts = v
|
self._k_autoHosts = v
|
||||||
config_changed()
|
config_changed()
|
||||||
|
|
||||||
|
def useDns(self):
|
||||||
|
return getattr(self, '_k_useDns', False)
|
||||||
|
def setUseDns_(self, v):
|
||||||
|
self._k_useDns = v
|
||||||
|
config_changed()
|
||||||
|
|
||||||
|
def latencyControl(self):
|
||||||
|
return getattr(self, '_k_latencyControl', LAT_INTERACTIVE)
|
||||||
|
def setLatencyControl_(self, v):
|
||||||
|
self._k_latencyControl = v
|
||||||
|
config_changed()
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
redo-ifchange debug.app
|
redo-ifchange debug.app
|
||||||
exec >&2
|
exec >&2
|
||||||
./debug.app/Contents/MacOS/run
|
./debug.app/Contents/MacOS/Sshuttle
|
||||||
|
|
||||||
|
1
version/.gitattributes
vendored
Normal file
1
version/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
gitvars.pre export-subst
|
3
version/.gitignore
vendored
Normal file
3
version/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/vars
|
||||||
|
/gitvars
|
||||||
|
/_version.py
|
1
version/__init__.py
Normal file
1
version/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from _version import COMMIT, TAG, DATE
|
3
version/_version.py.do
Normal file
3
version/_version.py.do
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
redo-ifchange vars
|
||||||
|
cat vars
|
||||||
|
|
2
version/all.do
Normal file
2
version/all.do
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
redo-ifchange vars _version.py
|
||||||
|
|
3
version/clean.do
Normal file
3
version/clean.do
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
rm -f *~ .*~ *.pyc _version.py vars gitvars
|
||||||
|
|
||||||
|
|
28
version/gitvars.do
Normal file
28
version/gitvars.do
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
redo-ifchange gitvars.pre prodname
|
||||||
|
|
||||||
|
read PROD <prodname
|
||||||
|
exec >$3
|
||||||
|
|
||||||
|
# Fix each line from gitvars.pre where git may or may not have already
|
||||||
|
# substituted the variables. If someone generated a tarball with 'git archive',
|
||||||
|
# then the data will have been substituted already. If we're in a checkout of
|
||||||
|
# the git repo, then it won't, but we can just ask git to do the substitutions
|
||||||
|
# right now.
|
||||||
|
while read line; do
|
||||||
|
# Lines *may* be of the form: $Format: ... $
|
||||||
|
x=${line#\$Format:} # remove prefix
|
||||||
|
if [ "$x" != "$line" ]; then
|
||||||
|
# git didn't substitute it
|
||||||
|
redo-always # git this from the git repo
|
||||||
|
x=${x%\$} # remove trailing $
|
||||||
|
if [ "$x" = "%d" ]; then
|
||||||
|
tag=$(git describe --match="$PROD-*")
|
||||||
|
x="(tag: $tag)"
|
||||||
|
else
|
||||||
|
x=$(git log -1 --pretty=format:"$x")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "$x"
|
||||||
|
done <gitvars.pre
|
||||||
|
|
||||||
|
redo-stamp <$3
|
3
version/gitvars.pre
Normal file
3
version/gitvars.pre
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
$Format:%H$
|
||||||
|
$Format:%d$
|
||||||
|
$Format:%ci$
|
1
version/prodname
Normal file
1
version/prodname
Normal file
@ -0,0 +1 @@
|
|||||||
|
sshuttle
|
40
version/vars.do
Normal file
40
version/vars.do
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
redo-ifchange gitvars prodname
|
||||||
|
|
||||||
|
read PROD <prodname
|
||||||
|
|
||||||
|
exec <gitvars
|
||||||
|
read COMMIT
|
||||||
|
read NAMES
|
||||||
|
read DATE
|
||||||
|
|
||||||
|
# the list of names is of the form:
|
||||||
|
# (x,y,tag: $PROD-####,tag: $PROD-####,a,b)
|
||||||
|
# The entries we want are the ones starting with "tag: $PROD-" since those
|
||||||
|
# refer to the right actual git tags.
|
||||||
|
names_to_tag()
|
||||||
|
{
|
||||||
|
x=${1#\(}
|
||||||
|
x=${x%\)}
|
||||||
|
cur=
|
||||||
|
while [ "$cur" != "$x" ]; do
|
||||||
|
x=${x# }
|
||||||
|
x=${x#tag: }
|
||||||
|
cur=${x%%,*}
|
||||||
|
tagpost=${cur#$PROD-}
|
||||||
|
if [ "$cur" != "$tagpost" ]; then
|
||||||
|
echo "$tagpost"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
x=${x#*,}
|
||||||
|
done
|
||||||
|
commitpost=${COMMIT#???????}
|
||||||
|
commitpre=${COMMIT%$commitpost}
|
||||||
|
echo "unknown-$commitpre"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sTAG=$(names_to_tag "$NAMES")
|
||||||
|
|
||||||
|
echo "COMMIT='$COMMIT'"
|
||||||
|
echo "TAG='$sTAG'"
|
||||||
|
echo "DATE='${DATE%% *}'"
|
Reference in New Issue
Block a user