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