// Join joins to network namespace func (n *Namespace) Join() error { runtime.LockOSThread() f, err := os.OpenFile(n.Path, os.O_RDONLY, 0) if err != nil { return fmt.Errorf("failed get network namespace fd: %v", err) } defer f.Close() if _, _, err := syscall.RawSyscall(syscall.SYS_SETNS, f.Fd(), syscall.CLONE_NEWNET, 0); err != 0 { return err } return nil }
func main() { if len(os.Args) != 3 { panic("not enough args") } intf, err := net.InterfaceByName(os.Args[1]) if err != nil { panic(err) } containerID := os.Args[2] log.Infof("Requesting for container ID %q on interface %q", containerID, intf.Name) contPid := getContainerInfo(containerID) log.Infof("Container has PID %s", contPid) runtime.LockOSThread() f, err := os.Open(fmt.Sprintf("/proc/%s/ns/net", contPid)) if err != nil { panic(err) } if _, _, err := unix.RawSyscall(unix.SYS_SETNS, f.Fd(), syscall.CLONE_NEWNET, 0); err != 0 { panic(err) } link, err := netlink.LinkByName("eth0") if err != nil { panic(err) } chaddr := link.Attrs().HardwareAddr p := dhcp.RequestPacket(dhcp.Discover, chaddr, nil, []byte{1, 2, 3, 4}, true, []dhcp.Option{}) conn, err := net.ListenPacket("udp", ":68") if err != nil { panic(err) } ipc := ipv4.NewPacketConn(conn) ipc.SetControlMessage(ipv4.FlagInterface, true) to := &net.UDPAddr{ IP: net.IPv4(255, 255, 255, 255), Port: 67, } eth0, err := net.InterfaceByName("eth0") if err != nil { panic(err) } if _, err := ipc.WriteTo(p, &ipv4.ControlMessage{IfIndex: eth0.Index}, to); err != nil { panic(err) } newPacket := dhcp.NewPacket(dhcp.BootReply) for { _, cm, _, err := ipc.ReadFrom(newPacket) if err != nil { panic(err) } if cm != nil && cm.IfIndex == eth0.Index { log.Infof("Received reply: %q", newPacket.YIAddr().String()) break } } addr, err := netlink.ParseAddr(newPacket.YIAddr().String() + "/16") if err != nil { panic(err) } log.Infof("Setting interface eth0...") if err := netlink.AddrAdd(link, addr); err != nil { panic(err) } }