diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-02-28 17:41:30 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-03-01 01:38:30 +0100 |
commit | 1c56fb8996d9014e1b96332344f663fa201f3a5e (patch) | |
tree | dd411c7c77d655164621b5ed623d945346b2ebf7 /service | |
parent | tunnel: log the builtin go log to elog (diff) | |
download | wireguard-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')
-rw-r--r-- | service/errors.go | 1 | ||||
-rw-r--r-- | service/service_tunnel.go | 84 |
2 files changed, 74 insertions, 11 deletions
diff --git a/service/errors.go b/service/errors.go index 04f0638c..e2d17ab9 100644 --- a/service/errors.go +++ b/service/errors.go @@ -17,4 +17,5 @@ const ( ERROR_SERVER_SID_MISMATCH uint32 = 0x00000274 ERROR_NETWORK_BUSY uint32 = 0x00000036 ERROR_NO_TRACKING_SERVICE uint32 = 0x00000494 + ERROR_OBJECT_ALREADY_EXISTS uint32 = 0x00001392 ) 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() |