diff options
Diffstat (limited to 'ipn/ipnlocal/peerapi_macios_ext.go')
| -rw-r--r-- | ipn/ipnlocal/peerapi_macios_ext.go | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/ipn/ipnlocal/peerapi_macios_ext.go b/ipn/ipnlocal/peerapi_macios_ext.go new file mode 100644 index 000000000..a75e18eed --- /dev/null +++ b/ipn/ipnlocal/peerapi_macios_ext.go @@ -0,0 +1,54 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin,redo ios,redo + +package ipnlocal + +import ( + "fmt" + "log" + "net" + "strings" + "syscall" + + "golang.org/x/sys/unix" + "inet.af/netaddr" + "tailscale.com/net/interfaces" +) + +func init() { + initListenConfig = initListenConfigNetworkExtension +} + +// initListenConfigNetworkExtension configures nc for listening on IP +// through the iOS/macOS Network/System Extension (Packet Tunnel +// Provider) sandbox. +func initListenConfigNetworkExtension(nc *net.ListenConfig, ip netaddr.IP, st *interfaces.State, tunIfName string) error { + tunIf, ok := st.Interface[tunIfName] + if !ok { + return fmt.Errorf("no interface with name %q", tunIfName) + } + nc.Control = func(network, address string, c syscall.RawConn) error { + var sockErr error + err := c.Control(func(fd uintptr) { + + v6 := strings.Contains(address, "]:") || strings.HasSuffix(network, "6") // hacky test for v6 + proto := unix.IPPROTO_IP + opt := unix.IP_BOUND_IF + if v6 { + proto = unix.IPPROTO_IPV6 + opt = unix.IPV6_BOUND_IF + } + + sockErr = unix.SetsockoptInt(int(fd), proto, opt, tunIf.Index) + log.Printf("peerapi: bind(%q, %q) on index %v = %v", network, address, tunIf.Index, sockErr) + }) + if err != nil { + return err + } + return sockErr + } + return nil +} |
