Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>main
parent
5cb9999be3
commit
463728a885
@ -0,0 +1,63 @@ |
||||
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package netconv provides utilities to convert between netaddr and netip.
|
||||
// To convert from a net.IP, use the netaddr/netip API.
|
||||
package netconv |
||||
|
||||
import ( |
||||
"net/netip" |
||||
|
||||
"inet.af/netaddr" |
||||
) |
||||
|
||||
// AsIP returns a as a netaddr.IP.
|
||||
func AsIP(a netip.Addr) netaddr.IP { |
||||
switch { |
||||
case a.Is4(): |
||||
return netaddr.IPFrom4(a.As4()) |
||||
case a.Is6(): |
||||
return netaddr.IPv6Raw(a.As16()).WithZone(a.Zone()) |
||||
} |
||||
return netaddr.IP{} |
||||
} |
||||
|
||||
// AsAddr returns a as a netip.IP.
|
||||
func AsAddr(a netaddr.IP) netip.Addr { |
||||
switch { |
||||
case a.Is4(): |
||||
return netip.AddrFrom4(a.As4()) |
||||
case a.Is6(): |
||||
return netip.AddrFrom16(a.As16()).WithZone(a.Zone()) |
||||
} |
||||
return netip.Addr{} |
||||
} |
||||
|
||||
// AsIPPrefix returns a as a netaddr.IPPrefix.
|
||||
// If a has Bits of -1, indicating an invalid bits,
|
||||
// the returned IPPrefix will have Bits of 255.
|
||||
// AsIPPrefix and AsPrefix do not
|
||||
// round trip for invalid Bits values.
|
||||
func AsIPPrefix(a netip.Prefix) netaddr.IPPrefix { |
||||
return netaddr.IPPrefixFrom(AsIP(a.Addr()), uint8(a.Bits())) |
||||
} |
||||
|
||||
// AsPrefix returns a as a netip.Prefix.
|
||||
// If a has an invalid Bits value,
|
||||
// the returned Prefix will have Bits of -1.
|
||||
// AsIPPrefix and AsPrefix do not
|
||||
// round trip for invalid Bits values.
|
||||
func AsPrefix(a netaddr.IPPrefix) netip.Prefix { |
||||
return netip.PrefixFrom(AsAddr(a.IP()), int(a.Bits())) |
||||
} |
||||
|
||||
// AsIPPort returns a as a netaddr.IPPort.
|
||||
func AsIPPort(a netip.AddrPort) netaddr.IPPort { |
||||
return netaddr.IPPortFrom(AsIP(a.Addr()), a.Port()) |
||||
} |
||||
|
||||
// AsAddrPort returns a as a netip.AddrPort.
|
||||
func AsAddrPort(a netaddr.IPPort) netip.AddrPort { |
||||
return netip.AddrPortFrom(AsAddr(a.IP()), a.Port()) |
||||
} |
||||
@ -0,0 +1,76 @@ |
||||
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package netconv |
||||
|
||||
import ( |
||||
"net/netip" |
||||
"testing" |
||||
|
||||
qt "github.com/frankban/quicktest" |
||||
"inet.af/netaddr" |
||||
) |
||||
|
||||
func TestAddr(t *testing.T) { |
||||
c := qt.New(t) |
||||
|
||||
c.Assert(netip.Addr{}, qt.Equals, AsAddr(netaddr.IP{})) |
||||
c.Assert(netaddr.IP{}, qt.Equals, AsIP(netip.Addr{})) |
||||
|
||||
// Cover IPv4, IPv6, 4in6, and zones.
|
||||
addrStrs := []string{ |
||||
"0.0.0.0", |
||||
"123.45.67.89", |
||||
"::", |
||||
"fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", |
||||
"fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", |
||||
"::ffff:192.0.2.128", |
||||
"::ffff:192.0.2.128%eth0", |
||||
} |
||||
for _, s := range addrStrs { |
||||
ip := netaddr.MustParseIP(s) |
||||
addr := netip.MustParseAddr(s) |
||||
c.Assert(addr, qt.Equals, AsAddr(ip)) |
||||
c.Assert(ip, qt.Equals, AsIP(addr)) |
||||
} |
||||
} |
||||
|
||||
func TestAddrPort(t *testing.T) { |
||||
c := qt.New(t) |
||||
|
||||
c.Assert(netip.AddrPort{}, qt.Equals, AsAddrPort(netaddr.IPPort{})) |
||||
c.Assert(netaddr.IPPort{}, qt.Equals, AsIPPort(netip.AddrPort{})) |
||||
|
||||
// Test just a single AddrPort conversion;
|
||||
// there's almost nothing happening in the code.
|
||||
portStr := "1.2.4.5:8" |
||||
ipPort := netaddr.MustParseIPPort(portStr) |
||||
ap := netip.MustParseAddrPort(portStr) |
||||
c.Assert(ipPort, qt.Equals, AsIPPort(ap)) |
||||
c.Assert(ap, qt.Equals, AsAddrPort(ipPort)) |
||||
} |
||||
|
||||
func TestPrefix(t *testing.T) { |
||||
c := qt.New(t) |
||||
|
||||
// The interesting Prefix cases are invalid bits.
|
||||
addr := netip.MustParseAddr("1.2.3.4") |
||||
ip := AsIP(addr) |
||||
|
||||
tests := []struct { |
||||
ipp netaddr.IPPrefix // input IPPrefix, output from converting pfx
|
||||
pfx netip.Prefix // input Prefix, output from converting ipp
|
||||
out netaddr.IPPrefix // output from converting pfx
|
||||
}{ |
||||
{netaddr.IPPrefix{}, netip.Prefix{}, netaddr.IPPrefix{}}, |
||||
{netaddr.IPPrefixFrom(ip, 24), netip.PrefixFrom(addr, 24), netaddr.IPPrefixFrom(ip, 24)}, |
||||
{netaddr.IPPrefixFrom(ip, 255), netip.PrefixFrom(addr, -1), netaddr.IPPrefixFrom(ip, 255)}, |
||||
{netaddr.IPPrefixFrom(ip, 204), netip.PrefixFrom(addr, -1), netaddr.IPPrefixFrom(ip, 255)}, |
||||
} |
||||
|
||||
for _, test := range tests { |
||||
c.Assert(test.out, qt.Equals, AsIPPrefix(test.pfx)) |
||||
c.Assert(test.pfx, qt.Equals, AsPrefix(test.ipp)) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue