From: Dongsheng Yang Date: Fri, 10 Oct 2014 02:57:13 +0000 (+0800) Subject: container: introduce two functions named as {at/de}tach_interface(). X-Git-Tag: lxc-1.1.0.alpha3~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e58fae8f29b171bb0fd164c2f566b2475a2b6928;p=thirdparty%2Flxc.git container: introduce two functions named as {at/de}tach_interface(). Currently, we depends on ip command to attach interface to container. It means we only implemented it by python. This patch implement adding and removing interface by c and added them in struct container. Changelog: 10/15/2014 (serge): return error if ifname is NULL. Signed-off-by: Dongsheng Yang Acked-by: Serge E. Hallyn --- diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 47f60d9bf..6b854338b 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -39,6 +39,7 @@ #include #include +#include #include "config.h" #include "lxc.h" @@ -3426,6 +3427,99 @@ static bool lxcapi_remove_device_node(struct lxc_container *c, const char *src_p return add_remove_device_node(c, src_path, dest_path, false); } +static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname, + const char *dst_ifname) +{ + int ret = 0; + if (am_unpriv()) { + ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); + return false; + } + + if (!ifname) { + ERROR("No source interface name given"); + return false; + } + + ret = lxc_netdev_isup(ifname); + if (ret < 0) + goto err; + + /* netdev of ifname is up. */ + if (ret) { + ret = lxc_netdev_down(ifname); + if (ret) + goto err; + } + + ret = lxc_netdev_move_by_name(ifname, c->init_pid(c), dst_ifname); + if (ret) + goto err; + + return true; +err: + /* -EINVAL means there is no netdev named as ifanme. */ + if (ret == -EINVAL) { + ERROR("No network device named as %s.", ifname); + } + return false; +} + +static bool lxcapi_detach_interface(struct lxc_container *c, const char *ifname, + const char *dst_ifname) +{ + pid_t pid, pid_outside; + + if (am_unpriv()) { + ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); + return false; + } + + if (!ifname) { + ERROR("No source interface name given"); + return false; + } + + pid_outside = getpid(); + pid = fork(); + if (pid < 0) { + ERROR("failed to fork task to get interfaces information"); + return false; + } + + if (pid == 0) { // child + int ret = 0; + if (!enter_to_ns(c)) { + ERROR("failed to enter namespace"); + exit(-1); + } + + ret = lxc_netdev_isup(ifname); + if (ret < 0) + exit(ret); + + /* netdev of ifname is up. */ + if (ret) { + ret = lxc_netdev_down(ifname); + if (ret) + exit(ret); + } + + ret = lxc_netdev_move_by_name(ifname, pid_outside, dst_ifname); + + /* -EINVAL means there is no netdev named as ifanme. */ + if (ret == -EINVAL) { + ERROR("No network device named as %s.", ifname); + } + exit(ret); + } + + if (wait_for_pid(pid) != 0) + return false; + + return true; +} + struct criu_opts { /* The type of criu invocation, one of "dump" or "restore" */ char *action; @@ -4051,6 +4145,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath c->may_control = lxcapi_may_control; c->add_device_node = lxcapi_add_device_node; c->remove_device_node = lxcapi_remove_device_node; + c->attach_interface = lxcapi_attach_interface; + c->detach_interface = lxcapi_detach_interface; c->checkpoint = lxcapi_checkpoint; c->restore = lxcapi_restore;