2007-10-04 22:23:22 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-06-06 15:43:09 +04:00
multiple interface handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2007-10-11 05:25:16 +04:00
Copyright ( C ) Jeremy Allison 2007
2007-10-04 22:23:22 +04:00
1996-06-06 15:43:09 +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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-06-06 15:43:09 +04:00
( at your option ) any later version .
2007-10-04 22:23:22 +04:00
1996-06-06 15:43:09 +04:00
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 .
2007-10-04 22:23:22 +04:00
1996-06-06 15:43:09 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-06-06 15:43:09 +04:00
*/
# include "includes.h"
2011-05-02 06:20:21 +04:00
# include "lib/socket/interfaces.h"
2016-01-25 05:38:54 +03:00
# include "librpc/gen_ndr/ioctl.h"
1996-06-06 15:43:09 +04:00
1999-12-13 16:27:58 +03:00
static struct iface_struct * probed_ifaces ;
static int total_probed ;
2001-11-23 04:00:54 +03:00
static struct interface * local_interfaces ;
1996-06-29 23:27:12 +04:00
2007-10-11 05:25:16 +04:00
/****************************************************************************
Check if an IP is one of mine .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-23 21:53:15 +04:00
bool ismyaddr ( const struct sockaddr * ip )
2007-10-11 05:25:16 +04:00
{
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
2008-12-03 10:29:57 +03:00
if ( sockaddr_equal ( ( struct sockaddr * ) & i - > ip , ip ) ) {
2007-10-11 05:25:16 +04:00
return true ;
}
}
return false ;
}
bool ismyip_v4 ( struct in_addr ip )
{
struct sockaddr_storage ss ;
in_addr_to_sockaddr_storage ( & ss , ip ) ;
2008-10-23 21:53:15 +04:00
return ismyaddr ( ( struct sockaddr * ) & ss ) ;
2007-10-11 05:25:16 +04:00
}
1999-12-13 16:27:58 +03:00
1997-09-26 23:23:26 +04:00
/****************************************************************************
2007-10-04 22:23:22 +04:00
Try and find an interface that matches an ip . If we cannot , return NULL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-23 21:53:15 +04:00
static struct interface * iface_find ( const struct sockaddr * ip ,
2007-10-11 05:25:16 +04:00
bool check_mask )
1997-09-26 23:23:26 +04:00
{
1999-12-13 16:27:58 +03:00
struct interface * i ;
2007-10-11 05:25:16 +04:00
if ( is_address_any ( ip ) ) {
return local_interfaces ;
}
for ( i = local_interfaces ; i ; i = i - > next ) {
if ( check_mask ) {
2008-10-23 21:53:15 +04:00
if ( same_net ( ip , ( struct sockaddr * ) & i - > ip , ( struct sockaddr * ) & i - > netmask ) ) {
2007-10-11 05:25:16 +04:00
return i ;
}
2008-12-03 10:29:57 +03:00
} else if ( sockaddr_equal ( ( struct sockaddr * ) & i - > ip , ip ) ) {
2007-10-11 05:25:16 +04:00
return i ;
}
}
1999-12-13 16:27:58 +03:00
return NULL ;
1997-09-26 23:23:26 +04:00
}
2007-10-11 05:25:16 +04:00
/****************************************************************************
Check if a packet is from a local ( known ) net .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-23 21:53:15 +04:00
bool is_local_net ( const struct sockaddr * from )
2007-10-11 05:25:16 +04:00
{
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
2008-10-23 21:53:15 +04:00
if ( same_net ( from , ( struct sockaddr * ) & i - > ip , ( struct sockaddr * ) & i - > netmask ) ) {
2007-10-11 05:25:16 +04:00
return true ;
}
}
return false ;
}
2007-10-26 05:28:36 +04:00
# if defined(HAVE_IPV6)
2008-10-23 21:53:15 +04:00
void setup_linklocal_scope_id ( struct sockaddr * pss )
2007-10-26 05:28:36 +04:00
{
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
2008-12-03 10:29:57 +03:00
if ( sockaddr_equal ( ( struct sockaddr * ) & i - > ip , pss ) ) {
2007-10-26 05:28:36 +04:00
struct sockaddr_in6 * psa6 =
( struct sockaddr_in6 * ) pss ;
psa6 - > sin6_scope_id = if_nametoindex ( i - > name ) ;
return ;
}
}
}
# endif
2007-10-11 05:25:16 +04:00
/****************************************************************************
Check if a packet is from a local ( known ) net .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool is_local_net_v4 ( struct in_addr from )
{
struct sockaddr_storage ss ;
in_addr_to_sockaddr_storage ( & ss , from ) ;
2008-10-23 21:53:15 +04:00
return is_local_net ( ( struct sockaddr * ) & ss ) ;
2007-10-11 05:25:16 +04:00
}
/****************************************************************************
How many interfaces do we have ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int iface_count ( void )
{
int ret = 0 ;
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
ret + + ;
}
return ret ;
}
/****************************************************************************
2008-08-20 04:30:30 +04:00
How many non - loopback IPv4 interfaces do we have ?
2007-10-11 05:25:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-20 04:30:30 +04:00
int iface_count_v4_nl ( void )
2007-10-11 05:25:16 +04:00
{
int ret = 0 ;
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
2008-10-23 21:53:15 +04:00
if ( is_loopback_addr ( ( struct sockaddr * ) & i - > ip ) ) {
2008-08-20 04:30:30 +04:00
continue ;
}
2007-10-11 05:25:16 +04:00
if ( i - > ip . ss_family = = AF_INET ) {
ret + + ;
}
}
return ret ;
}
/****************************************************************************
2009-02-05 03:05:36 +03:00
Return a pointer to the in_addr of the first IPv4 interface that ' s
not 0.0 .0 .0 .
2007-10-11 05:25:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const struct in_addr * first_ipv4_iface ( void )
{
struct interface * i ;
for ( i = local_interfaces ; i ; i = i - > next ) {
2009-02-05 03:05:36 +03:00
if ( ( i - > ip . ss_family = = AF_INET ) & &
( ! is_zero_ip_v4 ( ( ( struct sockaddr_in * ) & i - > ip ) - > sin_addr ) ) )
{
2007-10-11 05:25:16 +04:00
break ;
}
}
if ( ! i ) {
return NULL ;
}
return & ( ( const struct sockaddr_in * ) & i - > ip ) - > sin_addr ;
}
/****************************************************************************
Return the Nth interface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct interface * get_interface ( int n )
{
struct interface * i ;
for ( i = local_interfaces ; i & & n ; i = i - > next ) {
n - - ;
}
if ( i ) {
return i ;
}
return NULL ;
}
/****************************************************************************
Return IP sockaddr_storage of the Nth interface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const struct sockaddr_storage * iface_n_sockaddr_storage ( int n )
{
struct interface * i ;
for ( i = local_interfaces ; i & & n ; i = i - > next ) {
n - - ;
}
if ( i ) {
return & i - > ip ;
}
return NULL ;
}
/****************************************************************************
Return IPv4 of the Nth interface ( if a v4 address ) . NULL otherwise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const struct in_addr * iface_n_ip_v4 ( int n )
{
struct interface * i ;
for ( i = local_interfaces ; i & & n ; i = i - > next ) {
n - - ;
}
if ( i & & i - > ip . ss_family = = AF_INET ) {
return & ( ( const struct sockaddr_in * ) & i - > ip ) - > sin_addr ;
}
return NULL ;
}
/****************************************************************************
Return IPv4 bcast of the Nth interface ( if a v4 address ) . NULL otherwise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const struct in_addr * iface_n_bcast_v4 ( int n )
{
struct interface * i ;
for ( i = local_interfaces ; i & & n ; i = i - > next ) {
n - - ;
}
if ( i & & i - > ip . ss_family = = AF_INET ) {
return & ( ( const struct sockaddr_in * ) & i - > bcast ) - > sin_addr ;
}
return NULL ;
}
/****************************************************************************
Return bcast of the Nth interface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const struct sockaddr_storage * iface_n_bcast ( int n )
{
struct interface * i ;
for ( i = local_interfaces ; i & & n ; i = i - > next ) {
n - - ;
}
if ( i ) {
return & i - > bcast ;
}
return NULL ;
}
/* these 3 functions return the ip/bcast/nmask for the interface
most appropriate for the given ip address . If they can ' t find
an appropriate interface they return the requested field of the
first known interface . */
2008-10-23 21:53:15 +04:00
const struct sockaddr_storage * iface_ip ( const struct sockaddr * ip )
2007-10-11 05:25:16 +04:00
{
struct interface * i = iface_find ( ip , true ) ;
if ( i ) {
return & i - > ip ;
}
/* Search for the first interface with
* matching address family . */
for ( i = local_interfaces ; i ; i = i - > next ) {
2008-10-23 21:53:15 +04:00
if ( i - > ip . ss_family = = ip - > sa_family ) {
2007-10-11 05:25:16 +04:00
return & i - > ip ;
}
}
return NULL ;
}
/*
return True if a IP is directly reachable on one of our interfaces
*/
2008-10-23 21:53:15 +04:00
bool iface_local ( const struct sockaddr * ip )
2007-10-11 05:25:16 +04:00
{
2008-10-24 01:20:50 +04:00
return iface_find ( ip , true ) ? true : false ;
2007-10-11 05:25:16 +04:00
}
1997-09-26 23:23:26 +04:00
/****************************************************************************
2007-10-04 22:23:22 +04:00
Add an interface to the linked list of interfaces .
1997-09-26 23:23:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 22:23:22 +04:00
2007-10-11 05:25:16 +04:00
static void add_interface ( const struct iface_struct * ifs )
1999-12-13 16:27:58 +03:00
{
2007-10-11 05:25:16 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
1999-12-13 16:27:58 +03:00
struct interface * iface ;
2007-10-11 05:25:16 +04:00
2011-05-06 00:42:05 +04:00
if ( iface_find ( ( const struct sockaddr * ) & ifs - > ip , False ) ) {
2007-10-11 05:25:16 +04:00
DEBUG ( 3 , ( " add_interface: not adding duplicate interface %s \n " ,
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , & ifs - > ip ) ) ) ;
1999-12-13 16:27:58 +03:00
return ;
1998-07-29 07:08:05 +04:00
}
1999-12-13 16:27:58 +03:00
2007-10-14 19:17:07 +04:00
if ( ! ( ifs - > flags & ( IFF_BROADCAST | IFF_LOOPBACK ) ) ) {
2007-10-04 22:23:22 +04:00
DEBUG ( 3 , ( " not adding non-broadcast interface %s \n " ,
2007-10-11 05:25:16 +04:00
ifs - > name ) ) ;
1999-12-13 16:27:58 +03:00
return ;
1997-09-26 23:23:26 +04:00
}
2004-12-07 21:25:53 +03:00
iface = SMB_MALLOC_P ( struct interface ) ;
2007-10-11 05:25:16 +04:00
if ( ! iface ) {
return ;
}
2007-10-04 22:23:22 +04:00
1999-12-13 16:27:58 +03:00
ZERO_STRUCTPN ( iface ) ;
2007-10-11 05:25:16 +04:00
iface - > name = SMB_STRDUP ( ifs - > name ) ;
if ( ! iface - > name ) {
SAFE_FREE ( iface ) ;
return ;
}
iface - > flags = ifs - > flags ;
iface - > ip = ifs - > ip ;
iface - > netmask = ifs - > netmask ;
iface - > bcast = ifs - > bcast ;
2016-01-25 16:09:37 +03:00
iface - > linkspeed = ifs - > linkspeed ;
iface - > capability = ifs - > capability ;
iface - > if_index = ifs - > if_index ;
1999-12-13 16:27:58 +03:00
DLIST_ADD ( local_interfaces , iface ) ;
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " added interface %s ip=%s " ,
iface - > name ,
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , & iface - > ip ) ) ) ;
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " bcast=%s " ,
print_sockaddr ( addr , sizeof ( addr ) ,
2007-10-25 01:16:54 +04:00
& iface - > bcast ) ) ) ;
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " netmask=%s \n " ,
print_sockaddr ( addr , sizeof ( addr ) ,
2007-10-25 01:16:54 +04:00
& iface - > netmask ) ) ) ;
2007-10-11 05:25:16 +04:00
}
2016-01-25 05:38:54 +03:00
static void parse_extra_info ( char * key , uint64_t * speed , uint32_t * cap ,
uint32_t * if_index )
{
while ( key ! = NULL & & * key ! = ' \0 ' ) {
char * next_key ;
char * val ;
next_key = strchr_m ( key , ' , ' ) ;
if ( next_key ! = NULL ) {
* next_key + + = 0 ;
}
val = strchr_m ( key , ' = ' ) ;
if ( val ! = NULL ) {
* val + + = 0 ;
if ( strequal_m ( key , " speed " ) ) {
* speed = ( uint64_t ) strtoull ( val , NULL , 0 ) ;
} else if ( strequal_m ( key , " capability " ) ) {
if ( strequal_m ( val , " RSS " ) ) {
* cap | = FSCTL_NET_IFACE_RSS_CAPABLE ;
} else if ( strequal ( val , " RDMA " ) ) {
* cap | = FSCTL_NET_IFACE_RDMA_CAPABLE ;
} else {
DBG_WARNING ( " Capability unknown: "
" '%s' \n " , val ) ;
}
} else if ( strequal_m ( key , " if_index " ) ) {
* if_index = ( uint32_t ) strtoul ( val , NULL , 0 ) ;
} else {
DBG_DEBUG ( " Key unknown: '%s' \n " , key ) ;
}
}
key = next_key ;
}
}
1996-06-06 15:43:09 +04:00
/****************************************************************************
2007-10-04 22:23:22 +04:00
Interpret a single element from a interfaces = config line .
1999-12-13 16:27:58 +03:00
2007-10-04 22:23:22 +04:00
This handles the following different forms :
1999-12-13 16:27:58 +03:00
2007-10-04 22:23:22 +04:00
1 ) wildcard interface name
2 ) DNS name
3 ) IP / masklen
4 ) ip / mask
5 ) bcast / mask
2016-01-25 05:38:54 +03:00
Additional information for an interface can be specified with
this extended syntax :
interface [ ; key1 = value1 [ , key2 = value2 [ . . . ] ] ]
where
- keys known : ' speed ' , ' capability ' , ' if_index '
- speed is in bits per second
- capabilites known : ' RSS ' , ' RDMA '
- if_index should be used with care , because
these indexes should not conicide with indexes
the kernel sets . . .
1996-06-06 15:43:09 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 22:23:22 +04:00
2004-06-25 03:27:00 +04:00
static void interpret_interface ( char * token )
1996-06-06 15:43:09 +04:00
{
2007-10-11 05:25:16 +04:00
struct sockaddr_storage ss ;
struct sockaddr_storage ss_mask ;
struct sockaddr_storage ss_net ;
struct sockaddr_storage ss_bcast ;
struct iface_struct ifs ;
1999-12-13 16:27:58 +03:00
char * p ;
2007-10-11 05:25:16 +04:00
int i ;
bool added = false ;
bool goodaddr = false ;
2016-01-25 05:38:54 +03:00
uint64_t speed = 0 ;
uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE ;
uint32_t if_index = 0 ;
bool speed_set = false ;
bool cap_set = false ;
bool if_index_set = false ;
2007-10-02 23:27:25 +04:00
1999-12-13 16:27:58 +03:00
/* first check if it is an interface name */
for ( i = 0 ; i < total_probed ; i + + ) {
2001-08-20 09:15:26 +04:00
if ( gen_fnmatch ( token , probed_ifaces [ i ] . name ) = = 0 ) {
2007-10-11 05:25:16 +04:00
add_interface ( & probed_ifaces [ i ] ) ;
added = true ;
1999-12-13 16:27:58 +03:00
}
}
2007-10-11 05:25:16 +04:00
if ( added ) {
return ;
}
1999-12-13 16:27:58 +03:00
2016-01-25 05:38:54 +03:00
/*
* extract speed / capability information if present
*/
p = strchr_m ( token , ' ; ' ) ;
if ( p ! = NULL ) {
* p + + = 0 ;
parse_extra_info ( p , & speed , & cap , & if_index ) ;
if ( speed ! = 0 ) {
speed_set = true ;
}
if ( cap ! = FSCTL_NET_IFACE_NONE_CAPABLE ) {
cap_set = true ;
}
if ( if_index ! = 0 ) {
if_index_set = true ;
}
}
2001-07-04 11:36:09 +04:00
p = strchr_m ( token , ' / ' ) ;
2007-10-13 18:27:52 +04:00
if ( p = = NULL ) {
2007-10-16 03:11:48 +04:00
if ( ! interpret_string_addr ( & ss , token , 0 ) ) {
2007-10-13 18:27:52 +04:00
DEBUG ( 2 , ( " interpret_interface: Can't find address "
" for %s \n " , token ) ) ;
return ;
}
1999-12-13 16:27:58 +03:00
for ( i = 0 ; i < total_probed ; i + + ) {
2015-09-22 02:27:48 +03:00
if ( sockaddr_equal ( ( struct sockaddr * ) & ss ,
( struct sockaddr * ) & probed_ifaces [ i ] . ip ) )
{
2016-01-25 05:38:54 +03:00
if ( speed_set ) {
probed_ifaces [ i ] . linkspeed = speed ;
}
if ( cap_set ) {
probed_ifaces [ i ] . capability = cap ;
}
if ( if_index_set ) {
probed_ifaces [ i ] . if_index = if_index ;
}
2007-10-11 05:25:16 +04:00
add_interface ( & probed_ifaces [ i ] ) ;
1999-12-13 16:27:58 +03:00
return ;
}
}
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " interpret_interface: "
" can't determine interface for %s \n " ,
token ) ) ;
1999-12-13 16:27:58 +03:00
return ;
}
/* parse it into an IP address/netmasklength pair */
2004-06-25 03:27:00 +04:00
* p = 0 ;
2007-10-16 03:11:48 +04:00
goodaddr = interpret_string_addr ( & ss , token , 0 ) ;
2004-06-25 03:27:00 +04:00
* p + + = ' / ' ;
1999-12-13 16:27:58 +03:00
2007-10-11 05:25:16 +04:00
if ( ! goodaddr ) {
DEBUG ( 2 , ( " interpret_interface: "
" can't determine interface for %s \n " ,
token ) ) ;
return ;
}
1999-12-13 16:27:58 +03:00
if ( strlen ( p ) > 2 ) {
2007-10-16 03:11:48 +04:00
goodaddr = interpret_string_addr ( & ss_mask , p , 0 ) ;
2007-10-11 05:25:16 +04:00
if ( ! goodaddr ) {
DEBUG ( 2 , ( " interpret_interface: "
" can't determine netmask from %s \n " ,
p ) ) ;
return ;
}
1999-12-13 16:27:58 +03:00
} else {
2007-10-11 05:25:16 +04:00
char * endp = NULL ;
unsigned long val = strtoul ( p , & endp , 0 ) ;
if ( p = = endp | | ( endp & & * endp ! = ' \0 ' ) ) {
DEBUG ( 2 , ( " interpret_interface: "
" can't determine netmask value from %s \n " ,
p ) ) ;
return ;
}
if ( ! make_netmask ( & ss_mask , & ss , val ) ) {
DEBUG ( 2 , ( " interpret_interface: "
" can't apply netmask value %lu from %s \n " ,
val ,
p ) ) ;
return ;
}
1999-12-13 16:27:58 +03:00
}
2007-10-11 05:25:16 +04:00
make_bcast ( & ss_bcast , & ss , & ss_mask ) ;
make_net ( & ss_net , & ss , & ss_mask ) ;
/* Maybe the first component was a broadcast address. */
2008-12-03 10:29:57 +03:00
if ( sockaddr_equal ( ( struct sockaddr * ) & ss_bcast , ( struct sockaddr * ) & ss ) | |
sockaddr_equal ( ( struct sockaddr * ) & ss_net , ( struct sockaddr * ) & ss ) ) {
1999-12-13 16:27:58 +03:00
for ( i = 0 ; i < total_probed ; i + + ) {
2008-10-23 21:53:15 +04:00
if ( same_net ( ( struct sockaddr * ) & ss ,
( struct sockaddr * ) & probed_ifaces [ i ] . ip ,
( struct sockaddr * ) & ss_mask ) ) {
2007-10-11 05:25:16 +04:00
/* Temporarily replace netmask on
* the detected interface - user knows
* best . . . . */
struct sockaddr_storage saved_mask =
probed_ifaces [ i ] . netmask ;
probed_ifaces [ i ] . netmask = ss_mask ;
DEBUG ( 2 , ( " interpret_interface: "
" using netmask value %s from "
" config file on interface %s \n " ,
p ,
probed_ifaces [ i ] . name ) ) ;
2016-01-25 05:38:54 +03:00
if ( speed_set ) {
probed_ifaces [ i ] . linkspeed = speed ;
}
if ( cap_set ) {
probed_ifaces [ i ] . capability = cap ;
}
if ( if_index_set ) {
probed_ifaces [ i ] . if_index = if_index ;
}
2007-10-11 05:25:16 +04:00
add_interface ( & probed_ifaces [ i ] ) ;
probed_ifaces [ i ] . netmask = saved_mask ;
1999-12-13 16:27:58 +03:00
return ;
}
}
2007-10-11 05:25:16 +04:00
DEBUG ( 2 , ( " interpret_interface: Can't determine ip for "
" broadcast address %s \n " ,
token ) ) ;
1999-12-13 16:27:58 +03:00
return ;
}
2007-10-11 05:25:16 +04:00
/* Just fake up the interface definition. User knows best. */
DEBUG ( 2 , ( " interpret_interface: Adding interface %s \n " ,
token ) ) ;
ZERO_STRUCT ( ifs ) ;
2008-07-03 03:31:16 +04:00
( void ) strlcpy ( ifs . name , token , sizeof ( ifs . name ) ) ;
2007-10-11 05:25:16 +04:00
ifs . flags = IFF_BROADCAST ;
ifs . ip = ss ;
ifs . netmask = ss_mask ;
ifs . bcast = ss_bcast ;
2016-01-25 05:38:54 +03:00
if ( if_index_set ) {
probed_ifaces [ i ] . if_index = if_index ;
}
if ( speed_set ) {
ifs . linkspeed = speed ;
} else {
ifs . linkspeed = 1000 * 1000 * 1000 ;
}
ifs . capability = cap ;
2007-10-11 05:25:16 +04:00
add_interface ( & ifs ) ;
1996-06-06 15:43:09 +04:00
}
1996-06-29 23:27:12 +04:00
/****************************************************************************
2007-10-04 22:23:22 +04:00
Load the list of network interfaces .
1996-06-29 23:27:12 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 22:23:22 +04:00
1996-06-29 23:27:12 +04:00
void load_interfaces ( void )
{
2009-05-18 12:32:27 +04:00
struct iface_struct * ifaces = NULL ;
2007-10-11 05:25:16 +04:00
const char * * ptr = lp_interfaces ( ) ;
int i ;
1999-12-13 16:27:58 +03:00
2009-11-18 17:19:09 +03:00
gfree_interfaces ( ) ;
1999-12-13 16:27:58 +03:00
2007-10-11 05:25:16 +04:00
/* Probe the kernel for interfaces */
2009-05-18 12:32:27 +04:00
total_probed = get_interfaces ( talloc_tos ( ) , & ifaces ) ;
1999-12-13 16:27:58 +03:00
if ( total_probed > 0 ) {
2014-04-14 16:37:29 +04:00
probed_ifaces = ( struct iface_struct * ) smb_memdup ( ifaces ,
2007-10-04 22:23:22 +04:00
sizeof ( ifaces [ 0 ] ) * total_probed ) ;
2006-06-28 04:50:14 +04:00
if ( ! probed_ifaces ) {
2014-04-14 16:37:29 +04:00
DEBUG ( 0 , ( " ERROR: smb_memdup failed \n " ) ) ;
2006-06-28 04:50:14 +04:00
exit ( 1 ) ;
}
1999-12-13 16:27:58 +03:00
}
2009-05-18 12:32:27 +04:00
TALLOC_FREE ( ifaces ) ;
1999-12-13 16:27:58 +03:00
2007-10-04 22:23:22 +04:00
/* if we don't have a interfaces line then use all broadcast capable
1999-12-13 16:27:58 +03:00
interfaces except loopback */
2001-07-02 03:24:08 +04:00
if ( ! ptr | | ! * ptr | | ! * * ptr ) {
1999-12-13 16:27:58 +03:00
if ( total_probed < = 0 ) {
2007-10-04 22:23:22 +04:00
DEBUG ( 0 , ( " ERROR: Could not determine network "
" interfaces, you must use a interfaces config line \n " ) ) ;
1999-12-13 16:27:58 +03:00
exit ( 1 ) ;
}
for ( i = 0 ; i < total_probed ; i + + ) {
2007-10-11 05:25:16 +04:00
if ( probed_ifaces [ i ] . flags & IFF_BROADCAST ) {
add_interface ( & probed_ifaces [ i ] ) ;
1999-12-13 16:27:58 +03:00
}
}
return ;
}
2001-07-03 04:54:55 +04:00
if ( ptr ) {
while ( * ptr ) {
2004-12-07 21:25:53 +03:00
char * ptr_cpy = SMB_STRDUP ( * ptr ) ;
2004-06-25 03:27:00 +04:00
if ( ptr_cpy ) {
interpret_interface ( ptr_cpy ) ;
free ( ptr_cpy ) ;
}
2001-07-03 04:54:55 +04:00
ptr + + ;
}
1999-12-13 16:27:58 +03:00
}
if ( ! local_interfaces ) {
DEBUG ( 0 , ( " WARNING: no network interfaces found \n " ) ) ;
}
1996-06-29 23:27:12 +04:00
}
2007-03-16 17:13:46 +03:00
void gfree_interfaces ( void )
{
while ( local_interfaces ) {
struct interface * iface = local_interfaces ;
DLIST_REMOVE ( local_interfaces , local_interfaces ) ;
2007-10-11 05:25:16 +04:00
SAFE_FREE ( iface - > name ) ;
2007-03-16 17:13:46 +03:00
SAFE_FREE ( iface ) ;
}
SAFE_FREE ( probed_ifaces ) ;
}
1996-06-06 15:43:09 +04:00
/****************************************************************************
2007-10-04 22:23:22 +04:00
Return True if the list of probed interfaces has changed .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 22:23:22 +04:00
2007-10-11 05:25:16 +04:00
bool interfaces_changed ( void )
1996-06-06 15:43:09 +04:00
{
2009-05-18 12:32:27 +04:00
bool ret = false ;
1999-12-13 16:27:58 +03:00
int n ;
2009-05-18 12:32:27 +04:00
struct iface_struct * ifaces = NULL ;
1999-12-13 16:27:58 +03:00
2009-05-18 12:32:27 +04:00
n = get_interfaces ( talloc_tos ( ) , & ifaces ) ;
1999-12-13 16:27:58 +03:00
2000-11-10 22:02:32 +03:00
if ( ( n > 0 ) & & ( n ! = total_probed | |
2007-10-11 05:25:16 +04:00
memcmp ( ifaces , probed_ifaces , sizeof ( ifaces [ 0 ] ) * n ) ) ) {
2009-05-18 12:32:27 +04:00
ret = true ;
1999-12-13 16:27:58 +03:00
}
1996-06-06 15:43:09 +04:00
2009-05-18 12:32:27 +04:00
TALLOC_FREE ( ifaces ) ;
return ret ;
1996-06-06 15:43:09 +04:00
}