github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/libnetwork/drivers/solaris/bridge/bridge.go (about) 1 // +build solaris 2 3 package bridge 4 5 import ( 6 "bufio" 7 "errors" 8 "fmt" 9 "net" 10 "os" 11 "os/exec" 12 "strconv" 13 "strings" 14 "sync" 15 16 "github.com/Sirupsen/logrus" 17 "github.com/docker/libnetwork/datastore" 18 "github.com/docker/libnetwork/discoverapi" 19 "github.com/docker/libnetwork/driverapi" 20 "github.com/docker/libnetwork/iptables" 21 "github.com/docker/libnetwork/netlabel" 22 "github.com/docker/libnetwork/netutils" 23 "github.com/docker/libnetwork/options" 24 "github.com/docker/libnetwork/portmapper" 25 "github.com/docker/libnetwork/types" 26 ) 27 28 const ( 29 networkType = "bridge" 30 31 // DefaultBridgeName is the default name for the bridge interface managed 32 // by the driver when unspecified by the caller. 33 DefaultBridgeName = "docker0" 34 35 // BridgeName label for bridge driver 36 BridgeName = "com.docker.network.bridge.name" 37 38 // EnableIPMasquerade label for bridge driver 39 EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade" 40 41 // EnableICC label 42 EnableICC = "com.docker.network.bridge.enable_icc" 43 44 // DefaultBindingIP label 45 DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4" 46 47 // DefaultBridge label 48 DefaultBridge = "com.docker.network.bridge.default_bridge" 49 50 // DefaultGatewayV4AuxKey represents the default-gateway configured by the user 51 DefaultGatewayV4AuxKey = "DefaultGatewayIPv4" 52 53 // DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user 54 DefaultGatewayV6AuxKey = "DefaultGatewayIPv6" 55 ) 56 57 // configuration info for the "bridge" driver. 58 type configuration struct { 59 EnableIPForwarding bool 60 EnableIPTables bool 61 EnableUserlandProxy bool 62 } 63 64 // networkConfiguration for network specific configuration 65 type networkConfiguration struct { 66 ID string 67 BridgeName string 68 BridgeNameInternal string 69 EnableIPv6 bool 70 EnableIPMasquerade bool 71 EnableICC bool 72 Mtu int 73 DefaultBindingIntf string 74 DefaultBindingIP net.IP 75 DefaultBridge bool 76 // Internal fields set after ipam data parsing 77 AddressIPv4 *net.IPNet 78 AddressIPv6 *net.IPNet 79 DefaultGatewayIPv4 net.IP 80 DefaultGatewayIPv6 net.IP 81 dbIndex uint64 82 dbExists bool 83 Internal bool 84 } 85 86 // endpointConfiguration represents the user specified configuration for the sandbox endpoint 87 type endpointConfiguration struct { 88 MacAddress net.HardwareAddr 89 PortBindings []types.PortBinding 90 ExposedPorts []types.TransportPort 91 } 92 93 // containerConfiguration represents the user specified configuration for a container 94 type containerConfiguration struct { 95 ParentEndpoints []string 96 ChildEndpoints []string 97 } 98 99 // cnnectivityConfiguration represents the user specified configuration regarding the external connectivity 100 type connectivityConfiguration struct { 101 PortBindings []types.PortBinding 102 ExposedPorts []types.TransportPort 103 } 104 105 type bridgeEndpoint struct { 106 id string 107 nid string 108 srcName string 109 addr *net.IPNet 110 addrv6 *net.IPNet 111 macAddress net.HardwareAddr 112 config *endpointConfiguration // User specified parameters 113 containerConfig *containerConfiguration 114 extConnConfig *connectivityConfiguration 115 portMapping []types.PortBinding // Operation port bindings 116 dbIndex uint64 117 dbExists bool 118 } 119 120 type bridgeInterface struct { 121 bridgeIPv4 *net.IPNet 122 bridgeIPv6 *net.IPNet 123 gatewayIPv4 net.IP 124 gatewayIPv6 net.IP 125 } 126 127 type bridgeNetwork struct { 128 id string 129 bridge *bridgeInterface 130 config *networkConfiguration 131 endpoints map[string]*bridgeEndpoint // key: endpoint id 132 portMapper *portmapper.PortMapper 133 driver *driver // The network's driver 134 sync.Mutex 135 } 136 137 type driver struct { 138 config *configuration 139 network *bridgeNetwork 140 natChain *iptables.ChainInfo 141 filterChain *iptables.ChainInfo 142 isolationChain *iptables.ChainInfo 143 networks map[string]*bridgeNetwork 144 store datastore.DataStore 145 sync.Mutex 146 defrouteIP net.IP 147 } 148 149 // New constructs a new bridge driver 150 func newDriver() *driver { 151 return &driver{networks: map[string]*bridgeNetwork{}} 152 } 153 154 // Init registers a new instance of bridge driver 155 func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { 156 d := newDriver() 157 if err := d.configure(config); err != nil { 158 return err 159 } 160 161 c := driverapi.Capability{ 162 DataScope: datastore.LocalScope, 163 } 164 return dc.RegisterDriver(networkType, d, c) 165 } 166 167 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 168 return nil, types.NotImplementedErrorf("not implemented") 169 } 170 171 func (d *driver) NetworkFree(id string) error { 172 return types.NotImplementedErrorf("not implemented") 173 } 174 175 func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { 176 } 177 178 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 179 if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { 180 return types.BadRequestErrorf("ipv4 pool is empty") 181 } 182 // Sanity checks 183 d.Lock() 184 if _, ok := d.networks[id]; ok { 185 d.Unlock() 186 return types.ForbiddenErrorf("network %s exists", id) 187 } 188 d.Unlock() 189 190 // Parse and validate the config. It should not conflict with existing networks' config 191 config, err := parseNetworkOptions(d, id, option) 192 if err != nil { 193 return err 194 } 195 196 err = config.processIPAM(id, ipV4Data, ipV6Data) 197 if err != nil { 198 return err 199 } 200 201 if err = d.createNetwork(config); err != nil { 202 return err 203 } 204 205 return d.storeUpdate(config) 206 } 207 208 func newInterface(config *networkConfiguration) *bridgeInterface { 209 i := &bridgeInterface{} 210 211 i.bridgeIPv4 = config.AddressIPv4 212 i.gatewayIPv4 = config.AddressIPv4.IP 213 if config.BridgeName == "" { 214 config.BridgeName = DefaultBridgeName 215 } 216 return i 217 } 218 219 // This function prunes the pf.conf for the firewall 220 // that enable the service successfully. 221 func fixPFConf() error { 222 conf := "/etc/firewall/pf.conf" 223 f, err := os.Open("/etc/firewall/pf.conf") 224 if err != nil { 225 return fmt.Errorf("cannot open %s: %v", conf, err) 226 } 227 defer f.Close() 228 229 // Look for line beginning with "REMOVE THIS LINE" 230 modify := false 231 lines := []string{} 232 scanner := bufio.NewScanner(f) 233 for scanner.Scan() { 234 l := scanner.Text() 235 if strings.Contains(l, "REMOVE THIS LINE") { 236 modify = true 237 continue 238 } 239 lines = append(lines, fmt.Sprintf("%s\n", l)) 240 } 241 if err = scanner.Err(); err != nil { 242 return fmt.Errorf("cannot open %s: %v", conf, err) 243 } 244 245 // No changes needed to fix pf.conf 246 if !modify { 247 return nil 248 } 249 250 // Write back the file removing the line found above 251 tmpname := "/etc/firewall/pf.conf.tmp." + strconv.Itoa(os.Getpid()) 252 tmp, err := os.OpenFile(tmpname, 253 os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_APPEND, 0644) 254 if err != nil { 255 return fmt.Errorf("cannot open %s: %v", tmpname, err) 256 } 257 defer tmp.Close() 258 for _, l := range lines { 259 _, err = tmp.WriteString(l) 260 if err != nil { 261 return fmt.Errorf("cannot write to %s: %v", 262 tmpname, err) 263 } 264 } 265 if err = tmp.Sync(); err != nil { 266 return fmt.Errorf("cannot sync %s: %v", tmpname, err) 267 } 268 if err = os.Rename(tmpname, conf); err != nil { 269 return fmt.Errorf("cannot rename %s to %s: %v", 270 tmpname, conf, err) 271 } 272 return nil 273 } 274 275 func (d *driver) initFirewall() error { 276 out, err := exec.Command("/usr/bin/svcs", "-Ho", "state", 277 "firewall").Output() 278 if err != nil { 279 return fmt.Errorf("cannot check firewall state: %v", err) 280 } 281 state := strings.TrimSpace(string(out)) 282 if state != "online" { 283 if state != "disabled" { 284 return fmt.Errorf("firewall service is in %s state. "+ 285 "please enable service manually.", state) 286 } 287 if err = fixPFConf(); err != nil { 288 return fmt.Errorf("cannot verify pf.conf: %v", err) 289 } 290 err = exec.Command("/usr/sbin/svcadm", "enable", "-ts", 291 "firewall").Run() 292 if err != nil { 293 return fmt.Errorf("cannot enable firewall service: %v", err) 294 } 295 } 296 out, err = exec.Command("/usr/sbin/pfctl", "-sr").Output() 297 if err != nil { 298 return fmt.Errorf("failed to list firewall rules: %v", err) 299 } 300 if strings.Contains(string(out), "anchor \"_auto/docker/*\" all") { 301 return nil 302 } 303 pfctlCmd := "(/usr/sbin/pfctl -sr; " + 304 "/usr/bin/echo \"anchor \\\"_auto/docker/*\\\"\") |" + 305 "/usr/sbin/pfctl -f -" 306 err = exec.Command("/usr/bin/bash", "-c", pfctlCmd).Run() 307 if err != nil { 308 return fmt.Errorf("failed to add docker firewall rules: %v", err) 309 } 310 return nil 311 } 312 313 func (d *driver) initRouting() error { 314 err := exec.Command("/usr/sbin/ipadm", "set-prop", "-t", 315 "-p", "forwarding=on", "ipv4").Run() 316 if err != nil { 317 return fmt.Errorf("cannot switch-on IP forwarding: %v", err) 318 } 319 routeCmd := "/usr/sbin/ipadm show-addr -p -o addr " + 320 "`/usr/sbin/route get default | /usr/bin/grep interface | " + 321 "/usr/bin/awk '{print $2}'`" 322 out, err := exec.Command("/usr/bin/bash", "-c", routeCmd).Output() 323 if err != nil { 324 return fmt.Errorf("cannot get default route: %v", err) 325 } 326 defroute := strings.SplitN(string(out), "/", 2) 327 d.defrouteIP = net.ParseIP(defroute[0]) 328 if d.defrouteIP == nil { 329 return &ErrNoIPAddr{} 330 } 331 return nil 332 } 333 334 func (d *driver) configure(option map[string]interface{}) error { 335 var err error 336 337 if err = d.initFirewall(); err != nil { 338 return fmt.Errorf("failed to configure firewall: %v", err) 339 } 340 if err = d.initRouting(); err != nil { 341 return fmt.Errorf("failed to configure routing: %v", err) 342 } 343 if err = d.initStore(option); err != nil { 344 return fmt.Errorf("failed to initialize datastore: %v", err) 345 } 346 347 return nil 348 } 349 350 func (d *driver) getNetwork(id string) (*bridgeNetwork, error) { 351 d.Lock() 352 defer d.Unlock() 353 354 if id == "" { 355 return nil, types.BadRequestErrorf("invalid network id: %s", id) 356 } 357 358 if nw, ok := d.networks[id]; ok { 359 return nw, nil 360 } 361 362 return nil, types.NotFoundErrorf("network not found: %s", id) 363 } 364 365 // Return a slice of networks over which caller can iterate safely 366 func (d *driver) getNetworks() []*bridgeNetwork { 367 d.Lock() 368 defer d.Unlock() 369 370 ls := make([]*bridgeNetwork, 0, len(d.networks)) 371 for _, nw := range d.networks { 372 ls = append(ls, nw) 373 } 374 return ls 375 } 376 377 func bridgeSetup(config *networkConfiguration) error { 378 var err error 379 var bindingIntf string 380 381 bridgeName := config.BridgeName 382 gwName := fmt.Sprintf("%s_gw0", bridgeName) 383 gwIP := config.AddressIPv4.String() 384 385 if config.DefaultBindingIP == nil { 386 // Default to net0 if bindingIP is not provided. 387 bindingIntf = "net0" 388 } else { 389 ipadmCmd := "/usr/sbin/ipadm show-addr -p -o addrobj,addr |" + 390 "/usr/bin/grep " + config.DefaultBindingIP.String() 391 out, err := exec.Command("/usr/bin/bash", "-c", ipadmCmd).Output() 392 if err != nil { 393 logrus.Warnf("cannot find binding interface") 394 return err 395 } 396 bindingIntf = strings.SplitN(string(out), "/", 2)[0] 397 if bindingIntf == "" { 398 logrus.Warnf("cannot parse binding interface %s", string(out)) 399 return &ErrNoIPAddr{} 400 } 401 } 402 config.DefaultBindingIntf = bindingIntf 403 404 err = exec.Command("/usr/sbin/dladm", "create-etherstub", 405 "-t", config.BridgeNameInternal).Run() 406 if err != nil { 407 logrus.Warnf("cannot create etherstub %s: %+v", config.BridgeNameInternal, err) 408 return err 409 } 410 err = exec.Command("/usr/sbin/dladm", "create-vnic", 411 "-t", "-l", config.BridgeNameInternal, gwName).Run() 412 if err != nil { 413 logrus.Warnf("cannot create vnic %s", gwName) 414 return err 415 } 416 err = exec.Command("/usr/sbin/ifconfig", gwName, 417 "plumb", gwIP, "up").Run() 418 if err != nil { 419 logrus.Warnf("cannot create gateway interface %s on %s", 420 gwIP, gwName) 421 return err 422 } 423 424 tableName := "bridge_nw_subnets" 425 pfAnchor := fmt.Sprintf("_auto/docker/%s", tableName) 426 err = exec.Command("/usr/sbin/pfctl", "-a", pfAnchor, "-t", tableName, "-T", "add", gwIP).Run() 427 if err != nil { 428 logrus.Warnf("cannot add bridge network '%s' to PF table", bridgeName) 429 } 430 431 pfCmd := fmt.Sprintf( 432 "/usr/bin/echo \"pass out on %s from %s:network to any nat-to (%s)\n"+ 433 "block in quick from { <%s>, ! %s } to %s\" |"+ 434 "/usr/sbin/pfctl -a _auto/docker/%s -f -", 435 bindingIntf, gwName, bindingIntf, 436 tableName, gwIP, gwIP, 437 bridgeName) 438 err = exec.Command("/usr/bin/bash", "-c", pfCmd).Run() 439 if err != nil { 440 logrus.Warnf("cannot add pf rule using: %s", pfCmd) 441 return err 442 } 443 444 return nil 445 } 446 447 func bridgeCleanup(config *networkConfiguration, logErr bool) { 448 var err error 449 450 bridgeName := config.BridgeName 451 tableName := "bridge_nw_subnets" 452 gwName := fmt.Sprintf("%s_gw0", bridgeName) 453 gwIP := config.AddressIPv4.String() 454 pfAnchor := fmt.Sprintf("_auto/docker/%s", bridgeName) 455 tableAnchor := fmt.Sprintf("_auto/docker/%s", tableName) 456 457 err = exec.Command("/usr/sbin/pfctl", "-a", pfAnchor, "-F", "all").Run() 458 if err != nil && logErr { 459 logrus.Warnf("cannot flush firewall rules") 460 } 461 err = exec.Command("/usr/sbin/ifconfig", gwName, "unplumb").Run() 462 if err != nil && logErr { 463 logrus.Warnf("cannot remove gateway interface") 464 } 465 err = exec.Command("/usr/sbin/dladm", "delete-vnic", 466 "-t", gwName).Run() 467 if err != nil && logErr { 468 logrus.Warnf("cannot delete vnic") 469 } 470 err = exec.Command("/usr/sbin/dladm", "delete-etherstub", 471 "-t", config.BridgeNameInternal).Run() 472 if err != nil && logErr { 473 logrus.Warnf("cannot delete etherstub") 474 } 475 err = exec.Command("/usr/sbin/pfctl", "-a", tableAnchor, "-t", tableName, "-T", "delete", gwIP).Run() 476 if err != nil && logErr { 477 logrus.Warnf("cannot remove bridge network '%s' from PF table", bridgeName) 478 } 479 } 480 481 func (d *driver) createNetwork(config *networkConfiguration) error { 482 var err error 483 484 logrus.Infof("Creating bridge network: %s %s %s", config.ID, 485 config.BridgeName, config.AddressIPv4) 486 487 networkList := d.getNetworks() 488 for i, nw := range networkList { 489 nw.Lock() 490 nwConfig := nw.config 491 nw.Unlock() 492 if err := nwConfig.Conflicts(config); err != nil { 493 if config.DefaultBridge { 494 // We encountered and identified a stale default network 495 // We must delete it as libnetwork is the source of thruth 496 // The default network being created must be the only one 497 // This can happen only from docker 1.12 on ward 498 logrus.Infof("Removing stale default bridge network %s (%s)", nwConfig.ID, nwConfig.BridgeName) 499 if err := d.DeleteNetwork(nwConfig.ID); err != nil { 500 logrus.Warnf("Failed to remove stale default network: %s (%s): %v. Will remove from store.", nwConfig.ID, nwConfig.BridgeName, err) 501 d.storeDelete(nwConfig) 502 } 503 networkList = append(networkList[:i], networkList[i+1:]...) 504 } else { 505 return types.ForbiddenErrorf( 506 "cannot create network %s (%s): "+ 507 "conflicts with network %s (%s): %s", 508 nwConfig.BridgeName, config.ID, nw.id, 509 nw.config.BridgeName, err.Error()) 510 } 511 } 512 } 513 if config.DefaultBindingIP == nil || 514 config.DefaultBindingIP.IsUnspecified() { 515 config.DefaultBindingIP = d.defrouteIP 516 } 517 518 // Create and set network handler in driver 519 network := &bridgeNetwork{ 520 id: config.ID, 521 endpoints: make(map[string]*bridgeEndpoint), 522 config: config, 523 portMapper: portmapper.New(""), 524 driver: d, 525 } 526 527 d.Lock() 528 d.networks[config.ID] = network 529 d.Unlock() 530 531 // On failure make sure to reset driver network handler to nil 532 defer func() { 533 if err != nil { 534 d.Lock() 535 delete(d.networks, config.ID) 536 d.Unlock() 537 } 538 }() 539 540 // Create or retrieve the bridge L3 interface 541 bridgeIface := newInterface(config) 542 network.bridge = bridgeIface 543 544 // Verify the network configuration does not conflict with previously installed 545 // networks. This step is needed now because driver might have now set the bridge 546 // name on this config struct. And because we need to check for possible address 547 // conflicts, so we need to check against operational networks. 548 if err = config.conflictsWithNetworks(config.ID, networkList); err != nil { 549 return err 550 } 551 552 // We only attempt to create the bridge when the requested device name is 553 // the default one. 554 if config.BridgeName != DefaultBridgeName && config.DefaultBridge { 555 return NonDefaultBridgeExistError(config.BridgeName) 556 } 557 558 bridgeCleanup(config, false) 559 err = bridgeSetup(config) 560 if err != nil { 561 return err 562 } 563 return nil 564 } 565 566 func (d *driver) DeleteNetwork(nid string) error { 567 var err error 568 // Get network handler and remove it from driver 569 d.Lock() 570 n, ok := d.networks[nid] 571 d.Unlock() 572 573 if !ok { 574 return types.InternalMaskableErrorf("network %s does not exist", nid) 575 } 576 d.Lock() 577 delete(d.networks, nid) 578 d.Unlock() 579 580 // On failure set network handler back in driver, but 581 // only if is not already taken over by some other thread 582 defer func() { 583 if err != nil { 584 d.Lock() 585 if _, ok := d.networks[nid]; !ok { 586 d.networks[nid] = n 587 } 588 d.Unlock() 589 } 590 }() 591 592 // Sanity check 593 if n == nil { 594 err = driverapi.ErrNoNetwork(nid) 595 return err 596 } 597 598 // Cannot remove network if endpoints are still present 599 if len(n.endpoints) != 0 { 600 err = ActiveEndpointsError(n.id) 601 return err 602 } 603 bridgeCleanup(n.config, true) 604 logrus.Infof("Deleting bridge network: %s", nid[:12]) 605 return d.storeDelete(n.config) 606 } 607 608 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { 609 if ifInfo == nil { 610 return errors.New("invalid interface passed") 611 } 612 613 // Get the network handler and make sure it exists 614 d.Lock() 615 n, ok := d.networks[nid] 616 d.Unlock() 617 618 if !ok { 619 return types.NotFoundErrorf("network %s does not exist", nid) 620 } 621 if n == nil { 622 return driverapi.ErrNoNetwork(nid) 623 } 624 625 // Sanity check 626 n.Lock() 627 if n.id != nid { 628 n.Unlock() 629 return InvalidNetworkIDError(nid) 630 } 631 n.Unlock() 632 633 // Check if endpoint id is good and retrieve correspondent endpoint 634 ep, err := n.getEndpoint(eid) 635 if err != nil { 636 return err 637 } 638 639 // Endpoint with that id exists either on desired or other sandbox 640 if ep != nil { 641 return driverapi.ErrEndpointExists(eid) 642 } 643 644 // Try to convert the options to endpoint configuration 645 epConfig, err := parseEndpointOptions(epOptions) 646 if err != nil { 647 return err 648 } 649 650 // Create and add the endpoint 651 n.Lock() 652 endpoint := &bridgeEndpoint{id: eid, config: epConfig} 653 n.endpoints[eid] = endpoint 654 n.Unlock() 655 656 // On failure make sure to remove the endpoint 657 defer func() { 658 if err != nil { 659 n.Lock() 660 delete(n.endpoints, eid) 661 n.Unlock() 662 } 663 }() 664 665 // Create the sandbox side pipe interface 666 if ifInfo.MacAddress() == nil { 667 // No MAC address assigned to interface. Generate a random MAC to assign 668 endpoint.macAddress = netutils.GenerateRandomMAC() 669 if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { 670 logrus.Warnf("Unable to set mac address: %s to endpoint: %s", 671 endpoint.macAddress.String(), endpoint.id) 672 return err 673 } 674 } else { 675 endpoint.macAddress = ifInfo.MacAddress() 676 } 677 endpoint.addr = ifInfo.Address() 678 endpoint.addrv6 = ifInfo.AddressIPv6() 679 c := n.config 680 681 // Program any required port mapping and store them in the endpoint 682 endpoint.portMapping, err = n.allocatePorts(endpoint, c.DefaultBindingIntf, c.DefaultBindingIP, true) 683 if err != nil { 684 return err 685 } 686 687 return nil 688 } 689 690 func (d *driver) DeleteEndpoint(nid, eid string) error { 691 var err error 692 693 // Get the network handler and make sure it exists 694 d.Lock() 695 n, ok := d.networks[nid] 696 d.Unlock() 697 698 if !ok { 699 return types.InternalMaskableErrorf("network %s does not exist", nid) 700 } 701 if n == nil { 702 return driverapi.ErrNoNetwork(nid) 703 } 704 705 // Sanity Check 706 n.Lock() 707 if n.id != nid { 708 n.Unlock() 709 return InvalidNetworkIDError(nid) 710 } 711 n.Unlock() 712 713 // Check endpoint id and if an endpoint is actually there 714 ep, err := n.getEndpoint(eid) 715 if err != nil { 716 return err 717 } 718 if ep == nil { 719 return EndpointNotFoundError(eid) 720 } 721 722 // Remove it 723 n.Lock() 724 delete(n.endpoints, eid) 725 n.Unlock() 726 727 // On failure make sure to set back ep in n.endpoints, but only 728 // if it hasn't been taken over already by some other thread. 729 defer func() { 730 if err != nil { 731 n.Lock() 732 if _, ok := n.endpoints[eid]; !ok { 733 n.endpoints[eid] = ep 734 } 735 n.Unlock() 736 } 737 }() 738 739 err = n.releasePorts(ep) 740 if err != nil { 741 logrus.Warn(err) 742 } 743 744 return nil 745 } 746 747 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { 748 // Get the network handler and make sure it exists 749 d.Lock() 750 n, ok := d.networks[nid] 751 d.Unlock() 752 if !ok { 753 return nil, types.NotFoundErrorf("network %s does not exist", nid) 754 } 755 if n == nil { 756 return nil, driverapi.ErrNoNetwork(nid) 757 } 758 759 // Sanity check 760 n.Lock() 761 if n.id != nid { 762 n.Unlock() 763 return nil, InvalidNetworkIDError(nid) 764 } 765 n.Unlock() 766 767 // Check if endpoint id is good and retrieve correspondent endpoint 768 ep, err := n.getEndpoint(eid) 769 if err != nil { 770 return nil, err 771 } 772 if ep == nil { 773 return nil, driverapi.ErrNoEndpoint(eid) 774 } 775 776 m := make(map[string]interface{}) 777 778 if ep.extConnConfig != nil && ep.extConnConfig.ExposedPorts != nil { 779 // Return a copy of the config data 780 epc := make([]types.TransportPort, 0, len(ep.extConnConfig.ExposedPorts)) 781 for _, tp := range ep.extConnConfig.ExposedPorts { 782 epc = append(epc, tp.GetCopy()) 783 } 784 m[netlabel.ExposedPorts] = epc 785 } 786 787 if ep.portMapping != nil { 788 // Return a copy of the operational data 789 pmc := make([]types.PortBinding, 0, len(ep.portMapping)) 790 for _, pm := range ep.portMapping { 791 pmc = append(pmc, pm.GetCopy()) 792 } 793 m[netlabel.PortMap] = pmc 794 } 795 796 if len(ep.macAddress) != 0 { 797 m[netlabel.MacAddress] = ep.macAddress 798 } 799 return m, nil 800 } 801 802 // Join method is invoked when a Sandbox is attached to an endpoint. 803 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 804 network, err := d.getNetwork(nid) 805 if err != nil { 806 return err 807 } 808 809 endpoint, err := network.getEndpoint(eid) 810 if err != nil { 811 return err 812 } 813 814 if endpoint == nil { 815 return EndpointNotFoundError(eid) 816 } 817 818 endpoint.containerConfig, err = parseContainerOptions(options) 819 if err != nil { 820 return err 821 } 822 823 err = jinfo.SetGateway(network.bridge.gatewayIPv4) 824 if err != nil { 825 return err 826 } 827 828 err = jinfo.SetGatewayIPv6(network.bridge.gatewayIPv6) 829 if err != nil { 830 return err 831 } 832 833 return nil 834 } 835 836 func (d *driver) link(network *bridgeNetwork, endpoint *bridgeEndpoint, enable bool) error { 837 return nil 838 } 839 840 // Leave method is invoked when a Sandbox detaches from an endpoint. 841 func (d *driver) Leave(nid, eid string) error { 842 network, err := d.getNetwork(nid) 843 if err != nil { 844 return types.InternalMaskableErrorf("%s", err) 845 } 846 847 endpoint, err := network.getEndpoint(eid) 848 if err != nil { 849 return err 850 } 851 852 if endpoint == nil { 853 return EndpointNotFoundError(eid) 854 } 855 856 return nil 857 } 858 859 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 860 network, err := d.getNetwork(nid) 861 if err != nil { 862 return err 863 } 864 865 endpoint, err := network.getEndpoint(eid) 866 if err != nil { 867 return err 868 } 869 870 if endpoint == nil { 871 return EndpointNotFoundError(eid) 872 } 873 874 endpoint.extConnConfig, err = parseConnectivityOptions(options) 875 if err != nil { 876 return err 877 } 878 879 // Program any required port mapping and store them in the endpoint 880 endpoint.portMapping, err = network.allocatePorts(endpoint, network.config.DefaultBindingIntf, network.config.DefaultBindingIP, true) 881 if err != nil { 882 return err 883 } 884 885 if !network.config.EnableICC { 886 return d.link(network, endpoint, true) 887 } 888 889 return nil 890 } 891 892 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 893 network, err := d.getNetwork(nid) 894 if err != nil { 895 return err 896 } 897 898 endpoint, err := network.getEndpoint(eid) 899 if err != nil { 900 return err 901 } 902 903 if endpoint == nil { 904 return EndpointNotFoundError(eid) 905 } 906 907 err = network.releasePorts(endpoint) 908 if err != nil { 909 logrus.Warn(err) 910 } 911 912 return nil 913 } 914 915 func (d *driver) Type() string { 916 return networkType 917 } 918 919 // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster 920 func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { 921 return nil 922 } 923 924 // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster 925 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { 926 return nil 927 } 928 929 // Validate performs a static validation on the network configuration parameters. 930 // Whatever can be assessed a priori before attempting any programming. 931 func (c *networkConfiguration) Validate() error { 932 if c.Mtu < 0 { 933 return ErrInvalidMtu(c.Mtu) 934 } 935 936 // If bridge v4 subnet is specified 937 if c.AddressIPv4 != nil { 938 // If default gw is specified, it must be part of bridge subnet 939 if c.DefaultGatewayIPv4 != nil { 940 if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) { 941 return &ErrInvalidGateway{} 942 } 943 } 944 } 945 946 // If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet 947 if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil { 948 if c.AddressIPv6 == nil || !c.AddressIPv6.Contains(c.DefaultGatewayIPv6) { 949 return &ErrInvalidGateway{} 950 } 951 } 952 return nil 953 } 954 955 // Checks whether this network's configuration for the network with this id conflicts with any of the passed networks 956 func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridgeNetwork) error { 957 for _, nw := range others { 958 959 nw.Lock() 960 nwID := nw.id 961 nwConfig := nw.config 962 nwBridge := nw.bridge 963 nw.Unlock() 964 965 if nwID == id { 966 continue 967 } 968 // Verify the name (which may have been set by newInterface()) does not conflict with 969 // existing bridge interfaces. Ironically the system chosen name gets stored in the config... 970 // Basically we are checking if the two original configs were both empty. 971 if nwConfig.BridgeName == c.BridgeName { 972 return types.ForbiddenErrorf("conflicts with network %s (%s) by bridge name", nwID, nwConfig.BridgeName) 973 } 974 // If this network config specifies the AddressIPv4, we need 975 // to make sure it does not conflict with any previously allocated 976 // bridges. This could not be completely caught by the config conflict 977 // check, because networks which config does not specify the AddressIPv4 978 // get their address and subnet selected by the driver (see electBridgeIPv4()) 979 if c.AddressIPv4 != nil { 980 if nwBridge.bridgeIPv4.Contains(c.AddressIPv4.IP) || 981 c.AddressIPv4.Contains(nwBridge.bridgeIPv4.IP) { 982 return types.ForbiddenErrorf("conflicts with network %s (%s) by ip network", nwID, nwConfig.BridgeName) 983 } 984 } 985 } 986 987 return nil 988 } 989 990 // Conflicts check if two NetworkConfiguration objects overlap 991 func (c *networkConfiguration) Conflicts(o *networkConfiguration) error { 992 if o == nil { 993 return fmt.Errorf("same configuration") 994 } 995 996 // Also empty, becasue only one network with empty name is allowed 997 if c.BridgeName == o.BridgeName { 998 return fmt.Errorf("networks have same bridge name") 999 } 1000 1001 // They must be in different subnets 1002 if (c.AddressIPv4 != nil && o.AddressIPv4 != nil) && 1003 (c.AddressIPv4.Contains(o.AddressIPv4.IP) || o.AddressIPv4.Contains(c.AddressIPv4.IP)) { 1004 return fmt.Errorf("networks have overlapping IPv4") 1005 } 1006 1007 // They must be in different v6 subnets 1008 if (c.AddressIPv6 != nil && o.AddressIPv6 != nil) && 1009 (c.AddressIPv6.Contains(o.AddressIPv6.IP) || o.AddressIPv6.Contains(c.AddressIPv6.IP)) { 1010 return fmt.Errorf("networks have overlapping IPv6") 1011 } 1012 1013 return nil 1014 } 1015 1016 func (c *networkConfiguration) fromLabels(labels map[string]string) error { 1017 var err error 1018 for label, value := range labels { 1019 switch label { 1020 case BridgeName: 1021 c.BridgeName = value 1022 case netlabel.DriverMTU: 1023 if c.Mtu, err = strconv.Atoi(value); err != nil { 1024 return parseErr(label, value, err.Error()) 1025 } 1026 case netlabel.EnableIPv6: 1027 if c.EnableIPv6, err = strconv.ParseBool(value); err != nil { 1028 return parseErr(label, value, err.Error()) 1029 } 1030 case EnableIPMasquerade: 1031 if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil { 1032 return parseErr(label, value, err.Error()) 1033 } 1034 case EnableICC: 1035 if c.EnableICC, err = strconv.ParseBool(value); err != nil { 1036 return parseErr(label, value, err.Error()) 1037 } 1038 case DefaultBridge: 1039 if c.DefaultBridge, err = strconv.ParseBool(value); err != nil { 1040 return parseErr(label, value, err.Error()) 1041 } 1042 case DefaultBindingIP: 1043 if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil { 1044 return parseErr(label, value, "nil ip") 1045 } 1046 } 1047 } 1048 1049 return nil 1050 } 1051 1052 func parseErr(label, value, errString string) error { 1053 return types.BadRequestErrorf("failed to parse %s value: %v (%s)", label, value, errString) 1054 } 1055 1056 func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error) { 1057 var ( 1058 err error 1059 config *networkConfiguration 1060 ) 1061 1062 switch opt := data.(type) { 1063 case *networkConfiguration: 1064 config = opt 1065 case map[string]string: 1066 config = &networkConfiguration{ 1067 EnableICC: true, 1068 EnableIPMasquerade: true, 1069 } 1070 err = config.fromLabels(opt) 1071 case options.Generic: 1072 var opaqueConfig interface{} 1073 if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil { 1074 config = opaqueConfig.(*networkConfiguration) 1075 } 1076 default: 1077 err = types.BadRequestErrorf("do not recognize network configuration format: %T", opt) 1078 } 1079 1080 return config, err 1081 } 1082 1083 func parseNetworkOptions(d *driver, id string, option options.Generic) (*networkConfiguration, error) { 1084 var ( 1085 err error 1086 config = &networkConfiguration{} 1087 ) 1088 1089 // Parse generic label first, config will be re-assigned 1090 if genData, ok := option[netlabel.GenericData]; ok && genData != nil { 1091 if config, err = parseNetworkGenericOptions(genData); err != nil { 1092 return nil, err 1093 } 1094 } 1095 1096 // Process well-known labels next 1097 if val, ok := option[netlabel.EnableIPv6]; ok { 1098 config.EnableIPv6 = val.(bool) 1099 } 1100 1101 if val, ok := option[netlabel.Internal]; ok { 1102 if internal, ok := val.(bool); ok && internal { 1103 config.Internal = true 1104 } 1105 } 1106 1107 // Finally validate the configuration 1108 if err = config.Validate(); err != nil { 1109 return nil, err 1110 } 1111 1112 if config.BridgeName == "" && config.DefaultBridge == false { 1113 config.BridgeName = "br_" + id[:12] + "_0" 1114 } 1115 1116 lastChar := config.BridgeName[len(config.BridgeName)-1:] 1117 if _, err = strconv.Atoi(lastChar); err != nil { 1118 config.BridgeNameInternal = config.BridgeName + "_0" 1119 } else { 1120 config.BridgeNameInternal = config.BridgeName 1121 } 1122 1123 config.ID = id 1124 return config, nil 1125 } 1126 1127 func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error { 1128 if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 { 1129 return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets") 1130 } 1131 1132 if len(ipamV4Data) == 0 { 1133 return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id) 1134 } 1135 1136 if ipamV4Data[0].Gateway != nil { 1137 c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway) 1138 } 1139 1140 if gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]; ok { 1141 c.DefaultGatewayIPv4 = gw.IP 1142 } 1143 1144 if len(ipamV6Data) > 0 { 1145 c.AddressIPv6 = ipamV6Data[0].Pool 1146 1147 if ipamV6Data[0].Gateway != nil { 1148 c.AddressIPv6 = types.GetIPNetCopy(ipamV6Data[0].Gateway) 1149 } 1150 1151 if gw, ok := ipamV6Data[0].AuxAddresses[DefaultGatewayV6AuxKey]; ok { 1152 c.DefaultGatewayIPv6 = gw.IP 1153 } 1154 } 1155 1156 return nil 1157 } 1158 1159 func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) { 1160 n.Lock() 1161 defer n.Unlock() 1162 1163 if eid == "" { 1164 return nil, InvalidEndpointIDError(eid) 1165 } 1166 1167 if ep, ok := n.endpoints[eid]; ok { 1168 return ep, nil 1169 } 1170 1171 return nil, nil 1172 } 1173 1174 func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) { 1175 if epOptions == nil { 1176 return nil, nil 1177 } 1178 1179 ec := &endpointConfiguration{} 1180 1181 if opt, ok := epOptions[netlabel.MacAddress]; ok { 1182 if mac, ok := opt.(net.HardwareAddr); ok { 1183 ec.MacAddress = mac 1184 } else { 1185 return nil, &ErrInvalidEndpointConfig{} 1186 } 1187 } 1188 1189 if opt, ok := epOptions[netlabel.PortMap]; ok { 1190 if bs, ok := opt.([]types.PortBinding); ok { 1191 ec.PortBindings = bs 1192 } else { 1193 return nil, &ErrInvalidEndpointConfig{} 1194 } 1195 } 1196 1197 if opt, ok := epOptions[netlabel.ExposedPorts]; ok { 1198 if ports, ok := opt.([]types.TransportPort); ok { 1199 ec.ExposedPorts = ports 1200 } else { 1201 return nil, &ErrInvalidEndpointConfig{} 1202 } 1203 } 1204 1205 return ec, nil 1206 } 1207 1208 func parseContainerOptions(cOptions map[string]interface{}) (*containerConfiguration, error) { 1209 if cOptions == nil { 1210 return nil, nil 1211 } 1212 genericData := cOptions[netlabel.GenericData] 1213 if genericData == nil { 1214 return nil, nil 1215 } 1216 switch opt := genericData.(type) { 1217 case options.Generic: 1218 opaqueConfig, err := options.GenerateFromModel(opt, &containerConfiguration{}) 1219 if err != nil { 1220 return nil, err 1221 } 1222 return opaqueConfig.(*containerConfiguration), nil 1223 case *containerConfiguration: 1224 return opt, nil 1225 default: 1226 return nil, nil 1227 } 1228 } 1229 1230 func parseConnectivityOptions(cOptions map[string]interface{}) (*connectivityConfiguration, error) { 1231 if cOptions == nil { 1232 return nil, nil 1233 } 1234 1235 cc := &connectivityConfiguration{} 1236 1237 if opt, ok := cOptions[netlabel.PortMap]; ok { 1238 if pb, ok := opt.([]types.PortBinding); ok { 1239 cc.PortBindings = pb 1240 } else { 1241 return nil, types.BadRequestErrorf("Invalid port mapping data in connectivity configuration: %v", opt) 1242 } 1243 } 1244 1245 if opt, ok := cOptions[netlabel.ExposedPorts]; ok { 1246 if ports, ok := opt.([]types.TransportPort); ok { 1247 cc.ExposedPorts = ports 1248 } else { 1249 return nil, types.BadRequestErrorf("Invalid exposed ports data in connectivity configuration: %v", opt) 1250 } 1251 } 1252 1253 return cc, nil 1254 }