bind_darwin.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package dialer
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "syscall"
  7. "github.com/metacubex/mihomo/component/iface"
  8. "golang.org/x/sys/unix"
  9. )
  10. func bindControl(ifaceIdx int) controlFn {
  11. return func(ctx context.Context, network, address string, c syscall.RawConn) (err error) {
  12. addrPort, err := netip.ParseAddrPort(address)
  13. if err == nil && !addrPort.Addr().IsGlobalUnicast() {
  14. return
  15. }
  16. var innerErr error
  17. err = c.Control(func(fd uintptr) {
  18. switch network {
  19. case "tcp4", "udp4":
  20. innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx)
  21. case "tcp6", "udp6":
  22. innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx)
  23. }
  24. })
  25. if innerErr != nil {
  26. err = innerErr
  27. }
  28. return
  29. }
  30. }
  31. func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
  32. ifaceObj, err := iface.ResolveInterface(ifaceName)
  33. if err != nil {
  34. return err
  35. }
  36. addControlToDialer(dialer, bindControl(ifaceObj.Index))
  37. return nil
  38. }
  39. func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
  40. ifaceObj, err := iface.ResolveInterface(ifaceName)
  41. if err != nil {
  42. return "", err
  43. }
  44. addControlToListenConfig(lc, bindControl(ifaceObj.Index))
  45. return address, nil
  46. }
  47. func ParseNetwork(network string, addr netip.Addr) string {
  48. return network
  49. }