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 }