* 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
#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;
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;
- struct ifaddrs *ifa, *ifaddr;
+ struct netns_ifaddrs *ifa, *ifaddr;
char name[IFNAMSIZ];
bool exists = false;
size_t i = 0;
return NULL;
/* Get all the network interfaces. */
- ret = getifaddrs(&ifaddr);
+ ret = netns_getifaddrs(&ifaddr, -1, &(bool){false});
if (ret < 0) {
SYSERROR("Failed to get network interfaces");
return NULL;
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);
+ netns_freeifaddrs(ifaddr);
(void)strlcpy(template, name, strlen(template) + 1);
return template;
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) {
}
if (child == 0) {
- int ret;
- size_t retlen;
char pidstr[INTTYPE_TO_STRLEN(pid_t)];
close(pipefd[0]);
/* close the write-end of the pipe */
close(pipefd[1]);
- bytes = lxc_read_nointr(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]);
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 = lxc_read_nointr(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]);
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.
*/
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.
*/
/* set the network device up */
if (netdev->flags & IFF_UP) {
- int err;
-
err = lxc_netdev_up(current_ifname);
if (err) {
errno = -err;
if (netdev->type != LXC_NET_VETH)
continue;
- ret = send(data_sock, netdev->name, IFNAMSIZ, MSG_NOSIGNAL);
+ 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, MSG_NOSIGNAL);
+ 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), MSG_NOSIGNAL);
+ 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;
}
DEBUG("Deleted network devices");
}
-int addattr(struct nlmsghdr *n, size_t maxlen, int type, const void *data, size_t alen)
+int lxc_netns_set_nsid(int fd)
{
- int len = RTA_LENGTH(alen);
- struct rtattr *rta;
+ 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;
- if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
+ ret = netlink_open(&nlh, NETLINK_ROUTE);
+ if (ret < 0)
return -1;
- rta = NLMSG_TAIL(n);
- rta->rta_type = type;
- rta->rta_len = len;
- if (alen)
- memcpy(RTA_DATA(rta), data, alen);
- n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ 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;
}
-/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
-enum {
- __LXC_NETNSA_NONE,
-#define __LXC_NETNSA_NSID_NOT_ASSIGNED -1
- __LXC_NETNSA_NSID,
- __LXC_NETNSA_PID,
- __LXC_NETNSA_FD,
- __LXC_NETNSA_MAX,
-};
+static inline __s32 rta_getattr_s32(const struct rtattr *rta)
+{
+ return *(__s32 *)RTA_DATA(rta);
+}
-int lxc_netns_set_nsid(int fd)
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
+
+int lxc_netns_get_nsid(int fd)
{
- ssize_t ret;
+ 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;
- __s32 ns_id = -1;
+ int saved_errno;
__u32 netns_fd = fd;
ret = netlink_open(&nlh, NETLINK_ROUTE);
if (ret < 0)
- return ret;
+ 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_type = RTM_GETNSID;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_pid = 0;
- hdr->nlmsg_seq = RTM_NEWNSID;
+ hdr->nlmsg_seq = RTM_GETNSID;
msg->rtgen_family = AF_UNSPEC;
- addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
- addattr(hdr, 1024, __LXC_NETNSA_NSID, &ns_id, sizeof(ns_id));
+ ret = addattr(hdr, 1024, __LXC_NETNSA_FD, &netns_fd, sizeof(netns_fd));
+ if (ret == 0)
+ ret = __netlink_transaction(&nlh, hdr, hdr);
- ret = __netlink_transaction(&nlh, hdr, hdr);
+ saved_errno = errno;
netlink_close(&nlh);
+ errno = saved_errno;
if (ret < 0)
return -1;
- return 0;
+ 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;
}