2021-09-23 09:34:58 +00:00
|
|
|
|
//go:build windows
|
2019-11-23 13:46:05 +00:00
|
|
|
|
// +build windows
|
|
|
|
|
|
2022-09-24 13:41:47 +00:00
|
|
|
|
package tun
|
2018-01-24 10:59:01 +00:00
|
|
|
|
|
2018-06-12 22:50:08 +00:00
|
|
|
|
import (
|
2019-11-22 18:34:43 +00:00
|
|
|
|
"bytes"
|
2019-07-19 21:21:30 +00:00
|
|
|
|
"errors"
|
2019-11-22 18:34:43 +00:00
|
|
|
|
"log"
|
|
|
|
|
"net"
|
|
|
|
|
|
2019-11-22 20:11:39 +00:00
|
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
2019-11-22 18:34:43 +00:00
|
|
|
|
"golang.org/x/sys/windows"
|
2018-06-12 22:50:08 +00:00
|
|
|
|
|
2019-11-22 16:43:50 +00:00
|
|
|
|
wgtun "golang.zx2c4.com/wireguard/tun"
|
2019-11-23 13:46:05 +00:00
|
|
|
|
"golang.zx2c4.com/wireguard/windows/elevate"
|
2019-11-22 18:34:43 +00:00
|
|
|
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
2018-06-12 22:50:08 +00:00
|
|
|
|
)
|
2018-01-24 10:59:01 +00:00
|
|
|
|
|
|
|
|
|
// This is to catch Windows platforms
|
|
|
|
|
|
2019-11-22 16:43:50 +00:00
|
|
|
|
// Configures the TUN adapter with the correct IPv6 address and MTU.
|
2021-05-16 19:00:45 +00:00
|
|
|
|
func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
2019-11-22 20:11:39 +00:00
|
|
|
|
if ifname == "auto" {
|
2019-11-22 20:16:24 +00:00
|
|
|
|
ifname = defaults.GetDefaults().DefaultIfName
|
2019-11-22 20:11:39 +00:00
|
|
|
|
}
|
2019-11-23 13:56:48 +00:00
|
|
|
|
return elevate.DoAsSystem(func() error {
|
|
|
|
|
var err error
|
|
|
|
|
var iface wgtun.Device
|
|
|
|
|
var guid windows.GUID
|
|
|
|
|
if guid, err = windows.GUIDFromString("{8f59971a-7872-4aa6-b2eb-061fc4e9d0a7}"); err != nil {
|
|
|
|
|
return err
|
2019-11-23 13:34:27 +00:00
|
|
|
|
}
|
2020-01-05 17:27:54 +00:00
|
|
|
|
if iface, err = wgtun.CreateTUNWithRequestedGUID(ifname, &guid, int(mtu)); err != nil {
|
2019-11-23 13:56:48 +00:00
|
|
|
|
return err
|
2019-11-22 18:34:43 +00:00
|
|
|
|
}
|
|
|
|
|
tun.iface = iface
|
2019-11-23 13:56:48 +00:00
|
|
|
|
if err = tun.setupAddress(addr); err != nil {
|
2019-11-22 18:34:43 +00:00
|
|
|
|
tun.log.Errorln("Failed to set up TUN address:", err)
|
2019-11-23 13:56:48 +00:00
|
|
|
|
return err
|
2019-11-22 18:34:43 +00:00
|
|
|
|
}
|
2019-11-23 13:56:48 +00:00
|
|
|
|
if err = tun.setupMTU(getSupportedMTU(mtu)); err != nil {
|
2019-11-22 18:34:43 +00:00
|
|
|
|
tun.log.Errorln("Failed to set up TUN MTU:", err)
|
2019-11-23 13:56:48 +00:00
|
|
|
|
return err
|
2019-11-22 18:34:43 +00:00
|
|
|
|
}
|
2020-01-05 17:27:54 +00:00
|
|
|
|
if mtu, err := iface.MTU(); err == nil {
|
2021-05-16 19:00:45 +00:00
|
|
|
|
tun.mtu = uint64(mtu)
|
2019-11-22 18:34:43 +00:00
|
|
|
|
}
|
2019-11-23 13:56:48 +00:00
|
|
|
|
return nil
|
2019-11-22 18:34:43 +00:00
|
|
|
|
})
|
2018-01-24 10:59:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-24 13:41:47 +00:00
|
|
|
|
// Sets the MTU of the TUN adapter.
|
2021-05-16 19:00:45 +00:00
|
|
|
|
func (tun *TunAdapter) setupMTU(mtu uint64) error {
|
2019-11-22 18:34:43 +00:00
|
|
|
|
if tun.iface == nil || tun.Name() == "" {
|
|
|
|
|
return errors.New("Can't configure MTU as TUN adapter is not present")
|
|
|
|
|
}
|
|
|
|
|
if intf, ok := tun.iface.(*wgtun.NativeTun); ok {
|
|
|
|
|
luid := winipcfg.LUID(intf.LUID())
|
|
|
|
|
ipfamily, err := luid.IPInterface(windows.AF_INET6)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ipfamily.NLMTU = uint32(mtu)
|
|
|
|
|
intf.ForceMTU(int(ipfamily.NLMTU))
|
|
|
|
|
ipfamily.UseAutomaticMetric = false
|
|
|
|
|
ipfamily.Metric = 0
|
|
|
|
|
ipfamily.DadTransmits = 0
|
|
|
|
|
ipfamily.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
|
|
|
|
|
|
|
|
|
|
if err := ipfamily.Set(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2018-01-25 17:44:56 +00:00
|
|
|
|
}
|
2019-11-22 18:34:43 +00:00
|
|
|
|
|
2018-01-25 17:44:56 +00:00
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-24 13:41:47 +00:00
|
|
|
|
// Sets the IPv6 address of the TUN adapter.
|
2019-03-28 00:30:25 +00:00
|
|
|
|
func (tun *TunAdapter) setupAddress(addr string) error {
|
2019-11-22 18:34:43 +00:00
|
|
|
|
if tun.iface == nil || tun.Name() == "" {
|
|
|
|
|
return errors.New("Can't configure IPv6 address as TUN adapter is not present")
|
|
|
|
|
}
|
|
|
|
|
if intf, ok := tun.iface.(*wgtun.NativeTun); ok {
|
|
|
|
|
if ipaddr, ipnet, err := net.ParseCIDR(addr); err == nil {
|
|
|
|
|
luid := winipcfg.LUID(intf.LUID())
|
|
|
|
|
addresses := append([]net.IPNet{}, net.IPNet{
|
|
|
|
|
IP: ipaddr,
|
|
|
|
|
Mask: ipnet.Mask,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
err := luid.SetIPAddressesForFamily(windows.AF_INET6, addresses)
|
|
|
|
|
if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
|
|
|
|
|
cleanupAddressesOnDisconnectedInterfaces(windows.AF_INET6, addresses)
|
|
|
|
|
err = luid.SetIPAddressesForFamily(windows.AF_INET6, addresses)
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return errors.New("unable to get NativeTUN")
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* cleanupAddressesOnDisconnectedInterfaces
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
|
|
|
|
|
*/
|
|
|
|
|
func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []net.IPNet) {
|
|
|
|
|
if len(addresses) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
includedInAddresses := func(a net.IPNet) bool {
|
|
|
|
|
// TODO: this makes the whole algorithm O(n^2). But we can't stick net.IPNet in a Go hashmap. Bummer!
|
|
|
|
|
for _, addr := range addresses {
|
|
|
|
|
ip := addr.IP
|
|
|
|
|
if ip4 := ip.To4(); ip4 != nil {
|
|
|
|
|
ip = ip4
|
|
|
|
|
}
|
|
|
|
|
mA, _ := addr.Mask.Size()
|
|
|
|
|
mB, _ := a.Mask.Size()
|
|
|
|
|
if bytes.Equal(ip, a.IP) && mA == mB {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
interfaces, err := winipcfg.GetAdaptersAddresses(family, winipcfg.GAAFlagDefault)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for _, iface := range interfaces {
|
|
|
|
|
if iface.OperStatus == winipcfg.IfOperStatusUp {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
|
|
|
|
|
ip := address.Address.IP()
|
|
|
|
|
ipnet := net.IPNet{IP: ip, Mask: net.CIDRMask(int(address.OnLinkPrefixLength), 8*len(ip))}
|
|
|
|
|
if includedInAddresses(ipnet) {
|
|
|
|
|
log.Printf("Cleaning up stale address %s from interface ‘%s’", ipnet.String(), iface.FriendlyName())
|
|
|
|
|
iface.LUID.DeleteIPAddress(ipnet)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|