github.com/yaling888/clash@v1.53.0/component/dialer/mark_linux.go (about)

     1  package dialer
     2  
     3  import (
     4  	"net"
     5  	"net/netip"
     6  	"syscall"
     7  
     8  	"golang.org/x/sys/unix"
     9  )
    10  
    11  func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ netip.Addr) {
    12  	dialer.Control = bindMarkToControl(mark, dialer.Control)
    13  }
    14  
    15  func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, _ string) {
    16  	lc.Control = bindMarkToControl(mark, lc.Control)
    17  }
    18  
    19  func bindMarkToControl(mark int, chain controlFn) controlFn {
    20  	return func(network, address string, c syscall.RawConn) (err error) {
    21  		defer func() {
    22  			if err == nil && chain != nil {
    23  				err = chain(network, address, c)
    24  			}
    25  		}()
    26  
    27  		addrPort, err := netip.ParseAddrPort(address)
    28  		if err == nil && !addrPort.Addr().IsGlobalUnicast() {
    29  			return
    30  		}
    31  
    32  		var innerErr error
    33  		err = c.Control(func(fd uintptr) {
    34  			innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, mark)
    35  		})
    36  		if err == nil && innerErr != nil {
    37  			err = innerErr
    38  		}
    39  		return
    40  	}
    41  }