return ret == 0;
}
-static inline bool enter_to_ns(struct lxc_container *c) {
- int netns, userns, ret = 0, init_pid = 0;;
- char new_netns_path[MAXPATHLEN];
- char new_userns_path[MAXPATHLEN];
-
- if (!c->is_running(c))
- goto out;
-
- init_pid = c->init_pid(c);
+static inline bool enter_to_ns(struct lxc_container *c)
+{
+ pid_t pid = c->init_pid(c);
- /* Switch to new userns */
if ((geteuid() != 0 || (c->lxc_conf && !lxc_list_empty(&c->lxc_conf->id_map))) && access("/proc/self/ns/user", F_OK) == 0) {
- ret = snprintf(new_userns_path, MAXPATHLEN, "/proc/%d/ns/user", init_pid);
- if (ret < 0 || ret >= MAXPATHLEN)
- goto out;
-
- userns = open(new_userns_path, O_RDONLY);
- if (userns < 0) {
- SYSERROR("failed to open %s", new_userns_path);
- goto out;
- }
-
- if (setns(userns, CLONE_NEWUSER)) {
- SYSERROR("failed to setns for CLONE_NEWUSER");
- close(userns);
- goto out;
- }
- close(userns);
- }
-
- /* Switch to new netns */
- ret = snprintf(new_netns_path, MAXPATHLEN, "/proc/%d/ns/net", init_pid);
- if (ret < 0 || ret >= MAXPATHLEN)
- goto out;
-
- netns = open(new_netns_path, O_RDONLY);
- if (netns < 0) {
- SYSERROR("failed to open %s", new_netns_path);
- goto out;
- }
-
- if (setns(netns, CLONE_NEWNET)) {
- SYSERROR("failed to setns for CLONE_NEWNET");
- close(netns);
- goto out;
+ if (!switch_to_ns(pid, "user"))
+ return false;
}
- close(netns);
- return true;
-out:
- return false;
+ return switch_to_ns(pid, "net");
}
// used by qsort and bsearch functions for comparing names
*/
bool (*remove_device_node)(struct lxc_container *c, const char *src_path, const char *dest_path);
+ /*!
+ * \brief Add specified netdev to the container.
+ *
+ * \param c Container.
+ * \param dev name of net device.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*attach_interface)(struct lxc_container *c, const char *dev, const char *dst_dev);
+
+ /*!
+ * \brief Remove specified netdev from the container.
+ *
+ * \param c Container.
+ * \param dev name of net device.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*detach_interface)(struct lxc_container *c, const char *dev, const char *dst_dev);
/*!
* \brief Checkpoint a container.
*
#include "utils.h"
#include "log.h"
#include "lxclock.h"
+#include "namespace.h"
lxc_log_define(lxc_utils, lxc);
return 0;
}
+bool switch_to_ns(pid_t pid, const char *ns) {
+ int fd, ret;
+ char nspath[MAXPATHLEN];
+
+ /* Switch to new ns */
+ ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns);
+ if (ret < 0 || ret >= MAXPATHLEN)
+ return false;
+
+ fd = open(nspath, O_RDONLY);
+ if (fd < 0) {
+ SYSERROR("failed to open %s", nspath);
+ return false;
+ }
+
+ ret = setns(fd, 0);
+ if (ret) {
+ SYSERROR("failed to set process %d to %s of %d.", pid, ns, fd);
+ close(fd);
+ return false;
+ }
+ close(fd);
+ return true;
+}
+
/*
* looking at fs/proc_namespace.c, it appears we can
* actually expect the rootfs entry to very specifically contain