github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/redir/redir_linux.go (about)

     1  package redir
     2  
     3  import (
     4  	"encoding/binary"
     5  	"net"
     6  	"net/netip"
     7  	"os"
     8  	"syscall"
     9  
    10  	"github.com/sagernet/sing/common"
    11  	"github.com/sagernet/sing/common/control"
    12  	M "github.com/sagernet/sing/common/metadata"
    13  )
    14  
    15  func GetOriginalDestination(conn net.Conn) (destination netip.AddrPort, err error) {
    16  	syscallConn, ok := common.Cast[syscall.Conn](conn)
    17  	if !ok {
    18  		return netip.AddrPort{}, os.ErrInvalid
    19  	}
    20  	err = control.Conn(syscallConn, func(fd uintptr) error {
    21  		const SO_ORIGINAL_DST = 80
    22  		if conn.RemoteAddr().(*net.TCPAddr).IP.To4() != nil {
    23  			raw, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
    24  			if err != nil {
    25  				return err
    26  			}
    27  			destination = netip.AddrPortFrom(M.AddrFromIP(raw.Multiaddr[4:8]), uint16(raw.Multiaddr[2])<<8+uint16(raw.Multiaddr[3]))
    28  		} else {
    29  			raw, err := syscall.GetsockoptIPv6MTUInfo(int(fd), syscall.IPPROTO_IPV6, SO_ORIGINAL_DST)
    30  			if err != nil {
    31  				return err
    32  			}
    33  			var port [2]byte
    34  			binary.BigEndian.PutUint16(port[:], raw.Addr.Port)
    35  			destination = netip.AddrPortFrom(M.AddrFromIP(raw.Addr.Addr[:]), binary.LittleEndian.Uint16(port[:]))
    36  		}
    37  		return nil
    38  	})
    39  	return
    40  }