diff --git a/params_darwin.go b/params_darwin.go index 5e6a5d6..f33a07a 100644 --- a/params_darwin.go +++ b/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 diff --git a/syscalls_darwin.go b/syscalls_darwin.go index e59ea72..0b27349 100644 --- a/syscalls_darwin.go +++ b/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