diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2019-09-09 19:44:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-09 19:44:57 +0200 |
commit | 7042a3d7a539bae79ed63bdc87f432b8ec73afd8 (patch) | |
tree | 6f229373f5e436663c8908d0f2409fdbac2f6a2a /pkg/network/subnet.go | |
parent | 511b0717454e0619d9d7d201cb10a41201cebef2 (diff) | |
parent | ee432cf2792c5dbe81953007f1fd5c87beb3ebd5 (diff) | |
download | podman-7042a3d7a539bae79ed63bdc87f432b8ec73afd8.tar.gz podman-7042a3d7a539bae79ed63bdc87f432b8ec73afd8.tar.bz2 podman-7042a3d7a539bae79ed63bdc87f432b8ec73afd8.zip |
Merge pull request #3862 from baude/networkcreate
podman network create
Diffstat (limited to 'pkg/network/subnet.go')
-rw-r--r-- | pkg/network/subnet.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/pkg/network/subnet.go b/pkg/network/subnet.go new file mode 100644 index 000000000..82ab9a8c8 --- /dev/null +++ b/pkg/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 +} |