-
Notifications
You must be signed in to change notification settings - Fork 47
/
protect_unix.go
43 lines (38 loc) · 1.04 KB
/
protect_unix.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//go:build (go1.19 && unix) || (!go1.19 && (linux || darwin))
package control
import (
"syscall"
E "github.com/sagernet/sing/common/exceptions"
)
func sendAncillaryFileDescriptors(protectPath string, fileDescriptors []int) error {
socket, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
if err != nil {
return E.Cause(err, "open protect socket")
}
defer syscall.Close(socket)
err = syscall.Connect(socket, &syscall.SockaddrUnix{Name: protectPath})
if err != nil {
return E.Cause(err, "connect protect path")
}
oob := syscall.UnixRights(fileDescriptors...)
dummy := []byte{1}
err = syscall.Sendmsg(socket, dummy, oob, nil, 0)
if err != nil {
return err
}
n, err := syscall.Read(socket, dummy)
if err != nil {
return err
}
if n != 1 {
return E.New("failed to protect fd")
}
return nil
}
func ProtectPath(protectPath string) Func {
return func(network, address string, conn syscall.RawConn) error {
return Raw(conn, func(fd uintptr) error {
return sendAncillaryFileDescriptors(protectPath, []int{int(fd)})
})
}
}