github.com/yaling888/clash@v1.53.0/component/dialer/mark_freebsd.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  type controlFn = func(network, address string, c syscall.RawConn) error
    12  
    13  func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ netip.Addr) {
    14  	dialer.Control = bindMarkToControl(mark, dialer.Control)
    15  }
    16  
    17  func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, _ string) {
    18  	lc.Control = bindMarkToControl(mark, lc.Control)
    19  }
    20  
    21  func bindMarkToControl(mark int, chain controlFn) controlFn {
    22  	return func(network, address string, c syscall.RawConn) (err error) {
    23  		defer func() {
    24  			if err == nil && chain != nil {
    25  				err = chain(network, address, c)
    26  			}
    27  		}()
    28  
    29  		addrPort, err := netip.ParseAddrPort(address)
    30  		if err == nil && !addrPort.Addr().IsGlobalUnicast() {
    31  			return
    32  		}
    33  
    34  		var innerErr error
    35  		err = c.Control(func(fd uintptr) {
    36  			innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_USER_COOKIE, mark)
    37  		})
    38  		if err == nil && innerErr != nil {
    39  			err = innerErr
    40  		}
    41  		return
    42  	}
    43  }