github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/drivers/bridge/bridge_linux.go (about) 1 package bridge 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net" 8 "os" 9 "os/exec" 10 "strconv" 11 "sync" 12 13 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/datastore" 14 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/driverapi" 15 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/iptables" 16 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/netlabel" 17 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/netutils" 18 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/ns" 19 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/options" 20 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/portallocator" 21 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/portmapper" 22 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/scope" 23 "github.com/Prakhar-Agarwal-byte/moby/libnetwork/types" 24 "github.com/containerd/log" 25 "github.com/vishvananda/netlink" 26 ) 27 28 const ( 29 NetworkType = "bridge" 30 vethPrefix = "veth" 31 vethLen = len(vethPrefix) + 7 32 defaultContainerVethPrefix = "eth" 33 maxAllocatePortAttempts = 10 34 ) 35 36 const ( 37 // DefaultGatewayV4AuxKey represents the default-gateway configured by the user 38 DefaultGatewayV4AuxKey = "DefaultGatewayIPv4" 39 // DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user 40 DefaultGatewayV6AuxKey = "DefaultGatewayIPv6" 41 ) 42 43 type defaultBridgeNetworkConflict struct { 44 ID string 45 } 46 47 func (d defaultBridgeNetworkConflict) Error() string { 48 return fmt.Sprintf("Stale default bridge network %s", d.ID) 49 } 50 51 type ( 52 iptableCleanFunc func() error 53 iptablesCleanFuncs []iptableCleanFunc 54 ) 55 56 // configuration info for the "bridge" driver. 57 type configuration struct { 58 EnableIPForwarding bool 59 EnableIPTables bool 60 EnableIP6Tables bool 61 EnableUserlandProxy bool 62 UserlandProxyPath string 63 } 64 65 // networkConfiguration for network specific configuration 66 type networkConfiguration struct { 67 ID string 68 BridgeName string 69 EnableIPv6 bool 70 EnableIPMasquerade bool 71 EnableICC bool 72 InhibitIPv4 bool 73 Mtu int 74 DefaultBindingIP net.IP 75 DefaultBridge bool 76 HostIPv4 net.IP 77 ContainerIfacePrefix string 78 // Internal fields set after ipam data parsing 79 AddressIPv4 *net.IPNet 80 AddressIPv6 *net.IPNet 81 DefaultGatewayIPv4 net.IP 82 DefaultGatewayIPv6 net.IP 83 dbIndex uint64 84 dbExists bool 85 Internal bool 86 87 BridgeIfaceCreator ifaceCreator 88 } 89 90 // ifaceCreator represents how the bridge interface was created 91 type ifaceCreator int8 92 93 const ( 94 ifaceCreatorUnknown ifaceCreator = iota 95 ifaceCreatedByLibnetwork 96 ifaceCreatedByUser 97 ) 98 99 // endpointConfiguration represents the user specified configuration for the sandbox endpoint 100 type endpointConfiguration struct { 101 MacAddress net.HardwareAddr 102 } 103 104 // containerConfiguration represents the user specified configuration for a container 105 type containerConfiguration struct { 106 ParentEndpoints []string 107 ChildEndpoints []string 108 } 109 110 // connectivityConfiguration represents the user specified configuration regarding the external connectivity 111 type connectivityConfiguration struct { 112 PortBindings []types.PortBinding 113 ExposedPorts []types.TransportPort 114 } 115 116 type bridgeEndpoint struct { 117 id string 118 nid string 119 srcName string 120 addr *net.IPNet 121 addrv6 *net.IPNet 122 macAddress net.HardwareAddr 123 config *endpointConfiguration // User specified parameters 124 containerConfig *containerConfiguration 125 extConnConfig *connectivityConfiguration 126 portMapping []types.PortBinding // Operation port bindings 127 dbIndex uint64 128 dbExists bool 129 } 130 131 type bridgeNetwork struct { 132 id string 133 bridge *bridgeInterface // The bridge's L3 interface 134 config *networkConfiguration 135 endpoints map[string]*bridgeEndpoint // key: endpoint id 136 portMapper *portmapper.PortMapper 137 portMapperV6 *portmapper.PortMapper 138 driver *driver // The network's driver 139 iptCleanFuncs iptablesCleanFuncs 140 sync.Mutex 141 } 142 143 type driver struct { 144 config configuration 145 natChain *iptables.ChainInfo 146 filterChain *iptables.ChainInfo 147 isolationChain1 *iptables.ChainInfo 148 isolationChain2 *iptables.ChainInfo 149 natChainV6 *iptables.ChainInfo 150 filterChainV6 *iptables.ChainInfo 151 isolationChain1V6 *iptables.ChainInfo 152 isolationChain2V6 *iptables.ChainInfo 153 networks map[string]*bridgeNetwork 154 store *datastore.Store 155 nlh *netlink.Handle 156 configNetwork sync.Mutex 157 portAllocator *portallocator.PortAllocator // Overridable for tests. 158 sync.Mutex 159 } 160 161 // New constructs a new bridge driver 162 func newDriver() *driver { 163 return &driver{ 164 networks: map[string]*bridgeNetwork{}, 165 portAllocator: portallocator.Get(), 166 } 167 } 168 169 // Register registers a new instance of bridge driver. 170 func Register(r driverapi.Registerer, config map[string]interface{}) error { 171 d := newDriver() 172 if err := d.configure(config); err != nil { 173 return err 174 } 175 return r.RegisterDriver(NetworkType, d, driverapi.Capability{ 176 DataScope: scope.Local, 177 ConnectivityScope: scope.Local, 178 }) 179 } 180 181 // Validate performs a static validation on the network configuration parameters. 182 // Whatever can be assessed a priori before attempting any programming. 183 func (c *networkConfiguration) Validate() error { 184 if c.Mtu < 0 { 185 return ErrInvalidMtu(c.Mtu) 186 } 187 188 // If bridge v4 subnet is specified 189 if c.AddressIPv4 != nil { 190 // If default gw is specified, it must be part of bridge subnet 191 if c.DefaultGatewayIPv4 != nil { 192 if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) { 193 return &ErrInvalidGateway{} 194 } 195 } 196 } 197 198 // If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet 199 if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil { 200 if c.AddressIPv6 == nil || !c.AddressIPv6.Contains(c.DefaultGatewayIPv6) { 201 return &ErrInvalidGateway{} 202 } 203 } 204 return nil 205 } 206 207 // Conflicts check if two NetworkConfiguration objects overlap 208 func (c *networkConfiguration) Conflicts(o *networkConfiguration) error { 209 if o == nil { 210 return errors.New("same configuration") 211 } 212 213 // Also empty, because only one network with empty name is allowed 214 if c.BridgeName == o.BridgeName { 215 return errors.New("networks have same bridge name") 216 } 217 218 // They must be in different subnets 219 if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) && 220 (c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) { 221 return errors.New("networks have overlapping IPv4") 222 } 223 224 // They must be in different v6 subnets 225 if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) && 226 (c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) { 227 return errors.New("networks have overlapping IPv6") 228 } 229 230 return nil 231 } 232 233 func (c *networkConfiguration) fromLabels(labels map[string]string) error { 234 var err error 235 for label, value := range labels { 236 switch label { 237 case BridgeName: 238 c.BridgeName = value 239 case netlabel.DriverMTU: 240 if c.Mtu, err = strconv.Atoi(value); err != nil { 241 return parseErr(label, value, err.Error()) 242 } 243 case netlabel.EnableIPv6: 244 if c.EnableIPv6, err = strconv.ParseBool(value); err != nil { 245 return parseErr(label, value, err.Error()) 246 } 247 case EnableIPMasquerade: 248 if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil { 249 return parseErr(label, value, err.Error()) 250 } 251 case EnableICC: 252 if c.EnableICC, err = strconv.ParseBool(value); err != nil { 253 return parseErr(label, value, err.Error()) 254 } 255 case InhibitIPv4: 256 if c.InhibitIPv4, err = strconv.ParseBool(value); err != nil { 257 return parseErr(label, value, err.Error()) 258 } 259 case DefaultBridge: 260 if c.DefaultBridge, err = strconv.ParseBool(value); err != nil { 261 return parseErr(label, value, err.Error()) 262 } 263 case DefaultBindingIP: 264 if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil { 265 return parseErr(label, value, "nil ip") 266 } 267 case netlabel.ContainerIfacePrefix: 268 c.ContainerIfacePrefix = value 269 case netlabel.HostIPv4: 270 if c.HostIPv4 = net.ParseIP(value); c.HostIPv4 == nil { 271 return parseErr(label, value, "nil ip") 272 } 273 } 274 } 275 276 return nil 277 } 278 279 func parseErr(label, value, errString string) error { 280 return types.InvalidParameterErrorf("failed to parse %s value: %v (%s)", label, value, errString) 281 } 282 283 func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) { 284 n.iptCleanFuncs = append(n.iptCleanFuncs, clean) 285 } 286 287 func (n *bridgeNetwork) getDriverChains(version iptables.IPVersion) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) { 288 n.Lock() 289 defer n.Unlock() 290 291 if n.driver == nil { 292 return nil, nil, nil, nil, types.InvalidParameterErrorf("no driver found") 293 } 294 295 if version == iptables.IPv6 { 296 return n.driver.natChainV6, n.driver.filterChainV6, n.driver.isolationChain1V6, n.driver.isolationChain2V6, nil 297 } 298 299 return n.driver.natChain, n.driver.filterChain, n.driver.isolationChain1, n.driver.isolationChain2, nil 300 } 301 302 func (n *bridgeNetwork) getNetworkBridgeName() string { 303 n.Lock() 304 config := n.config 305 n.Unlock() 306 307 return config.BridgeName 308 } 309 310 func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) { 311 if eid == "" { 312 return nil, InvalidEndpointIDError(eid) 313 } 314 315 n.Lock() 316 defer n.Unlock() 317 if ep, ok := n.endpoints[eid]; ok { 318 return ep, nil 319 } 320 321 return nil, nil 322 } 323 324 // Install/Removes the iptables rules needed to isolate this network 325 // from each of the other networks 326 func (n *bridgeNetwork) isolateNetwork(enable bool) error { 327 n.Lock() 328 thisConfig := n.config 329 n.Unlock() 330 331 if thisConfig.Internal { 332 return nil 333 } 334 335 // Install the rules to isolate this network against each of the other networks 336 if n.driver.config.EnableIP6Tables { 337 err := setINC(iptables.IPv6, thisConfig.BridgeName, enable) 338 if err != nil { 339 return err 340 } 341 } 342 343 if n.driver.config.EnableIPTables { 344 return setINC(iptables.IPv4, thisConfig.BridgeName, enable) 345 } 346 return nil 347 } 348 349 func (d *driver) configure(option map[string]interface{}) error { 350 var ( 351 config configuration 352 err error 353 natChain *iptables.ChainInfo 354 filterChain *iptables.ChainInfo 355 isolationChain1 *iptables.ChainInfo 356 isolationChain2 *iptables.ChainInfo 357 natChainV6 *iptables.ChainInfo 358 filterChainV6 *iptables.ChainInfo 359 isolationChain1V6 *iptables.ChainInfo 360 isolationChain2V6 *iptables.ChainInfo 361 ) 362 363 switch opt := option[netlabel.GenericData].(type) { 364 case options.Generic: 365 opaqueConfig, err := options.GenerateFromModel(opt, &configuration{}) 366 if err != nil { 367 return err 368 } 369 config = *opaqueConfig.(*configuration) 370 case *configuration: 371 config = *opt 372 case nil: 373 // No GenericData option set. Use defaults. 374 default: 375 return &ErrInvalidDriverConfig{} 376 } 377 378 if config.EnableIPTables || config.EnableIP6Tables { 379 if _, err := os.Stat("/proc/sys/net/bridge"); err != nil { 380 if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil { 381 log.G(context.TODO()).Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err) 382 } 383 } 384 } 385 386 if config.EnableIPTables { 387 removeIPChains(iptables.IPv4) 388 389 natChain, filterChain, isolationChain1, isolationChain2, err = setupIPChains(config, iptables.IPv4) 390 if err != nil { 391 return err 392 } 393 394 // Make sure on firewall reload, first thing being re-played is chains creation 395 iptables.OnReloaded(func() { 396 log.G(context.TODO()).Debugf("Recreating iptables chains on firewall reload") 397 if _, _, _, _, err := setupIPChains(config, iptables.IPv4); err != nil { 398 log.G(context.TODO()).WithError(err).Error("Error reloading iptables chains") 399 } 400 }) 401 } 402 403 if config.EnableIP6Tables { 404 removeIPChains(iptables.IPv6) 405 406 natChainV6, filterChainV6, isolationChain1V6, isolationChain2V6, err = setupIPChains(config, iptables.IPv6) 407 if err != nil { 408 return err 409 } 410 411 // Make sure on firewall reload, first thing being re-played is chains creation 412 iptables.OnReloaded(func() { 413 log.G(context.TODO()).Debugf("Recreating ip6tables chains on firewall reload") 414 if _, _, _, _, err := setupIPChains(config, iptables.IPv6); err != nil { 415 log.G(context.TODO()).WithError(err).Error("Error reloading ip6tables chains") 416 } 417 }) 418 } 419 420 if config.EnableIPForwarding { 421 err = setupIPForwarding(config.EnableIPTables, config.EnableIP6Tables) 422 if err != nil { 423 log.G(context.TODO()).Warn(err) 424 return err 425 } 426 } 427 428 d.Lock() 429 d.natChain = natChain 430 d.filterChain = filterChain 431 d.isolationChain1 = isolationChain1 432 d.isolationChain2 = isolationChain2 433 d.natChainV6 = natChainV6 434 d.filterChainV6 = filterChainV6 435 d.isolationChain1V6 = isolationChain1V6 436 d.isolationChain2V6 = isolationChain2V6 437 d.config = config 438 d.Unlock() 439 440 return d.initStore(option) 441 } 442 443 func (d *driver) getNetwork(id string) (*bridgeNetwork, error) { 444 d.Lock() 445 defer d.Unlock() 446 447 if id == "" { 448 return nil, types.InvalidParameterErrorf("invalid network id: %s", id) 449 } 450 451 if nw, ok := d.networks[id]; ok { 452 return nw, nil 453 } 454 455 return nil, types.NotFoundErrorf("network not found: %s", id) 456 } 457 458 func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error) { 459 var ( 460 err error 461 config *networkConfiguration 462 ) 463 464 switch opt := data.(type) { 465 case *networkConfiguration: 466 config = opt 467 case map[string]string: 468 config = &networkConfiguration{ 469 EnableICC: true, 470 EnableIPMasquerade: true, 471 } 472 err = config.fromLabels(opt) 473 case options.Generic: 474 var opaqueConfig interface{} 475 if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil { 476 config = opaqueConfig.(*networkConfiguration) 477 } 478 default: 479 err = types.InvalidParameterErrorf("do not recognize network configuration format: %T", opt) 480 } 481 482 return config, err 483 } 484 485 func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error { 486 if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 { 487 return types.ForbiddenErrorf("bridge driver doesn't support multiple subnets") 488 } 489 490 if len(ipamV4Data) == 0 { 491 return types.InvalidParameterErrorf("bridge network %s requires ipv4 configuration", id) 492 } 493 494 if ipamV4Data[0].Gateway != nil { 495 c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway) 496 } 497 498 if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok { 499 c.DefaultGatewayIPv4 = gw.IP 500 } 501 502 if len(ipamV6Data) > 0 { 503 c.AddressIPv6 = ipamV6Data[0].Pool 504 505 if ipamV6Data[0].Gateway != nil { 506 c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway) 507 } 508 509 if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok { 510 c.DefaultGatewayIPv6 = gw.IP 511 } 512 } 513 514 return nil 515 } 516 517 func parseNetworkOptions(id string, option options.Generic) (*networkConfiguration, error) { 518 var ( 519 err error 520 config = &networkConfiguration{} 521 ) 522 523 // Parse generic label first, config will be re-assigned 524 if genData, ok := option[netlabel.GenericData]; ok && genData != nil { 525 if config, err = parseNetworkGenericOptions(genData); err != nil { 526 return nil, err 527 } 528 } 529 530 // Process well-known labels next 531 if val, ok := option[netlabel.EnableIPv6]; ok { 532 config.EnableIPv6 = val.(bool) 533 } 534 535 if val, ok := option[netlabel.Internal]; ok { 536 if internal, ok := val.(bool); ok && internal { 537 config.Internal = true 538 } 539 } 540 541 // Finally validate the configuration 542 if err = config.Validate(); err != nil { 543 return nil, err 544 } 545 546 if config.BridgeName == "" && !config.DefaultBridge { 547 config.BridgeName = "br-" + id[:12] 548 } 549 550 exists, err := bridgeInterfaceExists(config.BridgeName) 551 if err != nil { 552 return nil, err 553 } 554 555 if !exists { 556 config.BridgeIfaceCreator = ifaceCreatedByLibnetwork 557 } else { 558 config.BridgeIfaceCreator = ifaceCreatedByUser 559 } 560 561 config.ID = id 562 return config, nil 563 } 564 565 // Return a slice of networks over which caller can iterate safely 566 func (d *driver) getNetworks() []*bridgeNetwork { 567 d.Lock() 568 defer d.Unlock() 569 570 ls := make([]*bridgeNetwork, 0, len(d.networks)) 571 for _, nw := range d.networks { 572 ls = append(ls, nw) 573 } 574 return ls 575 } 576 577 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 578 return nil, types.NotImplementedErrorf("not implemented") 579 } 580 581 func (d *driver) NetworkFree(id string) error { 582 return types.NotImplementedErrorf("not implemented") 583 } 584 585 func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { 586 } 587 588 func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) { 589 return "", nil 590 } 591 592 // Create a new network using bridge plugin 593 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 594 if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { 595 return types.InvalidParameterErrorf("ipv4 pool is empty") 596 } 597 // Sanity checks 598 d.Lock() 599 if _, ok := d.networks[id]; ok { 600 d.Unlock() 601 return types.ForbiddenErrorf("network %s exists", id) 602 } 603 d.Unlock() 604 605 // Parse and validate the config. It should not be conflict with existing networks' config 606 config, err := parseNetworkOptions(id, option) 607 if err != nil { 608 return err 609 } 610 611 if err = config.processIPAM(id, ipV4Data, ipV6Data); err != nil { 612 return err 613 } 614 615 // start the critical section, from this point onward we are dealing with the list of networks 616 // so to be consistent we cannot allow that the list changes 617 d.configNetwork.Lock() 618 defer d.configNetwork.Unlock() 619 620 // check network conflicts 621 if err = d.checkConflict(config); err != nil { 622 nerr, ok := err.(defaultBridgeNetworkConflict) 623 if !ok { 624 return err 625 } 626 // Got a conflict with a stale default network, clean that up and continue 627 log.G(context.TODO()).Warn(nerr) 628 if err := d.deleteNetwork(nerr.ID); err != nil { 629 log.G(context.TODO()).WithError(err).Debug("Error while cleaning up network on conflict") 630 } 631 } 632 633 // there is no conflict, now create the network 634 if err = d.createNetwork(config); err != nil { 635 return err 636 } 637 638 return d.storeUpdate(config) 639 } 640 641 func (d *driver) checkConflict(config *networkConfiguration) error { 642 networkList := d.getNetworks() 643 for _, nw := range networkList { 644 nw.Lock() 645 nwConfig := nw.config 646 nw.Unlock() 647 if err := nwConfig.Conflicts(config); err != nil { 648 if nwConfig.DefaultBridge { 649 // We encountered and identified a stale default network 650 // We must delete it as libnetwork is the source of truth 651 // The default network being created must be the only one 652 // This can happen only from docker 1.12 on ward 653 log.G(context.TODO()).Infof("Found stale default bridge network %s (%s)", nwConfig.ID, nwConfig.BridgeName) 654 return defaultBridgeNetworkConflict{nwConfig.ID} 655 } 656 657 return types.ForbiddenErrorf("cannot create network %s (%s): conflicts with network %s (%s): %s", 658 config.ID, config.BridgeName, nwConfig.ID, nwConfig.BridgeName, err.Error()) 659 } 660 } 661 return nil 662 } 663 664 func (d *driver) createNetwork(config *networkConfiguration) (err error) { 665 // Initialize handle when needed 666 d.Lock() 667 if d.nlh == nil { 668 d.nlh = ns.NlHandle() 669 } 670 d.Unlock() 671 672 // Create or retrieve the bridge L3 interface 673 bridgeIface, err := newInterface(d.nlh, config) 674 if err != nil { 675 return err 676 } 677 678 // Create and set network handler in driver 679 network := &bridgeNetwork{ 680 id: config.ID, 681 endpoints: make(map[string]*bridgeEndpoint), 682 config: config, 683 portMapper: portmapper.NewWithPortAllocator(d.portAllocator, d.config.UserlandProxyPath), 684 portMapperV6: portmapper.NewWithPortAllocator(d.portAllocator, d.config.UserlandProxyPath), 685 bridge: bridgeIface, 686 driver: d, 687 } 688 689 d.Lock() 690 d.networks[config.ID] = network 691 d.Unlock() 692 693 // On failure make sure to reset driver network handler to nil 694 defer func() { 695 if err != nil { 696 d.Lock() 697 delete(d.networks, config.ID) 698 d.Unlock() 699 } 700 }() 701 702 // Add inter-network communication rules. 703 setupNetworkIsolationRules := func(config *networkConfiguration, i *bridgeInterface) error { 704 if err := network.isolateNetwork(true); err != nil { 705 if err = network.isolateNetwork(false); err != nil { 706 log.G(context.TODO()).Warnf("Failed on removing the inter-network iptables rules on cleanup: %v", err) 707 } 708 return err 709 } 710 // register the cleanup function 711 network.registerIptCleanFunc(func() error { 712 return network.isolateNetwork(false) 713 }) 714 return nil 715 } 716 717 // Prepare the bridge setup configuration 718 bridgeSetup := newBridgeSetup(config, bridgeIface) 719 720 // If the bridge interface doesn't exist, we need to start the setup steps 721 // by creating a new device and assigning it an IPv4 address. 722 bridgeAlreadyExists := bridgeIface.exists() 723 if !bridgeAlreadyExists { 724 bridgeSetup.queueStep(setupDevice) 725 bridgeSetup.queueStep(setupDefaultSysctl) 726 } 727 728 // For the default bridge, set expected sysctls 729 if config.DefaultBridge { 730 bridgeSetup.queueStep(setupDefaultSysctl) 731 } 732 733 // Even if a bridge exists try to setup IPv4. 734 bridgeSetup.queueStep(setupBridgeIPv4) 735 736 enableIPv6Forwarding := d.config.EnableIPForwarding && config.AddressIPv6 != nil 737 738 // Conditionally queue setup steps depending on configuration values. 739 for _, step := range []struct { 740 Condition bool 741 Fn setupStep 742 }{ 743 // Enable IPv6 on the bridge if required. We do this even for a 744 // previously existing bridge, as it may be here from a previous 745 // installation where IPv6 wasn't supported yet and needs to be 746 // assigned an IPv6 link-local address. 747 {config.EnableIPv6, setupBridgeIPv6}, 748 749 // We ensure that the bridge has the expectedIPv4 and IPv6 addresses in 750 // the case of a previously existing device. 751 {bridgeAlreadyExists && !config.InhibitIPv4, setupVerifyAndReconcile}, 752 753 // Enable IPv6 Forwarding 754 {enableIPv6Forwarding, setupIPv6Forwarding}, 755 756 // Setup Loopback Addresses Routing 757 {!d.config.EnableUserlandProxy, setupLoopbackAddressesRouting}, 758 759 // Setup IPTables. 760 {d.config.EnableIPTables, network.setupIP4Tables}, 761 762 // Setup IP6Tables. 763 {config.EnableIPv6 && d.config.EnableIP6Tables, network.setupIP6Tables}, 764 765 // We want to track firewalld configuration so that 766 // if it is started/reloaded, the rules can be applied correctly 767 {d.config.EnableIPTables, network.setupFirewalld}, 768 // same for IPv6 769 {config.EnableIPv6 && d.config.EnableIP6Tables, network.setupFirewalld6}, 770 771 // Setup DefaultGatewayIPv4 772 {config.DefaultGatewayIPv4 != nil, setupGatewayIPv4}, 773 774 // Setup DefaultGatewayIPv6 775 {config.DefaultGatewayIPv6 != nil, setupGatewayIPv6}, 776 777 // Add inter-network communication rules. 778 {d.config.EnableIPTables, setupNetworkIsolationRules}, 779 780 // Configure bridge networking filtering if ICC is off and IP tables are enabled 781 {!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering}, 782 } { 783 if step.Condition { 784 bridgeSetup.queueStep(step.Fn) 785 } 786 } 787 788 // Apply the prepared list of steps, and abort at the first error. 789 bridgeSetup.queueStep(setupDeviceUp) 790 return bridgeSetup.apply() 791 } 792 793 func (d *driver) DeleteNetwork(nid string) error { 794 d.configNetwork.Lock() 795 defer d.configNetwork.Unlock() 796 797 return d.deleteNetwork(nid) 798 } 799 800 func (d *driver) deleteNetwork(nid string) error { 801 var err error 802 803 // Get network handler and remove it from driver 804 d.Lock() 805 n, ok := d.networks[nid] 806 d.Unlock() 807 808 if !ok { 809 return types.InternalMaskableErrorf("network %s does not exist", nid) 810 } 811 812 n.Lock() 813 config := n.config 814 n.Unlock() 815 816 // delele endpoints belong to this network 817 for _, ep := range n.endpoints { 818 if err := n.releasePorts(ep); err != nil { 819 log.G(context.TODO()).Warn(err) 820 } 821 if link, err := d.nlh.LinkByName(ep.srcName); err == nil { 822 if err := d.nlh.LinkDel(link); err != nil { 823 log.G(context.TODO()).WithError(err).Errorf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id) 824 } 825 } 826 827 if err := d.storeDelete(ep); err != nil { 828 log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err) 829 } 830 } 831 832 d.Lock() 833 delete(d.networks, nid) 834 d.Unlock() 835 836 // On failure set network handler back in driver, but 837 // only if is not already taken over by some other thread 838 defer func() { 839 if err != nil { 840 d.Lock() 841 if _, ok := d.networks[nid]; !ok { 842 d.networks[nid] = n 843 } 844 d.Unlock() 845 } 846 }() 847 848 switch config.BridgeIfaceCreator { 849 case ifaceCreatedByLibnetwork, ifaceCreatorUnknown: 850 // We only delete the bridge if it was created by the bridge driver and 851 // it is not the default one (to keep the backward compatible behavior.) 852 if !config.DefaultBridge { 853 if err := d.nlh.LinkDel(n.bridge.Link); err != nil { 854 log.G(context.TODO()).Warnf("Failed to remove bridge interface %s on network %s delete: %v", config.BridgeName, nid, err) 855 } 856 } 857 case ifaceCreatedByUser: 858 // Don't delete the bridge interface if it was not created by libnetwork. 859 } 860 861 // clean all relevant iptables rules 862 for _, cleanFunc := range n.iptCleanFuncs { 863 if errClean := cleanFunc(); errClean != nil { 864 log.G(context.TODO()).Warnf("Failed to clean iptables rules for bridge network: %v", errClean) 865 } 866 } 867 return d.storeDelete(config) 868 } 869 870 func addToBridge(nlh *netlink.Handle, ifaceName, bridgeName string) error { 871 lnk, err := nlh.LinkByName(ifaceName) 872 if err != nil { 873 return fmt.Errorf("could not find interface %s: %v", ifaceName, err) 874 } 875 if err := nlh.LinkSetMaster(lnk, &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}}); err != nil { 876 log.G(context.TODO()).WithError(err).Errorf("Failed to add %s to bridge via netlink", ifaceName) 877 return err 878 } 879 return nil 880 } 881 882 func setHairpinMode(nlh *netlink.Handle, link netlink.Link, enable bool) error { 883 err := nlh.LinkSetHairpin(link, enable) 884 if err != nil { 885 return fmt.Errorf("unable to set hairpin mode on %s via netlink: %v", 886 link.Attrs().Name, err) 887 } 888 return nil 889 } 890 891 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { 892 if ifInfo == nil { 893 return errors.New("invalid interface info passed") 894 } 895 896 // Get the network handler and make sure it exists 897 d.Lock() 898 n, ok := d.networks[nid] 899 dconfig := d.config 900 d.Unlock() 901 902 if !ok { 903 return types.NotFoundErrorf("network %s does not exist", nid) 904 } 905 if n == nil { 906 return driverapi.ErrNoNetwork(nid) 907 } 908 909 // Sanity check 910 n.Lock() 911 if n.id != nid { 912 n.Unlock() 913 return InvalidNetworkIDError(nid) 914 } 915 n.Unlock() 916 917 // Check if endpoint id is good and retrieve correspondent endpoint 918 ep, err := n.getEndpoint(eid) 919 if err != nil { 920 return err 921 } 922 923 // Endpoint with that id exists either on desired or other sandbox 924 if ep != nil { 925 return driverapi.ErrEndpointExists(eid) 926 } 927 928 // Try to convert the options to endpoint configuration 929 epConfig, err := parseEndpointOptions(epOptions) 930 if err != nil { 931 return err 932 } 933 934 // Create and add the endpoint 935 n.Lock() 936 endpoint := &bridgeEndpoint{id: eid, nid: nid, config: epConfig} 937 n.endpoints[eid] = endpoint 938 n.Unlock() 939 940 // On failure make sure to remove the endpoint 941 defer func() { 942 if err != nil { 943 n.Lock() 944 delete(n.endpoints, eid) 945 n.Unlock() 946 } 947 }() 948 949 // Generate a name for what will be the host side pipe interface 950 hostIfName, err := netutils.GenerateIfaceName(d.nlh, vethPrefix, vethLen) 951 if err != nil { 952 return err 953 } 954 955 // Generate a name for what will be the sandbox side pipe interface 956 containerIfName, err := netutils.GenerateIfaceName(d.nlh, vethPrefix, vethLen) 957 if err != nil { 958 return err 959 } 960 961 // Generate and add the interface pipe host <-> sandbox 962 veth := &netlink.Veth{ 963 LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, 964 PeerName: containerIfName, 965 } 966 if err = d.nlh.LinkAdd(veth); err != nil { 967 return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) 968 } 969 970 // Get the host side pipe interface handler 971 host, err := d.nlh.LinkByName(hostIfName) 972 if err != nil { 973 return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) 974 } 975 defer func() { 976 if err != nil { 977 if err := d.nlh.LinkDel(host); err != nil { 978 log.G(context.TODO()).WithError(err).Warnf("Failed to delete host side interface (%s)'s link", hostIfName) 979 } 980 } 981 }() 982 983 // Get the sandbox side pipe interface handler 984 sbox, err := d.nlh.LinkByName(containerIfName) 985 if err != nil { 986 return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) 987 } 988 defer func() { 989 if err != nil { 990 if err := d.nlh.LinkDel(sbox); err != nil { 991 log.G(context.TODO()).WithError(err).Warnf("Failed to delete sandbox side interface (%s)'s link", containerIfName) 992 } 993 } 994 }() 995 996 n.Lock() 997 config := n.config 998 n.Unlock() 999 1000 // Add bridge inherited attributes to pipe interfaces 1001 if config.Mtu != 0 { 1002 err = d.nlh.LinkSetMTU(host, config.Mtu) 1003 if err != nil { 1004 return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) 1005 } 1006 err = d.nlh.LinkSetMTU(sbox, config.Mtu) 1007 if err != nil { 1008 return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) 1009 } 1010 } 1011 1012 // Attach host side pipe interface into the bridge 1013 if err = addToBridge(d.nlh, hostIfName, config.BridgeName); err != nil { 1014 return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) 1015 } 1016 1017 if !dconfig.EnableUserlandProxy { 1018 err = setHairpinMode(d.nlh, host, true) 1019 if err != nil { 1020 return err 1021 } 1022 } 1023 1024 // Store the sandbox side pipe interface parameters 1025 endpoint.srcName = containerIfName 1026 endpoint.macAddress = ifInfo.MacAddress() 1027 endpoint.addr = ifInfo.Address() 1028 endpoint.addrv6 = ifInfo.AddressIPv6() 1029 1030 // Set the sbox's MAC if not provided. If specified, use the one configured by user, otherwise generate one based on IP. 1031 if endpoint.macAddress == nil { 1032 endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) 1033 if err = ifInfo.SetMacAddress(endpoint.macAddress); err != nil { 1034 return err 1035 } 1036 } 1037 1038 // Up the host interface after finishing all netlink configuration 1039 if err = d.nlh.LinkSetUp(host); err != nil { 1040 return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) 1041 } 1042 1043 if endpoint.addrv6 == nil && config.EnableIPv6 { 1044 var ip6 net.IP 1045 network := n.bridge.bridgeIPv6 1046 if config.AddressIPv6 != nil { 1047 network = config.AddressIPv6 1048 } 1049 1050 ones, _ := network.Mask.Size() 1051 if ones > 80 { 1052 err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) 1053 return err 1054 } 1055 1056 ip6 = make(net.IP, len(network.IP)) 1057 copy(ip6, network.IP) 1058 for i, h := range endpoint.macAddress { 1059 ip6[i+10] = h 1060 } 1061 1062 endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} 1063 if err = ifInfo.SetIPAddress(endpoint.addrv6); err != nil { 1064 return err 1065 } 1066 } 1067 1068 if err = d.storeUpdate(endpoint); err != nil { 1069 return fmt.Errorf("failed to save bridge endpoint %.7s to store: %v", endpoint.id, err) 1070 } 1071 1072 return nil 1073 } 1074 1075 func (d *driver) DeleteEndpoint(nid, eid string) error { 1076 var err error 1077 1078 // Get the network handler and make sure it exists 1079 d.Lock() 1080 n, ok := d.networks[nid] 1081 d.Unlock() 1082 1083 if !ok { 1084 return types.InternalMaskableErrorf("network %s does not exist", nid) 1085 } 1086 if n == nil { 1087 return driverapi.ErrNoNetwork(nid) 1088 } 1089 1090 // Sanity Check 1091 n.Lock() 1092 if n.id != nid { 1093 n.Unlock() 1094 return InvalidNetworkIDError(nid) 1095 } 1096 n.Unlock() 1097 1098 // Check endpoint id and if an endpoint is actually there 1099 ep, err := n.getEndpoint(eid) 1100 if err != nil { 1101 return err 1102 } 1103 if ep == nil { 1104 return EndpointNotFoundError(eid) 1105 } 1106 1107 // Remove it 1108 n.Lock() 1109 delete(n.endpoints, eid) 1110 n.Unlock() 1111 1112 // On failure make sure to set back ep in n.endpoints, but only 1113 // if it hasn't been taken over already by some other thread. 1114 defer func() { 1115 if err != nil { 1116 n.Lock() 1117 if _, ok := n.endpoints[eid]; !ok { 1118 n.endpoints[eid] = ep 1119 } 1120 n.Unlock() 1121 } 1122 }() 1123 1124 // Try removal of link. Discard error: it is a best effort. 1125 // Also make sure defer does not see this error either. 1126 if link, err := d.nlh.LinkByName(ep.srcName); err == nil { 1127 if err := d.nlh.LinkDel(link); err != nil { 1128 log.G(context.TODO()).WithError(err).Errorf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id) 1129 } 1130 } 1131 1132 if err := d.storeDelete(ep); err != nil { 1133 log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err) 1134 } 1135 1136 return nil 1137 } 1138 1139 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { 1140 // Get the network handler and make sure it exists 1141 d.Lock() 1142 n, ok := d.networks[nid] 1143 d.Unlock() 1144 if !ok { 1145 return nil, types.NotFoundErrorf("network %s does not exist", nid) 1146 } 1147 if n == nil { 1148 return nil, driverapi.ErrNoNetwork(nid) 1149 } 1150 1151 // Sanity check 1152 n.Lock() 1153 if n.id != nid { 1154 n.Unlock() 1155 return nil, InvalidNetworkIDError(nid) 1156 } 1157 n.Unlock() 1158 1159 // Check if endpoint id is good and retrieve correspondent endpoint 1160 ep, err := n.getEndpoint(eid) 1161 if err != nil { 1162 return nil, err 1163 } 1164 if ep == nil { 1165 return nil, driverapi.ErrNoEndpoint(eid) 1166 } 1167 1168 m := make(map[string]interface{}) 1169 1170 if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil { 1171 // Return a copy of the config data 1172 epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts)) 1173 for _, tp := range ep.extConnConfig.ExposedPorts { 1174 epc = append(epc, tp.GetCopy()) 1175 } 1176 m[netlabel.ExposedPorts] = epc 1177 } 1178 1179 if ep.portMapping != nil { 1180 // Return a copy of the operational data 1181 pmc := make([]types.PortBinding, 0, len(ep.portMapping)) 1182 for _, pm := range ep.portMapping { 1183 pmc = append(pmc, pm.GetCopy()) 1184 } 1185 m[netlabel.PortMap] = pmc 1186 } 1187 1188 if len(ep.macAddress) != 0 { 1189 m[netlabel.MacAddress] = ep.macAddress 1190 } 1191 1192 return m, nil 1193 } 1194 1195 // Join method is invoked when a Sandbox is attached to an endpoint. 1196 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 1197 network, err := d.getNetwork(nid) 1198 if err != nil { 1199 return err 1200 } 1201 1202 endpoint, err := network.getEndpoint(eid) 1203 if err != nil { 1204 return err 1205 } 1206 1207 if endpoint == nil { 1208 return EndpointNotFoundError(eid) 1209 } 1210 1211 endpoint.containerConfig, err = parseContainerOptions(options) 1212 if err != nil { 1213 return err 1214 } 1215 1216 iNames := jinfo.InterfaceName() 1217 containerVethPrefix := defaultContainerVethPrefix 1218 if network.config.ContainerIfacePrefix != "" { 1219 containerVethPrefix = network.config.ContainerIfacePrefix 1220 } 1221 if err := iNames.SetNames(endpoint.srcName, containerVethPrefix); err != nil { 1222 return err 1223 } 1224 1225 if !network.config.Internal { 1226 if err := jinfo.SetGateway(network.bridge.gatewayIPv4); err != nil { 1227 return err 1228 } 1229 if err := jinfo.SetGatewayIPv6(network.bridge.gatewayIPv6); err != nil { 1230 return err 1231 } 1232 } 1233 1234 return nil 1235 } 1236 1237 // Leave method is invoked when a Sandbox detaches from an endpoint. 1238 func (d *driver) Leave(nid, eid string) error { 1239 network, err := d.getNetwork(nid) 1240 if err != nil { 1241 return types.InternalMaskableErrorf("%s", err) 1242 } 1243 1244 endpoint, err := network.getEndpoint(eid) 1245 if err != nil { 1246 return err 1247 } 1248 1249 if endpoint == nil { 1250 return EndpointNotFoundError(eid) 1251 } 1252 1253 if !network.config.EnableICC { 1254 if err = d.link(network, endpoint, false); err != nil { 1255 return err 1256 } 1257 } 1258 1259 return nil 1260 } 1261 1262 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 1263 network, err := d.getNetwork(nid) 1264 if err != nil { 1265 return err 1266 } 1267 1268 endpoint, err := network.getEndpoint(eid) 1269 if err != nil { 1270 return err 1271 } 1272 1273 if endpoint == nil { 1274 return EndpointNotFoundError(eid) 1275 } 1276 1277 endpoint.extConnConfig, err = parseConnectivityOptions(options) 1278 if err != nil { 1279 return err 1280 } 1281 1282 // Program any required port mapping and store them in the endpoint 1283 endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIP, d.config.EnableUserlandProxy) 1284 if err != nil { 1285 return err 1286 } 1287 1288 defer func() { 1289 if err != nil { 1290 if e := network.releasePorts(endpoint); e != nil { 1291 log.G(context.TODO()).Errorf("Failed to release ports allocated for the bridge endpoint %s on failure %v because of %v", 1292 eid, err, e) 1293 } 1294 endpoint.portMapping = nil 1295 } 1296 }() 1297 1298 // Clean the connection tracker state of the host for the specific endpoint. This is needed because some flows may 1299 // be bound to the local proxy, or to the host (for UDP packets), and won't be redirected to the new endpoints. 1300 clearConntrackEntries(d.nlh, endpoint) 1301 1302 if err = d.storeUpdate(endpoint); err != nil { 1303 return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) 1304 } 1305 1306 if !network.config.EnableICC { 1307 return d.link(network, endpoint, true) 1308 } 1309 1310 return nil 1311 } 1312 1313 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 1314 network, err := d.getNetwork(nid) 1315 if err != nil { 1316 return err 1317 } 1318 1319 endpoint, err := network.getEndpoint(eid) 1320 if err != nil { 1321 return err 1322 } 1323 1324 if endpoint == nil { 1325 return EndpointNotFoundError(eid) 1326 } 1327 1328 err = network.releasePorts(endpoint) 1329 if err != nil { 1330 log.G(context.TODO()).Warn(err) 1331 } 1332 1333 endpoint.portMapping = nil 1334 1335 // Clean the connection tracker state of the host for the specific endpoint. This is a precautionary measure to 1336 // avoid new endpoints getting the same IP address to receive unexpected packets due to bad conntrack state leading 1337 // to bad NATing. 1338 clearConntrackEntries(d.nlh, endpoint) 1339 1340 if err = d.storeUpdate(endpoint); err != nil { 1341 return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) 1342 } 1343 1344 return nil 1345 } 1346 1347 func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) (retErr error) { 1348 cc := endpoint.containerConfig 1349 ec := endpoint.extConnConfig 1350 if cc == nil || ec == nil || (len(cc.ParentEndpoints) == 0 && len(cc.ChildEndpoints) == 0) { 1351 // nothing to do 1352 return nil 1353 } 1354 1355 // Try to keep things atomic. addedLinks keeps track of links that were 1356 // successfully added. If any error occurred, then roll back all. 1357 var addedLinks []*link 1358 defer func() { 1359 if retErr == nil { 1360 return 1361 } 1362 for _, l := range addedLinks { 1363 l.Disable() 1364 } 1365 }() 1366 1367 if ec.ExposedPorts != nil { 1368 for _, p := range cc.ParentEndpoints { 1369 parentEndpoint, err := network.getEndpoint(p) 1370 if err != nil { 1371 return err 1372 } 1373 if parentEndpoint == nil { 1374 return InvalidEndpointIDError(p) 1375 } 1376 1377 l, err := newLink(parentEndpoint.addr.IP, endpoint.addr.IP, ec.ExposedPorts, network.config.BridgeName) 1378 if err != nil { 1379 return err 1380 } 1381 if enable { 1382 if err := l.Enable(); err != nil { 1383 return err 1384 } 1385 addedLinks = append(addedLinks, l) 1386 } else { 1387 l.Disable() 1388 } 1389 } 1390 } 1391 1392 for _, c := range cc.ChildEndpoints { 1393 childEndpoint, err := network.getEndpoint(c) 1394 if err != nil { 1395 return err 1396 } 1397 if childEndpoint == nil { 1398 return InvalidEndpointIDError(c) 1399 } 1400 if childEndpoint.extConnConfig == nil || childEndpoint.extConnConfig.ExposedPorts == nil { 1401 continue 1402 } 1403 1404 l, err := newLink(endpoint.addr.IP, childEndpoint.addr.IP, childEndpoint.extConnConfig.ExposedPorts, network.config.BridgeName) 1405 if err != nil { 1406 return err 1407 } 1408 if enable { 1409 if err := l.Enable(); err != nil { 1410 return err 1411 } 1412 addedLinks = append(addedLinks, l) 1413 } else { 1414 l.Disable() 1415 } 1416 } 1417 1418 return nil 1419 } 1420 1421 func (d *driver) Type() string { 1422 return NetworkType 1423 } 1424 1425 func (d *driver) IsBuiltIn() bool { 1426 return true 1427 } 1428 1429 func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) { 1430 if epOptions == nil { 1431 return nil, nil 1432 } 1433 1434 ec := &endpointConfiguration{} 1435 1436 if opt, ok := epOptions[netlabel.MacAddress]; ok { 1437 if mac, ok := opt.(net.HardwareAddr); ok { 1438 ec.MacAddress = mac 1439 } else { 1440 return nil, &ErrInvalidEndpointConfig{} 1441 } 1442 } 1443 1444 return ec, nil 1445 } 1446 1447 func parseContainerOptions(cOptions map[string]interface{}) (*containerConfiguration, error) { 1448 if cOptions == nil { 1449 return nil, nil 1450 } 1451 genericData := cOptions[netlabel.GenericData] 1452 if genericData == nil { 1453 return nil, nil 1454 } 1455 switch opt := genericData.(type) { 1456 case options.Generic: 1457 opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{}) 1458 if err != nil { 1459 return nil, err 1460 } 1461 return opaqueConfig.(*containerConfiguration), nil 1462 case *containerConfiguration: 1463 return opt, nil 1464 default: 1465 return nil, nil 1466 } 1467 } 1468 1469 func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) { 1470 if cOptions == nil { 1471 return nil, nil 1472 } 1473 1474 cc := &connectivityConfiguration{} 1475 1476 if opt, ok := cOptions[netlabel.PortMap]; ok { 1477 if pb, ok := opt.([]types.PortBinding); ok { 1478 cc.PortBindings = pb 1479 } else { 1480 return nil, types.InvalidParameterErrorf("invalid port mapping data in connectivity configuration: %v", opt) 1481 } 1482 } 1483 1484 if opt, ok := cOptions[netlabel.ExposedPorts]; ok { 1485 if ports, ok := opt.([]types.TransportPort); ok { 1486 cc.ExposedPorts = ports 1487 } else { 1488 return nil, types.InvalidParameterErrorf("invalid exposed ports data in connectivity configuration: %v", opt) 1489 } 1490 } 1491 1492 return cc, nil 1493 } 1494 1495 func electMacAddress(epConfig *endpointConfiguration, ip net.IP) net.HardwareAddr { 1496 if epConfig != nil && epConfig.MacAddress != nil { 1497 return epConfig.MacAddress 1498 } 1499 return netutils.GenerateMACFromIP(ip) 1500 }