github.phpd.cn/cilium/cilium@v1.6.12/pkg/ip/ip.go (about) 1 // Copyright 2017-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ip 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "math/big" 22 "net" 23 "sort" 24 ) 25 26 const ( 27 ipv4BitLen = 8 * net.IPv4len 28 ipv6BitLen = 8 * net.IPv6len 29 ) 30 31 // CountIPsInCIDR takes a RFC4632/RFC4291-formatted IPv4/IPv6 CIDR and 32 // determines how many IP addresses reside within that CIDR. 33 // Returns 0 if the input CIDR cannot be parsed. 34 func CountIPsInCIDR(ipnet *net.IPNet) int { 35 subnet, size := ipnet.Mask.Size() 36 if subnet == size { 37 return 1 38 } 39 return 1<<uint(size-subnet) - 1 40 } 41 42 var ( 43 // v4Mappedv6Prefix is the RFC2765 IPv4-mapped address prefix. 44 v4Mappedv6Prefix = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff} 45 ipv4LeadingZeroes = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 46 defaultIPv4 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0} 47 defaultIPv6 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 48 upperIPv4 = []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 255, 255, 255, 255} 49 upperIPv6 = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 50 ) 51 52 // NetsByMask is used to sort a list of IP networks by the size of their masks. 53 // Implements sort.Interface. 54 type NetsByMask []*net.IPNet 55 56 func (s NetsByMask) Swap(i, j int) { 57 s[i], s[j] = s[j], s[i] 58 } 59 60 func (s NetsByMask) Less(i, j int) bool { 61 iPrefixSize, _ := s[i].Mask.Size() 62 jPrefixSize, _ := s[j].Mask.Size() 63 if iPrefixSize == jPrefixSize { 64 return bytes.Compare(s[i].IP, s[j].IP) < 0 65 } 66 return iPrefixSize < jPrefixSize 67 } 68 69 func (s NetsByMask) Len() int { 70 return len(s) 71 } 72 73 // Assert that NetsByMask implements sort.Interface. 74 var _ sort.Interface = NetsByMask{} 75 var _ sort.Interface = NetsByRange{} 76 77 // NetsByRange is used to sort a list of ranges, first by their last IPs, then by 78 // their first IPs 79 // Implements sort.Interface. 80 type NetsByRange []*netWithRange 81 82 func (s NetsByRange) Swap(i, j int) { 83 s[i], s[j] = s[j], s[i] 84 } 85 86 func (s NetsByRange) Less(i, j int) bool { 87 // First compare by last IP. 88 lastComparison := bytes.Compare(*s[i].Last, *s[j].Last) 89 if lastComparison < 0 { 90 return true 91 } else if lastComparison > 0 { 92 return false 93 } 94 95 // Then compare by first IP. 96 firstComparison := bytes.Compare(*s[i].First, *s[i].First) 97 if firstComparison < 0 { 98 return true 99 } else if firstComparison > 0 { 100 return false 101 } 102 103 // First and last IPs are the same, so thus are equal, and s[i] 104 // is not less than s[j]. 105 return false 106 } 107 108 func (s NetsByRange) Len() int { 109 return len(s) 110 } 111 112 // RemoveCIDRs removes the specified CIDRs from another set of CIDRs. If a CIDR 113 // to remove is not contained within the CIDR, the CIDR to remove is ignored. A 114 // slice of CIDRs is returned which contains the set of CIDRs provided minus 115 // the set of CIDRs which were removed. Both input slices may be modified by 116 // calling this function. 117 func RemoveCIDRs(allowCIDRs, removeCIDRs []*net.IPNet) ([]*net.IPNet, error) { 118 119 // Ensure that we iterate through the provided CIDRs in order of largest 120 // subnet first. 121 sort.Sort(NetsByMask(removeCIDRs)) 122 123 PreLoop: 124 // Remove CIDRs which are contained within CIDRs that we want to remove; 125 // such CIDRs are redundant. 126 for j, removeCIDR := range removeCIDRs { 127 for i, removeCIDR2 := range removeCIDRs { 128 if i == j { 129 continue 130 } 131 if removeCIDR.Contains(removeCIDR2.IP) { 132 removeCIDRs = append(removeCIDRs[:i], removeCIDRs[i+1:]...) 133 // Re-trigger loop since we have modified the slice we are iterating over. 134 goto PreLoop 135 } 136 } 137 } 138 139 for _, remove := range removeCIDRs { 140 Loop: 141 for i, allowCIDR := range allowCIDRs { 142 143 // Don't allow comparison of different address spaces. 144 if allowCIDR.IP.To4() != nil && remove.IP.To4() == nil || 145 allowCIDR.IP.To4() == nil && remove.IP.To4() != nil { 146 return nil, fmt.Errorf("cannot mix IP addresses of different IP protocol versions") 147 } 148 149 // Only remove CIDR if it is contained in the subnet we are allowing. 150 if allowCIDR.Contains(remove.IP.Mask(remove.Mask)) { 151 nets, err := removeCIDR(allowCIDR, remove) 152 if err != nil { 153 return nil, err 154 } 155 156 // Remove CIDR that we have just processed and append new CIDRs 157 // that we computed from removing the CIDR to remove. 158 allowCIDRs = append(allowCIDRs[:i], allowCIDRs[i+1:]...) 159 allowCIDRs = append(allowCIDRs, nets...) 160 goto Loop 161 } else if remove.Contains(allowCIDR.IP.Mask(allowCIDR.Mask)) { 162 // If a CIDR that we want to remove contains a CIDR in the list 163 // that is allowed, then we can just remove the CIDR to allow. 164 allowCIDRs = append(allowCIDRs[:i], allowCIDRs[i+1:]...) 165 goto Loop 166 } 167 } 168 } 169 170 return allowCIDRs, nil 171 } 172 173 func getNetworkPrefix(ipNet *net.IPNet) *net.IP { 174 var mask net.IP 175 176 if ipNet.IP.To4() == nil { 177 mask = make(net.IP, net.IPv6len) 178 for i := 0; i < len(ipNet.Mask); i++ { 179 mask[net.IPv6len-i-1] = ipNet.IP[net.IPv6len-i-1] & ^ipNet.Mask[i] 180 } 181 } else { 182 mask = make(net.IP, net.IPv4len) 183 for i := 0; i < net.IPv4len; i++ { 184 mask[net.IPv4len-i-1] = ipNet.IP[net.IPv6len-i-1] & ^ipNet.Mask[i] 185 } 186 } 187 188 return &mask 189 } 190 191 func removeCIDR(allowCIDR, removeCIDR *net.IPNet) ([]*net.IPNet, error) { 192 var allows []*net.IPNet 193 var allowIsIpv4, removeIsIpv4 bool 194 var allowBitLen int 195 196 if allowCIDR.IP.To4() != nil { 197 allowIsIpv4 = true 198 allowBitLen = ipv4BitLen 199 } else { 200 allowBitLen = ipv6BitLen 201 } 202 203 if removeCIDR.IP.To4() != nil { 204 removeIsIpv4 = true 205 } 206 207 if removeIsIpv4 != allowIsIpv4 { 208 return nil, fmt.Errorf("cannot mix IP addresses of different IP protocol versions") 209 } 210 211 // Get size of each CIDR mask. 212 allowSize, _ := allowCIDR.Mask.Size() 213 removeSize, _ := removeCIDR.Mask.Size() 214 215 if allowSize >= removeSize { 216 return nil, fmt.Errorf("allow CIDR prefix must be a superset of " + 217 "remove CIDR prefix") 218 } 219 220 allowFirstIPMasked := allowCIDR.IP.Mask(allowCIDR.Mask) 221 removeFirstIPMasked := removeCIDR.IP.Mask(removeCIDR.Mask) 222 223 // Convert to IPv4 in IPv6 addresses if needed. 224 if allowIsIpv4 { 225 allowFirstIPMasked = append(v4Mappedv6Prefix, allowFirstIPMasked...) 226 } 227 228 if removeIsIpv4 { 229 removeFirstIPMasked = append(v4Mappedv6Prefix, removeFirstIPMasked...) 230 } 231 232 allowFirstIP := &allowFirstIPMasked 233 removeFirstIP := &removeFirstIPMasked 234 235 // Create CIDR prefixes with mask size of Y+1, Y+2 ... X where Y is the mask 236 // length of the CIDR prefix B from which we are excluding a CIDR prefix A 237 // with mask length X. 238 for i := (allowBitLen - allowSize - 1); i >= (allowBitLen - removeSize); i-- { 239 // The mask for each CIDR prefix is simply the ith bit flipped, and then 240 // zero'ing out all subsequent bits (the host identifier part of the 241 // prefix). 242 newMaskSize := allowBitLen - i 243 newIP := (*net.IP)(flipNthBit((*[]byte)(removeFirstIP), uint(i))) 244 for k := range *allowFirstIP { 245 (*newIP)[k] = (*allowFirstIP)[k] | (*newIP)[k] 246 } 247 248 newMask := net.CIDRMask(newMaskSize, allowBitLen) 249 newIPMasked := newIP.Mask(newMask) 250 251 newIPNet := net.IPNet{IP: newIPMasked, Mask: newMask} 252 allows = append(allows, &newIPNet) 253 } 254 255 return allows, nil 256 } 257 258 func getByteIndexOfBit(bit uint) uint { 259 return net.IPv6len - (bit / 8) - 1 260 } 261 262 func getNthBit(ip *net.IP, bitNum uint) uint8 { 263 byteNum := getByteIndexOfBit(bitNum) 264 bits := (*ip)[byteNum] 265 b := uint8(bits) 266 return b >> (bitNum % 8) & 1 267 } 268 269 func flipNthBit(ip *[]byte, bitNum uint) *[]byte { 270 ipCopy := make([]byte, len(*ip)) 271 copy(ipCopy, *ip) 272 byteNum := getByteIndexOfBit(bitNum) 273 ipCopy[byteNum] = ipCopy[byteNum] ^ 1<<(bitNum%8) 274 275 return &ipCopy 276 } 277 278 func ipNetToRange(ipNet net.IPNet) netWithRange { 279 firstIP := make(net.IP, len(ipNet.IP)) 280 lastIP := make(net.IP, len(ipNet.IP)) 281 282 copy(firstIP, ipNet.IP) 283 copy(lastIP, ipNet.IP) 284 285 firstIP = firstIP.Mask(ipNet.Mask) 286 lastIP = lastIP.Mask(ipNet.Mask) 287 288 if firstIP.To4() != nil { 289 firstIP = append(v4Mappedv6Prefix, firstIP...) 290 lastIP = append(v4Mappedv6Prefix, lastIP...) 291 } 292 293 lastIPMask := make(net.IPMask, len(ipNet.Mask)) 294 copy(lastIPMask, ipNet.Mask) 295 for i := range lastIPMask { 296 lastIPMask[len(lastIPMask)-i-1] = ^lastIPMask[len(lastIPMask)-i-1] 297 lastIP[net.IPv6len-i-1] = lastIP[net.IPv6len-i-1] | lastIPMask[len(lastIPMask)-i-1] 298 } 299 300 return netWithRange{First: &firstIP, Last: &lastIP, Network: &ipNet} 301 } 302 303 func getPreviousIP(ip net.IP) net.IP { 304 // Cannot go lower than zero! 305 if ip.Equal(net.IP(defaultIPv4)) || ip.Equal(net.IP(defaultIPv6)) { 306 return ip 307 } 308 309 previousIP := make(net.IP, len(ip)) 310 copy(previousIP, ip) 311 312 var overflow bool 313 var lowerByteBound int 314 if ip.To4() != nil { 315 lowerByteBound = net.IPv6len - net.IPv4len 316 } else { 317 lowerByteBound = 0 318 } 319 for i := len(ip) - 1; i >= lowerByteBound; i-- { 320 if overflow || i == len(ip)-1 { 321 previousIP[i]-- 322 } 323 // Track if we have overflowed and thus need to continue subtracting. 324 if ip[i] == 0 && previousIP[i] == 255 { 325 overflow = true 326 } else { 327 overflow = false 328 } 329 } 330 return previousIP 331 } 332 333 // GetNextIP returns the next IP from the given IP address. If the given IP is 334 // the last IP of a v4 or v6 range, the same IP is returned. 335 func GetNextIP(ip net.IP) net.IP { 336 if ip.Equal(upperIPv4) || ip.Equal(upperIPv6) { 337 return ip 338 } 339 340 nextIP := make(net.IP, len(ip)) 341 switch len(ip) { 342 case net.IPv4len: 343 ipU32 := binary.BigEndian.Uint32(ip) 344 ipU32++ 345 binary.BigEndian.PutUint32(nextIP, ipU32) 346 return nextIP 347 case net.IPv6len: 348 ipU64 := binary.BigEndian.Uint64(ip[net.IPv6len/2:]) 349 ipU64++ 350 binary.BigEndian.PutUint64(nextIP[net.IPv6len/2:], ipU64) 351 if ipU64 == 0 { 352 ipU64 = binary.BigEndian.Uint64(ip[:net.IPv6len/2]) 353 ipU64++ 354 binary.BigEndian.PutUint64(nextIP[:net.IPv6len/2], ipU64) 355 } else { 356 copy(nextIP[:net.IPv6len/2], ip[:net.IPv6len/2]) 357 } 358 return nextIP 359 default: 360 return ip 361 } 362 } 363 364 func createSpanningCIDR(r netWithRange) net.IPNet { 365 // Don't want to modify the values of the provided range, so make copies. 366 lowest := *r.First 367 highest := *r.Last 368 369 var isIPv4 bool 370 var spanningMaskSize, bitLen, byteLen int 371 if lowest.To4() != nil { 372 isIPv4 = true 373 bitLen = ipv4BitLen 374 byteLen = net.IPv4len 375 } else { 376 bitLen = ipv6BitLen 377 byteLen = net.IPv6len 378 } 379 380 if isIPv4 { 381 spanningMaskSize = ipv4BitLen 382 } else { 383 spanningMaskSize = ipv6BitLen 384 } 385 386 // Convert to big Int so we can easily do bitshifting on the IP addresses, 387 // since golang only provides up to 64-bit unsigned integers. 388 lowestBig := big.NewInt(0).SetBytes(lowest) 389 highestBig := big.NewInt(0).SetBytes(highest) 390 391 // Starting from largest mask / smallest range possible, apply a mask one bit 392 // larger in each iteration to the upper bound in the range until we have 393 // masked enough to pass the lower bound in the range. This 394 // gives us the size of the prefix for the spanning CIDR to return as 395 // well as the IP for the CIDR prefix of the spanning CIDR. 396 for spanningMaskSize > 0 && lowestBig.Cmp(highestBig) < 0 { 397 spanningMaskSize-- 398 mask := big.NewInt(1) 399 mask = mask.Lsh(mask, uint(bitLen-spanningMaskSize)) 400 mask = mask.Mul(mask, big.NewInt(-1)) 401 highestBig = highestBig.And(highestBig, mask) 402 } 403 404 // If ipv4, need to append 0s because math.Big gets rid of preceding zeroes. 405 if isIPv4 { 406 highest = append(ipv4LeadingZeroes, highestBig.Bytes()...) 407 } else { 408 highest = highestBig.Bytes() 409 } 410 411 // Int does not store leading zeroes. 412 if len(highest) == 0 { 413 highest = make([]byte, byteLen) 414 } 415 416 newNet := net.IPNet{IP: highest, Mask: net.CIDRMask(spanningMaskSize, bitLen)} 417 return newNet 418 } 419 420 type netWithRange struct { 421 First *net.IP 422 Last *net.IP 423 Network *net.IPNet 424 } 425 426 func mergeAdjacentCIDRs(ranges []*netWithRange) []*netWithRange { 427 // Sort the ranges. This sorts first by the last IP, then first IP, then by 428 // the IP network in the list itself 429 sort.Sort(NetsByRange(ranges)) 430 431 // Merge adjacent CIDRs if possible. 432 for i := len(ranges) - 1; i > 0; i-- { 433 first1 := getPreviousIP(*ranges[i].First) 434 435 // Since the networks are sorted, we know that if a network in the list 436 // is adjacent to another one in the list, it will be the network next 437 // to it in the list. If the previous IP of the current network we are 438 // processing overlaps with the last IP of the previous network in the 439 // list, then we can merge the two ranges together. 440 if bytes.Compare(first1, *ranges[i-1].Last) <= 0 { 441 // Pick the minimum of the first two IPs to represent the start 442 // of the new range. 443 var minFirstIP *net.IP 444 if bytes.Compare(*ranges[i-1].First, *ranges[i].First) < 0 { 445 minFirstIP = ranges[i-1].First 446 } else { 447 minFirstIP = ranges[i].First 448 } 449 450 // Always take the last IP of the ith IP. 451 newRangeLast := make(net.IP, len(*ranges[i].Last)) 452 copy(newRangeLast, *ranges[i].Last) 453 454 newRangeFirst := make(net.IP, len(*minFirstIP)) 455 copy(newRangeFirst, *minFirstIP) 456 457 // Can't set the network field because since we are combining a 458 // range of IPs, and we don't yet know what CIDR prefix(es) represent 459 // the new range. 460 ranges[i-1] = &netWithRange{First: &newRangeFirst, Last: &newRangeLast, Network: nil} 461 462 // Since we have combined ranges[i] with the preceding item in the 463 // ranges list, we can delete ranges[i] from the slice. 464 ranges = append(ranges[:i], ranges[i+1:]...) 465 } 466 } 467 return ranges 468 } 469 470 // coalesceRanges converts ranges into an equivalent list of net.IPNets. 471 // All IPs in ranges should be of the same address family (IPv4 or IPv6). 472 func coalesceRanges(ranges []*netWithRange) []*net.IPNet { 473 coalescedCIDRs := []*net.IPNet{} 474 // Create CIDRs from ranges that were combined if needed. 475 for _, netRange := range ranges { 476 // If the Network field of netWithRange wasn't modified, then we can 477 // add it to the list which we will return, as it cannot be joined with 478 // any other CIDR in the list. 479 if netRange.Network != nil { 480 coalescedCIDRs = append(coalescedCIDRs, netRange.Network) 481 } else { 482 // We have joined two ranges together, so we need to find the new CIDRs 483 // that represent this range. 484 rangeCIDRs := rangeToCIDRs(*netRange.First, *netRange.Last) 485 coalescedCIDRs = append(coalescedCIDRs, rangeCIDRs...) 486 } 487 } 488 489 return coalescedCIDRs 490 } 491 492 // CoalesceCIDRs transforms the provided list of CIDRs into the most-minimal 493 // equivalent set of IPv4 and IPv6 CIDRs. 494 // It removes CIDRs that are subnets of other CIDRs in the list, and groups 495 // together CIDRs that have the same mask size into a CIDR of the same mask 496 // size provided that they share the same number of most significant 497 // mask-size bits. 498 // 499 // Note: this algorithm was ported from the Python library netaddr. 500 // https://github.com/drkjam/netaddr . 501 func CoalesceCIDRs(cidrs []*net.IPNet) ([]*net.IPNet, []*net.IPNet) { 502 503 ranges4 := []*netWithRange{} 504 ranges6 := []*netWithRange{} 505 506 for _, network := range cidrs { 507 newNetToRange := ipNetToRange(*network) 508 if network.IP.To4() != nil { 509 ranges4 = append(ranges4, &newNetToRange) 510 } else { 511 ranges6 = append(ranges6, &newNetToRange) 512 } 513 } 514 515 return coalesceRanges(mergeAdjacentCIDRs(ranges4)), coalesceRanges(mergeAdjacentCIDRs(ranges6)) 516 } 517 518 // rangeToCIDRs converts the range of IPs covered by firstIP and lastIP to 519 // a list of CIDRs that contains all of the IPs covered by the range. 520 func rangeToCIDRs(firstIP, lastIP net.IP) []*net.IPNet { 521 522 // First, create a CIDR that spans both IPs. 523 spanningCIDR := createSpanningCIDR(netWithRange{&firstIP, &lastIP, nil}) 524 spanningRange := ipNetToRange(spanningCIDR) 525 firstIPSpanning := spanningRange.First 526 lastIPSpanning := spanningRange.Last 527 528 cidrList := []*net.IPNet{} 529 530 // If the first IP of the spanning CIDR passes the lower bound (firstIP), 531 // we need to split the spanning CIDR and only take the IPs that are 532 // greater than the value which we split on, as we do not want the lesser 533 // values since they are less than the lower-bound (firstIP). 534 if bytes.Compare(*firstIPSpanning, firstIP) < 0 { 535 // Split on the previous IP of the first IP so that the right list of IPs 536 // of the partition includes the firstIP. 537 prevFirstRangeIP := getPreviousIP(firstIP) 538 var bitLen int 539 if prevFirstRangeIP.To4() != nil { 540 bitLen = ipv4BitLen 541 } else { 542 bitLen = ipv6BitLen 543 } 544 _, _, right := partitionCIDR(spanningCIDR, net.IPNet{IP: prevFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) 545 546 // Append all CIDRs but the first, as this CIDR includes the upper 547 // bound of the spanning CIDR, which we still need to partition on. 548 cidrList = append(cidrList, right...) 549 spanningCIDR = *right[0] 550 cidrList = cidrList[1:] 551 } 552 553 // Conversely, if the last IP of the spanning CIDR passes the upper bound 554 // (lastIP), we need to split the spanning CIDR and only take the IPs that 555 // are greater than the value which we split on, as we do not want the greater 556 // values since they are greater than the upper-bound (lastIP). 557 if bytes.Compare(*lastIPSpanning, lastIP) > 0 { 558 // Split on the next IP of the last IP so that the left list of IPs 559 // of the partition include the lastIP. 560 nextFirstRangeIP := GetNextIP(lastIP) 561 var bitLen int 562 if nextFirstRangeIP.To4() != nil { 563 bitLen = ipv4BitLen 564 } else { 565 bitLen = ipv6BitLen 566 } 567 left, _, _ := partitionCIDR(spanningCIDR, net.IPNet{IP: nextFirstRangeIP, Mask: net.CIDRMask(bitLen, bitLen)}) 568 cidrList = append(cidrList, left...) 569 } else { 570 // Otherwise, there is no need to partition; just use add the spanning 571 // CIDR to the list of networks. 572 cidrList = append(cidrList, &spanningCIDR) 573 } 574 return cidrList 575 } 576 577 // partitionCIDR returns a list of IP Networks partitioned upon excludeCIDR. 578 // The first list contains the networks to the left of the excludeCIDR in the 579 // partition, the second is a list containing the excludeCIDR itself if it is 580 // contained within the targetCIDR (nil otherwise), and the 581 // third is a list containing the networks to the right of the excludeCIDR in 582 // the partition. 583 func partitionCIDR(targetCIDR net.IPNet, excludeCIDR net.IPNet) ([]*net.IPNet, []*net.IPNet, []*net.IPNet) { 584 var targetIsIPv4 bool 585 if targetCIDR.IP.To4() != nil { 586 targetIsIPv4 = true 587 } 588 589 targetIPRange := ipNetToRange(targetCIDR) 590 excludeIPRange := ipNetToRange(excludeCIDR) 591 592 targetFirstIP := *targetIPRange.First 593 targetLastIP := *targetIPRange.Last 594 595 excludeFirstIP := *excludeIPRange.First 596 excludeLastIP := *excludeIPRange.Last 597 598 targetMaskSize, _ := targetCIDR.Mask.Size() 599 excludeMaskSize, _ := excludeCIDR.Mask.Size() 600 601 if bytes.Compare(excludeLastIP, targetFirstIP) < 0 { 602 return nil, nil, []*net.IPNet{&targetCIDR} 603 } else if bytes.Compare(targetLastIP, excludeFirstIP) < 0 { 604 return []*net.IPNet{&targetCIDR}, nil, nil 605 } 606 607 if targetMaskSize >= excludeMaskSize { 608 return nil, []*net.IPNet{&targetCIDR}, nil 609 } 610 611 left := []*net.IPNet{} 612 right := []*net.IPNet{} 613 614 newPrefixLen := targetMaskSize + 1 615 616 targetFirstCopy := make(net.IP, len(targetFirstIP)) 617 copy(targetFirstCopy, targetFirstIP) 618 619 iLowerOld := make(net.IP, len(targetFirstCopy)) 620 copy(iLowerOld, targetFirstCopy) 621 622 // Since golang only supports up to unsigned 64-bit integers, and we need 623 // to perform addition on addresses, use math/big library, which allows 624 // for manipulation of large integers. 625 626 // Used to track the current lower and upper bounds of the ranges to compare 627 // to excludeCIDR. 628 iLower := big.NewInt(0) 629 iUpper := big.NewInt(0) 630 iLower = iLower.SetBytes(targetFirstCopy) 631 632 var bitLen int 633 634 if targetIsIPv4 { 635 bitLen = ipv4BitLen 636 } else { 637 bitLen = ipv6BitLen 638 } 639 shiftAmount := (uint)(bitLen - newPrefixLen) 640 641 targetIPInt := big.NewInt(0) 642 targetIPInt.SetBytes(targetFirstIP.To16()) 643 644 exp := big.NewInt(0) 645 646 // Use left shift for exponentiation 647 exp = exp.Lsh(big.NewInt(1), shiftAmount) 648 iUpper = iUpper.Add(targetIPInt, exp) 649 650 matched := big.NewInt(0) 651 652 for excludeMaskSize >= newPrefixLen { 653 // Append leading zeros to IPv4 addresses, as math.Big.Int does not 654 // append them when the IP address is copied from a byte array to 655 // math.Big.Int. Leading zeroes are required for parsing IPv4 addresses 656 // for use with net.IP / net.IPNet. 657 var iUpperBytes, iLowerBytes []byte 658 if targetIsIPv4 { 659 iUpperBytes = append(ipv4LeadingZeroes, iUpper.Bytes()...) 660 iLowerBytes = append(ipv4LeadingZeroes, iLower.Bytes()...) 661 } else { 662 iUpperBytesLen := len(iUpper.Bytes()) 663 // Make sure that the number of bytes in the array matches what net 664 // package expects, as big package doesn't append leading zeroes. 665 if iUpperBytesLen != net.IPv6len { 666 numZeroesToAppend := net.IPv6len - iUpperBytesLen 667 zeroBytes := make([]byte, numZeroesToAppend) 668 iUpperBytes = append(zeroBytes, iUpper.Bytes()...) 669 } else { 670 iUpperBytes = iUpper.Bytes() 671 672 } 673 674 iLowerBytesLen := len(iLower.Bytes()) 675 if iLowerBytesLen != net.IPv6len { 676 numZeroesToAppend := net.IPv6len - iLowerBytesLen 677 zeroBytes := make([]byte, numZeroesToAppend) 678 iLowerBytes = append(zeroBytes, iLower.Bytes()...) 679 } else { 680 iLowerBytes = iLower.Bytes() 681 682 } 683 } 684 // If the IP we are excluding over is of a higher value than the current 685 // CIDR prefix we are generating, add the CIDR prefix to the set of IPs 686 // to the left of the exclude CIDR 687 if bytes.Compare(excludeFirstIP, iUpperBytes) >= 0 { 688 left = append(left, &net.IPNet{IP: iLowerBytes, Mask: net.CIDRMask(newPrefixLen, bitLen)}) 689 matched = matched.Set(iUpper) 690 } else { 691 // Same as above, but opposite. 692 right = append(right, &net.IPNet{IP: iUpperBytes, Mask: net.CIDRMask(newPrefixLen, bitLen)}) 693 matched = matched.Set(iLower) 694 } 695 696 newPrefixLen++ 697 698 if newPrefixLen > bitLen { 699 break 700 } 701 702 iLower = iLower.Set(matched) 703 iUpper = iUpper.Add(matched, big.NewInt(0).Lsh(big.NewInt(1), uint(bitLen-newPrefixLen))) 704 705 } 706 excludeList := []*net.IPNet{&excludeCIDR} 707 708 return left, excludeList, right 709 } 710 711 // KeepUniqueIPs transforms the provided multiset of IPs into a single set, 712 // lexicographically sorted via a byte-wise comparison of the IP slices (i.e. 713 // IPv4 addresses show up before IPv6). 714 // The slice is manipulated in-place destructively. 715 // 716 // 1- Sort the slice by comparing the IPs as bytes 717 // 2- For every unseen unique IP in the sorted slice, move it to the end of 718 // the return slice. 719 // Note that the slice is always large enough and, because it is sorted, we 720 // will not overwrite a valid element with another. To overwrite an element i 721 // with j, i must have come before j AND we decided it was a duplicate of the 722 // element at i-1. 723 func KeepUniqueIPs(ips []net.IP) []net.IP { 724 sort.Slice(ips, func(i, j int) bool { 725 return bytes.Compare(ips[i], ips[j]) == -1 726 }) 727 728 returnIPs := ips[:0] // len==0 but cap==cap(ips) 729 for readIdx, ip := range ips { 730 if len(returnIPs) == 0 || !returnIPs[len(returnIPs)-1].Equal(ips[readIdx]) { 731 returnIPs = append(returnIPs, ip) 732 } 733 } 734 735 return returnIPs 736 } 737 738 var privateIPBlocks []*net.IPNet 739 740 func initPrivatePrefixes() { 741 // We only care about global scope prefixes here. 742 for _, cidr := range []string{ 743 "10.0.0.0/8", // RFC1918 744 "172.16.0.0/12", // RFC1918 745 "192.168.0.0/16", // RFC1918 746 "fc00::/7", // IPv6 ULA 747 } { 748 _, block, _ := net.ParseCIDR(cidr) 749 privateIPBlocks = append(privateIPBlocks, block) 750 } 751 } 752 753 var excludedIPs []net.IP 754 755 func init() { 756 initPrivatePrefixes() 757 initExcludedIPs() 758 } 759 760 // IsExcluded returns whether a given IP is must be excluded 761 // due to coming from blacklisted device. 762 func IsExcluded(excludeList []net.IP, ip net.IP) bool { 763 for _, e := range excludeList { 764 if e.Equal(ip) { 765 return true 766 } 767 } 768 return false 769 } 770 771 // IsPublicAddr returns whether a given global IP is from 772 // a public range. 773 func IsPublicAddr(ip net.IP) bool { 774 for _, block := range privateIPBlocks { 775 if block.Contains(ip) { 776 return false 777 } 778 } 779 return true 780 } 781 782 // GetExcludedIPs returns a list of IPs from netdevices that Cilium 783 // needs to exclude to operate 784 func GetExcludedIPs() []net.IP { 785 return excludedIPs 786 } 787 788 // GetCIDRPrefixesFromIPs returns all of the ips as a slice of *net.IPNet. 789 func GetCIDRPrefixesFromIPs(ips []net.IP) []*net.IPNet { 790 if len(ips) == 0 { 791 return nil 792 } 793 res := make([]*net.IPNet, 0, len(ips)) 794 for _, ip := range ips { 795 res = append(res, IPToPrefix(ip)) 796 } 797 return res 798 } 799 800 // IPToPrefix returns the corresponding IPNet for the given IP. 801 func IPToPrefix(ip net.IP) *net.IPNet { 802 bits := net.IPv6len * 8 803 if ip.To4() != nil { 804 ip = ip.To4() 805 bits = net.IPv4len * 8 806 } 807 prefix := &net.IPNet{ 808 IP: ip, 809 Mask: net.CIDRMask(bits, bits), 810 } 811 return prefix 812 }