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 }