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