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