github.com/igoogolx/clash@v1.19.8/component/dialer/mark_linux.go (about)

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