github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/sandbox.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "sort" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/docker/libnetwork/etchosts" 13 "github.com/docker/libnetwork/netlabel" 14 "github.com/docker/libnetwork/osl" 15 "github.com/docker/libnetwork/types" 16 "github.com/sirupsen/logrus" 17 ) 18 19 // Sandbox provides the control over the network container entity. It is a one to one mapping with the container. 20 type Sandbox interface { 21 // ID returns the ID of the sandbox 22 ID() string 23 // Key returns the sandbox's key 24 Key() string 25 // ContainerID returns the container id associated to this sandbox 26 ContainerID() string 27 // Labels returns the sandbox's labels 28 Labels() map[string]interface{} 29 // Statistics retrieves the interfaces' statistics for the sandbox 30 Statistics() (map[string]*types.InterfaceStatistics, error) 31 // Refresh leaves all the endpoints, resets and re-applies the options, 32 // re-joins all the endpoints without destroying the osl sandbox 33 Refresh(options ...SandboxOption) error 34 // SetKey updates the Sandbox Key 35 SetKey(key string) error 36 // Rename changes the name of all attached Endpoints 37 Rename(name string) error 38 // Delete destroys this container after detaching it from all connected endpoints. 39 Delete() error 40 // Endpoints returns all the endpoints connected to the sandbox 41 Endpoints() []Endpoint 42 // ResolveService returns all the backend details about the containers or hosts 43 // backing a service. Its purpose is to satisfy an SRV query 44 ResolveService(name string) ([]*net.SRV, []net.IP) 45 // EnableService makes a managed container's service available by adding the 46 // endpoint to the service load balancer and service discovery 47 EnableService() error 48 // DisableService removes a managed container's endpoints from the load balancer 49 // and service discovery 50 DisableService() error 51 } 52 53 // SandboxOption is an option setter function type used to pass various options to 54 // NewNetContainer method. The various setter functions of type SandboxOption are 55 // provided by libnetwork, they look like ContainerOptionXXXX(...) 56 type SandboxOption func(sb *sandbox) 57 58 func (sb *sandbox) processOptions(options ...SandboxOption) { 59 for _, opt := range options { 60 if opt != nil { 61 opt(sb) 62 } 63 } 64 } 65 66 type sandbox struct { 67 id string 68 containerID string 69 config containerConfig 70 extDNS []extDNSEntry 71 osSbox osl.Sandbox 72 controller *controller 73 resolver Resolver 74 resolverOnce sync.Once 75 refCnt int 76 endpoints []*endpoint 77 epPriority map[string]int 78 populatedEndpoints map[string]struct{} 79 joinLeaveDone chan struct{} 80 dbIndex uint64 81 dbExists bool 82 isStub bool 83 inDelete bool 84 ingress bool 85 ndotsSet bool 86 oslTypes []osl.SandboxType // slice of properties of this sandbox 87 loadBalancerNID string // NID that this SB is a load balancer for 88 sync.Mutex 89 // This mutex is used to serialize service related operation for an endpoint 90 // The lock is here because the endpoint is saved into the store so is not unique 91 Service sync.Mutex 92 } 93 94 // These are the container configs used to customize container /data/data/hilled.pwnterm/files/usr/etc/hosts file. 95 type hostsPathConfig struct { 96 hostName string 97 domainName string 98 hostsPath string 99 originHostsPath string 100 extraHosts []extraHost 101 parentUpdates []parentUpdate 102 } 103 104 type parentUpdate struct { 105 cid string 106 name string 107 ip string 108 } 109 110 type extraHost struct { 111 name string 112 IP string 113 } 114 115 // These are the container configs used to customize container /data/data/hilled.pwnterm/files/usr/etc/resolv.conf file. 116 type resolvConfPathConfig struct { 117 resolvConfPath string 118 originResolvConfPath string 119 resolvConfHashFile string 120 dnsList []string 121 dnsSearchList []string 122 dnsOptionsList []string 123 } 124 125 type containerConfig struct { 126 hostsPathConfig 127 resolvConfPathConfig 128 generic map[string]interface{} 129 useDefaultSandBox bool 130 useExternalKey bool 131 prio int // higher the value, more the priority 132 exposedPorts []types.TransportPort 133 } 134 135 const ( 136 resolverIPSandbox = "127.0.0.11" 137 ) 138 139 func (sb *sandbox) ID() string { 140 return sb.id 141 } 142 143 func (sb *sandbox) ContainerID() string { 144 return sb.containerID 145 } 146 147 func (sb *sandbox) Key() string { 148 if sb.config.useDefaultSandBox { 149 return osl.GenerateKey("default") 150 } 151 return osl.GenerateKey(sb.id) 152 } 153 154 func (sb *sandbox) Labels() map[string]interface{} { 155 sb.Lock() 156 defer sb.Unlock() 157 opts := make(map[string]interface{}, len(sb.config.generic)) 158 for k, v := range sb.config.generic { 159 opts[k] = v 160 } 161 return opts 162 } 163 164 func (sb *sandbox) Statistics() (map[string]*types.InterfaceStatistics, error) { 165 m := make(map[string]*types.InterfaceStatistics) 166 167 sb.Lock() 168 osb := sb.osSbox 169 sb.Unlock() 170 if osb == nil { 171 return m, nil 172 } 173 174 var err error 175 for _, i := range osb.Info().Interfaces() { 176 if m[i.DstName()], err = i.Statistics(); err != nil { 177 return m, err 178 } 179 } 180 181 return m, nil 182 } 183 184 func (sb *sandbox) Delete() error { 185 return sb.delete(false) 186 } 187 188 func (sb *sandbox) delete(force bool) error { 189 sb.Lock() 190 if sb.inDelete { 191 sb.Unlock() 192 return types.ForbiddenErrorf("another sandbox delete in progress") 193 } 194 // Set the inDelete flag. This will ensure that we don't 195 // update the store until we have completed all the endpoint 196 // leaves and deletes. And when endpoint leaves and deletes 197 // are completed then we can finally delete the sandbox object 198 // altogether from the data store. If the daemon exits 199 // ungracefully in the middle of a sandbox delete this way we 200 // will have all the references to the endpoints in the 201 // sandbox so that we can clean them up when we restart 202 sb.inDelete = true 203 sb.Unlock() 204 205 c := sb.controller 206 207 // Detach from all endpoints 208 retain := false 209 for _, ep := range sb.getConnectedEndpoints() { 210 // gw network endpoint detach and removal are automatic 211 if ep.endpointInGWNetwork() && !force { 212 continue 213 } 214 // Retain the sanbdox if we can't obtain the network from store. 215 if _, err := c.getNetworkFromStore(ep.getNetwork().ID()); err != nil { 216 if c.isDistributedControl() { 217 retain = true 218 } 219 logrus.Warnf("Failed getting network for ep %s during sandbox %s delete: %v", ep.ID(), sb.ID(), err) 220 continue 221 } 222 223 if !force { 224 if err := ep.Leave(sb); err != nil { 225 logrus.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err) 226 } 227 } 228 229 if err := ep.Delete(force); err != nil { 230 logrus.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err) 231 } 232 } 233 234 if retain { 235 sb.Lock() 236 sb.inDelete = false 237 sb.Unlock() 238 return fmt.Errorf("could not cleanup all the endpoints in container %s / sandbox %s", sb.containerID, sb.id) 239 } 240 // Container is going away. Path cache in etchosts is most 241 // likely not required any more. Drop it. 242 etchosts.Drop(sb.config.hostsPath) 243 244 if sb.resolver != nil { 245 sb.resolver.Stop() 246 } 247 248 if sb.osSbox != nil && !sb.config.useDefaultSandBox { 249 sb.osSbox.Destroy() 250 } 251 252 if err := sb.storeDelete(); err != nil { 253 logrus.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err) 254 } 255 256 c.Lock() 257 if sb.ingress { 258 c.ingressSandbox = nil 259 } 260 delete(c.sandboxes, sb.ID()) 261 c.Unlock() 262 263 return nil 264 } 265 266 func (sb *sandbox) Rename(name string) error { 267 var err error 268 269 for _, ep := range sb.getConnectedEndpoints() { 270 if ep.endpointInGWNetwork() { 271 continue 272 } 273 274 oldName := ep.Name() 275 lEp := ep 276 if err = ep.rename(name); err != nil { 277 break 278 } 279 280 defer func() { 281 if err != nil { 282 lEp.rename(oldName) 283 } 284 }() 285 } 286 287 return err 288 } 289 290 func (sb *sandbox) Refresh(options ...SandboxOption) error { 291 // Store connected endpoints 292 epList := sb.getConnectedEndpoints() 293 294 // Detach from all endpoints 295 for _, ep := range epList { 296 if err := ep.Leave(sb); err != nil { 297 logrus.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err) 298 } 299 } 300 301 // Re-apply options 302 sb.config = containerConfig{} 303 sb.processOptions(options...) 304 305 // Setup discovery files 306 if err := sb.setupResolutionFiles(); err != nil { 307 return err 308 } 309 310 // Re-connect to all endpoints 311 for _, ep := range epList { 312 if err := ep.Join(sb); err != nil { 313 logrus.Warnf("Failed attach sandbox %s to endpoint %s: %v\n", sb.ID(), ep.ID(), err) 314 } 315 } 316 317 return nil 318 } 319 320 func (sb *sandbox) MarshalJSON() ([]byte, error) { 321 sb.Lock() 322 defer sb.Unlock() 323 324 // We are just interested in the container ID. This can be expanded to include all of containerInfo if there is a need 325 return json.Marshal(sb.id) 326 } 327 328 func (sb *sandbox) UnmarshalJSON(b []byte) (err error) { 329 sb.Lock() 330 defer sb.Unlock() 331 332 var id string 333 if err := json.Unmarshal(b, &id); err != nil { 334 return err 335 } 336 sb.id = id 337 return nil 338 } 339 340 func (sb *sandbox) Endpoints() []Endpoint { 341 sb.Lock() 342 defer sb.Unlock() 343 344 endpoints := make([]Endpoint, len(sb.endpoints)) 345 for i, ep := range sb.endpoints { 346 endpoints[i] = ep 347 } 348 return endpoints 349 } 350 351 func (sb *sandbox) getConnectedEndpoints() []*endpoint { 352 sb.Lock() 353 defer sb.Unlock() 354 355 eps := make([]*endpoint, len(sb.endpoints)) 356 copy(eps, sb.endpoints) 357 358 return eps 359 } 360 361 func (sb *sandbox) addEndpoint(ep *endpoint) { 362 sb.Lock() 363 defer sb.Unlock() 364 365 l := len(sb.endpoints) 366 i := sort.Search(l, func(j int) bool { 367 return ep.Less(sb.endpoints[j]) 368 }) 369 370 sb.endpoints = append(sb.endpoints, nil) 371 copy(sb.endpoints[i+1:], sb.endpoints[i:]) 372 sb.endpoints[i] = ep 373 } 374 375 func (sb *sandbox) removeEndpoint(ep *endpoint) { 376 sb.Lock() 377 defer sb.Unlock() 378 379 sb.removeEndpointRaw(ep) 380 } 381 382 func (sb *sandbox) removeEndpointRaw(ep *endpoint) { 383 for i, e := range sb.endpoints { 384 if e == ep { 385 sb.endpoints = append(sb.endpoints[:i], sb.endpoints[i+1:]...) 386 return 387 } 388 } 389 } 390 391 func (sb *sandbox) getEndpoint(id string) *endpoint { 392 sb.Lock() 393 defer sb.Unlock() 394 395 for _, ep := range sb.endpoints { 396 if ep.id == id { 397 return ep 398 } 399 } 400 401 return nil 402 } 403 404 func (sb *sandbox) updateGateway(ep *endpoint) error { 405 sb.Lock() 406 osSbox := sb.osSbox 407 sb.Unlock() 408 if osSbox == nil { 409 return nil 410 } 411 osSbox.UnsetGateway() 412 osSbox.UnsetGatewayIPv6() 413 414 if ep == nil { 415 return nil 416 } 417 418 ep.Lock() 419 joinInfo := ep.joinInfo 420 ep.Unlock() 421 422 if err := osSbox.SetGateway(joinInfo.gw); err != nil { 423 return fmt.Errorf("failed to set gateway while updating gateway: %v", err) 424 } 425 426 if err := osSbox.SetGatewayIPv6(joinInfo.gw6); err != nil { 427 return fmt.Errorf("failed to set IPv6 gateway while updating gateway: %v", err) 428 } 429 430 return nil 431 } 432 433 func (sb *sandbox) HandleQueryResp(name string, ip net.IP) { 434 for _, ep := range sb.getConnectedEndpoints() { 435 n := ep.getNetwork() 436 n.HandleQueryResp(name, ip) 437 } 438 } 439 440 func (sb *sandbox) ResolveIP(ip string) string { 441 var svc string 442 logrus.Debugf("IP To resolve %v", ip) 443 444 for _, ep := range sb.getConnectedEndpoints() { 445 n := ep.getNetwork() 446 svc = n.ResolveIP(ip) 447 if len(svc) != 0 { 448 return svc 449 } 450 } 451 452 return svc 453 } 454 455 func (sb *sandbox) ExecFunc(f func()) error { 456 sb.Lock() 457 osSbox := sb.osSbox 458 sb.Unlock() 459 if osSbox != nil { 460 return osSbox.InvokeFunc(f) 461 } 462 return fmt.Errorf("osl sandbox unavailable in ExecFunc for %v", sb.ContainerID()) 463 } 464 465 func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) { 466 srv := []*net.SRV{} 467 ip := []net.IP{} 468 469 logrus.Debugf("Service name To resolve: %v", name) 470 471 // There are DNS implementations that allow SRV queries for names not in 472 // the format defined by RFC 2782. Hence specific validations checks are 473 // not done 474 parts := strings.Split(name, ".") 475 if len(parts) < 3 { 476 return nil, nil 477 } 478 479 for _, ep := range sb.getConnectedEndpoints() { 480 n := ep.getNetwork() 481 482 srv, ip = n.ResolveService(name) 483 if len(srv) > 0 { 484 break 485 } 486 } 487 return srv, ip 488 } 489 490 func getDynamicNwEndpoints(epList []*endpoint) []*endpoint { 491 eps := []*endpoint{} 492 for _, ep := range epList { 493 n := ep.getNetwork() 494 if n.dynamic && !n.ingress { 495 eps = append(eps, ep) 496 } 497 } 498 return eps 499 } 500 501 func getIngressNwEndpoint(epList []*endpoint) *endpoint { 502 for _, ep := range epList { 503 n := ep.getNetwork() 504 if n.ingress { 505 return ep 506 } 507 } 508 return nil 509 } 510 511 func getLocalNwEndpoints(epList []*endpoint) []*endpoint { 512 eps := []*endpoint{} 513 for _, ep := range epList { 514 n := ep.getNetwork() 515 if !n.dynamic && !n.ingress { 516 eps = append(eps, ep) 517 } 518 } 519 return eps 520 } 521 522 func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) { 523 // Embedded server owns the docker network domain. Resolution should work 524 // for both container_name and container_name.network_name 525 // We allow '.' in service name and network name. For a name a.b.c.d the 526 // following have to tried; 527 // {a.b.c.d in the networks container is connected to} 528 // {a.b.c in network d}, 529 // {a.b in network c.d}, 530 // {a in network b.c.d}, 531 532 logrus.Debugf("Name To resolve: %v", name) 533 name = strings.TrimSuffix(name, ".") 534 reqName := []string{name} 535 networkName := []string{""} 536 537 if strings.Contains(name, ".") { 538 var i int 539 dup := name 540 for { 541 if i = strings.LastIndex(dup, "."); i == -1 { 542 break 543 } 544 networkName = append(networkName, name[i+1:]) 545 reqName = append(reqName, name[:i]) 546 547 dup = dup[:i] 548 } 549 } 550 551 epList := sb.getConnectedEndpoints() 552 553 // In swarm mode services with exposed ports are connected to user overlay 554 // network, ingress network and docker_gwbridge network. Name resolution 555 // should prioritize returning the VIP/IPs on user overlay network. 556 newList := []*endpoint{} 557 if !sb.controller.isDistributedControl() { 558 newList = append(newList, getDynamicNwEndpoints(epList)...) 559 ingressEP := getIngressNwEndpoint(epList) 560 if ingressEP != nil { 561 newList = append(newList, ingressEP) 562 } 563 newList = append(newList, getLocalNwEndpoints(epList)...) 564 epList = newList 565 } 566 567 for i := 0; i < len(reqName); i++ { 568 569 // First check for local container alias 570 ip, ipv6Miss := sb.resolveName(reqName[i], networkName[i], epList, true, ipType) 571 if ip != nil { 572 return ip, false 573 } 574 if ipv6Miss { 575 return ip, ipv6Miss 576 } 577 578 // Resolve the actual container name 579 ip, ipv6Miss = sb.resolveName(reqName[i], networkName[i], epList, false, ipType) 580 if ip != nil { 581 return ip, false 582 } 583 if ipv6Miss { 584 return ip, ipv6Miss 585 } 586 } 587 return nil, false 588 } 589 590 func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) ([]net.IP, bool) { 591 var ipv6Miss bool 592 593 for _, ep := range epList { 594 name := req 595 n := ep.getNetwork() 596 597 if networkName != "" && networkName != n.Name() { 598 continue 599 } 600 601 if alias { 602 if ep.aliases == nil { 603 continue 604 } 605 606 var ok bool 607 ep.Lock() 608 name, ok = ep.aliases[req] 609 ep.Unlock() 610 if !ok { 611 continue 612 } 613 } else { 614 // If it is a regular lookup and if the requested name is an alias 615 // don't perform a svc lookup for this endpoint. 616 ep.Lock() 617 if _, ok := ep.aliases[req]; ok { 618 ep.Unlock() 619 continue 620 } 621 ep.Unlock() 622 } 623 624 ip, miss := n.ResolveName(name, ipType) 625 626 if ip != nil { 627 return ip, false 628 } 629 630 if miss { 631 ipv6Miss = miss 632 } 633 } 634 return nil, ipv6Miss 635 } 636 637 func (sb *sandbox) SetKey(basePath string) error { 638 start := time.Now() 639 defer func() { 640 logrus.Debugf("sandbox set key processing took %s for container %s", time.Since(start), sb.ContainerID()) 641 }() 642 643 if basePath == "" { 644 return types.BadRequestErrorf("invalid sandbox key") 645 } 646 647 sb.Lock() 648 if sb.inDelete { 649 sb.Unlock() 650 return types.ForbiddenErrorf("failed to SetKey: sandbox %q delete in progress", sb.id) 651 } 652 oldosSbox := sb.osSbox 653 sb.Unlock() 654 655 if oldosSbox != nil { 656 // If we already have an OS sandbox, release the network resources from that 657 // and destroy the OS snab. We are moving into a new home further down. Note that none 658 // of the network resources gets destroyed during the move. 659 sb.releaseOSSbox() 660 } 661 662 osSbox, err := osl.GetSandboxForExternalKey(basePath, sb.Key()) 663 if err != nil { 664 return err 665 } 666 667 sb.Lock() 668 sb.osSbox = osSbox 669 sb.Unlock() 670 671 // If the resolver was setup before stop it and set it up in the 672 // new osl sandbox. 673 if oldosSbox != nil && sb.resolver != nil { 674 sb.resolver.Stop() 675 676 if err := sb.osSbox.InvokeFunc(sb.resolver.SetupFunc(0)); err == nil { 677 if err := sb.resolver.Start(); err != nil { 678 logrus.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err) 679 } 680 } else { 681 logrus.Errorf("Resolver Setup Function failed for container %s, %q", sb.ContainerID(), err) 682 } 683 } 684 685 for _, ep := range sb.getConnectedEndpoints() { 686 if err = sb.populateNetworkResources(ep); err != nil { 687 return err 688 } 689 } 690 return nil 691 } 692 693 func (sb *sandbox) EnableService() (err error) { 694 logrus.Debugf("EnableService %s START", sb.containerID) 695 defer func() { 696 if err != nil { 697 sb.DisableService() 698 } 699 }() 700 for _, ep := range sb.getConnectedEndpoints() { 701 if !ep.isServiceEnabled() { 702 if err := ep.addServiceInfoToCluster(sb); err != nil { 703 return fmt.Errorf("could not update state for endpoint %s into cluster: %v", ep.Name(), err) 704 } 705 ep.enableService() 706 } 707 } 708 logrus.Debugf("EnableService %s DONE", sb.containerID) 709 return nil 710 } 711 712 func (sb *sandbox) DisableService() (err error) { 713 logrus.Debugf("DisableService %s START", sb.containerID) 714 failedEps := []string{} 715 defer func() { 716 if len(failedEps) > 0 { 717 err = fmt.Errorf("failed to disable service on sandbox:%s, for endpoints %s", sb.ID(), strings.Join(failedEps, ",")) 718 } 719 }() 720 for _, ep := range sb.getConnectedEndpoints() { 721 if ep.isServiceEnabled() { 722 if err := ep.deleteServiceInfoFromCluster(sb, false, "DisableService"); err != nil { 723 failedEps = append(failedEps, ep.Name()) 724 logrus.Warnf("failed update state for endpoint %s into cluster: %v", ep.Name(), err) 725 } 726 ep.disableService() 727 } 728 } 729 logrus.Debugf("DisableService %s DONE", sb.containerID) 730 return nil 731 } 732 733 func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) { 734 for _, i := range osSbox.Info().Interfaces() { 735 // Only remove the interfaces owned by this endpoint from the sandbox. 736 if ep.hasInterface(i.SrcName()) { 737 if err := i.Remove(); err != nil { 738 logrus.Debugf("Remove interface %s failed: %v", i.SrcName(), err) 739 } 740 } 741 } 742 743 ep.Lock() 744 joinInfo := ep.joinInfo 745 vip := ep.virtualIP 746 lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR 747 ep.Unlock() 748 749 if len(vip) > 0 && lbModeIsDSR { 750 ipNet := &net.IPNet{IP: vip, Mask: net.CIDRMask(32, 32)} 751 if err := osSbox.RemoveAliasIP(osSbox.GetLoopbackIfaceName(), ipNet); err != nil { 752 logrus.WithError(err).Debugf("failed to remove virtual ip %v to loopback", ipNet) 753 } 754 } 755 756 if joinInfo == nil { 757 return 758 } 759 760 // Remove non-interface routes. 761 for _, r := range joinInfo.StaticRoutes { 762 if err := osSbox.RemoveStaticRoute(r); err != nil { 763 logrus.Debugf("Remove route failed: %v", err) 764 } 765 } 766 } 767 768 func (sb *sandbox) releaseOSSbox() { 769 sb.Lock() 770 osSbox := sb.osSbox 771 sb.osSbox = nil 772 sb.Unlock() 773 774 if osSbox == nil { 775 return 776 } 777 778 for _, ep := range sb.getConnectedEndpoints() { 779 releaseOSSboxResources(osSbox, ep) 780 } 781 782 osSbox.Destroy() 783 } 784 785 func (sb *sandbox) restoreOslSandbox() error { 786 var routes []*types.StaticRoute 787 788 // restore osl sandbox 789 Ifaces := make(map[string][]osl.IfaceOption) 790 for _, ep := range sb.endpoints { 791 var ifaceOptions []osl.IfaceOption 792 ep.Lock() 793 joinInfo := ep.joinInfo 794 i := ep.iface 795 ep.Unlock() 796 797 if i == nil { 798 logrus.Errorf("error restoring endpoint %s for container %s", ep.Name(), sb.ContainerID()) 799 continue 800 } 801 802 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes)) 803 if i.addrv6 != nil && i.addrv6.IP.To16() != nil { 804 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6)) 805 } 806 if i.mac != nil { 807 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac)) 808 } 809 if len(i.llAddrs) != 0 { 810 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) 811 } 812 Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions 813 if joinInfo != nil { 814 routes = append(routes, joinInfo.StaticRoutes...) 815 } 816 if ep.needResolver() { 817 sb.startResolver(true) 818 } 819 } 820 821 gwep := sb.getGatewayEndpoint() 822 if gwep == nil { 823 return nil 824 } 825 826 // restore osl sandbox 827 err := sb.osSbox.Restore(Ifaces, routes, gwep.joinInfo.gw, gwep.joinInfo.gw6) 828 return err 829 } 830 831 func (sb *sandbox) populateNetworkResources(ep *endpoint) error { 832 sb.Lock() 833 if sb.osSbox == nil { 834 sb.Unlock() 835 return nil 836 } 837 inDelete := sb.inDelete 838 sb.Unlock() 839 840 ep.Lock() 841 joinInfo := ep.joinInfo 842 i := ep.iface 843 lbModeIsDSR := ep.network.loadBalancerMode == loadBalancerModeDSR 844 ep.Unlock() 845 846 if ep.needResolver() { 847 sb.startResolver(false) 848 } 849 850 if i != nil && i.srcName != "" { 851 var ifaceOptions []osl.IfaceOption 852 853 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes)) 854 if i.addrv6 != nil && i.addrv6.IP.To16() != nil { 855 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6)) 856 } 857 if len(i.llAddrs) != 0 { 858 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) 859 } 860 if i.mac != nil { 861 ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac)) 862 } 863 864 if err := sb.osSbox.AddInterface(i.srcName, i.dstPrefix, ifaceOptions...); err != nil { 865 return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err) 866 } 867 868 if len(ep.virtualIP) > 0 && lbModeIsDSR { 869 if sb.loadBalancerNID == "" { 870 if err := sb.osSbox.DisableARPForVIP(i.srcName); err != nil { 871 return fmt.Errorf("failed disable ARP for VIP: %v", err) 872 } 873 } 874 ipNet := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)} 875 if err := sb.osSbox.AddAliasIP(sb.osSbox.GetLoopbackIfaceName(), ipNet); err != nil { 876 return fmt.Errorf("failed to add virtual ip %v to loopback: %v", ipNet, err) 877 } 878 } 879 } 880 881 if joinInfo != nil { 882 // Set up non-interface routes. 883 for _, r := range joinInfo.StaticRoutes { 884 if err := sb.osSbox.AddStaticRoute(r); err != nil { 885 return fmt.Errorf("failed to add static route %s: %v", r.Destination.String(), err) 886 } 887 } 888 } 889 890 if ep == sb.getGatewayEndpoint() { 891 if err := sb.updateGateway(ep); err != nil { 892 return err 893 } 894 } 895 896 // Make sure to add the endpoint to the populated endpoint set 897 // before populating loadbalancers. 898 sb.Lock() 899 sb.populatedEndpoints[ep.ID()] = struct{}{} 900 sb.Unlock() 901 902 // Populate load balancer only after updating all the other 903 // information including gateway and other routes so that 904 // loadbalancers are populated all the network state is in 905 // place in the sandbox. 906 sb.populateLoadBalancers(ep) 907 908 // Only update the store if we did not come here as part of 909 // sandbox delete. If we came here as part of delete then do 910 // not bother updating the store. The sandbox object will be 911 // deleted anyway 912 if !inDelete { 913 return sb.storeUpdate() 914 } 915 916 return nil 917 } 918 919 func (sb *sandbox) clearNetworkResources(origEp *endpoint) error { 920 ep := sb.getEndpoint(origEp.id) 921 if ep == nil { 922 return fmt.Errorf("could not find the sandbox endpoint data for endpoint %s", 923 origEp.id) 924 } 925 926 sb.Lock() 927 osSbox := sb.osSbox 928 inDelete := sb.inDelete 929 sb.Unlock() 930 if osSbox != nil { 931 releaseOSSboxResources(osSbox, ep) 932 } 933 934 sb.Lock() 935 delete(sb.populatedEndpoints, ep.ID()) 936 937 if len(sb.endpoints) == 0 { 938 // sb.endpoints should never be empty and this is unexpected error condition 939 // We log an error message to note this down for debugging purposes. 940 logrus.Errorf("No endpoints in sandbox while trying to remove endpoint %s", ep.Name()) 941 sb.Unlock() 942 return nil 943 } 944 945 var ( 946 gwepBefore, gwepAfter *endpoint 947 index = -1 948 ) 949 for i, e := range sb.endpoints { 950 if e == ep { 951 index = i 952 } 953 if len(e.Gateway()) > 0 && gwepBefore == nil { 954 gwepBefore = e 955 } 956 if index != -1 && gwepBefore != nil { 957 break 958 } 959 } 960 961 if index == -1 { 962 logrus.Warnf("Endpoint %s has already been deleted", ep.Name()) 963 sb.Unlock() 964 return nil 965 } 966 967 sb.removeEndpointRaw(ep) 968 for _, e := range sb.endpoints { 969 if len(e.Gateway()) > 0 { 970 gwepAfter = e 971 break 972 } 973 } 974 delete(sb.epPriority, ep.ID()) 975 sb.Unlock() 976 977 if gwepAfter != nil && gwepBefore != gwepAfter { 978 sb.updateGateway(gwepAfter) 979 } 980 981 // Only update the store if we did not come here as part of 982 // sandbox delete. If we came here as part of delete then do 983 // not bother updating the store. The sandbox object will be 984 // deleted anyway 985 if !inDelete { 986 return sb.storeUpdate() 987 } 988 989 return nil 990 } 991 992 func (sb *sandbox) isEndpointPopulated(ep *endpoint) bool { 993 sb.Lock() 994 _, ok := sb.populatedEndpoints[ep.ID()] 995 sb.Unlock() 996 return ok 997 } 998 999 // joinLeaveStart waits to ensure there are no joins or leaves in progress and 1000 // marks this join/leave in progress without race 1001 func (sb *sandbox) joinLeaveStart() { 1002 sb.Lock() 1003 defer sb.Unlock() 1004 1005 for sb.joinLeaveDone != nil { 1006 joinLeaveDone := sb.joinLeaveDone 1007 sb.Unlock() 1008 1009 <-joinLeaveDone 1010 1011 sb.Lock() 1012 } 1013 1014 sb.joinLeaveDone = make(chan struct{}) 1015 } 1016 1017 // joinLeaveEnd marks the end of this join/leave operation and 1018 // signals the same without race to other join and leave waiters 1019 func (sb *sandbox) joinLeaveEnd() { 1020 sb.Lock() 1021 defer sb.Unlock() 1022 1023 if sb.joinLeaveDone != nil { 1024 close(sb.joinLeaveDone) 1025 sb.joinLeaveDone = nil 1026 } 1027 } 1028 1029 func (sb *sandbox) hasPortConfigs() bool { 1030 opts := sb.Labels() 1031 _, hasExpPorts := opts[netlabel.ExposedPorts] 1032 _, hasPortMaps := opts[netlabel.PortMap] 1033 return hasExpPorts || hasPortMaps 1034 } 1035 1036 // OptionHostname function returns an option setter for hostname option to 1037 // be passed to NewSandbox method. 1038 func OptionHostname(name string) SandboxOption { 1039 return func(sb *sandbox) { 1040 sb.config.hostName = name 1041 } 1042 } 1043 1044 // OptionDomainname function returns an option setter for domainname option to 1045 // be passed to NewSandbox method. 1046 func OptionDomainname(name string) SandboxOption { 1047 return func(sb *sandbox) { 1048 sb.config.domainName = name 1049 } 1050 } 1051 1052 // OptionHostsPath function returns an option setter for hostspath option to 1053 // be passed to NewSandbox method. 1054 func OptionHostsPath(path string) SandboxOption { 1055 return func(sb *sandbox) { 1056 sb.config.hostsPath = path 1057 } 1058 } 1059 1060 // OptionOriginHostsPath function returns an option setter for origin hosts file path 1061 // to be passed to NewSandbox method. 1062 func OptionOriginHostsPath(path string) SandboxOption { 1063 return func(sb *sandbox) { 1064 sb.config.originHostsPath = path 1065 } 1066 } 1067 1068 // OptionExtraHost function returns an option setter for extra /data/data/hilled.pwnterm/files/usr/etc/hosts options 1069 // which is a name and IP as strings. 1070 func OptionExtraHost(name string, IP string) SandboxOption { 1071 return func(sb *sandbox) { 1072 sb.config.extraHosts = append(sb.config.extraHosts, extraHost{name: name, IP: IP}) 1073 } 1074 } 1075 1076 // OptionParentUpdate function returns an option setter for parent container 1077 // which needs to update the IP address for the linked container. 1078 func OptionParentUpdate(cid string, name, ip string) SandboxOption { 1079 return func(sb *sandbox) { 1080 sb.config.parentUpdates = append(sb.config.parentUpdates, parentUpdate{cid: cid, name: name, ip: ip}) 1081 } 1082 } 1083 1084 // OptionResolvConfPath function returns an option setter for resolvconfpath option to 1085 // be passed to net container methods. 1086 func OptionResolvConfPath(path string) SandboxOption { 1087 return func(sb *sandbox) { 1088 sb.config.resolvConfPath = path 1089 } 1090 } 1091 1092 // OptionOriginResolvConfPath function returns an option setter to set the path to the 1093 // origin resolv.conf file to be passed to net container methods. 1094 func OptionOriginResolvConfPath(path string) SandboxOption { 1095 return func(sb *sandbox) { 1096 sb.config.originResolvConfPath = path 1097 } 1098 } 1099 1100 // OptionDNS function returns an option setter for dns entry option to 1101 // be passed to container Create method. 1102 func OptionDNS(dns string) SandboxOption { 1103 return func(sb *sandbox) { 1104 sb.config.dnsList = append(sb.config.dnsList, dns) 1105 } 1106 } 1107 1108 // OptionDNSSearch function returns an option setter for dns search entry option to 1109 // be passed to container Create method. 1110 func OptionDNSSearch(search string) SandboxOption { 1111 return func(sb *sandbox) { 1112 sb.config.dnsSearchList = append(sb.config.dnsSearchList, search) 1113 } 1114 } 1115 1116 // OptionDNSOptions function returns an option setter for dns options entry option to 1117 // be passed to container Create method. 1118 func OptionDNSOptions(options string) SandboxOption { 1119 return func(sb *sandbox) { 1120 sb.config.dnsOptionsList = append(sb.config.dnsOptionsList, options) 1121 } 1122 } 1123 1124 // OptionUseDefaultSandbox function returns an option setter for using default sandbox 1125 // (host namespace) to be passed to container Create method. 1126 func OptionUseDefaultSandbox() SandboxOption { 1127 return func(sb *sandbox) { 1128 sb.config.useDefaultSandBox = true 1129 } 1130 } 1131 1132 // OptionUseExternalKey function returns an option setter for using provided namespace 1133 // instead of creating one. 1134 func OptionUseExternalKey() SandboxOption { 1135 return func(sb *sandbox) { 1136 sb.config.useExternalKey = true 1137 } 1138 } 1139 1140 // OptionGeneric function returns an option setter for Generic configuration 1141 // that is not managed by libNetwork but can be used by the Drivers during the call to 1142 // net container creation method. Container Labels are a good example. 1143 func OptionGeneric(generic map[string]interface{}) SandboxOption { 1144 return func(sb *sandbox) { 1145 if sb.config.generic == nil { 1146 sb.config.generic = make(map[string]interface{}, len(generic)) 1147 } 1148 for k, v := range generic { 1149 sb.config.generic[k] = v 1150 } 1151 } 1152 } 1153 1154 // OptionExposedPorts function returns an option setter for the container exposed 1155 // ports option to be passed to container Create method. 1156 func OptionExposedPorts(exposedPorts []types.TransportPort) SandboxOption { 1157 return func(sb *sandbox) { 1158 if sb.config.generic == nil { 1159 sb.config.generic = make(map[string]interface{}) 1160 } 1161 // Defensive copy 1162 eps := make([]types.TransportPort, len(exposedPorts)) 1163 copy(eps, exposedPorts) 1164 // Store endpoint label and in generic because driver needs it 1165 sb.config.exposedPorts = eps 1166 sb.config.generic[netlabel.ExposedPorts] = eps 1167 } 1168 } 1169 1170 // OptionPortMapping function returns an option setter for the mapping 1171 // ports option to be passed to container Create method. 1172 func OptionPortMapping(portBindings []types.PortBinding) SandboxOption { 1173 return func(sb *sandbox) { 1174 if sb.config.generic == nil { 1175 sb.config.generic = make(map[string]interface{}) 1176 } 1177 // Store a copy of the bindings as generic data to pass to the driver 1178 pbs := make([]types.PortBinding, len(portBindings)) 1179 copy(pbs, portBindings) 1180 sb.config.generic[netlabel.PortMap] = pbs 1181 } 1182 } 1183 1184 // OptionIngress function returns an option setter for marking a 1185 // sandbox as the controller's ingress sandbox. 1186 func OptionIngress() SandboxOption { 1187 return func(sb *sandbox) { 1188 sb.ingress = true 1189 sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeIngress) 1190 } 1191 } 1192 1193 // OptionLoadBalancer function returns an option setter for marking a 1194 // sandbox as a load balancer sandbox. 1195 func OptionLoadBalancer(nid string) SandboxOption { 1196 return func(sb *sandbox) { 1197 sb.loadBalancerNID = nid 1198 sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeLoadBalancer) 1199 } 1200 } 1201 1202 // <=> Returns true if a < b, false if a > b and advances to next level if a == b 1203 // epi.prio <=> epj.prio # 2 < 1 1204 // epi.gw <=> epj.gw # non-gw < gw 1205 // epi.internal <=> epj.internal # non-internal < internal 1206 // epi.joininfo <=> epj.joininfo # ipv6 < ipv4 1207 // epi.name <=> epj.name # bar < foo 1208 func (epi *endpoint) Less(epj *endpoint) bool { 1209 var ( 1210 prioi, prioj int 1211 ) 1212 1213 sbi, _ := epi.getSandbox() 1214 sbj, _ := epj.getSandbox() 1215 1216 // Prio defaults to 0 1217 if sbi != nil { 1218 prioi = sbi.epPriority[epi.ID()] 1219 } 1220 if sbj != nil { 1221 prioj = sbj.epPriority[epj.ID()] 1222 } 1223 1224 if prioi != prioj { 1225 return prioi > prioj 1226 } 1227 1228 gwi := epi.endpointInGWNetwork() 1229 gwj := epj.endpointInGWNetwork() 1230 if gwi != gwj { 1231 return gwj 1232 } 1233 1234 inti := epi.getNetwork().Internal() 1235 intj := epj.getNetwork().Internal() 1236 if inti != intj { 1237 return intj 1238 } 1239 1240 jii := 0 1241 if epi.joinInfo != nil { 1242 if epi.joinInfo.gw != nil { 1243 jii = jii + 1 1244 } 1245 if epi.joinInfo.gw6 != nil { 1246 jii = jii + 2 1247 } 1248 } 1249 1250 jij := 0 1251 if epj.joinInfo != nil { 1252 if epj.joinInfo.gw != nil { 1253 jij = jij + 1 1254 } 1255 if epj.joinInfo.gw6 != nil { 1256 jij = jij + 2 1257 } 1258 } 1259 1260 if jii != jij { 1261 return jii > jij 1262 } 1263 1264 return epi.network.Name() < epj.network.Name() 1265 } 1266 1267 func (sb *sandbox) NdotsSet() bool { 1268 return sb.ndotsSet 1269 }