Skip to content

Commit

Permalink
Add support for OpenBSD, FreeBSD, NetBSD and add InterfaceName para…
Browse files Browse the repository at this point in the history
…meter for Windows to allow selecting between multiple `tap0901` adapters on the same system
  • Loading branch information
neilalexander committed May 9, 2018
1 parent bf1a5d0 commit 78c5d97
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 5 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Tony Lu <tonyluj@gmail.com>
ajee cai <ajee.cai@gmail.com>
yinheli <hi@yinheli.com>
Paul Querna <pquerna@apache.org>
Neil Alexander <neilalexander@users.noreply.github.com>
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ See https://github.com/songgao/packets for functions for parsing various packets
* Linux
* Windows (experimental; APIs might change)
* macOS (point-to-point TUN only)
* OpenBSD
* NetBSD
* FreeBSD

## Installation
```
Expand Down
20 changes: 20 additions & 0 deletions params_bsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// +build openbsd freebsd netbsd dragonfly

package water

// PlatformSpecificParams defines parameters in Config that are specific to
// Linux. A zero-value of such type is valid, yielding an interface
// with OS defined name.
type PlatformSpecificParams struct {
// Name is the name to be set for the interface to be created. This overrides
// the default name assigned by OS such as tap0 or tun0. A zero-value of this
// field, i.e. an empty string, indicates that the default name should be
// used.
Name string
}

func defaultPlatformSpecificParams() PlatformSpecificParams {
return PlatformSpecificParams{
Name: "/dev/tun0",
}
}
2 changes: 1 addition & 1 deletion params_others.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !linux,!darwin,!windows
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!dragonfly

package water

Expand Down
5 changes: 5 additions & 0 deletions params_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ type PlatformSpecificParams struct {
// use the default ComponentId. The default ComponentId is set to tap0901,
// the one used by OpenVPN.
ComponentID string
// Of course, you may have multiple tap0901 adapters on the system, in which
// case we need a friendlier way to identify them. In that case we can use
// the friendly name of the network adapter as set in Control Panel.
InterfaceName string
// Network is required when creating a TUN interface. The library will call
// net.ParseCIDR() to parse this string into LocalIP, RemoteNetaddr,
// RemoteNetmask. The underlying driver will need those to generate ARP
Expand All @@ -27,6 +31,7 @@ type PlatformSpecificParams struct {
func defaultPlatformSpecificParams() PlatformSpecificParams {
return PlatformSpecificParams{
ComponentID: "tap0901",
InterfaceName: "",
Network: "192.168.1.10/24",
}
}
35 changes: 35 additions & 0 deletions syscalls_bsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// +build openbsd freebsd netbsd dragonfly

package water

import (
"os"
)

func newTAP(config Config) (ifce *Interface, err error) {
if config.Name[:8] != "/dev/tap" {
panic("TUN/TAP name must be in format /dev/tunX or /dev/tapX")
}

file, err := os.OpenFile(config.Name, os.O_RDWR, 0)
if err != nil {
return nil, err
}

ifce = &Interface{isTAP: true, ReadWriteCloser: file, name: config.Name[5:]}
return
}

func newTUN(config Config) (ifce *Interface, err error) {
if config.Name[:8] != "/dev/tun" {
panic("TUN/TAP name must be in format /dev/tunX or /dev/tapX")
}

file, err := os.OpenFile(config.Name, os.O_RDWR, 0)
if err != nil {
return nil, err
}

ifce = &Interface{isTAP: false, ReadWriteCloser: file, name: config.Name[5:]}
return
}
2 changes: 1 addition & 1 deletion syscalls_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !linux,!darwin,!windows
// +build !linux,!darwin,!windows,!openbsd,!freebsd,!netbsd,!dragonfly

package water

Expand Down
27 changes: 24 additions & 3 deletions syscalls_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func tap_control_code(request, method uint32) uint32 {
}

// getdeviceid finds out a TAP device from registry, it *may* requires privileged right to prevent some weird issue.
func getdeviceid(componentID string) (deviceid string, err error) {
func getdeviceid(componentID string, interfaceName string) (deviceid string, err error) {
// TAP driver key location
regkey := `SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.READ)
Expand Down Expand Up @@ -170,12 +170,33 @@ func getdeviceid(componentID string) (deviceid string, err error) {
key.Close()
continue
}
if len(interfaceName) > 0 {
key2 := `SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\`+val+`\Connection`
k2, err := registry.OpenKey(registry.LOCAL_MACHINE, key2, registry.READ)
if err != nil {
fmt.Println("Unable to open", key2)
continue
}
defer k2.Close()
val, _, err := k2.GetStringValue("Name")
if err != nil {
fmt.Println("Unable to get Name value from", key2)
continue
}
if val != interfaceName {
continue
}
}
key.Close()
return val, nil
}
key.Close()
}
return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId(%s), TAP driver may be not installed", componentID)
if len(interfaceName) > 0 {
return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId '%s' and InterfaceName '%s', TAP driver may be not installed or you may have specified an interface name that doesn't exist", componentID)
} else {
return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId '%s', TAP driver may be not installed", componentID)
}
}

// setStatus is used to bring up or bring down the interface
Expand Down Expand Up @@ -217,7 +238,7 @@ func setTUN(fd syscall.Handle, network string) error {
// openDev find and open an interface.
func openDev(config Config) (ifce *Interface, err error) {
// find the device in registry.
deviceid, err := getdeviceid(config.PlatformSpecificParams.ComponentID)
deviceid, err := getdeviceid(config.PlatformSpecificParams.ComponentID, config.PlatformSpecificParams.InterfaceName)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 78c5d97

Please sign in to comment.