Merge pull request #2640 from brauner/2018-09-23/netns_getifaddrs

network: add netns_getifaddrs() implementation
This commit is contained in:
Stéphane Graber 2018-09-24 00:35:21 +02:00 committed by GitHub
commit 36be8e6c4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 330 additions and 169 deletions

View File

@ -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

View File

@ -1,15 +1,30 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.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/netlink.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/if.h> #include <linux/types.h>
#include <net/ethernet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.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 #define IFADDRS_HASH_SIZE 64
@ -47,10 +62,11 @@
#define __RTA_DATA(rta) ((void *)((char *)(rta) + sizeof(struct rtattr))) #define __RTA_DATA(rta) ((void *)((char *)(rta) + sizeof(struct rtattr)))
/* getifaddrs() reports hardware addresses with PF_PACKET that implies /* getifaddrs() reports hardware addresses with PF_PACKET that implies struct
* struct sockaddr_ll. But e.g. Infiniband socket address length is * sockaddr_ll. But e.g. Infiniband socket address length is longer than
* longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct * sockaddr_ll.ssl_addr[8] can hold. Use this hack struct to extend ssl_addr -
* to extend ssl_addr - callers should be able to still use it. */ * callers should be able to still use it.
*/
struct sockaddr_ll_hack { struct sockaddr_ll_hack {
unsigned short sll_family, sll_protocol; unsigned short sll_family, sll_protocol;
int sll_ifindex; int sll_ifindex;
@ -67,7 +83,7 @@ union sockany {
}; };
struct ifaddrs_storage { struct ifaddrs_storage {
struct ifaddrs ifa; struct netns_ifaddrs ifa;
struct ifaddrs_storage *hash_next; struct ifaddrs_storage *hash_next;
union sockany addr, netmask, ifu; union sockany addr, netmask, ifu;
unsigned int index; unsigned int index;
@ -80,17 +96,6 @@ struct ifaddrs_ctx {
struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE]; 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, static void copy_addr(struct sockaddr **r, int af, union sockany *sa,
void *addr, size_t addrlen, int ifindex) 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: case AF_INET6:
dst = (uint8_t *)&sa->v6.sin6_addr; dst = (uint8_t *)&sa->v6.sin6_addr;
len = 16; 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; sa->v6.sin6_scope_id = ifindex;
break; break;
default: default:
@ -157,7 +163,7 @@ static void copy_lladdr(struct sockaddr **r, union sockany *sa, void *addr,
*r = &sa->sa; *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 ifaddrs_storage *ifs, *ifs0;
struct rtattr *rta; struct rtattr *rta;
@ -169,7 +175,6 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
if (h->nlmsg_type == RTM_NEWLINK) { if (h->nlmsg_type == RTM_NEWLINK) {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h); for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h);
rta = __RTA_NEXT(rta)) { rta = __RTA_NEXT(rta)) {
if (rta->rta_type != IFLA_STATS) if (rta->rta_type != IFLA_STATS)
@ -178,7 +183,6 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
stats_len = __RTA_DATALEN(rta); stats_len = __RTA_DATALEN(rta);
break; break;
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} else { } else {
for (ifs0 = ctx->hash[ifa->ifa_index % IFADDRS_HASH_SIZE]; ifs0; for (ifs0 = ctx->hash[ifa->ifa_index % IFADDRS_HASH_SIZE]; ifs0;
@ -197,9 +201,9 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
if (h->nlmsg_type == RTM_NEWLINK) { if (h->nlmsg_type == RTM_NEWLINK) {
ifs->index = ifi->ifi_index; ifs->index = ifi->ifi_index;
ifs->ifa.ifa_ifindex = ifi->ifi_index;
ifs->ifa.ifa_flags = ifi->ifi_flags; ifs->ifa.ifa_flags = ifi->ifi_flags;
for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h); for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h);
@ -218,7 +222,7 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
ifi->ifi_index, ifi->ifi_type); ifi->ifi_index, ifi->ifi_type);
break; break;
case IFLA_BROADCAST: 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), __RTA_DATA(rta), __RTA_DATALEN(rta),
ifi->ifi_index, ifi->ifi_type); ifi->ifi_index, ifi->ifi_type);
break; break;
@ -227,6 +231,13 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
memcpy(ifs->ifa.ifa_data, __RTA_DATA(rta), memcpy(ifs->ifa.ifa_data, __RTA_DATA(rta),
__RTA_DATALEN(rta)); __RTA_DATALEN(rta));
break; break;
case IFLA_MTU:
memcpy(&ifs->ifa.ifa_mtu, __RTA_DATA(rta),
sizeof(int));
break;
case IFLA_TARGET_NETNSID:
*netnsid_aware = true;
break;
} }
} }
@ -237,6 +248,8 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
} }
} else { } else {
ifs->ifa.ifa_name = ifs0->ifa.ifa_name; 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; ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags;
for (rta = __NLMSG_RTA(h, sizeof(*ifa)); __NLMSG_RTAOK(rta, h); for (rta = __NLMSG_RTA(h, sizeof(*ifa)); __NLMSG_RTAOK(rta, h);
@ -244,11 +257,11 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
switch (rta->rta_type) { switch (rta->rta_type) {
case IFA_ADDRESS: case IFA_ADDRESS:
/* If ifa_addr is already set we, received an /* If ifa_addr is already set we, received an
* IFA_LOCAL before so treat this as destination * IFA_LOCAL before so treat this as
* address. * destination address.
*/ */
if (ifs->ifa.ifa_addr) if (ifs->ifa.ifa_addr)
copy_addr(&ifs->ifa.ifa_dstaddr, copy_addr(&ifs->ifa.__ifa_dstaddr,
ifa->ifa_family, &ifs->ifu, ifa->ifa_family, &ifs->ifu,
__RTA_DATA(rta), __RTA_DATA(rta),
__RTA_DATALEN(rta), __RTA_DATALEN(rta),
@ -261,19 +274,19 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
ifa->ifa_index); ifa->ifa_index);
break; break;
case IFA_BROADCAST: case IFA_BROADCAST:
copy_addr(&ifs->ifa.ifa_broadaddr, copy_addr(&ifs->ifa.__ifa_broadaddr,
ifa->ifa_family, &ifs->ifu, ifa->ifa_family, &ifs->ifu,
__RTA_DATA(rta), __RTA_DATALEN(rta), __RTA_DATA(rta), __RTA_DATALEN(rta),
ifa->ifa_index); ifa->ifa_index);
break; break;
case IFA_LOCAL: case IFA_LOCAL:
/* If ifa_addr is set and we get IFA_LOCAL, /* If ifa_addr is set and we get IFA_LOCAL,
* assume we have a point-to-point network. Move * assume we have a point-to-point network.
* address to correct field. * Move address to correct field.
*/ */
if (ifs->ifa.ifa_addr) { if (ifs->ifa.ifa_addr) {
ifs->ifu = ifs->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)); memset(&ifs->addr, 0, sizeof(ifs->addr));
} }
@ -289,14 +302,18 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
ifs->ifa.ifa_name = ifs->name; ifs->ifa.ifa_name = ifs->name;
} }
break; 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, gen_netmask(&ifs->ifa.ifa_netmask, ifa->ifa_family,
&ifs->netmask, ifa->ifa_prefixlen); &ifs->netmask, ifa->ifa_prefixlen);
ifs->ifa.ifa_prefixlen = ifa->ifa_prefixlen;
}
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
if (ifs->ifa.ifa_name) { if (ifs->ifa.ifa_name) {
@ -314,11 +331,49 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
return 0; return 0;
} }
static int __nl_recv(int fd, unsigned int seq, int type, int af, static int __ifaddrs_netlink_send(int fd, struct nlmsghdr *nlmsghdr)
int (*cb)(void *ctx, 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) void *ctx)
{ {
struct nlmsghdr *h; 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 { union {
uint8_t buf[8192]; uint8_t buf[8192];
struct { struct {
@ -327,17 +382,54 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
} req; } req;
struct nlmsghdr reply; struct nlmsghdr reply;
} u; } u;
int r, ret; int r, property, ret;
memset(&u.req, 0, sizeof(u.req)); if (type == RTM_GETLINK)
u.req.nlh.nlmsg_len = sizeof(u.req); buf = getlink_buf;
u.req.nlh.nlmsg_type = type; else if (type == RTM_GETADDR)
u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; buf = getaddr_buf;
u.req.nlh.nlmsg_seq = seq; else
u.req.g.rtgen_family = af; return -1;
r = send(fd, &u.req, sizeof(u.req), 0);
memset(buf, 0, sizeof(*buf));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
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));
#pragma GCC diagnostic pop
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) if (r < 0)
return r; return -1;
for (;;) { for (;;) {
r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT); r = recv(fd, u.buf, sizeof(u.buf), MSG_DONTWAIT);
@ -346,17 +438,17 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
for (h = &u.reply; __NLMSG_OK(h, (void *)&u.buf[r]); for (hdr = &u.reply; __NLMSG_OK(hdr, (void *)&u.buf[r]);
h = __NLMSG_NEXT(h)) { hdr = __NLMSG_NEXT(hdr)) {
if (h->nlmsg_type == NLMSG_DONE) if (hdr->nlmsg_type == NLMSG_DONE)
return 0; return 0;
if (h->nlmsg_type == NLMSG_ERROR) { if (hdr->nlmsg_type == NLMSG_ERROR) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ret = cb(ctx, h); ret = cb(ctx, netnsid_aware, hdr);
if (ret) if (ret)
return ret; return ret;
} }
@ -364,27 +456,87 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
} }
} }
static int __rtnl_enumerate(int link_af, int addr_af, static int __rtnl_enumerate(int link_af, int addr_af, __s32 netns_id,
int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx) bool *netnsid_aware,
int (*cb)(void *ctx, bool *netnsid_aware, struct nlmsghdr *h),
void *ctx)
{ {
int fd, r, saved_errno; int fd, r, saved_errno;
bool getaddr_netnsid_aware = false, getlink_netnsid_aware = false;
fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
if (fd < 0) if (fd < 0)
return -1; 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) 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; saved_errno = errno;
close(fd); close(fd);
errno = saved_errno; errno = saved_errno;
if (getaddr_netnsid_aware && getlink_netnsid_aware)
*netnsid_aware = true;
else
*netnsid_aware = false;
return r; return r;
} }
int getifaddrs(struct ifaddrs **ifap) #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
/* 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;
}
#pragma GCC diagnostic pop
static char *get_packet_address(struct sockaddr *sockaddr_ptr, char *buf, size_t buflen)
{
char *slider = buf;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
unsigned char *m = ((struct sockaddr_ll *)sockaddr_ptr)->sll_addr;
unsigned char n = ((struct sockaddr_ll *)sockaddr_ptr)->sll_halen;
#pragma GCC diagnostic pop
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; int r, saved_errno;
struct ifaddrs_ctx _ctx; struct ifaddrs_ctx _ctx;
@ -392,10 +544,11 @@ int getifaddrs(struct ifaddrs **ifap)
memset(ctx, 0, sizeof *ctx); 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; saved_errno = errno;
if (r < 0) if (r < 0)
freeifaddrs(&ctx->first->ifa); netns_freeifaddrs(&ctx->first->ifa);
else else
*ifap = &ctx->first->ifa; *ifap = &ctx->first->ifa;
errno = saved_errno; errno = saved_errno;

View File

@ -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 */

