[lxc-devel] [lxc/master] network: add netns_getifaddrs() implementation

brauner on Github lxc-bot at linuxcontainers.org
Sun Sep 23 13:42:55 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 2169 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180923/45e207bd/attachment.bin>
-------------- next part --------------
From 9940a0a6c0083d5b1ed553a4ab5245b3a9884722 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 23 Sep 2018 15:29:22 +0200
Subject: [PATCH 1/2] network: add netns_getifaddrs() implementation

This commit introduces my concept of a network namespace aware
getifaddrs(), i.e. netns_getifaddrs(). This presupposes a kernel that
carries my IF{L}A_TARGET_NETNSID patches:

struct netns_ifaddrs {
        struct netns_ifaddrs *ifa_next;

        /* Can - but shouldn't be - NULL. */
        char *ifa_name;

        /* This field is not present struct ifaddrs. */
        int ifa_ifindex;

        unsigned ifa_flags;

        /* This field is not present struct ifaddrs. */
        int ifa_mtu;

        /* This field is not present struct ifaddrs. */
        int ifa_prefixlen;

        struct sockaddr *ifa_addr;
        struct sockaddr *ifa_netmask;
        union {
                struct sockaddr *ifu_broadaddr;
                struct sockaddr *ifu_dstaddr;
        } ifa_ifu;

        /* If you don't know what this is for don't touch it. */
        void *ifa_data;
};

which is a superset of struct ifaddrs. It contains additional
information such as the mtu, ifindex of the interface and the prefix
length of the address.
Note that the field ordering is different. So don't get any ideas of
using memcpy() to copy from an old struct ifaddrs into a struct
netns_ifaddrs.

int netns_getifaddrs(struct netns_ifaddrs **ifap, __s32 netns_id, bool *netnsid_aware)

takes a network namespace identifier as argument which identifies the
target network namespace.
If successfull, i.e. netns_getifaddrs() returns 0, callers should check
the bool *netnsid_aware return argument. If it is true then
RTM_GET{ADDR,LINK} requests are fully netnsid aware. If it is false then
they are not and the information returned in struct netns_ifaddrs does
*not* contain correct information about the target network namespace
identified by netnsid.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/include/ifaddrs.h                      |  34 ---
 src/include/{ifaddrs.c => netns_ifaddrs.c} | 258 ++++++++++++++++-----
 src/include/netns_ifaddrs.h                |  53 +++++
 src/lxc/Makefile.am                        |  10 +-
 src/lxc/macro.h                            |  22 +-
 src/lxc/network.c                          |  29 ---
 src/lxc/nl.c                               |  19 ++
 src/lxc/nl.h                               |   4 +
 8 files changed, 302 insertions(+), 127 deletions(-)
 delete mode 100644 src/include/ifaddrs.h
 rename src/include/{ifaddrs.c => netns_ifaddrs.c} (56%)
 create mode 100644 src/include/netns_ifaddrs.h

diff --git a/src/include/ifaddrs.h b/src/include/ifaddrs.h
deleted file mode 100644
index 4f1352d05..000000000
--- a/src/include/ifaddrs.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef _IFADDRS_H
-#define _IFADDRS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <features.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-struct ifaddrs {
-	struct ifaddrs *ifa_next;
-	char *ifa_name;
-	unsigned ifa_flags;
-	struct sockaddr *ifa_addr;
-	struct sockaddr *ifa_netmask;
-	union {
-		struct sockaddr *ifu_broadaddr;
-		struct sockaddr *ifu_dstaddr;
-	} ifa_ifu;
-	void *ifa_data;
-};
-#define ifa_broadaddr ifa_ifu.ifu_broadaddr
-#define ifa_dstaddr ifa_ifu.ifu_dstaddr
-
-void freeifaddrs(struct ifaddrs *);
-int getifaddrs(struct ifaddrs **);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/include/ifaddrs.c b/src/include/netns_ifaddrs.c
similarity index 56%
rename from src/include/ifaddrs.c
rename to src/include/netns_ifaddrs.c
index a391173b3..b90eed7d5 100644
--- a/src/include/ifaddrs.c
+++ b/src/include/netns_ifaddrs.c
@@ -1,15 +1,30 @@
 #define _GNU_SOURCE
