Unverified Commit 4f71ecb8 by Stéphane Graber Committed by GitHub

Merge pull request #3069 from brauner/2019-07-01/network_creation

start: unify network creation
parents c83ad424 1871e646
...@@ -3563,16 +3563,19 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3563,16 +3563,19 @@ int lxc_setup(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
return -1; return -1;
ret = lxc_setup_network_in_child_namespaces(lxc_conf, &lxc_conf->network); if (handler->ns_clone_flags & CLONE_NEWNET) {
if (ret < 0) { ret = lxc_setup_network_in_child_namespaces(lxc_conf,
ERROR("Failed to setup network"); &lxc_conf->network);
return -1; if (ret < 0) {
} ERROR("Failed to setup network");
return -1;
}
ret = lxc_network_send_name_and_ifindex_to_parent(handler); ret = lxc_network_send_name_and_ifindex_to_parent(handler);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to send network device names and ifindices to parent"); ERROR("Failed to send network device names and ifindices to parent");
return -1; return -1;
}
} }
if (lxc_conf->autodev > 0) { if (lxc_conf->autodev > 0) {
......
...@@ -2588,8 +2588,18 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna ...@@ -2588,8 +2588,18 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
return -1; return -1;
} }
memset(netdev->name, 0, IFNAMSIZ); /*
memcpy(netdev->name, token, IFNAMSIZ - 1); * lxc-user-nic will take care of proper network device naming. So
* netdev->name and netdev->created_name need to be identical to not
* trigger another rename later on.
*/
retlen = strlcpy(netdev->name, token, IFNAMSIZ);
if (retlen < IFNAMSIZ)
retlen = strlcpy(netdev->created_name, token, IFNAMSIZ);
if (retlen >= IFNAMSIZ) {
ERROR("Container side veth device name returned by lxc-user-nic is too long");
return -E2BIG;
}
/* netdev->ifindex */ /* netdev->ifindex */
token = strtok_r(NULL, ":", &saveptr); token = strtok_r(NULL, ":", &saveptr);
...@@ -2641,9 +2651,8 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna ...@@ -2641,9 +2651,8 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcna
NULL, NULL,
}; };
ret = run_script_argv(lxcname, ret = run_script_argv(lxcname, hooks_version, "net",
hooks_version, "net", netdev->upscript, "up", argv);
netdev->upscript, "up", argv);
if (ret < 0) if (ret < 0)
return -1; return -1;
} }
...@@ -3076,14 +3085,11 @@ static int lxc_delete_l2proxy(struct lxc_netdev *netdev) { ...@@ -3076,14 +3085,11 @@ static int lxc_delete_l2proxy(struct lxc_netdev *netdev) {
return 0; return 0;
} }
int lxc_create_network_priv(struct lxc_handler *handler) static int lxc_create_network_priv(struct lxc_handler *handler)
{ {
struct lxc_list *iterator; struct lxc_list *iterator;
struct lxc_list *network = &handler->conf->network; struct lxc_list *network = &handler->conf->network;
if (!handler->am_root)
return 0;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
struct lxc_netdev *netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
...@@ -3109,17 +3115,18 @@ int lxc_create_network_priv(struct lxc_handler *handler) ...@@ -3109,17 +3115,18 @@ int lxc_create_network_priv(struct lxc_handler *handler)
return 0; return 0;
} }
int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcname, int lxc_network_move_created_netdev_priv(struct lxc_handler *handler)
struct lxc_list *network, pid_t pid)
{ {
int ret; pid_t pid = handler->pid;
char ifname[IFNAMSIZ]; struct lxc_list *network = &handler->conf->network;
struct lxc_list *iterator; struct lxc_list *iterator;
if (am_guest_unpriv()) if (am_guest_unpriv())
return 0; return 0;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
int ret;
char ifname[IFNAMSIZ];
struct lxc_netdev *netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
if (!netdev->ifindex) if (!netdev->ifindex)
...@@ -3135,28 +3142,29 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcnam ...@@ -3135,28 +3142,29 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcnam
ret = lxc_netdev_move_by_name(ifname, pid, NULL); ret = lxc_netdev_move_by_name(ifname, pid, NULL);
if (ret) { if (ret) {
errno = -ret; errno = -ret;
SYSERROR("Failed to move network device \"%s\" to " SYSERROR("Failed to move network device \"%s\" to network namespace %d",
"network namespace %d", ifname, pid); ifname, pid);
return -1; return -1;
} }
DEBUG("Moved network device \"%s\"/\"%s\" to network namespace " strlcpy(netdev->created_name, ifname, IFNAMSIZ);
"of %d",
ifname, netdev->name[0] != '\0' ? netdev->name : "(null)", DEBUG("Moved network device \"%s\" to network namespace of %d",
pid); netdev->created_name, pid);
} }
return 0; return 0;
} }
int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname, static int lxc_create_network_unpriv(struct lxc_handler *handler)
struct lxc_list *network, pid_t pid, unsigned int hooks_version)
{ {
int hooks_version = handler->conf->hooks_version;
const char *lxcname = handler->name;
const char *lxcpath = handler->lxcpath;
struct lxc_list *network = &handler->conf->network;
pid_t pid = handler->pid;
struct lxc_list *iterator; struct lxc_list *iterator;
if (!am_guest_unpriv())
return 0;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
struct lxc_netdev *netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
...@@ -3167,8 +3175,7 @@ int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname, ...@@ -3167,8 +3175,7 @@ int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
continue; continue;
if (netdev->type != LXC_NET_VETH) { if (netdev->type != LXC_NET_VETH) {
ERROR("Networks of type %s are not supported by " ERROR("Networks of type %s are not supported by unprivileged containers",
"unprivileged containers",
lxc_net_type_to_str(netdev->type)); lxc_net_type_to_str(netdev->type));
return -1; return -1;
} }
...@@ -3176,7 +3183,8 @@ int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname, ...@@ -3176,7 +3183,8 @@ int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
if (netdev->mtu) if (netdev->mtu)
INFO("mtu ignored due to insufficient privilege"); INFO("mtu ignored due to insufficient privilege");
if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev, pid, hooks_version)) if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev,
pid, hooks_version))
return -1; return -1;
} }
...@@ -3507,7 +3515,10 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3507,7 +3515,10 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
return -1; return -1;
} }
netdev->ifindex = if_nametoindex(netdev->name); netdev->ifindex = if_nametoindex(netdev->created_name);
if (!netdev->ifindex)
SYSERROR("Failed to retrieve ifindex for network device with name %s",
netdev->name ?: "(null)");
} }
/* get the new ifindex in case of physical netdev */ /* get the new ifindex in case of physical netdev */
...@@ -3522,12 +3533,12 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3522,12 +3533,12 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
/* retrieve the name of the interface */ /* retrieve the name of the interface */
if (!if_indextoname(netdev->ifindex, current_ifname)) { if (!if_indextoname(netdev->ifindex, current_ifname)) {
ERROR("Failed get name for network device with ifindex %d", SYSERROR("Failed to retrieve name for network device with ifindex %d",
netdev->ifindex); netdev->ifindex);
return -1; return -1;
} }
/* Default: let the system to choose one interface name. /* Default: let the system choose an interface name.
* When the IFLA_IFNAME attribute is passed something like "<prefix>%d" * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
* netlink will replace the format specifier with an appropriate index. * netlink will replace the format specifier with an appropriate index.
*/ */
...@@ -3539,14 +3550,17 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3539,14 +3550,17 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
} }
/* rename the interface name */ /* rename the interface name */
if (strcmp(ifname, netdev->name) != 0) { if (strcmp(current_ifname, netdev->name) != 0) {
err = lxc_netdev_rename_by_name(ifname, netdev->name); err = lxc_netdev_rename_by_name(current_ifname, netdev->name);
if (err) { if (err) {
errno = -err; errno = -err;
SYSERROR("Failed to rename network device \"%s\" to \"%s\"", SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
ifname, netdev->name); current_ifname, netdev->name);
return -1; return -1;
} }
TRACE("Renamed network device from \"%s\" to \"%s\"",
current_ifname, netdev->name);
} }
/* Re-read the name of the interface because its name has changed /* Re-read the name of the interface because its name has changed
...@@ -3576,14 +3590,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3576,14 +3590,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
/* setup ipv4 addresses on the interface */ /* setup ipv4 addresses on the interface */
if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) { if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
ERROR("Failed to setup ip addresses for network device \"%s\"", ERROR("Failed to setup ip addresses for network device \"%s\"",
ifname); current_ifname);
return -1; return -1;
} }
/* setup ipv6 addresses on the interface */ /* setup ipv6 addresses on the interface */
if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) { if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
ERROR("Failed to setup ipv6 addresses for network device \"%s\"", ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
ifname); current_ifname);
return -1; return -1;
} }
...@@ -3610,13 +3624,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3610,13 +3624,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) { if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) {
if (!(netdev->flags & IFF_UP)) { if (!(netdev->flags & IFF_UP)) {
ERROR("Cannot add ipv4 gateway for network device " ERROR("Cannot add ipv4 gateway for network device "
"\"%s\" when not bringing up the interface", ifname); "\"%s\" when not bringing up the interface", current_ifname);
return -1; return -1;
} }
if (lxc_list_empty(&netdev->ipv4)) { if (lxc_list_empty(&netdev->ipv4)) {
ERROR("Cannot add ipv4 gateway for network device " ERROR("Cannot add ipv4 gateway for network device "
"\"%s\" when not assigning an address", ifname); "\"%s\" when not assigning an address", current_ifname);
return -1; return -1;
} }
...@@ -3625,7 +3639,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3625,7 +3639,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
err = lxc_ipv4_gateway_add(netdev->ifindex, NULL); err = lxc_ipv4_gateway_add(netdev->ifindex, NULL);
if (err < 0) { if (err < 0) {
SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"", SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
ifname); current_ifname);
return minus_one_set_errno(-err); return minus_one_set_errno(-err);
} }
} else { } else {
...@@ -3645,7 +3659,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3645,7 +3659,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if (err < 0) { if (err < 0) {
errno = -err; errno = -err;
SYSERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"", SYSERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"",
bufinet4, ifname); bufinet4, current_ifname);
return -1; return -1;
} }
...@@ -3653,7 +3667,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3653,7 +3667,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if (err < 0) { if (err < 0) {
errno = -err; errno = -err;
SYSERROR("Failed to setup ipv4 gateway \"%s\" for network device \"%s\"", SYSERROR("Failed to setup ipv4 gateway \"%s\" for network device \"%s\"",
bufinet4, ifname); bufinet4, current_ifname);
return -1; return -1;
} }
} }
...@@ -3663,14 +3677,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3663,14 +3677,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
/* setup ipv6 gateway on the interface */ /* setup ipv6 gateway on the interface */
if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) { if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) {
if (!(netdev->flags & IFF_UP)) { if (!(netdev->flags & IFF_UP)) {
ERROR("Cannot add ipv6 gateway for network device " ERROR("Cannot add ipv6 gateway for network device \"%s\" when not bringing up the interface",
"\"%s\" when not bringing up the interface", ifname); current_ifname);
return -1; return -1;
} }
if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) { if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
ERROR("Cannot add ipv6 gateway for network device " ERROR("Cannot add ipv6 gateway for network device \"%s\" when not assigning an address",
"\"%s\" when not assigning an address", ifname); current_ifname);
return -1; return -1;
} }
...@@ -3679,7 +3693,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3679,7 +3693,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
err = lxc_ipv6_gateway_add(netdev->ifindex, NULL); err = lxc_ipv6_gateway_add(netdev->ifindex, NULL);
if (err < 0) { if (err < 0) {
SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"", SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
ifname); current_ifname);
return minus_one_set_errno(-err); return minus_one_set_errno(-err);
} }
} else { } else {
...@@ -3699,7 +3713,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3699,7 +3713,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if (err < 0) { if (err < 0) {
errno = -err; errno = -err;
SYSERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"", SYSERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"",
bufinet6, ifname); bufinet6, current_ifname);
return -1; return -1;
} }
...@@ -3707,7 +3721,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev) ...@@ -3707,7 +3721,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
if (err < 0) { if (err < 0) {
errno = -err; errno = -err;
SYSERROR("Failed to setup ipv6 gateway \"%s\" for network device \"%s\"", SYSERROR("Failed to setup ipv6 gateway \"%s\" for network device \"%s\"",
bufinet6, ifname); bufinet6, current_ifname);
return -1; return -1;
} }
} }
...@@ -3723,19 +3737,18 @@ int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf, ...@@ -3723,19 +3737,18 @@ int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
struct lxc_list *network) struct lxc_list *network)
{ {
struct lxc_list *iterator; struct lxc_list *iterator;
struct lxc_netdev *netdev;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
if (lxc_setup_netdev_in_child_namespaces(netdev)) { if (lxc_setup_netdev_in_child_namespaces(netdev)) {
ERROR("failed to setup netdev"); ERROR("Failed to setup netdev");
return -1; return -1;
} }
} }
if (!lxc_list_empty(network)) if (!lxc_list_empty(network))
INFO("network has been setup"); INFO("Network has been setup");
return 0; return 0;
} }
...@@ -3746,9 +3759,6 @@ int lxc_network_send_veth_names_to_child(struct lxc_handler *handler) ...@@ -3746,9 +3759,6 @@ int lxc_network_send_veth_names_to_child(struct lxc_handler *handler)
struct lxc_list *network = &handler->conf->network; struct lxc_list *network = &handler->conf->network;
int data_sock = handler->data_sock[0]; int data_sock = handler->data_sock[0];
if (handler->am_root)
return 0;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
int ret; int ret;
struct lxc_netdev *netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
...@@ -3759,7 +3769,12 @@ int lxc_network_send_veth_names_to_child(struct lxc_handler *handler) ...@@ -3759,7 +3769,12 @@ int lxc_network_send_veth_names_to_child(struct lxc_handler *handler)
ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL); ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
if (ret < 0) if (ret < 0)
return -1; return -1;
TRACE("Sent network device name \"%s\" to child", netdev->name);
ret = lxc_send_nointr(data_sock, netdev->created_name, IFNAMSIZ, MSG_NOSIGNAL);
if (ret < 0)
return -1;
TRACE("Sent network device name \"%s\" to child", netdev->created_name);
} }
return 0; return 0;
...@@ -3771,9 +3786,6 @@ int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler) ...@@ -3771,9 +3786,6 @@ int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler)
struct lxc_list *network = &handler->conf->network; struct lxc_list *network = &handler->conf->network;
int data_sock = handler->data_sock[1]; int data_sock = handler->data_sock[1];
if (handler->am_root)
return 0;
lxc_list_for_each(iterator, network) { lxc_list_for_each(iterator, network) {
int ret; int ret;
struct lxc_netdev *netdev = iterator->elem; struct lxc_netdev *netdev = iterator->elem;
...@@ -3784,7 +3796,11 @@ int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler) ...@@ -3784,7 +3796,11 @@ int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler)
ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0); ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
if (ret < 0) if (ret < 0)
return -1; return -1;
TRACE("Received network device name \"%s\" from parent", netdev->name);
ret = lxc_recv_nointr(data_sock, netdev->created_name, IFNAMSIZ, 0);
if (ret < 0)
return -1;
TRACE("Received network device name \"%s\" from parent", netdev->created_name);
} }
return 0; return 0;
...@@ -3816,7 +3832,9 @@ int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handler) ...@@ -3816,7 +3832,9 @@ int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handler)
return -1; return -1;
} }
TRACE("Sent network device names and ifindices to parent"); if (!lxc_list_empty(network))
TRACE("Sent network device names and ifindices to parent");
return 0; return 0;
} }
...@@ -4003,3 +4021,30 @@ int lxc_netns_get_nsid(int fd) ...@@ -4003,3 +4021,30 @@ int lxc_netns_get_nsid(int fd)
return -1; return -1;
} }
int lxc_create_network(struct lxc_handler *handler)
{
int ret;
/*
* Find gateway addresses from the link device, which is no longer
* accessible inside the container. Do this before creating network
* interfaces, since goto out_delete_net does not work before
* lxc_clone.
*/
ret = lxc_find_gateway_addresses(handler);
if (ret) {
ERROR("Failed to find gateway addresses");
return -1;
}
if (handler->am_root) {
ret = lxc_create_network_priv(handler);
if (ret)
return -1;
return lxc_network_move_created_netdev_priv(handler);
}
return lxc_create_network_unpriv(handler);
}
...@@ -147,7 +147,10 @@ union netdev_p { ...@@ -147,7 +147,10 @@ union netdev_p {
* @flags : flag of the network device (IFF_UP, ... ) * @flags : flag of the network device (IFF_UP, ... )
* @link : lxc.net.[i].link, name of bridge or host iface to attach * @link : lxc.net.[i].link, name of bridge or host iface to attach
* if any * if any
* @name : lxc.net.[i].name, name of iface on the container side * @name : lxc.net.[i].name, name of iface on the container side
* @created_name : the name with which this interface got created before
* being renamed to final_name.
* Currenly only used for veth devices.
* @hwaddr : mac address * @hwaddr : mac address
* @mtu : maximum transmission unit * @mtu : maximum transmission unit
* @priv : information specific to the specificed network type * @priv : information specific to the specificed network type
...@@ -176,6 +179,7 @@ struct lxc_netdev { ...@@ -176,6 +179,7 @@ struct lxc_netdev {
char link[IFNAMSIZ]; char link[IFNAMSIZ];
bool l2proxy; bool l2proxy;
char name[IFNAMSIZ]; char name[IFNAMSIZ];
char created_name[IFNAMSIZ];
char *hwaddr; char *hwaddr;
char *mtu; char *mtu;
union netdev_p priv; union netdev_p priv;
...@@ -267,15 +271,9 @@ extern char *lxc_mkifname(char *template); ...@@ -267,15 +271,9 @@ extern char *lxc_mkifname(char *template);
extern const char *lxc_net_type_to_str(int type); extern const char *lxc_net_type_to_str(int type);
extern int setup_private_host_hw_addr(char *veth1); extern int setup_private_host_hw_addr(char *veth1);
extern int netdev_get_mtu(int ifindex); extern int netdev_get_mtu(int ifindex);
extern int lxc_create_network_priv(struct lxc_handler *handler); extern int lxc_network_move_created_netdev_priv(struct lxc_handler *handler);
extern int lxc_network_move_created_netdev_priv(const char *lxcpath,
const char *lxcname,
struct lxc_list *network,
pid_t pid);
extern void lxc_delete_network(struct lxc_handler *handler); extern void lxc_delete_network(struct lxc_handler *handler);
extern int lxc_find_gateway_addresses(struct lxc_handler *handler); extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
extern int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
struct lxc_list *network, pid_t pid, unsigned int hook_version);
extern int lxc_requests_empty_network(struct lxc_handler *handler); extern int lxc_requests_empty_network(struct lxc_handler *handler);
extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler); extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler);
extern int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf, extern int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
...@@ -286,5 +284,6 @@ extern int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handl ...@@ -286,5 +284,6 @@ extern int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handl
extern int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler); extern int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler);
extern int lxc_netns_set_nsid(int netns_fd); extern int lxc_netns_set_nsid(int netns_fd);
extern int lxc_netns_get_nsid(__s32 fd); extern int lxc_netns_get_nsid(__s32 fd);
extern int lxc_create_network(struct lxc_handler *handler);
#endif /* __LXC_NETWORK_H */ #endif /* __LXC_NETWORK_H */
...@@ -1193,10 +1193,12 @@ static int do_start(void *data) ...@@ -1193,10 +1193,12 @@ static int do_start(void *data)
if (ret < 0) if (ret < 0)
goto out_error; goto out_error;
ret = lxc_network_recv_veth_names_from_parent(handler); if (handler->ns_clone_flags & CLONE_NEWNET) {
if (ret < 0) { ret = lxc_network_recv_veth_names_from_parent(handler);
ERROR("Failed to receive veth names from parent"); if (ret < 0) {
goto out_warn_father; ERROR("Failed to receive veth names from parent");
goto out_warn_father;
}
} }
/* If we are in a new user namespace, become root there to have /* If we are in a new user namespace, become root there to have
...@@ -1695,31 +1697,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1695,31 +1697,6 @@ static int lxc_spawn(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
goto out_sync_fini; goto out_sync_fini;
if (handler->ns_clone_flags & CLONE_NEWNET) {
if (!lxc_list_empty(&conf->network)) {
/* Find gateway addresses from the link device, which is
* no longer accessible inside the container. Do this
* before creating network interfaces, since goto
* out_delete_net does not work before lxc_clone.
*/
ret = lxc_find_gateway_addresses(handler);
if (ret < 0) {
ERROR("Failed to find gateway addresses");
goto out_sync_fini;
}
/* That should be done before the clone because we will
* fill the netdev index and use them in the child.
*/
ret = lxc_create_network_priv(handler);
if (ret < 0) {
ERROR("Failed to create the network");
goto out_delete_net;
}
}
}
if (!cgroup_ops->payload_create(cgroup_ops, handler)) { if (!cgroup_ops->payload_create(cgroup_ops, handler)) {
ERROR("Failed creating cgroups"); ERROR("Failed creating cgroups");
goto out_delete_net; goto out_delete_net;
...@@ -1780,6 +1757,14 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1780,6 +1757,14 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
ret = snprintf(pidstr, 20, "%d", handler->pid);
if (ret < 0 || ret >= 20)
goto out_delete_net;
ret = setenv("LXC_PID", pidstr, 1);
if (ret < 0)
SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr);
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag) if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
INFO("Cloned %s", ns_info[i].flag_name); INFO("Cloned %s", ns_info[i].flag_name);
...@@ -1848,29 +1833,19 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1848,29 +1833,19 @@ static int lxc_spawn(struct lxc_handler *handler)
/* Create the network configuration. */ /* Create the network configuration. */
if (handler->ns_clone_flags & CLONE_NEWNET) { if (handler->ns_clone_flags & CLONE_NEWNET) {
ret = lxc_network_move_created_netdev_priv(handler->lxcpath, ret = lxc_create_network(handler);
handler->name,
&conf->network,
handler->pid);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to create the configured network"); ERROR("Failed to create the network");
goto out_delete_net; goto out_delete_net;
} }
ret = lxc_create_network_unpriv(handler->lxcpath, handler->name, ret = lxc_network_send_veth_names_to_child(handler);
&conf->network, handler->pid, conf->hooks_version);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to create the configured network"); ERROR("Failed to send veth names to child");
goto out_delete_net; goto out_delete_net;
} }
} }
ret = lxc_network_send_veth_names_to_child(handler);
if (ret < 0) {
ERROR("Failed to send veth names to child");
goto out_delete_net;
}
if (!lxc_list_empty(&conf->procs)) { if (!lxc_list_empty(&conf->procs)) {
ret = setup_proc_filesystem(&conf->procs, handler->pid); ret = setup_proc_filesystem(&conf->procs, handler->pid);
if (ret < 0) if (ret < 0)
...@@ -1916,14 +1891,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1916,14 +1891,6 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
} }
ret = snprintf(pidstr, 20, "%d", handler->pid);
if (ret < 0 || ret >= 20)
goto out_delete_net;
ret = setenv("LXC_PID", pidstr, 1);
if (ret < 0)
SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr);
/* Run any host-side start hooks */ /* Run any host-side start hooks */
ret = run_lxc_hooks(name, "start-host", conf, NULL); ret = run_lxc_hooks(name, "start-host", conf, NULL);
if (ret < 0) { if (ret < 0) {
...@@ -1941,11 +1908,12 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1941,11 +1908,12 @@ static int lxc_spawn(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
goto out_delete_net; goto out_delete_net;
ret = lxc_network_recv_name_and_ifindex_from_child(handler); if (handler->ns_clone_flags & CLONE_NEWNET) {
if (ret < 0) { ret = lxc_network_recv_name_and_ifindex_from_child(handler);
ERROR("Failed to receive names and ifindices for network " if (ret < 0) {
"devices from child"); ERROR("Failed to receive names and ifindices for network devices from child");
goto out_delete_net; goto out_delete_net;
}
} }
/* Now all networks are created, network devices are moved into place, /* Now all networks are created, network devices are moved into place,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment