]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/apparentlymart/go-cidr/cidr/cidr.go
Merge branch 'master' of /home/ubuntu/terraform-vendor
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / apparentlymart / go-cidr / cidr / cidr.go
CommitLineData
bae9f6d2
JC
1// Package cidr is a collection of assorted utilities for computing
2// network and host addresses within network ranges.
3//
4// It expects a CIDR-type address structure where addresses are divided into
5// some number of prefix bits representing the network and then the remaining
6// suffix bits represent the host.
7//
8// For example, it can help to calculate addresses for sub-networks of a
9// parent network, or to calculate host addresses within a particular prefix.
10//
11// At present this package is prioritizing simplicity of implementation and
12// de-prioritizing speed and memory usage. Thus caution is advised before
13// using this package in performance-critical applications or hot codepaths.
14// Patches to improve the speed and memory usage may be accepted as long as
15// they do not result in a significant increase in code complexity.
16package cidr
17
18import (
19 "fmt"
20 "math/big"
21 "net"
22)
23
24// Subnet takes a parent CIDR range and creates a subnet within it
25// with the given number of additional prefix bits and the given
26// network number.
27//
28// For example, 10.3.0.0/16, extended by 8 bits, with a network number
29// of 5, becomes 10.3.5.0/24 .
30func Subnet(base *net.IPNet, newBits int, num int) (*net.IPNet, error) {
31 ip := base.IP
32 mask := base.Mask
33
34 parentLen, addrLen := mask.Size()
35 newPrefixLen := parentLen + newBits
36
37 if newPrefixLen > addrLen {
38 return nil, fmt.Errorf("insufficient address space to extend prefix of %d by %d", parentLen, newBits)
39 }
40
41 maxNetNum := uint64(1<<uint64(newBits)) - 1
42 if uint64(num) > maxNetNum {
43 return nil, fmt.Errorf("prefix extension of %d does not accommodate a subnet numbered %d", newBits, num)
44 }
45
46 return &net.IPNet{
47 IP: insertNumIntoIP(ip, num, newPrefixLen),
48 Mask: net.CIDRMask(newPrefixLen, addrLen),
49 }, nil
50}
51
52// Host takes a parent CIDR range and turns it into a host IP address with
53// the given host number.
54//
55// For example, 10.3.0.0/16 with a host number of 2 gives 10.3.0.2.
56func Host(base *net.IPNet, num int) (net.IP, error) {
57 ip := base.IP
58 mask := base.Mask
59
60 parentLen, addrLen := mask.Size()
61 hostLen := addrLen - parentLen
62
63 maxHostNum := uint64(1<<uint64(hostLen)) - 1
64
65 numUint64 := uint64(num)
66 if num < 0 {
67 numUint64 = uint64(-num) - 1
68 num = int(maxHostNum - numUint64)
69 }
70
71 if numUint64 > maxHostNum {
72 return nil, fmt.Errorf("prefix of %d does not accommodate a host numbered %d", parentLen, num)
73 }
74
75 return insertNumIntoIP(ip, num, 32), nil
76}
77
78// AddressRange returns the first and last addresses in the given CIDR range.
79func AddressRange(network *net.IPNet) (net.IP, net.IP) {
80 // the first IP is easy
81 firstIP := network.IP
82
83 // the last IP is the network address OR NOT the mask address
84 prefixLen, bits := network.Mask.Size()
85 if prefixLen == bits {
86 // Easy!
87 // But make sure that our two slices are distinct, since they
88 // would be in all other cases.
89 lastIP := make([]byte, len(firstIP))
90 copy(lastIP, firstIP)
91 return firstIP, lastIP
92 }
93
94 firstIPInt, bits := ipToInt(firstIP)
95 hostLen := uint(bits) - uint(prefixLen)
96 lastIPInt := big.NewInt(1)
97 lastIPInt.Lsh(lastIPInt, hostLen)
98 lastIPInt.Sub(lastIPInt, big.NewInt(1))
99 lastIPInt.Or(lastIPInt, firstIPInt)
100
101 return firstIP, intToIP(lastIPInt, bits)
102}
103
104// AddressCount returns the number of distinct host addresses within the given
105// CIDR range.
106//
107// Since the result is a uint64, this function returns meaningful information
108// only for IPv4 ranges and IPv6 ranges with a prefix size of at least 65.
109func AddressCount(network *net.IPNet) uint64 {
110 prefixLen, bits := network.Mask.Size()
111 return 1 << (uint64(bits) - uint64(prefixLen))
112}