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  }