github.com/xraypb/xray-core@v1.6.6/transport/internet/sockopt_darwin.go (about) 1 package internet 2 3 import ( 4 "github.com/xraypb/xray-core/common/net" 5 "golang.org/x/sys/unix" 6 "os" 7 "syscall" 8 "unsafe" 9 ) 10 11 const ( 12 // TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections. 13 TCP_FASTOPEN_SERVER = 0x01 14 // TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections. 15 TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck 16 // syscall.TCP_KEEPINTVL is missing on some darwin architectures. 17 sysTCP_KEEPINTVL = 0x101 // nolint: revive,stylecheck 18 ) 19 20 const ( 21 PfOut = 2 22 IOCOut = 0x40000000 23 IOCIn = 0x80000000 24 IOCInOut = IOCIn | IOCOut 25 IOCPARMMask = 0x1FFF 26 LEN = 4*16 + 4*4 + 4*1 27 // #define _IOC(inout,group,num,len) (inout | ((len & IOCPARMMask) << 16) | ((group) << 8) | (num)) 28 // #define _IOWR(g,n,t) _IOC(IOCInOut, (g), (n), sizeof(t)) 29 // #define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook) 30 DIOCNATLOOK = IOCInOut | ((LEN & IOCPARMMask) << 16) | ('D' << 8) | 23 31 ) 32 33 // OriginalDst uses ioctl to read original destination from /dev/pf 34 func OriginalDst(la, ra net.Addr) (net.IP, int, error) { 35 f, err := os.Open("/dev/pf") 36 if err != nil { 37 return net.IP{}, -1, newError("failed to open device /dev/pf").Base(err) 38 } 39 defer f.Close() 40 fd := f.Fd() 41 nl := struct { // struct pfioc_natlook 42 saddr, daddr, rsaddr, rdaddr [16]byte 43 sxport, dxport, rsxport, rdxport [4]byte 44 af, proto, protoVariant, direction uint8 45 }{ 46 af: syscall.AF_INET, 47 proto: syscall.IPPROTO_TCP, 48 direction: PfOut, 49 } 50 var raIP, laIP net.IP 51 var raPort, laPort int 52 switch la.(type) { 53 case *net.TCPAddr: 54 raIP = ra.(*net.TCPAddr).IP 55 laIP = la.(*net.TCPAddr).IP 56 raPort = ra.(*net.TCPAddr).Port 57 laPort = la.(*net.TCPAddr).Port 58 case *net.UDPAddr: 59 raIP = ra.(*net.UDPAddr).IP 60 laIP = la.(*net.UDPAddr).IP 61 raPort = ra.(*net.UDPAddr).Port 62 laPort = la.(*net.UDPAddr).Port 63 } 64 if raIP.To4() != nil { 65 if laIP.IsUnspecified() { 66 laIP = net.ParseIP("127.0.0.1") 67 } 68 copy(nl.saddr[:net.IPv4len], raIP.To4()) 69 copy(nl.daddr[:net.IPv4len], laIP.To4()) 70 } 71 if raIP.To16() != nil && raIP.To4() == nil { 72 if laIP.IsUnspecified() { 73 laIP = net.ParseIP("::1") 74 } 75 copy(nl.saddr[:], raIP) 76 copy(nl.daddr[:], laIP) 77 } 78 nl.sxport[0], nl.sxport[1] = byte(raPort>>8), byte(raPort) 79 nl.dxport[0], nl.dxport[1] = byte(laPort>>8), byte(laPort) 80 if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, DIOCNATLOOK, uintptr(unsafe.Pointer(&nl))); errno != 0 { 81 return net.IP{}, -1, os.NewSyscallError("ioctl", err) 82 } 83 84 odPort := nl.rdxport 85 var odIP net.IP 86 switch nl.af { 87 case syscall.AF_INET: 88 odIP = make(net.IP, net.IPv4len) 89 copy(odIP, nl.rdaddr[:net.IPv4len]) 90 case syscall.AF_INET6: 91 odIP = make(net.IP, net.IPv6len) 92 copy(odIP, nl.rdaddr[:]) 93 } 94 return odIP, int(net.PortFromBytes(odPort[:2])), nil 95 } 96 97 func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { 98 if isTCPSocket(network) { 99 tfo := config.ParseTFOValue() 100 if tfo > 0 { 101 tfo = TCP_FASTOPEN_CLIENT 102 } 103 if tfo >= 0 { 104 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil { 105 return err 106 } 107 } 108 109 if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { 110 if config.TcpKeepAliveIdle > 0 { 111 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil { 112 return newError("failed to set TCP_KEEPINTVL", err) 113 } 114 } 115 if config.TcpKeepAliveInterval > 0 { 116 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil { 117 return newError("failed to set TCP_KEEPIDLE", err) 118 } 119 } 120 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { 121 return newError("failed to set SO_KEEPALIVE", err) 122 } 123 } else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 { 124 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 0); err != nil { 125 return newError("failed to unset SO_KEEPALIVE", err) 126 } 127 } 128 } 129 130 return nil 131 } 132 133 func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error { 134 if isTCPSocket(network) { 135 tfo := config.ParseTFOValue() 136 if tfo > 0 { 137 tfo = TCP_FASTOPEN_SERVER 138 } 139 if tfo >= 0 { 140 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, tfo); err != nil { 141 return err 142 } 143 } 144 if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 { 145 if config.TcpKeepAliveIdle > 0 { 146 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveInterval)); err != nil { 147 return newError("failed to set TCP_KEEPINTVL", err) 148 } 149 } 150 if config.TcpKeepAliveInterval > 0 { 151 if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, sysTCP_KEEPINTVL, int(config.TcpKeepAliveIdle)); err != nil { 152 return newError("failed to set TCP_KEEPIDLE", err) 153 } 154 } 155 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { 156 return newError("failed to set SO_KEEPALIVE", err) 157 } 158 } else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 { 159 if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 0); err != nil { 160 return newError("failed to unset SO_KEEPALIVE", err) 161 } 162 } 163 } 164 165 return nil 166 } 167 168 func bindAddr(fd uintptr, address []byte, port uint32) error { 169 return nil 170 } 171 172 func setReuseAddr(fd uintptr) error { 173 return nil 174 } 175 176 func setReusePort(fd uintptr) error { 177 return nil 178 }