+#include <arpa/inet.h>
 #include <errno.h>
+#include <linux/if.h>
+#include <linux/if_addr.h>
+#include <linux/if_link.h>
+#include <linux/if_packet.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
-#include <net/if.h>
+#include <linux/types.h>
+#include <net/ethernet.h>
 #include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <unistd.h>
 
-#include "ifaddrs.h"
+#include "nl.h"
+#include "macro.h"
+#include "netns_ifaddrs.h"
+
+#ifndef NETNS_RTA
+#define NETNS_RTA(r) \
+	((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))))
+#endif
 
 #define IFADDRS_HASH_SIZE 64
 
@@ -47,10 +62,11 @@
 
 #define __RTA_DATA(rta) ((void *)((char *)(rta) + sizeof(struct rtattr)))
 
-/* getifaddrs() reports hardware addresses with PF_PACKET that implies
- * struct sockaddr_ll.  But e.g. Infiniband socket address length is
- * longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct
- * to extend ssl_addr - callers should be able to still use it. */
+/* getifaddrs() reports hardware addresses with PF_PACKET that implies struct
+ * sockaddr_ll.  But e.g. Infiniband socket address length is longer than
+ * sockaddr_ll.ssl_addr[8] can hold. Use this hack struct to extend ssl_addr -
+ * callers should be able to still use it.
+ */
 struct sockaddr_ll_hack {
 	unsigned short sll_family, sll_protocol;
 	int sll_ifindex;
@@ -67,7 +83,7 @@ union sockany {
 };
 
 struct ifaddrs_storage {
-	struct ifaddrs ifa;
+	struct netns_ifaddrs ifa;
 	struct ifaddrs_storage *hash_next;
 	union sockany addr, netmask, ifu;
 	unsigned int index;
@@ -80,17 +96,6 @@ struct ifaddrs_ctx {
 	struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE];
 };
 
-void freeifaddrs(struct ifaddrs *ifp)
-{
-	struct ifaddrs *n;
-
-	while (ifp) {
-		n = ifp->ifa_next;
-		free(ifp);
-		ifp = n;
-	}
-}
-
 static void copy_addr(struct sockaddr **r, int af, union sockany *sa,
 		      void *addr, size_t addrlen, int ifindex)
 {
@@ -105,7 +110,8 @@ static void copy_addr(struct sockaddr **r, int af, union sockany *sa,
 	case AF_INET6:
 		dst = (uint8_t *)&sa->v6.sin6_addr;
 		len = 16;
-		if (__IN6_IS_ADDR_LINKLOCAL(addr) || __IN6_IS_ADDR_MC_LINKLOCAL(addr))
+		if (__IN6_IS_ADDR_LINKLOCAL(addr) ||
+		    __IN6_IS_ADDR_MC_LINKLOCAL(addr))
 			sa->v6.sin6_scope_id = ifindex;
 		break;
 	default:
@@ -157,7 +163,7 @@ static void copy_lladdr(struct sockaddr **r, union sockany *sa, void *addr,
 	*r = &sa->sa;
 }
 
-static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
+static int nl_msg_to_ifaddr(void *pctx, bool *netnsid_aware, struct nlmsghdr *h)
 {
 	struct ifaddrs_storage *ifs, *ifs0;
 	struct rtattr *rta;
@@ -192,6 +198,7 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 
 	if (h->nlmsg_type == RTM_NEWLINK) {
 		ifs->index = ifi->ifi_index;
+		ifs->ifa.ifa_ifindex = ifi->ifi_index;
 		ifs->ifa.ifa_flags = ifi->ifi_flags;
 
 		for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h);
@@ -210,7 +217,7 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 					    ifi->ifi_index, ifi->ifi_type);
 				break;
 			case IFLA_BROADCAST:
-				copy_lladdr(&ifs->ifa.ifa_broadaddr, &ifs->ifu,
+				copy_lladdr(&ifs->ifa.__ifa_broadaddr, &ifs->ifu,
 					    __RTA_DATA(rta), __RTA_DATALEN(rta),
 					    ifi->ifi_index, ifi->ifi_type);
 				break;
@@ -219,6 +226,14 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 				memcpy(ifs->ifa.ifa_data, __RTA_DATA(rta),
 				       __RTA_DATALEN(rta));
 				break;
+			case IFLA_MTU:
+				memcpy(&ifs->ifa.ifa_mtu, __RTA_DATA(rta),
+				       sizeof(int));
+				printf("%d\n", ifs->ifa.ifa_mtu);
+				break;
+			case IFLA_TARGET_NETNSID:
+				*netnsid_aware = true;
+				break;
 			}
 		}
 
@@ -229,6 +244,8 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 		}
 	} else {
 		ifs->ifa.ifa_name = ifs0->ifa.ifa_name;
+		ifs->ifa.ifa_mtu = ifs0->ifa.ifa_mtu;
+		ifs->ifa.ifa_ifindex = ifs0->ifa.ifa_ifindex;
 		ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags;
 
 		for (rta = __NLMSG_RTA(h, sizeof(*ifa)); __NLMSG_RTAOK(rta, h);
@@ -236,11 +253,11 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 			switch (rta->rta_type) {
 			case IFA_ADDRESS:
 				/* If ifa_addr is already set we, received an
-				 * IFA_LOCAL before so treat this as destination
-				 * address.
+				 * IFA_LOCAL before so treat this as
+				 * destination address.
 				 */
 				if (ifs->ifa.ifa_addr)
-					copy_addr(&ifs->ifa.ifa_dstaddr,
+					copy_addr(&ifs->ifa.__ifa_dstaddr,
 						  ifa->ifa_family, &ifs->ifu,
 						  __RTA_DATA(rta),
 						  __RTA_DATALEN(rta),
@@ -253,19 +270,19 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 						  ifa->ifa_index);
 				break;
 			case IFA_BROADCAST:
-				copy_addr(&ifs->ifa.ifa_broadaddr,
+				copy_addr(&ifs->ifa.__ifa_broadaddr,
 					  ifa->ifa_family, &ifs->ifu,
 					  __RTA_DATA(rta), __RTA_DATALEN(rta),
 					  ifa->ifa_index);
 				break;
 			case IFA_LOCAL:
 				/* If ifa_addr is set and we get IFA_LOCAL,
-				 * assume we have a point-to-point network. Move
-				 * address to correct field.
+				 * assume we have a point-to-point network.
+				 * Move address to correct field.
 				 */
 				if (ifs->ifa.ifa_addr) {
 					ifs->ifu = ifs->addr;
-					ifs->ifa.ifa_dstaddr = &ifs->ifu.sa;
+					ifs->ifa.__ifa_dstaddr = &ifs->ifu.sa;
 
 					memset(&ifs->addr, 0, sizeof(ifs->addr));
 				}
@@ -281,12 +298,17 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 					ifs->ifa.ifa_name = ifs->name;
 				}
 				break;
+			case IFA_TARGET_NETNSID:
+				*netnsid_aware = true;
+				break;
 			}
 		}
 
-		if (ifs->ifa.ifa_addr)
+		if (ifs->ifa.ifa_addr) {
 			gen_netmask(&ifs->ifa.ifa_netmask, ifa->ifa_family,
 				    &ifs->netmask, ifa->ifa_prefixlen);
+			ifs->ifa.ifa_prefixlen = ifa->ifa_prefixlen;
+		}
 	}
 
 	if (ifs->ifa.ifa_name) {
@@ -304,11 +326,49 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 	return 0;
 }
 
-static int __nl_recv(int fd, unsigned int seq, int type, int af,
-			       int (*cb)(void *ctx, struct nlmsghdr *h),
-			       void *ctx)
+static int __ifaddrs_netlink_send(int fd, struct nlmsghdr *nlmsghdr)
 {
-	struct nlmsghdr *h;
+	int ret;
+	struct sockaddr_nl nladdr;
+	struct iovec iov = {
+	    .iov_base = nlmsghdr,
+	    .iov_len = nlmsghdr->nlmsg_len,
+	};
+	struct msghdr msg = {
+	    .msg_name = &nladdr,
+	    .msg_namelen = sizeof(nladdr),
+	    .msg_iov = &iov,
+	    .msg_iovlen = 1,
+	};
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+	nladdr.nl_pid = 0;
+	nladdr.nl_groups = 0;
+
+	ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
+	if (ret < 0)
+		return -1;
+
+	return ret;
+}
+
+static int __ifaddrs_netlink_recv(int fd, unsigned int seq, int type, int af,
+				  __s32 netns_id, bool *netnsid_aware,
+				  int (*cb)(void *ctx, bool *netnsid_aware,
+					    struct nlmsghdr *h),
+				  void *ctx)
+{
+	char getlink_buf[__NETLINK_ALIGN(sizeof(struct nlmsghdr)) +
+			 __NETLINK_ALIGN(sizeof(struct ifinfomsg)) +
+			 __NETLINK_ALIGN(1024)];
+	char getaddr_buf[__NETLINK_ALIGN(sizeof(struct nlmsghdr)) +
+			 __NETLINK_ALIGN(sizeof(struct ifaddrmsg)) +
+			 __NETLINK_ALIGN(1024)];
+	char *buf;
+	struct nlmsghdr *hdr;
+	struct ifinfomsg *ifi_msg;
+	struct ifaddrmsg *ifa_msg;
 	union {
 		uint8_t buf[8192];
 		struct {
@@ -317,61 +377,148 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
 		} req;
 		struct nlmsghdr reply;
 	} u;
-	int r, ret;
-
-	memset(&u.req, 0, sizeof(u.req));
-	u.req.nlh.nlmsg_len = sizeof(u.req);
-	u.req.nlh.nlmsg_type = type;
-	u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
-	u.req.nlh.nlmsg_seq = seq;
-	u.req.g.rtgen_family = af;
-	r = send(fd, &u.req, sizeof(u.req), 0);
+	int r, property, ret;
+
+	if (type == RTM_GETLINK)
+		buf = getlink_buf;
+	else if (type == RTM_GETADDR)
+		buf = getaddr_buf;
+	else
+		return -1;
+
+	memset(buf, 0, sizeof(*buf));
+	hdr = (struct nlmsghdr *)buf;
+	if (type == RTM_GETLINK)
+		ifi_msg = (struct ifinfomsg *)__NLMSG_DATA(hdr);
+	else
+		ifa_msg = (struct ifaddrmsg *)__NLMSG_DATA(hdr);
+
+	if (type == RTM_GETLINK)
+		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*ifi_msg));
+	else
+		hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*ifa_msg));
+
+	hdr->nlmsg_type = type;
+	hdr->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+	hdr->nlmsg_pid = 0;
+	hdr->nlmsg_seq = seq;
+	if (type == RTM_GETLINK)
+		ifi_msg->ifi_family = af;
+	else
+		ifa_msg->ifa_family = af;
+
+	errno = EINVAL;
+	if (type == RTM_GETLINK)
+		property = IFLA_TARGET_NETNSID;
+	else if (type == RTM_GETADDR)
+		property = IFA_TARGET_NETNSID;
+	else
+		return -1;
+
+	if (netns_id >= 0)
+		addattr(hdr, 1024, property, &netns_id, sizeof(netns_id));
+
+	r = __ifaddrs_netlink_send(fd, hdr);
 	if (r < 0)
