aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service/service_tunnel.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-02-28 17:41:30 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2019-03-01 01:38:30 +0100
commit1c56fb8996d9014e1b96332344f663fa201f3a5e (patch)
treedd411c7c77d655164621b5ed623d945346b2ebf7 /service/service_tunnel.go
parenttunnel: log the builtin go log to elog (diff)
downloadwireguard-windows-1c56fb8996d9014e1b96332344f663fa201f3a5e.tar.xz
wireguard-windows-1c56fb8996d9014e1b96332344f663fa201f3a5e.zip
tunnel: make winipcfg sort of work
The duplicate route thing is silly, and we currently don't do DNS or the fancy socket routing. But this is a step in the right direction, perhaps.
Diffstat (limited to 'service/service_tunnel.go')
-rw-r--r--service/service_tunnel.go84
1 files changed, 73 insertions, 11 deletions
diff --git a/service/service_tunnel.go b/service/service_tunnel.go
index 37e0de4c..f600aa36 100644
--- a/service/service_tunnel.go
+++ b/service/service_tunnel.go
@@ -7,15 +7,17 @@ package service
import (
"bufio"
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/winipcfg"
"log"
"net"
+ "os"
"strings"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
"golang.org/x/sys/windows/svc/eventlog"
- "golang.zx2c4.com/winipcfg"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/service/tun"
)
@@ -79,9 +81,9 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
logger.Info.Println("Starting wireguard-go version", WireGuardGoVersion)
logger.Debug.Println("Debug log enabled")
- tun, err := tun.CreateTUN(conf.Name)
+ wintun, err := tun.CreateTUN(conf.Name)
if err == nil {
- realInterfaceName, err2 := tun.Name()
+ realInterfaceName, err2 := wintun.Name()
if err2 == nil {
conf.Name = realInterfaceName
}
@@ -92,7 +94,7 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- device := NewDevice(tun, logger)
+ device := NewDevice(wintun, logger)
device.Up()
logger.Info.Println("Device started")
@@ -127,17 +129,77 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
ipcSetOperation(device, bufio.NewReader(strings.NewReader(uapiConf)))
- //TODO: configure addresses, routes, and DNS with winipcfg
- iface, err := winipcfg.InterfaceFromFriendlyName(conf.Name)
+ guid := wintun.(*tun.NativeTun).GUID()
+ iface, err := winipcfg.InterfaceFromGUID(&guid)
+ if err != nil {
+ logger.Error.Println("Unable to find Wintun device:", err)
+ changes <- svc.Status{State: svc.StopPending}
+ exitCode = ERROR_NETWORK_BUSY
+ device.Close()
+ return
+ }
+
+ routeCount := len(conf.Interface.Addresses)
+ for _, peer := range conf.Peers {
+ routeCount += len(peer.AllowedIPs)
+ }
+ routes := make([]winipcfg.RouteData, routeCount)
+ routeCount = 0
+ var firstGateway *net.IP
+ addresses := make([]*net.IPNet, len(conf.Interface.Addresses))
+ for i, addr := range conf.Interface.Addresses {
+ ipnet := addr.IPNet()
+ addresses[i] = &ipnet
+ gateway := ipnet.IP.Mask(ipnet.Mask)
+ if firstGateway == nil {
+ firstGateway = &gateway
+ }
+ routes[routeCount] = winipcfg.RouteData{
+ Destination: net.IPNet{
+ IP: gateway,
+ Mask: ipnet.Mask,
+ },
+ NextHop: gateway,
+ Metric: 1,
+ }
+ routeCount++
+ }
+
+ for _, peer := range conf.Peers {
+ for _, allowedip := range peer.AllowedIPs {
+ routes[routeCount] = winipcfg.RouteData{
+ Destination: allowedip.IPNet(),
+ NextHop: *firstGateway,
+ Metric: 1,
+ }
+ routeCount++
+ }
+ }
+
+ err = iface.SetAddresses(addresses)
if err == nil {
- a := make([]*net.IPNet, len(conf.Interface.Addresses))
- for i, addr := range conf.Interface.Addresses {
- a[i] = &net.IPNet{addr.IP, net.CIDRMask(int(addr.Cidr), len(addr.IP))}
+ err = iface.FlushRoutes()
+ if err == nil {
+ for _, route := range routes {
+ err = iface.AddRoute(&route, true)
+
+ //TODO: Ignoring duplicate errors like this maybe isn't very reasonable.
+ // instead we should make sure we're not adding duplicates ourselves when
+ // inserting the gateway routes.
+ if syserr, ok := err.(*os.SyscallError); ok {
+ if syserr.Err == windows.Errno(ERROR_OBJECT_ALREADY_EXISTS) {
+ err = nil
+ }
+ }
+
+ if err != nil {
+ break
+ }
+ }
}
- err = iface.SetAddresses(a)
}
if err != nil {
- logger.Error.Println("Unable to setup interface addresses:", err)
+ logger.Error.Println("Unable to set interface addresses and routes:", err)
changes <- svc.Status{State: svc.StopPending}
exitCode = ERROR_NETWORK_BUSY
device.Close()