summaryrefslogtreecommitdiff
path: root/libpod/network/subnet.go
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-10-07 13:56:56 -0400
committerGitHub <noreply@github.com>2020-10-07 13:56:56 -0400
commit9ae873e60e149677db66782eaf2b4ed1402e97d2 (patch)
tree1f72e0558316390e8a235edad0f2464725dbd9c9 /libpod/network/subnet.go
parent173e3c2faa74e5ef1b941338c06e5dd7dca68ac2 (diff)
parentfe3faa517e1bbc3b2e82afaae32d8712c844fdae (diff)
downloadpodman-9ae873e60e149677db66782eaf2b4ed1402e97d2.tar.gz
podman-9ae873e60e149677db66782eaf2b4ed1402e97d2.tar.bz2
podman-9ae873e60e149677db66782eaf2b4ed1402e97d2.zip
Merge pull request #7943 from baude/issue7807
prevent unpredictable results with network create|remove
Diffstat (limited to 'libpod/network/subnet.go')
-rw-r--r--libpod/network/subnet.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/libpod/network/subnet.go b/libpod/network/subnet.go
new file mode 100644
index 000000000..90f0cdfce
--- /dev/null
+++ b/libpod/network/subnet.go
@@ -0,0 +1,78 @@
+package network
+
+/*
+ The code in this was kindly contributed by Dan Williams(dcbw@redhat.com). Many thanks
+ for his contributions.
+*/
+
+import (
+ "fmt"
+ "net"
+)
+
+func incByte(subnet *net.IPNet, idx int, shift uint) error {
+ if idx < 0 {
+ return fmt.Errorf("no more subnets left")
+ }
+ if subnet.IP[idx] == 255 {
+ subnet.IP[idx] = 0
+ return incByte(subnet, idx-1, 0)
+ }
+ subnet.IP[idx] += 1 << shift
+ return nil
+}
+
+// NextSubnet returns subnet incremented by 1
+func NextSubnet(subnet *net.IPNet) (*net.IPNet, error) {
+ newSubnet := &net.IPNet{
+ IP: subnet.IP,
+ Mask: subnet.Mask,
+ }
+ ones, bits := newSubnet.Mask.Size()
+ if ones == 0 {
+ return nil, fmt.Errorf("%s has only one subnet", subnet.String())
+ }
+ zeroes := uint(bits - ones)
+ shift := zeroes % 8
+ idx := ones/8 - 1
+ if idx < 0 {
+ idx = 0
+ }
+ if err := incByte(newSubnet, idx, shift); err != nil {
+ return nil, err
+ }
+ return newSubnet, nil
+}
+
+// LastIPInSubnet gets the last IP in a subnet
+func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
+ // re-parse to ensure clean network address
+ _, cidr, err := net.ParseCIDR(addr.String())
+ if err != nil {
+ return nil, err
+ }
+
+ ones, bits := cidr.Mask.Size()
+ if ones == bits {
+ return FirstIPInSubnet(cidr)
+ }
+ hostStart := ones / 8
+ // Handle the first host byte
+ cidr.IP[hostStart] |= 0xff & cidr.Mask[hostStart]
+ // Fill the rest with ones
+ for i := hostStart; i < len(cidr.IP); i++ {
+ cidr.IP[i] = 0xff
+ }
+ return cidr.IP, nil
+}
+
+// FirstIPInSubnet gets the first IP in a subnet
+func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
+ // re-parse to ensure clean network address
+ _, cidr, err := net.ParseCIDR(addr.String())
+ if err != nil {
+ return nil, err
+ }
+ cidr.IP[len(cidr.IP)-1]++
+ return cidr.IP, nil
+}