Skip to content

Commit d9fb563

Browse files
committed
ping: Do not use connected socket on macOS
1 parent a24ab73 commit d9fb563

File tree

2 files changed

+27
-23
lines changed

2 files changed

+27
-23
lines changed

ping/ping.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/sagernet/sing/common/control"
1717
E "github.com/sagernet/sing/common/exceptions"
1818
M "github.com/sagernet/sing/common/metadata"
19-
2019
"golang.org/x/net/ipv4"
2120
"golang.org/x/net/ipv6"
2221
)
@@ -59,28 +58,27 @@ func (c *Conn) isLinuxUnprivileged() bool {
5958
func (c *Conn) ReadIP(buffer *buf.Buffer) error {
6059
if c.destination.Is6() || c.isLinuxUnprivileged() {
6160
var readMsg func(b, oob []byte) (n, oobn int, addr netip.Addr, err error)
62-
switch conn := c.conn.(type) {
63-
case *net.IPConn:
61+
if ipConn, isIPConn := common.Cast[*net.IPConn](c.conn); isIPConn {
6462
readMsg = func(b, oob []byte) (n, oobn int, addr netip.Addr, err error) {
6563
var ipAddr *net.IPAddr
66-
n, oobn, _, ipAddr, err = conn.ReadMsgIP(b, oob)
64+
n, oobn, _, ipAddr, err = ipConn.ReadMsgIP(b, oob)
6765
if err == nil {
6866
addr = M.AddrFromNet(ipAddr)
6967
}
7068
return
7169
}
72-
case *net.UDPConn:
70+
} else if udpConn, isUDPConn := common.Cast[*net.UDPConn](c.conn); isUDPConn {
7371
readMsg = func(b, oob []byte) (n, oobn int, addr netip.Addr, err error) {
7472
var addrPort netip.AddrPort
75-
n, oobn, _, addrPort, err = conn.ReadMsgUDPAddrPort(b, oob)
73+
n, oobn, _, addrPort, err = udpConn.ReadMsgUDPAddrPort(b, oob)
7674
if err == nil {
7775
addr = addrPort.Addr()
7876
}
7977
return
8078
}
81-
case *UnprivilegedConn:
82-
readMsg = conn.ReadMsg
83-
default:
79+
} else if unprivilegedConn, isUnprivilegedConn := c.conn.(*UnprivilegedConn); isUnprivilegedConn {
80+
readMsg = unprivilegedConn.ReadMsg
81+
} else {
8482
return E.New("unsupported conn type: ", reflect.TypeOf(c.conn))
8583
}
8684
if !c.destination.Is6() {

ping/socket_unix.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"runtime"
1010
"syscall"
1111

12+
"github.com/sagernet/sing/common/bufio"
1213
"github.com/sagernet/sing/common/control"
1314
E "github.com/sagernet/sing/common/exceptions"
1415
M "github.com/sagernet/sing/common/metadata"
@@ -80,19 +81,24 @@ func connect(privileged bool, controlFunc control.Func, destination netip.Addr)
8081
} else {
8182
bindAddress = netip.AddrFrom16([16]byte{})
8283
}
83-
err = unix.Bind(fd, M.AddrPortToSockaddr(netip.AddrPortFrom(bindAddress, 0)))
84-
if err != nil {
85-
return nil, err
86-
}
87-
88-
err = unix.Connect(fd, M.AddrPortToSockaddr(netip.AddrPortFrom(destination, 0)))
89-
if err != nil {
90-
return nil, E.Cause(err, "connect()")
91-
}
92-
93-
conn, err := net.FileConn(file)
94-
if err != nil {
95-
return nil, err
84+
if runtime.GOOS == "darwin" {
85+
// When running in NetworkExtension on macOS, write to connected socket results in EPIPE.
86+
var packetConn net.PacketConn
87+
packetConn, err = net.FilePacketConn(file)
88+
if err != nil {
89+
return nil, err
90+
}
91+
return bufio.NewBindPacketConn(packetConn, M.SocksaddrFrom(destination, 0).UDPAddr()), nil
92+
} else {
93+
err = unix.Bind(fd, M.AddrPortToSockaddr(netip.AddrPortFrom(bindAddress, 0)))
94+
if err != nil {
95+
return nil, err
96+
}
97+
var conn net.Conn
98+
conn, err = net.FileConn(file)
99+
if err != nil {
100+
return nil, err
101+
}
102+
return conn, nil
96103
}
97-
return conn, nil
98104
}

0 commit comments

Comments
 (0)