summaryrefslogtreecommitdiff
path: root/libpod/network/internal/util/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/network/internal/util/util.go')
-rw-r--r--libpod/network/internal/util/util.go123
1 files changed, 123 insertions, 0 deletions
diff --git a/libpod/network/internal/util/util.go b/libpod/network/internal/util/util.go
new file mode 100644
index 000000000..bf9d70aba
--- /dev/null
+++ b/libpod/network/internal/util/util.go
@@ -0,0 +1,123 @@
+package util
+
+import (
+ "errors"
+ "fmt"
+ "net"
+
+ "github.com/containers/podman/v3/libpod/network/types"
+ "github.com/containers/podman/v3/pkg/util"
+ "github.com/sirupsen/logrus"
+)
+
+// GetBridgeInterfaceNames returns all bridge interface names
+// already used by network configs
+func GetBridgeInterfaceNames(n NetUtil) []string {
+ names := make([]string, 0, n.Len())
+ n.ForEach(func(net types.Network) {
+ if net.Driver == types.BridgeNetworkDriver {
+ names = append(names, net.NetworkInterface)
+ }
+ })
+ return names
+}
+
+// GetUsedNetworkNames returns all network names already used
+// by network configs
+func GetUsedNetworkNames(n NetUtil) []string {
+ names := make([]string, 0, n.Len())
+ n.ForEach(func(net types.Network) {
+ if net.Driver == types.BridgeNetworkDriver {
+ names = append(names, net.NetworkInterface)
+ }
+ })
+ return names
+}
+
+// GetFreeDeviceName returns a free device name which can
+// be used for new configs as name and bridge interface name.
+// The base name is suffixed by a number
+func GetFreeDeviceName(n NetUtil) (string, error) {
+ bridgeNames := GetBridgeInterfaceNames(n)
+ netNames := GetUsedNetworkNames(n)
+ liveInterfaces, err := GetLiveNetworkNames()
+ if err != nil {
+ return "", nil
+ }
+ names := make([]string, 0, len(bridgeNames)+len(netNames)+len(liveInterfaces))
+ names = append(names, bridgeNames...)
+ names = append(names, netNames...)
+ names = append(names, liveInterfaces...)
+ // FIXME: Is a limit fine?
+ // Start by 1, 0 is reserved for the default network
+ for i := 1; i < 1000000; i++ {
+ deviceName := fmt.Sprintf("%s%d", n.DefaultInterfaceName(), i)
+ if !util.StringInSlice(deviceName, names) {
+ logrus.Debugf("found free device name %s", deviceName)
+ return deviceName, nil
+ }
+ }
+ return "", errors.New("could not find free device name, to many iterations")
+}
+
+// GetUsedSubnets returns a list of all used subnets by network
+// configs and interfaces on the host.
+func GetUsedSubnets(n NetUtil) ([]*net.IPNet, error) {
+ // first, load all used subnets from network configs
+ subnets := make([]*net.IPNet, 0, n.Len())
+ n.ForEach(func(n types.Network) {
+ for i := range n.Subnets {
+ subnets = append(subnets, &n.Subnets[i].Subnet.IPNet)
+ }
+ })
+ // second, load networks from the current system
+ liveSubnets, err := getLiveNetworkSubnets()
+ if err != nil {
+ return nil, err
+ }
+ return append(subnets, liveSubnets...), nil
+}
+
+// GetFreeIPv6NetworkSubnet returns a unused ipv4 subnet
+func GetFreeIPv4NetworkSubnet(usedNetworks []*net.IPNet) (*types.Subnet, error) {
+ // the default podman network is 10.88.0.0/16
+ // start locking for free /24 networks
+ network := &net.IPNet{
+ IP: net.IP{10, 89, 0, 0},
+ Mask: net.IPMask{255, 255, 255, 0},
+ }
+
+ // TODO: make sure to not use public subnets
+ for {
+ if intersectsConfig := NetworkIntersectsWithNetworks(network, usedNetworks); !intersectsConfig {
+ logrus.Debugf("found free ipv4 network subnet %s", network.String())
+ return &types.Subnet{
+ Subnet: types.IPNet{IPNet: *network},
+ }, nil
+ }
+ var err error
+ network, err = NextSubnet(network)
+ if err != nil {
+ return nil, err
+ }
+ }
+}
+
+// GetFreeIPv6NetworkSubnet returns a unused ipv6 subnet
+func GetFreeIPv6NetworkSubnet(usedNetworks []*net.IPNet) (*types.Subnet, error) {
+ // FIXME: Is 10000 fine as limit? We should prevent an endless loop.
+ for i := 0; i < 10000; i++ {
+ // RFC4193: Choose the ipv6 subnet random and NOT sequentially.
+ network, err := getRandomIPv6Subnet()
+ if err != nil {
+ return nil, err
+ }
+ if intersectsConfig := NetworkIntersectsWithNetworks(&network, usedNetworks); !intersectsConfig {
+ logrus.Debugf("found free ipv6 network subnet %s", network.String())
+ return &types.Subnet{
+ Subnet: types.IPNet{IPNet: network},
+ }, nil
+ }
+ }
+ return nil, errors.New("failed to get random ipv6 subnet")
+}