2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
return a list of network interfaces
Copyright ( C ) Andrew Tridgell 1998
2007-12-12 00:23:31 +03:00
Copyright ( C ) Jeremy Allison 2007
Copyright ( C ) Jelmer Vernooij 2007
2003-08-13 05:53:07 +04:00
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
/* working out the interfaces for a OS is an incredibly non-portable
thing . We have several possible implementations below , and autoconf
tries each of them to see what works
Note that this file does _not_ include includes . h . That is so this code
can be called directly from the autoconf tests . That also means
this code cannot use any of the normal Samba debug stuff or defines .
This is standalone code .
*/
2006-09-20 06:09:14 +04:00
# include "includes.h"
2007-12-16 04:39:01 +03:00
# include "system/network.h"
2005-07-18 13:46:52 +04:00
# include "netif.h"
2007-12-12 00:23:31 +03:00
/****************************************************************************
Try the " standard " getifaddrs / freeifaddrs interfaces .
Also gets IPv6 interfaces .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
Get the netmask address for a local interface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int _get_interfaces ( struct iface_struct * ifaces , int max_interfaces )
{
struct ifaddrs * iflist = NULL ;
struct ifaddrs * ifptr = NULL ;
int total = 0 ;
if ( getifaddrs ( & iflist ) < 0 ) {
return - 1 ;
}
/* Loop through interfaces, looking for given IP address */
for ( ifptr = iflist , total = 0 ;
ifptr ! = NULL & & total < max_interfaces ;
ifptr = ifptr - > ifa_next ) {
memset ( & ifaces [ total ] , ' \0 ' , sizeof ( ifaces [ total ] ) ) ;
if ( ! ifptr - > ifa_addr | | ! ifptr - > ifa_netmask ) {
continue ;
}
/* Check the interface is up. */
if ( ! ( ifptr - > ifa_flags & IFF_UP ) ) {
continue ;
}
/* We don't support IPv6 *yet* */
if ( ifptr - > ifa_addr - > sa_family ! = AF_INET ) {
continue ;
}
ifaces [ total ] . ip = ( ( struct sockaddr_in * ) ifptr - > ifa_addr ) - > sin_addr ;
ifaces [ total ] . netmask = ( ( struct sockaddr_in * ) ifptr - > ifa_netmask ) - > sin_addr ;
strlcpy ( ifaces [ total ] . name , ifptr - > ifa_name ,
sizeof ( ifaces [ total ] . name ) ) ;
total + + ;
}
freeifaddrs ( iflist ) ;
return total ;
}
2003-08-13 05:53:07 +04:00
static int iface_comp ( struct iface_struct * i1 , struct iface_struct * i2 )
{
int r ;
r = strcmp ( i1 - > name , i2 - > name ) ;
if ( r ) return r ;
r = ntohl ( i1 - > ip . s_addr ) - ntohl ( i2 - > ip . s_addr ) ;
if ( r ) return r ;
r = ntohl ( i1 - > netmask . s_addr ) - ntohl ( i2 - > netmask . s_addr ) ;
return r ;
}
/* this wrapper is used to remove duplicates from the interface list generated
above */
int get_interfaces ( struct iface_struct * ifaces , int max_interfaces )
{
int total , i , j ;
total = _get_interfaces ( ifaces , max_interfaces ) ;
if ( total < = 0 ) return total ;
/* now we need to remove duplicates */
qsort ( ifaces , total , sizeof ( ifaces [ 0 ] ) , QSORT_CAST iface_comp ) ;
for ( i = 1 ; i < total ; ) {
if ( iface_comp ( & ifaces [ i - 1 ] , & ifaces [ i ] ) = = 0 ) {
for ( j = i - 1 ; j < total - 1 ; j + + ) {
ifaces [ j ] = ifaces [ j + 1 ] ;
}
total - - ;
} else {
i + + ;
}
}
return total ;
}