github.com/chwjbn/xclash@v0.2.0/component/dialer/mark_linux.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package dialer
     5  
     6  import (
     7  	"net"
     8  	"syscall"
     9  )
    10  
    11  func bindMarkToDialer(mark int, dialer *net.Dialer, _ string, _ net.IP) {
    12  	dialer.Control = bindMarkToControl(mark, dialer.Control)
    13  }
    14  
    15  func bindMarkToListenConfig(mark int, lc *net.ListenConfig, _, address 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  		ipStr, _, err := net.SplitHostPort(address)
    28  		if err == nil {
    29  			ip := net.ParseIP(ipStr)
    30  			if ip != nil && !ip.IsGlobalUnicast() {
    31  				return
    32  			}
    33  		}
    34  
    35  		return c.Control(func(fd uintptr) {
    36  			switch network {
    37  			case "tcp4", "udp4":
    38  				syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
    39  			case "tcp6", "udp6":
    40  				syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
    41  			}
    42  		})
    43  	}
    44  }