View File

@ -14,6 +14,7 @@ noinst_HEADERS = api_extensions.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 \
@ -41,10 +42,6 @@ noinst_HEADERS = api_extensions.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
@ -103,6 +100,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 \
@ -139,10 +137,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
@ -347,6 +341,7 @@ init_lxc_SOURCES = cmd/lxc_init.c \
string_utils.c string_utils.h string_utils.c string_utils.h
lxc_monitord_SOURCES = cmd/lxc_monitord.c lxc_monitord_SOURCES = cmd/lxc_monitord.c
lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \ lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \
log.c log.h \ log.c log.h \
namespace.c namespace.h \ namespace.c namespace.h \
network.c network.h \ network.c network.h \

View File

@ -48,6 +48,7 @@
#include "config.h" #include "config.h"
#include "confile.h" #include "confile.h"
#include "confile_utils.h" #include "confile_utils.h"
#include <../include/netns_ifaddrs.h>
#include "log.h" #include "log.h"
#include "lxcseccomp.h" #include "lxcseccomp.h"
#include "network.h" #include "network.h"
@ -55,12 +56,6 @@
#include "storage.h" #include "storage.h"
#include "utils.h" #include "utils.h"
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
#include <../include/ifaddrs.h>
#endif
#if HAVE_SYS_PERSONALITY_H #if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h> #include <sys/personality.h>
#endif #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, static int create_matched_ifnames(const char *value, struct lxc_conf *lxc_conf,
struct lxc_netdev *netdev) struct lxc_netdev *netdev)
{ {
struct ifaddrs *ifaddr, *ifa; struct netns_ifaddrs *ifaddr, *ifa;
int n; int n;
int ret = 0; int ret = 0;
const char *type_key = "lxc.net.type"; const char *type_key = "lxc.net.type";
const char *link_key = "lxc.net.link"; const char *link_key = "lxc.net.link";
const char *tmpvalue = "phys"; const char *tmpvalue = "phys";
if (getifaddrs(&ifaddr) == -1) { if (netns_getifaddrs(&ifaddr, -1, &(bool){false}) < 0) {
SYSERROR("Get network interfaces failed"); SYSERROR("Get network interfaces failed");
return -1; 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; ifaddr = NULL;
return ret; return ret;

View File

@ -53,6 +53,7 @@
#include "confile_utils.h" #include "confile_utils.h"
#include "criu.h" #include "criu.h"
#include "error.h" #include "error.h"
#include <../include/netns_ifaddrs.h>
#include "initutils.h" #include "initutils.h"
#include "log.h" #include "log.h"
#include "lxc.h" #include "lxc.h"
@ -78,12 +79,6 @@
#include <sys/mkdev.h> #include <sys/mkdev.h>
#endif #endif
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
#include <../include/ifaddrs.h>
#endif
#if IS_BIONIC #if IS_BIONIC
#include <../include/lxcmntent.h> #include <../include/lxcmntent.h>
#else #else
@ -2327,7 +2322,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
if (pid == 0) { /* child */ if (pid == 0) { /* child */
int ret = 1, nbytes; 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 the read-end of the pipe */
close(pipefd[0]); close(pipefd[0]);
@ -2338,7 +2333,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
} }
/* Grab the list of interfaces */ /* Grab the list of interfaces */
if (getifaddrs(&interfaceArray)) { if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
SYSERROR("Failed to get interfaces list"); SYSERROR("Failed to get interfaces list");
goto out; goto out;
} }
@ -2357,7 +2352,7 @@ static char **do_lxcapi_get_interfaces(struct lxc_container *c)
out: out:
if (interfaceArray) if (interfaceArray)
freeifaddrs(interfaceArray); netns_freeifaddrs(interfaceArray);
/* close the write-end of the pipe, thus sending EOF to the reader */ /* close the write-end of the pipe, thus sending EOF to the reader */
close(pipefd[1]); close(pipefd[1]);
@ -2429,7 +2424,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
int ret = 1; int ret = 1;
char *address = NULL; char *address = NULL;
void *tempAddrPtr = 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 the read-end of the pipe */
close(pipefd[0]); 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 */ /* Grab the list of interfaces */
if (getifaddrs(&interfaceArray)) { if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
SYSERROR("Failed to get interfaces list"); SYSERROR("Failed to get interfaces list");
goto out; goto out;
} }
@ -2496,7 +2491,7 @@ static char **do_lxcapi_get_ips(struct lxc_container *c, const char *interface,
out: out:
if (interfaceArray) if (interfaceArray)
freeifaddrs(interfaceArray); netns_freeifaddrs(interfaceArray);
/* close the write-end of the pipe, thus sending EOF to the reader */ /* close the write-end of the pipe, thus sending EOF to the reader */
close(pipefd[1]); close(pipefd[1]);

View File

@ -272,9 +272,19 @@ 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
#define IFLA_IF_NETNSID 46 #ifndef IFLA_TARGET_NETNSID
#define IFLA_TARGET_NETNSID = IFLA_IF_NETNSID
#endif #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 #ifndef RTM_NEWNSID
#define RTM_NEWNSID 88 #define RTM_NEWNSID 88
@ -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)

View File

@ -48,6 +48,7 @@
#include "af_unix.h" #include "af_unix.h"
#include "conf.h" #include "conf.h"
#include "config.h" #include "config.h"
#include <../include/netns_ifaddrs.h>
#include "file_utils.h" #include "file_utils.h"
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
@ -55,12 +56,6 @@
#include "nl.h" #include "nl.h"
#include "utils.h" #include "utils.h"
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
#include <../include/ifaddrs.h>
#endif
#ifndef HAVE_STRLCPY #ifndef HAVE_STRLCPY
#include "include/strlcpy.h" #include "include/strlcpy.h"
#endif #endif
@ -1950,7 +1945,7 @@ static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *lxc_mkifname(char *template) char *lxc_mkifname(char *template)
{ {
int ret; int ret;
struct ifaddrs *ifa, *ifaddr; struct netns_ifaddrs *ifa, *ifaddr;
char name[IFNAMSIZ]; char name[IFNAMSIZ];
bool exists = false; bool exists = false;
size_t i = 0; size_t i = 0;
@ -1967,7 +1962,7 @@ char *lxc_mkifname(char *template)
return NULL; return NULL;
/* Get all the network interfaces. */ /* Get all the network interfaces. */
ret = getifaddrs(&ifaddr); ret = netns_getifaddrs(&ifaddr, -1, &(bool){false});
if (ret < 0) { if (ret < 0) {
SYSERROR("Failed to get network interfaces"); SYSERROR("Failed to get network interfaces");
return NULL; return NULL;
@ -2001,7 +1996,7 @@ char *lxc_mkifname(char *template)
break; break;
} }
freeifaddrs(ifaddr); netns_freeifaddrs(ifaddr);
(void)strlcpy(template, name, strlen(template) + 1); (void)strlcpy(template, name, strlen(template) + 1);
return template; return template;
@ -3181,35 +3176,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;

View File

@ -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;
}

View File

@ -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);
*/ */
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

View File

@ -30,15 +30,10 @@
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "arguments.h" #include "arguments.h"
#include "../../include/netns_ifaddrs.h"
#include "log.h" #include "log.h"
#include "utils.h" #include "utils.h"
#if HAVE_IFADDRS_H
#include <ifaddrs.h>
#else
#include "../include/ifaddrs.h"
#endif
lxc_log_define(lxc_device, lxc); lxc_log_define(lxc_device, lxc);
static bool is_interface(const char *dev_name, pid_t pid); 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) { if (p == 0) {
struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL; struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
if (!switch_to_ns(pid, "net")) { if (!switch_to_ns(pid, "net")) {
ERROR("Failed to enter netns of container"); 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 */ /* Grab the list of interfaces */
if (getifaddrs(&interfaceArray)) { if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
ERROR("Failed to get interfaces list"); ERROR("Failed to get interfaces list");
_exit(-1); _exit(-1);
} }