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