-		return r;
+		return -1;
 
 	for (;;) {
 		r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT);
 		if (r <= 0)
 			return -1;
 
-		for (h = &u.reply; __NLMSG_OK(h, (void *)&u.buf[r]);
-		     h = __NLMSG_NEXT(h)) {
-			if (h->nlmsg_type == NLMSG_DONE)
+		for (hdr = &u.reply; __NLMSG_OK(hdr, (void *)&u.buf[r]);
+		     hdr = __NLMSG_NEXT(hdr)) {
+			if (hdr->nlmsg_type == NLMSG_DONE)
 				return 0;
 
-			if (h->nlmsg_type == NLMSG_ERROR) {
+			if (hdr->nlmsg_type == NLMSG_ERROR) {
 				errno = EINVAL;
 				return -1;
 			}
 
-			ret = cb(ctx, h);
+			ret = cb(ctx, netnsid_aware, hdr);
 			if (ret)
 				return ret;
 		}
 	}
 }
 
-static int __rtnl_enumerate(int link_af, int addr_af,
-			    int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx)
+static int __rtnl_enumerate(int link_af, int addr_af, __s32 netns_id,
+			    bool *netnsid_aware,
+			    int (*cb)(void *ctx, bool *netnsid_aware, struct nlmsghdr *h),
+			    void *ctx)
 {
 	int fd, r, saved_errno;
+	bool getaddr_netnsid_aware = false, getlink_netnsid_aware = false;
 
 	fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
 	if (fd < 0)
 		return -1;
 
-	r = __nl_recv(fd, 1, RTM_GETLINK, link_af, cb, ctx);
+	r = __ifaddrs_netlink_recv(fd, 1, RTM_GETLINK, link_af, netns_id,
+				   &getlink_netnsid_aware, cb, ctx);
 	if (!r)
-		r = __nl_recv(fd, 2, RTM_GETADDR, addr_af, cb, ctx);
+		r = __ifaddrs_netlink_recv(fd, 2, RTM_GETADDR, addr_af, netns_id,
+					   &getaddr_netnsid_aware, cb, ctx);
 
 	saved_errno = errno;
 	close(fd);
 	errno = saved_errno;
 
+	if (getaddr_netnsid_aware && getlink_netnsid_aware)
+		*netnsid_aware = true;
+	else
+		*netnsid_aware = false;
+
 	return r;
 }
 
