github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/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  }