github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/dialer/setopt_linux.go (about)

     1  package dialer
     2  
     3  import (
     4  	"net"
     5  	"syscall"
     6  
     7  	"golang.org/x/sys/unix"
     8  )
     9  
    10  func LinuxMarkSymbol(fd int32, mark int) error {
    11  	return unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, mark)
    12  }
    13  
    14  func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
    15  	if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
    16  		return
    17  	}
    18  
    19  	var innerErr error
    20  	err = c.Control(func(fd uintptr) {
    21  		if opts.MarkSymbol != nil {
    22  			opts.MarkSymbol(int32(fd))
    23  		}
    24  
    25  		if opts.listener {
    26  			// Set up to *mem_max
    27  			_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, SocketBufferSize)
    28  			_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, SocketBufferSize)
    29  
    30  			// Set beyond *mem_max if CAP_NET_ADMIN
    31  			_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, SocketBufferSize)
    32  			_ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, SocketBufferSize)
    33  
    34  			return
    35  		}
    36  
    37  		if isTCPSocket(network) {
    38  			// https://github.com/golang/go/issues/48622
    39  			/*
    40  				TCP_KEEPIDLE=180
    41  				TCP_KEEPINTVL=15
    42  				TCP_KEEPCNT=2
    43  			*/
    44  			// _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(15))
    45  			// _ = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(180))
    46  			_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1)
    47  			// _ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0)
    48  		}
    49  
    50  		if (opts.InterfaceName == "" && opts.InterfaceIndex != 0) || opts.InterfaceName != "" {
    51  			host, _, _ := net.SplitHostPort(address)
    52  			if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
    53  				return
    54  			}
    55  		}
    56  
    57  		if opts.InterfaceName == "" && opts.InterfaceIndex != 0 {
    58  			if iface, err := net.InterfaceByIndex(opts.InterfaceIndex); err == nil {
    59  				opts.InterfaceName = iface.Name
    60  			}
    61  		}
    62  
    63  		if opts.InterfaceName != "" {
    64  			// log.Println("dialer: set socket option: SO_BINDTODEVICE", opts.InterfaceName)
    65  			if innerErr = unix.BindToDevice(int(fd), opts.InterfaceName); innerErr != nil {
    66  				return
    67  			}
    68  		}
    69  
    70  	})
    71  
    72  	if innerErr != nil {
    73  		err = innerErr
    74  	}
    75  	return
    76  }