github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/libnetwork/endpoint.go (about)

     1  // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
     2  //go:build go1.19
     3  
     4  package libnetwork
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net"
    11  	"sync"
    12  
    13  	"github.com/containerd/log"
    14  	"github.com/docker/docker/internal/sliceutil"
    15  	"github.com/docker/docker/libnetwork/datastore"
    16  	"github.com/docker/docker/libnetwork/ipamapi"
    17  	"github.com/docker/docker/libnetwork/netlabel"
    18  	"github.com/docker/docker/libnetwork/options"
    19  	"github.com/docker/docker/libnetwork/scope"
    20  	"github.com/docker/docker/libnetwork/types"
    21  )
    22  
    23  // ByNetworkType sorts a [Endpoint] slice based on the network-type
    24  // they're attached to. It implements [sort.Interface] and can be used
    25  // with [sort.Stable] or [sort.Sort]. It is used by [Sandbox.ResolveName]
    26  // when resolving names in swarm mode. In swarm mode, services with exposed
    27  // ports are connected to user overlay network, ingress network, and local
    28  // ("docker_gwbridge") networks. Name resolution should prioritize returning
    29  // the VIP/IPs on user overlay network over ingress and local networks.
    30  //
    31  // ByNetworkType re-orders the endpoints based on the network-type they
    32  // are attached to:
    33  //
    34  //  1. dynamic networks (user overlay networks)
    35  //  2. ingress network(s)
    36  //  3. local networks ("docker_gwbridge")
    37  type ByNetworkType []*Endpoint
    38  
    39  func (ep ByNetworkType) Len() int      { return len(ep) }
    40  func (ep ByNetworkType) Swap(i, j int) { ep[i], ep[j] = ep[j], ep[i] }
    41  func (ep ByNetworkType) Less(i, j int) bool {
    42  	return getNetworkType(ep[i].getNetwork()) < getNetworkType(ep[j].getNetwork())
    43  }
    44  
    45  // Define the order in which resolution should happen if an endpoint is
    46  // attached to multiple network-types. It is used by [ByNetworkType].
    47  const (
    48  	typeDynamic = iota
    49  	typeIngress
    50  	typeLocal
    51  )
    52  
    53  func getNetworkType(nw *Network) int {
    54  	switch {
    55  	case nw.ingress:
    56  		return typeIngress
    57  	case nw.dynamic:
    58  		return typeDynamic
    59  	default:
    60  		return typeLocal
    61  	}
    62  }
    63  
    64  // EndpointOption is an option setter function type used to pass various options to Network
    65  // and Endpoint interfaces methods. The various setter functions of type EndpointOption are
    66  // provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
    67  type EndpointOption func(ep *Endpoint)
    68  
    69  // Endpoint represents a logical connection between a network and a sandbox.
    70  type Endpoint struct {
    71  	name         string
    72  	id           string
    73  	network      *Network
    74  	iface        *EndpointInterface
    75  	joinInfo     *endpointJoinInfo
    76  	sandboxID    string
    77  	exposedPorts []types.TransportPort
    78  	// dnsNames holds all the non-fully qualified DNS names associated to this endpoint. Order matters: first entry
    79  	// will be used for the PTR records associated to the endpoint's IPv4 and IPv6 addresses.
    80  	dnsNames          []string
    81  	disableResolution bool
    82  	generic           map[string]interface{}
    83  	prefAddress       net.IP
    84  	prefAddressV6     net.IP
    85  	ipamOptions       map[string]string
    86  	aliases           map[string]string
    87  	svcID             string
    88  	svcName           string
    89  	virtualIP         net.IP
    90  	svcAliases        []string
    91  	ingressPorts      []*PortConfig
    92  	dbIndex           uint64
    93  	dbExists          bool
    94  	serviceEnabled    bool
    95  	loadBalancer      bool
    96  	mu                sync.Mutex
    97  }
    98  
    99  func (ep *Endpoint) MarshalJSON() ([]byte, error) {
   100  	ep.mu.Lock()
   101  	defer ep.mu.Unlock()
   102  
   103  	epMap := make(map[string]interface{})
   104  	epMap["name"] = ep.name
   105  	epMap["id"] = ep.id
   106  	epMap["ep_iface"] = ep.iface
   107  	epMap["joinInfo"] = ep.joinInfo
   108  	epMap["exposed_ports"] = ep.exposedPorts
   109  	if ep.generic != nil {
   110  		epMap["generic"] = ep.generic
   111  	}
   112  	epMap["sandbox"] = ep.sandboxID
   113  	epMap["dnsNames"] = ep.dnsNames
   114  	epMap["disableResolution"] = ep.disableResolution
   115  	epMap["svcName"] = ep.svcName
   116  	epMap["svcID"] = ep.svcID
   117  	epMap["virtualIP"] = ep.virtualIP.String()
   118  	epMap["ingressPorts"] = ep.ingressPorts
   119  	epMap["svcAliases"] = ep.svcAliases
   120  	epMap["loadBalancer"] = ep.loadBalancer
   121  
   122  	return json.Marshal(epMap)
   123  }
   124  
   125  func (ep *Endpoint) UnmarshalJSON(b []byte) (err error) {
   126  	ep.mu.Lock()
   127  	defer ep.mu.Unlock()
   128  
   129  	var epMap map[string]interface{}
   130  	if err := json.Unmarshal(b, &epMap); err != nil {
   131  		return err
   132  	}
   133  	ep.name = epMap["name"].(string)
   134  	ep.id = epMap["id"].(string)
   135  
   136  	// TODO(cpuguy83): So yeah, this isn't checking any errors anywhere.
   137  	// Seems like we should be checking errors even because of memory related issues that can arise.
   138  	// Alas it seems like given the nature of this data we could introduce problems if we start checking these errors.
   139  	//
   140  	// If anyone ever comes here and figures out one way or another if we can/should be checking these errors and it turns out we can't... then please document *why*
   141  
   142  	ib, _ := json.Marshal(epMap["ep_iface"])
   143  	json.Unmarshal(ib, &ep.iface) //nolint:errcheck
   144  
   145  	jb, _ := json.Marshal(epMap["joinInfo"])
   146  	json.Unmarshal(jb, &ep.joinInfo) //nolint:errcheck
   147  
   148  	tb, _ := json.Marshal(epMap["exposed_ports"])
   149  	var tPorts []types.TransportPort
   150  	json.Unmarshal(tb, &tPorts) //nolint:errcheck
   151  	ep.exposedPorts = tPorts
   152  
   153  	cb, _ := json.Marshal(epMap["sandbox"])
   154  	json.Unmarshal(cb, &ep.sandboxID) //nolint:errcheck
   155  
   156  	if v, ok := epMap["generic"]; ok {
   157  		ep.generic = v.(map[string]interface{})
   158  
   159  		if opt, ok := ep.generic[netlabel.PortMap]; ok {
   160  			pblist := []types.PortBinding{}
   161  
   162  			for i := 0; i < len(opt.([]interface{})); i++ {
   163  				pb := types.PortBinding{}
   164  				tmp := opt.([]interface{})[i].(map[string]interface{})
   165  
   166  				bytes, err := json.Marshal(tmp)
   167  				if err != nil {
   168  					log.G(context.TODO()).Error(err)
   169  					break
   170  				}
   171  				err = json.Unmarshal(bytes, &pb)
   172  				if err != nil {
   173  					log.G(context.TODO()).Error(err)
   174  					break
   175  				}
   176  				pblist = append(pblist, pb)
   177  			}
   178  			ep.generic[netlabel.PortMap] = pblist
   179  		}
   180  
   181  		if opt, ok := ep.generic[netlabel.ExposedPorts]; ok {
   182  			tplist := []types.TransportPort{}
   183  
   184  			for i := 0; i < len(opt.([]interface{})); i++ {
   185  				tp := types.TransportPort{}
   186  				tmp := opt.([]interface{})[i].(map[string]interface{})
   187  
   188  				bytes, err := json.Marshal(tmp)
   189  				if err != nil {
   190  					log.G(context.TODO()).Error(err)
   191  					break
   192  				}
   193  				err = json.Unmarshal(bytes, &tp)
   194  				if err != nil {
   195  					log.G(context.TODO()).Error(err)
   196  					break
   197  				}
   198  				tplist = append(tplist, tp)
   199  			}
   200  			ep.generic[netlabel.ExposedPorts] = tplist
   201  		}
   202  	}
   203  
   204  	var anonymous bool
   205  	if v, ok := epMap["anonymous"]; ok {
   206  		anonymous = v.(bool)
   207  	}
   208  	if v, ok := epMap["disableResolution"]; ok {
   209  		ep.disableResolution = v.(bool)
   210  	}
   211  
   212  	if sn, ok := epMap["svcName"]; ok {
   213  		ep.svcName = sn.(string)
   214  	}
   215  
   216  	if si, ok := epMap["svcID"]; ok {
   217  		ep.svcID = si.(string)
   218  	}
   219  
   220  	if vip, ok := epMap["virtualIP"]; ok {
   221  		ep.virtualIP = net.ParseIP(vip.(string))
   222  	}
   223  
   224  	if v, ok := epMap["loadBalancer"]; ok {
   225  		ep.loadBalancer = v.(bool)
   226  	}
   227  
   228  	sal, _ := json.Marshal(epMap["svcAliases"])
   229  	var svcAliases []string
   230  	json.Unmarshal(sal, &svcAliases) //nolint:errcheck
   231  	ep.svcAliases = svcAliases
   232  
   233  	pc, _ := json.Marshal(epMap["ingressPorts"])
   234  	var ingressPorts []*PortConfig
   235  	json.Unmarshal(pc, &ingressPorts) //nolint:errcheck
   236  	ep.ingressPorts = ingressPorts
   237  
   238  	ma, _ := json.Marshal(epMap["myAliases"])
   239  	var myAliases []string
   240  	json.Unmarshal(ma, &myAliases) //nolint:errcheck
   241  
   242  	_, hasDNSNames := epMap["dnsNames"]
   243  	dn, _ := json.Marshal(epMap["dnsNames"])
   244  	var dnsNames []string
   245  	json.Unmarshal(dn, &dnsNames)
   246  	ep.dnsNames = dnsNames
   247  
   248  	// TODO(aker): remove this migration code in v27
   249  	if !hasDNSNames {
   250  		// The field dnsNames was introduced in v25.0. If we don't have it, the on-disk state was written by an older
   251  		// daemon, thus we need to populate dnsNames based off of myAliases and anonymous values.
   252  		if !anonymous {
   253  			myAliases = append([]string{ep.name}, myAliases...)
   254  		}
   255  		ep.dnsNames = sliceutil.Dedup(myAliases)
   256  	}
   257  
   258  	return nil
   259  }
   260  
   261  func (ep *Endpoint) New() datastore.KVObject {
   262  	return &Endpoint{network: ep.getNetwork()}
   263  }
   264  
   265  func (ep *Endpoint) CopyTo(o datastore.KVObject) error {
   266  	ep.mu.Lock()
   267  	defer ep.mu.Unlock()
   268  
   269  	dstEp := o.(*Endpoint)
   270  	dstEp.name = ep.name
   271  	dstEp.id = ep.id
   272  	dstEp.sandboxID = ep.sandboxID
   273  	dstEp.dbIndex = ep.dbIndex
   274  	dstEp.dbExists = ep.dbExists
   275  	dstEp.disableResolution = ep.disableResolution
   276  	dstEp.svcName = ep.svcName
   277  	dstEp.svcID = ep.svcID
   278  	dstEp.virtualIP = ep.virtualIP
   279  	dstEp.loadBalancer = ep.loadBalancer
   280  
   281  	dstEp.svcAliases = make([]string, len(ep.svcAliases))
   282  	copy(dstEp.svcAliases, ep.svcAliases)
   283  
   284  	dstEp.ingressPorts = make([]*PortConfig, len(ep.ingressPorts))
   285  	copy(dstEp.ingressPorts, ep.ingressPorts)
   286  
   287  	if ep.iface != nil {
   288  		dstEp.iface = &EndpointInterface{}
   289  		if err := ep.iface.CopyTo(dstEp.iface); err != nil {
   290  			return err
   291  		}
   292  	}
   293  
   294  	if ep.joinInfo != nil {
   295  		dstEp.joinInfo = &endpointJoinInfo{}
   296  		if err := ep.joinInfo.CopyTo(dstEp.joinInfo); err != nil {
   297  			return err
   298  		}
   299  	}
   300  
   301  	dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
   302  	copy(dstEp.exposedPorts, ep.exposedPorts)
   303  
   304  	dstEp.dnsNames = make([]string, len(ep.dnsNames))
   305  	copy(dstEp.dnsNames, ep.dnsNames)
   306  
   307  	dstEp.generic = options.Generic{}
   308  	for k, v := range ep.generic {
   309  		dstEp.generic[k] = v
   310  	}
   311  
   312  	return nil
   313  }
   314  
   315  // ID returns the system-generated id for this endpoint.
   316  func (ep *Endpoint) ID() string {
   317  	ep.mu.Lock()
   318  	defer ep.mu.Unlock()
   319  
   320  	return ep.id
   321  }
   322  
   323  // Name returns the name of this endpoint.
   324  func (ep *Endpoint) Name() string {
   325  	ep.mu.Lock()
   326  	defer ep.mu.Unlock()
   327  
   328  	return ep.name
   329  }
   330  
   331  // Network returns the name of the network to which this endpoint is attached.
   332  func (ep *Endpoint) Network() string {
   333  	if ep.network == nil {
   334  		return ""
   335  	}
   336  
   337  	return ep.network.name
   338  }
   339  
   340  // getDNSNames returns a copy of the DNS names associated to this endpoint. The first entry is the one used for PTR
   341  // records.
   342  func (ep *Endpoint) getDNSNames() []string {
   343  	ep.mu.Lock()
   344  	defer ep.mu.Unlock()
   345  
   346  	dnsNames := make([]string, len(ep.dnsNames))
   347  	copy(dnsNames, ep.dnsNames)
   348  	return dnsNames
   349  }
   350  
   351  // isServiceEnabled check if service is enabled on the endpoint
   352  func (ep *Endpoint) isServiceEnabled() bool {
   353  	ep.mu.Lock()
   354  	defer ep.mu.Unlock()
   355  	return ep.serviceEnabled
   356  }
   357  
   358  // enableService sets service enabled on the endpoint
   359  func (ep *Endpoint) enableService() {
   360  	ep.mu.Lock()
   361  	defer ep.mu.Unlock()
   362  	ep.serviceEnabled = true
   363  }
   364  
   365  // disableService disables service on the endpoint
   366  func (ep *Endpoint) disableService() {
   367  	ep.mu.Lock()
   368  	defer ep.mu.Unlock()
   369  	ep.serviceEnabled = false
   370  }
   371  
   372  func (ep *Endpoint) needResolver() bool {
   373  	ep.mu.Lock()
   374  	defer ep.mu.Unlock()
   375  	return !ep.disableResolution
   376  }
   377  
   378  // endpoint Key structure : endpoint/network-id/endpoint-id
   379  func (ep *Endpoint) Key() []string {
   380  	if ep.network == nil {
   381  		return nil
   382  	}
   383  
   384  	return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id}
   385  }
   386  
   387  func (ep *Endpoint) KeyPrefix() []string {
   388  	if ep.network == nil {
   389  		return nil
   390  	}
   391  
   392  	return []string{datastore.EndpointKeyPrefix, ep.network.id}
   393  }
   394  
   395  func (ep *Endpoint) Value() []byte {
   396  	b, err := json.Marshal(ep)
   397  	if err != nil {
   398  		return nil
   399  	}
   400  	return b
   401  }
   402  
   403  func (ep *Endpoint) SetValue(value []byte) error {
   404  	return json.Unmarshal(value, ep)
   405  }
   406  
   407  func (ep *Endpoint) Index() uint64 {
   408  	ep.mu.Lock()
   409  	defer ep.mu.Unlock()
   410  	return ep.dbIndex
   411  }
   412  
   413  func (ep *Endpoint) SetIndex(index uint64) {
   414  	ep.mu.Lock()
   415  	defer ep.mu.Unlock()
   416  	ep.dbIndex = index
   417  	ep.dbExists = true
   418  }
   419  
   420  func (ep *Endpoint) Exists() bool {
   421  	ep.mu.Lock()
   422  	defer ep.mu.Unlock()
   423  	return ep.dbExists
   424  }
   425  
   426  func (ep *Endpoint) Skip() bool {
   427  	return ep.getNetwork().Skip()
   428  }
   429  
   430  func (ep *Endpoint) processOptions(options ...EndpointOption) {
   431  	ep.mu.Lock()
   432  	defer ep.mu.Unlock()
   433  
   434  	for _, opt := range options {
   435  		if opt != nil {
   436  			opt(ep)
   437  		}
   438  	}
   439  }
   440  
   441  func (ep *Endpoint) getNetwork() *Network {
   442  	ep.mu.Lock()
   443  	defer ep.mu.Unlock()
   444  
   445  	return ep.network
   446  }
   447  
   448  func (ep *Endpoint) getNetworkFromStore() (*Network, error) {
   449  	if ep.network == nil {
   450  		return nil, fmt.Errorf("invalid network object in endpoint %s", ep.Name())
   451  	}
   452  
   453  	return ep.network.getController().getNetworkFromStore(ep.network.id)
   454  }
   455  
   456  // Join joins the sandbox to the endpoint and populates into the sandbox
   457  // the network resources allocated for the endpoint.
   458  func (ep *Endpoint) Join(sb *Sandbox, options ...EndpointOption) error {
   459  	if sb == nil || sb.ID() == "" || sb.Key() == "" {
   460  		return types.InvalidParameterErrorf("invalid Sandbox passed to endpoint join: %v", sb)
   461  	}
   462  
   463  	sb.joinLeaveStart()
   464  	defer sb.joinLeaveEnd()
   465  
   466  	return ep.sbJoin(sb, options...)
   467  }
   468  
   469  func (ep *Endpoint) sbJoin(sb *Sandbox, options ...EndpointOption) (err error) {
   470  	n, err := ep.getNetworkFromStore()
   471  	if err != nil {
   472  		return fmt.Errorf("failed to get network from store during join: %v", err)
   473  	}
   474  
   475  	ep, err = n.getEndpointFromStore(ep.ID())
   476  	if err != nil {
   477  		return fmt.Errorf("failed to get endpoint from store during join: %v", err)
   478  	}
   479  
   480  	ep.mu.Lock()
   481  	if ep.sandboxID != "" {
   482  		ep.mu.Unlock()
   483  		return types.ForbiddenErrorf("another container is attached to the same network endpoint")
   484  	}
   485  	ep.network = n
   486  	ep.sandboxID = sb.ID()
   487  	ep.joinInfo = &endpointJoinInfo{}
   488  	epid := ep.id
   489  	ep.mu.Unlock()
   490  	defer func() {
   491  		if err != nil {
   492  			ep.mu.Lock()
   493  			ep.sandboxID = ""
   494  			ep.mu.Unlock()
   495  		}
   496  	}()
   497  
   498  	nid := n.ID()
   499  
   500  	ep.processOptions(options...)
   501  
   502  	d, err := n.driver(true)
   503  	if err != nil {
   504  		return fmt.Errorf("failed to get driver during join: %v", err)
   505  	}
   506  
   507  	err = d.Join(nid, epid, sb.Key(), ep, sb.Labels())
   508  	if err != nil {
   509  		return err
   510  	}
   511  	defer func() {
   512  		if err != nil {
   513  			if e := d.Leave(nid, epid); e != nil {
   514  				log.G(context.TODO()).Warnf("driver leave failed while rolling back join: %v", e)
   515  			}
   516  		}
   517  	}()
   518  
   519  	if !n.getController().isAgent() {
   520  		if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() {
   521  			n.updateSvcRecord(ep, true)
   522  		}
   523  	}
   524  
   525  	if err := sb.updateHostsFile(ep.getEtcHostsAddrs()); err != nil {
   526  		return err
   527  	}
   528  	if err = sb.updateDNS(n.enableIPv6); err != nil {
   529  		return err
   530  	}
   531  
   532  	// Current endpoint providing external connectivity for the sandbox
   533  	extEp := sb.getGatewayEndpoint()
   534  
   535  	sb.addEndpoint(ep)
   536  	defer func() {
   537  		if err != nil {
   538  			sb.removeEndpoint(ep)
   539  		}
   540  	}()
   541  
   542  	if err = sb.populateNetworkResources(ep); err != nil {
   543  		return err
   544  	}
   545  
   546  	if err = n.getController().updateToStore(ep); err != nil {
   547  		return err
   548  	}
   549  
   550  	if err = ep.addDriverInfoToCluster(); err != nil {
   551  		return err
   552  	}
   553  
   554  	defer func() {
   555  		if err != nil {
   556  			if e := ep.deleteDriverInfoFromCluster(); e != nil {
   557  				log.G(context.TODO()).Errorf("Could not delete endpoint state for endpoint %s from cluster on join failure: %v", ep.Name(), e)
   558  			}
   559  		}
   560  	}()
   561  
   562  	// Load balancing endpoints should never have a default gateway nor
   563  	// should they alter the status of a network's default gateway
   564  	if ep.loadBalancer && !sb.ingress {
   565  		return nil
   566  	}
   567  
   568  	if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
   569  		return sb.setupDefaultGW()
   570  	}
   571  
   572  	moveExtConn := sb.getGatewayEndpoint() != extEp
   573  
   574  	if moveExtConn {
   575  		if extEp != nil {
   576  			log.G(context.TODO()).Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
   577  			extN, err := extEp.getNetworkFromStore()
   578  			if err != nil {
   579  				return fmt.Errorf("failed to get network from store for revoking external connectivity during join: %v", err)
   580  			}
   581  			extD, err := extN.driver(true)
   582  			if err != nil {
   583  				return fmt.Errorf("failed to get driver for revoking external connectivity during join: %v", err)
   584  			}
   585  			if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
   586  				return types.InternalErrorf(
   587  					"driver failed revoking external connectivity on endpoint %s (%s): %v",
   588  					extEp.Name(), extEp.ID(), err)
   589  			}
   590  			defer func() {
   591  				if err != nil {
   592  					if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
   593  						log.G(context.TODO()).Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
   594  							extEp.Name(), extEp.ID(), e)
   595  					}
   596  				}
   597  			}()
   598  		}
   599  		if !n.internal {
   600  			log.G(context.TODO()).Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
   601  			if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
   602  				return types.InternalErrorf(
   603  					"driver failed programming external connectivity on endpoint %s (%s): %v",
   604  					ep.Name(), ep.ID(), err)
   605  			}
   606  		}
   607  	}
   608  
   609  	if !sb.needDefaultGW() {
   610  		if e := sb.clearDefaultGW(); e != nil {
   611  			log.G(context.TODO()).Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
   612  				sb.ID(), sb.ContainerID(), e)
   613  		}
   614  	}
   615  
   616  	return nil
   617  }
   618  
   619  func (ep *Endpoint) rename(name string) error {
   620  	ep.mu.Lock()
   621  	ep.name = name
   622  	ep.mu.Unlock()
   623  
   624  	// Update the store with the updated name
   625  	if err := ep.getNetwork().getController().updateToStore(ep); err != nil {
   626  		return err
   627  	}
   628  
   629  	return nil
   630  }
   631  
   632  func (ep *Endpoint) UpdateDNSNames(dnsNames []string) error {
   633  	nw := ep.getNetwork()
   634  	c := nw.getController()
   635  	sb, ok := ep.getSandbox()
   636  	if !ok {
   637  		log.G(context.TODO()).WithFields(log.Fields{
   638  			"sandboxID":  ep.sandboxID,
   639  			"endpointID": ep.ID(),
   640  		}).Warn("DNSNames update aborted, sandbox is not present anymore")
   641  		return nil
   642  	}
   643  
   644  	if c.isAgent() {
   645  		if err := ep.deleteServiceInfoFromCluster(sb, true, "UpdateDNSNames"); err != nil {
   646  			return types.InternalErrorf("could not delete service state for endpoint %s from cluster on UpdateDNSNames: %v", ep.Name(), err)
   647  		}
   648  
   649  		ep.dnsNames = dnsNames
   650  		if err := ep.addServiceInfoToCluster(sb); err != nil {
   651  			return types.InternalErrorf("could not add service state for endpoint %s to cluster on UpdateDNSNames: %v", ep.Name(), err)
   652  		}
   653  	} else {
   654  		nw.updateSvcRecord(ep, false)
   655  
   656  		ep.dnsNames = dnsNames
   657  		nw.updateSvcRecord(ep, true)
   658  	}
   659  
   660  	// Update the store with the updated name
   661  	if err := c.updateToStore(ep); err != nil {
   662  		return err
   663  	}
   664  
   665  	return nil
   666  }
   667  
   668  func (ep *Endpoint) hasInterface(iName string) bool {
   669  	ep.mu.Lock()
   670  	defer ep.mu.Unlock()
   671  
   672  	return ep.iface != nil && ep.iface.srcName == iName
   673  }
   674  
   675  // Leave detaches the network resources populated in the sandbox.
   676  func (ep *Endpoint) Leave(sb *Sandbox) error {
   677  	if sb == nil || sb.ID() == "" || sb.Key() == "" {
   678  		return types.InvalidParameterErrorf("invalid Sandbox passed to endpoint leave: %v", sb)
   679  	}
   680  
   681  	sb.joinLeaveStart()
   682  	defer sb.joinLeaveEnd()
   683  
   684  	return ep.sbLeave(sb, false)
   685  }
   686  
   687  func (ep *Endpoint) sbLeave(sb *Sandbox, force bool) error {
   688  	n, err := ep.getNetworkFromStore()
   689  	if err != nil {
   690  		return fmt.Errorf("failed to get network from store during leave: %v", err)
   691  	}
   692  
   693  	ep, err = n.getEndpointFromStore(ep.ID())
   694  	if err != nil {
   695  		return fmt.Errorf("failed to get endpoint from store during leave: %v", err)
   696  	}
   697  
   698  	ep.mu.Lock()
   699  	sid := ep.sandboxID
   700  	ep.mu.Unlock()
   701  
   702  	if sid == "" {
   703  		return types.ForbiddenErrorf("cannot leave endpoint with no attached sandbox")
   704  	}
   705  	if sid != sb.ID() {
   706  		return types.ForbiddenErrorf("unexpected sandbox ID in leave request. Expected %s. Got %s", ep.sandboxID, sb.ID())
   707  	}
   708  
   709  	d, err := n.driver(!force)
   710  	if err != nil {
   711  		return fmt.Errorf("failed to get driver during endpoint leave: %v", err)
   712  	}
   713  
   714  	ep.mu.Lock()
   715  	ep.sandboxID = ""
   716  	ep.network = n
   717  	ep.mu.Unlock()
   718  
   719  	// Current endpoint providing external connectivity to the sandbox
   720  	extEp := sb.getGatewayEndpoint()
   721  	moveExtConn := extEp != nil && (extEp.ID() == ep.ID())
   722  
   723  	if d != nil {
   724  		if moveExtConn {
   725  			log.G(context.TODO()).Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
   726  			if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
   727  				log.G(context.TODO()).Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
   728  					ep.Name(), ep.ID(), err)
   729  			}
   730  		}
   731  
   732  		if err := d.Leave(n.id, ep.id); err != nil {
   733  			if _, ok := err.(types.MaskableError); !ok {
   734  				log.G(context.TODO()).Warnf("driver error disconnecting container %s : %v", ep.name, err)
   735  			}
   736  		}
   737  	}
   738  
   739  	if err := ep.deleteServiceInfoFromCluster(sb, true, "sbLeave"); err != nil {
   740  		log.G(context.TODO()).Warnf("Failed to clean up service info on container %s disconnect: %v", ep.name, err)
   741  	}
   742  
   743  	if err := sb.clearNetworkResources(ep); err != nil {
   744  		log.G(context.TODO()).Warnf("Failed to clean up network resources on container %s disconnect: %v", ep.name, err)
   745  	}
   746  
   747  	// Update the store about the sandbox detach only after we
   748  	// have completed sb.clearNetworkresources above to avoid
   749  	// spurious logs when cleaning up the sandbox when the daemon
   750  	// ungracefully exits and restarts before completing sandbox
   751  	// detach but after store has been updated.
   752  	if err := n.getController().updateToStore(ep); err != nil {
   753  		return err
   754  	}
   755  
   756  	if e := ep.deleteDriverInfoFromCluster(); e != nil {
   757  		log.G(context.TODO()).Errorf("Failed to delete endpoint state for endpoint %s from cluster: %v", ep.Name(), e)
   758  	}
   759  
   760  	sb.deleteHostsEntries(n.getSvcRecords(ep))
   761  	if !sb.inDelete && sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
   762  		return sb.setupDefaultGW()
   763  	}
   764  
   765  	// New endpoint providing external connectivity for the sandbox
   766  	extEp = sb.getGatewayEndpoint()
   767  	if moveExtConn && extEp != nil {
   768  		log.G(context.TODO()).Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
   769  		extN, err := extEp.getNetworkFromStore()
   770  		if err != nil {
   771  			return fmt.Errorf("failed to get network from store for programming external connectivity during leave: %v", err)
   772  		}
   773  		extD, err := extN.driver(true)
   774  		if err != nil {
   775  			return fmt.Errorf("failed to get driver for programming external connectivity during leave: %v", err)
   776  		}
   777  		if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
   778  			log.G(context.TODO()).Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
   779  				extEp.Name(), extEp.ID(), err)
   780  		}
   781  	}
   782  
   783  	if !sb.needDefaultGW() {
   784  		if err := sb.clearDefaultGW(); err != nil {
   785  			log.G(context.TODO()).Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
   786  				sb.ID(), sb.ContainerID(), err)
   787  		}
   788  	}
   789  
   790  	return nil
   791  }
   792  
   793  // Delete deletes and detaches this endpoint from the network.
   794  func (ep *Endpoint) Delete(force bool) error {
   795  	var err error
   796  	n, err := ep.getNetworkFromStore()
   797  	if err != nil {
   798  		return fmt.Errorf("failed to get network during Delete: %v", err)
   799  	}
   800  
   801  	ep, err = n.getEndpointFromStore(ep.ID())
   802  	if err != nil {
   803  		return fmt.Errorf("failed to get endpoint from store during Delete: %v", err)
   804  	}
   805  
   806  	ep.mu.Lock()
   807  	epid := ep.id
   808  	name := ep.name
   809  	sbid := ep.sandboxID
   810  	ep.mu.Unlock()
   811  
   812  	sb, _ := n.getController().SandboxByID(sbid)
   813  	if sb != nil && !force {
   814  		return &ActiveContainerError{name: name, id: epid}
   815  	}
   816  
   817  	if sb != nil {
   818  		if e := ep.sbLeave(sb, force); e != nil {
   819  			log.G(context.TODO()).Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
   820  		}
   821  	}
   822  
   823  	if err = n.getController().deleteFromStore(ep); err != nil {
   824  		return err
   825  	}
   826  
   827  	defer func() {
   828  		if err != nil && !force {
   829  			ep.dbExists = false
   830  			if e := n.getController().updateToStore(ep); e != nil {
   831  				log.G(context.TODO()).Warnf("failed to recreate endpoint in store %s : %v", name, e)
   832  			}
   833  		}
   834  	}()
   835  
   836  	if !n.getController().isSwarmNode() || n.Scope() != scope.Swarm || !n.driverIsMultihost() {
   837  		n.updateSvcRecord(ep, false)
   838  	}
   839  
   840  	if err = ep.deleteEndpoint(force); err != nil && !force {
   841  		return err
   842  	}
   843  
   844  	ep.releaseAddress()
   845  
   846  	if err := n.getEpCnt().DecEndpointCnt(); err != nil {
   847  		log.G(context.TODO()).Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err)
   848  	}
   849  
   850  	return nil
   851  }
   852  
   853  func (ep *Endpoint) deleteEndpoint(force bool) error {
   854  	ep.mu.Lock()
   855  	n := ep.network
   856  	name := ep.name
   857  	epid := ep.id
   858  	ep.mu.Unlock()
   859  
   860  	driver, err := n.driver(!force)
   861  	if err != nil {
   862  		return fmt.Errorf("failed to delete endpoint: %v", err)
   863  	}
   864  
   865  	if driver == nil {
   866  		return nil
   867  	}
   868  
   869  	if err := driver.DeleteEndpoint(n.id, epid); err != nil {
   870  		if _, ok := err.(types.ForbiddenError); ok {
   871  			return err
   872  		}
   873  
   874  		if _, ok := err.(types.MaskableError); !ok {
   875  			log.G(context.TODO()).Warnf("driver error deleting endpoint %s : %v", name, err)
   876  		}
   877  	}
   878  
   879  	return nil
   880  }
   881  
   882  func (ep *Endpoint) getSandbox() (*Sandbox, bool) {
   883  	c := ep.network.getController()
   884  	ep.mu.Lock()
   885  	sid := ep.sandboxID
   886  	ep.mu.Unlock()
   887  
   888  	c.mu.Lock()
   889  	ps, ok := c.sandboxes[sid]
   890  	c.mu.Unlock()
   891  
   892  	return ps, ok
   893  }
   894  
   895  // Return a list of this endpoint's addresses to add to '/etc/hosts'.
   896  func (ep *Endpoint) getEtcHostsAddrs() []string {
   897  	ep.mu.Lock()
   898  	defer ep.mu.Unlock()
   899  
   900  	// Do not update hosts file with internal network's endpoint IP
   901  	if n := ep.network; n == nil || n.ingress || n.Name() == libnGWNetwork {
   902  		return nil
   903  	}
   904  
   905  	var addresses []string
   906  	if ep.iface.addr != nil {
   907  		addresses = append(addresses, ep.iface.addr.IP.String())
   908  	}
   909  	if ep.iface.addrv6 != nil {
   910  		addresses = append(addresses, ep.iface.addrv6.IP.String())
   911  	}
   912  	return addresses
   913  }
   914  
   915  // EndpointOptionGeneric function returns an option setter for a Generic option defined
   916  // in a Dictionary of Key-Value pair
   917  func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
   918  	return func(ep *Endpoint) {
   919  		for k, v := range generic {
   920  			ep.generic[k] = v
   921  		}
   922  	}
   923  }
   924  
   925  var (
   926  	linkLocalMask     = net.CIDRMask(16, 32)
   927  	linkLocalMaskIPv6 = net.CIDRMask(64, 128)
   928  )
   929  
   930  // CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint
   931  func CreateOptionIpam(ipV4, ipV6 net.IP, llIPs []net.IP, ipamOptions map[string]string) EndpointOption {
   932  	return func(ep *Endpoint) {
   933  		ep.prefAddress = ipV4
   934  		ep.prefAddressV6 = ipV6
   935  		if len(llIPs) != 0 {
   936  			for _, ip := range llIPs {
   937  				nw := &net.IPNet{IP: ip, Mask: linkLocalMask}
   938  				if ip.To4() == nil {
   939  					nw.Mask = linkLocalMaskIPv6
   940  				}
   941  				ep.iface.llAddrs = append(ep.iface.llAddrs, nw)
   942  			}
   943  		}
   944  		ep.ipamOptions = ipamOptions
   945  	}
   946  }
   947  
   948  // CreateOptionExposedPorts function returns an option setter for the container exposed
   949  // ports option to be passed to [Network.CreateEndpoint] method.
   950  func CreateOptionExposedPorts(exposedPorts []types.TransportPort) EndpointOption {
   951  	return func(ep *Endpoint) {
   952  		// Defensive copy
   953  		eps := make([]types.TransportPort, len(exposedPorts))
   954  		copy(eps, exposedPorts)
   955  		// Store endpoint label and in generic because driver needs it
   956  		ep.exposedPorts = eps
   957  		ep.generic[netlabel.ExposedPorts] = eps
   958  	}
   959  }
   960  
   961  // CreateOptionPortMapping function returns an option setter for the mapping
   962  // ports option to be passed to [Network.CreateEndpoint] method.
   963  func CreateOptionPortMapping(portBindings []types.PortBinding) EndpointOption {
   964  	return func(ep *Endpoint) {
   965  		// Store a copy of the bindings as generic data to pass to the driver
   966  		pbs := make([]types.PortBinding, len(portBindings))
   967  		copy(pbs, portBindings)
   968  		ep.generic[netlabel.PortMap] = pbs
   969  	}
   970  }
   971  
   972  // CreateOptionDNS function returns an option setter for dns entry option to
   973  // be passed to container Create method.
   974  func CreateOptionDNS(dns []string) EndpointOption {
   975  	return func(ep *Endpoint) {
   976  		ep.generic[netlabel.DNSServers] = dns
   977  	}
   978  }
   979  
   980  // CreateOptionDNSNames specifies the list of (non fully qualified) DNS names associated to an endpoint. These will be
   981  // used to populate the embedded DNS server. Order matters: first name will be used to generate PTR records.
   982  func CreateOptionDNSNames(names []string) EndpointOption {
   983  	return func(ep *Endpoint) {
   984  		ep.dnsNames = names
   985  	}
   986  }
   987  
   988  // CreateOptionDisableResolution function returns an option setter to indicate
   989  // this endpoint doesn't want embedded DNS server functionality
   990  func CreateOptionDisableResolution() EndpointOption {
   991  	return func(ep *Endpoint) {
   992  		ep.disableResolution = true
   993  	}
   994  }
   995  
   996  // CreateOptionAlias function returns an option setter for setting endpoint alias
   997  func CreateOptionAlias(name string, alias string) EndpointOption {
   998  	return func(ep *Endpoint) {
   999  		if ep.aliases == nil {
  1000  			ep.aliases = make(map[string]string)
  1001  		}
  1002  		ep.aliases[alias] = name
  1003  	}
  1004  }
  1005  
  1006  // CreateOptionService function returns an option setter for setting service binding configuration
  1007  func CreateOptionService(name, id string, vip net.IP, ingressPorts []*PortConfig, aliases []string) EndpointOption {
  1008  	return func(ep *Endpoint) {
  1009  		ep.svcName = name
  1010  		ep.svcID = id
  1011  		ep.virtualIP = vip
  1012  		ep.ingressPorts = ingressPorts
  1013  		ep.svcAliases = aliases
  1014  	}
  1015  }
  1016  
  1017  // CreateOptionLoadBalancer function returns an option setter for denoting the endpoint is a load balancer for a network
  1018  func CreateOptionLoadBalancer() EndpointOption {
  1019  	return func(ep *Endpoint) {
  1020  		ep.loadBalancer = true
  1021  	}
  1022  }
  1023  
  1024  // JoinOptionPriority function returns an option setter for priority option to
  1025  // be passed to the endpoint.Join() method.
  1026  func JoinOptionPriority(prio int) EndpointOption {
  1027  	return func(ep *Endpoint) {
  1028  		// ep lock already acquired
  1029  		c := ep.network.getController()
  1030  		c.mu.Lock()
  1031  		sb, ok := c.sandboxes[ep.sandboxID]
  1032  		c.mu.Unlock()
  1033  		if !ok {
  1034  			log.G(context.TODO()).Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
  1035  			return
  1036  		}
  1037  		sb.epPriority[ep.id] = prio
  1038  	}
  1039  }
  1040  
  1041  func (ep *Endpoint) assignAddress(ipam ipamapi.Ipam, assignIPv4, assignIPv6 bool) error {
  1042  	var err error
  1043  
  1044  	n := ep.getNetwork()
  1045  	if n.hasSpecialDriver() {
  1046  		return nil
  1047  	}
  1048  
  1049  	log.G(context.TODO()).Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  1050  
  1051  	if assignIPv4 {
  1052  		if err = ep.assignAddressVersion(4, ipam); err != nil {
  1053  			return err
  1054  		}
  1055  	}
  1056  
  1057  	if assignIPv6 {
  1058  		err = ep.assignAddressVersion(6, ipam)
  1059  	}
  1060  
  1061  	return err
  1062  }
  1063  
  1064  func (ep *Endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
  1065  	var (
  1066  		poolID  *string
  1067  		address **net.IPNet
  1068  		prefAdd net.IP
  1069  		progAdd net.IP
  1070  	)
  1071  
  1072  	n := ep.getNetwork()
  1073  	switch ipVer {
  1074  	case 4:
  1075  		poolID = &ep.iface.v4PoolID
  1076  		address = &ep.iface.addr
  1077  		prefAdd = ep.prefAddress
  1078  	case 6:
  1079  		poolID = &ep.iface.v6PoolID
  1080  		address = &ep.iface.addrv6
  1081  		prefAdd = ep.prefAddressV6
  1082  	default:
  1083  		return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
  1084  	}
  1085  
  1086  	ipInfo := n.getIPInfo(ipVer)
  1087  
  1088  	// ipv6 address is not mandatory
  1089  	if len(ipInfo) == 0 && ipVer == 6 {
  1090  		return nil
  1091  	}
  1092  
  1093  	// The address to program may be chosen by the user or by the network driver in one specific
  1094  	// case to support backward compatibility with `docker daemon --fixed-cidrv6` use case
  1095  	if prefAdd != nil {
  1096  		progAdd = prefAdd
  1097  	} else if *address != nil {
  1098  		progAdd = (*address).IP
  1099  	}
  1100  
  1101  	for _, d := range ipInfo {
  1102  		if progAdd != nil && !d.Pool.Contains(progAdd) {
  1103  			continue
  1104  		}
  1105  		addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions)
  1106  		if err == nil {
  1107  			ep.mu.Lock()
  1108  			*address = addr
  1109  			*poolID = d.PoolID
  1110  			ep.mu.Unlock()
  1111  			return nil
  1112  		}
  1113  		if err != ipamapi.ErrNoAvailableIPs || progAdd != nil {
  1114  			return err
  1115  		}
  1116  	}
  1117  	if progAdd != nil {
  1118  		return types.InvalidParameterErrorf("invalid address %s: It does not belong to any of this network's subnets", prefAdd)
  1119  	}
  1120  	return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
  1121  }
  1122  
  1123  func (ep *Endpoint) releaseAddress() {
  1124  	n := ep.getNetwork()
  1125  	if n.hasSpecialDriver() {
  1126  		return
  1127  	}
  1128  
  1129  	log.G(context.TODO()).Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
  1130  
  1131  	ipam, _, err := n.getController().getIPAMDriver(n.ipamType)
  1132  	if err != nil {
  1133  		log.G(context.TODO()).Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
  1134  		return
  1135  	}
  1136  
  1137  	if ep.iface.addr != nil {
  1138  		if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
  1139  			log.G(context.TODO()).Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
  1140  		}
  1141  	}
  1142  
  1143  	if ep.iface.addrv6 != nil {
  1144  		if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
  1145  			log.G(context.TODO()).Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
  1146  		}
  1147  	}
  1148  }
  1149  
  1150  func (c *Controller) cleanupLocalEndpoints() error {
  1151  	// Get used endpoints
  1152  	eps := make(map[string]interface{})
  1153  	for _, sb := range c.sandboxes {
  1154  		for _, ep := range sb.endpoints {
  1155  			eps[ep.id] = true
  1156  		}
  1157  	}
  1158  	nl, err := c.getNetworks()
  1159  	if err != nil {
  1160  		return fmt.Errorf("could not get list of networks: %v", err)
  1161  	}
  1162  
  1163  	for _, n := range nl {
  1164  		if n.ConfigOnly() {
  1165  			continue
  1166  		}
  1167  		epl, err := n.getEndpointsFromStore()
  1168  		if err != nil {
  1169  			log.G(context.TODO()).Warnf("Could not get list of endpoints in network %s during endpoint cleanup: %v", n.name, err)
  1170  			continue
  1171  		}
  1172  
  1173  		for _, ep := range epl {
  1174  			if _, ok := eps[ep.id]; ok {
  1175  				continue
  1176  			}
  1177  			log.G(context.TODO()).Infof("Removing stale endpoint %s (%s)", ep.name, ep.id)
  1178  			if err := ep.Delete(true); err != nil {
  1179  				log.G(context.TODO()).Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
  1180  			}
  1181  		}
  1182  
  1183  		epl, err = n.getEndpointsFromStore()
  1184  		if err != nil {
  1185  			log.G(context.TODO()).Warnf("Could not get list of endpoints in network %s for count update: %v", n.name, err)
  1186  			continue
  1187  		}
  1188  
  1189  		epCnt := n.getEpCnt().EndpointCnt()
  1190  		if epCnt != uint64(len(epl)) {
  1191  			log.G(context.TODO()).Infof("Fixing inconsistent endpoint_cnt for network %s. Expected=%d, Actual=%d", n.name, len(epl), epCnt)
  1192  			if err := n.getEpCnt().setCnt(uint64(len(epl))); err != nil {
  1193  				log.G(context.TODO()).WithField("network", n.name).WithError(err).Warn("Error while fixing inconsistent endpoint_cnt for network")
  1194  			}
  1195  		}
  1196  	}
  1197  
  1198  	return nil
  1199  }