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