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  }