network.go 33 KB

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