github.com/xraypb/Xray-core@v1.8.1/transport/internet/tcp/sockopt_linux.go (about) 1 //go:build linux 2 // +build linux 3 4 package tcp 5 6 import ( 7 "syscall" 8 "unsafe" 9 10 "github.com/xraypb/Xray-core/common/net" 11 "github.com/xraypb/Xray-core/transport/internet/stat" 12 ) 13 14 const SO_ORIGINAL_DST = 80 15 16 func GetOriginalDestination(conn stat.Connection) (net.Destination, error) { 17 sysrawconn, f := conn.(syscall.Conn) 18 if !f { 19 return net.Destination{}, newError("unable to get syscall.Conn") 20 } 21 rawConn, err := sysrawconn.SyscallConn() 22 if err != nil { 23 return net.Destination{}, newError("failed to get sys fd").Base(err) 24 } 25 var dest net.Destination 26 err = rawConn.Control(func(fd uintptr) { 27 level := syscall.IPPROTO_IP 28 if conn.RemoteAddr().String()[0] == '[' { 29 level = syscall.IPPROTO_IPV6 30 } 31 addr, err := syscall.GetsockoptIPv6MTUInfo(int(fd), level, SO_ORIGINAL_DST) 32 if err != nil { 33 newError("failed to call getsockopt").Base(err).WriteToLog() 34 return 35 } 36 ip := (*[4]byte)(unsafe.Pointer(&addr.Addr.Flowinfo))[:4] 37 if level == syscall.IPPROTO_IPV6 { 38 ip = addr.Addr.Addr[:] 39 } 40 port := (*[2]byte)(unsafe.Pointer(&addr.Addr.Port))[:2] 41 dest = net.TCPDestination(net.IPAddress(ip), net.PortFromBytes(port)) 42 }) 43 if err != nil { 44 return net.Destination{}, newError("failed to control connection").Base(err) 45 } 46 if !dest.IsValid() { 47 return net.Destination{}, newError("failed to call getsockopt") 48 } 49 return dest, nil 50 }