github.com/v2fly/v2ray-core/v4@v4.45.2/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 // nolint: golint,stylecheck
    13  	// For out-going connections.
    14  	TCP_FASTOPEN_CONNECT = 30 // nolint: golint,stylecheck
    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  		if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
    63  			if config.TcpKeepAliveInterval > 0 {
    64  				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
    65  					return newError("failed to set TCP_KEEPINTVL", err)
    66  				}
    67  			}
    68  			if config.TcpKeepAliveIdle > 0 {
    69  				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
    70  					return newError("failed to set TCP_KEEPIDLE", err)
    71  				}
    72  			}
    73  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
    74  				return newError("failed to set SO_KEEPALIVE", err)
    75  			}
    76  		}
    77  	}
    78  
    79  	if config.Tproxy.IsEnabled() {
    80  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
    81  			return newError("failed to set IP_TRANSPARENT").Base(err)
    82  		}
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
    89  	if config.Mark != 0 {
    90  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
    91  			return newError("failed to set SO_MARK").Base(err)
    92  		}
    93  	}
    94  	if isTCPSocket(network) {
    95  		switch config.Tfo {
    96  		case SocketConfig_Enable:
    97  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, int(config.TfoQueueLength)); err != nil {
    98  				return newError("failed to set TCP_FASTOPEN=", config.TfoQueueLength).Base(err)
    99  			}
   100  		case SocketConfig_Disable:
   101  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, TCP_FASTOPEN, 0); err != nil {
   102  				return newError("failed to set TCP_FASTOPEN=0").Base(err)
   103  			}
   104  		}
   105  
   106  		if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
   107  			if config.TcpKeepAliveInterval > 0 {
   108  				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
   109  					return newError("failed to set TCP_KEEPINTVL", err)
   110  				}
   111  			}
   112  			if config.TcpKeepAliveIdle > 0 {
   113  				if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
   114  					return newError("failed to set TCP_KEEPIDLE", err)
   115  				}
   116  			}
   117  			if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
   118  				return newError("failed to set SO_KEEPALIVE", err)
   119  			}
   120  		}
   121  	}
   122  
   123  	if config.Tproxy.IsEnabled() {
   124  		if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
   125  			return newError("failed to set IP_TRANSPARENT").Base(err)
   126  		}
   127  	}
   128  
   129  	if config.ReceiveOriginalDestAddress && isUDPSocket(network) {
   130  		err1 := syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
   131  		err2 := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
   132  		if err1 != nil && err2 != nil {
   133  			return err1
   134  		}
   135  	}
   136  
   137  	return nil
   138  }
   139  
   140  func setReuseAddr(fd uintptr) error {
   141  	if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
   142  		return newError("failed to set SO_REUSEADDR").Base(err).AtWarning()
   143  	}
   144  	return nil
   145  }
   146  
   147  func setReusePort(fd uintptr) error {
   148  	if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
   149  		return newError("failed to set SO_REUSEPORT").Base(err).AtWarning()
   150  	}
   151  	return nil
   152  }