github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/control/bind_linux.go (about) 1 package control 2 3 import ( 4 "os" 5 "syscall" 6 7 "github.com/sagernet/sing/common/atomic" 8 E "github.com/sagernet/sing/common/exceptions" 9 10 "golang.org/x/sys/unix" 11 ) 12 13 var ifIndexDisabled atomic.Bool 14 15 func bindToInterface(conn syscall.RawConn, network string, address string, finder InterfaceFinder, interfaceName string, interfaceIndex int, preferInterfaceName bool) error { 16 return Raw(conn, func(fd uintptr) error { 17 if !preferInterfaceName && !ifIndexDisabled.Load() { 18 if interfaceIndex == -1 { 19 if interfaceName == "" { 20 return os.ErrInvalid 21 } 22 var err error 23 interfaceIndex, err = finder.InterfaceIndexByName(interfaceName) 24 if err != nil { 25 return err 26 } 27 } 28 err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_BINDTOIFINDEX, interfaceIndex) 29 if err == nil { 30 return nil 31 } else if E.IsMulti(err, unix.ENOPROTOOPT, unix.EINVAL) { 32 ifIndexDisabled.Store(true) 33 } else { 34 return err 35 } 36 } 37 if interfaceName == "" { 38 return os.ErrInvalid 39 } 40 return unix.BindToDevice(int(fd), interfaceName) 41 }) 42 }