-int getifaddrs(struct ifaddrs **ifap)
+/* Get a pointer to the address structure from a sockaddr. */
+static void *get_addr_ptr(struct sockaddr *sockaddr_ptr)
+{
+	if (sockaddr_ptr->sa_family == AF_INET)
+		return &((struct sockaddr_in *)sockaddr_ptr)->sin_addr;
+
+	if (sockaddr_ptr->sa_family == AF_INET6)
+		return &((struct sockaddr_in6 *)sockaddr_ptr)->sin6_addr;
+
+	return NULL;
+}
+
+static char *get_packet_address(struct sockaddr *sockaddr_ptr, char *buf, size_t buflen)
+{
+	char *slider = buf;
+	unsigned char *m = ((struct sockaddr_ll *)sockaddr_ptr)->sll_addr;
+	unsigned char n = ((struct sockaddr_ll *)sockaddr_ptr)->sll_halen;
+
+	for (unsigned char i = 0; i < n; i++) {
+		int ret;
+
+		ret = snprintf(slider, buflen, "%02x%s", m[i], (i + 1) < n ? ":" : "");
+		if (ret < 0 || (size_t)ret >= buflen)
+			return NULL;
+
+		buflen -= ret;
+		slider = (slider + ret);
+	}
+
+	return buf;
+}
+
+void netns_freeifaddrs(struct netns_ifaddrs *ifp)
+{
+	struct netns_ifaddrs *n;
+
+	while (ifp) {
+		n = ifp->ifa_next;
+		free(ifp);
+		ifp = n;
+	}
+}
+
+int netns_getifaddrs(struct netns_ifaddrs **ifap, __s32 netns_id,
+		     bool *netnsid_aware)
 {
 	int r, saved_errno;
 	struct ifaddrs_ctx _ctx;
@@ -379,10 +526,11 @@ int getifaddrs(struct ifaddrs **ifap)
 
 	memset(ctx, 0, sizeof *ctx);
 
-	r = __rtnl_enumerate(AF_UNSPEC, AF_UNSPEC, nl_msg_to_ifaddr, ctx);
+	r = __rtnl_enumerate(AF_UNSPEC, AF_UNSPEC, netns_id, netnsid_aware,
+			     nl_msg_to_ifaddr, ctx);
 	saved_errno = errno;
 	if (r < 0)
-		freeifaddrs(&ctx->first->ifa);
+		netns_freeifaddrs(&ctx->first->ifa);
 	else
 		*ifap = &ctx->first->ifa;
 	errno = saved_errno;
diff --git a/src/include/netns_ifaddrs.h b/src/include/netns_ifaddrs.h
new file mode 100644
index 000000000..ee9236ed9
--- /dev/null
+++ b/src/include/netns_ifaddrs.h
@@ -0,0 +1,53 @@
+#ifndef _LXC_NETNS_IFADDRS_H
+#define _LXC_NETNS_IFADDRS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+#include <linux/types.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+
+struct netns_ifaddrs {
+	struct netns_ifaddrs *ifa_next;
+
+	/* Can - but shouldn't be - NULL. */
+	char *ifa_name;
+
+	/* This field is not present struct ifaddrs. */
+	int ifa_ifindex;
+
+	unsigned ifa_flags;
+
+	/* This field is not present struct ifaddrs. */
+	int ifa_mtu;
+
+	/* This field is not present struct ifaddrs. */
+	int ifa_prefixlen;
+
+	struct sockaddr *ifa_addr;
+	struct sockaddr *ifa_netmask;
+	union {
+		struct sockaddr *ifu_broadaddr;
+		struct sockaddr *ifu_dstaddr;
+	} ifa_ifu;
+
+	/* If you don't know what this is for don't touch it. */
+	void *ifa_data;
+};
+
+#define __ifa_broadaddr ifa_ifu.ifu_broadaddr
+#define __ifa_dstaddr ifa_ifu.ifu_dstaddr
+
+extern void netns_freeifaddrs(struct netns_ifaddrs *);
+extern int netns_getifaddrs(struct netns_ifaddrs **ifap, __s32 netns_id,
+			    bool *netnsid_aware);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LXC_NETNS_IFADDRS_H */
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 51c871eb6..690486d34 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -14,6 +14,7 @@ noinst_HEADERS = api_extensions.h \
 		 criu.h \
 		 error.h \
 		 file_utils.h \
+		 ../include/netns_ifaddrs.h \
 		 initutils.h \
 		 list.h \
 		 log.h \
@@ -41,10 +42,6 @@ noinst_HEADERS = api_extensions.h \
 		 tools/arguments.h \
 		 utils.h
 
-if !HAVE_IFADDRS_H
-noinst_HEADERS += ../include/ifaddrs.h
-endif
-
 if IS_BIONIC
 noinst_HEADERS += ../include/lxcmntent.h \
 		  ../include/openpty.h
@@ -103,6 +100,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
 		    execute.c \
 		    freezer.c \
 		    file_utils.c file_utils.h \
+		    ../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \
 		    initutils.c initutils.h \
 		    list.h \
 		    log.c log.h \
@@ -139,10 +137,6 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
 		    version.h \
 		    $(LSM_SOURCES)
 
-if !HAVE_IFADDRS_H
-liblxc_la_SOURCES += ../include/ifaddrs.c ../include/ifaddrs.h
-endif
-
 if IS_BIONIC
 liblxc_la_SOURCES += ../include/lxcmntent.c ../include/lxcmntent.h \
 		     ../include/openpty.c ../include/openpty.h
diff --git a/src/lxc/macro.h b/src/lxc/macro.h
index 3ff40648a..911d5e944 100644
--- a/src/lxc/macro.h
+++ b/src/lxc/macro.h
@@ -272,10 +272,20 @@ extern int __build_bug_on_failed;
 #define IFLA_NEW_NETNSID 45
 #endif
 
-#ifndef IFLA_IF_NETNSID
+#ifdef IFLA_IF_NETNSID
+#ifndef IFLA_TARGET_NETNSID
+#define IFLA_TARGET_NETNSID = IFLA_IF_NETNSID
+#endif
+#else
 #define IFLA_IF_NETNSID 46
+#define IFLA_TARGET_NETNSID 46
+#endif
+
+#ifndef IFA_TARGET_NETNSID
+#define IFA_TARGET_NETNSID 10
 #endif
 
+
 #ifndef RTM_NEWNSID
 #define RTM_NEWNSID 88
 #endif
@@ -304,6 +314,16 @@ extern int __build_bug_on_failed;
 #define MACVLAN_MODE_PASSTHRU 8
 #endif
 
+/* 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,
+};
+
 /* Length of abstract unix domain socket socket address. */
 #define LXC_AUDS_ADDR_LEN sizeof(((struct sockaddr_un *)0)->sun_path)
 
diff --git a/src/lxc/network.c b/src/lxc/network.c
index 72a3d6b7a..4c8f20641 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -3166,35 +3166,6 @@ void lxc_delete_network(struct lxc_handler *handler)
 		DEBUG("Deleted network devices");
 }
 
