github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/network/util/ip.go (about) 1 package util 2 3 import ( 4 "crypto/rand" 5 "net" 6 7 "github.com/pkg/errors" 8 ) 9 10 // IsIPv6 returns true if netIP is IPv6. 11 func IsIPv6(netIP net.IP) bool { 12 return netIP != nil && netIP.To4() == nil 13 } 14 15 // IsIPv4 returns true if netIP is IPv4. 16 func IsIPv4(netIP net.IP) bool { 17 return netIP != nil && netIP.To4() != nil 18 } 19 20 func incByte(subnet *net.IPNet, idx int, shift uint) error { 21 if idx < 0 { 22 return errors.New("no more subnets left") 23 } 24 if subnet.IP[idx] == 255 { 25 subnet.IP[idx] = 0 26 return incByte(subnet, idx-1, 0) 27 } 28 subnet.IP[idx] += 1 << shift 29 return nil 30 } 31 32 // NextSubnet returns subnet incremented by 1 33 func NextSubnet(subnet *net.IPNet) (*net.IPNet, error) { 34 newSubnet := &net.IPNet{ 35 IP: subnet.IP, 36 Mask: subnet.Mask, 37 } 38 ones, bits := newSubnet.Mask.Size() 39 if ones == 0 { 40 return nil, errors.Errorf("%s has only one subnet", subnet.String()) 41 } 42 zeroes := uint(bits - ones) 43 shift := zeroes % 8 44 idx := ones/8 - 1 45 if idx < 0 { 46 idx = 0 47 } 48 if err := incByte(newSubnet, idx, shift); err != nil { 49 return nil, err 50 } 51 return newSubnet, nil 52 } 53 54 // LastIPInSubnet gets the last IP in a subnet 55 func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer 56 // re-parse to ensure clean network address 57 _, cidr, err := net.ParseCIDR(addr.String()) 58 if err != nil { 59 return nil, err 60 } 61 62 ones, bits := cidr.Mask.Size() 63 if ones == bits { 64 return cidr.IP, nil 65 } 66 for i := range cidr.IP { 67 cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i] 68 } 69 return cidr.IP, nil 70 } 71 72 // FirstIPInSubnet gets the first IP in a subnet 73 func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer 74 // re-parse to ensure clean network address 75 _, cidr, err := net.ParseCIDR(addr.String()) 76 if err != nil { 77 return nil, err 78 } 79 ones, bits := cidr.Mask.Size() 80 if ones == bits { 81 return cidr.IP, nil 82 } 83 cidr.IP[len(cidr.IP)-1]++ 84 return cidr.IP, nil 85 } 86 87 func NetworkIntersectsWithNetworks(n *net.IPNet, networklist []*net.IPNet) bool { 88 for _, nw := range networklist { 89 if networkIntersect(n, nw) { 90 return true 91 } 92 } 93 return false 94 } 95 96 func networkIntersect(n1, n2 *net.IPNet) bool { 97 return n2.Contains(n1.IP) || n1.Contains(n2.IP) 98 } 99 100 // GetRandomIPv6Subnet returns a random internal ipv6 subnet as described in RFC3879. 101 func GetRandomIPv6Subnet() (net.IPNet, error) { 102 ip := make(net.IP, 8, net.IPv6len) 103 // read 8 random bytes 104 _, err := rand.Read(ip) 105 if err != nil { 106 return net.IPNet{}, nil 107 } 108 // first byte must be FD as per RFC3879 109 ip[0] = 0xfd 110 // add 8 zero bytes 111 ip = append(ip, make([]byte, 8)...) 112 return net.IPNet{IP: ip, Mask: net.CIDRMask(64, 128)}, nil 113 }