Skip to content

Commit

Permalink
Don't allocate socket until we need it
Browse files Browse the repository at this point in the history
Wew were trying to allocate an IPv6 socket even though we weren't using
IPv6, causing failures on systems without IPv6 support available.

This change means a number of methods on MultiListener, e.g. setsockopt,
should not be called until after the bind call.

Closes #68
  • Loading branch information
brianmay committed Jan 30, 2016
1 parent e06f024 commit ba8e948
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions sshuttle/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,21 @@ def daemon_cleanup():
class MultiListener:

def __init__(self, type=socket.SOCK_STREAM, proto=0):
self.v6 = socket.socket(socket.AF_INET6, type, proto)
self.v4 = socket.socket(socket.AF_INET, type, proto)
self.type = type
self.proto = proto
self.v6 = None
self.v4 = None
self.bind_called = False

def setsockopt(self, level, optname, value):
assert(self.bind_called)
if self.v6:
self.v6.setsockopt(level, optname, value)
if self.v4:
self.v4.setsockopt(level, optname, value)

def add_handler(self, handlers, callback, method, mux):
assert(self.bind_called)
socks = []
if self.v6:
socks.append(self.v6)
Expand All @@ -119,6 +124,7 @@ def add_handler(self, handlers, callback, method, mux):
)

def listen(self, backlog):
assert(self.bind_called)
if self.v6:
self.v6.listen(backlog)
if self.v4:
Expand All @@ -133,16 +139,23 @@ def listen(self, backlog):
raise e

def bind(self, address_v6, address_v4):
assert(not self.bind_called)
self.bind_called = True
if address_v6 and self.v6:
self.v6 = socket.socket(socket.AF_INET6, self.type, self.proto)
self.v6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.v6.bind(address_v6)
else:
self.v6 = None
if address_v4 and self.v4:
self.v4 = socket.socket(socket.AF_INET, self.type, self.proto)
self.v4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.v4.bind(address_v4)
else:
self.v4 = None

def print_listening(self, what):
assert(self.bind_called)
if self.v6:
listenip = self.v6.getsockname()
debug1('%s listening on %r.\n' % (what, listenip))
Expand Down Expand Up @@ -569,11 +582,9 @@ def main(listenip_v6, listenip_v4,
for port in ports:
debug2(' %d' % port)
tcp_listener = MultiListener()
tcp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

if required.udp:
udp_listener = MultiListener(socket.SOCK_DGRAM)
udp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
else:
udp_listener = None

Expand Down

0 comments on commit ba8e948

Please sign in to comment.