-int addattr(struct nlmsghdr *n, size_t maxlen, int type, const void *data, size_t alen)
-{
-	int len = RTA_LENGTH(alen);
-	struct rtattr *rta;
-
-	errno = EMSGSIZE;
-	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
-		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);
-
-	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,
-};
-
 int lxc_netns_set_nsid(int fd)
 {
 	int ret;
diff --git a/src/lxc/nl.c b/src/lxc/nl.c
index bf2452f0e..06a72fb88 100644
--- a/src/lxc/nl.c
+++ b/src/lxc/nl.c
@@ -345,3 +345,22 @@ extern int netlink_close(struct nl_handler *handler)
 	return 0;
 }
 
+int addattr(struct nlmsghdr *n, size_t maxlen, int type, const void *data,
+	    size_t alen)
+{
+	int len = RTA_LENGTH(alen);
+	struct rtattr *rta;
+
+	errno = EMSGSIZE;
+	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
+		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);
+
+	return 0;
+}
diff --git a/src/lxc/nl.h b/src/lxc/nl.h
index a00fc16df..2afda5f0f 100644
--- a/src/lxc/nl.h
+++ b/src/lxc/nl.h
@@ -23,6 +23,8 @@
 #ifndef __LXC_NL_H
 #define __LXC_NL_H
 
