diff --git a/if.go b/if.go index d841023..2113288 100644 --- a/if.go +++ b/if.go @@ -52,6 +52,7 @@ func New(config Config) (ifce *Interface, err error) { // NewTAP creates a new TAP interface whose name is ifName. If ifName is empty, a // default name (tap0, tap1, ... ) will be assigned. ifName should not exceed // 16 bytes. TAP interfaces are not supported on darwin. +// ifName cannot be specified on windows, you will need ifce.Name() to use some cmds. // // Note: this function is deprecated and will be removed from the library. // Please use New() instead. @@ -61,6 +62,7 @@ func NewTAP(ifName string) (ifce *Interface, err error) { // NewTUN creates a new TUN interface whose name is ifName. If ifName is empty, a // default name (tap0, tap1, ... ) will be assigned. ifName should not exceed +// ifName cannot be specified on windows, you will need ifce.Name() to use some cmds. // // Note: this function is deprecated and will be removed from the library. // Please use New() instead. diff --git a/syscalls_windows.go b/syscalls_windows.go index 140ab88..055a351 100644 --- a/syscalls_windows.go +++ b/syscalls_windows.go @@ -7,6 +7,7 @@ package water import ( + "bytes" "errors" "net" "os" @@ -17,7 +18,8 @@ import ( var ( IfceNameNotFound = errors.New("Failed to find the name of interface.") - TapDeviceNotFound = errors.New("Failed to find the tap device in registry.") + TapDeviceNotFound = errors.New("Failed to find the tap device with specified ComponentId in registry, TAP driver may not installed.") + RegistryOpenErr = errors.New("Failed to open the adapter registry, TAP driver may not installed.") // Device Control Codes tap_win_ioctl_get_mac = tap_control_code(1, 0) tap_win_ioctl_get_version = tap_control_code(2, 0) @@ -31,6 +33,9 @@ var ( tap_ioctl_config_tun = tap_control_code(10, 0) // w32 api file_device_unknown = uint32(0x00000022) + // Driver maker specified ComponentId + // ComponentId is defined here: https://github.com/OpenVPN/tap-windows6/blob/master/version.m4#L5 + componentId = "tap0901" ) func ctl_code(device_type, function, method, access uint32) uint32 { @@ -41,39 +46,40 @@ func tap_control_code(request, method uint32) uint32 { return ctl_code(file_device_unknown, request, method, 0) } -// getdeviceid finds out a TAP device from registry, it requires privileged right. +// getdeviceid finds out a TAP device from registry, it *may* requires privileged right to prevent some weird issue. func getdeviceid() (string, error) { // TAP driver key location regkey := `SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}` - k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.ALL_ACCESS) + k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.READ) if err != nil { - return "", err + return "", RegistryOpenErr } defer k.Close() - // read all subkeys + // read all subkeys, it should not return an err here keys, err := k.ReadSubKeyNames(-1) if err != nil { return "", err } - // find the one with ComponentId == "tap0901" + // find the one matched ComponentId for _, v := range keys { - key, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey+"\\"+v, registry.ALL_ACCESS) + key, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey+"\\"+v, registry.READ) if err != nil { continue } val, _, err := key.GetStringValue("ComponentId") if err != nil { - goto next + key.Close() + continue } - if val == "tap0901" { + if val == componentId { val, _, err = key.GetStringValue("NetCfgInstanceId") if err != nil { - goto next + key.Close() + continue } key.Close() return val, nil } - next: key.Close() } return "", TapDeviceNotFound @@ -82,7 +88,7 @@ func getdeviceid() (string, error) { // openDev find and open an interface. func openDev(isTAP bool) (ifce *Interface, err error) { // ifName won't work - // find the device in registrym you need privileged right. + // find the device in registry. deviceid, err := getdeviceid() if err != nil { return nil, err @@ -135,22 +141,13 @@ func openDev(isTAP bool) (ifce *Interface, err error) { return } // find the name of tap interface(u need it to set the ip or other command) - hwaddr_equal := func(a net.HardwareAddr, b []byte) bool { - for i := 0; i < 6; i++ { - if a[i] != b[i] { - return false - } - } - return true - } - ifces, err := net.Interfaces() if err != nil { return } for _, v := range ifces { - if hwaddr_equal(v.HardwareAddr[:6], mac[:6]) { + if bytes.Equal(v.HardwareAddr[:6], mac[:6]) { ifce.name = v.Name return }