123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- package osl
- import (
- "fmt"
- "net"
- "github.com/docker/docker/libnetwork/types"
- "github.com/vishvananda/netlink"
- )
- // Gateway returns the IPv4 gateway for the sandbox.
- func (n *Namespace) Gateway() net.IP {
- n.mu.Lock()
- defer n.mu.Unlock()
- return n.gw
- }
- // GatewayIPv6 returns the IPv6 gateway for the sandbox.
- func (n *Namespace) GatewayIPv6() net.IP {
- n.mu.Lock()
- defer n.mu.Unlock()
- return n.gwv6
- }
- // StaticRoutes returns additional static routes for the sandbox. Note that
- // directly connected routes are stored on the particular interface they
- // refer to.
- func (n *Namespace) StaticRoutes() []*types.StaticRoute {
- n.mu.Lock()
- defer n.mu.Unlock()
- routes := make([]*types.StaticRoute, len(n.staticRoutes))
- for i, route := range n.staticRoutes {
- r := route.GetCopy()
- routes[i] = r
- }
- return routes
- }
- // SetGateway sets the default IPv4 gateway for the sandbox. It is a no-op
- // if the given gateway is empty.
- func (n *Namespace) SetGateway(gw net.IP) error {
- if len(gw) == 0 {
- return nil
- }
- if err := n.programGateway(gw, true); err != nil {
- return err
- }
- n.mu.Lock()
- n.gw = gw
- n.mu.Unlock()
- return nil
- }
- // UnsetGateway the previously set default IPv4 gateway in the sandbox.
- // It is a no-op if no gateway was set.
- func (n *Namespace) UnsetGateway() error {
- gw := n.Gateway()
- if len(gw) == 0 {
- return nil
- }
- if err := n.programGateway(gw, false); err != nil {
- return err
- }
- n.mu.Lock()
- n.gw = net.IP{}
- n.mu.Unlock()
- return nil
- }
- func (n *Namespace) programGateway(gw net.IP, isAdd bool) error {
- gwRoutes, err := n.nlHandle.RouteGet(gw)
- if err != nil {
- return fmt.Errorf("route for the gateway %s could not be found: %v", gw, err)
- }
- var linkIndex int
- for _, gwRoute := range gwRoutes {
- if gwRoute.Gw == nil {
- linkIndex = gwRoute.LinkIndex
- break
- }
- }
- if linkIndex == 0 {
- return fmt.Errorf("direct route for the gateway %s could not be found", gw)
- }
- if isAdd {
- return n.nlHandle.RouteAdd(&netlink.Route{
- Scope: netlink.SCOPE_UNIVERSE,
- LinkIndex: linkIndex,
- Gw: gw,
- })
- }
- return n.nlHandle.RouteDel(&netlink.Route{
- Scope: netlink.SCOPE_UNIVERSE,
- LinkIndex: linkIndex,
- Gw: gw,
- })
- }
- // Program a route in to the namespace routing table.
- func (n *Namespace) programRoute(dest *net.IPNet, nh net.IP) error {
- gwRoutes, err := n.nlHandle.RouteGet(nh)
- if err != nil {
- return fmt.Errorf("route for the next hop %s could not be found: %v", nh, err)
- }
- return n.nlHandle.RouteAdd(&netlink.Route{
- Scope: netlink.SCOPE_UNIVERSE,
- LinkIndex: gwRoutes[0].LinkIndex,
- Gw: nh,
- Dst: dest,
- })
- }
- // Delete a route from the namespace routing table.
- func (n *Namespace) removeRoute(dest *net.IPNet, nh net.IP) error {
- gwRoutes, err := n.nlHandle.RouteGet(nh)
- if err != nil {
- return fmt.Errorf("route for the next hop could not be found: %v", err)
- }
- return n.nlHandle.RouteDel(&netlink.Route{
- Scope: netlink.SCOPE_UNIVERSE,
- LinkIndex: gwRoutes[0].LinkIndex,
- Gw: nh,
- Dst: dest,
- })
- }
- // SetGatewayIPv6 sets the default IPv6 gateway for the sandbox. It is a no-op
- // if the given gateway is empty.
- func (n *Namespace) SetGatewayIPv6(gwv6 net.IP) error {
- if len(gwv6) == 0 {
- return nil
- }
- if err := n.programGateway(gwv6, true); err != nil {
- return err
- }
- n.mu.Lock()
- n.gwv6 = gwv6
- n.mu.Unlock()
- return nil
- }
- // UnsetGatewayIPv6 unsets the previously set default IPv6 gateway in the sandbox.
- // It is a no-op if no gateway was set.
- func (n *Namespace) UnsetGatewayIPv6() error {
- gwv6 := n.GatewayIPv6()
- if len(gwv6) == 0 {
- return nil
- }
- if err := n.programGateway(gwv6, false); err != nil {
- return err
- }
- n.mu.Lock()
- n.gwv6 = net.IP{}
- n.mu.Unlock()
- return nil
- }
- // AddStaticRoute adds a static route to the sandbox.
- func (n *Namespace) AddStaticRoute(r *types.StaticRoute) error {
- if err := n.programRoute(r.Destination, r.NextHop); err != nil {
- return err
- }
- n.mu.Lock()
- n.staticRoutes = append(n.staticRoutes, r)
- n.mu.Unlock()
- return nil
- }
- // RemoveStaticRoute removes a static route from the sandbox.
- func (n *Namespace) RemoveStaticRoute(r *types.StaticRoute) error {
- if err := n.removeRoute(r.Destination, r.NextHop); err != nil {
- return err
- }
- n.mu.Lock()
- lastIndex := len(n.staticRoutes) - 1
- for i, v := range n.staticRoutes {
- if v == r {
- // Overwrite the route we're removing with the last element
- n.staticRoutes[i] = n.staticRoutes[lastIndex]
- // Shorten the slice to trim the extra element
- n.staticRoutes = n.staticRoutes[:lastIndex]
- break
- }
- }
- n.mu.Unlock()
- return nil
- }
|