mirror of
https://github.com/apernet/hysteria.git
synced 2025-04-04 13:07:39 +03:00
57 lines
1.3 KiB
Go
57 lines
1.3 KiB
Go
package outbounds
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"syscall"
|
|
)
|
|
|
|
// NewDirectOutboundBindToDevice creates a new directOutbound with the given mode,
|
|
// and binds to the given device. Only works on Linux.
|
|
func NewDirectOutboundBindToDevice(mode DirectOutboundMode, deviceName string) (PluggableOutbound, error) {
|
|
if err := verifyDeviceName(deviceName); err != nil {
|
|
return nil, err
|
|
}
|
|
d := &net.Dialer{
|
|
Timeout: defaultDialerTimeout,
|
|
Control: func(network, address string, c syscall.RawConn) error {
|
|
var errBind error
|
|
err := c.Control(func(fd uintptr) {
|
|
errBind = syscall.BindToDevice(int(fd), deviceName)
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return errBind
|
|
},
|
|
}
|
|
return &directOutbound{
|
|
Mode: mode,
|
|
Dialer4: d,
|
|
Dialer6: d,
|
|
DeviceName: deviceName,
|
|
}, nil
|
|
}
|
|
|
|
func verifyDeviceName(deviceName string) error {
|
|
if deviceName == "" {
|
|
return errors.New("device name cannot be empty")
|
|
}
|
|
_, err := net.InterfaceByName(deviceName)
|
|
return err
|
|
}
|
|
|
|
func udpConnBindToDevice(conn *net.UDPConn, deviceName string) error {
|
|
sc, err := conn.SyscallConn()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var errBind error
|
|
err = sc.Control(func(fd uintptr) {
|
|
errBind = syscall.BindToDevice(int(fd), deviceName)
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return errBind
|
|
}
|