route_linux.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package osl
  2. import (
  3. "fmt"
  4. "net"
  5. "github.com/docker/docker/libnetwork/types"
  6. "github.com/vishvananda/netlink"
  7. )
  8. // Gateway returns the IPv4 gateway for the sandbox.
  9. func (n *Namespace) Gateway() net.IP {
  10. n.mu.Lock()
  11. defer n.mu.Unlock()
  12. return n.gw
  13. }
  14. // GatewayIPv6 returns the IPv6 gateway for the sandbox.
  15. func (n *Namespace) GatewayIPv6() net.IP {
  16. n.mu.Lock()
  17. defer n.mu.Unlock()
  18. return n.gwv6
  19. }
  20. // StaticRoutes returns additional static routes for the sandbox. Note that
  21. // directly connected routes are stored on the particular interface they
  22. // refer to.
  23. func (n *Namespace) StaticRoutes() []*types.StaticRoute {
  24. n.mu.Lock()
  25. defer n.mu.Unlock()
  26. routes := make([]*types.StaticRoute, len(n.staticRoutes))
  27. for i, route := range n.staticRoutes {
  28. r := route.GetCopy()
  29. routes[i] = r
  30. }
  31. return routes
  32. }
  33. // SetGateway sets the default IPv4 gateway for the sandbox. It is a no-op
  34. // if the given gateway is empty.
  35. func (n *Namespace) SetGateway(gw net.IP) error {
  36. if len(gw) == 0 {
  37. return nil
  38. }
  39. if err := n.programGateway(gw, true); err != nil {
  40. return err
  41. }
  42. n.mu.Lock()
  43. n.gw = gw
  44. n.mu.Unlock()
  45. return nil
  46. }
  47. // UnsetGateway the previously set default IPv4 gateway in the sandbox.
  48. // It is a no-op if no gateway was set.
  49. func (n *Namespace) UnsetGateway() error {
  50. gw := n.Gateway()
  51. if len(gw) == 0 {
  52. return nil
  53. }
  54. if err := n.programGateway(gw, false); err != nil {
  55. return err
  56. }
  57. n.mu.Lock()
  58. n.gw = net.IP{}
  59. n.mu.Unlock()
  60. return nil
  61. }
  62. func (n *Namespace) programGateway(gw net.IP, isAdd bool) error {
  63. gwRoutes, err := n.nlHandle.RouteGet(gw)
  64. if err != nil {
  65. return fmt.Errorf("route for the gateway %s could not be found: %v", gw, err)
  66. }
  67. var linkIndex int
  68. for _, gwRoute := range gwRoutes {
  69. if gwRoute.Gw == nil {
  70. linkIndex = gwRoute.LinkIndex
  71. break
  72. }
  73. }
  74. if linkIndex == 0 {
  75. return fmt.Errorf("direct route for the gateway %s could not be found", gw)
  76. }
  77. if isAdd {
  78. return n.nlHandle.RouteAdd(&netlink.Route{
  79. Scope: netlink.SCOPE_UNIVERSE,
  80. LinkIndex: linkIndex,
  81. Gw: gw,
  82. })
  83. }
  84. return n.nlHandle.RouteDel(&netlink.Route{
  85. Scope: netlink.SCOPE_UNIVERSE,
  86. LinkIndex: linkIndex,
  87. Gw: gw,
  88. })
  89. }
  90. // Program a route in to the namespace routing table.
  91. func (n *Namespace) programRoute(dest *net.IPNet, nh net.IP) error {
  92. gwRoutes, err := n.nlHandle.RouteGet(nh)
  93. if err != nil {
  94. return fmt.Errorf("route for the next hop %s could not be found: %v", nh, err)
  95. }
  96. return n.nlHandle.RouteAdd(&netlink.Route{
  97. Scope: netlink.SCOPE_UNIVERSE,
  98. LinkIndex: gwRoutes[0].LinkIndex,
  99. Gw: nh,
  100. Dst: dest,
  101. })
  102. }
  103. // Delete a route from the namespace routing table.
  104. func (n *Namespace) removeRoute(dest *net.IPNet, nh net.IP) error {
  105. gwRoutes, err := n.nlHandle.RouteGet(nh)
  106. if err != nil {
  107. return fmt.Errorf("route for the next hop could not be found: %v", err)
  108. }
  109. return n.nlHandle.RouteDel(&netlink.Route{
  110. Scope: netlink.SCOPE_UNIVERSE,
  111. LinkIndex: gwRoutes[0].LinkIndex,
  112. Gw: nh,
  113. Dst: dest,
  114. })
  115. }
  116. // SetGatewayIPv6 sets the default IPv6 gateway for the sandbox. It is a no-op
  117. // if the given gateway is empty.
  118. func (n *Namespace) SetGatewayIPv6(gwv6 net.IP) error {
  119. if len(gwv6) == 0 {
  120. return nil
  121. }
  122. if err := n.programGateway(gwv6, true); err != nil {
  123. return err
  124. }
  125. n.mu.Lock()
  126. n.gwv6 = gwv6
  127. n.mu.Unlock()
  128. return nil
  129. }
  130. // UnsetGatewayIPv6 unsets the previously set default IPv6 gateway in the sandbox.
  131. // It is a no-op if no gateway was set.
  132. func (n *Namespace) UnsetGatewayIPv6() error {
  133. gwv6 := n.GatewayIPv6()
  134. if len(gwv6) == 0 {
  135. return nil
  136. }
  137. if err := n.programGateway(gwv6, false); err != nil {
  138. return err
  139. }
  140. n.mu.Lock()
  141. n.gwv6 = net.IP{}
  142. n.mu.Unlock()
  143. return nil
  144. }
  145. // AddStaticRoute adds a static route to the sandbox.
  146. func (n *Namespace) AddStaticRoute(r *types.StaticRoute) error {
  147. if err := n.programRoute(r.Destination, r.NextHop); err != nil {
  148. return err
  149. }
  150. n.mu.Lock()
  151. n.staticRoutes = append(n.staticRoutes, r)
  152. n.mu.Unlock()
  153. return nil
  154. }
  155. // RemoveStaticRoute removes a static route from the sandbox.
  156. func (n *Namespace) RemoveStaticRoute(r *types.StaticRoute) error {
  157. if err := n.removeRoute(r.Destination, r.NextHop); err != nil {
  158. return err
  159. }
  160. n.mu.Lock()
  161. lastIndex := len(n.staticRoutes) - 1
  162. for i, v := range n.staticRoutes {
  163. if v == r {
  164. // Overwrite the route we're removing with the last element
  165. n.staticRoutes[i] = n.staticRoutes[lastIndex]
  166. // Shorten the slice to trim the extra element
  167. n.staticRoutes = n.staticRoutes[:lastIndex]
  168. break
  169. }
  170. }
  171. n.mu.Unlock()
  172. return nil
  173. }