github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/tcp/sockopt_linux.go (about) 1 // +build linux 2 // +build !confonly 3 4 package tcp 5 6 import ( 7 "syscall" 8 9 "v2ray.com/core/common/net" 10 "v2ray.com/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 addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) 27 if err != nil { 28 newError("failed to call getsockopt").Base(err).WriteToLog() 29 return 30 } 31 ip := net.IPAddress(addr.Multiaddr[4:8]) 32 port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) 33 dest = net.TCPDestination(ip, net.Port(port)) 34 }) 35 if err != nil { 36 return net.Destination{}, newError("failed to control connection").Base(err) 37 } 38 if !dest.IsValid() { 39 return net.Destination{}, newError("failed to call getsockopt") 40 } 41 return dest, nil 42 }