windows.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. //go:build windows
  2. // Shim for the Host Network Service (HNS) to manage networking for
  3. // Windows Server containers and Hyper-V containers. This module
  4. // is a basic libnetwork driver that passes all the calls to HNS
  5. // It implements the 4 networking modes supported by HNS L2Bridge,
  6. // L2Tunnel, NAT and Transparent(DHCP)
  7. //
  8. // The network are stored in memory and docker daemon ensures discovering
  9. // and loading these networks on startup
  10. package windows
  11. import (
  12. "context"
  13. "encoding/json"
  14. "fmt"
  15. "net"
  16. "strconv"
  17. "strings"
  18. "sync"
  19. "github.com/Microsoft/hcsshim"
  20. "github.com/containerd/log"
  21. "github.com/docker/docker/libnetwork/datastore"
  22. "github.com/docker/docker/libnetwork/driverapi"
  23. "github.com/docker/docker/libnetwork/netlabel"
  24. "github.com/docker/docker/libnetwork/portmapper"
  25. "github.com/docker/docker/libnetwork/scope"
  26. "github.com/docker/docker/libnetwork/types"
  27. )
  28. // networkConfiguration for network specific configuration
  29. type networkConfiguration struct {
  30. ID string
  31. Type string
  32. Name string
  33. HnsID string
  34. RDID string
  35. VLAN uint
  36. VSID uint
  37. DNSServers string
  38. MacPools []hcsshim.MacPool
  39. DNSSuffix string
  40. SourceMac string
  41. NetworkAdapterName string
  42. dbIndex uint64
  43. dbExists bool
  44. DisableGatewayDNS bool
  45. EnableOutboundNat bool
  46. OutboundNatExceptions []string
  47. }
  48. // endpointConfiguration represents the user specified configuration for the sandbox endpoint
  49. type endpointOption struct {
  50. MacAddress net.HardwareAddr
  51. QosPolicies []types.QosPolicy
  52. DNSServers []string
  53. DisableDNS bool
  54. DisableICC bool
  55. }
  56. // EndpointConnectivity stores the port bindings and exposed ports that the user has specified in epOptions.
  57. type EndpointConnectivity struct {
  58. PortBindings []types.PortBinding
  59. ExposedPorts []types.TransportPort
  60. }
  61. type hnsEndpoint struct {
  62. id string
  63. nid string
  64. profileID string
  65. Type string
  66. // Note: Currently, the sandboxID is the same as the containerID since windows does
  67. // not expose the sandboxID.
  68. // In the future, windows will support a proper sandboxID that is different
  69. // than the containerID.
  70. // Therefore, we are using sandboxID now, so that we won't have to change this code
  71. // when windows properly supports a sandboxID.
  72. sandboxID string
  73. macAddress net.HardwareAddr
  74. epOption *endpointOption // User specified parameters
  75. epConnectivity *EndpointConnectivity // User specified parameters
  76. portMapping []types.PortBinding // Operation port bindings
  77. addr *net.IPNet
  78. gateway net.IP
  79. dbIndex uint64
  80. dbExists bool
  81. }
  82. type hnsNetwork struct {
  83. id string
  84. created bool
  85. config *networkConfiguration
  86. endpoints map[string]*hnsEndpoint // key: endpoint id
  87. driver *driver // The network's driver
  88. portMapper *portmapper.PortMapper
  89. sync.Mutex
  90. }
  91. type driver struct {
  92. name string
  93. networks map[string]*hnsNetwork
  94. store *datastore.Store
  95. sync.Mutex
  96. }
  97. const (
  98. errNotFound = "HNS failed with error : The object identifier does not represent a valid object. "
  99. )
  100. var builtinLocalDrivers = map[string]struct{}{
  101. "transparent": {},
  102. "l2bridge": {},
  103. "l2tunnel": {},
  104. "nat": {},
  105. "internal": {},
  106. "private": {},
  107. "ics": {},
  108. }
  109. // IsBuiltinLocalDriver validates if network-type is a builtin local-scoped driver
  110. func IsBuiltinLocalDriver(networkType string) bool {
  111. _, ok := builtinLocalDrivers[networkType]
  112. return ok
  113. }
  114. // New constructs a new bridge driver
  115. func newDriver(networkType string) *driver {
  116. return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
  117. }
  118. // GetInit returns an initializer for the given network type
  119. func RegisterBuiltinLocalDrivers(r driverapi.Registerer, driverConfig func(string) map[string]interface{}) error {
  120. for networkType := range builtinLocalDrivers {
  121. d := newDriver(networkType)
  122. err := d.initStore(driverConfig(networkType))
  123. if err != nil {
  124. return fmt.Errorf("failed to initialize %q driver: %w", networkType, err)
  125. }
  126. err = r.RegisterDriver(networkType, d, driverapi.Capability{
  127. DataScope: scope.Local,
  128. ConnectivityScope: scope.Local,
  129. })
  130. if err != nil {
  131. return fmt.Errorf("failed to register %q driver: %w", networkType, err)
  132. }
  133. }
  134. return nil
  135. }
  136. func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
  137. d.Lock()
  138. defer d.Unlock()
  139. if nw, ok := d.networks[id]; ok {
  140. return nw, nil
  141. }
  142. return nil, types.NotFoundErrorf("network not found: %s", id)
  143. }
  144. func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
  145. n.Lock()
  146. defer n.Unlock()
  147. if ep, ok := n.endpoints[eid]; ok {
  148. return ep, nil
  149. }
  150. return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
  151. }
  152. func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
  153. config := &networkConfiguration{Type: d.name}
  154. for label, value := range genericOptions {
  155. switch label {
  156. case NetworkName:
  157. config.Name = value
  158. case HNSID:
  159. config.HnsID = value
  160. case RoutingDomain:
  161. config.RDID = value
  162. case Interface:
  163. config.NetworkAdapterName = value
  164. case DNSSuffix:
  165. config.DNSSuffix = value
  166. case DNSServers:
  167. config.DNSServers = value
  168. case DisableGatewayDNS:
  169. b, err := strconv.ParseBool(value)
  170. if err != nil {
  171. return nil, err
  172. }
  173. config.DisableGatewayDNS = b
  174. case MacPool:
  175. config.MacPools = make([]hcsshim.MacPool, 0)
  176. s := strings.Split(value, ",")
  177. if len(s)%2 != 0 {
  178. return nil, types.InvalidParameterErrorf("invalid mac pool. You must specify both a start range and an end range")
  179. }
  180. for i := 0; i < len(s)-1; i += 2 {
  181. config.MacPools = append(config.MacPools, hcsshim.MacPool{
  182. StartMacAddress: s[i],
  183. EndMacAddress: s[i+1],
  184. })
  185. }
  186. case VLAN:
  187. vlan, err := strconv.ParseUint(value, 10, 32)
  188. if err != nil {
  189. return nil, err
  190. }
  191. config.VLAN = uint(vlan)
  192. case VSID:
  193. vsid, err := strconv.ParseUint(value, 10, 32)
  194. if err != nil {
  195. return nil, err
  196. }
  197. config.VSID = uint(vsid)
  198. case EnableOutboundNat:
  199. b, err := strconv.ParseBool(value)
  200. if err != nil {
  201. return nil, err
  202. }
  203. config.EnableOutboundNat = b
  204. case OutboundNatExceptions:
  205. s := strings.Split(value, ",")
  206. config.OutboundNatExceptions = s
  207. }
  208. }
  209. config.ID = id
  210. config.Type = d.name
  211. return config, nil
  212. }
  213. func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
  214. if len(ipamV6Data) > 0 {
  215. return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
  216. }
  217. if len(ipamV4Data) == 0 {
  218. return types.InvalidParameterErrorf("network %s requires ipv4 configuration", id)
  219. }
  220. return nil
  221. }
  222. func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
  223. }
  224. func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
  225. return "", nil
  226. }
  227. func (d *driver) createNetwork(config *networkConfiguration) *hnsNetwork {
  228. network := &hnsNetwork{
  229. id: config.ID,
  230. endpoints: make(map[string]*hnsEndpoint),
  231. config: config,
  232. driver: d,
  233. portMapper: portmapper.New(),
  234. }
  235. d.Lock()
  236. d.networks[config.ID] = network
  237. d.Unlock()
  238. return network
  239. }
  240. // Create a new network
  241. func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
  242. if _, err := d.getNetwork(id); err == nil {
  243. return types.ForbiddenErrorf("network %s exists", id)
  244. }
  245. genData, ok := option[netlabel.GenericData].(map[string]string)
  246. if !ok {
  247. return fmt.Errorf("Unknown generic data option")
  248. }
  249. // Parse and validate the config. It should not conflict with existing networks' config
  250. config, err := d.parseNetworkOptions(id, genData)
  251. if err != nil {
  252. return err
  253. }
  254. err = config.processIPAM(id, ipV4Data, ipV6Data)
  255. if err != nil {
  256. return err
  257. }
  258. n := d.createNetwork(config)
  259. // A non blank hnsid indicates that the network was discovered
  260. // from HNS. No need to call HNS if this network was discovered
  261. // from HNS
  262. if config.HnsID == "" {
  263. subnets := []hcsshim.Subnet{}
  264. for _, ipData := range ipV4Data {
  265. subnet := hcsshim.Subnet{
  266. AddressPrefix: ipData.Pool.String(),
  267. }
  268. if ipData.Gateway != nil {
  269. subnet.GatewayAddress = ipData.Gateway.IP.String()
  270. }
  271. subnets = append(subnets, subnet)
  272. }
  273. network := &hcsshim.HNSNetwork{
  274. Name: config.Name,
  275. Type: d.name,
  276. Subnets: subnets,
  277. DNSServerList: config.DNSServers,
  278. DNSSuffix: config.DNSSuffix,
  279. MacPools: config.MacPools,
  280. SourceMac: config.SourceMac,
  281. NetworkAdapterName: config.NetworkAdapterName,
  282. }
  283. if config.VLAN != 0 {
  284. vlanPolicy, err := json.Marshal(hcsshim.VlanPolicy{
  285. Type: "VLAN",
  286. VLAN: config.VLAN,
  287. })
  288. if err != nil {
  289. return err
  290. }
  291. network.Policies = append(network.Policies, vlanPolicy)
  292. }
  293. if config.VSID != 0 {
  294. vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
  295. Type: "VSID",
  296. VSID: config.VSID,
  297. })
  298. if err != nil {
  299. return err
  300. }
  301. network.Policies = append(network.Policies, vsidPolicy)
  302. }
  303. if network.Name == "" {
  304. network.Name = id
  305. }
  306. configurationb, err := json.Marshal(network)
  307. if err != nil {
  308. return err
  309. }
  310. configuration := string(configurationb)
  311. log.G(context.TODO()).Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
  312. hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
  313. if err != nil {
  314. return err
  315. }
  316. config.HnsID = hnsresponse.Id
  317. genData[HNSID] = config.HnsID
  318. n.created = true
  319. defer func() {
  320. if err != nil {
  321. d.DeleteNetwork(n.id)
  322. }
  323. }()
  324. hnsIPv4Data := make([]driverapi.IPAMData, len(hnsresponse.Subnets))
  325. for i, subnet := range hnsresponse.Subnets {
  326. var gwIP, subnetIP *net.IPNet
  327. // The gateway returned from HNS is an IPAddress.
  328. // We need to convert it to an IPNet to use as the Gateway of driverapi.IPAMData struct
  329. gwCIDR := subnet.GatewayAddress + "/32"
  330. _, gwIP, err = net.ParseCIDR(gwCIDR)
  331. if err != nil {
  332. return err
  333. }
  334. hnsIPv4Data[i].Gateway = gwIP
  335. _, subnetIP, err = net.ParseCIDR(subnet.AddressPrefix)
  336. if err != nil {
  337. return err
  338. }
  339. hnsIPv4Data[i].Pool = subnetIP
  340. }
  341. nInfo.UpdateIpamConfig(hnsIPv4Data)
  342. } else {
  343. // Delete any stale HNS endpoints for this network.
  344. if endpoints, err := hcsshim.HNSListEndpointRequest(); err == nil {
  345. for _, ep := range endpoints {
  346. if ep.VirtualNetwork == config.HnsID {
  347. log.G(context.TODO()).Infof("Removing stale HNS endpoint %s", ep.Id)
  348. _, err = hcsshim.HNSEndpointRequest("DELETE", ep.Id, "")
  349. if err != nil {
  350. log.G(context.TODO()).Warnf("Error removing HNS endpoint %s", ep.Id)
  351. }
  352. }
  353. }
  354. } else {
  355. log.G(context.TODO()).Warnf("Error listing HNS endpoints for network %s", config.HnsID)
  356. }
  357. n.created = true
  358. }
  359. return d.storeUpdate(config)
  360. }
  361. func (d *driver) DeleteNetwork(nid string) error {
  362. n, err := d.getNetwork(nid)
  363. if err != nil {
  364. return types.InternalMaskableErrorf("%s", err)
  365. }
  366. n.Lock()
  367. config := n.config
  368. n.Unlock()
  369. if n.created {
  370. _, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
  371. if err != nil && err.Error() != errNotFound {
  372. return types.ForbiddenErrorf(err.Error())
  373. }
  374. }
  375. d.Lock()
  376. delete(d.networks, nid)
  377. d.Unlock()
  378. // delele endpoints belong to this network
  379. for _, ep := range n.endpoints {
  380. if err := d.storeDelete(ep); err != nil {
  381. log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
  382. }
  383. }
  384. return d.storeDelete(config)
  385. }
  386. func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error) {
  387. var qps []json.RawMessage
  388. // Enumerate through the qos policies specified by the user and convert
  389. // them into the internal structure matching the JSON blob that can be
  390. // understood by the HCS.
  391. for _, elem := range qosPolicies {
  392. encodedPolicy, err := json.Marshal(hcsshim.QosPolicy{
  393. Type: "QOS",
  394. MaximumOutgoingBandwidthInBytes: elem.MaxEgressBandwidth,
  395. })
  396. if err != nil {
  397. return nil, err
  398. }
  399. qps = append(qps, encodedPolicy)
  400. }
  401. return qps, nil
  402. }
  403. // ConvertPortBindings converts PortBindings to JSON for HNS request
  404. func ConvertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
  405. var pbs []json.RawMessage
  406. // Enumerate through the port bindings specified by the user and convert
  407. // them into the internal structure matching the JSON blob that can be
  408. // understood by the HCS.
  409. for _, elem := range portBindings {
  410. proto := strings.ToUpper(elem.Proto.String())
  411. if proto != "TCP" && proto != "UDP" {
  412. return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
  413. }
  414. if elem.HostPort != elem.HostPortEnd {
  415. return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
  416. }
  417. if len(elem.HostIP) != 0 && !elem.HostIP.IsUnspecified() {
  418. return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
  419. }
  420. encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
  421. Type: "NAT",
  422. ExternalPort: elem.HostPort,
  423. InternalPort: elem.Port,
  424. Protocol: elem.Proto.String(),
  425. ExternalPortReserved: true,
  426. })
  427. if err != nil {
  428. return nil, err
  429. }
  430. pbs = append(pbs, encodedPolicy)
  431. }
  432. return pbs, nil
  433. }
  434. // ParsePortBindingPolicies parses HNS endpoint response message to PortBindings
  435. func ParsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
  436. var bindings []types.PortBinding
  437. hcsPolicy := &hcsshim.NatPolicy{}
  438. for _, elem := range policies {
  439. if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
  440. continue
  441. }
  442. binding := types.PortBinding{
  443. HostPort: hcsPolicy.ExternalPort,
  444. HostPortEnd: hcsPolicy.ExternalPort,
  445. Port: hcsPolicy.InternalPort,
  446. Proto: types.ParseProtocol(hcsPolicy.Protocol),
  447. HostIP: net.IPv4(0, 0, 0, 0),
  448. }
  449. bindings = append(bindings, binding)
  450. }
  451. return bindings, nil
  452. }
  453. func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
  454. if epOptions == nil {
  455. return nil, nil
  456. }
  457. ec := &endpointOption{}
  458. if opt, ok := epOptions[netlabel.MacAddress]; ok {
  459. if mac, ok := opt.(net.HardwareAddr); ok {
  460. ec.MacAddress = mac
  461. } else {
  462. return nil, fmt.Errorf("Invalid endpoint configuration")
  463. }
  464. }
  465. if opt, ok := epOptions[QosPolicies]; ok {
  466. if policies, ok := opt.([]types.QosPolicy); ok {
  467. ec.QosPolicies = policies
  468. } else {
  469. return nil, fmt.Errorf("Invalid endpoint configuration")
  470. }
  471. }
  472. if opt, ok := epOptions[netlabel.DNSServers]; ok {
  473. if dns, ok := opt.([]string); ok {
  474. ec.DNSServers = dns
  475. } else {
  476. return nil, fmt.Errorf("Invalid endpoint configuration")
  477. }
  478. }
  479. if opt, ok := epOptions[DisableICC]; ok {
  480. if disableICC, ok := opt.(bool); ok {
  481. ec.DisableICC = disableICC
  482. } else {
  483. return nil, fmt.Errorf("Invalid endpoint configuration")
  484. }
  485. }
  486. if opt, ok := epOptions[DisableDNS]; ok {
  487. if disableDNS, ok := opt.(bool); ok {
  488. ec.DisableDNS = disableDNS
  489. } else {
  490. return nil, fmt.Errorf("Invalid endpoint configuration")
  491. }
  492. }
  493. return ec, nil
  494. }
  495. // ParseEndpointConnectivity parses options passed to CreateEndpoint, specifically port bindings, and store in a endpointConnectivity object.
  496. func ParseEndpointConnectivity(epOptions map[string]interface{}) (*EndpointConnectivity, error) {
  497. if epOptions == nil {
  498. return nil, nil
  499. }
  500. ec := &EndpointConnectivity{}
  501. if opt, ok := epOptions[netlabel.PortMap]; ok {
  502. if bs, ok := opt.([]types.PortBinding); ok {
  503. ec.PortBindings = bs
  504. } else {
  505. return nil, fmt.Errorf("Invalid endpoint configuration")
  506. }
  507. }
  508. if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
  509. if ports, ok := opt.([]types.TransportPort); ok {
  510. ec.ExposedPorts = ports
  511. } else {
  512. return nil, fmt.Errorf("Invalid endpoint configuration")
  513. }
  514. }
  515. return ec, nil
  516. }
  517. func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
  518. n, err := d.getNetwork(nid)
  519. if err != nil {
  520. return err
  521. }
  522. // Check if endpoint id is good and retrieve corresponding endpoint
  523. ep, err := n.getEndpoint(eid)
  524. if err == nil && ep != nil {
  525. return driverapi.ErrEndpointExists(eid)
  526. }
  527. endpointStruct := &hcsshim.HNSEndpoint{
  528. VirtualNetwork: n.config.HnsID,
  529. }
  530. epOption, err := parseEndpointOptions(epOptions)
  531. if err != nil {
  532. return err
  533. }
  534. epConnectivity, err := ParseEndpointConnectivity(epOptions)
  535. if err != nil {
  536. return err
  537. }
  538. macAddress := ifInfo.MacAddress()
  539. // Use the macaddress if it was provided
  540. if macAddress != nil {
  541. endpointStruct.MacAddress = strings.ReplaceAll(macAddress.String(), ":", "-")
  542. }
  543. portMapping := epConnectivity.PortBindings
  544. if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
  545. ip := net.IPv4(0, 0, 0, 0)
  546. if ifInfo.Address() != nil {
  547. ip = ifInfo.Address().IP
  548. }
  549. portMapping, err = AllocatePorts(n.portMapper, portMapping, ip)
  550. if err != nil {
  551. return err
  552. }
  553. defer func() {
  554. if err != nil {
  555. ReleasePorts(n.portMapper, portMapping)
  556. }
  557. }()
  558. }
  559. endpointStruct.Policies, err = ConvertPortBindings(portMapping)
  560. if err != nil {
  561. return err
  562. }
  563. qosPolicies, err := convertQosPolicies(epOption.QosPolicies)
  564. if err != nil {
  565. return err
  566. }
  567. endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...)
  568. if ifInfo.Address() != nil {
  569. endpointStruct.IPAddress = ifInfo.Address().IP
  570. }
  571. endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
  572. // overwrite the ep DisableDNS option if DisableGatewayDNS was set to true during the network creation option
  573. if n.config.DisableGatewayDNS {
  574. log.G(context.TODO()).Debugf("n.config.DisableGatewayDNS[%v] overwrites epOption.DisableDNS[%v]", n.config.DisableGatewayDNS, epOption.DisableDNS)
  575. epOption.DisableDNS = n.config.DisableGatewayDNS
  576. }
  577. if n.driver.name == "nat" && !epOption.DisableDNS {
  578. endpointStruct.EnableInternalDNS = true
  579. log.G(context.TODO()).Debugf("endpointStruct.EnableInternalDNS =[%v]", endpointStruct.EnableInternalDNS)
  580. }
  581. endpointStruct.DisableICC = epOption.DisableICC
  582. // Inherit OutboundNat policy from the network
  583. if n.config.EnableOutboundNat {
  584. outboundNatPolicy, err := json.Marshal(hcsshim.OutboundNatPolicy{
  585. Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
  586. Exceptions: n.config.OutboundNatExceptions,
  587. })
  588. if err != nil {
  589. return err
  590. }
  591. endpointStruct.Policies = append(endpointStruct.Policies, outboundNatPolicy)
  592. }
  593. configurationb, err := json.Marshal(endpointStruct)
  594. if err != nil {
  595. return err
  596. }
  597. hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
  598. if err != nil {
  599. return err
  600. }
  601. mac, err := net.ParseMAC(hnsresponse.MacAddress)
  602. if err != nil {
  603. return err
  604. }
  605. // TODO For now the ip mask is not in the info generated by HNS
  606. endpoint := &hnsEndpoint{
  607. id: eid,
  608. nid: n.id,
  609. Type: d.name,
  610. addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
  611. macAddress: mac,
  612. }
  613. if hnsresponse.GatewayAddress != "" {
  614. endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress)
  615. }
  616. endpoint.profileID = hnsresponse.Id
  617. endpoint.epConnectivity = epConnectivity
  618. endpoint.epOption = epOption
  619. endpoint.portMapping, err = ParsePortBindingPolicies(hnsresponse.Policies)
  620. if err != nil {
  621. hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
  622. return err
  623. }
  624. n.Lock()
  625. n.endpoints[eid] = endpoint
  626. n.Unlock()
  627. if ifInfo.Address() == nil {
  628. ifInfo.SetIPAddress(endpoint.addr)
  629. }
  630. if macAddress == nil {
  631. ifInfo.SetMacAddress(endpoint.macAddress)
  632. }
  633. if err = d.storeUpdate(endpoint); err != nil {
  634. log.G(context.TODO()).Errorf("Failed to save endpoint %.7s to store: %v", endpoint.id, err)
  635. }
  636. return nil
  637. }
  638. func (d *driver) DeleteEndpoint(nid, eid string) error {
  639. n, err := d.getNetwork(nid)
  640. if err != nil {
  641. return types.InternalMaskableErrorf("%s", err)
  642. }
  643. ep, err := n.getEndpoint(eid)
  644. if err != nil {
  645. return err
  646. }
  647. if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
  648. ReleasePorts(n.portMapper, ep.portMapping)
  649. }
  650. n.Lock()
  651. delete(n.endpoints, eid)
  652. n.Unlock()
  653. _, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
  654. if err != nil && err.Error() != errNotFound {
  655. return err
  656. }
  657. if err := d.storeDelete(ep); err != nil {
  658. log.G(context.TODO()).Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
  659. }
  660. return nil
  661. }
  662. func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
  663. network, err := d.getNetwork(nid)
  664. if err != nil {
  665. return nil, err
  666. }
  667. ep, err := network.getEndpoint(eid)
  668. if err != nil {
  669. return nil, err
  670. }
  671. data := make(map[string]interface{}, 1)
  672. if network.driver.name == "nat" {
  673. data["AllowUnqualifiedDNSQuery"] = true
  674. }
  675. data["hnsid"] = ep.profileID
  676. if ep.epConnectivity.ExposedPorts != nil {
  677. // Return a copy of the config data
  678. epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts))
  679. for _, tp := range ep.epConnectivity.ExposedPorts {
  680. epc = append(epc, tp.GetCopy())
  681. }
  682. data[netlabel.ExposedPorts] = epc
  683. }
  684. if ep.portMapping != nil {
  685. // Return a copy of the operational data
  686. pmc := make([]types.PortBinding, 0, len(ep.portMapping))
  687. for _, pm := range ep.portMapping {
  688. pmc = append(pmc, pm.GetCopy())
  689. }
  690. data[netlabel.PortMap] = pmc
  691. }
  692. if len(ep.macAddress) != 0 {
  693. data[netlabel.MacAddress] = ep.macAddress
  694. }
  695. return data, nil
  696. }
  697. // Join method is invoked when a Sandbox is attached to an endpoint.
  698. func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
  699. network, err := d.getNetwork(nid)
  700. if err != nil {
  701. return err
  702. }
  703. // Ensure that the endpoint exists
  704. endpoint, err := network.getEndpoint(eid)
  705. if err != nil {
  706. return err
  707. }
  708. err = jinfo.SetGateway(endpoint.gateway)
  709. if err != nil {
  710. return err
  711. }
  712. endpoint.sandboxID = sboxKey
  713. err = hcsshim.HotAttachEndpoint(endpoint.sandboxID, endpoint.profileID)
  714. if err != nil {
  715. // If container doesn't exists in hcs, do not throw error for hot add/remove
  716. if err != hcsshim.ErrComputeSystemDoesNotExist {
  717. return err
  718. }
  719. }
  720. jinfo.DisableGatewayService()
  721. return nil
  722. }
  723. // Leave method is invoked when a Sandbox detaches from an endpoint.
  724. func (d *driver) Leave(nid, eid string) error {
  725. network, err := d.getNetwork(nid)
  726. if err != nil {
  727. return types.InternalMaskableErrorf("%s", err)
  728. }
  729. // Ensure that the endpoint exists
  730. endpoint, err := network.getEndpoint(eid)
  731. if err != nil {
  732. return err
  733. }
  734. err = hcsshim.HotDetachEndpoint(endpoint.sandboxID, endpoint.profileID)
  735. if err != nil {
  736. // If container doesn't exists in hcs, do not throw error for hot add/remove
  737. if err != hcsshim.ErrComputeSystemDoesNotExist {
  738. return err
  739. }
  740. }
  741. return nil
  742. }
  743. func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
  744. return nil
  745. }
  746. func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
  747. return nil
  748. }
  749. func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
  750. return nil, types.NotImplementedErrorf("not implemented")
  751. }
  752. func (d *driver) NetworkFree(id string) error {
  753. return types.NotImplementedErrorf("not implemented")
  754. }
  755. func (d *driver) Type() string {
  756. return d.name
  757. }
  758. func (d *driver) IsBuiltIn() bool {
  759. return true
  760. }