浏览代码

macOS: Allow to specify a name for the TUN interface (#79)

* macOS: Allow to specify a name for the TUN interface

* Update syscalls_darwin.go

Co-Authored-By: Song Gao <[email protected]>

* Add missing imports

* Update syscalls_darwin.go

Co-authored-by: Song Gao <[email protected]>
eycorsican 5 年之前
父节点
当前提交
2b4b6d7c09
共有 2 个文件被更改,包括 20 次插入3 次删除
  1. 4 2
      params_darwin.go
  2. 16 1
      syscalls_darwin.go

+ 4 - 2
params_darwin.go

@@ -17,9 +17,11 @@ const (
 // Currently it is not possible to set the interface name in macOS.
 type PlatformSpecificParams struct {
 	// Name is the name for the interface to be used.
-	// e.g. "tap0"
-	// Only valid if using TunTapOSXDriver.
+	//
+	// For TunTapOSXDriver, it should be something like "tap0".
+	// For SystemDriver, the name should match `utun[0-9]+`, e.g. utun233
 	Name string
+
 	// Driver should be set if an alternative driver is desired
 	// e.g. TunTapOSXDriver
 	Driver MacOSDriverProvider

+ 16 - 1
syscalls_darwin.go

@@ -4,7 +4,9 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"math"
 	"os"
+	"strconv"
 	"strings"
 	"sync"
 	"syscall"
@@ -75,6 +77,19 @@ func openDevSystem(config Config) (ifce *Interface, err error) {
 	if config.DeviceType != TUN {
 		return nil, errors.New("only tun is implemented for SystemDriver, use TunTapOSXDriver for tap")
 	}
+
+	ifIndex := -1
+	if config.Name != "" {
+		const utunPrefix = "utun"
+		if !strings.HasPrefix(config.Name, utunPrefix) {
+			return nil, fmt.Errorf("Interface name must be utun[0-9]+")
+		}
+		ifIndex, err = strconv.Atoi(config.Name[len(utunPrefix):])
+		if err != nil || ifIndex < 0 || ifIndex > math.MaxUint32-1 {
+			return nil, fmt.Errorf("Interface name must be utun[0-9]+")
+		}
+	}
+
 	var fd int
 	// Supposed to be socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), but ...
 	//
@@ -106,7 +121,7 @@ func openDevSystem(config Config) (ifce *Interface, err error) {
 		ssSysaddr: 2,
 
 		scID:   ctlInfo.ctlID,
-		scUnit: 0,
+		scUnit: uint32(ifIndex) + 1,
 	})
 	if _, _, errno := syscall.RawSyscall(syscall.SYS_CONNECT, uintptr(fd), uintptr(addrP), uintptr(sockaddrCtlSize)); errno != 0 {
 		err = errno