route_linux.go 4.0 KB

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