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: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 9b3475ac
#ifndef _IFADDRS_H #ifndef _LXC_NETNS_IFADDRS_H
#define _IFADDRS_H #define _LXC_NETNS_IFADDRS_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <features.h> #include <features.h>
#include <linux/types.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdbool.h>
#include <sys/socket.h> #include <sys/socket.h>
struct ifaddrs { struct netns_ifaddrs {
struct ifaddrs *ifa_next; struct netns_ifaddrs *ifa_next;
/* Can - but shouldn't be - NULL. */
char *ifa_name; char *ifa_name;
/* This field is not present struct ifaddrs. */
int ifa_ifindex;
unsigned ifa_flags; 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_addr;
struct sockaddr *ifa_netmask; struct sockaddr *ifa_netmask;
union { union {
struct sockaddr *ifu_broadaddr; struct sockaddr *ifu_broadaddr;
struct sockaddr *ifu_dstaddr; struct sockaddr *ifu_dstaddr;
} ifa_ifu; } ifa_ifu;
/* If you don't know what this is for don't touch it. */
void *ifa_data; void *ifa_data;
}; };
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void freeifaddrs(struct ifaddrs *); #define __ifa_broadaddr ifa_ifu.ifu_broadaddr
int getifaddrs(struct ifaddrs **); #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 #ifdef __cplusplus
} }
#endif #endif
#endif #endif /* _LXC_NETNS_IFADDRS_H */
...@@ -13,6 +13,7 @@ noinst_HEADERS = attach.h \ ...@@ -13,6 +13,7 @@ noinst_HEADERS = attach.h \
criu.h \ criu.h \
error.h \ error.h \
file_utils.h \ file_utils.h \
../include/netns_ifaddrs.h \
initutils.h \ initutils.h \
list.h \ list.h \
log.h \ log.h \
...@@ -40,10 +41,6 @@ noinst_HEADERS = attach.h \ ...@@ -40,10 +41,6 @@ noinst_HEADERS = attach.h \
tools/arguments.h \ tools/arguments.h \
utils.h utils.h
if !HAVE_IFADDRS_H
noinst_HEADERS += ../include/ifaddrs.h
endif
if IS_BIONIC if IS_BIONIC
noinst_HEADERS += ../include/lxcmntent.h \ noinst_HEADERS += ../include/lxcmntent.h \
../include/openpty.h ../include/openpty.h
...@@ -101,6 +98,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ ...@@ -101,6 +98,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
execute.c \ execute.c \
freezer.c \ freezer.c \
file_utils.c file_utils.h \ file_utils.c file_utils.h \
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \
initutils.c initutils.h \ initutils.c initutils.h \
list.h \ list.h \
log.c log.h \ log.c log.h \
...@@ -137,10 +135,6 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \ ...@@ -137,10 +135,6 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
version.h \ version.h \
$(LSM_SOURCES) $(LSM_SOURCES)
if !HAVE_IFADDRS_H
liblxc_la_SOURCES += ../include/ifaddrs.c ../include/ifaddrs.h
endif
if IS_BIONIC if IS_BIONIC
liblxc_la_SOURCES += ../include/lxcmntent.c ../include/lxcmntent.h \ liblxc_la_SOURCES += ../include/lxcmntent.c ../include/lxcmntent.h \
../include/openpty.c ../include/openpty.h ../include/openpty.c ../include/openpty.h
......
...@@ -272,10 +272,20 @@ extern int __build_bug_on_failed; ...@@ -272,10 +272,20 @@ extern int __build_bug_on_failed;
#define IFLA_NEW_NETNSID 45 #define IFLA_NEW_NETNSID 45
#endif #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_IF_NETNSID 46
#define IFLA_TARGET_NETNSID 46
#endif
#ifndef IFA_TARGET_NETNSID
#define IFA_TARGET_NETNSID 10
#endif #endif
#ifndef RTM_NEWNSID #ifndef RTM_NEWNSID
#define RTM_NEWNSID 88 #define RTM_NEWNSID 88
#endif #endif
...@@ -304,6 +314,16 @@ extern int __build_bug_on_failed; ...@@ -304,6 +314,16 @@ extern int __build_bug_on_failed;
#define MACVLAN_MODE_PASSTHRU 8 #define MACVLAN_MODE_PASSTHRU 8
#endif #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. */ /* Length of abstract unix domain socket socket address. */
#define LXC_AUDS_ADDR_LEN sizeof(((struct sockaddr_un *)0)->sun_path) #define LXC_AUDS_ADDR_LEN sizeof(((struct sockaddr_un *)0)->sun_path)
......
...@@ -3181,35 +3181,6 @@ void lxc_delete_network(struct lxc_handler *handler) ...@@ -3181,35 +3181,6 @@ void lxc_delete_network(struct lxc_handler *handler)
DEBUG("Deleted network devices"); 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 lxc_netns_set_nsid(int fd)
{ {
int ret; int ret;
......
...@@ -345,3 +345,22 @@ extern int netlink_close(struct nl_handler *handler) ...@@ -345,3 +345,22 @@ extern int netlink_close(struct nl_handler *handler)
return 0; 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;
}
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#ifndef __LXC_NL_H #ifndef __LXC_NL_H
#define __LXC_NL_H #define __LXC_NL_H
#include <stdio.h>
/* /*
* Use this as a good size to allocate generic netlink messages * Use this as a good size to allocate generic netlink messages
*/ */
...@@ -259,5 +261,7 @@ void nlmsg_free(struct nlmsg *nlmsg); ...@@ -259,5 +261,7 @@ void nlmsg_free(struct nlmsg *nlmsg);
*/ */
void *nlmsg_data(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 #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment