mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r26467: Use getifaddrs() for interface enumeration and provide replacements for platforms that don't have it in lib/replace.
(This used to be commit 9b4924fbd8
)
This commit is contained in:
parent
1786af425b
commit
be4decb2b7
391
source4/lib/replace/getifaddrs.c
Normal file
391
source4/lib/replace/getifaddrs.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Samba utility functions
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) Jeremy Allison 2007
|
||||
Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "replace.h"
|
||||
#include "system/network.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifndef SIOCGIFCONF
|
||||
#ifdef HAVE_SYS_SOCKIO_H
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IFACE_GETIFADDRS
|
||||
#define _FOUND_IFACE_ANY
|
||||
#else
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifp)
|
||||
{
|
||||
free(ifp->ifa_name);
|
||||
free(ifp->ifa_addr);
|
||||
free(ifp->ifa_netmask);
|
||||
free(ifp->ifa_dstaddr);
|
||||
if (ifp->ifa_next != NULL)
|
||||
freeifaddrs(ifp->ifa_next);
|
||||
free(ifp);
|
||||
}
|
||||
|
||||
struct sockaddr *sockaddr_dup(struct sockaddr *sa)
|
||||
{
|
||||
struct sockaddr *ret = calloc(1, sa->sa_len);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
memcpy(ret, sa, sa->sa_len);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_IFACE_IFCONF
|
||||
|
||||
/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
|
||||
V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
|
||||
|
||||
It probably also works on any BSD style system. */
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
char buff[8192];
|
||||
int fd, i, n;
|
||||
struct ifreq *ifr=NULL;
|
||||
int total = 0;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
struct ifaddrs *curif, *lastif;
|
||||
|
||||
*ifap = NULL;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifc.ifc_len = sizeof(buff);
|
||||
ifc.ifc_buf = buff;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
|
||||
n = ifc.ifc_len / sizeof(struct ifreq);
|
||||
|
||||
/* Loop through interfaces, looking for given IP address */
|
||||
for (i=n-1;i>=0 && total < max_interfaces;i--) {
|
||||
if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
}
|
||||
|
||||
curif = calloc(1, sizeof(struct ifaddrs));
|
||||
if (lastif == NULL) {
|
||||
*ifap = curif;
|
||||
} else {
|
||||
lastif->ifa_next = (*ifap);
|
||||
}
|
||||
|
||||
curif->ifa_name = strdup(ifr[i].ifr_name);
|
||||
curif->ifa_flags = ifreq.ifr_flags;
|
||||
curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr);
|
||||
curif->ifa_dstaddr = NULL;
|
||||
curif->ifa_data = NULL;
|
||||
curif->ifa_next = NULL;
|
||||
curif->ifa_netmask = NULL;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ifr[i].ifr_flags & IFF_UP)) {
|
||||
freeifaddrs(curif);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr);
|
||||
|
||||
lastif = curif;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_IFCONF */
|
||||
#ifdef HAVE_IFACE_IFREQ
|
||||
|
||||
#ifndef I_STR
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
this should cover most of the streams based systems
|
||||
Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
|
||||
****************************************************************************/
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
struct ifreq ifreq;
|
||||
struct strioctl strioctl;
|
||||
char buff[8192];
|
||||
int fd, i, n;
|
||||
struct ifreq *ifr=NULL;
|
||||
int total = 0;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
struct ifaddrs *curif;
|
||||
|
||||
*ifap = NULL;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFCONF;
|
||||
strioctl.ic_dp = buff;
|
||||
strioctl.ic_len = sizeof(buff);
|
||||
if (ioctl(fd, I_STR, &strioctl) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we can ignore the possible sizeof(int) here as the resulting
|
||||
number of interface structures won't change */
|
||||
n = strioctl.ic_len / sizeof(struct ifreq);
|
||||
|
||||
/* we will assume that the kernel returns the length as an int
|
||||
at the start of the buffer if the offered size is a
|
||||
multiple of the structure size plus an int */
|
||||
if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
|
||||
ifr = (struct ifreq *)(buff + sizeof(int));
|
||||
} else {
|
||||
ifr = (struct ifreq *)buff;
|
||||
}
|
||||
|
||||
/* Loop through interfaces */
|
||||
|
||||
for (i = 0; i<n && total < max_interfaces; i++) {
|
||||
ifreq = ifr[i];
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFFLAGS;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ifreq.ifr_flags & IFF_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFADDR;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curif = calloc(1, sizeof(struct ifaddrs));
|
||||
if (lastif == NULL) {
|
||||
*ifap = curif;
|
||||
} else {
|
||||
lastif->ifa_next = (*ifap);
|
||||
}
|
||||
|
||||
curif->ifa_name = strdup(ifreq.ifr_name);
|
||||
curif->ifa_flags = ifreq.ifr_flags;
|
||||
curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr);
|
||||
curif->ifa_dstaddr = NULL;
|
||||
curif->ifa_data = NULL;
|
||||
curif->ifa_next = NULL;
|
||||
curif->ifa_netmask = NULL;
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFNETMASK;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
freeifaddrs(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr);
|
||||
|
||||
lastif = curif;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_IFREQ */
|
||||
#ifdef HAVE_IFACE_AIX
|
||||
|
||||
/****************************************************************************
|
||||
this one is for AIX (tested on 4.2)
|
||||
****************************************************************************/
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
char buff[8192];
|
||||
int fd, i;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr=NULL;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
int total = 0;
|
||||
struct ifaddrs *curif, *lastif;
|
||||
|
||||
*ifap = NULL;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifc.ifc_len = sizeof(buff);
|
||||
ifc.ifc_buf = buff;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
|
||||
/* Loop through interfaces */
|
||||
i = ifc.ifc_len;
|
||||
|
||||
while (i > 0) {
|
||||
uint_t inc;
|
||||
|
||||
inc = ifr->ifr_addr.sa_len;
|
||||
|
||||
if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
|
||||
freeaddrinfo(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curif = calloc(1, sizeof(struct ifaddrs));
|
||||
if (lastif == NULL) {
|
||||
*ifap = curif;
|
||||
} else {
|
||||
lastif->ifa_next = (*ifap);
|
||||
}
|
||||
|
||||
curif->ifa_name = strdup(ifr->ifr_name);
|
||||
curif->ifa_flags = ifr->ifr_flags;
|
||||
curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr);
|
||||
curif->ifa_dstaddr = NULL;
|
||||
curif->ifa_data = NULL;
|
||||
curif->ifa_netmask = NULL;
|
||||
curif->ifa_next = NULL;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
|
||||
freeaddrinfo(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ifr->ifr_flags & IFF_UP)) {
|
||||
freeaddrinfo(curif);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
|
||||
freeaddrinfo(*ifap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr);
|
||||
|
||||
lastif = curif;
|
||||
|
||||
next:
|
||||
/*
|
||||
* Patch from Archie Cobbs (archie@whistle.com). The
|
||||
* addresses in the SIOCGIFCONF interface list have a
|
||||
* minimum size. Usually this doesn't matter, but if
|
||||
* your machine has tunnel interfaces, etc. that have
|
||||
* a zero length "link address", this does matter. */
|
||||
|
||||
if (inc < sizeof(ifr->ifr_addr))
|
||||
inc = sizeof(ifr->ifr_addr);
|
||||
inc += IFNAMSIZ;
|
||||
|
||||
ifr = (struct ifreq*) (((char*) ifr) + inc);
|
||||
i -= inc;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_AIX */
|
||||
#ifndef _FOUND_IFACE_ANY
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AUTOCONF_TEST
|
||||
/* this is the autoconf driver to test get_interfaces() */
|
||||
|
||||
int main()
|
||||
{
|
||||
struct ifaddrs *ifs;
|
||||
int total = get_interfaces(ifaces, MAX_INTERFACES);
|
||||
int i;
|
||||
|
||||
int ret = getifaddrs(&ifs);
|
||||
if (ret != 0) {
|
||||
perror("getifaddrs() failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (ifs) {
|
||||
printf("%-10s ", ifs->ifr_name);
|
||||
printf("IP=%s ", inet_ntoa(((struct sockaddr_in *)ifs->ifr_addr)->sin_addr));
|
||||
printf("NETMASK=%s\n", inet_ntoa(((struct sockaddr_in *)ifs->ifr_netmask)->sin_addr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
94
source4/lib/replace/getifaddrs.m4
Normal file
94
source4/lib/replace/getifaddrs.m4
Normal file
@ -0,0 +1,94 @@
|
||||
AC_CHECK_HEADERS([ifaddrs.h])
|
||||
|
||||
dnl test for getifaddrs and freeifaddrs
|
||||
AC_CACHE_CHECK([for getifaddrs and freeifaddrs],samba_cv_HAVE_GETIFADDRS,[
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>],
|
||||
[
|
||||
struct ifaddrs *ifp = NULL;
|
||||
int ret = getifaddrs (&ifp);
|
||||
freeifaddrs(ifp);
|
||||
],
|
||||
samba_cv_HAVE_GETIFADDRS=yes,samba_cv_HAVE_GETIFADDRS=no)])
|
||||
if test x"$samba_cv_HAVE_GETIFADDRS" = x"yes"; then
|
||||
AC_DEFINE(HAVE_GETIFADDRS,1,[Whether the system has getifaddrs])
|
||||
AC_DEFINE(HAVE_FREEIFADDRS,1,[Whether the system has freeifaddrs])
|
||||
AC_DEFINE(HAVE_STRUCT_IFADDRS,1,[Whether struct ifaddrs is available])
|
||||
fi
|
||||
|
||||
##################
|
||||
# look for a method of finding the list of network interfaces
|
||||
#
|
||||
# This tests need LIBS="$NSL_LIBS $SOCKET_LIBS"
|
||||
#
|
||||
old_CFLAGS=$CFLAGS
|
||||
old_LIBS=$LIBS
|
||||
LIBS="$NSL_LIBS $SOCKET_LIBS"
|
||||
CFLAGS="$CFLAGS -Ilib/replace"
|
||||
iface=no;
|
||||
##################
|
||||
# look for a method of finding the list of network interfaces
|
||||
iface=no;
|
||||
AC_CACHE_CHECK([for iface getifaddrs],samba_cv_HAVE_IFACE_GETIFADDRS,[
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
|
||||
AC_TRY_RUN([
|
||||
#define NO_CONFIG_H 1
|
||||
#define HAVE_IFACE_GETIFADDRS 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/replace/replace.c"
|
||||
#include "${srcdir-.}/lib/replace/getifaddrs.c"],
|
||||
samba_cv_HAVE_IFACE_GETIFADDRS=yes,samba_cv_HAVE_IFACE_GETIFADDRS=no,samba_cv_HAVE_IFACE_GETIFADDRS=cross)])
|
||||
CPPFLAGS="$SAVE_CPPFLAGS"
|
||||
if test x"$samba_cv_HAVE_IFACE_GETIFADDRS" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_GETIFADDRS,1,[Whether iface getifaddrs is available])
|
||||
else
|
||||
LIBREPLACEOBJ="${LIBREPLACEOBJ} getifaddrs.o"
|
||||
fi
|
||||
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_AIX 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#undef _XOPEN_SOURCE_EXTENDED
|
||||
#include "${srcdir-.}/lib/replace/getifaddrs.c"],
|
||||
samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_AIX" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface ifconf],samba_cv_HAVE_IFACE_IFCONF,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_IFCONF 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/replace/getifaddrs.c"],
|
||||
samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_IFCONF" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface ifreq],samba_cv_HAVE_IFACE_IFREQ,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_IFREQ 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/replace/getifaddrs.c"],
|
||||
samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
CFLAGS=$old_CFLAGS
|
||||
LIBS=$old_LIBS
|
@ -327,6 +327,7 @@ m4_include(inet_ntop.m4)
|
||||
m4_include(inet_pton.m4)
|
||||
m4_include(getaddrinfo.m4)
|
||||
m4_include(repdir.m4)
|
||||
m4_include(getifaddrs.m4)
|
||||
|
||||
AC_CHECK_FUNCS([syslog printf memset memcpy],,[AC_MSG_ERROR([Required function not found])])
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
networking system include wrappers
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
Copyright (C) Jelmer Vernooij 2007
|
||||
|
||||
** NOTE! The following LGPL license applies to the replace
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
@ -93,6 +94,30 @@ int rep_inet_pton(int af, const char *src, void *dst);
|
||||
const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_IFADDRS
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next; /* Pointer to next struct */
|
||||
char *ifa_name; /* Interface name */
|
||||
u_int ifa_flags; /* Interface flags */
|
||||
struct sockaddr *ifa_addr; /* Interface address */
|
||||
struct sockaddr *ifa_netmask; /* Interface netmask */
|
||||
struct sockaddr *ifa_dstaddr; /* P2P interface destination */
|
||||
void *ifa_data; /* Address specific data */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETIFADDRS
|
||||
int rep_getifaddrs(struct ifaddrs **);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FREEIFADDRS
|
||||
int rep_freeifaddrs(struct ifaddrs **);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some systems have getaddrinfo but not the
|
||||
* defines needed to use it.
|
||||
|
@ -96,96 +96,6 @@ fi
|
||||
dnl don't build ipv6 by default, unless the above test enables it, or
|
||||
dnl the configure uses --with-static-modules=socket_ipv6
|
||||
|
||||
AC_CHECK_HEADERS([ifaddrs.h])
|
||||
|
||||
dnl test for getifaddrs and freeifaddrs
|
||||
AC_CACHE_CHECK([for getifaddrs and freeifaddrs],samba_cv_HAVE_GETIFADDRS,[
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>],
|
||||
[
|
||||
struct ifaddrs *ifp = NULL;
|
||||
int ret = getifaddrs (&ifp);
|
||||
freeifaddrs(ifp);
|
||||
],
|
||||
samba_cv_HAVE_GETIFADDRS=yes,samba_cv_HAVE_GETIFADDRS=no)])
|
||||
if test x"$samba_cv_HAVE_GETIFADDRS" = x"yes"; then
|
||||
AC_DEFINE(HAVE_GETIFADDRS,1,[Whether the system has getifaddrs])
|
||||
AC_DEFINE(HAVE_FREEIFADDRS,1,[Whether the system has freeifaddrs])
|
||||
fi
|
||||
|
||||
|
||||
|
||||
##################
|
||||
# look for a method of finding the list of network interfaces
|
||||
#
|
||||
# This tests need LIBS="$NSL_LIBS $SOCKET_LIBS"
|
||||
#
|
||||
old_CFLAGS=$CFLAGS
|
||||
old_LIBS=$LIBS
|
||||
LIBS="$NSL_LIBS $SOCKET_LIBS"
|
||||
CFLAGS="$CFLAGS -Ilib/replace"
|
||||
iface=no;
|
||||
##################
|
||||
# look for a method of finding the list of network interfaces
|
||||
iface=no;
|
||||
AC_CACHE_CHECK([for iface getifaddrs],samba_cv_HAVE_IFACE_GETIFADDRS,[
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS ${SAMBA_CONFIGURE_CPPFLAGS}"
|
||||
AC_TRY_RUN([
|
||||
#define NO_CONFIG_H 1
|
||||
#define HAVE_IFACE_GETIFADDRS 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/replace/replace.c"
|
||||
#include "${srcdir-.}/lib/socket/netif.c"],
|
||||
samba_cv_HAVE_IFACE_GETIFADDRS=yes,samba_cv_HAVE_IFACE_GETIFADDRS=no,samba_cv_HAVE_IFACE_GETIFADDRS=cross)])
|
||||
CPPFLAGS="$SAVE_CPPFLAGS"
|
||||
if test x"$samba_cv_HAVE_IFACE_GETIFADDRS" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_GETIFADDRS,1,[Whether iface getifaddrs is available])
|
||||
fi
|
||||
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface AIX],samba_cv_HAVE_IFACE_AIX,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_AIX 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#undef _XOPEN_SOURCE_EXTENDED
|
||||
#include "${srcdir-.}/lib/socket/netif.c"],
|
||||
samba_cv_HAVE_IFACE_AIX=yes,samba_cv_HAVE_IFACE_AIX=no,samba_cv_HAVE_IFACE_AIX=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_AIX" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface ifconf],samba_cv_HAVE_IFACE_IFCONF,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_IFCONF 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/socket/netif.c"],
|
||||
samba_cv_HAVE_IFACE_IFCONF=yes,samba_cv_HAVE_IFACE_IFCONF=no,samba_cv_HAVE_IFACE_IFCONF=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_IFCONF" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $iface = no; then
|
||||
AC_CACHE_CHECK([for iface ifreq],samba_cv_HAVE_IFACE_IFREQ,[
|
||||
AC_TRY_RUN([
|
||||
#define HAVE_IFACE_IFREQ 1
|
||||
#define AUTOCONF_TEST 1
|
||||
#include "${srcdir-.}/lib/socket/netif.c"],
|
||||
samba_cv_HAVE_IFACE_IFREQ=yes,samba_cv_HAVE_IFACE_IFREQ=no,samba_cv_HAVE_IFACE_IFREQ=cross)])
|
||||
if test x"$samba_cv_HAVE_IFACE_IFREQ" = x"yes"; then
|
||||
iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available])
|
||||
fi
|
||||
fi
|
||||
|
||||
CFLAGS=$old_CFLAGS
|
||||
LIBS=$old_LIBS
|
||||
|
@ -31,60 +31,8 @@
|
||||
|
||||
*/
|
||||
|
||||
#define SOCKET_WRAPPER_NOT_REPLACE
|
||||
#ifndef AUTOCONF_TEST
|
||||
#include "includes.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifndef SIOCGIFCONF
|
||||
#ifdef HAVE_SYS_SOCKIO_H
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef __COMPAR_FN_T
|
||||
#define QSORT_CAST (__compar_fn_t)
|
||||
#endif
|
||||
|
||||
#ifndef QSORT_CAST
|
||||
#define QSORT_CAST (int (*)(const void *, const void *))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#include "system/network.h"
|
||||
#include "netif.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -92,7 +40,6 @@
|
||||
Also gets IPv6 interfaces.
|
||||
****************************************************************************/
|
||||
|
||||
#if HAVE_IFACE_GETIFADDRS
|
||||
/****************************************************************************
|
||||
Get the netmask address for a local interface.
|
||||
****************************************************************************/
|
||||
@ -141,277 +88,6 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
return total;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_GETIFADDRS */
|
||||
#if HAVE_IFACE_IFCONF
|
||||
|
||||
/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1
|
||||
V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2.
|
||||
|
||||
It probably also works on any BSD style system. */
|
||||
|
||||
/****************************************************************************
|
||||
get the netmask address for a local interface
|
||||
****************************************************************************/
|
||||
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
char buff[8192];
|
||||
int fd, i, n;
|
||||
struct ifreq *ifr=NULL;
|
||||
int total = 0;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifc.ifc_len = sizeof(buff);
|
||||
ifc.ifc_buf = buff;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
|
||||
n = ifc.ifc_len / sizeof(struct ifreq);
|
||||
|
||||
/* Loop through interfaces, looking for given IP address */
|
||||
for (i=n-1;i>=0 && total < max_interfaces;i--) {
|
||||
if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iname = ifr[i].ifr_name;
|
||||
ipaddr = (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ifr[i].ifr_flags & IFF_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nmask = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr;
|
||||
|
||||
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
|
||||
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
|
||||
ifaces[total].ip = ipaddr;
|
||||
ifaces[total].netmask = nmask;
|
||||
total++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_IFCONF */
|
||||
#ifdef HAVE_IFACE_IFREQ
|
||||
|
||||
#ifndef I_STR
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
this should cover most of the streams based systems
|
||||
Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code
|
||||
****************************************************************************/
|
||||
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
{
|
||||
struct ifreq ifreq;
|
||||
struct strioctl strioctl;
|
||||
char buff[8192];
|
||||
int fd, i, n;
|
||||
struct ifreq *ifr=NULL;
|
||||
int total = 0;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFCONF;
|
||||
strioctl.ic_dp = buff;
|
||||
strioctl.ic_len = sizeof(buff);
|
||||
if (ioctl(fd, I_STR, &strioctl) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we can ignore the possible sizeof(int) here as the resulting
|
||||
number of interface structures won't change */
|
||||
n = strioctl.ic_len / sizeof(struct ifreq);
|
||||
|
||||
/* we will assume that the kernel returns the length as an int
|
||||
at the start of the buffer if the offered size is a
|
||||
multiple of the structure size plus an int */
|
||||
if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) {
|
||||
ifr = (struct ifreq *)(buff + sizeof(int));
|
||||
} else {
|
||||
ifr = (struct ifreq *)buff;
|
||||
}
|
||||
|
||||
/* Loop through interfaces */
|
||||
|
||||
for (i = 0; i<n && total < max_interfaces; i++) {
|
||||
ifreq = ifr[i];
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFFLAGS;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ifreq.ifr_flags & IFF_UP)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFADDR;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ipaddr = (*(struct sockaddr_in *) &ifreq.ifr_addr).sin_addr;
|
||||
iname = ifreq.ifr_name;
|
||||
|
||||
strioctl.ic_cmd = SIOCGIFNETMASK;
|
||||
strioctl.ic_dp = (char *)&ifreq;
|
||||
strioctl.ic_len = sizeof(struct ifreq);
|
||||
if (ioctl(fd, I_STR, &strioctl) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
|
||||
|
||||
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
|
||||
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
|
||||
ifaces[total].ip = ipaddr;
|
||||
ifaces[total].netmask = nmask;
|
||||
|
||||
total++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_IFREQ */
|
||||
#ifdef HAVE_IFACE_AIX
|
||||
|
||||
/****************************************************************************
|
||||
this one is for AIX (tested on 4.2)
|
||||
****************************************************************************/
|
||||
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
{
|
||||
char buff[8192];
|
||||
int fd, i;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr=NULL;
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr nmask;
|
||||
char *iname;
|
||||
int total = 0;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ifc.ifc_len = sizeof(buff);
|
||||
ifc.ifc_buf = buff;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
|
||||
/* Loop through interfaces */
|
||||
i = ifc.ifc_len;
|
||||
|
||||
while (i > 0 && total < max_interfaces) {
|
||||
uint_t inc;
|
||||
|
||||
inc = ifr->ifr_addr.sa_len;
|
||||
|
||||
if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ipaddr = (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr;
|
||||
iname = ifr->ifr_name;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (!(ifr->ifr_flags & IFF_UP)) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
|
||||
|
||||
strncpy(ifaces[total].name, iname, sizeof(ifaces[total].name)-1);
|
||||
ifaces[total].name[sizeof(ifaces[total].name)-1] = 0;
|
||||
ifaces[total].ip = ipaddr;
|
||||
ifaces[total].netmask = nmask;
|
||||
|
||||
total++;
|
||||
|
||||
next:
|
||||
/*
|
||||
* Patch from Archie Cobbs (archie@whistle.com). The
|
||||
* addresses in the SIOCGIFCONF interface list have a
|
||||
* minimum size. Usually this doesn't matter, but if
|
||||
* your machine has tunnel interfaces, etc. that have
|
||||
* a zero length "link address", this does matter. */
|
||||
|
||||
if (inc < sizeof(ifr->ifr_addr))
|
||||
inc = sizeof(ifr->ifr_addr);
|
||||
inc += IFNAMSIZ;
|
||||
|
||||
ifr = (struct ifreq*) (((char*) ifr) + inc);
|
||||
i -= inc;
|
||||
}
|
||||
|
||||
|
||||
close(fd);
|
||||
return total;
|
||||
}
|
||||
|
||||
#define _FOUND_IFACE_ANY
|
||||
#endif /* HAVE_IFACE_AIX */
|
||||
#ifndef _FOUND_IFACE_ANY
|
||||
static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int iface_comp(struct iface_struct *i1, struct iface_struct *i2)
|
||||
{
|
||||
int r;
|
||||
@ -448,25 +124,3 @@ int get_interfaces(struct iface_struct *ifaces, int max_interfaces)
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
#ifdef AUTOCONF_TEST
|
||||
/* this is the autoconf driver to test get_interfaces() */
|
||||
|
||||
int main()
|
||||
{
|
||||
struct iface_struct ifaces[MAX_INTERFACES];
|
||||
int total = get_interfaces(ifaces, MAX_INTERFACES);
|
||||
int i;
|
||||
|
||||
printf("got %d interfaces:\n", total);
|
||||
if (total <= 0) exit(1);
|
||||
|
||||
for (i=0;i<total;i++) {
|
||||
printf("%-10s ", ifaces[i].name);
|
||||
printf("IP=%s ", inet_ntoa(ifaces[i].ip));
|
||||
printf("NETMASK=%s\n", inet_ntoa(ifaces[i].netmask));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user