Use the configuration structure for the network

We don't want to use anymore the configuration directory,
let's use the configuration structure.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
This commit is contained in:
Daniel Lezcano 2009-10-09 11:38:39 +02:00
parent 571e6ec89e
commit 82d5ae15e7
6 changed files with 218 additions and 630 deletions

View File

@ -63,14 +63,7 @@ lxc_log_define(lxc_conf, lxc);
#define MS_REC 16384 #define MS_REC 16384
#endif #endif
typedef int (*instanciate_cb)(const char *directory, typedef int (*instanciate_cb)(struct lxc_netdev *);
const char *file, pid_t pid);
struct netdev_conf {
const char *type;
instanciate_cb cb;
int count;
};
struct mount_opt { struct mount_opt {
char *name; char *name;
@ -78,17 +71,16 @@ struct mount_opt {
int flag; int flag;
}; };
static int instanciate_veth(const char *, const char *, pid_t); static int instanciate_veth(struct lxc_netdev *);
static int instanciate_macvlan(const char *, const char *, pid_t); static int instanciate_macvlan(struct lxc_netdev *);
static int instanciate_phys(const char *, const char *, pid_t); static int instanciate_phys(struct lxc_netdev *);
static int instanciate_empty(const char *, const char *, pid_t); static int instanciate_empty(struct lxc_netdev *);
static int unconfigure_cgroup(const char *name);
static struct netdev_conf netdev_conf[MAXCONFTYPE + 1] = { static instanciate_cb netdev_conf[MAXCONFTYPE + 1] = {
[VETH] = { "veth", instanciate_veth, 0 }, [VETH] = instanciate_veth,
[MACVLAN] = { "macvlan", instanciate_macvlan, 0, }, [MACVLAN] = instanciate_macvlan,
[PHYS] = { "phys", instanciate_phys, 0, }, [PHYS] = instanciate_phys,
[EMPTY] = { "empty", instanciate_empty, 0, }, [EMPTY] = instanciate_empty,
}; };
static struct mount_opt mount_opt[] = { static struct mount_opt mount_opt[] = {
@ -115,29 +107,6 @@ static struct mount_opt mount_opt[] = {
{ NULL, 0, 0 }, { NULL, 0, 0 },
}; };
static int write_info(const char *path, const char *file, const char *info)
{
int fd, err = -1;
char f[MAXPATHLEN];
snprintf(f, MAXPATHLEN, "%s/%s", path, file);
fd = creat(f, 0755);
if (fd < 0)
goto out;
if (write(fd, info, strlen(info)) < 0 ||
write(fd, "\n", strlen("\n") + 1) < 0)
goto out_write;
err = 0;
out:
close(fd);
return err;
out_write:
unlink(f);
goto out;
}
static int read_info(const char *path, const char *file, char *info, size_t len) static int read_info(const char *path, const char *file, char *info, size_t len)
{ {
int fd, ret = -1; int fd, ret = -1;
@ -175,204 +144,6 @@ static int delete_info(const char *path, const char *file)
return ret; return ret;
} }
static int configure_ip4addr(int fd, struct lxc_inetdev *in)
{
char addr[INET6_ADDRSTRLEN];
char bcast[INET_ADDRSTRLEN];
char line[MAXLINELEN];
int err = -1;
if (!inet_ntop(AF_INET, &in->addr, addr, sizeof(addr))) {
SYSERROR("failed to convert ipv4 address");
goto err;
}
if (!inet_ntop(AF_INET, &in->bcast, bcast, sizeof(bcast))) {
SYSERROR("failed to convert ipv4 broadcast");
goto err;
}
if (in->prefix)
snprintf(line, MAXLINELEN, "%s/%d %s\n", addr, in->prefix, bcast);
else
snprintf(line, MAXLINELEN, "%s %s\n", addr, bcast);
if (write(fd, line, strlen(line)) < 0) {
SYSERROR("failed to write address info");
goto err;
}
err = 0;
err:
return err;
}
static int configure_ip6addr(int fd, struct lxc_inet6dev *in6)
{
char addr[INET6_ADDRSTRLEN];
char line[MAXLINELEN];
int err = -1;
if (!inet_ntop(AF_INET6, &in6->addr, addr, sizeof(addr))) {
SYSERROR("failed to convert ipv4 address");
goto err;
}
snprintf(line, MAXLINELEN, "%s/%d\n", addr, in6->prefix?in6->prefix:64);
if (write(fd, line, strlen(line)) < 0) {
SYSERROR("failed to write address info");
goto err;
}
err = 0;
err:
return err;
}
static int configure_ip_address(const char *path, struct lxc_list *ip, int family)
{
char file[MAXPATHLEN];
struct lxc_list *iterator;
int fd, err = -1;
if (mkdir(path, 0755)) {
SYSERROR("failed to create directory %s", path);
return -1;
}
snprintf(file, MAXPATHLEN, "%s/addresses", path);
fd = creat(file, 0755);
if (fd < 0) {
SYSERROR("failed to create %s file", file);
goto err;
}
lxc_list_for_each(iterator, ip) {
err = family == AF_INET?
configure_ip4addr(fd, iterator->elem):
configure_ip6addr(fd, iterator->elem);
if (err)
goto err;
}
out:
close(fd);
return err;
err:
unlink(file);
rmdir(path);
goto out;
}
static int configure_netdev(const char *path, struct lxc_netdev *netdev)
{
int err = -1;
char dir[MAXPATHLEN];
if (mkdir(path, 0755)) {
SYSERROR("failed to create %s directory", path);
return -1;
}
if (netdev->ifname) {
if (write_info(path, "link", netdev->ifname))
goto out_link;
}
if (netdev->newname) {
if (write_info(path, "name", netdev->newname))
goto out_newname;
}
if (netdev->hwaddr) {
if (write_info(path, "hwaddr", netdev->hwaddr))
goto out_hwaddr;
}
if (netdev->mtu) {
if (write_info(path, "mtu", netdev->mtu))
goto out_mtu;
}
if (netdev->flags & IFF_UP) {
if (write_info(path, "up", ""))
goto out_up;
}
if (!lxc_list_empty(&netdev->ipv4)) {
snprintf(dir, MAXPATHLEN, "%s/ipv4", path);
if (configure_ip_address(dir, &netdev->ipv4, AF_INET))
goto out_ipv4;
}
if (!lxc_list_empty(&netdev->ipv6)) {
snprintf(dir, MAXPATHLEN, "%s/ipv6", path);
if (configure_ip_address(dir, &netdev->ipv6, AF_INET6))
goto out_ipv6;
}
err = 0;
out:
return err;
out_ipv6:
delete_info(path, "ipv4");
out_ipv4:
delete_info(path, "up");
out_up:
delete_info(path, "mtu");
out_mtu:
delete_info(path, "hwaddr");
out_hwaddr:
delete_info(path, "name");
out_newname:
delete_info(path, "link");
out_link:
rmdir(path);
goto out;
}
static int configure_network(const char *name, struct lxc_list *network)
{
struct lxc_list *iterator;
struct lxc_network *n;
char networkpath[MAXPATHLEN];
char path[MAXPATHLEN];
int err = -1;
if (lxc_list_empty(network))
return 0;
snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
if (mkdir(networkpath, 0755)) {
SYSERROR("failed to create %s directory", networkpath);
goto out;
}
lxc_list_for_each(iterator, network) {
n = iterator->elem;
if (n->type < 0 || n->type > MAXCONFTYPE) {
ERROR("invalid network configuration type '%d'",
n->type);
goto out;
}
snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
netdev_conf[n->type].type,
netdev_conf[n->type].count++);
if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
ERROR("failed to configure network type %s",
netdev_conf[n->type].type);
goto out;
}
}
err = 0;
out:
return err;
}
static int configure_find_fstype_cb(void* buffer, void *data) static int configure_find_fstype_cb(void* buffer, void *data)
{ {
struct cbarg { struct cbarg {
@ -977,78 +748,6 @@ out:
return ret; return ret;
} }
static int setup_ipv4_addr_cb(void *buffer, void *data)
{
char *ifname = data;
char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
int p = 24;
addr = buffer;
cursor = strstr(addr, " ");
if (cursor) {
*cursor = '\0';
bcast = cursor + 1;
cursor = strstr(bcast, "\n");
if (cursor)
*cursor = '\0';
}
slash = strstr(addr, "/");
if (slash) {
*slash = '\0';
prefix = slash + 1;
}
if (prefix)
p = atoi(prefix);
if (lxc_ip_addr_add(ifname, addr, p, bcast)) {
ERROR("failed to set %s to addr %s/%d %s", ifname,
addr, p, bcast?bcast:"");
return -1;
}
DEBUG("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
return 0;
}
static int setup_ipv6_addr_cb(void *buffer, void *data)
{
char *ifname = data;
char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
int p = 24;
addr = buffer;
cursor = strstr(addr, " ");
if (cursor) {
*cursor = '\0';
bcast = cursor + 1;
cursor = strstr(bcast, "\n");
if (cursor)
*cursor = '\0';
}
slash = strstr(addr, "/");
if (slash) {
*slash = '\0';
prefix = slash + 1;
}
if (prefix)
p = atoi(prefix);
if (lxc_ip6_addr_add(ifname, addr, p, bcast)) {
ERROR("failed to set %s to addr %s/%d %s", ifname,
addr, p, bcast?bcast:"");
return -1;
}
INFO("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
return 0;
}
static int setup_hw_addr(char *hwaddr, const char *ifname) static int setup_hw_addr(char *hwaddr, const char *ifname)
{ {
struct sockaddr sockaddr; struct sockaddr sockaddr;
@ -1079,71 +778,71 @@ static int setup_hw_addr(char *hwaddr, const char *ifname)
return ret; return ret;
} }
static int setup_ip_addr(const char *directory, const char *ifname) static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
{ {
char path[MAXPATHLEN], line[MAXLINELEN]; struct lxc_list *iterator;
struct stat s; struct lxc_inetdev *inetdev;
int ret = 0;
snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", directory); lxc_list_for_each(iterator, ip) {
if (!stat(path, &s))
ret = lxc_file_for_each_line(path, setup_ipv4_addr_cb, inetdev = iterator->elem;
line, MAXPATHLEN, (void*)ifname);
return ret; if (lxc_ip_addr_add(ifindex, inetdev->addr,
inetdev->prefix, inetdev->bcast)) {
return -1;
}
}
return 0;
} }
static int setup_ip6_addr(const char *directory, const char *ifname) static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
{ {
char path[MAXPATHLEN], line[MAXLINELEN]; struct lxc_list *iterator;
struct stat s; struct lxc_inet6dev *inet6dev;
int ret = 0;
snprintf(path, MAXLINELEN, "%s/ipv6/addresses", directory); lxc_list_for_each(iterator, ip) {
if (!stat(path, &s))
ret = lxc_file_for_each_line(path, setup_ipv6_addr_cb, inet6dev = iterator->elem;
line, MAXPATHLEN, (void*)ifname);
return ret; if (lxc_ip6_addr_add(ifindex, inet6dev->addr,
inet6dev->prefix, inet6dev->bcast)) {
return -1;
}
}
return 0;
} }
static int setup_network_cb(const char *name, const char *directory, static int setup_netdev(struct lxc_netdev *netdev)
const char *file, void *data)
{ {
char path[MAXPATHLEN];
char strindex[MAXINDEXLEN];
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
char newname[IFNAMSIZ];
char hwaddr[MAXHWLEN];
char *current_ifname = ifname; char *current_ifname = ifname;
int ifindex;
snprintf(path, MAXPATHLEN, "%s/%s", directory, file); /* empty network namespace */
if (!netdev->ifindex) {
if (read_info(path, "ifindex", strindex, sizeof(strindex))) { if (netdev->flags | IFF_UP) {
ERROR("failed to read ifindex info"); if (lxc_device_up("lo")) {
return -1; ERROR("failed to set the loopback up");
return -1;
}
return 0;
}
} }
ifindex = atoi(strindex); /* retrieve the name of the interface */
if (!ifindex) { if (!if_indextoname(netdev->ifindex, current_ifname)) {
if (!read_info(path, "up", strindex, sizeof(strindex)))
if (lxc_device_up("lo")) {
ERROR("failed to set the loopback up");
return -1;
}
return 0;
}
if (!if_indextoname(ifindex, current_ifname)) {
ERROR("no interface corresponding to index '%d'", ERROR("no interface corresponding to index '%d'",
ifindex); netdev->ifindex);
return -1; return -1;
} }
/* default: let the system to choose one interface name */ /* default: let the system to choose one interface name */
if (read_info(path, "name", newname, sizeof(newname))) if (!netdev->newname)
strcpy(newname, "eth%d"); netdev->newname = "eth%d";
if (lxc_device_rename(ifname, newname)) { /* rename the interface name */
if (lxc_device_rename(ifname, netdev->newname)) {
ERROR("failed to rename %s->%s", ifname, current_ifname); ERROR("failed to rename %s->%s", ifname, current_ifname);
return -1; return -1;
} }
@ -1151,33 +850,37 @@ static int setup_network_cb(const char *name, const char *directory,
/* Re-read the name of the interface because its name has changed /* Re-read the name of the interface because its name has changed
* and would be automatically allocated by the system * and would be automatically allocated by the system
*/ */
if (!if_indextoname(ifindex, current_ifname)) { if (!if_indextoname(netdev->ifindex, current_ifname)) {
ERROR("no interface corresponding to index '%d'", ERROR("no interface corresponding to index '%d'",
ifindex); netdev->ifindex);
return -1; return -1;
} }
if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) { /* set a mac address */
if (setup_hw_addr(hwaddr, current_ifname)) { if (netdev->hwaddr) {
if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
ERROR("failed to setup hw address for '%s'", ERROR("failed to setup hw address for '%s'",
current_ifname); current_ifname);
return -1; return -1;
} }
} }
if (setup_ip_addr(path, current_ifname)) { /* setup ipv4 addresses on the interface */
if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
ERROR("failed to setup ip addresses for '%s'", ERROR("failed to setup ip addresses for '%s'",
ifname); ifname);
return -1; return -1;
} }
if (setup_ip6_addr(path, current_ifname)) { /* setup ipv6 addresses on the interface */
if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
ERROR("failed to setup ipv6 addresses for '%s'", ERROR("failed to setup ipv6 addresses for '%s'",
ifname); ifname);
return -1; return -1;
} }
if (!read_info(path, "up", strindex, sizeof(strindex))) { /* set the network device up */
if (netdev->flags | IFF_UP) {
if (lxc_device_up(current_ifname)) { if (lxc_device_up(current_ifname)) {
ERROR("failed to set '%s' up", current_ifname); ERROR("failed to set '%s' up", current_ifname);
return -1; return -1;
@ -1195,16 +898,23 @@ static int setup_network_cb(const char *name, const char *directory,
return 0; return 0;
} }
static int setup_network(const char *name) static int setup_network(struct lxc_list *networks)
{ {
char directory[MAXPATHLEN]; struct lxc_list *iterator;
int ret; struct lxc_network *network;
struct lxc_netdev *netdev;
snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name); lxc_list_for_each(iterator, networks) {
ret = lxc_dir_for_each(name, directory, setup_network_cb, NULL); network = iterator->elem;
if (ret)
return ret; netdev = lxc_list_first_elem(&network->netdev);
if (setup_netdev(netdev)) {
ERROR("failed to setup netdev");
return -1;
}
}
INFO("network has been setup"); INFO("network has been setup");
@ -1250,14 +960,6 @@ int lxc_conf_init(struct lxc_conf *conf)
int lxc_configure(const char *name, struct lxc_conf *conf) int lxc_configure(const char *name, struct lxc_conf *conf)
{ {
if (!conf)
return 0;
if (configure_network(name, &conf->networks)) {
ERROR("failed to configure the network");
return -1;
}
return 0; return 0;
} }
@ -1287,263 +989,173 @@ int lxc_unconfigure(const char *name)
return 0; return 0;
} }
static int instanciate_veth(const char *directory, const char *file, pid_t pid) static int instanciate_veth(struct lxc_netdev *netdev)
{ {
char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL; char veth1[IFNAMSIZ];
char bridge[IFNAMSIZ]; char veth2[IFNAMSIZ];
char strmtu[MAXMTULEN]; int ret = -1;
int ifindex, mtu = 0, ret = -1;
if (!asprintf(&veth1, "%s_%d", file, pid) || snprintf(veth1, sizeof(veth1), "vethXXXXXX");
!asprintf(&veth2, "%s~%d", file, pid) || snprintf(veth2, sizeof(veth2), "vethXXXXXX");
!asprintf(&path, "%s/%s", directory, file)) {
SYSERROR("failed to allocate memory");
goto out;
}
if (read_info(path, "link", bridge, IFNAMSIZ)) { mktemp(veth1);
ERROR("failed to read bridge info"); mktemp(veth2);
goto out;
if (!strlen(veth1) || !strlen(veth2)) {
ERROR("failed to allocate a temporary name");
return -1;
} }
if (lxc_veth_create(veth1, veth2)) { if (lxc_veth_create(veth1, veth2)) {
ERROR("failed to create %s-%s/%s", veth1, veth2, bridge); ERROR("failed to create %s-%s/%s",
veth1, veth2, netdev->ifname);
goto out; goto out;
} }
if (!read_info(path, "mtu", strmtu, MAXMTULEN)) { if (netdev->mtu) {
if (sscanf(strmtu, "%u", &mtu) < 1) { if (lxc_device_set_mtu(veth1, atoi(netdev->mtu))) {
ERROR("invalid mtu size '%d'", mtu); ERROR("failed to set mtu '%s' for '%s'",
netdev->mtu, veth1);
goto out_delete; goto out_delete;
} }
if (lxc_device_set_mtu(veth1, mtu)) { if (lxc_device_set_mtu(veth2, atoi(netdev->mtu))) {
ERROR("failed to set mtu for '%s'", veth1); ERROR("failed to set mtu '%s' for '%s'",
goto out_delete; netdev->mtu, veth2);
}
if (lxc_device_set_mtu(veth2, mtu)) {
ERROR("failed to set mtu for '%s'", veth2);
goto out_delete; goto out_delete;
} }
} }
if (lxc_bridge_attach(bridge, veth1)) { if (lxc_bridge_attach(netdev->ifname, veth1)) {
ERROR("failed to attach '%s' to the bridge '%s'", ERROR("failed to attach '%s' to the bridge '%s'",
veth1, bridge); veth1, netdev->ifname);
goto out_delete; goto out_delete;
} }
ifindex = if_nametoindex(veth2); netdev->ifindex = if_nametoindex(veth2);
if (!ifindex) { if (!netdev->ifindex) {
ERROR("failed to retrieve the index for %s", veth2); ERROR("failed to retrieve the index for %s", veth2);
goto out_delete; goto out_delete;
} }
if (!asprintf(&strindex, "%d", ifindex)) { if (netdev->flags & IFF_UP) {
SYSERROR("failed to allocate memory");
goto out_delete;
}
if (write_info(path, "ifindex", strindex)) {
ERROR("failed to write interface index to %s", path);
goto out_delete;
}
if (!read_info(path, "up", strindex, sizeof(strindex))) {
if (lxc_device_up(veth1)) { if (lxc_device_up(veth1)) {
ERROR("failed to set %s up", veth1); ERROR("failed to set %s up", veth1);
goto out_delete; goto out_delete;
} }
} }
DEBUG("instanciated veth '%s/%s', index is '%d'",
veth1, veth2, netdev->ifindex);
ret = 0; ret = 0;
out: out:
free(path);
free(strindex);
free(veth1);
free(veth2);
return ret; return ret;
out_delete: out_delete:
lxc_device_delete(veth1); lxc_device_delete(veth1);
goto out; goto out;
} }
static int instanciate_macvlan(const char *directory, const char *file, pid_t pid) static int instanciate_macvlan(struct lxc_netdev *netdev)
{ {
char path[MAXPATHLEN], *strindex = NULL, *peer = NULL; char peer[IFNAMSIZ];
char link[IFNAMSIZ];
int ifindex, ret = -1;
if (!asprintf(&peer, "%s~%d", file, pid)) {
SYSERROR("failed to allocate memory");
return -1;
}
snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
if (read_info(path, "link", link, IFNAMSIZ)) {
ERROR("failed to read bridge info");
goto out;
}
if (lxc_macvlan_create(link, peer)) {
ERROR("failed to create macvlan interface '%s' on '%s'",
peer, link);
goto out;
}
ifindex = if_nametoindex(peer);
if (!ifindex) {
ERROR("failed to retrieve the index for %s", peer);
goto out;
}
if (!asprintf(&strindex, "%d", ifindex)) {
SYSERROR("failed to allocate memory");
return -1;
}
if (write_info(path, "ifindex", strindex)) {
ERROR("failed to write interface index to %s", path);
goto out;
}
ret = 0;
out:
free(strindex);
free(peer);
return ret;
}
static int instanciate_phys(const char *directory, const char *file, pid_t pid)
{
char path[MAXPATHLEN], *strindex = NULL;
char link[IFNAMSIZ];
int ifindex, ret = -1;
snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
if (read_info(path, "link", link, IFNAMSIZ)) {
ERROR("failed to read link info");
goto out;
}
ifindex = if_nametoindex(link);
if (!ifindex) {
ERROR("failed to retrieve the index for %s", link);
goto out;
}
if (!asprintf(&strindex, "%d", ifindex)) {
SYSERROR("failed to allocate memory");
return -1;
}
if (write_info(path, "ifindex", strindex)) {
ERROR("failed to write interface index to %s", path);
goto out;
}
ret = 0;
out:
free(strindex);
return ret;
}
static int instanciate_empty(const char *directory, const char *file, pid_t pid)
{
char path[MAXPATHLEN], *strindex = NULL;
int ret = -1; int ret = -1;
snprintf(path, MAXPATHLEN, "%s/%s", directory, file); snprintf(peer, sizeof(peer), "mcXXXXXX");
if (!asprintf(&strindex, "%d", 0)) {
ERROR("not enough memory"); mktemp(peer);
if (!strlen(peer)) {
ERROR("failed to make a temporary name");
return -1; return -1;
} }
if (write_info(path, "ifindex", strindex)) { if (lxc_macvlan_create(netdev->ifname, peer)) {
ERROR("failed to write interface index to %s", path); ERROR("failed to create macvlan interface '%s' on '%s'",
peer, netdev->ifname);
goto out; goto out;
} }
netdev->ifindex = if_nametoindex(peer);
if (!netdev->ifindex) {
ERROR("failed to retrieve the index for %s", peer);
goto out_delete;
}
DEBUG("instanciated macvlan '%s', index is '%d'", peer, netdev->ifindex);
ret = 0; ret = 0;
out: out:
free(strindex);
return ret; return ret;
out_delete:
lxc_device_delete(peer);
goto out;
} }
static int instanciate_netdev_cb(const char *name, const char *directory, static int instanciate_phys(struct lxc_netdev *netdev)
const char *file, void *data)
{ {
pid_t *pid = data; netdev->ifindex = if_nametoindex(netdev->ifname);
if (!netdev->ifindex) {
if (!strncmp("veth", file, strlen("veth"))) ERROR("failed to retrieve the index for %s", netdev->ifname);
return instanciate_veth(directory, file, *pid);
else if (!strncmp("macvlan", file, strlen("macvlan")))
return instanciate_macvlan(directory, file, *pid);
else if (!strncmp("phys", file, strlen("phys")))
return instanciate_phys(directory, file, *pid);
else if (!strncmp("empty", file, strlen("empty")))
return instanciate_empty(directory, file, *pid);
return -1;
}
static int instanciate_netdev(const char *name, pid_t pid)
{
char directory[MAXPATHLEN];
snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
return lxc_dir_for_each(name, directory, instanciate_netdev_cb, &pid);
}
static int move_netdev_cb(const char *name, const char *directory,
const char *file, void *data)
{
char path[MAXPATHLEN], ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
pid_t *pid = data;
int ifindex;
snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
ERROR("failed to read index to from %s", path);
return -1;
}
ifindex = atoi(strindex);
if (!ifindex)
return 0;
if (!if_indextoname(ifindex, ifname)) {
ERROR("interface with index %d does not exist",
ifindex);
return -1;
}
if (lxc_device_move(ifname, *pid)) {
ERROR("failed to move %s to %d", ifname, *pid);
return -1; return -1;
} }
return 0; return 0;
} }
static int move_netdev(const char *name, pid_t pid) static int instanciate_empty(struct lxc_netdev *netdev)
{ {
char directory[MAXPATHLEN]; netdev->ifindex = 0;
snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name); return 0;
return lxc_dir_for_each(name, directory, move_netdev_cb, &pid);
} }
int conf_create_network(const char *name, pid_t pid) int lxc_create_network(struct lxc_list *networks)
{ {
if (instanciate_netdev(name, pid)) { struct lxc_list *iterator;
ERROR("failed to instantiate the network devices"); struct lxc_network *network;
return -1; struct lxc_netdev *netdev;
lxc_list_for_each(iterator, networks) {
network = iterator->elem;
if (network->type < 0 || network->type > MAXCONFTYPE) {
ERROR("invalid network configuration type '%d'",
network->type);
return -1;
}
netdev = lxc_list_first_elem(&network->netdev);
if (netdev_conf[network->type](netdev)) {
ERROR("failed to create netdev");
return -1;
}
} }
if (move_netdev(name, pid)) { return 0;
ERROR("failed to move the netdev to the container"); }
return -1;
int lxc_assign_network(struct lxc_list *networks, pid_t pid)
{
struct lxc_list *iterator;
struct lxc_network *network;
struct lxc_netdev *netdev;
lxc_list_for_each(iterator, networks) {
network = iterator->elem;
netdev = lxc_list_first_elem(&network->netdev);
if (lxc_device_move(netdev->ifindex, pid)) {
ERROR("failed to move '%s' to the container",
netdev->ifname);
return -1;
}
DEBUG("move '%s' to '%d'", netdev->ifname, pid);
} }
return 0; return 0;
@ -1627,7 +1239,7 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
return -1; return -1;
} }
if (!lxc_list_empty(&lxc_conf->networks) && setup_network(name)) { if (setup_network(&lxc_conf->networks)) {
ERROR("failed to setup the network for '%s'", name); ERROR("failed to setup the network for '%s'", name);
return -1; return -1;
} }

View File

@ -76,6 +76,7 @@ struct lxc_route6 {
*/ */
struct lxc_netdev { struct lxc_netdev {
int flags; int flags;
int ifindex;
char *ifname; char *ifname;
char *newname; char *newname;
char *hwaddr; char *hwaddr;
@ -168,9 +169,8 @@ extern int lxc_configure(const char *name, struct lxc_conf *conf);
*/ */
extern int lxc_unconfigure(const char *name); extern int lxc_unconfigure(const char *name);
extern int conf_create_network(const char *name, pid_t pid); extern int lxc_create_network(struct lxc_list *networks);
extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
extern int conf_destroy_network(const char *name);
extern int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info); extern int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info);
extern void lxc_delete_tty(struct lxc_tty_info *tty_info); extern void lxc_delete_tty(struct lxc_tty_info *tty_info);

View File

@ -114,6 +114,7 @@ static int config_network_type(const char *key, char *value, struct lxc_conf *lx
return -1; return -1;
} }
memset(netdev, 0, sizeof(*netdev));
lxc_list_init(&netdev->ipv4); lxc_list_init(&netdev->ipv4);
lxc_list_init(&netdev->ipv6); lxc_list_init(&netdev->ipv6);
lxc_list_init(&netdev->route4); lxc_list_init(&netdev->route4);

View File

@ -81,31 +81,23 @@ struct ip_req {
struct ifaddrmsg ifa; struct ifaddrmsg ifa;
}; };
int lxc_device_move(const char *name, pid_t pid) int lxc_device_move(int ifindex, pid_t pid)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct nlmsg *nlmsg = NULL; struct nlmsg *nlmsg = NULL;
struct link_req *link_req; struct link_req *link_req;
int index, len, err = -1; int len, err = -1;
if (netlink_open(&nlh, NETLINK_ROUTE)) if (netlink_open(&nlh, NETLINK_ROUTE))
return -1; return -1;
len = strlen(name);
if (len == 1 || len > IFNAMSIZ)
goto out;
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; goto out;
index = if_nametoindex(name);
if (!index)
goto out;
link_req = (struct link_req *)nlmsg; link_req = (struct link_req *)nlmsg;
link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_family = AF_UNSPEC;
link_req->ifinfomsg.ifi_index = index; link_req->ifinfomsg.ifi_index = ifindex;
nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK;
nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
@ -113,9 +105,6 @@ int lxc_device_move(const char *name, pid_t pid)
if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid)) if (nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
goto out; goto out;
if (nla_put_string(nlmsg, IFLA_IFNAME, name))
goto out;
if (netlink_transaction(&nlh, nlmsg, nlmsg)) if (netlink_transaction(&nlh, nlmsg, nlmsg))
goto out; goto out;
@ -576,25 +565,17 @@ int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr)
return 0; return 0;
} }
int lxc_ip_addr_add(const char *ifname, const char *addr, int lxc_ip_addr_add(int ifindex, struct in_addr in_addr,
int prefix, const char *bcast) int prefix, struct in_addr in_bcast)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct in_addr in_addr;
/* struct in_addr in_bcast; */
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct ip_req *ip_req; struct ip_req *ip_req;
int ifindex, err = -1; int err = -1;
if (netlink_open(&nlh, NETLINK_ROUTE)) if (netlink_open(&nlh, NETLINK_ROUTE))
return -1; return -1;
if (inet_pton(AF_INET, addr, (void *)&in_addr) < 0)
goto out;
/* if (inet_pton(AF_INET, bcast, (void *)&in_bcast) < 0) */
/* goto out; */
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; goto out;
@ -603,10 +584,6 @@ int lxc_ip_addr_add(const char *ifname, const char *addr,
if (!answer) if (!answer)
goto out; goto out;
ifindex = if_nametoindex(ifname);
if (!ifindex)
goto out;
ip_req = (struct ip_req *)nlmsg; ip_req = (struct ip_req *)nlmsg;
ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_flags = ip_req->nlmsg.nlmsghdr.nlmsg_flags =
@ -639,26 +616,17 @@ out:
return err; return err;
} }
int lxc_ip6_addr_add(const char *ifname, const char *addr, int lxc_ip6_addr_add(int ifindex, struct in6_addr in6_addr,
int prefix, const char *bcast) int prefix, struct in6_addr in6_bcast)
{ {
struct nl_handler nlh; struct nl_handler nlh;
struct in6_addr in6_addr;
/* struct in6_addr in6_bcast; */
struct nlmsg *nlmsg = NULL, *answer = NULL; struct nlmsg *nlmsg = NULL, *answer = NULL;
struct ip_req *ip_req; struct ip_req *ip_req;
int ifindex, err = -1; int err = -1;
if (netlink_open(&nlh, NETLINK_ROUTE)) if (netlink_open(&nlh, NETLINK_ROUTE))
return -1; return -1;
if (inet_pton(AF_INET6, addr, (void *)&in6_addr) < 0)
goto out;
/* if (inet_pton(AF_INET6, bcast, (void *)&in6_bcast) < 0) */
/* goto out; */
nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
if (!nlmsg) if (!nlmsg)
goto out; goto out;
@ -667,10 +635,6 @@ int lxc_ip6_addr_add(const char *ifname, const char *addr,
if (!answer) if (!answer)
goto out; goto out;
ifindex = if_nametoindex(ifname);
if (!ifindex)
goto out;
ip_req = (struct ip_req *)nlmsg; ip_req = (struct ip_req *)nlmsg;
ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); ip_req->nlmsg.nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
ip_req->nlmsg.nlmsghdr.nlmsg_flags = ip_req->nlmsg.nlmsghdr.nlmsg_flags =

View File

@ -31,7 +31,7 @@ extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr);
/* /*
* Move a device between namespaces * Move a device between namespaces
*/ */
extern int lxc_device_move(const char *name, pid_t pid); extern int lxc_device_move(int ifindex, pid_t pid);
/* /*
* Delete a network device * Delete a network device
@ -81,11 +81,11 @@ extern int lxc_ip_forward_off(const char *name, int family);
/* /*
* Set ip address * Set ip address
*/ */
extern int lxc_ip_addr_add(const char *ifname, const char *addr, extern int lxc_ip_addr_add(int ifindex, struct in_addr addr,
int prefix, const char *bcast); int prefix, struct in_addr bcast);
extern int lxc_ip6_addr_add(const char *ifname, const char *addr, extern int lxc_ip6_addr_add(int ifindex, struct in6_addr addr,
int prefix, const char *bcast); int prefix, struct in6_addr bcast);
/* /*
* Attach an interface to the bridge * Attach an interface to the bridge

View File

@ -425,9 +425,19 @@ int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
} }
clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS; clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
if (conf_has_network(name)) if (!lxc_list_empty(&handler->conf.networks)) {
clone_flags |= CLONE_NEWNET; clone_flags |= CLONE_NEWNET;
/* that should be done before the clone because we will
* fill the netdev index and use them in the child
*/
if (lxc_create_network(&handler->conf.networks)) {
ERROR("failed to create the network");
goto out_close;
}
}
/* Create a process in a new set of namespaces */ /* Create a process in a new set of namespaces */
handler->pid = lxc_clone(do_start, &start_arg, clone_flags); handler->pid = lxc_clone(do_start, &start_arg, clone_flags);
if (handler->pid < 0) { if (handler->pid < 0) {
@ -447,10 +457,11 @@ int lxc_spawn(const char *name, struct lxc_handler *handler, char *const argv[])
goto out_abort; goto out_abort;
/* Create the network configuration */ /* Create the network configuration */
if (clone_flags & CLONE_NEWNET && if (clone_flags & CLONE_NEWNET) {
conf_create_network(name, handler->pid)) { if (lxc_assign_network(&handler->conf.networks, handler->pid)) {
ERROR("failed to create the configured network"); ERROR("failed to create the configured network");
goto out_abort; goto out_abort;
}
} }
/* Tell the child to continue its initialization */ /* Tell the child to continue its initialization */