summaryrefslogtreecommitdiffhomepage
path: root/ipn/ipnlocal/peerapi_macios_ext.go
diff options
context:
space:
mode:
Diffstat (limited to 'ipn/ipnlocal/peerapi_macios_ext.go')
-rw-r--r--ipn/ipnlocal/peerapi_macios_ext.go54
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
+}