diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2020-10-07 13:56:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-07 13:56:56 -0400 |
commit | 9ae873e60e149677db66782eaf2b4ed1402e97d2 (patch) | |
tree | 1f72e0558316390e8a235edad0f2464725dbd9c9 /libpod/network/subnet.go | |
parent | 173e3c2faa74e5ef1b941338c06e5dd7dca68ac2 (diff) | |
parent | fe3faa517e1bbc3b2e82afaae32d8712c844fdae (diff) | |
download | podman-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.go | 78 |
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 +} |