diff --git a/net/prefix.go b/net/prefix.go index f75c2004abf3194de0c6f430afa5d29fc0579a7a..5abd32f141f8ae5cfb9c107d2bc5a7ce98bddf4e 100644 --- a/net/prefix.go +++ b/net/prefix.go @@ -70,7 +70,7 @@ func (pfx Prefix) Contains(x Prefix) bool { return pfx.containsIPv4(x) } - panic("No IPv6 support yet!") + return pfx.containsIPv6(x) } func (pfx Prefix) containsIPv4(x Prefix) bool { @@ -78,6 +78,20 @@ func (pfx Prefix) containsIPv4(x Prefix) bool { return (pfx.addr.ToUint32() & mask) == (x.addr.ToUint32() & mask) } +func (pfx Prefix) containsIPv6(x Prefix) bool { + var maskHigh, maskLow uint64 + if pfx.pfxlen <= 64 { + maskHigh = math.MaxUint32 << (64 - pfx.pfxlen) + maskLow = uint64(0) + } else { + maskHigh = math.MaxUint32 + maskLow = math.MaxUint32 << (128 - pfx.pfxlen) + } + + return pfx.addr.higher&maskHigh&maskHigh == x.addr.higher&maskHigh&maskHigh && + pfx.addr.lower&maskHigh&maskLow == x.addr.lower&maskHigh&maskLow +} + // Equal checks if pfx and x are equal func (pfx Prefix) Equal(x Prefix) bool { return pfx == x diff --git a/net/prefix_test.go b/net/prefix_test.go index 4428a4e84181f2f20ce5862aca531a23fcff0487..ccb05a7d3d753d61d6389d9ba6363da7562317f2 100644 --- a/net/prefix_test.go +++ b/net/prefix_test.go @@ -240,6 +240,30 @@ func TestContains(t *testing.T) { }, expected: false, }, + { + name: "IPv6: 2001:678:1e0:100::/56 is subnet of 2001:678:1e0::/48", + a: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0), + pfxlen: 48, + }, + expected: true, + b: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x100, 0, 0, 0, 0), + pfxlen: 56, + }, + }, + { + name: "IPv6: 2001:678:1e0:100::/56 is subnet of 2001:678:1e0::/48", + a: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x200, 0, 0, 0, 0), + pfxlen: 56, + }, + b: Prefix{ + addr: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0x100, 0, 0, 0, 0), + pfxlen: 64, + }, + expected: false, + }, } for _, test := range tests {