github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/network/netconflist.go (about)

     1  package network
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"syscall"
     9  	"time"
    10  
    11  	"github.com/containernetworking/cni/libcni"
    12  	"github.com/containers/common/pkg/config"
    13  	"github.com/containers/podman/v3/pkg/network"
    14  	"github.com/containers/podman/v3/pkg/util"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  const (
    19  	defaultIPv4Route = "0.0.0.0/0"
    20  	defaultIPv6Route = "::/0"
    21  )
    22  
    23  // NcList describes a generic map
    24  type NcList map[string]interface{}
    25  
    26  // NcArgs describes the cni args field
    27  type NcArgs map[string]NcLabels
    28  
    29  // NcLabels describes the label map
    30  type NcLabels map[string]string
    31  
    32  // PodmanLabelKey key used to store the podman network label in a cni config
    33  const PodmanLabelKey = "podman_labels"
    34  
    35  // NewNcList creates a generic map of values with string
    36  // keys and adds in version and network name
    37  func NewNcList(name, version string, labels NcLabels) NcList {
    38  	n := NcList{}
    39  	n["cniVersion"] = version
    40  	n["name"] = name
    41  	if len(labels) > 0 {
    42  		n["args"] = NcArgs{PodmanLabelKey: labels}
    43  	}
    44  	return n
    45  }
    46  
    47  // NewHostLocalBridge creates a new LocalBridge for host-local
    48  func NewHostLocalBridge(name string, isGateWay, isDefaultGW, ipMasq bool, mtu int, vlan int, ipamConf IPAMConfig) *HostLocalBridge {
    49  	hostLocalBridge := HostLocalBridge{
    50  		PluginType:  "bridge",
    51  		BrName:      name,
    52  		IPMasq:      ipMasq,
    53  		MTU:         mtu,
    54  		HairpinMode: true,
    55  		Vlan:        vlan,
    56  		IPAM:        ipamConf,
    57  	}
    58  	if isGateWay {
    59  		hostLocalBridge.IsGW = true
    60  	}
    61  	if isDefaultGW {
    62  		hostLocalBridge.IsDefaultGW = true
    63  	}
    64  	return &hostLocalBridge
    65  }
    66  
    67  // NewIPAMHostLocalConf creates a new IPAMHostLocal configuration
    68  func NewIPAMHostLocalConf(routes []IPAMRoute, ipamRanges [][]IPAMLocalHostRangeConf) (IPAMConfig, error) {
    69  	ipamConf := IPAMConfig{
    70  		PluginType: "host-local",
    71  		Routes:     routes,
    72  		// Possible future support ? Leaving for clues
    73  		//ResolveConf: "",
    74  		//DataDir: ""
    75  	}
    76  
    77  	ipamConf.Ranges = ipamRanges
    78  	return ipamConf, nil
    79  }
    80  
    81  // NewIPAMLocalHostRange create a new IPAM range
    82  func NewIPAMLocalHostRange(subnet *net.IPNet, ipRange *net.IPNet, gw net.IP) ([]IPAMLocalHostRangeConf, error) { //nolint:interfacer
    83  	var ranges []IPAMLocalHostRangeConf
    84  	hostRange := IPAMLocalHostRangeConf{
    85  		Subnet: subnet.String(),
    86  	}
    87  	// an user provided a range, we add it here
    88  	if ipRange != nil && ipRange.IP != nil {
    89  		first, err := FirstIPInSubnet(ipRange)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  		last, err := LastIPInSubnet(ipRange)
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  		hostRange.RangeStart = first.String()
    98  		hostRange.RangeEnd = last.String()
    99  	}
   100  	if gw != nil {
   101  		hostRange.Gateway = gw.String()
   102  	} else {
   103  		// Add first ip in subnet as gateway. It is not required
   104  		// by cni but should be included because of network inspect.
   105  		hostRange.Gateway = CalcGatewayIP(subnet).String()
   106  	}
   107  	ranges = append(ranges, hostRange)
   108  	return ranges, nil
   109  }
   110  
   111  // NewIPAMRoute creates a new IPAM route configuration
   112  func NewIPAMRoute(r *net.IPNet) IPAMRoute { //nolint:interfacer
   113  	return IPAMRoute{Dest: r.String()}
   114  }
   115  
   116  // NewIPAMDefaultRoute creates a new IPAMDefault route of
   117  // 0.0.0.0/0 for IPv4 or ::/0 for IPv6
   118  func NewIPAMDefaultRoute(isIPv6 bool) (IPAMRoute, error) {
   119  	route := defaultIPv4Route
   120  	if isIPv6 {
   121  		route = defaultIPv6Route
   122  	}
   123  	_, n, err := net.ParseCIDR(route)
   124  	if err != nil {
   125  		return IPAMRoute{}, err
   126  	}
   127  	return NewIPAMRoute(n), nil
   128  }
   129  
   130  // NewPortMapPlugin creates a predefined, default portmapping
   131  // configuration
   132  func NewPortMapPlugin() PortMapConfig {
   133  	caps := make(map[string]bool)
   134  	caps["portMappings"] = true
   135  	p := PortMapConfig{
   136  		PluginType:   "portmap",
   137  		Capabilities: caps,
   138  	}
   139  	return p
   140  }
   141  
   142  // NewFirewallPlugin creates a generic firewall plugin
   143  func NewFirewallPlugin() FirewallConfig {
   144  	return FirewallConfig{
   145  		PluginType: "firewall",
   146  	}
   147  }
   148  
   149  // NewTuningPlugin creates a generic tuning section
   150  func NewTuningPlugin() TuningConfig {
   151  	return TuningConfig{
   152  		PluginType: "tuning",
   153  	}
   154  }
   155  
   156  // NewDNSNamePlugin creates the dnsname config with a given
   157  // domainname
   158  func NewDNSNamePlugin(domainName string) DNSNameConfig {
   159  	caps := make(map[string]bool, 1)
   160  	caps["aliases"] = true
   161  	return DNSNameConfig{
   162  		PluginType:   "dnsname",
   163  		DomainName:   domainName,
   164  		Capabilities: caps,
   165  	}
   166  }
   167  
   168  // HasDNSNamePlugin looks to see if the dnsname cni plugin is present
   169  func HasDNSNamePlugin(paths []string) bool {
   170  	for _, p := range paths {
   171  		if _, err := os.Stat(filepath.Join(p, "dnsname")); err == nil {
   172  			return true
   173  		}
   174  	}
   175  	return false
   176  }
   177  
   178  // NewMacVLANPlugin creates a macvlanconfig with a given device name
   179  func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet *net.IPNet, mtu int) (MacVLANConfig, error) {
   180  	i := IPAMConfig{PluginType: "dhcp"}
   181  	if gateway != nil ||
   182  		(ipRange != nil && ipRange.IP != nil && ipRange.Mask != nil) ||
   183  		(subnet != nil && subnet.IP != nil && subnet.Mask != nil) {
   184  		ipam, err := NewIPAMLocalHostRange(subnet, ipRange, gateway)
   185  		if err != nil {
   186  			return MacVLANConfig{}, err
   187  		}
   188  		ranges := make([][]IPAMLocalHostRangeConf, 0)
   189  		ranges = append(ranges, ipam)
   190  		i.Ranges = ranges
   191  		route, err := NewIPAMDefaultRoute(IsIPv6(subnet.IP))
   192  		if err != nil {
   193  			return MacVLANConfig{}, err
   194  		}
   195  		i.Routes = []IPAMRoute{route}
   196  		i.PluginType = "host-local"
   197  	}
   198  
   199  	m := MacVLANConfig{
   200  		PluginType: "macvlan",
   201  		IPAM:       i,
   202  	}
   203  	if mtu > 0 {
   204  		m.MTU = mtu
   205  	}
   206  	// CNI is supposed to use the default route if a
   207  	// parent device is not provided
   208  	if len(device) > 0 {
   209  		m.Master = device
   210  	}
   211  	return m, nil
   212  }
   213  
   214  // IfPassesFilter filters NetworkListReport and returns true if the filter match the given config
   215  func IfPassesFilter(netconf *libcni.NetworkConfigList, filters map[string][]string) (bool, error) {
   216  	result := true
   217  	for key, filterValues := range filters {
   218  		result = false
   219  		switch strings.ToLower(key) {
   220  		case "name":
   221  			// matches one name, regex allowed
   222  			result = util.StringMatchRegexSlice(netconf.Name, filterValues)
   223  
   224  		case "plugin":
   225  			// match one plugin
   226  			plugins := network.GetCNIPlugins(netconf)
   227  			for _, val := range filterValues {
   228  				if strings.Contains(plugins, val) {
   229  					result = true
   230  					break
   231  				}
   232  			}
   233  
   234  		case "label":
   235  			// matches all labels
   236  			result = util.MatchLabelFilters(filterValues, GetNetworkLabels(netconf))
   237  
   238  		case "driver":
   239  			// matches only for the DefaultNetworkDriver
   240  			for _, filterValue := range filterValues {
   241  				plugins := network.GetCNIPlugins(netconf)
   242  				if filterValue == DefaultNetworkDriver &&
   243  					strings.Contains(plugins, DefaultNetworkDriver) {
   244  					result = true
   245  				}
   246  			}
   247  
   248  		case "id":
   249  			// matches part of one id
   250  			for _, filterValue := range filterValues {
   251  				if strings.Contains(network.GetNetworkID(netconf.Name), filterValue) {
   252  					result = true
   253  					break
   254  				}
   255  			}
   256  
   257  		// TODO: add dangling filter
   258  
   259  		default:
   260  			return false, errors.Errorf("invalid filter %q", key)
   261  		}
   262  	}
   263  	return result, nil
   264  }
   265  
   266  // IfPassesPruneFilter filters NetworkListReport and returns true if the prune filter match the given config
   267  func IfPassesPruneFilter(config *config.Config, netconf *libcni.NetworkConfigList, f map[string][]string) (bool, error) {
   268  	for key, filterValues := range f {
   269  		switch strings.ToLower(key) {
   270  		case "label":
   271  			return util.MatchLabelFilters(filterValues, GetNetworkLabels(netconf)), nil
   272  		case "until":
   273  			until, err := util.ComputeUntilTimestamp(filterValues)
   274  			if err != nil {
   275  				return false, err
   276  			}
   277  			created, err := getCreatedTimestamp(config, netconf)
   278  			if err != nil {
   279  				return false, err
   280  			}
   281  			if created.Before(until) {
   282  				return true, nil
   283  			}
   284  		default:
   285  			return false, errors.Errorf("invalid filter %q", key)
   286  		}
   287  	}
   288  	return false, nil
   289  }
   290  
   291  func getCreatedTimestamp(config *config.Config, netconf *libcni.NetworkConfigList) (*time.Time, error) {
   292  	networkConfigPath, err := GetCNIConfigPathByNameOrID(config, netconf.Name)
   293  	if err != nil {
   294  		return nil, err
   295  	}
   296  	f, err := os.Stat(networkConfigPath)
   297  	if err != nil {
   298  		return nil, err
   299  	}
   300  	stat := f.Sys().(*syscall.Stat_t)
   301  	created := time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)) // nolint: unconvert
   302  	return &created, nil
   303  }
   304  
   305  func NewPodmanMachinePlugin() PodmanMachineConfig {
   306  	caps := make(map[string]bool, 1)
   307  	caps["portMappings"] = true
   308  	return PodmanMachineConfig{
   309  		PluginType:   "podman-machine",
   310  		Capabilities: caps,
   311  	}
   312  }