func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) { origns, err := netns.Get() if err != nil { t.Fatalf("Could not get the current netns: %v", err) } defer origns.Close() key := info.Sandbox().Key() f, err := os.OpenFile(key, os.O_RDONLY, 0) if err != nil { t.Fatalf("Failed to open network namespace path %q: %v", key, err) } defer f.Close() runtime.LockOSThread() defer runtime.UnlockOSThread() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", key, err) } defer netns.Set(origns) _, err = netlink.LinkByName("eth0") if err != nil { t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err) } _, err = netlink.LinkByName("eth1") if err != nil { t.Fatalf("Could not find the interface eth1 inside the sandbox: %v", err) } }
func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error { defer InitOSContext()() 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() // Invoked before the namespace switch happens but after the namespace file // handle is obtained. if err := prefunc(int(nsFD)); err != nil { return fmt.Errorf("failed in prefunc: %v", err) } if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } defer ns.SetNamespace() // Invoked after the namespace switch. return postfunc(ns.ParseHandlerInt()) }
func setupNetNs(nsPath string) (*os.Process, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return nil, err } defer origns.Close() f, err := os.OpenFile(nsPath, os.O_RDONLY, 0) if err != nil { return nil, fmt.Errorf("failed to get network namespace %q: %v", nsPath, err) } defer f.Close() nsFD := f.Fd() if err := netns.Set(netns.NsHandle(nsFD)); err != nil { return nil, fmt.Errorf("failed to set network namespace %q: %v", nsPath, err) } defer netns.Set(origns) cmd := exec.Command("/bin/sh", "-c", "while true; do sleep 1; done") if err := cmd.Start(); err != nil { return nil, fmt.Errorf("failed to start netns process: %v", err) } return cmd.Process, nil }
func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { _, ok := s.(*networkNamespace) if !ok { t.Fatalf("The sandox interface returned is not of type networkNamespace") } origns, err := netns.Get() if err != nil { t.Fatalf("Could not get the current netns: %v", err) } defer origns.Close() f, err := os.OpenFile(s.Key(), os.O_RDONLY, 0) if err != nil { t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err) } defer f.Close() runtime.LockOSThread() defer runtime.UnlockOSThread() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", s.Key(), err) } defer netns.Set(origns) for _, suffix := range ifaceSuffixes { _, err = netlink.LinkByName(sboxIfaceName + suffix) if err != nil { t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+suffix, err) } } }
func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) 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() // Invoked before the namespace switch happens but after the namespace file // handle is obtained. if err := prefunc(int(nsFD)); err != nil { return fmt.Errorf("failed in prefunc: %v", err) } if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } defer netns.Set(origns) // Invoked after the namespace switch. return postfunc(int(origns)) }
func nsInvoke(path string, inNsfunc func(callerFD int) error) 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) // Invoked after the namespace switch. return inNsfunc(int(origns)) }
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, }) }
func (n *networkNamespace) AddInterface(i *Interface) error { n.Lock() i.DstName = fmt.Sprintf("%s%d", i.DstName, n.nextIfIndex) n.nextIfIndex++ n.Unlock() runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return err } defer origns.Close() f, err := os.OpenFile(n.path, os.O_RDONLY, 0) if err != nil { return fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer f.Close() // Find the network interface identified by the SrcName attribute. iface, err := netlink.LinkByName(i.SrcName) if err != nil { return err } // Move the network interface to the destination namespace. nsFD := f.Fd() if err := netlink.LinkSetNsFd(iface, int(nsFD)); err != nil { return err } if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } defer netns.Set(origns) // Down the interface before configuring if err := netlink.LinkSetDown(iface); err != nil { return err } // Configure the interface now this is moved in the proper namespace. if err := configureInterface(iface, i); err != nil { return err } // Up the interface. if err := netlink.LinkSetUp(iface); err != nil { return err } n.Lock() n.sinfo.Interfaces = append(n.sinfo.Interfaces, i) n.Unlock() return nil }
func (n *networkNamespace) RemoveInterface(i *Interface) error { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return err } defer origns.Close() f, err := os.OpenFile(n.path, os.O_RDONLY, 0) if err != nil { return fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer f.Close() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } defer netns.Set(origns) // Find the network inteerface identified by the DstName attribute. iface, err := netlink.LinkByName(i.DstName) if err != nil { return err } // Down the interface before configuring if err := netlink.LinkSetDown(iface); err != nil { return err } err = netlink.LinkSetName(iface, i.SrcName) if err != nil { fmt.Println("LinkSetName failed: ", err) return err } // Move the network interface to caller namespace. if err := netlink.LinkSetNsFd(iface, int(origns)); err != nil { fmt.Println("LinkSetNsPid failed: ", err) return err } n.Lock() for index, intf := range n.sinfo.Interfaces { if intf == i { n.sinfo.Interfaces = append(n.sinfo.Interfaces[:index], n.sinfo.Interfaces[index+1:]...) break } } n.Unlock() return nil }
func reexecSetupResolver() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 4 { log.Error("invalid number of arguments..") os.Exit(1) } resolverIP, ipPort, _ := net.SplitHostPort(os.Args[2]) _, tcpPort, _ := net.SplitHostPort(os.Args[3]) rules := [][]string{ {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[2]}, {"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[3]}, {"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, } f, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0) if err != nil { log.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(2) } defer f.Close() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { log.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) os.Exit(3) } // insert outputChain and postroutingchain err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain) if err == nil { iptables.RawCombinedOutputNative("-t", "nat", "-F", outputChain) } else { iptables.RawCombinedOutputNative("-t", "nat", "-N", outputChain) iptables.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain) } err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) if err == nil { iptables.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain) } else { iptables.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain) iptables.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) } for _, rule := range rules { if iptables.RawCombinedOutputNative(rule...) != nil { log.Errorf("setting up rule failed, %v", rule) } } }
func Exec(fd *os.File, cb func() error) error { runtime.LockOSThread() defer runtime.UnlockOSThread() newns := vishnetns.NsHandle(int(fd.Fd())) origns, _ := vishnetns.Get() defer origns.Close() if err := vishnetns.Set(newns); err != nil { return fmt.Errorf("set netns: %s", err) } err := cb() mustSetNs(origns) // if this happens we definitely can't recover return err }