+#include <stdio.h>
+
 /*
  * Use this as a good size to allocate generic netlink messages
  */
@@ -259,5 +261,7 @@ void nlmsg_free(struct nlmsg *nlmsg);
  */
 void *nlmsg_data(struct nlmsg *nlmsg);
 
+extern int addattr(struct nlmsghdr *n, size_t maxlen, int type,
+		   const void *data, size_t alen);
 
 #endif

From 26543ebd7affca824465f6c1cfc8cd6c820a4d96 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 23 Sep 2018 15:40:20 +0200
Subject: [PATCH 2/2] tree_wide: switch to netns_getifaddrs()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/confile.c          | 13 ++++---------
 src/lxc/lxccontainer.c     | 19 +++++++------------
 src/lxc/network.c          | 13 ++++---------
 src/lxc/tools/lxc_device.c | 11 +++--------
 4 files changed, 18 insertions(+), 38 deletions(-)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index b6b3032bb..2a362e8c2 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -48,6 +48,7 @@
 #include "config.h"
 #include "confile.h"
 #include "confile_utils.h"
+#include <../include/netns_ifaddrs.h>
 #include "log.h"
 #include "lxcseccomp.h"
 #include "network.h"
@@ -55,12 +56,6 @@
 #include "storage.h"
 #include "utils.h"
 
