github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/network/subnet.go (about) 1 package network 2 3 /* 4 The code in this was kindly contributed by Dan Williams(dcbw@redhat.com). Many thanks 5 for his contributions. 6 */ 7 8 import ( 9 "fmt" 10 "net" 11 ) 12 13 func incByte(subnet *net.IPNet, idx int, shift uint) error { 14 if idx < 0 { 15 return fmt.Errorf("no more subnets left") 16 } 17 if subnet.IP[idx] == 255 { 18 subnet.IP[idx] = 0 19 return incByte(subnet, idx-1, 0) 20 } 21 subnet.IP[idx] += 1 << shift 22 return nil 23 } 24 25 // NextSubnet returns subnet incremented by 1 26 func NextSubnet(subnet *net.IPNet) (*net.IPNet, error) { 27 newSubnet := &net.IPNet{ 28 IP: subnet.IP, 29 Mask: subnet.Mask, 30 } 31 ones, bits := newSubnet.Mask.Size() 32 if ones == 0 { 33 return nil, fmt.Errorf("%s has only one subnet", subnet.String()) 34 } 35 zeroes := uint(bits - ones) 36 shift := zeroes % 8 37 idx := ones/8 - 1 38 if idx < 0 { 39 idx = 0 40 } 41 if err := incByte(newSubnet, idx, shift); err != nil { 42 return nil, err 43 } 44 return newSubnet, nil 45 } 46 47 // LastIPInSubnet gets the last IP in a subnet 48 func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer 49 // re-parse to ensure clean network address 50 _, cidr, err := net.ParseCIDR(addr.String()) 51 if err != nil { 52 return nil, err 53 } 54 55 ones, bits := cidr.Mask.Size() 56 if ones == bits { 57 return cidr.IP, nil 58 } 59 for i := range cidr.IP { 60 cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i] 61 } 62 return cidr.IP, nil 63 } 64 65 // FirstIPInSubnet gets the first IP in a subnet 66 func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer 67 // re-parse to ensure clean network address 68 _, cidr, err := net.ParseCIDR(addr.String()) 69 if err != nil { 70 return nil, err 71 } 72 ones, bits := cidr.Mask.Size() 73 if ones == bits { 74 return cidr.IP, nil 75 } 76 cidr.IP[len(cidr.IP)-1]++ 77 return cidr.IP, nil 78 }