github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/netutils/utils_linux.go (about)

     1  //go:build linux
     2  
     3  // Network utility functions.
     4  
     5  package netutils
     6  
     7  import (
     8  	"net"
     9  	"os"
    10  
    11  	"github.com/Prakhar-Agarwal-byte/moby/libnetwork/ns"
    12  	"github.com/Prakhar-Agarwal-byte/moby/libnetwork/resolvconf"
    13  	"github.com/Prakhar-Agarwal-byte/moby/libnetwork/types"
    14  	"github.com/pkg/errors"
    15  	"github.com/vishvananda/netlink"
    16  )
    17  
    18  var networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error)
    19  
    20  // CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
    21  func CheckRouteOverlaps(toCheck *net.IPNet) error {
    22  	networkGetRoutesFct := networkGetRoutesFct
    23  	if networkGetRoutesFct == nil {
    24  		networkGetRoutesFct = ns.NlHandle().RouteList
    25  	}
    26  	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
    27  	if err != nil {
    28  		return err
    29  	}
    30  	for _, network := range networks {
    31  		if network.Dst != nil && network.Scope == netlink.SCOPE_LINK && NetworkOverlaps(toCheck, network.Dst) {
    32  			return ErrNetworkOverlaps
    33  		}
    34  	}
    35  	return nil
    36  }
    37  
    38  // GenerateIfaceName returns an interface name using the passed in
    39  // prefix and the length of random bytes. The api ensures that the
    40  // there are is no interface which exists with that name.
    41  func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, error) {
    42  	linkByName := netlink.LinkByName
    43  	if nlh != nil {
    44  		linkByName = nlh.LinkByName
    45  	}
    46  	for i := 0; i < 3; i++ {
    47  		name, err := GenerateRandomName(prefix, len)
    48  		if err != nil {
    49  			return "", err
    50  		}
    51  		_, err = linkByName(name)
    52  		if err != nil {
    53  			if errors.As(err, &netlink.LinkNotFoundError{}) {
    54  				return name, nil
    55  			}
    56  			return "", err
    57  		}
    58  	}
    59  	return "", types.InternalErrorf("could not generate interface name")
    60  }
    61  
    62  // FindAvailableNetwork returns a network from the passed list which does not
    63  // overlap with existing interfaces in the system
    64  func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
    65  	// We don't check for an error here, because we don't really care if we
    66  	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
    67  	// is nil. It either doesn't exist, or we can't read it for some reason.
    68  	var nameservers []string
    69  	if rc, err := os.ReadFile(resolvconf.Path()); err == nil {
    70  		nameservers = resolvconf.GetNameserversAsCIDR(rc)
    71  	}
    72  	for _, nw := range list {
    73  		if err := CheckNameserverOverlaps(nameservers, nw); err == nil {
    74  			if err := CheckRouteOverlaps(nw); err == nil {
    75  				return nw, nil
    76  			}
    77  		}
    78  	}
    79  	return nil, errors.New("no available network")
    80  }