reexec_move_interface.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package libnetwork
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "runtime"
  8. "syscall"
  9. "github.com/vishvananda/netlink"
  10. )
  11. type setupError struct {
  12. Message string
  13. }
  14. func (s setupError) Error() string {
  15. return s.Message
  16. }
  17. func reexecMoveInterface() {
  18. runtime.LockOSThread()
  19. var (
  20. err error
  21. pipe = os.NewFile(3, "child")
  22. )
  23. defer func() {
  24. if err != nil {
  25. ioutil.ReadAll(pipe)
  26. if err := json.NewEncoder(pipe).Encode(setupError{Message: err.Error()}); err != nil {
  27. panic(err)
  28. }
  29. }
  30. pipe.Close()
  31. }()
  32. n := &Interface{}
  33. if err = json.NewDecoder(pipe).Decode(n); err == nil {
  34. err = setupInNS(os.Args[1], n)
  35. }
  36. }
  37. func setupInNS(nsPath string, settings *Interface) error {
  38. f, err := os.OpenFile(nsPath, os.O_RDONLY, 0)
  39. if err != nil {
  40. return fmt.Errorf("failed get network namespace %q: %v", nsPath, err)
  41. }
  42. // Find the network inteerface identified by the SrcName attribute.
  43. iface, err := netlink.LinkByName(settings.SrcName)
  44. if err != nil {
  45. return err
  46. }
  47. // Move the network interface to the destination namespace.
  48. nsFD := f.Fd()
  49. if err := netlink.LinkSetNsFd(iface, int(nsFD)); err != nil {
  50. return err
  51. }
  52. f.Close()
  53. // Move the executing code to the destination namespace so we can start
  54. // configure the interface.
  55. if err := setns(nsFD, syscall.CLONE_NEWNET); err != nil {
  56. return err
  57. }
  58. // Configure the interface now this is moved in the proper namespace.
  59. if err := configureInterface(iface, settings); err != nil {
  60. return err
  61. }
  62. // Up the interface.
  63. return netlink.LinkSetUp(iface)
  64. }