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