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 }