123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- package osl
- import (
- "fmt"
- "net"
- "github.com/docker/libnetwork/types"
- "github.com/vishvananda/netlink"
- )
- func (n *networkNamespace) Gateway() net.IP {
- n.Lock()
- defer n.Unlock()
- return n.gw
- }
- func (n *networkNamespace) GatewayIPv6() net.IP {
- n.Lock()
- defer n.Unlock()
- return n.gwv6
- }
- func (n *networkNamespace) StaticRoutes() []*types.StaticRoute {
- n.Lock()
- defer n.Unlock()
- routes := make([]*types.StaticRoute, len(n.staticRoutes))
- for i, route := range n.staticRoutes {
- r := route.GetCopy()
- routes[i] = r
- }
- return routes
- }
- func (n *networkNamespace) setGateway(gw net.IP) {
- n.Lock()
- n.gw = gw
- n.Unlock()
- }
- func (n *networkNamespace) setGatewayIPv6(gwv6 net.IP) {
- n.Lock()
- n.gwv6 = gwv6
- n.Unlock()
- }
- func (n *networkNamespace) SetGateway(gw net.IP) error {
- // Silently return if the gateway is empty
- if len(gw) == 0 {
- return nil
- }
- err := n.programGateway(gw, true)
- if err == nil {
- n.setGateway(gw)
- }
- return err
- }
- func (n *networkNamespace) UnsetGateway() error {
- gw := n.Gateway()
- // Silently return if the gateway is empty
- if len(gw) == 0 {
- return nil
- }
- err := n.programGateway(gw, false)
- if err == nil {
- n.setGateway(net.IP{})
- }
- return err
- }
- func (n *networkNamespace) 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 *networkNamespace) programRoute(path string, 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 *networkNamespace) removeRoute(path string, 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,
- })
- }
- func (n *networkNamespace) SetGatewayIPv6(gwv6 net.IP) error {
- // Silently return if the gateway is empty
- if len(gwv6) == 0 {
- return nil
- }
- err := n.programGateway(gwv6, true)
- if err == nil {
- n.setGatewayIPv6(gwv6)
- }
- return err
- }
- func (n *networkNamespace) UnsetGatewayIPv6() error {
- gwv6 := n.GatewayIPv6()
- // Silently return if the gateway is empty
- if len(gwv6) == 0 {
- return nil
- }
- err := n.programGateway(gwv6, false)
- if err == nil {
- n.Lock()
- n.gwv6 = net.IP{}
- n.Unlock()
- }
- return err
- }
- func (n *networkNamespace) AddStaticRoute(r *types.StaticRoute) error {
- err := n.programRoute(n.nsPath(), r.Destination, r.NextHop)
- if err == nil {
- n.Lock()
- n.staticRoutes = append(n.staticRoutes, r)
- n.Unlock()
- }
- return err
- }
- func (n *networkNamespace) RemoveStaticRoute(r *types.StaticRoute) error {
- err := n.removeRoute(n.nsPath(), r.Destination, r.NextHop)
- if err == nil {
- n.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.Unlock()
- }
- return err
- }
|