* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include "../include/netns_ifaddrs.h"
#include "af_unix.h"
#include "conf.h"
#include "config.h"
+#include "file_utils.h"
#include "log.h"
+#include "macro.h"
+#include "memory_utils.h"
#include "network.h"
#include "nl.h"
+#include "raw_syscalls.h"
+#include "syscall_wrappers.h"
#include "utils.h"
-#if HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#else
-#include <../include/ifaddrs.h>
-#endif
-
#ifndef HAVE_STRLCPY
#include "include/strlcpy.h"
#endif
-#ifndef IFLA_LINKMODE
-#define IFLA_LINKMODE 17
-#endif
-
-#ifndef IFLA_LINKINFO
-#define IFLA_LINKINFO 18
-#endif
-
-#ifndef IFLA_NET_NS_PID
-#define IFLA_NET_NS_PID 19
-#endif
-
-#ifndef IFLA_INFO_KIND
-#define IFLA_INFO_KIND 1
-#endif
-
-#ifndef IFLA_VLAN_ID
-#define IFLA_VLAN_ID 1
-#endif
-
-#ifndef IFLA_INFO_DATA
-#define IFLA_INFO_DATA 2
-#endif
-
-#ifndef VETH_INFO_PEER
-#define VETH_INFO_PEER 1
-#endif
-
-#ifndef IFLA_MACVLAN_MODE
-#define IFLA_MACVLAN_MODE 1
-#endif
-
-lxc_log_define(lxc_network, lxc);
+lxc_log_define(network, lxc);
typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
}
- snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
+ err = snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
+ if (err < 0 || (size_t)err >= sizeof(veth2buf))
+ return -1;
+
veth2 = lxc_mkifname(veth2buf);
if (!veth2)
goto out_delete;
err = lxc_veth_create(veth1, veth2);
if (err) {
- ERROR("Failed to create veth pair \"%s\" and \"%s\": %s", veth1,
- veth2, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1, veth2);
goto out_delete;
}
* of a container */
err = setup_private_host_hw_addr(veth1);
if (err) {
- ERROR("Failed to change mac address of host interface \"%s\": %s",
- veth1, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to change mac address of host interface \"%s\"", veth1);
goto out_delete;
}
err = lxc_netdev_set_mtu(veth1, mtu);
if (!err)
err = lxc_netdev_set_mtu(veth2, mtu);
+
if (err) {
- ERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
- "and \"%s\": %s",
- mtu, veth1, veth2, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
+ "and \"%s\"", mtu, veth1, veth2);
goto out_delete;
}
}
if (netdev->link[0] != '\0') {
err = lxc_bridge_attach(netdev->link, veth1);
if (err) {
- ERROR("Failed to attach \"%s\" to bridge \"%s\": %s",
- veth1, netdev->link, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to attach \"%s\" to bridge \"%s\"",
+ veth1, netdev->link);
goto out_delete;
}
INFO("Attached \"%s\" to bridge \"%s\"", veth1, netdev->link);
err = lxc_netdev_up(veth1);
if (err) {
- ERROR("Failed to set \"%s\" up: %s", veth1, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set \"%s\" up", veth1);
goto out_delete;
}
err = lxc_macvlan_create(netdev->link, peer,
netdev->priv.macvlan_attr.mode);
if (err) {
- ERROR("Failed to create macvlan interface \"%s\" on \"%s\": %s",
- peer, netdev->link, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to create macvlan interface \"%s\" on \"%s\"",
+ peer, netdev->link);
goto on_error;
}
err = lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid);
if (err) {
- ERROR("Failed to create vlan interface \"%s\" on \"%s\": %s",
- peer, netdev->link, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to create vlan interface \"%s\" on \"%s\"",
+ peer, netdev->link);
return -1;
}
netdev->name[0] != '\0' ? netdev->name : "(null)");
return -1;
}
+
err = lxc_netdev_set_mtu(peer, mtu);
if (err) {
- ERROR("Failed to set mtu \"%s\" for \"%s\": %s",
- netdev->mtu, peer, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set mtu \"%s\" for \"%s\"",
+ netdev->mtu, peer);
lxc_netdev_delete_by_name(peer);
return -1;
}
#define PHYSNAME "/sys/class/net/%s/phy80211/name"
static char *is_wlan(const char *ifname)
{
+ __do_free char *path;
int i, ret;
long physlen;
size_t len;
- char *path;
FILE *f;
char *physname = NULL;
len = strlen(ifname) + strlen(PHYSNAME) - 1;
- path = alloca(len + 1);
+ path = must_realloc(NULL, len + 1);
ret = snprintf(path, len, PHYSNAME, ifname);
if (ret < 0 || (size_t)ret >= len)
goto bad;
if (err < 0)
goto out;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
do {
/* Restore the answer buffer length, it might have been
* overwritten by a previous receive.
}
} while (readmore);
+#pragma GCC diagnostic pop
+
/* If we end up here, we didn't find any result, so signal an error. */
err = -1;
if (fd < 0)
return -errno;
- if (write(fd, value, strlen(value)) < 0)
+ if (lxc_write_nointr(fd, value, strlen(value)) < 0)
err = -errno;
close(fd);
static int neigh_proxy_set(const char *ifname, int family, int flag)
{
int ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
if (family != AF_INET && family != AF_INET6)
return -EINVAL;
- ret = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/%s",
+ ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
family == AF_INET ? "ipv4" : "ipv6", ifname,
family == AF_INET ? "proxy_arp" : "proxy_ndp");
- if (ret < 0 || (size_t)ret >= MAXPATHLEN)
+ if (ret < 0 || (size_t)ret >= PATH_MAX)
return -E2BIG;
return proc_sys_net_write(path, flag ? "1" : "0");
* the given RTM_NEWADDR message. Allocates memory for the address and stores
* that pointer in *res (so res should be an in_addr** or in6_addr**).
*/
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
static int ifa_get_local_ip(int family, struct nlmsghdr *msg, void **res)
{
int addrlen;
return 0;
}
+#pragma GCC diagnostic pop
+
static int ip_addr_get(int family, int ifindex, void **res)
{
int answer_len, err;
if (err < 0)
goto out;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+
do {
/* Restore the answer buffer length, it might have been
* overwritten by a previous receive.
}
} while (readmore);
+#pragma GCC diagnostic pop
+
/* If we end up here, we didn't find any result, so signal an
* error.
*/
int lxc_ovs_delete_port(const char *bridge, const char *nic)
{
int ret;
- char cmd_output[MAXPATHLEN];
+ char cmd_output[PATH_MAX];
struct ovs_veth_args args;
args.bridge = bridge;
static int lxc_ovs_attach_bridge(const char *bridge, const char *nic)
{
int ret;
- char cmd_output[MAXPATHLEN];
+ char cmd_output[PATH_MAX];
struct ovs_veth_args args;
args.bridge = bridge;
char *lxc_mkifname(char *template)
{
int ret;
- unsigned int seed;
- FILE *urandom;
- struct ifaddrs *ifa, *ifaddr;
+ struct netns_ifaddrs *ifa, *ifaddr;
char name[IFNAMSIZ];
bool exists = false;
size_t i = 0;
+#ifdef HAVE_RAND_R
+ unsigned int seed;
+
+ seed = randseed(false);
+#else
+
+ (void)randseed(true);
+#endif
if (strlen(template) >= IFNAMSIZ)
return NULL;
/* Get all the network interfaces. */
- ret = getifaddrs(&ifaddr);
+ ret = netns_getifaddrs(&ifaddr, -1, &(bool){false});
if (ret < 0) {
- ERROR("%s - Failed to get network interfaces", strerror(errno));
+ SYSERROR("Failed to get network interfaces");
return NULL;
}
- /* Initialize the random number generator. */
- urandom = fopen("/dev/urandom", "r");
- if (urandom != NULL) {
- if (fread(&seed, sizeof(seed), 1, urandom) <= 0)
- seed = time(0);
- fclose(urandom);
- } else {
- seed = time(0);
- }
-
-#ifndef HAVE_RAND_R
- srand(seed);
-#endif
-
/* Generate random names until we find one that doesn't exist. */
while (true) {
name[0] = '\0';
- strcpy(name, template);
+ (void)strlcpy(name, template, IFNAMSIZ);
exists = false;
+
for (i = 0; i < strlen(name); i++) {
if (name[i] == 'X') {
#ifdef HAVE_RAND_R
- name[i] = padchar[rand_r(&seed) % (strlen(padchar) - 1)];
+ name[i] = padchar[rand_r(&seed) % strlen(padchar)];
#else
- name[i] = padchar[rand() % (strlen(padchar) - 1)];
+ name[i] = padchar[rand() % strlen(padchar)];
#endif
}
}
break;
}
- freeifaddrs(ifaddr);
- return strcpy(template, name);
+ netns_freeifaddrs(ifaddr);
+ (void)strlcpy(template, name, strlen(template) + 1);
+
+ return template;
}
int setup_private_host_hw_addr(char *veth1)
#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname,
- struct lxc_netdev *netdev, pid_t pid)
+ struct lxc_netdev *netdev, pid_t pid, unsigned int hooks_version)
{
int ret;
pid_t child;
int bytes, pipefd[2];
char *token, *saveptr = NULL;
char netdev_link[IFNAMSIZ];
- char buffer[MAXPATHLEN] = {0};
+ char buffer[PATH_MAX] = {0};
+ size_t retlen;
if (netdev->type != LXC_NET_VETH) {
ERROR("Network type %d not support for unprivileged use", netdev->type);
}
if (child == 0) {
- int ret;
- size_t retlen;
- char pidstr[LXC_NUMSTRLEN64];
+ char pidstr[INTTYPE_TO_STRLEN(pid_t)];
close(pipefd[0]);
_exit(EXIT_FAILURE);
}
- ret = snprintf(pidstr, LXC_NUMSTRLEN64, "%d", pid);
- if (ret < 0 || ret >= LXC_NUMSTRLEN64)
+ ret = snprintf(pidstr, sizeof(pidstr), "%d", pid);
+ if (ret < 0 || ret >= sizeof(pidstr))
_exit(EXIT_FAILURE);
- pidstr[LXC_NUMSTRLEN64 - 1] = '\0';
+ pidstr[sizeof(pidstr) - 1] = '\0';
INFO("Execing lxc-user-nic create %s %s %s veth %s %s", lxcpath,
lxcname, pidstr, netdev_link,
/* close the write-end of the pipe */
close(pipefd[1]);
- bytes = read(pipefd[0], &buffer, MAXPATHLEN);
+ bytes = lxc_read_nointr(pipefd[0], &buffer, PATH_MAX);
if (bytes < 0) {
SYSERROR("Failed to read from pipe file descriptor");
close(pipefd[0]);
ret = lxc_safe_int(token, &netdev->ifindex);
if (ret < 0) {
- ERROR("%s - Failed to convert string \"%s\" to integer",
- strerror(-ret), token);
+ errno = -ret;
+ SYSERROR("Failed to convert string \"%s\" to integer", token);
return -1;
}
return -1;
}
- if (strlen(token) >= IFNAMSIZ) {
+ retlen = strlcpy(netdev->priv.veth_attr.veth1, token, IFNAMSIZ);
+ if (retlen >= IFNAMSIZ) {
ERROR("Host side veth device name returned by lxc-user-nic is "
"too long");
return -E2BIG;
}
- strcpy(netdev->priv.veth_attr.veth1, token);
/* netdev->priv.veth_attr.ifindex */
token = strtok_r(NULL, ":", &saveptr);
ret = lxc_safe_int(token, &netdev->priv.veth_attr.ifindex);
if (ret < 0) {
- ERROR("%s - Failed to convert string \"%s\" to integer",
- strerror(-ret), token);
+ errno = -ret;
+ SYSERROR("Failed to convert string \"%s\" to integer", token);
return -1;
}
+ if (netdev->upscript) {
+ char *argv[] = {
+ "veth",
+ netdev->link,
+ netdev->priv.veth_attr.veth1,
+ NULL,
+ };
+
+ ret = run_script_argv(lxcname,
+ hooks_version, "net",
+ netdev->upscript, "up", argv);
+ if (ret < 0)
+ return -1;
+ }
+
return 0;
}
int bytes, ret;
pid_t child;
int pipefd[2];
- char buffer[MAXPATHLEN] = {0};
+ char buffer[PATH_MAX] = {0};
if (netdev->type != LXC_NET_VETH) {
ERROR("Network type %d not support for unprivileged use", netdev->type);
if (child == 0) {
char *hostveth;
- int ret;
close(pipefd[0]);
close(pipefd[1]);
- bytes = read(pipefd[0], &buffer, MAXPATHLEN);
+ bytes = lxc_read_nointr(pipefd[0], &buffer, PATH_MAX);
if (bytes < 0) {
SYSERROR("Failed to read from pipe file descriptor.");
close(pipefd[0]);
struct lxc_list *network = &handler->conf->network;
/* strlen("/proc/") = 6
* +
- * LXC_NUMSTRLEN64
+ * INTTYPE_TO_STRLEN(pid_t)
* +
* strlen("/fd/") = 4
* +
- * LXC_NUMSTRLEN64
+ * INTTYPE_TO_STRLEN(int)
* +
* \0
*/
- char netns_path[6 + LXC_NUMSTRLEN64 + 4 + LXC_NUMSTRLEN64 + 1];
+ char netns_path[6 + INTTYPE_TO_STRLEN(pid_t) + 4 + INTTYPE_TO_STRLEN(int) + 1];
*netns_path = '\0';
netdev->link);
clear_ifindices:
- /* We need to clear any ifindeces we recorded so liblxc won't
+ /* We need to clear any ifindices we recorded so liblxc won't
* have cached stale data which would cause it to fail on reboot
* we're we don't re-read the on-disk config file.
*/
ret = lxc_netdev_move_by_name(ifname, pid, NULL);
if (ret) {
- ERROR("Failed to move network device \"%s\" to "
- "network namespace %d: %s", ifname, pid,
- strerror(-ret));
+ errno = -ret;
+ SYSERROR("Failed to move network device \"%s\" to "
+ "network namespace %d", ifname, pid);
return -1;
}
}
int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
- struct lxc_list *network, pid_t pid)
+ struct lxc_list *network, pid_t pid, unsigned int hooks_version)
{
struct lxc_list *iterator;
if (netdev->mtu)
INFO("mtu ignored due to insufficient privilege");
- if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev, pid))
+ if (lxc_create_network_unpriv_exec(lxcpath, lxcname, netdev, pid, hooks_version))
return -1;
}
netdev->name[0] != '\0' ? netdev->name : "(null)",
netdev->ifindex);
} else if (ret < 0) {
- WARN("Failed to remove interface \"%s\" with "
- "index %d: %s",
- netdev->name[0] != '\0' ? netdev->name : "(null)",
- netdev->ifindex, strerror(-ret));
+ errno = -ret;
+ SYSWARN("Failed to remove interface \"%s\" with index %d",
+ netdev->name[0] != '\0' ? netdev->name : "(null)",
+ netdev->ifindex);
goto clear_ifindices;
}
INFO("Removed interface \"%s\" with index %d",
ret = lxc_netdev_delete_by_name(hostveth);
if (ret < 0) {
- WARN("Failed to remove interface \"%s\" from \"%s\": %s",
- hostveth, netdev->link, strerror(-ret));
+ errno = -ret;
+ SYSWARN("Failed to remove interface \"%s\" from \"%s\"",
+ hostveth, netdev->link);
goto clear_ifindices;
}
INFO("Removed interface \"%s\" from \"%s\"", hostveth, netdev->link);
hostveth, netdev->link);
clear_ifindices:
- /* We need to clear any ifindeces we recorded so liblxc won't
+ /* We need to clear any ifindices we recorded so liblxc won't
* have cached stale data which would cause it to fail on reboot
* we're we don't re-read the on-disk config file.
*/
{
struct sockaddr sockaddr;
struct ifreq ifr;
- int ret, fd, saved_errno;
+ int ret, fd;
ret = lxc_convert_mac(hwaddr, &sockaddr);
if (ret) {
- ERROR("Mac address \"%s\" conversion failed: %s", hwaddr,
- strerror(-ret));
+ errno = -ret;
+ SYSERROR("Mac address \"%s\" conversion failed", hwaddr);
return -1;
}
return -1;
ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
- saved_errno = errno;
- close(fd);
if (ret)
- ERROR("Failed to perform ioctl: %s", strerror(saved_errno));
+ SYSERROR("Failed to perform ioctl");
+
+ close(fd);
DEBUG("Mac address \"%s\" on \"%s\" has been setup", hwaddr,
ifr.ifr_name);
err = lxc_ipv4_addr_add(ifindex, &inetdev->addr,
&inetdev->bcast, inetdev->prefix);
if (err) {
- ERROR("Failed to setup ipv4 address for network device "
- "with eifindex %d: %s", ifindex, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to setup ipv4 address for network device "
+ "with eifindex %d", ifindex);
return -1;
}
}
&inet6dev->mcast, &inet6dev->acast,
inet6dev->prefix);
if (err) {
- ERROR("Failed to setup ipv6 address for network device "
- "with eifindex %d: %s", ifindex, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to setup ipv6 address for network device "
+ "with eifindex %d", ifindex);
return -1;
}
}
if (netdev->flags & IFF_UP) {
err = lxc_netdev_up("lo");
if (err) {
- ERROR("Failed to set the loopback network "
- "device up: %s",
- strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set the loopback network device up");
return -1;
}
}
*/
if (netdev->name[0] == '\0') {
if (netdev->type == LXC_NET_PHYS)
- strcpy(netdev->name, netdev->link);
+ (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
else
- strcpy(netdev->name, "eth%d");
+ (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
}
/* rename the interface name */
if (strcmp(ifname, netdev->name) != 0) {
err = lxc_netdev_rename_by_name(ifname, netdev->name);
if (err) {
- ERROR("Failed to rename network device \"%s\" to "
- "\"%s\": %s", ifname, netdev->name, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
+ ifname, netdev->name);
return -1;
}
}
* name of the network device in the child's network namespace. We will
* later on send this information back to the parent.
*/
- strcpy(netdev->name, current_ifname);
+ (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
/* set a mac address */
if (netdev->hwaddr) {
/* set the network device up */
if (netdev->flags & IFF_UP) {
- int err;
-
err = lxc_netdev_up(current_ifname);
if (err) {
- ERROR("Failed to set network device \"%s\" up: %s",
- current_ifname, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set network device \"%s\" up",
+ current_ifname);
return -1;
}
/* the network is up, make the loopback up too */
err = lxc_netdev_up("lo");
if (err) {
- ERROR("Failed to set the loopback network device up: %s",
- strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to set the loopback network device up");
return -1;
}
}
if (err) {
err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway);
if (err) {
- ERROR("Failed to add ipv4 dest for network "
- "device \"%s\": %s", ifname, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
+ ifname);
}
err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
if (err) {
- ERROR("Failed to setup ipv4 gateway for "
- "network device \"%s\": %s",
- ifname, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
+ ifname);
+
if (netdev->ipv4_gateway_auto) {
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
if (err) {
err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway);
if (err) {
- ERROR("Failed to add ipv6 dest for network "
- "device \"%s\": %s", ifname, strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
+ ifname);
}
err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
if (err) {
- ERROR("Failed to setup ipv6 gateway for "
- "network device \"%s\": %s", ifname,
- strerror(-err));
+ errno = -err;
+ SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
+ ifname);
+
if (netdev->ipv6_gateway_auto) {
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
if (netdev->type != LXC_NET_VETH)
continue;
- ret = send(data_sock, netdev->name, IFNAMSIZ, 0);
+ ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
if (ret < 0)
return -1;
TRACE("Sent network device name \"%s\" to child", netdev->name);
if (netdev->type != LXC_NET_VETH)
continue;
- ret = recv(data_sock, netdev->name, IFNAMSIZ, 0);
+ ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
if (ret < 0)
return -1;
TRACE("Received network device name \"%s\" from parent", netdev->name);
struct lxc_netdev *netdev = iterator->elem;
/* Send network device name in the child's namespace to parent. */
- ret = send(data_sock, netdev->name, IFNAMSIZ, 0);
+ ret = lxc_send_nointr(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
if (ret < 0)
return -1;
/* Send network device ifindex in the child's namespace to
* parent.
*/
- ret = send(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), 0);
+ ret = lxc_send_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), MSG_NOSIGNAL);
if (ret < 0)
return -1;
}
- TRACE("Sent network device names and ifindeces to parent");
+ TRACE("Sent network device names and ifindices to parent");
return 0;
}
/* Receive network device name in the child's namespace to
* parent.
*/
- ret = recv(data_sock, netdev->name, IFNAMSIZ, 0);
+ ret = lxc_recv_nointr(data_sock, netdev->name, IFNAMSIZ, 0);
if (ret < 0)
return -1;
/* Receive network device ifindex in the child's namespace to
* parent.
*/
- ret = recv(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), 0);
+ ret = lxc_recv_nointr(data_sock, &netdev->ifindex, sizeof(netdev->ifindex), 0);
if (ret < 0)
return -1;
}
else
DEBUG("Deleted network devices");
}
+
+int lxc_netns_set_nsid(int fd)
+{
+ int ret;
+ char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
+ NLMSG_ALIGN(1024)];
+ struct nl_handler nlh;
+ struct nlmsghdr *hdr;
+ struct rtgenmsg *msg;
+ int saved_errno;
+ const __s32 ns_id = -1;
+ const __u32 netns_fd = fd;
+
+ ret = netlink_open(&nlh, NETLINK_ROUTE);
+ if (ret < 0)
+ return -1;
+
+ memset(buf, 0, sizeof(buf));
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ hdr = (struct nlmsghdr *)buf;
+ msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
+#pragma GCC diagnostic pop
+
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
+ hdr->nlmsg_type = RTM_NEWNSID;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_pid = 0;
+ hdr->nlmsg_seq = RTM_NEWNSID;
+ msg->rtgen_family = AF_UNSPEC;
+
+ ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
+ if (ret < 0)
+ goto on_error;
+
+ ret = addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
+ if (ret < 0)
+ goto on_error;
+
+ ret = __netlink_transaction(&nlh, hdr, hdr);
+
+on_error:
+ saved_errno = errno;
+ netlink_close(&nlh);
+ errno = saved_errno;
+
+ return ret;
+}
+
+static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+
+ while (RTA_OK(rta, len)) {
+ unsigned short type = rta->rta_type;
+
+ if ((type <= max) && (!tb[type]))
+ tb[type] = rta;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ rta = RTA_NEXT(rta, len);
+#pragma GCC diagnostic pop
+ }
+
+ return 0;
+}
+
+static inline __s32 rta_getattr_s32(const struct rtattr *rta)
+{
+ return *(__s32 *)RTA_DATA(rta);
+}
+
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
+
+int lxc_netns_get_nsid(int fd)
+{
+ int ret;
+ ssize_t len;
+ char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct rtgenmsg)) +
+ NLMSG_ALIGN(1024)];
+ struct rtattr *tb[__LXC_NETNSA_MAX + 1];
+ struct nl_handler nlh;
+ struct nlmsghdr *hdr;
+ struct rtgenmsg *msg;
+ int saved_errno;
+ __u32 netns_fd = fd;
+
+ ret = netlink_open(&nlh, NETLINK_ROUTE);
+ if (ret < 0)
+ return -1;
+
+ memset(buf, 0, sizeof(buf));
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ hdr = (struct nlmsghdr *)buf;
+ msg = (struct rtgenmsg *)NLMSG_DATA(hdr);
+#pragma GCC diagnostic pop
+
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*msg));
+ hdr->nlmsg_type = RTM_GETNSID;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_pid = 0;
+ hdr->nlmsg_seq = RTM_GETNSID;
+ msg->rtgen_family = AF_UNSPEC;
+
+ ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
+ if (ret == 0)
+ ret = __netlink_transaction(&nlh, hdr, hdr);
+
+ saved_errno = errno;
+ netlink_close(&nlh);
+ errno = saved_errno;
+ if (ret < 0)
+ return -1;
+
+ errno = EINVAL;
+ msg = NLMSG_DATA(hdr);
+ len = hdr->nlmsg_len - NLMSG_SPACE(sizeof(*msg));
+ if (len < 0)
+ return -1;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+ parse_rtattr(tb, __LXC_NETNSA_MAX, NETNS_RTA(msg), len);
+ if (tb[__LXC_NETNSA_NSID])
+ return rta_getattr_s32(tb[__LXC_NETNSA_NSID]);
+#pragma GCC diagnostic pop
+
+ return -1;
+}