From be4decb2b73e3431155663c2dae3a8452ecde28a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 16 Dec 2007 02:39:01 +0100 Subject: r26467: Use getifaddrs() for interface enumeration and provide replacements for platforms that don't have it in lib/replace. (This used to be commit 9b4924fbd8619033c55b4c6e2589da247332e7db) --- source4/lib/replace/getifaddrs.c | 391 +++++++++++++++++++++++++++++++++++ source4/lib/replace/getifaddrs.m4 | 94 +++++++++ source4/lib/replace/libreplace.m4 | 1 + source4/lib/replace/system/network.h | 25 +++ source4/lib/socket/config.m4 | 90 -------- source4/lib/socket/netif.c | 348 +------------------------------ 6 files changed, 512 insertions(+), 437 deletions(-) create mode 100644 source4/lib/replace/getifaddrs.c create mode 100644 source4/lib/replace/getifaddrs.m4 (limited to 'source4') diff --git a/source4/lib/replace/getifaddrs.c b/source4/lib/replace/getifaddrs.c new file mode 100644 index 0000000000..3969535a0b --- /dev/null +++ b/source4/lib/replace/getifaddrs.c @@ -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 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 . +*/ + +#include "replace.h" +#include "system/network.h" + +#include +#include +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include +#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 +#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; iifa_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 diff --git a/source4/lib/replace/getifaddrs.m4 b/source4/lib/replace/getifaddrs.m4 new file mode 100644 index 0000000000..f38827406d --- /dev/null +++ b/source4/lib/replace/getifaddrs.m4 @@ -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 +#include +#include +#include +#include +#include ], +[ +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 diff --git a/source4/lib/replace/libreplace.m4 b/source4/lib/replace/libreplace.m4 index c10a4b2381..7e456b4d03 100644 --- a/source4/lib/replace/libreplace.m4 +++ b/source4/lib/replace/libreplace.m4 @@ -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])]) diff --git a/source4/lib/replace/system/network.h b/source4/lib/replace/system/network.h index d3ae2bf398..45d84e0386 100644 --- a/source4/lib/replace/system/network.h +++ b/source4/lib/replace/system/network.h @@ -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 +#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. diff --git a/source4/lib/socket/config.m4 b/source4/lib/socket/config.m4 index f8a4915adb..a713090c6d 100644 --- a/source4/lib/socket/config.m4 +++ b/source4/lib/socket/config.m4 @@ -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 -#include -#include -#include -#include -#include ], -[ -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 diff --git a/source4/lib/socket/netif.c b/source4/lib/socket/netif.c index cd9ea6c977..bf410af441 100644 --- a/source4/lib/socket/netif.c +++ b/source4/lib/socket/netif.c @@ -31,60 +31,8 @@ */ -#define SOCKET_WRAPPER_NOT_REPLACE -#ifndef AUTOCONF_TEST #include "includes.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#ifndef SIOCGIFCONF -#ifdef HAVE_SYS_SOCKIO_H -#include -#endif -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef HAVE_STRING_H -#include -#endif - -#ifdef HAVE_STRINGS_H -#include -#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 -#endif - -#ifdef HAVE_NET_IF_H -#include -#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 -#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; isin_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