Quoting Stéphane Graber (stgra...@ubuntu.com): > This adds a local ifaddrs implementation to be used on Bionic or other C > libraries that don't come with a getifaddrs implementation. > > This code was written by Kenneth MacKay and is under a two-clause BSD > license (copyright information in the file headers). > > Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hal...@ubuntu.com> > --- > configure.ac | 2 +- > src/include/ifaddrs.c | 597 > +++++++++++++++++++++++++++++++++++++++++++++++++ > src/include/ifaddrs.h | 54 +++++ > src/lxc/Makefile.am | 2 + > src/lxc/conf.c | 7 +- > src/lxc/lxccontainer.c | 5 + > 6 files changed, 665 insertions(+), 2 deletions(-) > create mode 100644 src/include/ifaddrs.c > create mode 100644 src/include/ifaddrs.h > > diff --git a/configure.ac b/configure.ac > index 245df30..a0f0126 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -298,7 +298,7 @@ AM_CONDITIONAL([IS_BIONIC], [test "x$is_bionic" = "xyes"]) > AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include <sys/prctl.h>]) > > # Check for some headers > -AC_CHECK_HEADERS([sys/signalfd.h pty.h sys/capability.h sys/personality.h > utmpx.h sys/timerfd.h]) > +AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h > sys/personality.h utmpx.h sys/timerfd.h]) > > # Check for some syscalls functions > AC_CHECK_FUNCS([setns pivot_root sethostname unshare]) > diff --git a/src/include/ifaddrs.c b/src/include/ifaddrs.c > new file mode 100644 > index 0000000..855f0cd > --- /dev/null > +++ b/src/include/ifaddrs.c > @@ -0,0 +1,597 @@ > +/* > +Copyright (c) 2013, Kenneth MacKay > +All rights reserved. > + > +Redistribution and use in source and binary forms, with or without > modification, > +are permitted provided that the following conditions are met: > + * Redistributions of source code must retain the above copyright notice, > this > + list of conditions and the following disclaimer. > + * Redistributions in binary form must reproduce the above copyright notice, > + this list of conditions and the following disclaimer in the documentation > + and/or other materials provided with the distribution. > + > +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" > AND > +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE > FOR > +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > DAMAGES > +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; > +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > ON > +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS > +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > +*/ > + > +#include "ifaddrs.h" > + > +#include <string.h> > +#include <stdlib.h> > +#include <errno.h> > +#include <unistd.h> > +#include <sys/socket.h> > +#include <net/if_arp.h> > +#include <netinet/in.h> > +#include <linux/netlink.h> > +#include <linux/rtnetlink.h> > + > +typedef struct NetlinkList > +{ > + struct NetlinkList *m_next; > + struct nlmsghdr *m_data; > + unsigned int m_size; > +} NetlinkList; > + > +static int netlink_socket(void) > +{ > + int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); > + if(l_socket < 0) > + { > + return -1; > + } > + > + struct sockaddr_nl l_addr; > + memset(&l_addr, 0, sizeof(l_addr)); > + l_addr.nl_family = AF_NETLINK; > + if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0) > + { > + close(l_socket); > + return -1; > + } > + > + return l_socket; > +} > + > +static int netlink_send(int p_socket, int p_request) > +{ > + char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + > NLMSG_ALIGN(sizeof(struct rtgenmsg))]; > + memset(l_buffer, 0, sizeof(l_buffer)); > + struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer; > + struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr); > + > + l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg)); > + l_hdr->nlmsg_type = p_request; > + l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; > + l_hdr->nlmsg_pid = 0; > + l_hdr->nlmsg_seq = p_socket; > + l_msg->rtgen_family = AF_UNSPEC; > + > + struct sockaddr_nl l_addr; > + memset(&l_addr, 0, sizeof(l_addr)); > + l_addr.nl_family = AF_NETLINK; > + return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr > *)&l_addr, sizeof(l_addr))); > +} > + > +static int netlink_recv(int p_socket, void *p_buffer, size_t p_len) > +{ > + struct msghdr l_msg; > + struct iovec l_iov = { p_buffer, p_len }; > + struct sockaddr_nl l_addr; > + > + for(;;) > + { > + l_msg.msg_name = (void *)&l_addr; > + l_msg.msg_namelen = sizeof(l_addr); > + l_msg.msg_iov = &l_iov; > + l_msg.msg_iovlen = 1; > + l_msg.msg_control = NULL; > + l_msg.msg_controllen = 0; > + l_msg.msg_flags = 0; > + int l_result = recvmsg(p_socket, &l_msg, 0); > + > + if(l_result < 0) > + { > + if(errno == EINTR) > + { > + continue; > + } > + return -2; > + } > + > + if(l_msg.msg_flags & MSG_TRUNC) > + { // buffer was too small > + return -1; > + } > + return l_result; > + } > +} > + > +static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int > *p_done) > +{ > + size_t l_size = 4096; > + void *l_buffer = NULL; > + > + for(;;) > + { > + free(l_buffer); > + l_buffer = malloc(l_size); > + > + int l_read = netlink_recv(p_socket, l_buffer, l_size); > + *p_size = l_read; > + if(l_read == -2) > + { > + free(l_buffer); > + return NULL; > + } > + if(l_read >= 0) > + { > + pid_t l_pid = getpid(); > + struct nlmsghdr *l_hdr; > + for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, > (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read)) > + { > + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq > != p_socket) > + { > + continue; > + } > + > + if(l_hdr->nlmsg_type == NLMSG_DONE) > + { > + *p_done = 1; > + break; > + } > + > + if(l_hdr->nlmsg_type == NLMSG_ERROR) > + { > + free(l_buffer); > + return NULL; > + } > + } > + return l_buffer; > + } > + > + l_size *= 2; > + } > +} > + > +static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size) > +{ > + NetlinkList *l_item = malloc(sizeof(NetlinkList)); > + l_item->m_next = NULL; > + l_item->m_data = p_data; > + l_item->m_size = p_size; > + return l_item; > +} > + > +static void freeResultList(NetlinkList *p_list) > +{ > + NetlinkList *l_cur; > + while(p_list) > + { > + l_cur = p_list; > + p_list = p_list->m_next; > + free(l_cur->m_data); > + free(l_cur); > + } > +} > + > +static NetlinkList *getResultList(int p_socket, int p_request) > +{ > + if(netlink_send(p_socket, p_request) < 0) > + { > + return NULL; > + } > + > + NetlinkList *l_list = NULL; > + NetlinkList *l_end = NULL; > + int l_size; > + int l_done = 0; > + while(!l_done) > + { > + struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, > &l_done); > + if(!l_hdr) > + { // error > + freeResultList(l_list); > + return NULL; > + } > + > + NetlinkList *l_item = newListItem(l_hdr, l_size); > + if(!l_list) > + { > + l_list = l_item; > + } > + else > + { > + l_end->m_next = l_item; > + } > + l_end = l_item; > + } > + return l_list; > +} > + > +static size_t maxSize(size_t a, size_t b) > +{ > + return (a > b ? a : b); > +} > + > +static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) > +{ > + switch(p_family) > + { > + case AF_INET: > + return sizeof(struct sockaddr_in); > + case AF_INET6: > + return sizeof(struct sockaddr_in6); > + case AF_PACKET: > + return maxSize(sizeof(struct sockaddr_ll), offsetof(struct > sockaddr_ll, sll_addr) + p_dataSize); > + default: > + return maxSize(sizeof(struct sockaddr), offsetof(struct > sockaddr, sa_data) + p_dataSize); > + } > +} > + > +static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void > *p_data, size_t p_size) > +{ > + switch(p_family) > + { > + case AF_INET: > + memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size); > + break; > + case AF_INET6: > + memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, > p_size); > + break; > + case AF_PACKET: > + memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size); > + ((struct sockaddr_ll*)p_dest)->sll_halen = p_size; > + break; > + default: > + memcpy(p_dest->sa_data, p_data, p_size); > + break; > + } > + p_dest->sa_family = p_family; > +} > + > +static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry) > +{ > + if(!*p_resultList) > + { > + *p_resultList = p_entry; > + } > + else > + { > + struct ifaddrs *l_cur = *p_resultList; > + while(l_cur->ifa_next) > + { > + l_cur = l_cur->ifa_next; > + } > + l_cur->ifa_next = p_entry; > + } > +} > + > +static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, > struct ifaddrs **p_resultList) > +{ > + struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr); > + > + size_t l_nameSize = 0; > + size_t l_addrSize = 0; > + size_t l_dataSize = 0; > + > + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); > + struct rtattr *l_rta; > + for(l_rta = (struct rtattr *)(((char *)l_info) + > NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = > RTA_NEXT(l_rta, l_rtaSize)) > + { > + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); > + switch(l_rta->rta_type) > + { > + case IFLA_ADDRESS: > + case IFLA_BROADCAST: > + l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, > l_rtaDataSize)); > + break; > + case IFLA_IFNAME: > + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); > + break; > + case IFLA_STATS: > + l_dataSize += NLMSG_ALIGN(l_rtaSize); > + break; > + default: > + break; > + } > + } > + > + struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + > l_addrSize + l_dataSize); > + memset(l_entry, 0, sizeof(struct ifaddrs)); > + l_entry->ifa_name = ""; > + > + char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); > + char *l_addr = l_name + l_nameSize; > + char *l_data = l_addr + l_addrSize; > + > + l_entry->ifa_flags = l_info->ifi_flags; > + > + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg)); > + for(l_rta = (struct rtattr *)(((char *)l_info) + > NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = > RTA_NEXT(l_rta, l_rtaSize)) > + { > + void *l_rtaData = RTA_DATA(l_rta); > + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); > + switch(l_rta->rta_type) > + { > + case IFLA_ADDRESS: > + case IFLA_BROADCAST: > + { > + size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize); > + makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, > l_rtaData, l_rtaDataSize); > + ((struct sockaddr_ll *)l_addr)->sll_ifindex = > l_info->ifi_index; > + ((struct sockaddr_ll *)l_addr)->sll_hatype = > l_info->ifi_type; > + if(l_rta->rta_type == IFLA_ADDRESS) > + { > + l_entry->ifa_addr = (struct sockaddr *)l_addr; > + } > + else > + { > + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; > + } > + l_addr += NLMSG_ALIGN(l_addrLen); > + break; > + } > + case IFLA_IFNAME: > + strncpy(l_name, l_rtaData, l_rtaDataSize); > + l_name[l_rtaDataSize] = '\0'; > + l_entry->ifa_name = l_name; > + break; > + case IFLA_STATS: > + memcpy(l_data, l_rtaData, l_rtaDataSize); > + l_entry->ifa_data = l_data; > + break; > + default: > + break; > + } > + } > + > + addToEnd(p_resultList, l_entry); > + p_links[l_info->ifi_index - 1] = l_entry; > +} > + > +static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, > struct ifaddrs **p_resultList) > +{ > + struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr); > + > + size_t l_nameSize = 0; > + size_t l_addrSize = 0; > + > + int l_addedNetmask = 0; > + > + size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); > + struct rtattr *l_rta; > + for(l_rta = (struct rtattr *)(((char *)l_info) + > NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = > RTA_NEXT(l_rta, l_rtaSize)) > + { > + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); > + if(l_info->ifa_family == AF_PACKET) > + { > + continue; > + } > + > + switch(l_rta->rta_type) > + { > + case IFA_ADDRESS: > + case IFA_LOCAL: > + if((l_info->ifa_family == AF_INET || l_info->ifa_family == > AF_INET6) && !l_addedNetmask) > + { // make room for netmask > + l_addrSize += > NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); > + l_addedNetmask = 1; > + } > + case IFA_BROADCAST: > + l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, > l_rtaDataSize)); > + break; > + case IFA_LABEL: > + l_nameSize += NLMSG_ALIGN(l_rtaSize + 1); > + break; > + default: > + break; > + } > + } > + > + struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + > l_addrSize); > + memset(l_entry, 0, sizeof(struct ifaddrs)); > + l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name; > + > + char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs); > + char *l_addr = l_name + l_nameSize; > + > + l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - > 1]->ifa_flags; > + > + l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg)); > + for(l_rta = (struct rtattr *)(((char *)l_info) + > NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = > RTA_NEXT(l_rta, l_rtaSize)) > + { > + void *l_rtaData = RTA_DATA(l_rta); > + size_t l_rtaDataSize = RTA_PAYLOAD(l_rta); > + switch(l_rta->rta_type) > + { > + case IFA_ADDRESS: > + case IFA_BROADCAST: > + case IFA_LOCAL: > + { > + size_t l_addrLen = calcAddrLen(l_info->ifa_family, > l_rtaDataSize); > + makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, > l_rtaData, l_rtaDataSize); > + if(l_info->ifa_family == AF_INET6) > + { > + if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) > || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData)) > + { > + ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = > l_info->ifa_index; > + } > + } > + > + if(l_rta->rta_type == IFA_ADDRESS) > + { // apparently in a point-to-point network IFA_ADDRESS > contains the dest address and IFA_LOCAL contains the local address > + if(l_entry->ifa_addr) > + { > + l_entry->ifa_dstaddr = (struct sockaddr *)l_addr; > + } > + else > + { > + l_entry->ifa_addr = (struct sockaddr *)l_addr; > + } > + } > + else if(l_rta->rta_type == IFA_LOCAL) > + { > + if(l_entry->ifa_addr) > + { > + l_entry->ifa_dstaddr = l_entry->ifa_addr; > + } > + l_entry->ifa_addr = (struct sockaddr *)l_addr; > + } > + else > + { > + l_entry->ifa_broadaddr = (struct sockaddr *)l_addr; > + } > + l_addr += NLMSG_ALIGN(l_addrLen); > + break; > + } > + case IFA_LABEL: > + strncpy(l_name, l_rtaData, l_rtaDataSize); > + l_name[l_rtaDataSize] = '\0'; > + l_entry->ifa_name = l_name; > + break; > + default: > + break; > + } > + } > + > + if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || > l_entry->ifa_addr->sa_family == AF_INET6)) > + { > + unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 > : 128); > + unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? > l_maxPrefix : l_info->ifa_prefixlen); > + char l_mask[16] = {0}; > + unsigned i; > + for(i=0; i<(l_prefix/8); ++i) > + { > + l_mask[i] = 0xff; > + } > + l_mask[i] = 0xff << (8 - (l_prefix % 8)); > + > + makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr > *)l_addr, l_mask, l_maxPrefix / 8); > + l_entry->ifa_netmask = (struct sockaddr *)l_addr; > + } > + > + addToEnd(p_resultList, l_entry); > +} > + > +static void interpret(int p_socket, NetlinkList *p_netlinkList, struct > ifaddrs **p_links, struct ifaddrs **p_resultList) > +{ > + pid_t l_pid = getpid(); > + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) > + { > + unsigned int l_nlsize = p_netlinkList->m_size; > + struct nlmsghdr *l_hdr; > + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr > = NLMSG_NEXT(l_hdr, l_nlsize)) > + { > + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != > p_socket) > + { > + continue; > + } > + > + if(l_hdr->nlmsg_type == NLMSG_DONE) > + { > + break; > + } > + > + if(l_hdr->nlmsg_type == RTM_NEWLINK) > + { > + interpretLink(l_hdr, p_links, p_resultList); > + } > + else if(l_hdr->nlmsg_type == RTM_NEWADDR) > + { > + interpretAddr(l_hdr, p_links, p_resultList); > + } > + } > + } > +} > + > +static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList) > +{ > + unsigned l_links = 0; > + pid_t l_pid = getpid(); > + for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next) > + { > + unsigned int l_nlsize = p_netlinkList->m_size; > + struct nlmsghdr *l_hdr; > + for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr > = NLMSG_NEXT(l_hdr, l_nlsize)) > + { > + if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != > p_socket) > + { > + continue; > + } > + > + if(l_hdr->nlmsg_type == NLMSG_DONE) > + { > + break; > + } > + > + if(l_hdr->nlmsg_type == RTM_NEWLINK) > + { > + ++l_links; > + } > + } > + } > + > + return l_links; > +} > + > +int getifaddrs(struct ifaddrs **ifap) > +{ > + if(!ifap) > + { > + return -1; > + } > + *ifap = NULL; > + > + int l_socket = netlink_socket(); > + if(l_socket < 0) > + { > + return -1; > + } > + > + NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK); > + if(!l_linkResults) > + { > + close(l_socket); > + return -1; > + } > + > + NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR); > + if(!l_addrResults) > + { > + close(l_socket); > + freeResultList(l_linkResults); > + return -1; > + } > + > + unsigned l_numLinks = countLinks(l_socket, l_linkResults) + > countLinks(l_socket, l_addrResults); > + struct ifaddrs *l_links[l_numLinks]; > + memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *)); > + > + interpret(l_socket, l_linkResults, l_links, ifap); > + interpret(l_socket, l_addrResults, l_links, ifap); > + > + freeResultList(l_linkResults); > + freeResultList(l_addrResults); > + close(l_socket); > + return 0; > +} > + > +void freeifaddrs(struct ifaddrs *ifa) > +{ > + struct ifaddrs *l_cur; > + while(ifa) > + { > + l_cur = ifa; > + ifa = ifa->ifa_next; > + free(l_cur); > + } > +} > diff --git a/src/include/ifaddrs.h b/src/include/ifaddrs.h > new file mode 100644 > index 0000000..9cd19fe > --- /dev/null > +++ b/src/include/ifaddrs.h > @@ -0,0 +1,54 @@ > +/* > + * Copyright (c) 1995, 1999 > + * Berkeley Software Design, Inc. All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * > + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE > LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp > + */ > + > +#ifndef _IFADDRS_H_ > +#define _IFADDRS_H_ > + > +struct ifaddrs { > + struct ifaddrs *ifa_next; > + char *ifa_name; > + unsigned int ifa_flags; > + struct sockaddr *ifa_addr; > + struct sockaddr *ifa_netmask; > + struct sockaddr *ifa_dstaddr; > + void *ifa_data; > +}; > + > +/* > + * This may have been defined in <net/if.h>. Note that if <net/if.h> is > + * to be included it must be included before this header file. > + */ > +#ifndef ifa_broadaddr > +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface > */ > +#endif > + > +#include <sys/cdefs.h> > + > +__BEGIN_DECLS > +extern int getifaddrs(struct ifaddrs **ifap); > +extern void freeifaddrs(struct ifaddrs *ifa); > +__END_DECLS > + > +#endif > diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am > index ef48833..da5ff15 100644 > --- a/src/lxc/Makefile.am > +++ b/src/lxc/Makefile.am > @@ -22,6 +22,7 @@ pkginclude_HEADERS = \ > > if IS_BIONIC > pkginclude_HEADERS += \ > + ../include/ifaddrs.h \ > ../include/openpty.h \ > ../include/lxcmntent.h > endif > @@ -79,6 +80,7 @@ liblxc_so_SOURCES = \ > > if IS_BIONIC > liblxc_so_SOURCES += \ > + ../include/ifaddrs.c ../include/ifaddrs.h \ > ../include/openpty.c ../include/openpty.h \ > ../include/lxcmntent.c ../include/lxcmntent.h > endif > diff --git a/src/lxc/conf.c b/src/lxc/conf.c > index aff6982..867a150 100644 > --- a/src/lxc/conf.c > +++ b/src/lxc/conf.c > @@ -31,9 +31,14 @@ > #include <unistd.h> > #include <sys/wait.h> > #include <sys/syscall.h> > -#include <ifaddrs.h> > #include <time.h> > > +#if HAVE_IFADDRS_H > +#include <ifaddrs.h> > +#else > +#include <../include/ifaddrs.h> > +#endif > + > #if HAVE_PTY_H > #include <pty.h> > #else > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index 02e3766..6cf3da6 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -44,7 +44,12 @@ > #include <lxc/monitor.h> > #include <sched.h> > #include <arpa/inet.h> > + > +#if HAVE_IFADDRS_H > #include <ifaddrs.h> > +#else > +#include <../include/ifaddrs.h> > +#endif > > lxc_log_define(lxc_container, lxc); > > -- > 1.8.3.2 > > > ------------------------------------------------------------------------------ > Get 100% visibility into Java/.NET code with AppDynamics Lite! > It's a free troubleshooting tool designed for production. > Get down to code-level detail for bottlenecks, with <2% overhead. > Download for free and get started troubleshooting in minutes. > http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk > _______________________________________________ > Lxc-devel mailing list > Lxc-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/lxc-devel ------------------------------------------------------------------------------ Get 100% visibility into Java/.NET code with AppDynamics Lite! It's a free troubleshooting tool designed for production. Get down to code-level detail for bottlenecks, with <2% overhead. Download for free and get started troubleshooting in minutes. http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel