Skip to content

Commit b896a4b

Browse files
committed
Remove references to legacy PyXAPI socket_ext for recvmsg
socket.recvmsg has been in Python since version 3.3 and we don't support anything older then 3.6 the server side.
1 parent fca9bd6 commit b896a4b

File tree

5 files changed

+54
-166
lines changed

5 files changed

+54
-166
lines changed

docs/requirements.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ Linux with TPROXY method
4040
Supports:
4141

4242
* IPv4 TCP
43-
* IPv4 UDP (requires ``recvmsg`` - see below)
44-
* IPv6 DNS (requires ``recvmsg`` - see below)
43+
* IPv4 UDP
44+
* IPv6 DNS
4545
* IPv6 TCP
46-
* IPv6 UDP (requires ``recvmsg`` - see below)
47-
* IPv6 DNS (requires ``recvmsg`` - see below)
46+
* IPv6 UDP
47+
* IPv6 DNS
4848

4949

5050
MacOS / FreeBSD / OpenBSD / pfSense

sshuttle/client.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,7 @@
2222
except ImportError:
2323
getpwnam = None
2424

25-
try:
26-
# try getting recvmsg from python
27-
import socket as pythonsocket
28-
getattr(pythonsocket.socket, "recvmsg")
29-
socket = pythonsocket
30-
except AttributeError:
31-
# try getting recvmsg from socket_ext library
32-
try:
33-
import socket_ext
34-
getattr(socket_ext.socket, "recvmsg")
35-
socket = socket_ext
36-
except ImportError:
37-
import socket
25+
import socket
3826

3927
_extra_fd = os.open(os.devnull, os.O_RDONLY)
4028

sshuttle/methods/ipfw.py

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,26 @@
44
from sshuttle.helpers import log, debug1, debug2, debug3, \
55
Fatal, family_to_string, get_env, which
66

7-
recvmsg = None
8-
try:
9-
# try getting recvmsg from python
10-
import socket as pythonsocket
11-
getattr(pythonsocket.socket, "recvmsg")
12-
socket = pythonsocket
13-
recvmsg = "python"
14-
except AttributeError:
15-
# try getting recvmsg from socket_ext library
16-
try:
17-
import socket_ext
18-
getattr(socket_ext.socket, "recvmsg")
19-
socket = socket_ext
20-
recvmsg = "socket_ext"
21-
except ImportError:
22-
import socket
7+
import socket
238

249
IP_BINDANY = 24
2510
IP_RECVDSTADDR = 7
2611
SOL_IPV6 = 41
2712
IPV6_RECVDSTADDR = 74
2813

29-
if recvmsg == "python":
30-
def recv_udp(listener, bufsize):
31-
debug3('Accept UDP python using recvmsg.')
32-
data, ancdata, _, srcip = listener.recvmsg(4096,
33-
socket.CMSG_SPACE(4))
34-
dstip = None
35-
for cmsg_level, cmsg_type, cmsg_data in ancdata:
36-
if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVDSTADDR:
37-
port = 53
38-
ip = socket.inet_ntop(socket.AF_INET, cmsg_data[0:4])
39-
dstip = (ip, port)
40-
break
41-
return (srcip, dstip, data)
42-
elif recvmsg == "socket_ext":
43-
def recv_udp(listener, bufsize):
44-
debug3('Accept UDP using socket_ext recvmsg.')
45-
srcip, data, adata, _ = listener.recvmsg((bufsize,),
46-
socket.CMSG_SPACE(4))
47-
dstip = None
48-
for a in adata:
49-
if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_RECVDSTADDR:
50-
port = 53
51-
ip = socket.inet_ntop(socket.AF_INET, a.cmsg_data[0:4])
52-
dstip = (ip, port)
53-
break
54-
return (srcip, dstip, data[0])
55-
else:
56-
def recv_udp(listener, bufsize):
57-
debug3('Accept UDP using recvfrom.')
58-
data, srcip = listener.recvfrom(bufsize)
59-
return (srcip, None, data)
14+
15+
def recv_udp(listener, bufsize):
16+
debug3('Accept UDP python using recvmsg.')
17+
data, ancdata, _, srcip = listener.recvmsg(4096,
18+
socket.CMSG_SPACE(4))
19+
dstip = None
20+
for cmsg_level, cmsg_type, cmsg_data in ancdata:
21+
if cmsg_level == socket.SOL_IP and cmsg_type == IP_RECVDSTADDR:
22+
port = 53
23+
ip = socket.inet_ntop(socket.AF_INET, cmsg_data[0:4])
24+
dstip = (ip, port)
25+
break
26+
return (srcip, dstip, data)
6027

6128

6229
def ipfw_rule_exists(n):

sshuttle/methods/tproxy.py

Lines changed: 34 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,7 @@
55
from sshuttle.methods import BaseMethod
66
from sshuttle.helpers import debug1, debug2, debug3, Fatal, which
77

8-
recvmsg = None
9-
try:
10-
# try getting recvmsg from python
11-
import socket as pythonsocket
12-
getattr(pythonsocket.socket, "recvmsg")
13-
socket = pythonsocket
14-
recvmsg = "python"
15-
except AttributeError:
16-
# try getting recvmsg from socket_ext library
17-
try:
18-
import socket_ext
19-
getattr(socket_ext.socket, "recvmsg")
20-
socket = socket_ext
21-
recvmsg = "socket_ext"
22-
except ImportError:
23-
import socket
8+
import socket
249

2510

2611
IP_TRANSPARENT = 19
@@ -30,88 +15,46 @@
3015
IPV6_ORIGDSTADDR = 74
3116
IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
3217

33-
if recvmsg == "python":
34-
def recv_udp(listener, bufsize):
35-
debug3('Accept UDP python using recvmsg.')
36-
data, ancdata, _, srcip = listener.recvmsg(
37-
4096, socket.CMSG_SPACE(24))
38-
dstip = None
39-
family = None
40-
for cmsg_level, cmsg_type, cmsg_data in ancdata:
41-
if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR:
42-
family, port = struct.unpack('=HH', cmsg_data[0:4])
43-
port = socket.htons(port)
44-
if family == socket.AF_INET:
45-
start = 4
46-
length = 4
47-
else:
48-
raise Fatal("Unsupported socket type '%s'" % family)
49-
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
50-
dstip = (ip, port)
51-
break
52-
elif cmsg_level == SOL_IPV6 and cmsg_type == IPV6_ORIGDSTADDR:
53-
family, port = struct.unpack('=HH', cmsg_data[0:4])
54-
port = socket.htons(port)
55-
if family == socket.AF_INET6:
56-
start = 8
57-
length = 16
58-
else:
59-
raise Fatal("Unsupported socket type '%s'" % family)
60-
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
61-
dstip = (ip, port)
62-
break
63-
return (srcip, dstip, data)
64-
elif recvmsg == "socket_ext":
65-
def recv_udp(listener, bufsize):
66-
debug3('Accept UDP using socket_ext recvmsg.')
67-
srcip, data, adata, _ = listener.recvmsg(
68-
(bufsize,), socket.CMSG_SPACE(24))
69-
dstip = None
70-
family = None
71-
for a in adata:
72-
if a.cmsg_level == socket.SOL_IP and a.cmsg_type == IP_ORIGDSTADDR:
73-
family, port = struct.unpack('=HH', a.cmsg_data[0:4])
74-
port = socket.htons(port)
75-
if family == socket.AF_INET:
76-
start = 4
77-
length = 4
78-
else:
79-
raise Fatal("Unsupported socket type '%s'" % family)
80-
ip = socket.inet_ntop(
81-
family, a.cmsg_data[start:start + length])
82-
dstip = (ip, port)
83-
break
84-
elif a.cmsg_level == SOL_IPV6 and a.cmsg_type == IPV6_ORIGDSTADDR:
85-
family, port = struct.unpack('=HH', a.cmsg_data[0:4])
86-
port = socket.htons(port)
87-
if family == socket.AF_INET6:
88-
start = 8
89-
length = 16
90-
else:
91-
raise Fatal("Unsupported socket type '%s'" % family)
92-
ip = socket.inet_ntop(
93-
family, a.cmsg_data[start:start + length])
94-
dstip = (ip, port)
95-
break
96-
return (srcip, dstip, data[0])
97-
else:
98-
def recv_udp(listener, bufsize):
99-
debug3('Accept UDP using recvfrom.')
100-
data, srcip = listener.recvfrom(bufsize)
101-
return (srcip, None, data)
18+
19+
def recv_udp(listener, bufsize):
20+
debug3('Accept UDP python using recvmsg.')
21+
data, ancdata, _, srcip = listener.recvmsg(
22+
4096, socket.CMSG_SPACE(24))
23+
dstip = None
24+
family = None
25+
for cmsg_level, cmsg_type, cmsg_data in ancdata:
26+
if cmsg_level == socket.SOL_IP and cmsg_type == IP_ORIGDSTADDR:
27+
family, port = struct.unpack('=HH', cmsg_data[0:4])
28+
port = socket.htons(port)
29+
if family == socket.AF_INET:
30+
start = 4
31+
length = 4
32+
else:
33+
raise Fatal("Unsupported socket type '%s'" % family)
34+
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
35+
dstip = (ip, port)
36+
break
37+
elif cmsg_level == SOL_IPV6 and cmsg_type == IPV6_ORIGDSTADDR:
38+
family, port = struct.unpack('=HH', cmsg_data[0:4])
39+
port = socket.htons(port)
40+
if family == socket.AF_INET6:
41+
start = 8
42+
length = 16
43+
else:
44+
raise Fatal("Unsupported socket type '%s'" % family)
45+
ip = socket.inet_ntop(family, cmsg_data[start:start + length])
46+
dstip = (ip, port)
47+
break
48+
return (srcip, dstip, data)
10249

10350

10451
class Method(BaseMethod):
10552

10653
def get_supported_features(self):
10754
result = super(Method, self).get_supported_features()
10855
result.ipv6 = True
109-
if recvmsg is None:
110-
result.udp = False
111-
result.dns = False
112-
else:
113-
result.udp = True
114-
result.dns = True
56+
result.udp = True
57+
result.dns = True
11558
return result
11659

11760
def get_tcp_dstip(self, sock):

tests/client/test_methods_tproxy.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,14 @@
66
from sshuttle.methods import get_method
77

88

9-
@patch("sshuttle.methods.tproxy.recvmsg")
10-
def test_get_supported_features_recvmsg(mock_recvmsg):
9+
def test_get_supported_features():
1110
method = get_method('tproxy')
1211
features = method.get_supported_features()
1312
assert features.ipv6
1413
assert features.udp
1514
assert features.dns
1615

1716

18-
@patch("sshuttle.methods.tproxy.recvmsg", None)
19-
def test_get_supported_features_norecvmsg():
20-
method = get_method('tproxy')
21-
features = method.get_supported_features()
22-
assert features.ipv6
23-
assert not features.udp
24-
assert not features.dns
25-
26-
2717
def test_get_tcp_dstip():
2818
sock = Mock()
2919
sock.getsockname.return_value = ('127.0.0.1', 1024)

0 commit comments

Comments
 (0)