-#if HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#else
-#include <../include/ifaddrs.h>
-#endif
-
 #if HAVE_SYS_PERSONALITY_H
 #include <sys/personality.h>
 #endif
@@ -324,14 +319,14 @@ static int set_config_net_flags(const char *key, const char *value,
 static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf,
 				  struct lxc_netdev *netdev)
 {
-	struct ifaddrs *ifaddr, *ifa;
+	struct netns_ifaddrs *ifaddr, *ifa;
 	int n;
 	int ret = 0;
 	const char *type_key = "lxc.net.type";
 	const char *link_key = "lxc.net.link";
 	const char *tmpvalue = "phys";
 
-	if (getifaddrs(&ifaddr) == -1) {
+	if (netns_getifaddrs(&ifaddr, -1, &(bool){false}) < 0) {
 		SYSERROR("Get network interfaces failed");
 		return -1;
 	}
@@ -359,7 +354,7 @@ static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf,
 		}
 	}
 
-	freeifaddrs(ifaddr);
+	netns_freeifaddrs(ifaddr);
 	ifaddr = NULL;
 
 	return ret;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 80cf73207..bd3214bed 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -53,6 +53,7 @@
 #include "confile_utils.h"
 #include "criu.h"
 #include "error.h"
+#include <../include/netns_ifaddrs.h>
 #include "initutils.h"
 #include "log.h"
 #include "lxc.h"
@@ -78,12 +79,6 @@
 #include <sys/mkdev.h>
 #endif
 
-#if HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#else
-#include <../include/ifaddrs.h>
-#endif
-
 #if IS_BIONIC
 #include <../include/lxcmntent.h>
 #else
@@ -2327,7 +2322,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
 
 	if (pid == 0) { /* child */
 		int ret = 1, nbytes;
-		struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+		struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
 
 		/* close the read-end of the pipe */
 		close(pipefd[0]);
@@ -2338,7 +2333,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
 		}
 
 		/* Grab the list of interfaces */
-		if (getifaddrs(&interfaceArray)) {
+		if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
 			SYSERROR("Failed to get interfaces list");
 			goto out;
 		}
@@ -2357,7 +2352,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
 
 	out:
 		if (interfaceArray)
-			freeifaddrs(interfaceArray);
+			netns_freeifaddrs(interfaceArray);
 
 		/* close the write-end of the pipe, thus sending EOF to the reader */
 		close(pipefd[1]);
@@ -2429,7 +2424,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
 		int ret = 1;
 		char *address = NULL;
 		void *tempAddrPtr = NULL;
-		struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+		struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
 
 		/* close the read-end of the pipe */
 		close(pipefd[0]);
@@ -2440,7 +2435,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
 		}
 
 		/* Grab the list of interfaces */
-		if (getifaddrs(&interfaceArray)) {
+		if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
 			SYSERROR("Failed to get interfaces list");
 			goto out;
 		}
@@ -2491,7 +2486,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
 
 	out:
 		if (interfaceArray)
-			freeifaddrs(interfaceArray);
+			netns_freeifaddrs(interfaceArray);
 
 		/* close the write-end of the pipe, thus sending EOF to the reader */
 		close(pipefd[1]);
diff --git a/src/lxc/network.c b/src/lxc/network.c
index 4c8f20641..a3d6d0764 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -48,6 +48,7 @@
 #include "af_unix.h"
 #include "conf.h"
 #include "config.h"
+#include <../include/netns_ifaddrs.h>
 #include "file_utils.h"
 #include "log.h"
 #include "macro.h"
@@ -55,12 +56,6 @@
 #include "nl.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
@@ -1935,7 +1930,7 @@ static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 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;
@@ -1952,7 +1947,7 @@ char *lxc_mkifname(char *template)
 		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;
@@ -1986,7 +1981,7 @@ char *lxc_mkifname(char *template)
 			break;
 	}
 
-	freeifaddrs(ifaddr);
+	netns_freeifaddrs(ifaddr);
 	(void)strlcpy(template, name, strlen(template) + 1);
 
 	return template;
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index e2f576d71..1d0c40415 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -30,15 +30,10 @@
 #include <lxc/lxccontainer.h>
 
 #include "arguments.h"
+#include "../../include/netns_ifaddrs.h"
 #include "log.h"
 #include "utils.h"
 
-#if HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#else
-#include "../include/ifaddrs.h"
-#endif
-
 lxc_log_define(lxc_device, lxc);
 
 static bool is_interface(const char *dev_name, pid_t pid);
@@ -73,7 +68,7 @@ static bool is_interface(const char *dev_name, pid_t pid)
 	}
 
 	if (p == 0) {
-		struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
+		struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
 
 		if (!switch_to_ns(pid, "net")) {
 			ERROR("Failed to enter netns of container");
@@ -81,7 +76,7 @@ static bool is_interface(const char *dev_name, pid_t pid)
 		}
 
 		/* Grab the list of interfaces */
-		if (getifaddrs(&interfaceArray)) {
+		if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
 			ERROR("Failed to get interfaces list");
 			_exit(-1);
 		}


More information about the lxc-devel mailing list