Compare commits

...

1 Commits

Author SHA1 Message Date
Andrew Dunham
284809da13 net/tsaddr: add MapViaAddr function
Change-Id: I45122fd65c7133fb3d2cbc7eec6f1de89d768ef4
Signed-off-by: Andrew Dunham <andrew@tailscale.com>
2022-11-08 16:59:17 -05:00
2 changed files with 47 additions and 0 deletions

View File

@@ -309,3 +309,17 @@ func MapVia(siteID uint32, v4 netip.Prefix) (via netip.Prefix, err error) {
copy(a[12:], ip4a[:])
return netip.PrefixFrom(netip.AddrFrom16(a), v4.Bits()+64+32), nil
}
// MapViaAddr returns an IPv6 "via" address for an IPv4 address in a given siteID.
func MapViaAddr(siteID uint32, v4 netip.Addr) (netip.Addr, error) {
if !v4.Is4() {
return netip.Addr{}, errors.New("want IPv4 address with a site ID")
}
viaRange16 := TailscaleViaRange().Addr().As16()
var a [16]byte
copy(a[:], viaRange16[:8])
binary.BigEndian.PutUint32(a[8:], siteID)
ip4a := v4.As4()
copy(a[12:], ip4a[:])
return netip.AddrFrom16(a), nil
}

View File

@@ -105,3 +105,36 @@ func TestUnmapVia(t *testing.T) {
}
}
}
func TestMapViaAddr(t *testing.T) {
tests := []struct {
ip string
site uint32
want string
}{
{"1.2.3.4", 0, "fd7a:115c:a1e0:b1a::102:304"},
{"1.2.3.4", 7, "fd7a:115c:a1e0:b1a:0:7:102:304"},
}
for _, tt := range tests {
got, err := MapViaAddr(tt.site, netip.MustParseAddr(tt.ip))
if err != nil {
t.Errorf("for %q @ %d: error: %v", tt.ip, tt.site, err)
continue
}
if got.String() != tt.want {
t.Errorf("for %q @ %d: got %q, want %q", tt.ip, tt.site, got.String(), tt.want)
}
}
t.Run("Error", func(t *testing.T) {
addr, err := MapViaAddr(9, netip.MustParseAddr("::1"))
want := "want IPv4 address with a site ID"
if err == nil || err.Error() != want {
t.Errorf("got err=%v; want %q", err, want)
}
if addr.IsValid() {
t.Errorf("expected invalid Addr")
}
})
}