From 76d01e8d6c90ede97d3646dc88d2e1e22dcf6138 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 31 May 2021 11:40:57 -0700 Subject: [PATCH] Make IPPrefix uniformly strip/ignore IPv6 zones. Enabler for #167. Signed-off-by: David Anderson --- netaddr.go | 6 ++---- netaddr_test.go | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/netaddr.go b/netaddr.go index ce5d95c..97a4fa8 100644 --- a/netaddr.go +++ b/netaddr.go @@ -1237,10 +1237,7 @@ func ParseIPPrefix(s string) (IPPrefix, error) { if bits < 0 || bits > maxBits { return IPPrefix{}, fmt.Errorf("netaddr.ParseIPPrefix(%q): prefix length out of range", s) } - return IPPrefix{ - ip: ip, - bits: uint8(bits), - }, nil + return IPPrefixFrom(ip, uint8(bits)), nil } // MustParseIPPrefix calls ParseIPPrefix(s) and panics on error. @@ -1292,6 +1289,7 @@ func (p IPPrefix) IPNet() *net.IPNet { // An IPv4 address will not match an IPv6 prefix. // A v6-mapped IPv6 address will not match an IPv4 prefix. // A zero-value IP will not match any prefix. +// ip's zone, if any, is ignored. func (p IPPrefix) Contains(ip IP) bool { if !p.Valid() { return false diff --git a/netaddr_test.go b/netaddr_test.go index 10572be..0310113 100644 --- a/netaddr_test.go +++ b/netaddr_test.go @@ -1128,7 +1128,6 @@ func TestIPPrefixMarshalUnmarshal(t *testing.T) { "0.0.0.0/0", "::/0", "::1/128", - "fe80::1cc0:3e8c:119f:c2e1%ens18/128", "::ffff:c000:1234/128", "2001:db8::/32", } @@ -1157,6 +1156,26 @@ func TestIPPrefixMarshalUnmarshal(t *testing.T) { } } +func TestIPPrefixMarshalUnmarshalZone(t *testing.T) { + orig := `"fe80::1cc0:3e8c:119f:c2e1%ens18/128"` + unzoned := `"fe80::1cc0:3e8c:119f:c2e1/128"` + + var p IPPrefix + if err := json.Unmarshal([]byte(orig), &p); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + pb, err := json.Marshal(p) + if err != nil { + t.Fatalf("failed to marshal: %v", err) + } + + back := string(pb) + if back != unzoned { + t.Errorf("Marshal = %q; want %q", back, unzoned) + } +} + func TestIPPrefixUnmarshalTextNonZero(t *testing.T) { ip := mustIPPrefix("fe80::/64") if err := ip.UnmarshalText([]byte("xxx")); err == nil { @@ -1260,6 +1279,7 @@ func TestIPPrefix(t *testing.T) { ip IP bits uint8 ipNet *net.IPNet + str string contains []IP notContains []IP }{ @@ -1342,14 +1362,15 @@ func TestIPPrefix(t *testing.T) { }, { prefix: "::%0/00/80", - ip: mustIP("::%0/00"), + ip: mustIP("::"), bits: 80, + str: "::/80", ipNet: &net.IPNet{ IP: net.ParseIP("::"), // net.IPNet drops zones Mask: net.CIDRMask(80, 128), }, - contains: mustIPs("::%0/00"), - notContains: mustIPs("ff::%0/00"), + contains: mustIPs("::%0/00", "::%1/23"), + notContains: mustIPs("ff::%0/00", "ff::%1/23"), }, } for _, test := range tests { @@ -1378,8 +1399,12 @@ func TestIPPrefix(t *testing.T) { t.Errorf("contains %s", ip) } } - if got := prefix.String(); got != test.prefix { - t.Errorf("prefix.String()=%q, want %q", got, test.prefix) + want := test.str + if want == "" { + want = test.prefix + } + if got := prefix.String(); got != want { + t.Errorf("prefix.String()=%q, want %q", got, want) } testAppendToMarshal(t, prefix)