mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 10:51:24 +00:00
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@ubuntu.com>
This commit is contained in:
parent
7e270c97f1
commit
cc6119a033
@ -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
|
@ -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;
|
||||
@ -169,7 +175,6 @@ static int nl_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
|
||||
if (h->nlmsg_type == RTM_NEWLINK) {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
for (rta = __NLMSG_RTA(h, sizeof(*ifi)); __NLMSG_RTAOK(rta, h);
|
||||
rta = __RTA_NEXT(rta)) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
} else {
|
||||
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 ignored "-Wcast-align"
|
||||
|
||||
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);
|
||||
@ -218,7 +222,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;
|
||||
@ -227,6 +231,13 @@ 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));
|
||||
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 {
|
||||
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);
|
||||
@ -244,11 +257,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),
|
||||
@ -261,19 +274,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));
|
||||
}
|
||||
@ -289,14 +302,18 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
if (ifs->ifa.ifa_name) {
|
||||
@ -314,11 +331,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),
|
||||
static int __ifaddrs_netlink_send(int fd, struct nlmsghdr *nlmsghdr)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 {
|
||||
uint8_t buf[8192];
|
||||
struct {
|
||||
@ -327,17 +382,50 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
|
||||
} req;
|
||||
struct nlmsghdr reply;
|
||||
} u;
|
||||
int r, ret;
|
||||
int r, property, 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);
|
||||
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);
|
||||
@ -346,17 +434,17 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
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;
|
||||
}
|
||||
@ -364,27 +452,81 @@ static int __nl_recv(int fd, unsigned int seq, int type, int af,
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -392,10 +534,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;
|
53
src/include/netns_ifaddrs.h
Normal file
53
src/include/netns_ifaddrs.h
Normal 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 */
|
@ -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
|
||||
|
@ -272,9 +272,19 @@ extern int __build_bug_on_failed;
|
||||
#define IFLA_NEW_NETNSID 45
|
||||
#endif
|
||||
|
||||
#ifndef IFLA_IF_NETNSID
|
||||
#define IFLA_IF_NETNSID 46
|
||||
#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
|
||||
@ -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)
|
||||
|
||||
|
@ -3181,35 +3181,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;
|
||||
|
19
src/lxc/nl.c
19
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user