github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/sockopt_linux.go (about)

     1  package internet
     2  
     3  import (
     4  	"net"
     5  	"syscall"
     6  
     7  	"golang.org/x/sys/unix"
     8  )
     9  
    10  const (
    11  	// For incoming connections.
    12  	TCP_FASTOPEN = 23
    13  	// For out-going connections.
    14  	TCP_FASTOPEN_CONNECT = 30
    15  )
    16  
    17  func bindAddr(fd uintptr, ip []byte, port uint32) error {
    18  	setReuseAddr(fd)
    19  	setReusePort(fd)
    20  
    21  	var sockaddr syscall.Sockaddr
    22  
    23  	switch len(ip) {
    24  	case net.IPv4len:
    25  		a4 := &syscall.SockaddrInet4{
    26  			Port: int(port),
    27  		}
    28  		copy(a4.Addr[:], ip)
    29  		sockaddr = a4
    30  	case net.IPv6len:
    31  		a6 := &syscall.SockaddrInet6{
    32  			Port: int(port),
    33  		}
    34  		copy(a6.Addr[:], ip)
    35  		sockaddr = a6
    36  	default:
    37  		return newError("unexpected length of ip")
    38  	}
    39  
    40  	return syscall.Bind(int(fd), sockaddr)
    41  }
    42  
    43  func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
    44  	if config.Mark != 0 {
    45  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
    46  			return newError("failed to set SO_MARK").Base(err)
    47  		}
    48  	}
    49  
    50  	if isTCPSocket(network) {
    51  		switch config.Tfo {
    52  		case SocketConfig_Enable:
    53  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN_CONNECT, 1); err != nil {
    54  				return newError("failed to set TCP_FASTOPEN_CONNECT=1").Base(err)
    55  			}
    56  		case SocketConfig_Disable:
    57  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN_CONNECT, 0); err != nil {
    58  				return newError("failed to set TCP_FASTOPEN_CONNECT=0").Base(err)
    59  			}
    60  		}
    61  	}
    62  
    63  	if config.Tproxy.IsEnabled() {
    64  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
    65  			return newError("failed to set IP_TRANSPARENT").Base(err)
    66  		}
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
    73  	if config.Mark != 0 {
    74  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
    75  			return newError("failed to set SO_MARK").Base(err)
    76  		}
    77  	}
    78  	if isTCPSocket(network) {
    79  		switch config.Tfo {
    80  		case SocketConfig_Enable:
    81  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, 1); err != nil {
    82  				return newError("failed to set TCP_FASTOPEN=1").Base(err)
    83  			}
    84  		case SocketConfig_Disable:
    85  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, 0); err != nil {
    86  				return newError("failed to set TCP_FASTOPEN=0").Base(err)
    87  			}
    88  		}
    89  	}
    90  
    91  	if config.Tproxy.IsEnabled() {
    92  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
    93  			return newError("failed to set IP_TRANSPARENT").Base(err)
    94  		}
    95  	}
    96  
    97  	if config.ReceiveOriginalDestAddress && isUDPSocket(network) {
    98  		err1 := syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
    99  		err2 := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
   100  		if err1 != nil && err2 != nil {
   101  			return err1
   102  		}
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  func setReuseAddr(fd uintptr) error {
   109  	if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
   110  		return newError("failed to set SO_REUSEADDR").Base(err).AtWarning()
   111  	}
   112  	return nil
   113  }
   114  
   115  func setReusePort(fd uintptr) error {
   116  	if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
   117  		return newError("failed to set SO_REUSEPORT").Base(err).AtWarning()
   118  	}
   119  	return nil
   120  }