Commit f0ab9713 by Stéphane Graber Committed by GitHub

Merge pull request #1781 from brauner/stable-2.0

stable 2.0: cherry-picks + delta reduction between master and stable 2.0
parents d3e7b8ad 567d7611
...@@ -2515,15 +2515,20 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) ...@@ -2515,15 +2515,20 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
lxc_map_ids_exec_wrapper, lxc_map_ids_exec_wrapper,
(void *)mapbuf); (void *)mapbuf);
if (ret < 0) { if (ret < 0) {
ERROR("new%cidmap failed to write mapping: %s", ERROR("new%cidmap failed to write mapping \"%s\": %s",
u_or_g, cmd_output); u_or_g, cmd_output, mapbuf);
return -1; return -1;
} }
TRACE("new%cidmap wrote mapping \"%s\"", u_or_g, mapbuf);
} else { } else {
ret = write_id_mapping(type, pid, mapbuf, pos - mapbuf); ret = write_id_mapping(type, pid, mapbuf, pos - mapbuf);
if (ret < 0) if (ret < 0) {
ERROR("Failed to write mapping \"%s\": %s",
cmd_output, mapbuf);
return -1; return -1;
} }
TRACE("Wrote mapping \"%s\"", mapbuf);
}
memset(mapbuf, 0, sizeof(mapbuf)); memset(mapbuf, 0, sizeof(mapbuf));
} }
...@@ -3006,41 +3011,36 @@ static bool verify_start_hooks(struct lxc_conf *conf) ...@@ -3006,41 +3011,36 @@ static bool verify_start_hooks(struct lxc_conf *conf)
static int lxc_send_ttys_to_parent(struct lxc_handler *handler) static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
{ {
int i; int i;
int *ttyfds;
struct lxc_pty_info *pty_info;
struct lxc_conf *conf = handler->conf; struct lxc_conf *conf = handler->conf;
const struct lxc_tty_info *tty_info = &conf->tty_info; struct lxc_tty_info *tty_info = &conf->tty_info;
int sock = handler->ttysock[0]; int sock = handler->data_sock[0];
int ret = -1; int ret = -1;
size_t num_ttyfds = (2 * conf->tty);
ttyfds = malloc(num_ttyfds * sizeof(int)); if (!conf->tty)
if (!ttyfds) return 0;
return -1;
for (i = 0; i < num_ttyfds; i++) { for (i = 0; i < conf->tty; i++) {
pty_info = &tty_info->pty_info[i / 2]; int ttyfds[2];
ttyfds[i++] = pty_info->slave; struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
ttyfds[i] = pty_info->master;
TRACE("send pty \"%s\" with master fd %d and slave fd %d to " ttyfds[0] = pty_info->master;
"parent", ttyfds[1] = pty_info->slave;
pty_info->name, pty_info->master, pty_info->slave);
ret = lxc_abstract_unix_send_fds(sock, ttyfds, 2, NULL, 0);
if (ret < 0)
break;
TRACE("Send pty \"%s\" with master fd %d and slave fd %d to "
"parent", pty_info->name, pty_info->master, pty_info->slave);
} }
ret = lxc_abstract_unix_send_fds(sock, ttyfds, num_ttyfds, NULL, 0);
if (ret < 0) if (ret < 0)
ERROR("failed to send %d ttys to parent: %s", conf->tty, ERROR("Failed to send %d ttys to parent: %s", conf->tty,
strerror(errno)); strerror(errno));
else else
TRACE("sent %d ttys to parent", conf->tty); TRACE("Sent %d ttys to parent", conf->tty);
close(handler->ttysock[0]);
close(handler->ttysock[1]);
for (i = 0; i < num_ttyfds; i++)
close(ttyfds[i]);
free(ttyfds); lxc_delete_tty(tty_info);
return ret; return ret;
} }
...@@ -3068,6 +3068,11 @@ int lxc_setup(struct lxc_handler *handler) ...@@ -3068,6 +3068,11 @@ int lxc_setup(struct lxc_handler *handler)
return -1; return -1;
} }
if (lxc_network_send_name_and_ifindex_to_parent(handler) < 0) {
ERROR("Failed to network device names and ifindices to parent");
return -1;
}
if (lxc_conf->autodev > 0) { if (lxc_conf->autodev > 0) {
if (mount_autodev(name, &lxc_conf->rootfs, lxcpath)) { if (mount_autodev(name, &lxc_conf->rootfs, lxcpath)) {
ERROR("failed to mount /dev in the container"); ERROR("failed to mount /dev in the container");
...@@ -3243,10 +3248,6 @@ static void lxc_remove_nic(struct lxc_list *it) ...@@ -3243,10 +3248,6 @@ static void lxc_remove_nic(struct lxc_list *it)
lxc_list_del(it); lxc_list_del(it);
free(netdev->link);
free(netdev->name);
if (netdev->type == LXC_NET_VETH)
free(netdev->priv.veth_attr.pair);
free(netdev->upscript); free(netdev->upscript);
free(netdev->downscript); free(netdev->downscript);
free(netdev->hwaddr); free(netdev->hwaddr);
...@@ -3469,17 +3470,6 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key) ...@@ -3469,17 +3470,6 @@ int lxc_clear_hooks(struct lxc_conf *c, const char *key)
return 0; return 0;
} }
static void lxc_clear_saved_nics(struct lxc_conf *conf)
{
int i;
if (!conf->saved_nics)
return;
for (i=0; i < conf->num_savednics; i++)
free(conf->saved_nics[i].orig_name);
free(conf->saved_nics);
}
static inline void lxc_clear_aliens(struct lxc_conf *conf) static inline void lxc_clear_aliens(struct lxc_conf *conf)
{ {
struct lxc_list *it,*next; struct lxc_list *it,*next;
...@@ -3533,7 +3523,6 @@ void lxc_conf_free(struct lxc_conf *conf) ...@@ -3533,7 +3523,6 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_cgroups(conf, "lxc.cgroup"); lxc_clear_cgroups(conf, "lxc.cgroup");
lxc_clear_hooks(conf, "lxc.hook"); lxc_clear_hooks(conf, "lxc.hook");
lxc_clear_mount_entries(conf); lxc_clear_mount_entries(conf);
lxc_clear_saved_nics(conf);
lxc_clear_idmaps(conf); lxc_clear_idmaps(conf);
lxc_clear_groups(conf); lxc_clear_groups(conf);
lxc_clear_includes(conf); lxc_clear_includes(conf);
......
...@@ -211,8 +211,6 @@ struct lxc_conf { ...@@ -211,8 +211,6 @@ struct lxc_conf {
struct lxc_list cgroup; struct lxc_list cgroup;
struct lxc_list id_map; struct lxc_list id_map;
struct lxc_list network; struct lxc_list network;
struct saved_nic *saved_nics;
int num_savednics;
int auto_mounts; int auto_mounts;
struct lxc_list mount_list; struct lxc_list mount_list;
struct lxc_list caps; struct lxc_list caps;
......
...@@ -764,11 +764,6 @@ static struct lxc_netdev *network_netdev(const char *key, const char *value, ...@@ -764,11 +764,6 @@ static struct lxc_netdev *network_netdev(const char *key, const char *value,
return netdev; return netdev;
} }
static int network_ifname(char **valuep, const char *value)
{
return set_config_string_item_max(valuep, value, IFNAMSIZ);
}
#ifndef MACVLAN_MODE_PRIVATE #ifndef MACVLAN_MODE_PRIVATE
#define MACVLAN_MODE_PRIVATE 1 #define MACVLAN_MODE_PRIVATE 1
#endif #endif
...@@ -870,7 +865,7 @@ static int set_config_network_link(const char *key, const char *value, ...@@ -870,7 +865,7 @@ static int set_config_network_link(const char *key, const char *value,
if (!netdev) if (!netdev)
return -1; return -1;
return network_ifname(&netdev->link, value); return network_ifname(netdev->link, value);
} }
static int set_config_network_name(const char *key, const char *value, static int set_config_network_name(const char *key, const char *value,
...@@ -882,7 +877,7 @@ static int set_config_network_name(const char *key, const char *value, ...@@ -882,7 +877,7 @@ static int set_config_network_name(const char *key, const char *value,
if (!netdev) if (!netdev)
return -1; return -1;
return network_ifname(&netdev->name, value); return network_ifname(netdev->name, value);
} }
static int set_config_network_veth_pair(const char *key, const char *value, static int set_config_network_veth_pair(const char *key, const char *value,
...@@ -899,7 +894,7 @@ static int set_config_network_veth_pair(const char *key, const char *value, ...@@ -899,7 +894,7 @@ static int set_config_network_veth_pair(const char *key, const char *value,
return -1; return -1;
} }
return network_ifname(&netdev->priv.veth_attr.pair, value); return network_ifname(netdev->priv.veth_attr.pair, value);
} }
static int set_config_network_macvlan_mode(const char *key, const char *value, static int set_config_network_macvlan_mode(const char *key, const char *value,
......
...@@ -260,6 +260,15 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) ...@@ -260,6 +260,15 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
switch (netdev->type) { switch (netdev->type) {
case LXC_NET_VETH: case LXC_NET_VETH:
TRACE("type: veth"); TRACE("type: veth");
if (netdev->priv.veth_attr.pair)
TRACE("veth pair: %s",
netdev->priv.veth_attr.pair);
if (netdev->priv.veth_attr.veth1[0] != '\0')
TRACE("veth1 : %s",
netdev->priv.veth_attr.veth1);
if (netdev->priv.veth_attr.ifindex > 0)
TRACE("host side ifindex for veth device: %d",
netdev->priv.veth_attr.ifindex);
break; break;
case LXC_NET_MACVLAN: case LXC_NET_MACVLAN:
TRACE("type: macvlan"); TRACE("type: macvlan");
...@@ -269,6 +278,10 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) ...@@ -269,6 +278,10 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
break; break;
case LXC_NET_PHYS: case LXC_NET_PHYS:
TRACE("type: phys"); TRACE("type: phys");
if (netdev->priv.phys_attr.ifindex > 0) {
TRACE("host side ifindex for phys device: %d",
netdev->priv.phys_attr.ifindex);
}
break; break;
case LXC_NET_EMPTY: case LXC_NET_EMPTY:
TRACE("type: empty"); TRACE("type: empty");
...@@ -296,3 +309,14 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf) ...@@ -296,3 +309,14 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
TRACE("downscript: %s", netdev->downscript); TRACE("downscript: %s", netdev->downscript);
} }
} }
int network_ifname(char *valuep, const char *value)
{
if (strlen(value) >= IFNAMSIZ) {
ERROR("Network devie name \"%s\" is too long (>= %zu)", value,
(size_t)IFNAMSIZ);
}
strcpy(valuep, value);
return 0;
}
...@@ -33,5 +33,6 @@ extern struct lxc_netdev *lxc_find_netdev_by_idx(struct lxc_conf *conf, ...@@ -33,5 +33,6 @@ extern struct lxc_netdev *lxc_find_netdev_by_idx(struct lxc_conf *conf,
extern struct lxc_netdev *lxc_get_netdev_by_idx(struct lxc_conf *conf, extern struct lxc_netdev *lxc_get_netdev_by_idx(struct lxc_conf *conf,
unsigned int idx); unsigned int idx);
extern void lxc_log_configured_netdevs(const struct lxc_conf *conf); extern void lxc_log_configured_netdevs(const struct lxc_conf *conf);
extern int network_ifname(char *valuep, const char *value);
#endif /* __LXC_CONFILE_UTILS_H */ #endif /* __LXC_CONFILE_UTILS_H */
...@@ -126,6 +126,47 @@ static int load_tty_major_minor(char *directory, char *output, int len) ...@@ -126,6 +126,47 @@ static int load_tty_major_minor(char *directory, char *output, int len)
return 0; return 0;
} }
static int cmp_version(const char *v1, const char *v2)
{
int ret;
int oct_v1[3], oct_v2[3];
memset(oct_v1, -1, sizeof(oct_v1));
memset(oct_v2, -1, sizeof(oct_v2));
ret = sscanf(v1, "%d.%d.%d", &oct_v1[0], &oct_v1[1], &oct_v1[2]);
if (ret < 1)
return -1;
ret = sscanf(v2, "%d.%d.%d", &oct_v2[0], &oct_v2[1], &oct_v2[2]);
if (ret < 1)
return -1;
/* Major version is greater. */
if (oct_v1[0] > oct_v2[0])
return 1;
if (oct_v1[0] < oct_v2[0])
return -1;
/* Minor number is greater.*/
if (oct_v1[1] > oct_v2[1])
return 1;
if (oct_v1[1] < oct_v2[1])
return -1;
/* Patch number is greater. */
if (oct_v1[2] > oct_v2[2])
return 1;
/* Patch numbers are equal. */
if (oct_v1[2] == oct_v2[2])
return 0;
return -1;
}
static void exec_criu(struct criu_opts *opts) static void exec_criu(struct criu_opts *opts)
{ {
char **argv, log[PATH_MAX]; char **argv, log[PATH_MAX];
...@@ -499,7 +540,7 @@ static void exec_criu(struct criu_opts *opts) ...@@ -499,7 +540,7 @@ static void exec_criu(struct criu_opts *opts)
struct lxc_netdev *n = it->elem; struct lxc_netdev *n = it->elem;
bool external_not_veth; bool external_not_veth;
if (strcmp(opts->criu_version, CRIU_EXTERNAL_NOT_VETH) >= 0) { if (cmp_version(opts->criu_version, CRIU_EXTERNAL_NOT_VETH) >= 0) {
/* Since criu version 2.8 the usage of --veth-pair /* Since criu version 2.8 the usage of --veth-pair
* has been deprecated: * has been deprecated:
* git tag --contains f2037e6d3445fc400 * git tag --contains f2037e6d3445fc400
...@@ -523,7 +564,7 @@ static void exec_criu(struct criu_opts *opts) ...@@ -523,7 +564,7 @@ static void exec_criu(struct criu_opts *opts)
case LXC_NET_VETH: case LXC_NET_VETH:
veth = n->priv.veth_attr.pair; veth = n->priv.veth_attr.pair;
if (n->link) { if (n->link[0] != '\0') {
if (external_not_veth) if (external_not_veth)
fmt = "veth[%s]:%s@%s"; fmt = "veth[%s]:%s@%s";
else else
...@@ -542,7 +583,7 @@ static void exec_criu(struct criu_opts *opts) ...@@ -542,7 +583,7 @@ static void exec_criu(struct criu_opts *opts)
goto err; goto err;
break; break;
case LXC_NET_MACVLAN: case LXC_NET_MACVLAN:
if (!n->link) { if (n->link[0] == '\0') {
ERROR("no host interface for macvlan %s", n->name); ERROR("no host interface for macvlan %s", n->name);
goto err; goto err;
} }
...@@ -764,11 +805,13 @@ static bool restore_net_info(struct lxc_container *c) ...@@ -764,11 +805,13 @@ static bool restore_net_info(struct lxc_container *c)
snprintf(template, sizeof(template), "vethXXXXXX"); snprintf(template, sizeof(template), "vethXXXXXX");
if (!netdev->priv.veth_attr.pair) if (netdev->priv.veth_attr.pair[0] == '\0' &&
netdev->priv.veth_attr.pair = lxc_mkifname(template); netdev->priv.veth_attr.veth1[0] == '\0') {
if (!lxc_mkifname(template))
if (!netdev->priv.veth_attr.pair)
goto out_unlock; goto out_unlock;
strcpy(netdev->priv.veth_attr.veth1, template);
}
} }
has_error = false; has_error = false;
......
...@@ -79,9 +79,21 @@ struct lxc_route6 { ...@@ -79,9 +79,21 @@ struct lxc_route6 {
struct in6_addr addr; struct in6_addr addr;
}; };
/* Contains information about the host side veth device.
* @pair : Name of the host side veth device.
* If the user requested that the host veth device be created with a
* specific names this field will be set. If this field is set @veth1
* is not set.
* @veth1 : Name of the host side veth device.
* If the user did not request that the host veth device be created
* with a specific name this field will be set. If this field is set
* @pair is not set.
* @ifindex : Ifindex of the network device.
*/
struct ifla_veth { struct ifla_veth {
char *pair; /* pair name */ char pair[IFNAMSIZ];
char veth1[IFNAMSIZ]; /* needed for deconf */ char veth1[IFNAMSIZ];
int ifindex;
}; };
struct ifla_vlan { struct ifla_vlan {
...@@ -95,60 +107,83 @@ struct ifla_macvlan { ...@@ -95,60 +107,83 @@ struct ifla_macvlan {
int mode; /* private, vepa, bridge, passthru */ int mode; /* private, vepa, bridge, passthru */
}; };
/* Contains information about the physical network device as seen from the host.
* @ifindex : The ifindex of the physical network device in the host's network
* namespace.
*/
struct ifla_phys {
int ifindex;
};
union netdev_p { union netdev_p {
struct ifla_macvlan macvlan_attr;
struct ifla_phys phys_attr;
struct ifla_veth veth_attr; struct ifla_veth veth_attr;
struct ifla_vlan vlan_attr; struct ifla_vlan vlan_attr;
struct ifla_macvlan macvlan_attr;
}; };
/* /*
* Defines a structure to configure a network device * Defines a structure to configure a network device
* @link : lxc.net.[i].link, name of bridge or host iface to attach if any * @idx : network counter
* @name : lxc.net.[i].name, name of iface on the container side * @ifindex : ifindex of the network device
* Note that this is the ifindex of the network device in
* the container's network namespace. If the network device
* consists of a pair of network devices (e.g. veth pairs
* attached to a network bridge) then this index cannot be
* used to identify or modify the host veth device. See
* struct ifla_veth for the host side information.
* @type : network type (veth, macvlan, vlan, ...)
* @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
* if any
* @name : lxc.net.[i].name, name of iface on the container side
* @hwaddr : mac address
* @mtu : maximum transmission unit
* @priv : information specific to the specificed network type
* Note that this is a union so whether accessing a struct
* is possible is dependent on the network type.
* @ipv4 : a list of ipv4 addresses to be set on the network device * @ipv4 : a list of ipv4 addresses to be set on the network device
* @ipv6 : a list of ipv6 addresses to be set on the network device * @ipv6 : a list of ipv6 addresses to be set on the network device
* @upscript : a script filename to be executed during interface configuration * @ipv4_gateway_auto : whether the ipv4 gateway is to be automatically gathered
* @downscript : a script filename to be executed during interface destruction * from the associated @link
* @idx : network counter * @ipv4_gateway : ipv4 gateway
* @ipv6_gateway_auto : whether the ipv6 gateway is to be automatically gathered
* from the associated @link
* @ipv6_gateway : ipv6 gateway
* @upscript : a script filename to be executed during interface
* configuration
* @downscript : a script filename to be executed during interface
* destruction
*/ */
struct lxc_netdev { struct lxc_netdev {
ssize_t idx; ssize_t idx;
int ifindex;
int type; int type;
int flags; int flags;
int ifindex; char link[IFNAMSIZ];
char *link; char name[IFNAMSIZ];
char *name;
char *hwaddr; char *hwaddr;
char *mtu; char *mtu;
union netdev_p priv; union netdev_p priv;
struct lxc_list ipv4; struct lxc_list ipv4;
struct lxc_list ipv6; struct lxc_list ipv6;
struct in_addr *ipv4_gateway;
bool ipv4_gateway_auto; bool ipv4_gateway_auto;
struct in6_addr *ipv6_gateway; struct in_addr *ipv4_gateway;
bool ipv6_gateway_auto; bool ipv6_gateway_auto;
struct in6_addr *ipv6_gateway;
char *upscript; char *upscript;
char *downscript; char *downscript;
}; };
struct saved_nic {
int ifindex;
char *orig_name;
};
/* Convert a string mac address to a socket structure. */ /* Convert a string mac address to a socket structure. */
extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr); extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr);
/* /* Move a device between namespaces. */
* Move a device between namespaces extern int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char *ifname);
*/ extern int lxc_netdev_move_by_name(const char *ifname, pid_t pid,
extern int lxc_netdev_move_by_index(int ifindex, pid_t pid, const char* ifname); const char *newname);
extern int lxc_netdev_move_by_name(const char *ifname, pid_t pid, const char* newname);
/* /* Delete a network device. */
* Delete a network device
*/
extern int lxc_netdev_delete_by_name(const char *name); extern int lxc_netdev_delete_by_name(const char *name);
extern int lxc_netdev_delete_by_index(int ifindex); extern int lxc_netdev_delete_by_index(int ifindex);
...@@ -251,19 +286,28 @@ extern int lxc_neigh_proxy_off(const char *name, int family); ...@@ -251,19 +286,28 @@ extern int lxc_neigh_proxy_off(const char *name, int family);
/* Generate a new unique network interface name. /* Generate a new unique network interface name.
* Allocated memory must be freed by caller. * Allocated memory must be freed by caller.
*/ */
extern char *lxc_mkifname(const char *template); 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_create_network_priv(struct lxc_handler *handler);
extern bool lxc_delete_network(struct lxc_handler *handler); extern int lxc_network_move_created_netdev_priv(const char *lxcpath,
char *lxcname,
struct lxc_list *network,
pid_t pid);
extern bool lxc_delete_network_priv(struct lxc_handler *handler);
extern bool lxc_delete_network_unpriv(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(const char *lxcpath, char *lxcname, extern int lxc_create_network_unpriv(const char *lxcpath, char *lxcname,
struct lxc_list *network, pid_t pid); struct lxc_list *network, pid_t pid);
extern int lxc_requests_empty_network(struct lxc_handler *handler); extern int lxc_requests_empty_network(struct lxc_handler *handler);
extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf); 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,
struct lxc_list *network); struct lxc_list *network);
extern int lxc_network_send_veth_names_to_child(struct lxc_handler *handler);
extern int lxc_network_recv_veth_names_from_parent(struct lxc_handler *handler);
extern int lxc_network_send_name_and_ifindex_to_parent(struct lxc_handler *handler);
extern int lxc_network_recv_name_and_ifindex_from_child(struct lxc_handler *handler);
#endif /* __LXC_NETWORK_H */ #endif /* __LXC_NETWORK_H */
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* *
* Authors: * Authors:
* Daniel Lezcano <daniel.lezcano at free.fr> * Daniel Lezcano <daniel.lezcano at free.fr>
* Serge Hallyn <serge@hallyn.com>
* Christian Brauner <christian.brauner@ubuntu.com>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -24,39 +26,86 @@ ...@@ -24,39 +26,86 @@
#define __LXC_START_H #define __LXC_START_H
#include <signal.h> #include <signal.h>
#include <stdbool.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <stdbool.h>
#include "conf.h" #include "conf.h"
#include "config.h" #include "config.h"
#include "state.h"
#include "namespace.h" #include "namespace.h"
#include "state.h"
struct lxc_handler { struct lxc_handler {
pid_t pid; /* The clone flags that were requested. */
char *name;
lxc_state_t state;
int clone_flags; int clone_flags;
int sigfd;
sigset_t oldmask; /* File descriptors referring to the network namespace of the container. */
struct lxc_conf *conf; int netnsfd;
struct lxc_operations *ops;
void *data; /* File descriptor to pin the rootfs for privileged containers. */
int sv[2];
int pinfd; int pinfd;
const char *lxcpath;
void *cgroup_data; /* Signal file descriptor. */
int ttysock[2]; // socketpair for child->parent tty fd passing int sigfd;
bool backgrounded; // indicates whether should we close std{in,out,err} on start
/* List of file descriptors referring to the namespaces of the
* container. Note that these are not necessarily identical to
* the "clone_flags" handler field in case namespace inheritance is
* requested.
*/
int nsfd[LXC_NS_MAX]; int nsfd[LXC_NS_MAX];
int netnsfd;
/* The socketpair() fds used to wait on successful daemonized /* Abstract unix domain SOCK_DGRAM socketpair to pass arbitrary data
* startup. * between child and parent.
*/ */
int data_sock[2];
/* The socketpair() fds used to wait on successful daemonized startup. */
int state_socket_pair[2]; int state_socket_pair[2];
/* Socketpair to synchronize processes during container creation. */
int sync_sock[2];
/* The name of the container. */
char *name;
/* The path the container is running in. */
const char *lxcpath;
/* Whether the container's startup process euid is 0. */
bool am_root;
/* Indicates whether should we close std{in,out,err} on start. */
bool backgrounded;
/* The child's pid. */
pid_t pid;
/* The signal mask prior to setting up the signal file descriptor. */
sigset_t oldmask;
/* The container's in-memory configuration. */
struct lxc_conf *conf;
/* A list of clients registered to be informed about a container state. */
struct lxc_list state_clients; struct lxc_list state_clients;
/* A set of operations to be performed at various stages of the
* container's life.
*/
struct lxc_operations *ops;
/* This holds the cgroup information. Note that the data here is
* specific to the cgroup driver used.
*/
void *cgroup_data;
/* Data to be passed to handler ops. */
void *data;
/* Current state of the container. */
lxc_state_t state;
}; };
struct lxc_operations { struct lxc_operations {
...@@ -89,8 +138,8 @@ extern void lxc_fini(const char *name, struct lxc_handler *handler); ...@@ -89,8 +138,8 @@ extern void lxc_fini(const char *name, struct lxc_handler *handler);
*/ */
extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall,
int *fds_to_ignore, size_t len_fds); int *fds_to_ignore, size_t len_fds);
int __lxc_start(const char *, struct lxc_handler *, struct lxc_operations *, extern int __lxc_start(const char *, struct lxc_handler *,
void *, const char *, bool); struct lxc_operations *, void *, const char *, bool);
extern void resolve_clone_flags(struct lxc_handler *handler); extern void resolve_clone_flags(struct lxc_handler *handler);
#endif #endif
......
...@@ -86,63 +86,63 @@ static int __sync_barrier(int fd, int sequence) ...@@ -86,63 +86,63 @@ static int __sync_barrier(int fd, int sequence)
int lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence) int lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence)
{ {
return __sync_barrier(handler->sv[0], sequence); return __sync_barrier(handler->sync_sock[0], sequence);
} }
int lxc_sync_barrier_child(struct lxc_handler *handler, int sequence) int lxc_sync_barrier_child(struct lxc_handler *handler, int sequence)
{ {
return __sync_barrier(handler->sv[1], sequence); return __sync_barrier(handler->sync_sock[1], sequence);
} }
int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence) int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
{ {
return __sync_wake(handler->sv[0], sequence); return __sync_wake(handler->sync_sock[0], sequence);
} }
int lxc_sync_wait_parent(struct lxc_handler *handler, int sequence) int lxc_sync_wait_parent(struct lxc_handler *handler, int sequence)
{ {
return __sync_wait(handler->sv[0], sequence); return __sync_wait(handler->sync_sock[0], sequence);
} }
int lxc_sync_wait_child(struct lxc_handler *handler, int sequence) int lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
{ {
return __sync_wait(handler->sv[1], sequence); return __sync_wait(handler->sync_sock[1], sequence);
} }
int lxc_sync_wake_child(struct lxc_handler *handler, int sequence) int lxc_sync_wake_child(struct lxc_handler *handler, int sequence)
{ {
return __sync_wake(handler->sv[1], sequence); return __sync_wake(handler->sync_sock[1], sequence);
} }
int lxc_sync_init(struct lxc_handler *handler) int lxc_sync_init(struct lxc_handler *handler)
{ {
int ret; int ret;
ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sv); ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sync_sock);
if (ret) { if (ret) {
SYSERROR("failed to create synchronization socketpair"); SYSERROR("failed to create synchronization socketpair");
return -1; return -1;
} }
/* Be sure we don't inherit this after the exec */ /* Be sure we don't inherit this after the exec */
fcntl(handler->sv[0], F_SETFD, FD_CLOEXEC); fcntl(handler->sync_sock[0], F_SETFD, FD_CLOEXEC);
return 0; return 0;
} }
void lxc_sync_fini_child(struct lxc_handler *handler) void lxc_sync_fini_child(struct lxc_handler *handler)
{ {
if (handler->sv[0] != -1) { if (handler->sync_sock[0] != -1) {
close(handler->sv[0]); close(handler->sync_sock[0]);
handler->sv[0] = -1; handler->sync_sock[0] = -1;
} }
} }
void lxc_sync_fini_parent(struct lxc_handler *handler) void lxc_sync_fini_parent(struct lxc_handler *handler)
{ {
if (handler->sv[1] != -1) { if (handler->sync_sock[1] != -1) {
close(handler->sv[1]); close(handler->sync_sock[1]);
handler->sv[1] = -1; handler->sync_sock[1] = -1;
} }
} }
......
...@@ -2406,3 +2406,24 @@ bool has_fs_type(const char *path, fs_type_magic magic_val) ...@@ -2406,3 +2406,24 @@ bool has_fs_type(const char *path, fs_type_magic magic_val)
return has_type; return has_type;
} }
bool lxc_nic_exists(char *nic)
{
#define __LXC_SYS_CLASS_NET_LEN 15 + IFNAMSIZ + 1
char path[__LXC_SYS_CLASS_NET_LEN];
int ret;
struct stat sb;
if (!strcmp(nic, "none"))
return true;
ret = snprintf(path, __LXC_SYS_CLASS_NET_LEN, "/sys/class/net/%s", nic);
if (ret < 0 || (size_t)ret >= __LXC_SYS_CLASS_NET_LEN)
return false;
ret = stat(path, &sb);
if (ret < 0)
return false;
return true;
}
...@@ -390,7 +390,8 @@ void *must_realloc(void *orig, size_t sz); ...@@ -390,7 +390,8 @@ void *must_realloc(void *orig, size_t sz);
/* __typeof__ should be safe to use with all compilers. */ /* __typeof__ should be safe to use with all compilers. */
typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic; typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic;
bool has_fs_type(const char *path, fs_type_magic magic_val); extern bool has_fs_type(const char *path, fs_type_magic magic_val);
bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val); extern bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val);
extern bool lxc_nic_exists(char *nic);
#endif /* __LXC_UTILS_H */ #endif /* __LXC_UTILS_H */
...@@ -92,6 +92,14 @@ configure_ubuntu() ...@@ -92,6 +92,14 @@ configure_ubuntu()
password=$5 password=$5
# configure the network using the dhcp # configure the network using the dhcp
if chroot $rootfs which netplan >/dev/null 2>&1; then
cat <<EOF > $rootfs/etc/netplan/10-lxc.yaml
network:
ethernets:
eth0: {dhcp4: true}
version: 2
EOF
else
cat <<EOF > $rootfs/etc/network/interfaces cat <<EOF > $rootfs/etc/network/interfaces
# This file describes the network interfaces available on your system # This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5). # and how to activate them. For more information, see interfaces(5).
...@@ -103,6 +111,7 @@ iface lo inet loopback ...@@ -103,6 +111,7 @@ iface lo inet loopback
auto eth0 auto eth0
iface eth0 inet dhcp iface eth0 inet dhcp
EOF EOF
fi
# set the hostname # set the hostname
cat <<EOF > $rootfs/etc/hostname cat <<EOF > $rootfs/etc/hostname
...@@ -366,7 +375,13 @@ download_ubuntu() ...@@ -366,7 +375,13 @@ download_ubuntu()
debootstrap_parameters="$debootstrap_parameters --variant=$variant" debootstrap_parameters="$debootstrap_parameters --variant=$variant"
fi fi
if [ "$variant" = 'minbase' ]; then if [ "$variant" = 'minbase' ]; then
packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client" packages_template="${packages_template},sudo"
# Newer releases use netplan, EOL releases not supported
case $release in
trusty|xenial|zesty)
packages_template="${packages_template},ifupdown,isc-dhcp-client"
;;
esac
fi fi
echo "Installing packages in template: ${packages_template}" echo "Installing packages in template: ${packages_template}"
......
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