aboutsummaryrefslogtreecommitdiffstatshomepage
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
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.
-rw-r--r--conf/config.go15
-rw-r--r--conf/parser.go8
-rw-r--r--service/errors.go1
-rw-r--r--service/service_tunnel.go84
m---------wireguard-go0
5 files changed, 95 insertions, 13 deletions
diff --git a/conf/config.go b/conf/config.go
index a321bc0c..d802ec61 100644
--- a/conf/config.go
+++ b/conf/config.go
@@ -64,6 +64,21 @@ func (r *IPCidr) String() string {
return fmt.Sprintf("%s/%d", r.IP.String(), r.Cidr)
}
+func (r *IPCidr) Bits() uint8 {
+ if r.IP.To4() != nil {
+ return 32
+ } else {
+ return 128
+ }
+}
+
+func (r *IPCidr) IPNet() net.IPNet {
+ return net.IPNet{
+ IP: r.IP,
+ Mask: net.CIDRMask(int(r.Cidr), int(r.Bits())),
+ }
+}
+
func (e *Endpoint) String() string {
if strings.IndexByte(e.Host, ':') > 0 {
return fmt.Sprintf("[%s]:%d", e.Host, e.Port)
diff --git a/conf/parser.go b/conf/parser.go
index 6a397a9d..48cf88b6 100644
--- a/conf/parser.go
+++ b/conf/parser.go
@@ -40,17 +40,21 @@ func parseIPCidr(s string) (ipcidr *IPCidr, err error) {
if addr == nil {
return
}
+ maybeV4 := addr.To4()
+ if maybeV4 != nil {
+ addr = maybeV4
+ }
if len(cidrStr) > 0 {
err = &ParseError{"Invalid network prefix length", s}
cidr, err = strconv.Atoi(cidrStr)
if err != nil || cidr < 0 || cidr > 128 {
return
}
- if cidr > 32 && addr.To4() != nil {
+ if cidr > 32 && maybeV4 != nil {
return
}
} else {
- if addr.To4() != nil {
+ if maybeV4 != nil {
cidr = 32
} else {
cidr = 128
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()
diff --git a/wireguard-go b/wireguard-go
-Subproject 88ff67fb6f55456e46877b71aa5d33060468f95
+Subproject d435be35cac49af9367b2005d831d55e570c4b1