github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/endpoint_info.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 8 "github.com/docker/libnetwork/driverapi" 9 "github.com/docker/libnetwork/types" 10 ) 11 12 // EndpointInfo provides an interface to retrieve network resources bound to the endpoint. 13 type EndpointInfo interface { 14 // Iface returns InterfaceInfo, go interface that can be used 15 // to get more information on the interface which was assigned to 16 // the endpoint by the driver. This can be used after the 17 // endpoint has been created. 18 Iface() InterfaceInfo 19 20 // Gateway returns the IPv4 gateway assigned by the driver. 21 // This will only return a valid value if a container has joined the endpoint. 22 Gateway() net.IP 23 24 // GatewayIPv6 returns the IPv6 gateway assigned by the driver. 25 // This will only return a valid value if a container has joined the endpoint. 26 GatewayIPv6() net.IP 27 28 // StaticRoutes returns the list of static routes configured by the network 29 // driver when the container joins a network 30 StaticRoutes() []*types.StaticRoute 31 32 // Sandbox returns the attached sandbox if there, nil otherwise. 33 Sandbox() Sandbox 34 35 // LoadBalancer returns whether the endpoint is the load balancer endpoint for the network. 36 LoadBalancer() bool 37 } 38 39 // InterfaceInfo provides an interface to retrieve interface addresses bound to the endpoint. 40 type InterfaceInfo interface { 41 // MacAddress returns the MAC address assigned to the endpoint. 42 MacAddress() net.HardwareAddr 43 44 // Address returns the IPv4 address assigned to the endpoint. 45 Address() *net.IPNet 46 47 // AddressIPv6 returns the IPv6 address assigned to the endpoint. 48 AddressIPv6() *net.IPNet 49 50 // LinkLocalAddresses returns the list of link-local (IPv4/IPv6) addresses assigned to the endpoint. 51 LinkLocalAddresses() []*net.IPNet 52 53 // SrcName returns the name of the interface w/in the container 54 SrcName() string 55 } 56 57 type endpointInterface struct { 58 mac net.HardwareAddr 59 addr *net.IPNet 60 addrv6 *net.IPNet 61 llAddrs []*net.IPNet 62 srcName string 63 dstPrefix string 64 routes []*net.IPNet 65 v4PoolID string 66 v6PoolID string 67 } 68 69 func (epi *endpointInterface) MarshalJSON() ([]byte, error) { 70 epMap := make(map[string]interface{}) 71 if epi.mac != nil { 72 epMap["mac"] = epi.mac.String() 73 } 74 if epi.addr != nil { 75 epMap["addr"] = epi.addr.String() 76 } 77 if epi.addrv6 != nil { 78 epMap["addrv6"] = epi.addrv6.String() 79 } 80 if len(epi.llAddrs) != 0 { 81 list := make([]string, 0, len(epi.llAddrs)) 82 for _, ll := range epi.llAddrs { 83 list = append(list, ll.String()) 84 } 85 epMap["llAddrs"] = list 86 } 87 epMap["srcName"] = epi.srcName 88 epMap["dstPrefix"] = epi.dstPrefix 89 var routes []string 90 for _, route := range epi.routes { 91 routes = append(routes, route.String()) 92 } 93 epMap["routes"] = routes 94 epMap["v4PoolID"] = epi.v4PoolID 95 epMap["v6PoolID"] = epi.v6PoolID 96 return json.Marshal(epMap) 97 } 98 99 func (epi *endpointInterface) UnmarshalJSON(b []byte) error { 100 var ( 101 err error 102 epMap map[string]interface{} 103 ) 104 if err = json.Unmarshal(b, &epMap); err != nil { 105 return err 106 } 107 if v, ok := epMap["mac"]; ok { 108 if epi.mac, err = net.ParseMAC(v.(string)); err != nil { 109 return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string)) 110 } 111 } 112 if v, ok := epMap["addr"]; ok { 113 if epi.addr, err = types.ParseCIDR(v.(string)); err != nil { 114 return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err) 115 } 116 } 117 if v, ok := epMap["addrv6"]; ok { 118 if epi.addrv6, err = types.ParseCIDR(v.(string)); err != nil { 119 return types.InternalErrorf("failed to decode endpoint interface ipv6 address after json unmarshal: %v", err) 120 } 121 } 122 if v, ok := epMap["llAddrs"]; ok { 123 list := v.([]interface{}) 124 epi.llAddrs = make([]*net.IPNet, 0, len(list)) 125 for _, llS := range list { 126 ll, err := types.ParseCIDR(llS.(string)) 127 if err != nil { 128 return types.InternalErrorf("failed to decode endpoint interface link-local address (%v) after json unmarshal: %v", llS, err) 129 } 130 epi.llAddrs = append(epi.llAddrs, ll) 131 } 132 } 133 epi.srcName = epMap["srcName"].(string) 134 epi.dstPrefix = epMap["dstPrefix"].(string) 135 136 rb, _ := json.Marshal(epMap["routes"]) 137 var routes []string 138 json.Unmarshal(rb, &routes) 139 epi.routes = make([]*net.IPNet, 0) 140 for _, route := range routes { 141 ip, ipr, err := net.ParseCIDR(route) 142 if err == nil { 143 ipr.IP = ip 144 epi.routes = append(epi.routes, ipr) 145 } 146 } 147 epi.v4PoolID = epMap["v4PoolID"].(string) 148 epi.v6PoolID = epMap["v6PoolID"].(string) 149 150 return nil 151 } 152 153 func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error { 154 dstEpi.mac = types.GetMacCopy(epi.mac) 155 dstEpi.addr = types.GetIPNetCopy(epi.addr) 156 dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6) 157 dstEpi.srcName = epi.srcName 158 dstEpi.dstPrefix = epi.dstPrefix 159 dstEpi.v4PoolID = epi.v4PoolID 160 dstEpi.v6PoolID = epi.v6PoolID 161 if len(epi.llAddrs) != 0 { 162 dstEpi.llAddrs = make([]*net.IPNet, 0, len(epi.llAddrs)) 163 dstEpi.llAddrs = append(dstEpi.llAddrs, epi.llAddrs...) 164 } 165 166 for _, route := range epi.routes { 167 dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route)) 168 } 169 170 return nil 171 } 172 173 type endpointJoinInfo struct { 174 gw net.IP 175 gw6 net.IP 176 StaticRoutes []*types.StaticRoute 177 driverTableEntries []*tableEntry 178 disableGatewayService bool 179 } 180 181 type tableEntry struct { 182 tableName string 183 key string 184 value []byte 185 } 186 187 func (ep *endpoint) Info() EndpointInfo { 188 if ep.sandboxID != "" { 189 return ep 190 } 191 n, err := ep.getNetworkFromStore() 192 if err != nil { 193 return nil 194 } 195 196 ep, err = n.getEndpointFromStore(ep.ID()) 197 if err != nil { 198 return nil 199 } 200 201 sb, ok := ep.getSandbox() 202 if !ok { 203 // endpoint hasn't joined any sandbox. 204 // Just return the endpoint 205 return ep 206 } 207 208 return sb.getEndpoint(ep.ID()) 209 } 210 211 func (ep *endpoint) Iface() InterfaceInfo { 212 ep.Lock() 213 defer ep.Unlock() 214 215 if ep.iface != nil { 216 return ep.iface 217 } 218 219 return nil 220 } 221 222 func (ep *endpoint) Interface() driverapi.InterfaceInfo { 223 ep.Lock() 224 defer ep.Unlock() 225 226 if ep.iface != nil { 227 return ep.iface 228 } 229 230 return nil 231 } 232 233 func (epi *endpointInterface) SetMacAddress(mac net.HardwareAddr) error { 234 if epi.mac != nil { 235 return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", epi.mac, mac) 236 } 237 if mac == nil { 238 return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface") 239 } 240 epi.mac = types.GetMacCopy(mac) 241 return nil 242 } 243 244 func (epi *endpointInterface) SetIPAddress(address *net.IPNet) error { 245 if address.IP == nil { 246 return types.BadRequestErrorf("tried to set nil IP address to endpoint interface") 247 } 248 if address.IP.To4() == nil { 249 return setAddress(&epi.addrv6, address) 250 } 251 return setAddress(&epi.addr, address) 252 } 253 254 func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error { 255 if *ifaceAddr != nil { 256 return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address) 257 } 258 *ifaceAddr = types.GetIPNetCopy(address) 259 return nil 260 } 261 262 func (epi *endpointInterface) MacAddress() net.HardwareAddr { 263 return types.GetMacCopy(epi.mac) 264 } 265 266 func (epi *endpointInterface) Address() *net.IPNet { 267 return types.GetIPNetCopy(epi.addr) 268 } 269 270 func (epi *endpointInterface) AddressIPv6() *net.IPNet { 271 return types.GetIPNetCopy(epi.addrv6) 272 } 273 274 func (epi *endpointInterface) LinkLocalAddresses() []*net.IPNet { 275 return epi.llAddrs 276 } 277 278 func (epi *endpointInterface) SrcName() string { 279 return epi.srcName 280 } 281 282 func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error { 283 epi.srcName = srcName 284 epi.dstPrefix = dstPrefix 285 return nil 286 } 287 288 func (ep *endpoint) InterfaceName() driverapi.InterfaceNameInfo { 289 ep.Lock() 290 defer ep.Unlock() 291 292 if ep.iface != nil { 293 return ep.iface 294 } 295 296 return nil 297 } 298 299 func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error { 300 ep.Lock() 301 defer ep.Unlock() 302 303 r := types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop} 304 305 if routeType == types.NEXTHOP { 306 // If the route specifies a next-hop, then it's loosely routed (i.e. not bound to a particular interface). 307 ep.joinInfo.StaticRoutes = append(ep.joinInfo.StaticRoutes, &r) 308 } else { 309 // If the route doesn't specify a next-hop, it must be a connected route, bound to an interface. 310 ep.iface.routes = append(ep.iface.routes, r.Destination) 311 } 312 return nil 313 } 314 315 func (ep *endpoint) AddTableEntry(tableName, key string, value []byte) error { 316 ep.Lock() 317 defer ep.Unlock() 318 319 ep.joinInfo.driverTableEntries = append(ep.joinInfo.driverTableEntries, &tableEntry{ 320 tableName: tableName, 321 key: key, 322 value: value, 323 }) 324 325 return nil 326 } 327 328 func (ep *endpoint) Sandbox() Sandbox { 329 cnt, ok := ep.getSandbox() 330 if !ok { 331 return nil 332 } 333 return cnt 334 } 335 336 func (ep *endpoint) LoadBalancer() bool { 337 ep.Lock() 338 defer ep.Unlock() 339 return ep.loadBalancer 340 } 341 342 func (ep *endpoint) StaticRoutes() []*types.StaticRoute { 343 ep.Lock() 344 defer ep.Unlock() 345 346 if ep.joinInfo == nil { 347 return nil 348 } 349 350 return ep.joinInfo.StaticRoutes 351 } 352 353 func (ep *endpoint) Gateway() net.IP { 354 ep.Lock() 355 defer ep.Unlock() 356 357 if ep.joinInfo == nil { 358 return net.IP{} 359 } 360 361 return types.GetIPCopy(ep.joinInfo.gw) 362 } 363 364 func (ep *endpoint) GatewayIPv6() net.IP { 365 ep.Lock() 366 defer ep.Unlock() 367 368 if ep.joinInfo == nil { 369 return net.IP{} 370 } 371 372 return types.GetIPCopy(ep.joinInfo.gw6) 373 } 374 375 func (ep *endpoint) SetGateway(gw net.IP) error { 376 ep.Lock() 377 defer ep.Unlock() 378 379 ep.joinInfo.gw = types.GetIPCopy(gw) 380 return nil 381 } 382 383 func (ep *endpoint) SetGatewayIPv6(gw6 net.IP) error { 384 ep.Lock() 385 defer ep.Unlock() 386 387 ep.joinInfo.gw6 = types.GetIPCopy(gw6) 388 return nil 389 } 390 391 func (ep *endpoint) retrieveFromStore() (*endpoint, error) { 392 n, err := ep.getNetworkFromStore() 393 if err != nil { 394 return nil, fmt.Errorf("could not find network in store to get latest endpoint %s: %v", ep.Name(), err) 395 } 396 return n.getEndpointFromStore(ep.ID()) 397 } 398 399 func (ep *endpoint) DisableGatewayService() { 400 ep.Lock() 401 defer ep.Unlock() 402 403 ep.joinInfo.disableGatewayService = true 404 } 405 406 func (epj *endpointJoinInfo) MarshalJSON() ([]byte, error) { 407 epMap := make(map[string]interface{}) 408 if epj.gw != nil { 409 epMap["gw"] = epj.gw.String() 410 } 411 if epj.gw6 != nil { 412 epMap["gw6"] = epj.gw6.String() 413 } 414 epMap["disableGatewayService"] = epj.disableGatewayService 415 epMap["StaticRoutes"] = epj.StaticRoutes 416 return json.Marshal(epMap) 417 } 418 419 func (epj *endpointJoinInfo) UnmarshalJSON(b []byte) error { 420 var ( 421 err error 422 epMap map[string]interface{} 423 ) 424 if err = json.Unmarshal(b, &epMap); err != nil { 425 return err 426 } 427 if v, ok := epMap["gw"]; ok { 428 epj.gw = net.ParseIP(v.(string)) 429 } 430 if v, ok := epMap["gw6"]; ok { 431 epj.gw6 = net.ParseIP(v.(string)) 432 } 433 epj.disableGatewayService = epMap["disableGatewayService"].(bool) 434 435 var tStaticRoute []types.StaticRoute 436 if v, ok := epMap["StaticRoutes"]; ok { 437 tb, _ := json.Marshal(v) 438 var tStaticRoute []types.StaticRoute 439 json.Unmarshal(tb, &tStaticRoute) 440 } 441 var StaticRoutes []*types.StaticRoute 442 for _, r := range tStaticRoute { 443 StaticRoutes = append(StaticRoutes, &r) 444 } 445 epj.StaticRoutes = StaticRoutes 446 447 return nil 448 } 449 450 func (epj *endpointJoinInfo) CopyTo(dstEpj *endpointJoinInfo) error { 451 dstEpj.disableGatewayService = epj.disableGatewayService 452 dstEpj.StaticRoutes = make([]*types.StaticRoute, len(epj.StaticRoutes)) 453 copy(dstEpj.StaticRoutes, epj.StaticRoutes) 454 dstEpj.driverTableEntries = make([]*tableEntry, len(epj.driverTableEntries)) 455 copy(dstEpj.driverTableEntries, epj.driverTableEntries) 456 dstEpj.gw = types.GetIPCopy(epj.gw) 457 dstEpj.gw6 = types.GetIPCopy(epj.gw6) 458 return nil 459 }