mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-15 00:27:05 +00:00
Merge pull request #2640 from brauner/2018-09-23/netns_getifaddrs
network: add netns_getifaddrs() implementation
This commit is contained in:
commit
36be8e6c4a
@ -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,54 @@ 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));
|
||||
|
||||
#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)
|
||||
return r;
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
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 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 +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,
|
||||
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)
|
||||
#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;
|
||||
struct ifaddrs_ctx _ctx;
|
||||
@ -392,10 +544,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
|
||||
@ -347,6 +341,7 @@ init_lxc_SOURCES = cmd/lxc_init.c \
|
||||
string_utils.c string_utils.h
|
||||
lxc_monitord_SOURCES = cmd/lxc_monitord.c
|
||||
lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \
|
||||
../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \
|
||||
log.c log.h \
|
||||
namespace.c namespace.h \
|
||||
network.c network.h \
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
@ -2496,7 +2491,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]);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
@ -1950,7 +1945,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;
|
||||
@ -1967,7 +1962,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;
|
||||
@ -2001,7 +1996,7 @@ char *lxc_mkifname(char *template)
|
||||
break;
|
||||
}
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
netns_freeifaddrs(ifaddr);
|
||||
(void)strlcpy(template, name, strlen(template) + 1);
|
||||
|
||||
return template;
|
||||
@ -3181,35 +3176,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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user