예제 #1
0
// Detect and return host-side network configuration.
func getNetConfig() (config *netConfig, err error) {
	eth0, err := netlink.LinkByName("eth0")
	if err != nil {
		return nil, fmt.Errorf("LinkByName(eth0): %v", err)
	}
	eth0Addrs, err := netlink.AddrList(eth0, syscall.AF_INET)
	if err != nil {
		return nil, fmt.Errorf("AddrList(eth0): %v", err)
	}
	if len(eth0Addrs) != 1 {
		return nil, fmt.Errorf("eth0: Expected single IPv4 address")
	}
	// TODO Is there a better way than relying on "8.8.8.8" being past
	// the default router?
	defaultroute, err := netlink.RouteGet(net.ParseIP("8.8.8.8"))
	if len(defaultroute) != 1 {
		return nil, fmt.Errorf("Could not determine single default route (got %v)", len(defaultroute))
	}
	eth0Attrs := eth0.Attrs()
	dns := dnsReadConfig("/etc/resolv.conf")
	hostname, _ := os.Hostname()
	config = &netConfig{
		hostname,
		eth0Addrs[0].IPNet.String(),
		defaultroute[0].Gw.String(),
		eth0Attrs.HardwareAddr.String(),
		dns.servers,
		dns.search,
	}
	return
}
예제 #2
0
func programGateway(path string, gw net.IP) error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	origns, err := netns.Get()
	if err != nil {
		return err
	}
	defer origns.Close()

	f, err := os.OpenFile(path, os.O_RDONLY, 0)
	if err != nil {
		return fmt.Errorf("failed get network namespace %q: %v", path, err)
	}
	defer f.Close()

	nsFD := f.Fd()
	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
		return err
	}
	defer netns.Set(origns)

	gwRoutes, err := netlink.RouteGet(gw)
	if err != nil {
		return fmt.Errorf("route for the gateway could not be found: %v", err)
	}

	return netlink.RouteAdd(&netlink.Route{
		Scope:     netlink.SCOPE_UNIVERSE,
		LinkIndex: gwRoutes[0].LinkIndex,
		Gw:        gw,
	})
}
예제 #3
0
// Add a route from the global namespace
func programRoute(dest *net.IPNet, nh net.IP) error {
	gwRoutes, err := netlink.RouteGet(nh)
	if err != nil {
		return fmt.Errorf("route for the next hop %s could not be found: %v", nh, err)
	}
	return netlink.RouteAdd(&netlink.Route{
		Scope:     netlink.SCOPE_UNIVERSE,
		LinkIndex: gwRoutes[0].LinkIndex,
		Gw:        gwRoutes[0].Gw,
		Dst:       dest,
	})
}
예제 #4
0
// Delete a route from the namespace routing table.
func removeRoute(path string, dest *net.IPNet, nh net.IP) error {
	return nsInvoke(path, func(nsFD int) error { return nil }, func(callerFD int) error {
		gwRoutes, err := netlink.RouteGet(nh)
		if err != nil {
			return fmt.Errorf("route for the next hop could not be found: %v", err)
		}

		return netlink.RouteDel(&netlink.Route{
			Scope:     netlink.SCOPE_UNIVERSE,
			LinkIndex: gwRoutes[0].LinkIndex,
			Gw:        gwRoutes[0].Gw,
			Dst:       dest,
		})
	})
}
예제 #5
0
func programGateway(path string, gw net.IP, isAdd bool) error {
	return nsInvoke(path, func(nsFD int) error { return nil }, func(callerFD int) error {
		gwRoutes, err := netlink.RouteGet(gw)
		if err != nil {
			return fmt.Errorf("route for the gateway could not be found: %v", err)
		}

		if isAdd {
			return netlink.RouteAdd(&netlink.Route{
				Scope:     netlink.SCOPE_UNIVERSE,
				LinkIndex: gwRoutes[0].LinkIndex,
				Gw:        gw,
			})
		}

		return netlink.RouteDel(&netlink.Route{
			Scope:     netlink.SCOPE_UNIVERSE,
			LinkIndex: gwRoutes[0].LinkIndex,
			Gw:        gw,
		})
	})
}
예제 #6
0
func processRoute(ru *exportRoute, s net.Addr) error {
	src := s.(*net.TCPAddr).IP

	_, err := netlink.AddrList(nil, netlink.FAMILY_ALL)
	if err != nil {
		log.Error("Failed to get addresses")
		log.Error(err)
		return err
	}

	switch {
	case ru.Type == syscall.RTM_NEWROUTE:
		r := &netlink.Route{
			Dst:      ru.Dst,
			Gw:       src,
			Priority: ru.Priority + 100,
		}
		err := netlink.RouteAdd(r)
		if err != nil {
			log.Errorf("Failed to add route: %v", r)
			log.Error(err)
			return err
		}
	case ru.Type == syscall.RTM_DELROUTE:
		routes, err := netlink.RouteGet(ru.Dst.IP)
		if err != nil {
			log.Error("Failed to get routes")
			log.Error(err)
			return err
		}
		for _, r := range routes {
			if r.Gw.Equal(src) {
				netlink.RouteDel(&r)
			}
		}
	}
	return nil
}