github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drivers/windows/overlay/ov_network_windows.go (about) 1 package overlay 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "strconv" 8 "strings" 9 "sync" 10 11 "github.com/Microsoft/hcsshim" 12 "github.com/docker/libnetwork/driverapi" 13 "github.com/docker/libnetwork/netlabel" 14 "github.com/docker/libnetwork/portmapper" 15 "github.com/docker/libnetwork/types" 16 "github.com/sirupsen/logrus" 17 ) 18 19 var ( 20 hostMode bool 21 networkMu sync.Mutex 22 ) 23 24 type networkTable map[string]*network 25 26 type subnet struct { 27 vni uint32 28 subnetIP *net.IPNet 29 gwIP *net.IP 30 } 31 32 type subnetJSON struct { 33 SubnetIP string 34 GwIP string 35 Vni uint32 36 } 37 38 type network struct { 39 id string 40 name string 41 hnsID string 42 providerAddress string 43 interfaceName string 44 endpoints endpointTable 45 driver *driver 46 initEpoch int 47 initErr error 48 subnets []*subnet 49 secure bool 50 portMapper *portmapper.PortMapper 51 sync.Mutex 52 } 53 54 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 55 return nil, types.NotImplementedErrorf("not implemented") 56 } 57 58 func (d *driver) NetworkFree(id string) error { 59 return types.NotImplementedErrorf("not implemented") 60 } 61 62 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 63 var ( 64 networkName string 65 interfaceName string 66 staleNetworks []string 67 ) 68 69 if id == "" { 70 return fmt.Errorf("invalid network id") 71 } 72 73 if nInfo == nil { 74 return fmt.Errorf("invalid network info structure") 75 } 76 77 if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" { 78 return types.BadRequestErrorf("ipv4 pool is empty") 79 } 80 81 staleNetworks = make([]string, 0) 82 vnis := make([]uint32, 0, len(ipV4Data)) 83 84 existingNetwork := d.network(id) 85 if existingNetwork != nil { 86 logrus.Debugf("Network preexists. Deleting %s", id) 87 err := d.DeleteNetwork(id) 88 if err != nil { 89 logrus.Errorf("Error deleting stale network %s", err.Error()) 90 } 91 } 92 93 n := &network{ 94 id: id, 95 driver: d, 96 endpoints: endpointTable{}, 97 subnets: []*subnet{}, 98 portMapper: portmapper.New(""), 99 } 100 101 genData, ok := option[netlabel.GenericData].(map[string]string) 102 103 if !ok { 104 return fmt.Errorf("Unknown generic data option") 105 } 106 107 for label, value := range genData { 108 switch label { 109 case "com.docker.network.windowsshim.networkname": 110 networkName = value 111 case "com.docker.network.windowsshim.interface": 112 interfaceName = value 113 case "com.docker.network.windowsshim.hnsid": 114 n.hnsID = value 115 case netlabel.OverlayVxlanIDList: 116 vniStrings := strings.Split(value, ",") 117 for _, vniStr := range vniStrings { 118 vni, err := strconv.Atoi(vniStr) 119 if err != nil { 120 return fmt.Errorf("invalid vxlan id value %q passed", vniStr) 121 } 122 123 vnis = append(vnis, uint32(vni)) 124 } 125 } 126 } 127 128 // If we are getting vnis from libnetwork, either we get for 129 // all subnets or none. 130 if len(vnis) < len(ipV4Data) { 131 return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis)) 132 } 133 134 for i, ipd := range ipV4Data { 135 s := &subnet{ 136 subnetIP: ipd.Pool, 137 gwIP: &ipd.Gateway.IP, 138 } 139 140 if len(vnis) != 0 { 141 s.vni = vnis[i] 142 } 143 144 d.Lock() 145 for _, network := range d.networks { 146 found := false 147 for _, sub := range network.subnets { 148 if sub.vni == s.vni { 149 staleNetworks = append(staleNetworks, network.id) 150 found = true 151 break 152 } 153 } 154 if found { 155 break 156 } 157 } 158 d.Unlock() 159 160 n.subnets = append(n.subnets, s) 161 } 162 163 for _, staleNetwork := range staleNetworks { 164 d.DeleteNetwork(staleNetwork) 165 } 166 167 n.name = networkName 168 if n.name == "" { 169 n.name = id 170 } 171 172 n.interfaceName = interfaceName 173 174 if nInfo != nil { 175 if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil { 176 return err 177 } 178 } 179 180 d.addNetwork(n) 181 182 err := d.createHnsNetwork(n) 183 184 if err != nil { 185 d.deleteNetwork(id) 186 } else { 187 genData["com.docker.network.windowsshim.hnsid"] = n.hnsID 188 } 189 190 return err 191 } 192 193 func (d *driver) DeleteNetwork(nid string) error { 194 if nid == "" { 195 return fmt.Errorf("invalid network id") 196 } 197 198 n := d.network(nid) 199 if n == nil { 200 return types.ForbiddenErrorf("could not find network with id %s", nid) 201 } 202 203 _, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "") 204 if err != nil { 205 return types.ForbiddenErrorf(err.Error()) 206 } 207 208 d.deleteNetwork(nid) 209 210 return nil 211 } 212 213 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 214 return nil 215 } 216 217 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 218 return nil 219 } 220 221 func (d *driver) addNetwork(n *network) { 222 d.Lock() 223 d.networks[n.id] = n 224 d.Unlock() 225 } 226 227 func (d *driver) deleteNetwork(nid string) { 228 d.Lock() 229 delete(d.networks, nid) 230 d.Unlock() 231 } 232 233 func (d *driver) network(nid string) *network { 234 d.Lock() 235 defer d.Unlock() 236 return d.networks[nid] 237 } 238 239 // func (n *network) restoreNetworkEndpoints() error { 240 // logrus.Infof("Restoring endpoints for overlay network: %s", n.id) 241 242 // hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "") 243 // if err != nil { 244 // return err 245 // } 246 247 // for _, endpoint := range hnsresponse { 248 // if endpoint.VirtualNetwork != n.hnsID { 249 // continue 250 // } 251 252 // ep := n.convertToOverlayEndpoint(&endpoint) 253 254 // if ep != nil { 255 // logrus.Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote) 256 // n.addEndpoint(ep) 257 // } 258 // } 259 260 // return nil 261 // } 262 263 func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint { 264 ep := &endpoint{ 265 id: v.Name, 266 profileID: v.Id, 267 nid: n.id, 268 remote: v.IsRemoteEndpoint, 269 } 270 271 mac, err := net.ParseMAC(v.MacAddress) 272 273 if err != nil { 274 return nil 275 } 276 277 ep.mac = mac 278 ep.addr = &net.IPNet{ 279 IP: v.IPAddress, 280 Mask: net.CIDRMask(32, 32), 281 } 282 283 return ep 284 } 285 286 func (d *driver) createHnsNetwork(n *network) error { 287 288 subnets := []hcsshim.Subnet{} 289 290 for _, s := range n.subnets { 291 subnet := hcsshim.Subnet{ 292 AddressPrefix: s.subnetIP.String(), 293 } 294 295 if s.gwIP != nil { 296 subnet.GatewayAddress = s.gwIP.String() 297 } 298 299 vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{ 300 Type: "VSID", 301 VSID: uint(s.vni), 302 }) 303 304 if err != nil { 305 return err 306 } 307 308 subnet.Policies = append(subnet.Policies, vsidPolicy) 309 subnets = append(subnets, subnet) 310 } 311 312 network := &hcsshim.HNSNetwork{ 313 Name: n.name, 314 Type: d.Type(), 315 Subnets: subnets, 316 NetworkAdapterName: n.interfaceName, 317 AutomaticDNS: true, 318 } 319 320 configurationb, err := json.Marshal(network) 321 if err != nil { 322 return err 323 } 324 325 configuration := string(configurationb) 326 logrus.Infof("HNSNetwork Request =%v", configuration) 327 328 hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration) 329 if err != nil { 330 return err 331 } 332 333 n.hnsID = hnsresponse.Id 334 n.providerAddress = hnsresponse.ManagementIP 335 336 return nil 337 } 338 339 // contains return true if the passed ip belongs to one the network's 340 // subnets 341 func (n *network) contains(ip net.IP) bool { 342 for _, s := range n.subnets { 343 if s.subnetIP.Contains(ip) { 344 return true 345 } 346 } 347 348 return false 349 } 350 351 // getSubnetforIP returns the subnet to which the given IP belongs 352 func (n *network) getSubnetforIP(ip *net.IPNet) *subnet { 353 for _, s := range n.subnets { 354 // first check if the mask lengths are the same 355 i, _ := s.subnetIP.Mask.Size() 356 j, _ := ip.Mask.Size() 357 if i != j { 358 continue 359 } 360 if s.subnetIP.Contains(ip.IP) { 361 return s 362 } 363 } 364 return nil 365 } 366 367 // getMatchingSubnet return the network's subnet that matches the input 368 func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet { 369 if ip == nil { 370 return nil 371 } 372 for _, s := range n.subnets { 373 // first check if the mask lengths are the same 374 i, _ := s.subnetIP.Mask.Size() 375 j, _ := ip.Mask.Size() 376 if i != j { 377 continue 378 } 379 if s.subnetIP.IP.Equal(ip.IP) { 380 return s 381 } 382 } 383 return nil 384 }