Skip to content

Commit ba8e948

Browse files
committed
Don't allocate socket until we need it
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
1 parent e06f024 commit ba8e948

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

sshuttle/client.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,21 @@ def daemon_cleanup():
9595
class MultiListener:
9696

9797
def __init__(self, type=socket.SOCK_STREAM, proto=0):
98-
self.v6 = socket.socket(socket.AF_INET6, type, proto)
99-
self.v4 = socket.socket(socket.AF_INET, type, proto)
98+
self.type = type
99+
self.proto = proto
100+
self.v6 = None
101+
self.v4 = None
102+
self.bind_called = False
100103

101104
def setsockopt(self, level, optname, value):
105+
assert(self.bind_called)
102106
if self.v6:
103107
self.v6.setsockopt(level, optname, value)
104108
if self.v4:
105109
self.v4.setsockopt(level, optname, value)
106110

107111
def add_handler(self, handlers, callback, method, mux):
112+
assert(self.bind_called)
108113
socks = []
109114
if self.v6:
110115
socks.append(self.v6)
@@ -119,6 +124,7 @@ def add_handler(self, handlers, callback, method, mux):
119124
)
120125

121126
def listen(self, backlog):
127+
assert(self.bind_called)
122128
if self.v6:
123129
self.v6.listen(backlog)
124130
if self.v4:
@@ -133,16 +139,23 @@ def listen(self, backlog):
133139
raise e
134140

135141
def bind(self, address_v6, address_v4):
142+
assert(not self.bind_called)
143+
self.bind_called = True
136144
if address_v6 and self.v6:
145+
self.v6 = socket.socket(socket.AF_INET6, self.type, self.proto)
146+
self.v6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
137147
self.v6.bind(address_v6)
138148
else:
139149
self.v6 = None
140150
if address_v4 and self.v4:
151+
self.v4 = socket.socket(socket.AF_INET, self.type, self.proto)
152+
self.v4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
141153
self.v4.bind(address_v4)
142154
else:
143155
self.v4 = None
144156

145157
def print_listening(self, what):
158+
assert(self.bind_called)
146159
if self.v6:
147160
listenip = self.v6.getsockname()
148161
debug1('%s listening on %r.\n' % (what, listenip))
@@ -569,11 +582,9 @@ def main(listenip_v6, listenip_v4,
569582
for port in ports:
570583
debug2(' %d' % port)
571584
tcp_listener = MultiListener()
572-
tcp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
573585

574586
if required.udp:
575587
udp_listener = MultiListener(socket.SOCK_DGRAM)
576-
udp_listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
577588
else:
578589
udp_listener = None
579590

0 commit comments

Comments
 (0)