Upgrade dependent version: github.com/open-policy-agent/opa (#5315)
Upgrade dependent version: github.com/open-policy-agent/opa v0.18.0 -> v0.45.0 Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io> Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
367
vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go
generated
vendored
Normal file
367
vendor/github.com/open-policy-agent/opa/internal/cidr/merge/merge.go
generated
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
// Copyright 2017-2020 Authors of Cilium
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package merge provides helper functions for merging a list of
|
||||
// IP addresses and subnets into the smallest possible list of CIDRs.
|
||||
// Original Implementation: https://github.com/cilium/cilium
|
||||
package merge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
ipv4BitLen = 8 * net.IPv4len
|
||||
ipv6BitLen = 8 * net.IPv6len
|
||||
)
|
||||
|
||||
var (
|
||||
v4Mappedv6Prefix = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff}
|
||||
defaultIPv4 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0}
|
||||
defaultIPv6 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
|
||||
upperIPv4 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 255, 255, 255, 255}
|
||||
upperIPv6 = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
ipv4LeadingZeroes = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
|
||||
)
|
||||
|
||||
// RangeToCIDRs converts the range of IPs covered by firstIP and lastIP to
|
||||
// a list of CIDRs that contains all of the IPs covered by the range.
|
||||
func RangeToCIDRs(firstIP, lastIP net.IP) []*net.IPNet {
|
||||
// First, create a CIDR that spans both IPs.
|
||||
spanningCIDR := createSpanningCIDR(&firstIP, &lastIP)
|
||||
firstIPSpanning, lastIPSpanning := GetAddressRange(spanningCIDR)
|
||||
|
||||
cidrList := []*net.IPNet{}
|
||||
|
||||
// If the first IP of the spanning CIDR passes the lower bound (firstIP),
|
||||
// we need to split the spanning CIDR and only take the IPs that are
|
||||
// greater than the value which we split on, as we do not want the lesser
|
||||
// values since they are less than the lower-bound (firstIP).
|
||||
if bytes.Compare(firstIPSpanning, firstIP) < 0 {
|
||||
// Split on the previous IP of the first IP so that the right list of IPs
|
||||
// of the partition includes the firstIP.
|
||||
prevFirstRangeIP := GetPreviousIP(firstIP)
|
||||
var bitLen int
|
||||
if prevFirstRangeIP.To4() != nil {
|
||||
bitLen = ipv4BitLen
|
||||
} else {
|
||||
bitLen = ipv6BitLen
|
||||
}
|
||||
_, _, right := partitionCIDR(spanningCIDR, net.IPNet{IP: prevFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)})
|
||||
|
||||
// Append all CIDRs but the first, as this CIDR includes the upper
|
||||
// bound of the spanning CIDR, which we still need to partition on.
|
||||
cidrList = append(cidrList, right...)
|
||||
spanningCIDR = *right[0]
|
||||
cidrList = cidrList[1:]
|
||||
}
|
||||
|
||||
// Conversely, if the last IP of the spanning CIDR passes the upper bound
|
||||
// (lastIP), we need to split the spanning CIDR and only take the IPs that
|
||||
// are greater than the value which we split on, as we do not want the greater
|
||||
// values since they are greater than the upper-bound (lastIP).
|
||||
if bytes.Compare(lastIPSpanning, lastIP) > 0 {
|
||||
// Split on the next IP of the last IP so that the left list of IPs
|
||||
// of the partition include the lastIP.
|
||||
nextFirstRangeIP := getNextIP(lastIP)
|
||||
var bitLen int
|
||||
if nextFirstRangeIP.To4() != nil {
|
||||
bitLen = ipv4BitLen
|
||||
} else {
|
||||
bitLen = ipv6BitLen
|
||||
}
|
||||
left, _, _ := partitionCIDR(spanningCIDR, net.IPNet{IP: nextFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)})
|
||||
cidrList = append(cidrList, left...)
|
||||
} else {
|
||||
// Otherwise, there is no need to partition; just use add the spanning
|
||||
// CIDR to the list of networks.
|
||||
cidrList = append(cidrList, &spanningCIDR)
|
||||
}
|
||||
return cidrList
|
||||
}
|
||||
|
||||
// GetAddressRange returns the first and last addresses in the given CIDR range.
|
||||
func GetAddressRange(ipNet net.IPNet) (net.IP, net.IP) {
|
||||
firstIP := make(net.IP, len(ipNet.IP))
|
||||
lastIP := make(net.IP, len(ipNet.IP))
|
||||
|
||||
copy(firstIP, ipNet.IP)
|
||||
copy(lastIP, ipNet.IP)
|
||||
|
||||
firstIP = firstIP.Mask(ipNet.Mask)
|
||||
lastIP = lastIP.Mask(ipNet.Mask)
|
||||
|
||||
if firstIP.To4() != nil {
|
||||
firstIP = append(v4Mappedv6Prefix, firstIP...)
|
||||
lastIP = append(v4Mappedv6Prefix, lastIP...)
|
||||
}
|
||||
|
||||
lastIPMask := make(net.IPMask, len(ipNet.Mask))
|
||||
copy(lastIPMask, ipNet.Mask)
|
||||
for i := range lastIPMask {
|
||||
lastIPMask[len(lastIPMask)-i-1] = ^lastIPMask[len(lastIPMask)-i-1]
|
||||
lastIP[net.IPv6len-i-1] = lastIP[net.IPv6len-i-1] | lastIPMask[len(lastIPMask)-i-1]
|
||||
}
|
||||
|
||||
return firstIP, lastIP
|
||||
}
|
||||
|
||||
// GetPreviousIP returns the previous IP from the given IP address.
|
||||
func GetPreviousIP(ip net.IP) net.IP {
|
||||
// Cannot go lower than zero!
|
||||
if ip.Equal(net.IP(defaultIPv4)) || ip.Equal(net.IP(defaultIPv6)) {
|
||||
return ip
|
||||
}
|
||||
|
||||
previousIP := make(net.IP, len(ip))
|
||||
copy(previousIP, ip)
|
||||
|
||||
var overflow bool
|
||||
var lowerByteBound int
|
||||
if ip.To4() != nil {
|
||||
lowerByteBound = net.IPv6len - net.IPv4len
|
||||
} else {
|
||||
lowerByteBound = 0
|
||||
}
|
||||
for i := len(ip) - 1; i >= lowerByteBound; i-- {
|
||||
if overflow || i == len(ip)-1 {
|
||||
previousIP[i]--
|
||||
}
|
||||
// Track if we have overflowed and thus need to continue subtracting.
|
||||
if ip[i] == 0 && previousIP[i] == 255 {
|
||||
overflow = true
|
||||
} else {
|
||||
overflow = false
|
||||
}
|
||||
}
|
||||
return previousIP
|
||||
}
|
||||
|
||||
// createSpanningCIDR returns a single IP network spanning the
|
||||
// the lower and upper bound IP addresses.
|
||||
func createSpanningCIDR(firstIP, lastIP *net.IP) net.IPNet {
|
||||
// Don't want to modify the values of the provided range, so make copies.
|
||||
lowest := *firstIP
|
||||
highest := *lastIP
|
||||
|
||||
var isIPv4 bool
|
||||
var spanningMaskSize, bitLen, byteLen int
|
||||
if lowest.To4() != nil {
|
||||
isIPv4 = true
|
||||
bitLen = ipv4BitLen
|
||||
byteLen = net.IPv4len
|
||||
} else {
|
||||
bitLen = ipv6BitLen
|
||||
byteLen = net.IPv6len
|
||||
}
|
||||
|
||||
if isIPv4 {
|
||||
spanningMaskSize = ipv4BitLen
|
||||
} else {
|
||||
spanningMaskSize = ipv6BitLen
|
||||
}
|
||||
|
||||
// Convert to big Int so we can easily do bitshifting on the IP addresses,
|
||||
// since golang only provides up to 64-bit unsigned integers.
|
||||
lowestBig := big.NewInt(0).SetBytes(lowest)
|
||||
highestBig := big.NewInt(0).SetBytes(highest)
|
||||
|
||||
// Starting from largest mask / smallest range possible, apply a mask one bit
|
||||
// larger in each iteration to the upper bound in the range until we have
|
||||
// masked enough to pass the lower bound in the range. This
|
||||
// gives us the size of the prefix for the spanning CIDR to return as
|
||||
// well as the IP for the CIDR prefix of the spanning CIDR.
|
||||
for spanningMaskSize > 0 && lowestBig.Cmp(highestBig) < 0 {
|
||||
spanningMaskSize--
|
||||
mask := big.NewInt(1)
|
||||
mask = mask.Lsh(mask, uint(bitLen-spanningMaskSize))
|
||||
mask = mask.Mul(mask, big.NewInt(-1))
|
||||
highestBig = highestBig.And(highestBig, mask)
|
||||
}
|
||||
|
||||
// If ipv4, need to append 0s because math.Big gets rid of preceding zeroes.
|
||||
if isIPv4 {
|
||||
highest = append(ipv4LeadingZeroes, highestBig.Bytes()...)
|
||||
} else {
|
||||
highest = highestBig.Bytes()
|
||||
}
|
||||
|
||||
// Int does not store leading zeroes.
|
||||
if len(highest) == 0 {
|
||||
highest = make([]byte, byteLen)
|
||||
}
|
||||
|
||||
newNet := net.IPNet{IP: highest, Mask: net.CIDRMask(spanningMaskSize, bitLen)}
|
||||
return newNet
|
||||
}
|
||||
|
||||
// partitionCIDR returns a list of IP Networks partitioned upon excludeCIDR.
|
||||
// The first list contains the networks to the left of the excludeCIDR in the
|
||||
// partition, the second is a list containing the excludeCIDR itself if it is
|
||||
// contained within the targetCIDR (nil otherwise), and the
|
||||
// third is a list containing the networks to the right of the excludeCIDR in
|
||||
// the partition.
|
||||
func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, []*net.IPNet, []*net.IPNet) {
|
||||
var targetIsIPv4 bool
|
||||
if targetCIDR.IP.To4() != nil {
|
||||
targetIsIPv4 = true
|
||||
}
|
||||
|
||||
targetFirstIP, targetLastIP := GetAddressRange(targetCIDR)
|
||||
excludeFirstIP, excludeLastIP := GetAddressRange(excludeCIDR)
|
||||
|
||||
targetMaskSize, _ := targetCIDR.Mask.Size()
|
||||
excludeMaskSize, _ := excludeCIDR.Mask.Size()
|
||||
|
||||
if bytes.Compare(excludeLastIP, targetFirstIP) < 0 {
|
||||
return nil, nil, []*net.IPNet{&targetCIDR}
|
||||
} else if bytes.Compare(targetLastIP, excludeFirstIP) < 0 {
|
||||
return []*net.IPNet{&targetCIDR}, nil, nil
|
||||
}
|
||||
|
||||
if targetMaskSize >= excludeMaskSize {
|
||||
return nil, []*net.IPNet{&targetCIDR}, nil
|
||||
}
|
||||
|
||||
left := []*net.IPNet{}
|
||||
right := []*net.IPNet{}
|
||||
|
||||
newPrefixLen := targetMaskSize + 1
|
||||
|
||||
targetFirstCopy := make(net.IP, len(targetFirstIP))
|
||||
copy(targetFirstCopy, targetFirstIP)
|
||||
|
||||
iLowerOld := make(net.IP, len(targetFirstCopy))
|
||||
copy(iLowerOld, targetFirstCopy)
|
||||
|
||||
// Since golang only supports up to unsigned 64-bit integers, and we need
|
||||
// to perform addition on addresses, use math/big library, which allows
|
||||
// for manipulation of large integers.
|
||||
|
||||
// Used to track the current lower and upper bounds of the ranges to compare
|
||||
// to excludeCIDR.
|
||||
iLower := big.NewInt(0)
|
||||
iUpper := big.NewInt(0)
|
||||
iLower = iLower.SetBytes(targetFirstCopy)
|
||||
|
||||
var bitLen int
|
||||
|
||||
if targetIsIPv4 {
|
||||
bitLen = ipv4BitLen
|
||||
} else {
|
||||
bitLen = ipv6BitLen
|
||||
}
|
||||
shiftAmount := (uint)(bitLen - newPrefixLen)
|
||||
|
||||
targetIPInt := big.NewInt(0)
|
||||
targetIPInt.SetBytes(targetFirstIP.To16())
|
||||
|
||||
exp := big.NewInt(0)
|
||||
|
||||
// Use left shift for exponentiation
|
||||
exp = exp.Lsh(big.NewInt(1), shiftAmount)
|
||||
iUpper = iUpper.Add(targetIPInt, exp)
|
||||
|
||||
matched := big.NewInt(0)
|
||||
|
||||
for excludeMaskSize >= newPrefixLen {
|
||||
// Append leading zeros to IPv4 addresses, as math.Big.Int does not
|
||||
// append them when the IP address is copied from a byte array to
|
||||
// math.Big.Int. Leading zeroes are required for parsing IPv4 addresses
|
||||
// for use with net.IP / net.IPNet.
|
||||
var iUpperBytes, iLowerBytes []byte
|
||||
if targetIsIPv4 {
|
||||
iUpperBytes = append(ipv4LeadingZeroes, iUpper.Bytes()...)
|
||||
iLowerBytes = append(ipv4LeadingZeroes, iLower.Bytes()...)
|
||||
} else {
|
||||
iUpperBytesLen := len(iUpper.Bytes())
|
||||
// Make sure that the number of bytes in the array matches what net
|
||||
// package expects, as big package doesn't append leading zeroes.
|
||||
if iUpperBytesLen != net.IPv6len {
|
||||
numZeroesToAppend := net.IPv6len - iUpperBytesLen
|
||||
zeroBytes := make([]byte, numZeroesToAppend)
|
||||
iUpperBytes = append(zeroBytes, iUpper.Bytes()...)
|
||||
} else {
|
||||
iUpperBytes = iUpper.Bytes()
|
||||
|
||||
}
|
||||
|
||||
iLowerBytesLen := len(iLower.Bytes())
|
||||
if iLowerBytesLen != net.IPv6len {
|
||||
numZeroesToAppend := net.IPv6len - iLowerBytesLen
|
||||
zeroBytes := make([]byte, numZeroesToAppend)
|
||||
iLowerBytes = append(zeroBytes, iLower.Bytes()...)
|
||||
} else {
|
||||
iLowerBytes = iLower.Bytes()
|
||||
|
||||
}
|
||||
}
|
||||
// If the IP we are excluding over is of a higher value than the current
|
||||
// CIDR prefix we are generating, add the CIDR prefix to the set of IPs
|
||||
// to the left of the exclude CIDR
|
||||
if bytes.Compare(excludeFirstIP, iUpperBytes) >= 0 {
|
||||
left = append(left, &net.IPNet{IP: iLowerBytes, Mask: net.CIDRMask(newPrefixLen, bitLen)})
|
||||
matched = matched.Set(iUpper)
|
||||
} else {
|
||||
// Same as above, but opposite.
|
||||
right = append(right, &net.IPNet{IP: iUpperBytes, Mask: net.CIDRMask(newPrefixLen, bitLen)})
|
||||
matched = matched.Set(iLower)
|
||||
}
|
||||
|
||||
newPrefixLen++
|
||||
|
||||
if newPrefixLen > bitLen {
|
||||
break
|
||||
}
|
||||
|
||||
iLower = iLower.Set(matched)
|
||||
iUpper = iUpper.Add(matched, big.NewInt(0).Lsh(big.NewInt(1), uint(bitLen-newPrefixLen)))
|
||||
|
||||
}
|
||||
excludeList := []*net.IPNet{&excludeCIDR}
|
||||
|
||||
return left, excludeList, right
|
||||
}
|
||||
|
||||
func getNextIP(ip net.IP) net.IP {
|
||||
if ip.Equal(upperIPv4) || ip.Equal(upperIPv6) {
|
||||
return ip
|
||||
}
|
||||
|
||||
nextIP := make(net.IP, len(ip))
|
||||
switch len(ip) {
|
||||
case net.IPv4len:
|
||||
ipU32 := binary.BigEndian.Uint32(ip)
|
||||
ipU32++
|
||||
binary.BigEndian.PutUint32(nextIP, ipU32)
|
||||
return nextIP
|
||||
case net.IPv6len:
|
||||
ipU64 := binary.BigEndian.Uint64(ip[net.IPv6len/2:])
|
||||
ipU64++
|
||||
binary.BigEndian.PutUint64(nextIP[net.IPv6len/2:], ipU64)
|
||||
if ipU64 == 0 {
|
||||
ipU64 = binary.BigEndian.Uint64(ip[:net.IPv6len/2])
|
||||
ipU64++
|
||||
binary.BigEndian.PutUint64(nextIP[:net.IPv6len/2], ipU64)
|
||||
} else {
|
||||
copy(nextIP[:net.IPv6len/2], ip[:net.IPv6len/2])
|
||||
}
|
||||
return nextIP
|
||||
default:
|
||||
return ip
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user