github.com/rawahars/moby@v24.0.4+incompatible/daemon/network.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  	"sync"
    11  
    12  	"github.com/docker/docker/api/types"
    13  	containertypes "github.com/docker/docker/api/types/container"
    14  	"github.com/docker/docker/api/types/filters"
    15  	"github.com/docker/docker/api/types/network"
    16  	"github.com/docker/docker/container"
    17  	clustertypes "github.com/docker/docker/daemon/cluster/provider"
    18  	internalnetwork "github.com/docker/docker/daemon/network"
    19  	"github.com/docker/docker/errdefs"
    20  	"github.com/docker/docker/libnetwork"
    21  	lncluster "github.com/docker/docker/libnetwork/cluster"
    22  	"github.com/docker/docker/libnetwork/driverapi"
    23  	"github.com/docker/docker/libnetwork/ipamapi"
    24  	"github.com/docker/docker/libnetwork/netlabel"
    25  	"github.com/docker/docker/libnetwork/networkdb"
    26  	"github.com/docker/docker/libnetwork/options"
    27  	networktypes "github.com/docker/docker/libnetwork/types"
    28  	"github.com/docker/docker/opts"
    29  	"github.com/docker/docker/pkg/plugingetter"
    30  	"github.com/docker/docker/runconfig"
    31  	"github.com/docker/go-connections/nat"
    32  	"github.com/pkg/errors"
    33  	"github.com/sirupsen/logrus"
    34  )
    35  
    36  // PredefinedNetworkError is returned when user tries to create predefined network that already exists.
    37  type PredefinedNetworkError string
    38  
    39  func (pnr PredefinedNetworkError) Error() string {
    40  	return fmt.Sprintf("operation is not permitted on predefined %s network ", string(pnr))
    41  }
    42  
    43  // Forbidden denotes the type of this error
    44  func (pnr PredefinedNetworkError) Forbidden() {}
    45  
    46  // NetworkControllerEnabled checks if the networking stack is enabled.
    47  // This feature depends on OS primitives and it's disabled in systems like Windows.
    48  func (daemon *Daemon) NetworkControllerEnabled() bool {
    49  	return daemon.netController != nil
    50  }
    51  
    52  // NetworkController returns the network controller created by the daemon.
    53  func (daemon *Daemon) NetworkController() *libnetwork.Controller {
    54  	return daemon.netController
    55  }
    56  
    57  // FindNetwork returns a network based on:
    58  // 1. Full ID
    59  // 2. Full Name
    60  // 3. Partial ID
    61  // as long as there is no ambiguity
    62  func (daemon *Daemon) FindNetwork(term string) (libnetwork.Network, error) {
    63  	listByFullName := []libnetwork.Network{}
    64  	listByPartialID := []libnetwork.Network{}
    65  	for _, nw := range daemon.getAllNetworks() {
    66  		if nw.ID() == term {
    67  			return nw, nil
    68  		}
    69  		if nw.Name() == term {
    70  			listByFullName = append(listByFullName, nw)
    71  		}
    72  		if strings.HasPrefix(nw.ID(), term) {
    73  			listByPartialID = append(listByPartialID, nw)
    74  		}
    75  	}
    76  	switch {
    77  	case len(listByFullName) == 1:
    78  		return listByFullName[0], nil
    79  	case len(listByFullName) > 1:
    80  		return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found on name)", term, len(listByFullName)))
    81  	case len(listByPartialID) == 1:
    82  		return listByPartialID[0], nil
    83  	case len(listByPartialID) > 1:
    84  		return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID)))
    85  	}
    86  
    87  	// Be very careful to change the error type here, the
    88  	// libnetwork.ErrNoSuchNetwork error is used by the controller
    89  	// to retry the creation of the network as managed through the swarm manager
    90  	return nil, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term))
    91  }
    92  
    93  // GetNetworkByID function returns a network whose ID matches the given ID.
    94  // It fails with an error if no matching network is found.
    95  func (daemon *Daemon) GetNetworkByID(id string) (libnetwork.Network, error) {
    96  	c := daemon.netController
    97  	if c == nil {
    98  		return nil, errors.Wrap(libnetwork.ErrNoSuchNetwork(id), "netcontroller is nil")
    99  	}
   100  	return c.NetworkByID(id)
   101  }
   102  
   103  // GetNetworkByName function returns a network for a given network name.
   104  // If no network name is given, the default network is returned.
   105  func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
   106  	c := daemon.netController
   107  	if c == nil {
   108  		return nil, libnetwork.ErrNoSuchNetwork(name)
   109  	}
   110  	if name == "" {
   111  		name = c.Config().DefaultNetwork
   112  	}
   113  	return c.NetworkByName(name)
   114  }
   115  
   116  // GetNetworksByIDPrefix returns a list of networks whose ID partially matches zero or more networks
   117  func (daemon *Daemon) GetNetworksByIDPrefix(partialID string) []libnetwork.Network {
   118  	c := daemon.netController
   119  	if c == nil {
   120  		return nil
   121  	}
   122  	list := []libnetwork.Network{}
   123  	l := func(nw libnetwork.Network) bool {
   124  		if strings.HasPrefix(nw.ID(), partialID) {
   125  			list = append(list, nw)
   126  		}
   127  		return false
   128  	}
   129  	c.WalkNetworks(l)
   130  
   131  	return list
   132  }
   133  
   134  // getAllNetworks returns a list containing all networks
   135  func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
   136  	c := daemon.netController
   137  	if c == nil {
   138  		return nil
   139  	}
   140  	return c.Networks()
   141  }
   142  
   143  type ingressJob struct {
   144  	create  *clustertypes.NetworkCreateRequest
   145  	ip      net.IP
   146  	jobDone chan struct{}
   147  }
   148  
   149  var (
   150  	ingressWorkerOnce  sync.Once
   151  	ingressJobsChannel chan *ingressJob
   152  	ingressID          string
   153  )
   154  
   155  func (daemon *Daemon) startIngressWorker() {
   156  	ingressJobsChannel = make(chan *ingressJob, 100)
   157  	go func() {
   158  		//nolint: gosimple
   159  		for {
   160  			select {
   161  			case r := <-ingressJobsChannel:
   162  				if r.create != nil {
   163  					daemon.setupIngress(r.create, r.ip, ingressID)
   164  					ingressID = r.create.ID
   165  				} else {
   166  					daemon.releaseIngress(ingressID)
   167  					ingressID = ""
   168  				}
   169  				close(r.jobDone)
   170  			}
   171  		}
   172  	}()
   173  }
   174  
   175  // enqueueIngressJob adds a ingress add/rm request to the worker queue.
   176  // It guarantees the worker is started.
   177  func (daemon *Daemon) enqueueIngressJob(job *ingressJob) {
   178  	ingressWorkerOnce.Do(daemon.startIngressWorker)
   179  	ingressJobsChannel <- job
   180  }
   181  
   182  // SetupIngress setups ingress networking.
   183  // The function returns a channel which will signal the caller when the programming is completed.
   184  func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) (<-chan struct{}, error) {
   185  	ip, _, err := net.ParseCIDR(nodeIP)
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	done := make(chan struct{})
   190  	daemon.enqueueIngressJob(&ingressJob{&create, ip, done})
   191  	return done, nil
   192  }
   193  
   194  // ReleaseIngress releases the ingress networking.
   195  // The function returns a channel which will signal the caller when the programming is completed.
   196  func (daemon *Daemon) ReleaseIngress() (<-chan struct{}, error) {
   197  	done := make(chan struct{})
   198  	daemon.enqueueIngressJob(&ingressJob{nil, nil, done})
   199  	return done, nil
   200  }
   201  
   202  func (daemon *Daemon) setupIngress(create *clustertypes.NetworkCreateRequest, ip net.IP, staleID string) {
   203  	controller := daemon.netController
   204  	controller.AgentInitWait()
   205  
   206  	if staleID != "" && staleID != create.ID {
   207  		daemon.releaseIngress(staleID)
   208  	}
   209  
   210  	if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
   211  		// If it is any other error other than already
   212  		// exists error log error and return.
   213  		if _, ok := err.(libnetwork.NetworkNameError); !ok {
   214  			logrus.Errorf("Failed creating ingress network: %v", err)
   215  			return
   216  		}
   217  		// Otherwise continue down the call to create or recreate sandbox.
   218  	}
   219  
   220  	_, err := daemon.GetNetworkByID(create.ID)
   221  	if err != nil {
   222  		logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
   223  	}
   224  }
   225  
   226  func (daemon *Daemon) releaseIngress(id string) {
   227  	controller := daemon.netController
   228  
   229  	if id == "" {
   230  		return
   231  	}
   232  
   233  	n, err := controller.NetworkByID(id)
   234  	if err != nil {
   235  		logrus.Errorf("failed to retrieve ingress network %s: %v", id, err)
   236  		return
   237  	}
   238  
   239  	if err := n.Delete(libnetwork.NetworkDeleteOptionRemoveLB); err != nil {
   240  		logrus.Errorf("Failed to delete ingress network %s: %v", n.ID(), err)
   241  		return
   242  	}
   243  }
   244  
   245  // SetNetworkBootstrapKeys sets the bootstrap keys.
   246  func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
   247  	err := daemon.netController.SetKeys(keys)
   248  	if err == nil {
   249  		// Upon successful key setting dispatch the keys available event
   250  		daemon.cluster.SendClusterEvent(lncluster.EventNetworkKeysAvailable)
   251  	}
   252  	return err
   253  }
   254  
   255  // UpdateAttachment notifies the attacher about the attachment config.
   256  func (daemon *Daemon) UpdateAttachment(networkName, networkID, containerID string, config *network.NetworkingConfig) error {
   257  	if daemon.clusterProvider == nil {
   258  		return fmt.Errorf("cluster provider is not initialized")
   259  	}
   260  
   261  	if err := daemon.clusterProvider.UpdateAttachment(networkName, containerID, config); err != nil {
   262  		return daemon.clusterProvider.UpdateAttachment(networkID, containerID, config)
   263  	}
   264  
   265  	return nil
   266  }
   267  
   268  // WaitForDetachment makes the cluster manager wait for detachment of
   269  // the container from the network.
   270  func (daemon *Daemon) WaitForDetachment(ctx context.Context, networkName, networkID, taskID, containerID string) error {
   271  	if daemon.clusterProvider == nil {
   272  		return fmt.Errorf("cluster provider is not initialized")
   273  	}
   274  
   275  	return daemon.clusterProvider.WaitForDetachment(ctx, networkName, networkID, taskID, containerID)
   276  }
   277  
   278  // CreateManagedNetwork creates an agent network.
   279  func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
   280  	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
   281  	return err
   282  }
   283  
   284  // CreateNetwork creates a network with the given name, driver and other optional parameters
   285  func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
   286  	return daemon.createNetwork(create, "", false)
   287  }
   288  
   289  func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
   290  	if runconfig.IsPreDefinedNetwork(create.Name) {
   291  		return nil, PredefinedNetworkError(create.Name)
   292  	}
   293  
   294  	var warning string
   295  	nw, err := daemon.GetNetworkByName(create.Name)
   296  	if err != nil {
   297  		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
   298  			return nil, err
   299  		}
   300  	}
   301  	if nw != nil {
   302  		// check if user defined CheckDuplicate, if set true, return err
   303  		// otherwise prepare a warning message
   304  		if create.CheckDuplicate {
   305  			if !agent || nw.Info().Dynamic() {
   306  				return nil, libnetwork.NetworkNameError(create.Name)
   307  			}
   308  		}
   309  		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
   310  	}
   311  
   312  	c := daemon.netController
   313  	driver := create.Driver
   314  	if driver == "" {
   315  		driver = c.Config().DefaultDriver
   316  	}
   317  
   318  	networkOptions := make(map[string]string)
   319  	for k, v := range create.Options {
   320  		networkOptions[k] = v
   321  	}
   322  	if defaultOpts, ok := daemon.configStore.DefaultNetworkOpts[driver]; create.ConfigFrom == nil && ok {
   323  		for k, v := range defaultOpts {
   324  			if _, ok := networkOptions[k]; !ok {
   325  				logrus.WithFields(logrus.Fields{"driver": driver, "network": id, k: v}).Debug("Applying network default option")
   326  				networkOptions[k] = v
   327  			}
   328  		}
   329  	}
   330  
   331  	nwOptions := []libnetwork.NetworkOption{
   332  		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
   333  		libnetwork.NetworkOptionDriverOpts(networkOptions),
   334  		libnetwork.NetworkOptionLabels(create.Labels),
   335  		libnetwork.NetworkOptionAttachable(create.Attachable),
   336  		libnetwork.NetworkOptionIngress(create.Ingress),
   337  		libnetwork.NetworkOptionScope(create.Scope),
   338  	}
   339  
   340  	if create.ConfigOnly {
   341  		nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly())
   342  	}
   343  
   344  	if create.IPAM != nil {
   345  		ipam := create.IPAM
   346  		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
   347  		if err != nil {
   348  			return nil, err
   349  		}
   350  		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
   351  	}
   352  
   353  	if create.Internal {
   354  		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
   355  	}
   356  	if agent {
   357  		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
   358  		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
   359  	}
   360  
   361  	if create.ConfigFrom != nil {
   362  		nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network))
   363  	}
   364  
   365  	if agent && driver == "overlay" {
   366  		nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id)
   367  		if !exists {
   368  			return nil, fmt.Errorf("failed to find a load balancer IP to use for network: %v", id)
   369  		}
   370  
   371  		nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP))
   372  	}
   373  
   374  	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
   375  	if err != nil {
   376  		if errors.Is(err, libnetwork.ErrDataStoreNotInitialized) {
   377  			//nolint: revive
   378  			return nil, errors.New("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again.")
   379  		}
   380  		return nil, err
   381  	}
   382  
   383  	daemon.pluginRefCount(driver, driverapi.NetworkPluginEndpointType, plugingetter.Acquire)
   384  	if create.IPAM != nil {
   385  		daemon.pluginRefCount(create.IPAM.Driver, ipamapi.PluginEndpointType, plugingetter.Acquire)
   386  	}
   387  	daemon.LogNetworkEvent(n, "create")
   388  
   389  	return &types.NetworkCreateResponse{
   390  		ID:      n.ID(),
   391  		Warning: warning,
   392  	}, nil
   393  }
   394  
   395  func (daemon *Daemon) pluginRefCount(driver, capability string, mode int) {
   396  	var builtinDrivers []string
   397  
   398  	if capability == driverapi.NetworkPluginEndpointType {
   399  		builtinDrivers = daemon.netController.BuiltinDrivers()
   400  	} else if capability == ipamapi.PluginEndpointType {
   401  		builtinDrivers = daemon.netController.BuiltinIPAMDrivers()
   402  	}
   403  
   404  	for _, d := range builtinDrivers {
   405  		if d == driver {
   406  			return
   407  		}
   408  	}
   409  
   410  	if daemon.PluginStore != nil {
   411  		_, err := daemon.PluginStore.Get(driver, capability, mode)
   412  		if err != nil {
   413  			logrus.WithError(err).WithFields(logrus.Fields{"mode": mode, "driver": driver}).Error("Error handling plugin refcount operation")
   414  		}
   415  	}
   416  }
   417  
   418  func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
   419  	ipamV4Cfg := []*libnetwork.IpamConf{}
   420  	ipamV6Cfg := []*libnetwork.IpamConf{}
   421  	for _, d := range data {
   422  		iCfg := libnetwork.IpamConf{}
   423  		iCfg.PreferredPool = d.Subnet
   424  		iCfg.SubPool = d.IPRange
   425  		iCfg.Gateway = d.Gateway
   426  		iCfg.AuxAddresses = d.AuxAddress
   427  		ip, _, err := net.ParseCIDR(d.Subnet)
   428  		if err != nil {
   429  			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
   430  		}
   431  		if ip.To4() != nil {
   432  			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
   433  		} else {
   434  			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
   435  		}
   436  	}
   437  	return ipamV4Cfg, ipamV6Cfg, nil
   438  }
   439  
   440  // UpdateContainerServiceConfig updates a service configuration.
   441  func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
   442  	ctr, err := daemon.GetContainer(containerName)
   443  	if err != nil {
   444  		return err
   445  	}
   446  
   447  	ctr.NetworkSettings.Service = serviceConfig
   448  	return nil
   449  }
   450  
   451  // ConnectContainerToNetwork connects the given container to the given
   452  // network. If either cannot be found, an err is returned. If the
   453  // network cannot be set up, an err is returned.
   454  func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
   455  	ctr, err := daemon.GetContainer(containerName)
   456  	if err != nil {
   457  		return err
   458  	}
   459  	return daemon.ConnectToNetwork(ctr, networkName, endpointConfig)
   460  }
   461  
   462  // DisconnectContainerFromNetwork disconnects the given container from
   463  // the given network. If either cannot be found, an err is returned.
   464  func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
   465  	ctr, err := daemon.GetContainer(containerName)
   466  	if err != nil {
   467  		if force {
   468  			return daemon.ForceEndpointDelete(containerName, networkName)
   469  		}
   470  		return err
   471  	}
   472  	return daemon.DisconnectFromNetwork(ctr, networkName, force)
   473  }
   474  
   475  // GetNetworkDriverList returns the list of plugins drivers
   476  // registered for network.
   477  func (daemon *Daemon) GetNetworkDriverList() []string {
   478  	if !daemon.NetworkControllerEnabled() {
   479  		return nil
   480  	}
   481  
   482  	pluginList := daemon.netController.BuiltinDrivers()
   483  
   484  	managedPlugins := daemon.PluginStore.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
   485  
   486  	for _, plugin := range managedPlugins {
   487  		pluginList = append(pluginList, plugin.Name())
   488  	}
   489  
   490  	pluginMap := make(map[string]bool)
   491  	for _, plugin := range pluginList {
   492  		pluginMap[plugin] = true
   493  	}
   494  
   495  	networks := daemon.netController.Networks()
   496  
   497  	for _, nw := range networks {
   498  		if !pluginMap[nw.Type()] {
   499  			pluginList = append(pluginList, nw.Type())
   500  			pluginMap[nw.Type()] = true
   501  		}
   502  	}
   503  
   504  	sort.Strings(pluginList)
   505  
   506  	return pluginList
   507  }
   508  
   509  // DeleteManagedNetwork deletes an agent network.
   510  // The requirement of networkID is enforced.
   511  func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
   512  	n, err := daemon.GetNetworkByID(networkID)
   513  	if err != nil {
   514  		return err
   515  	}
   516  	return daemon.deleteNetwork(n, true)
   517  }
   518  
   519  // DeleteNetwork destroys a network unless it's one of docker's predefined networks.
   520  func (daemon *Daemon) DeleteNetwork(networkID string) error {
   521  	n, err := daemon.GetNetworkByID(networkID)
   522  	if err != nil {
   523  		return errors.Wrap(err, "could not find network by ID")
   524  	}
   525  	return daemon.deleteNetwork(n, false)
   526  }
   527  
   528  func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error {
   529  	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
   530  		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
   531  		return errdefs.Forbidden(err)
   532  	}
   533  
   534  	if dynamic && !nw.Info().Dynamic() {
   535  		if runconfig.IsPreDefinedNetwork(nw.Name()) {
   536  			// Predefined networks now support swarm services. Make this
   537  			// a no-op when cluster requests to remove the predefined network.
   538  			return nil
   539  		}
   540  		err := fmt.Errorf("%s is not a dynamic network", nw.Name())
   541  		return errdefs.Forbidden(err)
   542  	}
   543  
   544  	if err := nw.Delete(); err != nil {
   545  		return errors.Wrap(err, "error while removing network")
   546  	}
   547  
   548  	// If this is not a configuration only network, we need to
   549  	// update the corresponding remote drivers' reference counts
   550  	if !nw.Info().ConfigOnly() {
   551  		daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release)
   552  		ipamType, _, _, _ := nw.Info().IpamConfig()
   553  		daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release)
   554  		daemon.LogNetworkEvent(nw, "destroy")
   555  	}
   556  
   557  	return nil
   558  }
   559  
   560  // GetNetworks returns a list of all networks
   561  func (daemon *Daemon) GetNetworks(filter filters.Args, config types.NetworkListConfig) ([]types.NetworkResource, error) {
   562  	networks := daemon.getAllNetworks()
   563  
   564  	list := make([]types.NetworkResource, 0, len(networks))
   565  	var idx map[string]libnetwork.Network
   566  	if config.Detailed {
   567  		idx = make(map[string]libnetwork.Network)
   568  	}
   569  
   570  	for _, n := range networks {
   571  		nr := buildNetworkResource(n)
   572  		list = append(list, nr)
   573  		if config.Detailed {
   574  			idx[nr.ID] = n
   575  		}
   576  	}
   577  
   578  	var err error
   579  	list, err = internalnetwork.FilterNetworks(list, filter)
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  
   584  	if config.Detailed {
   585  		for i := range list {
   586  			np := &list[i]
   587  			buildDetailedNetworkResources(np, idx[np.ID], config.Verbose)
   588  			list[i] = *np
   589  		}
   590  	}
   591  
   592  	return list, nil
   593  }
   594  
   595  func buildNetworkResource(nw libnetwork.Network) types.NetworkResource {
   596  	r := types.NetworkResource{}
   597  	if nw == nil {
   598  		return r
   599  	}
   600  
   601  	info := nw.Info()
   602  	r.Name = nw.Name()
   603  	r.ID = nw.ID()
   604  	r.Created = info.Created()
   605  	r.Scope = info.Scope()
   606  	r.Driver = nw.Type()
   607  	r.EnableIPv6 = info.IPv6Enabled()
   608  	r.Internal = info.Internal()
   609  	r.Attachable = info.Attachable()
   610  	r.Ingress = info.Ingress()
   611  	r.Options = info.DriverOptions()
   612  	r.Containers = make(map[string]types.EndpointResource)
   613  	buildIpamResources(&r, info)
   614  	r.Labels = info.Labels()
   615  	r.ConfigOnly = info.ConfigOnly()
   616  
   617  	if cn := info.ConfigFrom(); cn != "" {
   618  		r.ConfigFrom = network.ConfigReference{Network: cn}
   619  	}
   620  
   621  	peers := info.Peers()
   622  	if len(peers) != 0 {
   623  		r.Peers = buildPeerInfoResources(peers)
   624  	}
   625  
   626  	return r
   627  }
   628  
   629  func buildDetailedNetworkResources(r *types.NetworkResource, nw libnetwork.Network, verbose bool) {
   630  	if nw == nil {
   631  		return
   632  	}
   633  
   634  	epl := nw.Endpoints()
   635  	for _, e := range epl {
   636  		ei := e.Info()
   637  		if ei == nil {
   638  			continue
   639  		}
   640  		sb := ei.Sandbox()
   641  		tmpID := e.ID()
   642  		key := "ep-" + tmpID
   643  		if sb != nil {
   644  			key = sb.ContainerID()
   645  		}
   646  
   647  		r.Containers[key] = buildEndpointResource(tmpID, e.Name(), ei)
   648  	}
   649  	if !verbose {
   650  		return
   651  	}
   652  	services := nw.Info().Services()
   653  	r.Services = make(map[string]network.ServiceInfo)
   654  	for name, service := range services {
   655  		tasks := []network.Task{}
   656  		for _, t := range service.Tasks {
   657  			tasks = append(tasks, network.Task{
   658  				Name:       t.Name,
   659  				EndpointID: t.EndpointID,
   660  				EndpointIP: t.EndpointIP,
   661  				Info:       t.Info,
   662  			})
   663  		}
   664  		r.Services[name] = network.ServiceInfo{
   665  			VIP:          service.VIP,
   666  			Ports:        service.Ports,
   667  			Tasks:        tasks,
   668  			LocalLBIndex: service.LocalLBIndex,
   669  		}
   670  	}
   671  }
   672  
   673  func buildPeerInfoResources(peers []networkdb.PeerInfo) []network.PeerInfo {
   674  	peerInfo := make([]network.PeerInfo, 0, len(peers))
   675  	for _, peer := range peers {
   676  		peerInfo = append(peerInfo, network.PeerInfo{
   677  			Name: peer.Name,
   678  			IP:   peer.IP,
   679  		})
   680  	}
   681  	return peerInfo
   682  }
   683  
   684  func buildIpamResources(r *types.NetworkResource, nwInfo libnetwork.NetworkInfo) {
   685  	id, opts, ipv4conf, ipv6conf := nwInfo.IpamConfig()
   686  
   687  	ipv4Info, ipv6Info := nwInfo.IpamInfo()
   688  
   689  	r.IPAM.Driver = id
   690  
   691  	r.IPAM.Options = opts
   692  
   693  	r.IPAM.Config = []network.IPAMConfig{}
   694  	for _, ip4 := range ipv4conf {
   695  		if ip4.PreferredPool == "" {
   696  			continue
   697  		}
   698  		iData := network.IPAMConfig{}
   699  		iData.Subnet = ip4.PreferredPool
   700  		iData.IPRange = ip4.SubPool
   701  		iData.Gateway = ip4.Gateway
   702  		iData.AuxAddress = ip4.AuxAddresses
   703  		r.IPAM.Config = append(r.IPAM.Config, iData)
   704  	}
   705  
   706  	if len(r.IPAM.Config) == 0 {
   707  		for _, ip4Info := range ipv4Info {
   708  			iData := network.IPAMConfig{}
   709  			iData.Subnet = ip4Info.IPAMData.Pool.String()
   710  			if ip4Info.IPAMData.Gateway != nil {
   711  				iData.Gateway = ip4Info.IPAMData.Gateway.IP.String()
   712  			}
   713  			r.IPAM.Config = append(r.IPAM.Config, iData)
   714  		}
   715  	}
   716  
   717  	hasIpv6Conf := false
   718  	for _, ip6 := range ipv6conf {
   719  		if ip6.PreferredPool == "" {
   720  			continue
   721  		}
   722  		hasIpv6Conf = true
   723  		iData := network.IPAMConfig{}
   724  		iData.Subnet = ip6.PreferredPool
   725  		iData.IPRange = ip6.SubPool
   726  		iData.Gateway = ip6.Gateway
   727  		iData.AuxAddress = ip6.AuxAddresses
   728  		r.IPAM.Config = append(r.IPAM.Config, iData)
   729  	}
   730  
   731  	if !hasIpv6Conf {
   732  		for _, ip6Info := range ipv6Info {
   733  			if ip6Info.IPAMData.Pool == nil {
   734  				continue
   735  			}
   736  			iData := network.IPAMConfig{}
   737  			iData.Subnet = ip6Info.IPAMData.Pool.String()
   738  			iData.Gateway = ip6Info.IPAMData.Gateway.String()
   739  			r.IPAM.Config = append(r.IPAM.Config, iData)
   740  		}
   741  	}
   742  }
   743  
   744  func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo) types.EndpointResource {
   745  	er := types.EndpointResource{}
   746  
   747  	er.EndpointID = id
   748  	er.Name = name
   749  	ei := info
   750  	if ei == nil {
   751  		return er
   752  	}
   753  
   754  	if iface := ei.Iface(); iface != nil {
   755  		if mac := iface.MacAddress(); mac != nil {
   756  			er.MacAddress = mac.String()
   757  		}
   758  		if ip := iface.Address(); ip != nil && len(ip.IP) > 0 {
   759  			er.IPv4Address = ip.String()
   760  		}
   761  
   762  		if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 {
   763  			er.IPv6Address = ipv6.String()
   764  		}
   765  	}
   766  	return er
   767  }
   768  
   769  // clearAttachableNetworks removes the attachable networks
   770  // after disconnecting any connected container
   771  func (daemon *Daemon) clearAttachableNetworks() {
   772  	for _, n := range daemon.getAllNetworks() {
   773  		if !n.Info().Attachable() {
   774  			continue
   775  		}
   776  		for _, ep := range n.Endpoints() {
   777  			epInfo := ep.Info()
   778  			if epInfo == nil {
   779  				continue
   780  			}
   781  			sb := epInfo.Sandbox()
   782  			if sb == nil {
   783  				continue
   784  			}
   785  			containerID := sb.ContainerID()
   786  			if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil {
   787  				logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v",
   788  					containerID, n.Name(), err)
   789  			}
   790  		}
   791  		if err := daemon.DeleteManagedNetwork(n.ID()); err != nil {
   792  			logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err)
   793  		}
   794  	}
   795  }
   796  
   797  // buildCreateEndpointOptions builds endpoint options from a given network.
   798  func buildCreateEndpointOptions(c *container.Container, n libnetwork.Network, epConfig *network.EndpointSettings, sb *libnetwork.Sandbox, daemonDNS []string) ([]libnetwork.EndpointOption, error) {
   799  	var (
   800  		bindings      = make(nat.PortMap)
   801  		pbList        []networktypes.PortBinding
   802  		exposeList    []networktypes.TransportPort
   803  		createOptions []libnetwork.EndpointOption
   804  	)
   805  
   806  	defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
   807  
   808  	if (!serviceDiscoveryOnDefaultNetwork() && n.Name() == defaultNetName) ||
   809  		c.NetworkSettings.IsAnonymousEndpoint {
   810  		createOptions = append(createOptions, libnetwork.CreateOptionAnonymous())
   811  	}
   812  
   813  	if epConfig != nil {
   814  		ipam := epConfig.IPAMConfig
   815  
   816  		if ipam != nil {
   817  			var (
   818  				ipList          []net.IP
   819  				ip, ip6, linkip net.IP
   820  			)
   821  
   822  			for _, ips := range ipam.LinkLocalIPs {
   823  				if linkip = net.ParseIP(ips); linkip == nil && ips != "" {
   824  					return nil, errors.Errorf("Invalid link-local IP address: %s", ipam.LinkLocalIPs)
   825  				}
   826  				ipList = append(ipList, linkip)
   827  			}
   828  
   829  			if ip = net.ParseIP(ipam.IPv4Address); ip == nil && ipam.IPv4Address != "" {
   830  				return nil, errors.Errorf("Invalid IPv4 address: %s)", ipam.IPv4Address)
   831  			}
   832  
   833  			if ip6 = net.ParseIP(ipam.IPv6Address); ip6 == nil && ipam.IPv6Address != "" {
   834  				return nil, errors.Errorf("Invalid IPv6 address: %s)", ipam.IPv6Address)
   835  			}
   836  
   837  			createOptions = append(createOptions,
   838  				libnetwork.CreateOptionIpam(ip, ip6, ipList, nil))
   839  		}
   840  
   841  		for _, alias := range epConfig.Aliases {
   842  			createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias))
   843  		}
   844  		for k, v := range epConfig.DriverOpts {
   845  			createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v}))
   846  		}
   847  	}
   848  
   849  	if c.NetworkSettings.Service != nil {
   850  		svcCfg := c.NetworkSettings.Service
   851  
   852  		var vip string
   853  		if svcCfg.VirtualAddresses[n.ID()] != nil {
   854  			vip = svcCfg.VirtualAddresses[n.ID()].IPv4
   855  		}
   856  
   857  		var portConfigs []*libnetwork.PortConfig
   858  		for _, portConfig := range svcCfg.ExposedPorts {
   859  			portConfigs = append(portConfigs, &libnetwork.PortConfig{
   860  				Name:          portConfig.Name,
   861  				Protocol:      libnetwork.PortConfig_Protocol(portConfig.Protocol),
   862  				TargetPort:    portConfig.TargetPort,
   863  				PublishedPort: portConfig.PublishedPort,
   864  			})
   865  		}
   866  
   867  		createOptions = append(createOptions, libnetwork.CreateOptionService(svcCfg.Name, svcCfg.ID, net.ParseIP(vip), portConfigs, svcCfg.Aliases[n.ID()]))
   868  	}
   869  
   870  	if !containertypes.NetworkMode(n.Name()).IsUserDefined() {
   871  		createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution())
   872  	}
   873  
   874  	// configs that are applicable only for the endpoint in the network
   875  	// to which container was connected to on docker run.
   876  	// Ideally all these network-specific endpoint configurations must be moved under
   877  	// container.NetworkSettings.Networks[n.Name()]
   878  	if n.Name() == c.HostConfig.NetworkMode.NetworkName() ||
   879  		(n.Name() == defaultNetName && c.HostConfig.NetworkMode.IsDefault()) {
   880  		if c.Config.MacAddress != "" {
   881  			mac, err := net.ParseMAC(c.Config.MacAddress)
   882  			if err != nil {
   883  				return nil, err
   884  			}
   885  
   886  			genericOption := options.Generic{
   887  				netlabel.MacAddress: mac,
   888  			}
   889  
   890  			createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
   891  		}
   892  	}
   893  
   894  	// Port-mapping rules belong to the container & applicable only to non-internal networks
   895  	portmaps := getPortMapInfo(sb)
   896  	if n.Info().Internal() || len(portmaps) > 0 {
   897  		return createOptions, nil
   898  	}
   899  
   900  	if c.HostConfig.PortBindings != nil {
   901  		for p, b := range c.HostConfig.PortBindings {
   902  			bindings[p] = []nat.PortBinding{}
   903  			for _, bb := range b {
   904  				bindings[p] = append(bindings[p], nat.PortBinding{
   905  					HostIP:   bb.HostIP,
   906  					HostPort: bb.HostPort,
   907  				})
   908  			}
   909  		}
   910  	}
   911  
   912  	portSpecs := c.Config.ExposedPorts
   913  	ports := make([]nat.Port, len(portSpecs))
   914  	var i int
   915  	for p := range portSpecs {
   916  		ports[i] = p
   917  		i++
   918  	}
   919  	nat.SortPortMap(ports, bindings)
   920  	for _, port := range ports {
   921  		expose := networktypes.TransportPort{}
   922  		expose.Proto = networktypes.ParseProtocol(port.Proto())
   923  		expose.Port = uint16(port.Int())
   924  		exposeList = append(exposeList, expose)
   925  
   926  		pb := networktypes.PortBinding{Port: expose.Port, Proto: expose.Proto}
   927  		binding := bindings[port]
   928  		for i := 0; i < len(binding); i++ {
   929  			pbCopy := pb.GetCopy()
   930  			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
   931  			var portStart, portEnd int
   932  			if err == nil {
   933  				portStart, portEnd, err = newP.Range()
   934  			}
   935  			if err != nil {
   936  				return nil, errors.Wrapf(err, "Error parsing HostPort value (%s)", binding[i].HostPort)
   937  			}
   938  			pbCopy.HostPort = uint16(portStart)
   939  			pbCopy.HostPortEnd = uint16(portEnd)
   940  			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
   941  			pbList = append(pbList, pbCopy)
   942  		}
   943  
   944  		if c.HostConfig.PublishAllPorts && len(binding) == 0 {
   945  			pbList = append(pbList, pb)
   946  		}
   947  	}
   948  
   949  	var dns []string
   950  
   951  	if len(c.HostConfig.DNS) > 0 {
   952  		dns = c.HostConfig.DNS
   953  	} else if len(daemonDNS) > 0 {
   954  		dns = daemonDNS
   955  	}
   956  
   957  	if len(dns) > 0 {
   958  		createOptions = append(createOptions,
   959  			libnetwork.CreateOptionDNS(dns))
   960  	}
   961  
   962  	createOptions = append(createOptions,
   963  		libnetwork.CreateOptionPortMapping(pbList),
   964  		libnetwork.CreateOptionExposedPorts(exposeList))
   965  
   966  	return createOptions, nil
   967  }
   968  
   969  // getPortMapInfo retrieves the current port-mapping programmed for the given sandbox
   970  func getPortMapInfo(sb *libnetwork.Sandbox) nat.PortMap {
   971  	pm := nat.PortMap{}
   972  	if sb == nil {
   973  		return pm
   974  	}
   975  
   976  	for _, ep := range sb.Endpoints() {
   977  		pm, _ = getEndpointPortMapInfo(ep)
   978  		if len(pm) > 0 {
   979  			break
   980  		}
   981  	}
   982  	return pm
   983  }
   984  
   985  func getEndpointPortMapInfo(ep *libnetwork.Endpoint) (nat.PortMap, error) {
   986  	pm := nat.PortMap{}
   987  	driverInfo, err := ep.DriverInfo()
   988  	if err != nil {
   989  		return pm, err
   990  	}
   991  
   992  	if driverInfo == nil {
   993  		// It is not an error for epInfo to be nil
   994  		return pm, nil
   995  	}
   996  
   997  	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
   998  		if exposedPorts, ok := expData.([]networktypes.TransportPort); ok {
   999  			for _, tp := range exposedPorts {
  1000  				natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
  1001  				if err != nil {
  1002  					return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err)
  1003  				}
  1004  				pm[natPort] = nil
  1005  			}
  1006  		}
  1007  	}
  1008  
  1009  	mapData, ok := driverInfo[netlabel.PortMap]
  1010  	if !ok {
  1011  		return pm, nil
  1012  	}
  1013  
  1014  	if portMapping, ok := mapData.([]networktypes.PortBinding); ok {
  1015  		for _, pp := range portMapping {
  1016  			natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
  1017  			if err != nil {
  1018  				return pm, err
  1019  			}
  1020  			natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
  1021  			pm[natPort] = append(pm[natPort], natBndg)
  1022  		}
  1023  	}
  1024  
  1025  	return pm, nil
  1026  }
  1027  
  1028  // buildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint.
  1029  func buildEndpointInfo(networkSettings *internalnetwork.Settings, n libnetwork.Network, ep *libnetwork.Endpoint) error {
  1030  	if ep == nil {
  1031  		return errors.New("endpoint cannot be nil")
  1032  	}
  1033  
  1034  	if networkSettings == nil {
  1035  		return errors.New("network cannot be nil")
  1036  	}
  1037  
  1038  	epInfo := ep.Info()
  1039  	if epInfo == nil {
  1040  		// It is not an error to get an empty endpoint info
  1041  		return nil
  1042  	}
  1043  
  1044  	if _, ok := networkSettings.Networks[n.Name()]; !ok {
  1045  		networkSettings.Networks[n.Name()] = &internalnetwork.EndpointSettings{
  1046  			EndpointSettings: &network.EndpointSettings{},
  1047  		}
  1048  	}
  1049  	networkSettings.Networks[n.Name()].NetworkID = n.ID()
  1050  	networkSettings.Networks[n.Name()].EndpointID = ep.ID()
  1051  
  1052  	iface := epInfo.Iface()
  1053  	if iface == nil {
  1054  		return nil
  1055  	}
  1056  
  1057  	if iface.MacAddress() != nil {
  1058  		networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String()
  1059  	}
  1060  
  1061  	if iface.Address() != nil {
  1062  		ones, _ := iface.Address().Mask.Size()
  1063  		networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String()
  1064  		networkSettings.Networks[n.Name()].IPPrefixLen = ones
  1065  	}
  1066  
  1067  	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
  1068  		onesv6, _ := iface.AddressIPv6().Mask.Size()
  1069  		networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String()
  1070  		networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6
  1071  	}
  1072  
  1073  	return nil
  1074  }
  1075  
  1076  // buildJoinOptions builds endpoint Join options from a given network.
  1077  func buildJoinOptions(networkSettings *internalnetwork.Settings, n interface {
  1078  	Name() string
  1079  }) ([]libnetwork.EndpointOption, error) {
  1080  	var joinOptions []libnetwork.EndpointOption
  1081  	if epConfig, ok := networkSettings.Networks[n.Name()]; ok {
  1082  		for _, str := range epConfig.Links {
  1083  			name, alias, err := opts.ParseLink(str)
  1084  			if err != nil {
  1085  				return nil, err
  1086  			}
  1087  			joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
  1088  		}
  1089  		for k, v := range epConfig.DriverOpts {
  1090  			joinOptions = append(joinOptions, libnetwork.EndpointOptionGeneric(options.Generic{k: v}))
  1091  		}
  1092  	}
  1093  
  1094  	return joinOptions, nil
  1095  }