go.mod: bump wireguard/windows, which moves to using net/netip

Updates #5162

Change-Id: If99a3f0000bce0c01bdf44da1d513f236fd7cdf8
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/5509/head
Brad Fitzpatrick 2 years ago committed by Brad Fitzpatrick
parent 185f2e4768
commit 9bd9f37d29

@ -64,7 +64,7 @@ require (
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
golang.org/x/tools v0.1.11 golang.org/x/tools v0.1.11
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478
golang.zx2c4.com/wireguard/windows v0.4.10 golang.zx2c4.com/wireguard/windows v0.5.3
gvisor.dev/gvisor v0.0.0-20220801230058-850e42eb4444 gvisor.dev/gvisor v0.0.0-20220801230058-850e42eb4444
honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83 honnef.co/go/tools v0.4.0-0.dev.0.20220404092545-59d7a2877f83
inet.af/peercred v0.0.0-20210906144145-0893ea02156a inet.af/peercred v0.0.0-20210906144145-0893ea02156a
@ -266,7 +266,7 @@ require (
github.com/yeya24/promlinter v0.1.0 // indirect github.com/yeya24/promlinter v0.1.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb // indirect golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
google.golang.org/protobuf v1.28.0 // indirect google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/ini.v1 v1.66.2 // indirect

@ -729,8 +729,6 @@ github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@ -1352,7 +1350,6 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -1449,7 +1446,6 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201109165425-215b40eba54c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201109165425-215b40eba54c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1508,8 +1504,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1636,11 +1633,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20210905140043-2ef39d47540c/go.mod h1:laHzsbfMhGSobUmruXWAyMKKHSqvIcrqZJMyHD+/3O8=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0= golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
golang.zx2c4.com/wireguard/windows v0.4.10 h1:HmjzJnb+G4NCdX+sfjsQlsxGPuYaThxRbZUZFLyR0/s= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
golang.zx2c4.com/wireguard/windows v0.4.10/go.mod h1:v7w/8FC48tTBm1IzScDVPEEb0/GjLta+T0ybpP9UWRg= golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=

@ -485,11 +485,7 @@ func (m windowsManager) getBasePrimaryResolver() (resolvers []netip.Addr, err er
} }
ipLoop: ipLoop:
for _, stdip := range ips { for _, ip := range ips {
ip, ok := netip.AddrFromSlice(stdip)
if !ok {
continue
}
ip = ip.Unmap() ip = ip.Unmap()
// Skip IPv6 site-local resolvers. These are an ancient // Skip IPv6 site-local resolvers. These are an ancient
// and obsolete IPv6 RFC, which Windows still faithfully // and obsolete IPv6 RFC, which Windows still faithfully

@ -6,7 +6,6 @@ package interfaces
import ( import (
"log" "log"
"net"
"net/netip" "net/netip"
"net/url" "net/url"
"strings" "strings"
@ -54,22 +53,21 @@ func likelyHomeRouterIPWindows() (ret netip.Addr, ok bool) {
return return
} }
unspec := net.IPv4(0, 0, 0, 0) v4unspec := netip.IPv4Unspecified()
var best *winipcfg.MibIPforwardRow2 // best (lowest metric) found so far, or nil var best *winipcfg.MibIPforwardRow2 // best (lowest metric) found so far, or nil
for i := range rs { for i := range rs {
r := &rs[i] r := &rs[i]
if r.Loopback || r.DestinationPrefix.PrefixLength != 0 || !r.DestinationPrefix.Prefix.IP().Equal(unspec) { if r.Loopback || r.DestinationPrefix.PrefixLength != 0 || r.DestinationPrefix.Prefix().Addr().Unmap() != v4unspec {
// Not a default route, so skip // Not a default route, so skip
continue continue
} }
ip, ok := netip.AddrFromSlice(r.NextHop.IP()) ip := r.NextHop.Addr().Unmap()
if !ok { if !ip.IsValid() {
// Not a valid gateway, so skip (won't happen though) // Not a valid gateway, so skip (won't happen though)
continue continue
} }
ip = ip.Unmap()
if best == nil { if best == nil {
best = r best = r

@ -7,13 +7,11 @@ package monitor
import ( import (
"context" "context"
"errors" "errors"
"net/netip"
"strings" "strings"
"sync" "sync"
"time" "time"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"tailscale.com/net/netaddr"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/types/logger" "tailscale.com/types/logger"
) )
@ -133,7 +131,7 @@ func (m *winMon) Receive() (message, error) {
// unicastAddressChanged is the callback we register with Windows to call when unicast address changes. // unicastAddressChanged is the callback we register with Windows to call when unicast address changes.
func (m *winMon) unicastAddressChanged(_ winipcfg.MibNotificationType, row *winipcfg.MibUnicastIPAddressRow) { func (m *winMon) unicastAddressChanged(_ winipcfg.MibNotificationType, row *winipcfg.MibUnicastIPAddressRow) {
what := "addr" what := "addr"
if ip, ok := netip.AddrFromSlice(row.Address.IP()); ok && tsaddr.IsTailscaleIP(ip.Unmap()) { if ip := row.Address.Addr(); ip.IsValid() && tsaddr.IsTailscaleIP(ip.Unmap()) {
what = "tsaddr" what = "tsaddr"
} }
@ -144,8 +142,8 @@ func (m *winMon) unicastAddressChanged(_ winipcfg.MibNotificationType, row *wini
// routeChanged is the callback we register with Windows to call when route changes. // routeChanged is the callback we register with Windows to call when route changes.
func (m *winMon) routeChanged(_ winipcfg.MibNotificationType, row *winipcfg.MibIPforwardRow2) { func (m *winMon) routeChanged(_ winipcfg.MibNotificationType, row *winipcfg.MibIPforwardRow2) {
what := "route" what := "route"
ipn := row.DestinationPrefix.IPNet() ip := row.DestinationPrefix.Prefix().Addr().Unmap()
if cidr, ok := netaddr.FromStdIPNet(&ipn); ok && tsaddr.IsTailscaleIP(cidr.Addr()) { if ip.IsValid() && tsaddr.IsTailscaleIP(ip) {
what = "tsroute" what = "tsroute"
} }
// start a goroutine to finish our work, to return to Windows out of this callback // start a goroutine to finish our work, to return to Windows out of this callback

@ -6,7 +6,6 @@
package router package router
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"log" "log"
@ -18,12 +17,12 @@ import (
ole "github.com/go-ole/go-ole" ole "github.com/go-ole/go-ole"
"go4.org/netipx" "go4.org/netipx"
"golang.org/x/exp/slices"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"tailscale.com/health" "tailscale.com/health"
"tailscale.com/net/interfaces" "tailscale.com/net/interfaces"
"tailscale.com/net/netaddr"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/util/multierr" "tailscale.com/util/multierr"
"tailscale.com/wgengine/winnet" "tailscale.com/wgengine/winnet"
@ -324,25 +323,23 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
// ours where the nexthop is meaningless, you're supposed to use // ours where the nexthop is meaningless, you're supposed to use
// one of the local IP addresses of the interface. Find an IPv4 // one of the local IP addresses of the interface. Find an IPv4
// and IPv6 address we can use for this purpose. // and IPv6 address we can use for this purpose.
var firstGateway4 *net.IP var firstGateway4 netip.Addr
var firstGateway6 *net.IP var firstGateway6 netip.Addr
addresses := make([]*net.IPNet, 0, len(cfg.LocalAddrs)) addresses := make([]netip.Prefix, 0, len(cfg.LocalAddrs))
for _, addr := range cfg.LocalAddrs { for _, addr := range cfg.LocalAddrs {
if (addr.Addr().Is4() && ipif4 == nil) || (addr.Addr().Is6() && ipif6 == nil) { if (addr.Addr().Is4() && ipif4 == nil) || (addr.Addr().Is6() && ipif6 == nil) {
// Can't program addresses for disabled protocol. // Can't program addresses for disabled protocol.
continue continue
} }
ipnet := netipx.PrefixIPNet(addr) addresses = append(addresses, addr)
addresses = append(addresses, ipnet) if addr.Addr().Is4() && !firstGateway4.IsValid() {
gateway := ipnet.IP firstGateway4 = addr.Addr()
if addr.Addr().Is4() && firstGateway4 == nil { } else if addr.Addr().Is6() && !firstGateway6.IsValid() {
firstGateway4 = &gateway firstGateway6 = addr.Addr()
} else if addr.Addr().Is6() && firstGateway6 == nil {
firstGateway6 = &gateway
} }
} }
var routes []winipcfg.RouteData var routes []*winipcfg.RouteData
foundDefault4 := false foundDefault4 := false
foundDefault6 := false foundDefault6 := false
for _, route := range cfg.Routes { for _, route := range cfg.Routes {
@ -351,37 +348,33 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
continue continue
} }
if route.Addr().Is6() && firstGateway6 == nil { if route.Addr().Is6() && !firstGateway6.IsValid() {
// Windows won't let us set IPv6 routes without having an // Windows won't let us set IPv6 routes without having an
// IPv6 local address set. However, when we've configured // IPv6 local address set. However, when we've configured
// a default route, we want to forcibly grab IPv6 traffic // a default route, we want to forcibly grab IPv6 traffic
// even if the v6 overlay network isn't configured. To do // even if the v6 overlay network isn't configured. To do
// that, we add a dummy local IPv6 address to serve as a // that, we add a dummy local IPv6 address to serve as a
// route source. // route source.
ipnet := &net.IPNet{tsaddr.Tailscale4To6Placeholder().AsSlice(), net.CIDRMask(128, 128)} ip := tsaddr.Tailscale4To6Placeholder()
addresses = append(addresses, ipnet) addresses = append(addresses, netip.PrefixFrom(ip, ip.BitLen()))
firstGateway6 = &ipnet.IP firstGateway6 = ip
} else if route.Addr().Is4() && firstGateway4 == nil { } else if route.Addr().Is4() && !firstGateway4.IsValid() {
// TODO: do same dummy behavior as v6? // TODO: do same dummy behavior as v6?
return errors.New("due to a Windows limitation, one cannot have interface routes without an interface address") return errors.New("due to a Windows limitation, one cannot have interface routes without an interface address")
} }
ipn := netipx.PrefixIPNet(route) var gateway netip.Addr
var gateway net.IP
if route.Addr().Is4() { if route.Addr().Is4() {
gateway = *firstGateway4 gateway = firstGateway4
} else if route.Addr().Is6() { } else if route.Addr().Is6() {
gateway = *firstGateway6 gateway = firstGateway6
} }
r := winipcfg.RouteData{ r := &winipcfg.RouteData{
Destination: net.IPNet{ Destination: route,
IP: ipn.IP.Mask(ipn.Mask),
Mask: ipn.Mask,
},
NextHop: gateway, NextHop: gateway,
Metric: 0, Metric: 0,
} }
if net.IP.Equal(r.Destination.IP, gateway) { if r.Destination.Addr().Unmap() == gateway {
// no need to add a route for the interface's // no need to add a route for the interface's
// own IP. The kernel does that for us. // own IP. The kernel does that for us.
// If we try to replace it, we'll fail to // If we try to replace it, we'll fail to
@ -393,12 +386,12 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
if route.Bits() == 0 { if route.Bits() == 0 {
foundDefault4 = true foundDefault4 = true
} }
r.NextHop = *firstGateway4 r.NextHop = firstGateway4
} else if route.Addr().Is6() { } else if route.Addr().Is6() {
if route.Bits() == 0 { if route.Bits() == 0 {
foundDefault6 = true foundDefault6 = true
} }
r.NextHop = *firstGateway6 r.NextHop = firstGateway6
} }
routes = append(routes, r) routes = append(routes, r)
} }
@ -408,18 +401,16 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
return fmt.Errorf("syncAddresses: %w", err) return fmt.Errorf("syncAddresses: %w", err)
} }
sort.Slice(routes, func(i, j int) bool { return routeLess(&routes[i], &routes[j]) }) slices.SortFunc(routes, routeDataLess)
deduplicatedRoutes := []*winipcfg.RouteData{} deduplicatedRoutes := []*winipcfg.RouteData{}
for i := 0; i < len(routes); i++ { for i := 0; i < len(routes); i++ {
// There's only one way to get to a given IP+Mask, so delete // There's only one way to get to a given IP+Mask, so delete
// all matches after the first. // all matches after the first.
if i > 0 && if i > 0 && routes[i].Destination == routes[i-1].Destination {
net.IP.Equal(routes[i].Destination.IP, routes[i-1].Destination.IP) &&
bytes.Equal(routes[i].Destination.Mask, routes[i-1].Destination.Mask) {
continue continue
} }
deduplicatedRoutes = append(deduplicatedRoutes, &routes[i]) deduplicatedRoutes = append(deduplicatedRoutes, routes[i])
} }
// Re-read interface after syncAddresses. // Re-read interface after syncAddresses.
@ -484,28 +475,6 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
return errAcc return errAcc
} }
// routeLess reports whether ri should sort before rj.
// The actual sort order doesn't appear to matter. The caller just
// wants them sorted to be able to de-dup.
func routeLess(ri, rj *winipcfg.RouteData) bool {
if v := bytes.Compare(ri.Destination.IP, rj.Destination.IP); v != 0 {
return v == -1
}
if v := bytes.Compare(ri.Destination.Mask, rj.Destination.Mask); v != 0 {
// Narrower masks first
return v == 1
}
if ri.Metric != rj.Metric {
// Lower metrics first
return ri.Metric < rj.Metric
}
if v := bytes.Compare(ri.NextHop, rj.NextHop); v != 0 {
// No nexthop before non-empty nexthop.
return v == -1
}
return false
}
// unwrapIP returns the shortest version of ip. // unwrapIP returns the shortest version of ip.
func unwrapIP(ip net.IP) net.IP { func unwrapIP(ip net.IP) net.IP {
if ip4 := ip.To4(); ip4 != nil { if ip4 := ip.To4(); ip4 != nil {
@ -521,40 +490,40 @@ func v4Mask(m net.IPMask) net.IPMask {
return m return m
} }
func netCompare(a, b net.IPNet) int { func netCompare(a, b netip.Prefix) int {
aip, bip := unwrapIP(a.IP), unwrapIP(b.IP) aip, bip := a.Addr().Unmap(), b.Addr().Unmap()
v := bytes.Compare(aip, bip) v := aip.Compare(bip)
if v != 0 { if v != 0 {
return v return v
} }
amask, bmask := a.Mask, b.Mask if a.Bits() == b.Bits() {
if len(aip) == 4 { return 0
amask = v4Mask(a.Mask)
bmask = v4Mask(b.Mask)
} }
// narrower first // narrower first
return -bytes.Compare(amask, bmask) if a.Bits() > b.Bits() {
return -1
}
return 1
} }
func sortNets(a []*net.IPNet) { func sortNets(s []netip.Prefix) {
sort.Slice(a, func(i, j int) bool { sort.Slice(s, func(i, j int) bool {
return netCompare(*a[i], *a[j]) == -1 return netCompare(s[i], s[j]) == -1
}) })
} }
// deltaNets returns the changes to turn a into b. // deltaNets returns the changes to turn a into b.
func deltaNets(a, b []*net.IPNet) (add, del []*net.IPNet) { func deltaNets(a, b []netip.Prefix) (add, del []netip.Prefix) {
add = make([]*net.IPNet, 0, len(b)) add = make([]netip.Prefix, 0, len(b))
del = make([]*net.IPNet, 0, len(a)) del = make([]netip.Prefix, 0, len(a))
sortNets(a) sortNets(a)
sortNets(b) sortNets(b)
i := 0 i := 0
j := 0 j := 0
for i < len(a) && j < len(b) { for i < len(a) && j < len(b) {
switch netCompare(*a[i], *b[j]) { switch netCompare(a[i], b[j]) {
case -1: case -1:
// a < b, delete // a < b, delete
del = append(del, a[i]) del = append(del, a[i])
@ -576,28 +545,21 @@ func deltaNets(a, b []*net.IPNet) (add, del []*net.IPNet) {
return return
} }
func isIPv6LinkLocal(in *net.IPNet) bool { func isIPv6LinkLocal(a netip.Prefix) bool {
return len(in.IP) == 16 && in.IP.IsLinkLocalUnicast() return a.Addr().Is6() && a.Addr().IsLinkLocalUnicast()
} }
// ipAdapterUnicastAddressToIPNet converts windows.IpAdapterUnicastAddress to net.IPNet. // ipAdapterUnicastAddressToPrefix converts windows.IpAdapterUnicastAddress to netip.Prefix
func ipAdapterUnicastAddressToIPNet(u *windows.IpAdapterUnicastAddress) *net.IPNet { func ipAdapterUnicastAddressToPrefix(u *windows.IpAdapterUnicastAddress) netip.Prefix {
ip := u.Address.IP() ip, _ := netip.AddrFromSlice(u.Address.IP())
w := 32 return netip.PrefixFrom(ip.Unmap(), int(u.OnLinkPrefixLength))
if ip.To4() == nil {
w = 128
}
return &net.IPNet{
IP: ip,
Mask: net.CIDRMask(int(u.OnLinkPrefixLength), w),
}
} }
// unicastIPNets returns all unicast net.IPNet for ifc interface. // unicastIPNets returns all unicast net.IPNet for ifc interface.
func unicastIPNets(ifc *winipcfg.IPAdapterAddresses) []*net.IPNet { func unicastIPNets(ifc *winipcfg.IPAdapterAddresses) []netip.Prefix {
nets := make([]*net.IPNet, 0) var nets []netip.Prefix
for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next { for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next {
nets = append(nets, ipAdapterUnicastAddressToIPNet(addr)) nets = append(nets, ipAdapterUnicastAddressToPrefix(addr))
} }
return nets return nets
} }
@ -612,13 +574,13 @@ func unicastIPNets(ifc *winipcfg.IPAdapterAddresses) []*net.IPNet {
// DNS locally or remotely and from being picked as a source address for // DNS locally or remotely and from being picked as a source address for
// outgoing packets with unspecified sources. See #4647 and // outgoing packets with unspecified sources. See #4647 and
// https://web.archive.org/web/20200912120956/https://devblogs.microsoft.com/scripting/use-powershell-to-change-ip-behavior-with-skipassource/ // https://web.archive.org/web/20200912120956/https://devblogs.microsoft.com/scripting/use-powershell-to-change-ip-behavior-with-skipassource/
func syncAddresses(ifc *winipcfg.IPAdapterAddresses, want []*net.IPNet) error { func syncAddresses(ifc *winipcfg.IPAdapterAddresses, want []netip.Prefix) error {
var erracc error var erracc error
got := unicastIPNets(ifc) got := unicastIPNets(ifc)
add, del := deltaNets(got, want) add, del := deltaNets(got, want)
ll := make([]*net.IPNet, 0) ll := make([]netip.Prefix, 0)
for _, a := range del { for _, a := range del {
// do not delete link-local addresses, and collect them for later // do not delete link-local addresses, and collect them for later
// applying SkipAsSource. // applying SkipAsSource.
@ -627,29 +589,29 @@ func syncAddresses(ifc *winipcfg.IPAdapterAddresses, want []*net.IPNet) error {
continue continue
} }
err := ifc.LUID.DeleteIPAddress(*a) err := ifc.LUID.DeleteIPAddress(a)
if err != nil { if err != nil {
erracc = fmt.Errorf("deleting IP %q: %w", *a, err) erracc = fmt.Errorf("deleting IP %q: %w", a, err)
} }
} }
for _, a := range add { for _, a := range add {
err := ifc.LUID.AddIPAddress(*a) err := ifc.LUID.AddIPAddress(a)
if err != nil { if err != nil {
erracc = fmt.Errorf("adding IP %q: %w", *a, err) erracc = fmt.Errorf("adding IP %q: %w", a, err)
} }
} }
for _, a := range ll { for _, a := range ll {
mib, err := ifc.LUID.IPAddress(a.IP) mib, err := ifc.LUID.IPAddress(a.Addr())
if err != nil { if err != nil {
erracc = fmt.Errorf("setting skip-as-source on IP %q: unable to retrieve MIB: %w", *a, err) erracc = fmt.Errorf("setting skip-as-source on IP %q: unable to retrieve MIB: %w", a, err)
continue continue
} }
if !mib.SkipAsSource { if !mib.SkipAsSource {
mib.SkipAsSource = true mib.SkipAsSource = true
if err := mib.Set(); err != nil { if err := mib.Set(); err != nil {
erracc = fmt.Errorf("setting skip-as-source on IP %q: unable to set MIB: %w", *a, err) erracc = fmt.Errorf("setting skip-as-source on IP %q: unable to set MIB: %w", a, err)
} }
} }
} }
@ -657,20 +619,27 @@ func syncAddresses(ifc *winipcfg.IPAdapterAddresses, want []*net.IPNet) error {
return erracc return erracc
} }
func routeDataLess(a, b *winipcfg.RouteData) bool {
return routeDataCompare(a, b) < 0
}
func routeDataCompare(a, b *winipcfg.RouteData) int { func routeDataCompare(a, b *winipcfg.RouteData) int {
v := bytes.Compare(a.Destination.IP, b.Destination.IP) v := a.Destination.Addr().Compare(b.Destination.Addr())
if v != 0 { if v != 0 {
return v return v
} }
// Narrower masks first // Narrower masks first
v = bytes.Compare(a.Destination.Mask, b.Destination.Mask) b1, b2 := a.Destination.Bits(), b.Destination.Bits()
if v != 0 { if b1 != b2 {
return -v if b1 > b2 {
return -1
}
return 1
} }
// No nexthop before non-empty nexthop // No nexthop before non-empty nexthop
v = bytes.Compare(a.NextHop, b.NextHop) v = a.NextHop.Compare(b.NextHop)
if v != 0 { if v != 0 {
return v return v
} }
@ -685,17 +654,11 @@ func routeDataCompare(a, b *winipcfg.RouteData) int {
return 0 return 0
} }
func sortRouteData(a []*winipcfg.RouteData) {
sort.Slice(a, func(i, j int) bool {
return routeDataCompare(a[i], a[j]) < 0
})
}
func deltaRouteData(a, b []*winipcfg.RouteData) (add, del []*winipcfg.RouteData) { func deltaRouteData(a, b []*winipcfg.RouteData) (add, del []*winipcfg.RouteData) {
add = make([]*winipcfg.RouteData, 0, len(b)) add = make([]*winipcfg.RouteData, 0, len(b))
del = make([]*winipcfg.RouteData, 0, len(a)) del = make([]*winipcfg.RouteData, 0, len(a))
sortRouteData(a) slices.SortFunc(a, routeDataLess)
sortRouteData(b) slices.SortFunc(b, routeDataLess)
i := 0 i := 0
j := 0 j := 0
@ -751,15 +714,15 @@ func getAllInterfaceRoutes(ifc *winipcfg.IPAdapterAddresses) ([]*winipcfg.RouteD
rd := make([]*winipcfg.RouteData, 0, len(routes4)+len(routes6)) rd := make([]*winipcfg.RouteData, 0, len(routes4)+len(routes6))
for _, r := range routes4 { for _, r := range routes4 {
rd = append(rd, &winipcfg.RouteData{ rd = append(rd, &winipcfg.RouteData{
Destination: r.DestinationPrefix.IPNet(), Destination: r.DestinationPrefix.Prefix(),
NextHop: r.NextHop.IP(), NextHop: r.NextHop.Addr(),
Metric: r.Metric, Metric: r.Metric,
}) })
} }
for _, r := range routes6 { for _, r := range routes6 {
rd = append(rd, &winipcfg.RouteData{ rd = append(rd, &winipcfg.RouteData{
Destination: r.DestinationPrefix.IPNet(), Destination: r.DestinationPrefix.Prefix(),
NextHop: r.NextHop.IP(), NextHop: r.NextHop.Addr(),
Metric: r.Metric, Metric: r.Metric,
}) })
} }
@ -777,8 +740,8 @@ func filterRoutes(routes []*winipcfg.RouteData, dontDelete []netip.Prefix) []*wi
} }
for _, r := range routes { for _, r := range routes {
// We don't want to touch broadcast routes that Windows adds. // We don't want to touch broadcast routes that Windows adds.
nr, ok := netaddr.FromStdIPNet(&r.Destination) nr := r.Destination
if !ok { if !nr.IsValid() {
continue continue
} }
if nr.IsSingleIP() { if nr.IsSingleIP() {
@ -789,8 +752,8 @@ func filterRoutes(routes []*winipcfg.RouteData, dontDelete []netip.Prefix) []*wi
} }
filtered := make([]*winipcfg.RouteData, 0, len(routes)) filtered := make([]*winipcfg.RouteData, 0, len(routes))
for _, r := range routes { for _, r := range routes {
rr, ok := netaddr.FromStdIPNet(&r.Destination) rr := r.Destination
if ok && ddm[rr] { if rr.IsValid() && ddm[rr] {
continue continue
} }
filtered = append(filtered, r) filtered = append(filtered, r)

@ -7,26 +7,22 @@ package router
import ( import (
"fmt" "fmt"
"math/rand" "math/rand"
"net"
"net/netip" "net/netip"
"reflect"
"strings" "strings"
"testing" "testing"
"go4.org/netipx"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
) )
func randIP() net.IP { func randIP() netip.Addr {
b := byte(rand.Intn(3)) b := byte(rand.Intn(3))
return net.IP{b, b, b, b} return netip.AddrFrom4([4]byte{b, b, b, b})
} }
func randRouteData() *winipcfg.RouteData { func randRouteData() *winipcfg.RouteData {
return &winipcfg.RouteData{ return &winipcfg.RouteData{
Destination: net.IPNet{ Destination: netip.PrefixFrom(randIP(), rand.Intn(30)+1),
IP: randIP(),
Mask: net.CIDRMask(rand.Intn(3)+1, 32),
},
NextHop: randIP(), NextHop: randIP(),
Metric: uint32(rand.Intn(3)), Metric: uint32(rand.Intn(3)),
} }
@ -34,14 +30,7 @@ func randRouteData() *winipcfg.RouteData {
func TestRouteLess(t *testing.T) { func TestRouteLess(t *testing.T) {
type D = winipcfg.RouteData type D = winipcfg.RouteData
ipnet := func(s string) net.IPNet { ipnet := netip.MustParsePrefix
ipp, err := netip.ParsePrefix(s)
if err != nil {
t.Fatalf("error parsing test data %q: %v", s, err)
}
return *netipx.PrefixIPNet(ipp)
}
tests := []struct { tests := []struct {
ri, rj *winipcfg.RouteData ri, rj *winipcfg.RouteData
want bool want bool
@ -72,76 +61,51 @@ func TestRouteLess(t *testing.T) {
want: true, want: true,
}, },
{ {
ri: &D{Destination: ipnet("1.1.0.0/16"), Metric: 1, NextHop: net.ParseIP("3.3.3.3")}, ri: &D{Destination: ipnet("1.1.0.0/16"), Metric: 1, NextHop: netip.MustParseAddr("3.3.3.3")},
rj: &D{Destination: ipnet("1.1.0.0/16"), Metric: 1, NextHop: net.ParseIP("4.4.4.4")}, rj: &D{Destination: ipnet("1.1.0.0/16"), Metric: 1, NextHop: netip.MustParseAddr("4.4.4.4")},
want: true, want: true,
}, },
} }
for i, tt := range tests { for i, tt := range tests {
got := routeLess(tt.ri, tt.rj) got := routeDataLess(tt.ri, tt.rj)
if got != tt.want { if got != tt.want {
t.Errorf("%v. less = %v; want %v", i, got, tt.want) t.Errorf("%v. less = %v; want %v", i, got, tt.want)
} }
back := routeLess(tt.rj, tt.ri) back := routeDataLess(tt.rj, tt.ri)
if back && got { if back && got {
t.Errorf("%v. less both ways", i) t.Errorf("%v. less both ways", i)
} }
} }
} }
func TestRouteLessConsistent(t *testing.T) { func TestRouteDataLessConsistent(t *testing.T) {
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
ri := randRouteData() ri := randRouteData()
rj := randRouteData() rj := randRouteData()
if routeLess(ri, rj) && routeLess(rj, ri) { if routeDataLess(ri, rj) && routeDataLess(rj, ri) {
t.Fatalf("both compare less to each other:\n\t%#v\nand\n\t%#v", ri, rj) t.Fatalf("both compare less to each other:\n\t%#v\nand\n\t%#v", ri, rj)
} }
} }
} }
func equalNetIPs(a, b []*net.IPNet) bool { func nets(cidrs ...string) (ret []netip.Prefix) {
if len(a) != len(b) {
return false
}
for i := range a {
if netCompare(*a[i], *b[i]) != 0 {
return false
}
}
return true
}
func ipnet4(ip string, bits int) *net.IPNet {
return &net.IPNet{
IP: net.ParseIP(ip),
Mask: net.CIDRMask(bits, 32),
}
}
// each cidr can end in "[4]" to mean To4 form.
func nets(cidrs ...string) (ret []*net.IPNet) {
for _, s := range cidrs { for _, s := range cidrs {
to4 := strings.HasSuffix(s, "[4]") ret = append(ret, netip.MustParsePrefix(s))
if to4 {
s = strings.TrimSuffix(s, "[4]")
} }
ip, ipNet, err := net.ParseCIDR(s) return
if err != nil {
panic(fmt.Sprintf("Bogus CIDR %q in test", s))
}
if to4 {
ip = ip.To4()
} }
ipNet.IP = ip
ret = append(ret, ipNet) func nilIfEmpty[E any](s []E) []E {
if len(s) == 0 {
return nil
} }
return return s
} }
func TestDeltaNets(t *testing.T) { func TestDeltaNets(t *testing.T) {
tests := []struct { tests := []struct {
a, b []*net.IPNet a, b []netip.Prefix
wantAdd, wantDel []*net.IPNet wantAdd, wantDel []netip.Prefix
}{ }{
{ {
a: nets("1.2.3.4/24", "1.2.3.4/31", "1.2.3.3/32", "10.0.1.1/32", "100.0.1.1/32"), a: nets("1.2.3.4/24", "1.2.3.4/31", "1.2.3.3/32", "10.0.1.1/32", "100.0.1.1/32"),
@ -161,30 +125,16 @@ func TestDeltaNets(t *testing.T) {
}, },
{ {
a: nets("100.84.36.11/32", "fe80::99d0:ec2d:b2e7:536b/64"), a: nets("100.84.36.11/32", "fe80::99d0:ec2d:b2e7:536b/64"),
b: nets("100.84.36.11/32[4]"), b: nets("100.84.36.11/32"),
wantDel: nets("fe80::99d0:ec2d:b2e7:536b/64"), wantDel: nets("fe80::99d0:ec2d:b2e7:536b/64"),
}, },
{
a: []*net.IPNet{
{
IP: net.ParseIP("1.2.3.4"),
Mask: net.IPMask{0xff, 0xff, 0xff, 0xff},
},
},
b: []*net.IPNet{
{
IP: net.ParseIP("1.2.3.4"),
Mask: net.IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
},
},
},
} }
for i, tt := range tests { for i, tt := range tests {
add, del := deltaNets(tt.a, tt.b) add, del := deltaNets(tt.a, tt.b)
if !equalNetIPs(add, tt.wantAdd) { if !reflect.DeepEqual(nilIfEmpty(add), nilIfEmpty(tt.wantAdd)) {
t.Errorf("[%d] add:\n got: %v\n want: %v\n", i, add, tt.wantAdd) t.Errorf("[%d] add:\n got: %v\n want: %v\n", i, add, tt.wantAdd)
} }
if !equalNetIPs(del, tt.wantDel) { if !reflect.DeepEqual(nilIfEmpty(del), nilIfEmpty(tt.wantDel)) {
t.Errorf("[%d] del:\n got: %v\n want: %v\n", i, del, tt.wantDel) t.Errorf("[%d] del:\n got: %v\n want: %v\n", i, del, tt.wantDel)
} }
} }
@ -210,35 +160,40 @@ func equalRouteDatas(a, b []*winipcfg.RouteData) bool {
return true return true
} }
func ipnet4(ip string, bits int) netip.Prefix {
return netip.PrefixFrom(netip.MustParseAddr(ip), bits)
}
func TestFilterRoutes(t *testing.T) { func TestFilterRoutes(t *testing.T) {
var h0 net.IP var h0 netip.Addr
in := []*winipcfg.RouteData{ in := []*winipcfg.RouteData{
// LinkLocal and Loopback routes. // LinkLocal and Loopback routes.
{*ipnet4("169.254.0.0", 16), h0, 1}, {ipnet4("169.254.0.0", 16), h0, 1},
{*ipnet4("169.254.255.255", 32), h0, 1}, {ipnet4("169.254.255.255", 32), h0, 1},
{*ipnet4("127.0.0.0", 8), h0, 1}, {ipnet4("127.0.0.0", 8), h0, 1},
{*ipnet4("127.255.255.255", 32), h0, 1}, {ipnet4("127.255.255.255", 32), h0, 1},
// Local LAN routes. // Local LAN routes.
{*ipnet4("192.168.0.0", 24), h0, 1}, {ipnet4("192.168.0.0", 24), h0, 1},
{*ipnet4("192.168.0.255", 32), h0, 1}, {ipnet4("192.168.0.255", 32), h0, 1},
{*ipnet4("192.168.1.0", 25), h0, 1}, {ipnet4("192.168.1.0", 25), h0, 1},
{*ipnet4("192.168.1.127", 32), h0, 1}, {ipnet4("192.168.1.127", 32), h0, 1},
// Some random other route. // Some random other route.
{*ipnet4("192.168.2.23", 32), h0, 1}, {ipnet4("192.168.2.23", 32), h0, 1},
// Our own tailscale address. // Our own tailscale address.
{*ipnet4("100.100.100.100", 32), h0, 1}, {ipnet4("100.100.100.100", 32), h0, 1},
// Other tailscale addresses. // Other tailscale addresses.
{*ipnet4("100.100.100.101", 32), h0, 1}, {ipnet4("100.100.100.101", 32), h0, 1},
{*ipnet4("100.100.100.102", 32), h0, 1}, {ipnet4("100.100.100.102", 32), h0, 1},
} }
want := []*winipcfg.RouteData{ want := []*winipcfg.RouteData{
{*ipnet4("169.254.0.0", 16), h0, 1}, {ipnet4("169.254.0.0", 16), h0, 1},
{*ipnet4("127.0.0.0", 8), h0, 1}, {ipnet4("127.0.0.0", 8), h0, 1},
{*ipnet4("192.168.0.0", 24), h0, 1}, {ipnet4("192.168.0.0", 24), h0, 1},
{*ipnet4("192.168.1.0", 25), h0, 1}, {ipnet4("192.168.1.0", 25), h0, 1},
{*ipnet4("192.168.2.23", 32), h0, 1}, {ipnet4("192.168.2.23", 32), h0, 1},
{*ipnet4("100.100.100.101", 32), h0, 1}, {ipnet4("100.100.100.101", 32), h0, 1},
{*ipnet4("100.100.100.102", 32), h0, 1}, {ipnet4("100.100.100.102", 32), h0, 1},
} }
got := filterRoutes(in, mustCIDRs("100.100.100.100/32")) got := filterRoutes(in, mustCIDRs("100.100.100.100/32"))
@ -248,29 +203,29 @@ func TestFilterRoutes(t *testing.T) {
} }
func TestDeltaRouteData(t *testing.T) { func TestDeltaRouteData(t *testing.T) {
var h0 net.IP var h0 netip.Addr
h1 := net.ParseIP("99.99.99.99") h1 := netip.MustParseAddr("99.99.99.99")
h2 := net.ParseIP("99.99.9.99") h2 := netip.MustParseAddr("99.99.9.99")
a := []*winipcfg.RouteData{ a := []*winipcfg.RouteData{
{*ipnet4("1.2.3.4", 32), h0, 1}, {ipnet4("1.2.3.4", 32), h0, 1},
{*ipnet4("1.2.3.4", 24), h1, 2}, {ipnet4("1.2.3.4", 24), h1, 2},
{*ipnet4("1.2.3.4", 24), h2, 1}, {ipnet4("1.2.3.4", 24), h2, 1},
{*ipnet4("1.2.3.5", 32), h0, 1}, {ipnet4("1.2.3.5", 32), h0, 1},
} }
b := []*winipcfg.RouteData{ b := []*winipcfg.RouteData{
{*ipnet4("1.2.3.5", 32), h0, 1}, {ipnet4("1.2.3.5", 32), h0, 1},
{*ipnet4("1.2.3.4", 24), h1, 2}, {ipnet4("1.2.3.4", 24), h1, 2},
{*ipnet4("1.2.3.4", 24), h2, 2}, {ipnet4("1.2.3.4", 24), h2, 2},
} }
add, del := deltaRouteData(a, b) add, del := deltaRouteData(a, b)
wantAdd := []*winipcfg.RouteData{ wantAdd := []*winipcfg.RouteData{
{*ipnet4("1.2.3.4", 24), h2, 2}, {ipnet4("1.2.3.4", 24), h2, 2},
} }
wantDel := []*winipcfg.RouteData{ wantDel := []*winipcfg.RouteData{
{*ipnet4("1.2.3.4", 32), h0, 1}, {ipnet4("1.2.3.4", 32), h0, 1},
{*ipnet4("1.2.3.4", 24), h2, 1}, {ipnet4("1.2.3.4", 24), h2, 1},
} }
if !equalRouteDatas(add, wantAdd) { if !equalRouteDatas(add, wantAdd) {

Loading…
Cancel
Save