1996-06-04 10:42:03 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-06-04 10:42:03 +04:00
name query routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1996-06-04 10:42:03 +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
the Free Software Foundation ; either version 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
1998-03-16 23:59:47 +03:00
/* nmbd.c sets this to True. */
BOOL global_in_nmbd = False ;
1996-06-04 10:42:03 +04:00
2000-01-03 06:17:16 +03:00
/****************************************************************************
2003-06-14 01:03:15 +04:00
Generate a random trn_id .
2000-01-03 06:17:16 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-14 01:03:15 +04:00
2000-01-03 06:17:16 +03:00
static int generate_trn_id ( void )
{
static int trn_id ;
if ( trn_id = = 0 ) {
2000-06-01 21:01:34 +04:00
sys_srandom ( sys_getpid ( ) ) ;
2000-01-03 06:17:16 +03:00
}
2000-06-01 21:01:34 +04:00
trn_id = sys_random ( ) ;
2000-01-03 06:17:16 +03:00
return trn_id % ( unsigned ) 0x7FFF ;
}
1996-06-04 10:42:03 +04:00
/****************************************************************************
2003-06-14 01:03:15 +04:00
Parse a node status response into an array of structures .
1996-06-04 10:42:03 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-14 01:03:15 +04:00
2000-12-20 06:22:51 +03:00
static struct node_status * parse_node_status ( char * p , int * num_names )
1996-06-04 10:42:03 +04:00
{
2000-12-20 06:22:51 +03:00
struct node_status * ret ;
int i ;
1996-06-04 10:42:03 +04:00
2000-12-20 06:22:51 +03:00
* num_names = CVAL ( p , 0 ) ;
2003-06-14 01:03:15 +04:00
if ( * num_names = = 0 )
return NULL ;
2000-12-20 06:22:51 +03:00
ret = ( struct node_status * ) malloc ( sizeof ( struct node_status ) * ( * num_names ) ) ;
if ( ! ret ) return NULL ;
1999-12-13 16:27:58 +03:00
2000-12-20 06:22:51 +03:00
p + + ;
for ( i = 0 ; i < * num_names ; i + + ) {
StrnCpy ( ret [ i ] . name , p , 15 ) ;
2003-09-05 23:59:55 +04:00
trim_char ( ret [ i ] . name , ' \0 ' , ' ' ) ;
2000-12-20 06:22:51 +03:00
ret [ i ] . type = CVAL ( p , 15 ) ;
ret [ i ] . flags = p [ 16 ] ;
p + = 18 ;
2002-01-21 01:50:23 +03:00
DEBUG ( 10 , ( " %s#%02x: flags = 0x%02x \n " , ret [ i ] . name ,
ret [ i ] . type , ret [ i ] . flags ) ) ;
2000-12-20 06:22:51 +03:00
}
return ret ;
1996-06-04 10:42:03 +04:00
}
2000-12-20 06:22:51 +03:00
1996-06-04 10:42:03 +04:00
/****************************************************************************
2003-06-14 01:03:15 +04:00
Do a NBT node status query on an open socket and return an array of
structures holding the returned names or NULL if the query failed .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-14 01:03:15 +04:00
2001-08-29 08:26:27 +04:00
struct node_status * node_status_query ( int fd , struct nmb_name * name ,
2000-12-20 06:22:51 +03:00
struct in_addr to_ip , int * num_names )
1996-06-04 10:42:03 +04:00
{
2000-12-20 06:22:51 +03:00
BOOL found = False ;
int retries = 2 ;
int retry_time = 2000 ;
struct timeval tval ;
struct packet_struct p ;
struct packet_struct * p2 ;
struct nmb_packet * nmb = & p . packet . nmb ;
struct node_status * ret ;
ZERO_STRUCT ( p ) ;
nmb - > header . name_trn_id = generate_trn_id ( ) ;
nmb - > header . opcode = 0 ;
nmb - > header . response = False ;
nmb - > header . nm_flags . bcast = False ;
nmb - > header . nm_flags . recursion_available = False ;
nmb - > header . nm_flags . recursion_desired = False ;
nmb - > header . nm_flags . trunc = False ;
nmb - > header . nm_flags . authoritative = False ;
nmb - > header . rcode = 0 ;
nmb - > header . qdcount = 1 ;
nmb - > header . ancount = 0 ;
nmb - > header . nscount = 0 ;
nmb - > header . arcount = 0 ;
nmb - > question . question_name = * name ;
nmb - > question . question_type = 0x21 ;
nmb - > question . question_class = 0x1 ;
p . ip = to_ip ;
p . port = NMB_PORT ;
p . fd = fd ;
p . timestamp = time ( NULL ) ;
p . packet_type = NMB_PACKET ;
GetTimeOfDay ( & tval ) ;
if ( ! send_packet ( & p ) )
return NULL ;
retries - - ;
while ( 1 ) {
struct timeval tval2 ;
GetTimeOfDay ( & tval2 ) ;
if ( TvalDiff ( & tval , & tval2 ) > retry_time ) {
if ( ! retries )
break ;
if ( ! found & & ! send_packet ( & p ) )
return NULL ;
GetTimeOfDay ( & tval ) ;
retries - - ;
}
1996-06-04 10:42:03 +04:00
2000-12-20 06:22:51 +03:00
if ( ( p2 = receive_nmb_packet ( fd , 90 , nmb - > header . name_trn_id ) ) ) {
struct nmb_packet * nmb2 = & p2 - > packet . nmb ;
debug_nmb_packet ( p2 ) ;
if ( nmb2 - > header . opcode ! = 0 | |
nmb2 - > header . nm_flags . bcast | |
nmb2 - > header . rcode | |
! nmb2 - > header . ancount | |
nmb2 - > answers - > rr_type ! = 0x21 ) {
/* XXXX what do we do with this? could be a
redirect , but we ' ll discard it for the
moment */
free_packet ( p2 ) ;
continue ;
}
1996-06-04 10:42:03 +04:00
2000-12-20 06:22:51 +03:00
ret = parse_node_status ( & nmb2 - > answers - > rdata [ 0 ] , num_names ) ;
free_packet ( p2 ) ;
return ret ;
}
}
return NULL ;
}
1999-12-13 16:27:58 +03:00
2000-12-20 06:22:51 +03:00
/****************************************************************************
2003-06-14 01:03:15 +04:00
Find the first type XX name in a node status reply - used for finding
a servers name given its IP . Return the matched name in * name .
2000-12-20 06:22:51 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-22 02:00:59 +03:00
2004-03-13 05:16:21 +03:00
BOOL name_status_find ( const char * q_name , int q_type , int type , struct in_addr to_ip , fstring name )
2000-12-20 06:22:51 +03:00
{
2002-01-16 04:41:30 +03:00
struct node_status * status = NULL ;
2000-12-20 06:22:51 +03:00
struct nmb_name nname ;
int count , i ;
int sock ;
2002-01-16 04:41:30 +03:00
BOOL result = False ;
2002-08-17 21:00:51 +04:00
if ( lp_disable_netbios ( ) ) {
DEBUG ( 5 , ( " name_status_find(%s#%02x): netbios is disabled \n " , q_name , q_type ) ) ;
return False ;
}
2002-01-17 08:07:36 +03:00
DEBUG ( 10 , ( " name_status_find: looking up %s#%02x at %s \n " , q_name ,
q_type , inet_ntoa ( to_ip ) ) ) ;
1996-06-04 10:42:03 +04:00
2003-06-14 01:03:15 +04:00
/* Check the cache first. */
if ( namecache_status_fetch ( q_name , q_type , type , to_ip , name ) )
return True ;
2000-12-20 06:22:51 +03:00
sock = open_socket_in ( SOCK_DGRAM , 0 , 3 , interpret_addr ( lp_socket_address ( ) ) , True ) ;
2001-11-22 02:00:59 +03:00
if ( sock = = - 1 )
2002-01-16 04:41:30 +03:00
goto done ;
2000-01-03 06:17:16 +03:00
2001-11-22 02:00:59 +03:00
/* W2K PDC's seem not to respond to '*'#0. JRA */
make_nmb_name ( & nname , q_name , q_type ) ;
2001-08-29 08:26:27 +04:00
status = node_status_query ( sock , & nname , to_ip , & count ) ;
2000-12-20 06:22:51 +03:00
close ( sock ) ;
2001-11-22 02:00:59 +03:00
if ( ! status )
2002-01-16 04:41:30 +03:00
goto done ;
2000-01-03 06:17:16 +03:00
2000-12-20 06:22:51 +03:00
for ( i = 0 ; i < count ; i + + ) {
2001-11-22 02:00:59 +03:00
if ( status [ i ] . type = = type )
break ;
2000-12-20 06:22:51 +03:00
}
2001-11-22 02:00:59 +03:00
if ( i = = count )
2002-01-16 04:41:30 +03:00
goto done ;
1996-06-04 10:42:03 +04:00
2004-03-13 05:16:21 +03:00
pull_ascii_nstring ( name , sizeof ( fstring ) , status [ i ] . name ) ;
2003-06-14 01:03:15 +04:00
/* Store the result in the cache. */
2003-06-25 21:41:05 +04:00
/* but don't store an entry for 0x1c names here. Here we have
a single host and DOMAIN < 0x1c > names should be a list of hosts */
if ( q_type ! = 0x1c )
namecache_status_store ( q_name , q_type , type , to_ip , name ) ;
2003-06-14 01:03:15 +04:00
2002-01-16 04:41:30 +03:00
result = True ;
2001-02-14 08:34:50 +03:00
2002-01-16 04:41:30 +03:00
done :
2001-09-17 07:33:37 +04:00
SAFE_FREE ( status ) ;
2002-01-16 04:41:30 +03:00
DEBUG ( 10 , ( " name_status_find: name %sfound " , result ? " " : " not " ) ) ;
if ( result )
2003-06-14 01:03:15 +04:00
DEBUGADD ( 10 , ( " , name %s ip address is %s " , name , inet_ntoa ( to_ip ) ) ) ;
2002-01-16 04:41:30 +03:00
DEBUG ( 10 , ( " \n " ) ) ;
return result ;
1996-06-04 10:42:03 +04:00
}
2002-07-15 14:35:28 +04:00
/*
comparison function used by sort_ip_list
*/
2003-06-14 01:03:15 +04:00
2004-02-08 03:54:32 +03:00
static int ip_compare ( struct in_addr * ip1 , struct in_addr * ip2 )
2002-07-15 14:35:28 +04:00
{
int max_bits1 = 0 , max_bits2 = 0 ;
int num_interfaces = iface_count ( ) ;
int i ;
2001-02-18 13:36:03 +03:00
2002-07-15 14:35:28 +04:00
for ( i = 0 ; i < num_interfaces ; i + + ) {
struct in_addr ip ;
int bits1 , bits2 ;
ip = * iface_n_bcast ( i ) ;
bits1 = matching_quad_bits ( ( uchar * ) & ip1 - > s_addr , ( uchar * ) & ip . s_addr ) ;
bits2 = matching_quad_bits ( ( uchar * ) & ip2 - > s_addr , ( uchar * ) & ip . s_addr ) ;
max_bits1 = MAX ( bits1 , max_bits1 ) ;
max_bits2 = MAX ( bits2 , max_bits2 ) ;
}
/* bias towards directly reachable IPs */
if ( iface_local ( * ip1 ) ) {
max_bits1 + = 32 ;
}
if ( iface_local ( * ip2 ) ) {
max_bits2 + = 32 ;
}
2001-02-18 13:36:03 +03:00
2002-07-15 14:35:28 +04:00
return max_bits2 - max_bits1 ;
}
2001-02-18 13:36:03 +03:00
2003-06-25 21:41:05 +04:00
/*******************************************************************
compare 2 ldap IPs by nearness to our interfaces - used in qsort
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int ip_service_compare ( struct ip_service * ip1 , struct ip_service * ip2 )
{
int result ;
if ( ( result = ip_compare ( & ip1 - > ip , & ip2 - > ip ) ) ! = 0 )
return result ;
if ( ip1 - > port > ip2 - > port )
return 1 ;
if ( ip1 - > port < ip2 - > port )
return - 1 ;
return 0 ;
}
2002-07-15 14:35:28 +04:00
/*
sort an IP list so that names that are close to one of our interfaces
are at the top . This prevents the problem where a WINS server returns an IP that
is not reachable from our subnet as the first match
*/
2003-06-14 01:03:15 +04:00
2002-07-15 14:35:28 +04:00
static void sort_ip_list ( struct in_addr * iplist , int count )
{
if ( count < = 1 ) {
return ;
}
2001-02-18 13:36:03 +03:00
2002-07-15 14:35:28 +04:00
qsort ( iplist , count , sizeof ( struct in_addr ) , QSORT_CAST ip_compare ) ;
2001-02-18 13:36:03 +03:00
}
1996-06-04 10:42:03 +04:00
2004-02-08 03:54:32 +03:00
static void sort_ip_list2 ( struct ip_service * iplist , int count )
2003-06-25 21:41:05 +04:00
{
if ( count < = 1 ) {
return ;
}
qsort ( iplist , count , sizeof ( struct ip_service ) , QSORT_CAST ip_service_compare ) ;
}
/**********************************************************************
Remove any duplicate address / port pairs in the list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int remove_duplicate_addrs2 ( struct ip_service * iplist , int count )
{
int i , j ;
DEBUG ( 10 , ( " remove_duplicate_addrs2: looking for duplicate address/port pairs \n " ) ) ;
/* one loop to remove duplicates */
for ( i = 0 ; i < count ; i + + ) {
if ( is_zero_ip ( iplist [ i ] . ip ) )
continue ;
for ( j = i + 1 ; j < count ; j + + ) {
if ( ip_service_equal ( iplist [ i ] , iplist [ j ] ) )
zero_ip ( & iplist [ j ] . ip ) ;
}
}
/* one loop to clean up any holes we left */
/* first ip should never be a zero_ip() */
for ( i = 0 ; i < count ; ) {
if ( is_zero_ip ( iplist [ i ] . ip ) ) {
if ( i ! = count - 1 )
memmove ( & iplist [ i ] , & iplist [ i + 1 ] , ( count - i - 1 ) * sizeof ( iplist [ i ] ) ) ;
count - - ;
continue ;
}
i + + ;
}
return count ;
}
1996-06-04 10:42:03 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Do a netbios name query to find someones IP .
Returns an array of IP addresses or NULL if none .
* count will be set to the number of addresses returned .
2002-07-15 14:35:28 +04:00
* timed_out is set if we failed by timing out
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-14 01:03:15 +04:00
2000-01-03 06:17:16 +03:00
struct in_addr * name_query ( int fd , const char * name , int name_type ,
BOOL bcast , BOOL recurse ,
2002-07-15 14:35:28 +04:00
struct in_addr to_ip , int * count , int * flags ,
BOOL * timed_out )
1996-06-04 10:42:03 +04:00
{
2002-07-15 14:35:28 +04:00
BOOL found = False ;
int i , retries = 3 ;
int retry_time = bcast ? 250 : 2000 ;
struct timeval tval ;
struct packet_struct p ;
struct packet_struct * p2 ;
struct nmb_packet * nmb = & p . packet . nmb ;
struct in_addr * ip_list = NULL ;
1999-12-13 16:27:58 +03:00
2002-08-17 21:00:51 +04:00
if ( lp_disable_netbios ( ) ) {
DEBUG ( 5 , ( " name_query(%s#%02x): netbios is disabled \n " , name , name_type ) ) ;
return NULL ;
}
2002-07-15 14:35:28 +04:00
if ( timed_out ) {
* timed_out = False ;
}
memset ( ( char * ) & p , ' \0 ' , sizeof ( p ) ) ;
( * count ) = 0 ;
( * flags ) = 0 ;
nmb - > header . name_trn_id = generate_trn_id ( ) ;
nmb - > header . opcode = 0 ;
nmb - > header . response = False ;
nmb - > header . nm_flags . bcast = bcast ;
nmb - > header . nm_flags . recursion_available = False ;
nmb - > header . nm_flags . recursion_desired = recurse ;
nmb - > header . nm_flags . trunc = False ;
nmb - > header . nm_flags . authoritative = False ;
nmb - > header . rcode = 0 ;
nmb - > header . qdcount = 1 ;
nmb - > header . ancount = 0 ;
nmb - > header . nscount = 0 ;
nmb - > header . arcount = 0 ;
make_nmb_name ( & nmb - > question . question_name , name , name_type ) ;
nmb - > question . question_type = 0x20 ;
nmb - > question . question_class = 0x1 ;
p . ip = to_ip ;
p . port = NMB_PORT ;
p . fd = fd ;
p . timestamp = time ( NULL ) ;
p . packet_type = NMB_PACKET ;
GetTimeOfDay ( & tval ) ;
if ( ! send_packet ( & p ) )
return NULL ;
retries - - ;
2001-11-28 05:42:55 +03:00
while ( 1 ) {
2002-07-15 14:35:28 +04:00
struct timeval tval2 ;
struct in_addr * tmp_ip_list ;
GetTimeOfDay ( & tval2 ) ;
if ( TvalDiff ( & tval , & tval2 ) > retry_time ) {
if ( ! retries )
break ;
if ( ! found & & ! send_packet ( & p ) )
return NULL ;
GetTimeOfDay ( & tval ) ;
retries - - ;
}
if ( ( p2 = receive_nmb_packet ( fd , 90 , nmb - > header . name_trn_id ) ) ) {
struct nmb_packet * nmb2 = & p2 - > packet . nmb ;
debug_nmb_packet ( p2 ) ;
/* If we get a Negative Name Query Response from a WINS
* server , we should report it and give up .
*/
if ( 0 = = nmb2 - > header . opcode /* A query response */
& & ! ( bcast ) /* from a WINS server */
& & nmb2 - > header . rcode /* Error returned */
) {
if ( DEBUGLVL ( 3 ) ) {
/* Only executed if DEBUGLEVEL >= 3 */
2001-11-28 05:42:55 +03:00
dbgtext ( " Negative name query response, rcode 0x%02x: " , nmb2 - > header . rcode ) ;
2002-07-15 14:35:28 +04:00
switch ( nmb2 - > header . rcode ) {
case 0x01 :
dbgtext ( " Request was invalidly formatted. \n " ) ;
break ;
case 0x02 :
dbgtext ( " Problem with NBNS, cannot process name. \n " ) ;
break ;
case 0x03 :
dbgtext ( " The name requested does not exist. \n " ) ;
break ;
case 0x04 :
dbgtext ( " Unsupported request error. \n " ) ;
break ;
case 0x05 :
dbgtext ( " Query refused error. \n " ) ;
break ;
default :
dbgtext ( " Unrecognized error code. \n " ) ;
break ;
}
}
free_packet ( p2 ) ;
return ( NULL ) ;
}
if ( nmb2 - > header . opcode ! = 0 | |
nmb2 - > header . nm_flags . bcast | |
nmb2 - > header . rcode | |
! nmb2 - > header . ancount ) {
/*
* XXXX what do we do with this ? Could be a
* redirect , but we ' ll discard it for the
2001-11-28 05:42:55 +03:00
* moment .
*/
2002-07-15 14:35:28 +04:00
free_packet ( p2 ) ;
continue ;
}
tmp_ip_list = ( struct in_addr * ) Realloc ( ip_list , sizeof ( ip_list [ 0 ] )
* ( ( * count ) + nmb2 - > answers - > rdlength / 6 ) ) ;
if ( ! tmp_ip_list ) {
DEBUG ( 0 , ( " name_query: Realloc failed. \n " ) ) ;
SAFE_FREE ( ip_list ) ;
}
ip_list = tmp_ip_list ;
if ( ip_list ) {
2001-11-28 05:42:55 +03:00
DEBUG ( 2 , ( " Got a positive name query response from %s ( " , inet_ntoa ( p2 - > ip ) ) ) ;
2002-07-15 14:35:28 +04:00
for ( i = 0 ; i < nmb2 - > answers - > rdlength / 6 ; i + + ) {
putip ( ( char * ) & ip_list [ ( * count ) ] , & nmb2 - > answers - > rdata [ 2 + i * 6 ] ) ;
DEBUGADD ( 2 , ( " %s " , inet_ntoa ( ip_list [ ( * count ) ] ) ) ) ;
( * count ) + + ;
}
DEBUGADD ( 2 , ( " ) \n " ) ) ;
}
found = True ;
retries = 0 ;
/* We add the flags back ... */
if ( nmb2 - > header . response )
( * flags ) | = NM_FLAGS_RS ;
if ( nmb2 - > header . nm_flags . authoritative )
( * flags ) | = NM_FLAGS_AA ;
if ( nmb2 - > header . nm_flags . trunc )
( * flags ) | = NM_FLAGS_TC ;
if ( nmb2 - > header . nm_flags . recursion_desired )
( * flags ) | = NM_FLAGS_RD ;
if ( nmb2 - > header . nm_flags . recursion_available )
( * flags ) | = NM_FLAGS_RA ;
if ( nmb2 - > header . nm_flags . bcast )
( * flags ) | = NM_FLAGS_B ;
free_packet ( p2 ) ;
/*
* If we ' re doing a unicast lookup we only
* expect one reply . Don ' t wait the full 2
* seconds if we got one . JRA .
*/
if ( ! bcast & & found )
break ;
}
}
1998-11-06 21:40:51 +03:00
2003-07-03 08:54:49 +04:00
/* only set timed_out if we didn't fund what we where looking for*/
if ( ! found & & timed_out ) {
2002-07-15 14:35:28 +04:00
* timed_out = True ;
}
1996-06-04 10:42:03 +04:00
2002-07-15 14:35:28 +04:00
/* sort the ip list so we choose close servers first if possible */
sort_ip_list ( ip_list , * count ) ;
2000-08-12 02:29:44 +04:00
2002-07-15 14:35:28 +04:00
return ip_list ;
1996-06-04 10:42:03 +04:00
}
1998-03-16 23:59:47 +03:00
/********************************************************
Start parsing the lmhosts file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-10 16:46:42 +04:00
XFILE * startlmhosts ( char * fname )
1998-03-16 23:59:47 +03:00
{
2001-09-10 16:46:42 +04:00
XFILE * fp = x_fopen ( fname , O_RDONLY , 0 ) ;
if ( ! fp ) {
DEBUG ( 4 , ( " startlmhosts: Can't open lmhosts file %s. Error was %s \n " ,
fname , strerror ( errno ) ) ) ;
return NULL ;
}
return fp ;
1998-03-16 23:59:47 +03:00
}
/********************************************************
Parse the next line in the lmhosts file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2001-09-10 16:46:42 +04:00
BOOL getlmhostsent ( XFILE * fp , pstring name , int * name_type , struct in_addr * ipaddr )
1998-03-16 23:59:47 +03:00
{
pstring line ;
2001-09-10 16:46:42 +04:00
while ( ! x_feof ( fp ) & & ! x_ferror ( fp ) ) {
1998-03-16 23:59:47 +03:00
pstring ip , flags , extra ;
2002-11-13 02:20:50 +03:00
const char * ptr ;
char * ptr1 ;
1998-03-16 23:59:47 +03:00
int count = 0 ;
* name_type = - 1 ;
if ( ! fgets_slash ( line , sizeof ( pstring ) , fp ) )
continue ;
if ( * line = = ' # ' )
continue ;
1998-05-12 04:55:32 +04:00
pstrcpy ( ip , " " ) ;
pstrcpy ( name , " " ) ;
pstrcpy ( flags , " " ) ;
1998-03-16 23:59:47 +03:00
ptr = line ;
1998-08-31 07:11:42 +04:00
if ( next_token ( & ptr , ip , NULL , sizeof ( ip ) ) )
1998-03-16 23:59:47 +03:00
+ + count ;
1998-11-16 04:27:51 +03:00
if ( next_token ( & ptr , name , NULL , sizeof ( pstring ) ) )
1998-03-16 23:59:47 +03:00
+ + count ;
1998-08-31 07:11:42 +04:00
if ( next_token ( & ptr , flags , NULL , sizeof ( flags ) ) )
1998-03-16 23:59:47 +03:00
+ + count ;
1998-08-31 07:11:42 +04:00
if ( next_token ( & ptr , extra , NULL , sizeof ( extra ) ) )
1998-03-16 23:59:47 +03:00
+ + count ;
if ( count < = 0 )
continue ;
if ( count > 0 & & count < 2 )
{
DEBUG ( 0 , ( " getlmhostsent: Ill formed hosts line [%s] \n " , line ) ) ;
continue ;
}
if ( count > = 4 )
{
DEBUG ( 0 , ( " getlmhostsent: too many columns in lmhosts file (obsolete syntax) \n " ) ) ;
continue ;
}
DEBUG ( 4 , ( " getlmhostsent: lmhost entry: %s %s %s \n " , ip , name , flags ) ) ;
2001-07-04 11:36:09 +04:00
if ( strchr_m ( flags , ' G ' ) | | strchr_m ( flags , ' S ' ) )
1998-03-16 23:59:47 +03:00
{
DEBUG ( 0 , ( " getlmhostsent: group flag in lmhosts ignored (obsolete) \n " ) ) ;
continue ;
}
* ipaddr = * interpret_addr2 ( ip ) ;
/* Extra feature. If the name ends in '#XX', where XX is a hex number,
then only add that name type . */
2002-11-13 02:20:50 +03:00
if ( ( ptr1 = strchr_m ( name , ' # ' ) ) ! = NULL )
1998-03-16 23:59:47 +03:00
{
char * endptr ;
2002-11-13 02:20:50 +03:00
ptr1 + + ;
* name_type = ( int ) strtol ( ptr1 , & endptr , 16 ) ;
1998-03-16 23:59:47 +03:00
2002-11-13 02:20:50 +03:00
if ( ! * ptr1 | | ( endptr = = ptr1 ) )
1998-03-16 23:59:47 +03:00
{
DEBUG ( 0 , ( " getlmhostsent: invalid name %s containing '#'. \n " , name ) ) ;
continue ;
}
2002-11-13 02:20:50 +03:00
* ( - - ptr1 ) = ' \0 ' ; /* Truncate at the '#' */
1998-03-16 23:59:47 +03:00
}
return True ;
}
return False ;
}
/********************************************************
Finish parsing the lmhosts file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-09-10 16:46:42 +04:00
void endlmhosts ( XFILE * fp )
1998-03-16 23:59:47 +03:00
{
2001-09-10 16:46:42 +04:00
x_fclose ( fp ) ;
1998-03-16 23:59:47 +03:00
}
2003-06-25 21:41:05 +04:00
/********************************************************
convert an array if struct in_addrs to struct ip_service
return False on failure . Port is set to PORT_NONE ;
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL convert_ip2service ( struct ip_service * * return_iplist , struct in_addr * ip_list , int count )
{
int i ;
2001-02-18 13:36:03 +03:00
2003-06-25 21:41:05 +04:00
if ( count = = 0 | | ! ip_list )
return False ;
/* copy the ip address; port will be PORT_NONE */
if ( ( * return_iplist = ( struct ip_service * ) malloc ( count * sizeof ( struct ip_service ) ) ) = = NULL ) {
DEBUG ( 0 , ( " convert_ip2service: malloc failed for %d enetries! \n " , count ) ) ;
return False ;
}
for ( i = 0 ; i < count ; i + + ) {
( * return_iplist ) [ i ] . ip = ip_list [ i ] ;
( * return_iplist ) [ i ] . port = PORT_NONE ;
}
return True ;
}
1998-10-04 16:00:40 +04:00
/********************************************************
1999-12-13 16:27:58 +03:00
Resolve via " bcast " method .
1998-10-04 16:00:40 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2000-12-11 03:08:17 +03:00
BOOL name_resolve_bcast ( const char * name , int name_type ,
2003-06-25 21:41:05 +04:00
struct ip_service * * return_iplist , int * return_count )
1998-10-04 16:00:40 +04:00
{
int sock , i ;
1999-12-13 16:27:58 +03:00
int num_interfaces = iface_count ( ) ;
2003-06-25 21:41:05 +04:00
struct in_addr * ip_list ;
BOOL ret ;
1999-12-13 16:27:58 +03:00
2002-08-17 21:00:51 +04:00
if ( lp_disable_netbios ( ) ) {
DEBUG ( 5 , ( " name_resolve_bcast(%s#%02x): netbios is disabled \n " , name , name_type ) ) ;
return False ;
}
2003-06-25 21:41:05 +04:00
* return_iplist = NULL ;
1999-12-13 16:27:58 +03:00
* return_count = 0 ;
1998-10-04 16:00:40 +04:00
/*
* " bcast " means do a broadcast lookup on all the local interfaces .
*/
2000-12-11 03:08:17 +03:00
DEBUG ( 3 , ( " name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x> \n " , name , name_type ) ) ;
1998-10-04 16:00:40 +04:00
sock = open_socket_in ( SOCK_DGRAM , 0 , 3 ,
1999-12-13 16:27:58 +03:00
interpret_addr ( lp_socket_address ( ) ) , True ) ;
if ( sock = = - 1 ) return False ;
set_socket_options ( sock , " SO_BROADCAST " ) ;
/*
* Lookup the name on all the interfaces , return on
* the first successful match .
*/
for ( i = num_interfaces - 1 ; i > = 0 ; i - - ) {
struct in_addr sendto_ip ;
2002-07-15 14:35:28 +04:00
int flags ;
1999-12-13 16:27:58 +03:00
/* Done this way to fix compiler error on IRIX 5.x */
2002-04-04 19:50:28 +04:00
sendto_ip = * iface_n_bcast ( i ) ;
2003-06-25 21:41:05 +04:00
ip_list = name_query ( sock , name , name_type , True ,
2002-07-15 14:35:28 +04:00
True , sendto_ip , return_count , & flags , NULL ) ;
2003-06-25 21:41:05 +04:00
if ( ip_list )
goto success ;
1998-10-04 16:00:40 +04:00
}
2003-06-25 21:41:05 +04:00
/* failed - no response */
1999-12-13 16:27:58 +03:00
close ( sock ) ;
1998-10-04 16:00:40 +04:00
return False ;
2003-06-25 21:41:05 +04:00
success :
ret = True ;
if ( ! convert_ip2service ( return_iplist , ip_list , * return_count ) )
ret = False ;
SAFE_FREE ( ip_list ) ;
close ( sock ) ;
return ret ;
1998-10-04 16:00:40 +04:00
}
/********************************************************
1999-12-13 16:27:58 +03:00
Resolve via " wins " method .
1998-10-04 16:00:40 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-06-14 01:03:15 +04:00
2002-07-15 14:35:28 +04:00
BOOL resolve_wins ( const char * name , int name_type ,
2003-06-25 21:41:05 +04:00
struct ip_service * * return_iplist , int * return_count )
1998-10-04 16:00:40 +04:00
{
2002-07-15 14:35:28 +04:00
int sock , t , i ;
char * * wins_tags ;
2003-06-25 21:41:05 +04:00
struct in_addr src_ip , * ip_list = NULL ;
BOOL ret ;
1998-10-04 16:00:40 +04:00
2002-08-17 21:00:51 +04:00
if ( lp_disable_netbios ( ) ) {
DEBUG ( 5 , ( " resolve_wins(%s#%02x): netbios is disabled \n " , name , name_type ) ) ;
return False ;
}
1999-12-13 16:27:58 +03:00
* return_iplist = NULL ;
* return_count = 0 ;
DEBUG ( 3 , ( " resolve_wins: Attempting wins lookup for name %s<0x%x> \n " , name , name_type ) ) ;
1998-10-04 16:00:40 +04:00
2002-07-15 14:35:28 +04:00
if ( wins_srv_count ( ) < 1 ) {
2000-07-19 05:21:30 +04:00
DEBUG ( 3 , ( " resolve_wins: WINS server resolution selected and no WINS servers listed. \n " ) ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
1998-10-04 16:00:40 +04:00
2002-07-15 14:35:28 +04:00
/* we try a lookup on each of the WINS tags in turn */
wins_tags = wins_srv_tags ( ) ;
if ( ! wins_tags ) {
/* huh? no tags?? give up in disgust */
return False ;
}
/* the address we will be sending from */
src_ip = * interpret_addr2 ( lp_socket_address ( ) ) ;
/* in the worst case we will try every wins server with every
tag ! */
for ( t = 0 ; wins_tags & & wins_tags [ t ] ; t + + ) {
int srv_count = wins_srv_count_tag ( wins_tags [ t ] ) ;
for ( i = 0 ; i < srv_count ; i + + ) {
struct in_addr wins_ip ;
int flags ;
BOOL timed_out ;
wins_ip = wins_srv_ip_tag ( wins_tags [ t ] , src_ip ) ;
if ( global_in_nmbd & & ismyip ( wins_ip ) ) {
/* yikes! we'll loop forever */
continue ;
}
/* skip any that have been unresponsive lately */
if ( wins_srv_is_dead ( wins_ip , src_ip ) ) {
continue ;
}
DEBUG ( 3 , ( " resolve_wins: using WINS server %s and tag '%s' \n " , inet_ntoa ( wins_ip ) , wins_tags [ t ] ) ) ;
sock = open_socket_in ( SOCK_DGRAM , 0 , 3 , src_ip . s_addr , True ) ;
if ( sock = = - 1 ) {
continue ;
}
2003-06-25 21:41:05 +04:00
ip_list = name_query ( sock , name , name_type , False ,
2002-07-15 14:35:28 +04:00
True , wins_ip , return_count , & flags ,
& timed_out ) ;
2003-07-03 08:54:49 +04:00
/* exit loop if we got a list of addresses */
if ( ip_list )
2002-07-15 14:35:28 +04:00
goto success ;
2003-06-25 21:41:05 +04:00
1999-12-13 16:27:58 +03:00
close ( sock ) ;
2002-07-15 14:35:28 +04:00
if ( timed_out ) {
/* Timed out wating for WINS server to respond. Mark it dead. */
wins_srv_died ( wins_ip , src_ip ) ;
} else {
/* The name definately isn't in this
group of WINS servers . goto the next group */
break ;
}
1999-12-13 16:27:58 +03:00
}
}
1998-10-04 16:00:40 +04:00
2002-07-15 14:35:28 +04:00
wins_srv_tags_free ( wins_tags ) ;
1999-12-13 16:27:58 +03:00
return False ;
2002-07-15 14:35:28 +04:00
success :
2003-06-25 21:41:05 +04:00
ret = True ;
if ( ! convert_ip2service ( return_iplist , ip_list , * return_count ) )
ret = False ;
SAFE_FREE ( ip_list ) ;
2002-07-15 14:35:28 +04:00
wins_srv_tags_free ( wins_tags ) ;
close ( sock ) ;
2003-06-25 21:41:05 +04:00
return ret ;
1998-10-04 16:00:40 +04:00
}
/********************************************************
1999-12-13 16:27:58 +03:00
Resolve via " lmhosts " method .
1998-10-04 16:00:40 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-05-08 12:12:57 +04:00
static BOOL resolve_lmhosts ( const char * name , int name_type ,
2003-06-25 21:41:05 +04:00
struct ip_service * * return_iplist , int * return_count )
1998-10-04 16:00:40 +04:00
{
/*
* " lmhosts " means parse the local lmhosts file .
*/
2001-09-10 16:46:42 +04:00
XFILE * fp ;
1998-10-04 16:00:40 +04:00
pstring lmhost_name ;
int name_type2 ;
1999-12-13 16:27:58 +03:00
struct in_addr return_ip ;
* return_iplist = NULL ;
* return_count = 0 ;
1998-10-04 16:00:40 +04:00
1999-12-13 16:27:58 +03:00
DEBUG ( 3 , ( " resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x> \n " , name , name_type ) ) ;
1998-10-04 16:00:40 +04:00
2001-11-19 06:12:10 +03:00
fp = startlmhosts ( dyn_LMHOSTSFILE ) ;
1998-10-04 16:00:40 +04:00
if ( fp ) {
1999-12-13 16:27:58 +03:00
while ( getlmhostsent ( fp , lmhost_name , & name_type2 , & return_ip ) ) {
1998-10-04 16:00:40 +04:00
if ( strequal ( name , lmhost_name ) & &
1999-12-13 16:27:58 +03:00
( ( name_type2 = = - 1 ) | | ( name_type = = name_type2 ) )
) {
1998-10-04 16:00:40 +04:00
endlmhosts ( fp ) ;
2003-06-25 21:41:05 +04:00
if ( ( * return_iplist = ( struct ip_service * ) malloc ( sizeof ( struct ip_service ) ) ) = = NULL ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 3 , ( " resolve_lmhosts: malloc fail ! \n " ) ) ;
return False ;
}
2003-06-25 21:41:05 +04:00
( * return_iplist ) [ 0 ] . ip = return_ip ;
( * return_iplist ) [ 0 ] . port = PORT_NONE ;
1999-12-13 16:27:58 +03:00
* return_count = 1 ;
1998-10-04 16:00:40 +04:00
return True ;
}
}
endlmhosts ( fp ) ;
}
return False ;
}
/********************************************************
1999-12-13 16:27:58 +03:00
Resolve via " hosts " method .
1998-10-04 16:00:40 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2003-06-25 21:41:05 +04:00
static BOOL resolve_hosts ( const char * name , int name_type ,
struct ip_service * * return_iplist , int * return_count )
1998-10-04 16:00:40 +04:00
{
/*
* " host " means do a localhost , or dns lookup .
*/
struct hostent * hp ;
2003-06-25 21:41:05 +04:00
2004-01-09 05:38:58 +03:00
if ( name_type ! = 0x20 & & name_type ! = 0x0 ) {
DEBUG ( 5 , ( " resolve_hosts: not appropriate for name type <0x%x> \n " , name_type ) ) ;
return False ;
}
* return_iplist = NULL ;
* return_count = 0 ;
DEBUG ( 3 , ( " resolve_hosts: Attempting host lookup for name %s<0x%x> \n " , name , name_type ) ) ;
if ( ( ( hp = sys_gethostbyname ( name ) ) ! = NULL ) & & ( hp - > h_addr ! = NULL ) ) {
struct in_addr return_ip ;
putip ( ( char * ) & return_ip , ( char * ) hp - > h_addr ) ;
* return_iplist = ( struct ip_service * ) malloc ( sizeof ( struct ip_service ) ) ;
if ( * return_iplist = = NULL ) {
DEBUG ( 3 , ( " resolve_hosts: malloc fail ! \n " ) ) ;
return False ;
}
( * return_iplist ) - > ip = return_ip ;
( * return_iplist ) - > port = PORT_NONE ;
* return_count = 1 ;
return True ;
}
return False ;
}
/********************************************************
Resolve via " ADS " method .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL resolve_ads ( const char * name , int name_type ,
struct ip_service * * return_iplist , int * return_count )
{
2003-06-25 21:41:05 +04:00
# ifdef HAVE_ADS
if ( name_type = = 0x1c ) {
int count , i = 0 ;
char * list = NULL ;
const char * ptr ;
pstring tok ;
/* try to lookup the _ldap._tcp.<domain> if we are using ADS */
if ( lp_security ( ) ! = SEC_ADS )
return False ;
DEBUG ( 5 , ( " resolve_hosts: Attempting to resolve DC's for %s using DNS \n " ,
name ) ) ;
if ( ldap_domain2hostlist ( name , & list ) ! = LDAP_SUCCESS )
return False ;
count = count_chars ( list , ' ' ) + 1 ;
if ( ( * return_iplist = malloc ( count * sizeof ( struct ip_service ) ) ) = = NULL ) {
DEBUG ( 0 , ( " resolve_hosts: malloc failed for %d entries \n " , count ) ) ;
return False ;
}
ptr = list ;
while ( next_token ( & ptr , tok , " " , sizeof ( tok ) ) ) {
unsigned port = LDAP_PORT ;
char * p = strchr ( tok , ' : ' ) ;
if ( p ) {
* p = 0 ;
port = atoi ( p + 1 ) ;
}
( * return_iplist ) [ i ] . ip = * interpret_addr2 ( tok ) ;
( * return_iplist ) [ i ] . port = port ;
/* make sure it is a valid IP. I considered checking the negative
connection cache , but this is the wrong place for it . Maybe only
as a hac . After think about it , if all of the IP addresses retuend
from DNS are dead , what hope does a netbios name lookup have ?
The standard reason for falling back to netbios lookups is that
our DNS server doesn ' t know anything about the DC ' s - - jerry */
if ( is_zero_ip ( ( * return_iplist ) [ i ] . ip ) )
continue ;
i + + ;
}
SAFE_FREE ( list ) ;
* return_count = i ;
return True ;
2004-01-09 05:38:58 +03:00
} else
2003-06-25 21:41:05 +04:00
# endif /* HAVE_ADS */
2004-01-09 05:38:58 +03:00
{
return False ;
1998-10-04 16:00:40 +04:00
}
}
2003-06-25 21:41:05 +04:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Internal interface to resolve a name into an IP address .
Use this function if the string is either an IP address , DNS
or host name or NetBIOS name . This uses the name switch in the
1998-03-16 23:59:47 +03:00
smb . conf to determine the order of name resolution .
2003-06-25 21:41:05 +04:00
Added support for ip addr / port to support ADS ldap servers .
the only place we currently care about the port is in the
resolve_hosts ( ) when looking up DC ' s via SRV RR entries in DNS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-11-28 01:34:12 +03:00
1999-12-13 16:27:58 +03:00
static BOOL internal_resolve_name ( const char * name , int name_type ,
2003-06-25 21:41:05 +04:00
struct ip_service * * return_iplist ,
int * return_count , const char * resolve_order )
1999-11-28 01:34:12 +03:00
{
1998-03-17 03:57:46 +03:00
pstring name_resolve_list ;
fstring tok ;
2002-11-13 02:20:50 +03:00
const char * ptr ;
1999-12-13 16:27:58 +03:00
BOOL allones = ( strcmp ( name , " 255.255.255.255 " ) = = 0 ) ;
BOOL allzeros = ( strcmp ( name , " 0.0.0.0 " ) = = 0 ) ;
BOOL is_address = is_ipaddress ( name ) ;
2002-01-09 07:26:41 +03:00
BOOL result = False ;
int i ;
1999-12-13 16:27:58 +03:00
* return_iplist = NULL ;
* return_count = 0 ;
2002-01-09 07:26:41 +03:00
DEBUG ( 10 , ( " internal_resolve_name: looking up %s#%x \n " , name , name_type ) ) ;
1999-12-13 16:27:58 +03:00
if ( allzeros | | allones | | is_address ) {
2003-06-25 21:41:05 +04:00
if ( ( * return_iplist = ( struct ip_service * ) malloc ( sizeof ( struct ip_service ) ) ) = = NULL ) {
DEBUG ( 0 , ( " internal_resolve_name: malloc fail ! \n " ) ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
2003-06-25 21:41:05 +04:00
1999-12-13 16:27:58 +03:00
if ( is_address ) {
2003-06-25 21:41:05 +04:00
/* ignore the port here */
( * return_iplist ) - > port = PORT_NONE ;
1999-12-13 16:27:58 +03:00
/* if it's in the form of an IP address then get the lib to interpret it */
2003-06-25 21:41:05 +04:00
if ( ( ( * return_iplist ) - > ip . s_addr = inet_addr ( name ) ) = = 0xFFFFFFFF ) {
2003-02-18 00:19:00 +03:00
DEBUG ( 1 , ( " internal_resolve_name: inet_addr failed on %s \n " , name ) ) ;
return False ;
}
} else {
2003-06-25 21:41:05 +04:00
( * return_iplist ) - > ip . s_addr = allones ? 0xFFFFFFFF : 0 ;
1999-12-13 16:27:58 +03:00
}
2003-12-09 05:29:27 +03:00
* return_count = 1 ;
return True ;
1998-03-16 23:59:47 +03:00
}
1999-12-13 16:27:58 +03:00
2003-06-25 21:41:05 +04:00
/* Check name cache */
2002-08-17 21:00:51 +04:00
if ( namecache_fetch ( name , name_type , return_iplist , return_count ) ) {
2003-06-25 21:41:05 +04:00
/* This could be a negative response */
return ( * return_count > 0 ) ;
2002-08-17 21:00:51 +04:00
}
2003-06-25 21:41:05 +04:00
/* set the name resolution order */
2004-01-13 22:42:53 +03:00
if ( strcmp ( resolve_order , " NULL " ) = = 0 ) {
DEBUG ( 8 , ( " internal_resolve_name: all lookups disabled \n " ) ) ;
return False ;
}
2003-06-25 21:41:05 +04:00
if ( ! resolve_order )
pstrcpy ( name_resolve_list , lp_name_resolve_order ( ) ) ;
else
pstrcpy ( name_resolve_list , resolve_order ) ;
if ( ! name_resolve_list [ 0 ] )
1999-12-13 16:27:58 +03:00
ptr = " host " ;
2003-06-25 21:41:05 +04:00
else
ptr = name_resolve_list ;
1998-04-12 06:50:43 +04:00
2003-06-25 21:41:05 +04:00
/* iterate through the name resolution backends */
1998-08-31 07:11:42 +04:00
while ( next_token ( & ptr , tok , LIST_SEP , sizeof ( tok ) ) ) {
1998-10-04 16:00:40 +04:00
if ( ( strequal ( tok , " host " ) | | strequal ( tok , " hosts " ) ) ) {
2004-01-09 05:38:58 +03:00
if ( resolve_hosts ( name , name_type , return_iplist , return_count ) ) {
result = True ;
goto done ;
}
} else if ( strequal ( tok , " ads " ) ) {
/* deal with 0x1c names here. This will result in a
SRV record lookup for _ldap . _tcp . < domain > if we
are using ' security = ads ' */
if ( resolve_ads ( name , name_type , return_iplist , return_count ) ) {
result = True ;
goto done ;
1998-10-04 16:00:40 +04:00
}
} else if ( strequal ( tok , " lmhosts " ) ) {
1999-12-13 16:27:58 +03:00
if ( resolve_lmhosts ( name , name_type , return_iplist , return_count ) ) {
2002-01-09 07:26:41 +03:00
result = True ;
goto done ;
1998-10-04 16:00:40 +04:00
}
} else if ( strequal ( tok , " wins " ) ) {
/* don't resolve 1D via WINS */
if ( name_type ! = 0x1D & &
1999-12-13 16:27:58 +03:00
resolve_wins ( name , name_type , return_iplist , return_count ) ) {
2002-01-09 07:26:41 +03:00
result = True ;
goto done ;
1998-10-04 16:00:40 +04:00
}
} else if ( strequal ( tok , " bcast " ) ) {
2000-12-11 03:08:17 +03:00
if ( name_resolve_bcast ( name , name_type , return_iplist , return_count ) ) {
2002-01-09 07:26:41 +03:00
result = True ;
goto done ;
1998-10-04 16:00:40 +04:00
}
} else {
DEBUG ( 0 , ( " resolve_name: unknown name switch type %s \n " , tok ) ) ;
}
1998-03-16 23:59:47 +03:00
}
2002-01-09 07:26:41 +03:00
/* All of the resolve_* functions above have returned false. */
2001-09-17 07:44:52 +04:00
SAFE_FREE ( * return_iplist ) ;
2002-01-09 07:26:41 +03:00
* return_count = 0 ;
1998-03-16 23:59:47 +03:00
return False ;
2002-01-09 07:26:41 +03:00
done :
/* Remove duplicate entries. Some queries, notably #1c (domain
controllers ) return the PDC in iplist [ 0 ] and then all domain
controllers including the PDC in iplist [ 1. . n ] . Iterating over
the iplist when the PDC is down will cause two sets of timeouts . */
2003-06-25 21:41:05 +04:00
if ( * return_count ) {
* return_count = remove_duplicate_addrs2 ( * return_iplist , * return_count ) ;
2002-01-09 07:26:41 +03:00
}
2002-08-17 21:00:51 +04:00
/* Save in name cache */
2003-06-25 21:41:05 +04:00
if ( DEBUGLEVEL > = 100 ) {
for ( i = 0 ; i < * return_count & & DEBUGLEVEL = = 100 ; i + + )
DEBUG ( 100 , ( " Storing name %s of type %d (%s:%d) \n " , name ,
name_type , inet_ntoa ( ( * return_iplist ) [ i ] . ip ) , ( * return_iplist ) [ i ] . port ) ) ;
}
2002-08-17 21:00:51 +04:00
namecache_store ( name , name_type , * return_count , * return_iplist ) ;
2002-01-09 07:26:41 +03:00
/* Display some debugging info */
2003-06-25 21:41:05 +04:00
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " internal_resolve_name: returning %d addresses: " ,
* return_count ) ) ;
2002-01-09 07:26:41 +03:00
2003-06-25 21:41:05 +04:00
for ( i = 0 ; i < * return_count ; i + + )
DEBUGADD ( 10 , ( " %s:%d " , inet_ntoa ( ( * return_iplist ) [ i ] . ip ) , ( * return_iplist ) [ i ] . port ) ) ;
2002-01-09 07:26:41 +03:00
2003-06-25 21:41:05 +04:00
DEBUG ( 10 , ( " \n " ) ) ;
}
2002-01-09 07:26:41 +03:00
return result ;
1998-03-16 23:59:47 +03:00
}
1998-10-04 15:25:06 +04:00
1999-11-27 02:04:19 +03:00
/********************************************************
1999-12-13 16:27:58 +03:00
Internal interface to resolve a name into one IP address .
Use this function if the string is either an IP address , DNS
or host name or NetBIOS name . This uses the name switch in the
smb . conf to determine the order of name resolution .
1999-11-27 02:04:19 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-02 19:31:24 +03:00
1999-12-13 16:27:58 +03:00
BOOL resolve_name ( const char * name , struct in_addr * return_ip , int name_type )
{
2003-06-25 21:41:05 +04:00
struct ip_service * ip_list = NULL ;
1999-12-13 16:27:58 +03:00
int count = 0 ;
1998-10-04 15:25:06 +04:00
2002-01-11 12:48:27 +03:00
if ( is_ipaddress ( name ) ) {
* return_ip = * interpret_addr2 ( name ) ;
return True ;
}
2003-06-25 21:41:05 +04:00
if ( internal_resolve_name ( name , name_type , & ip_list , & count , lp_name_resolve_order ( ) ) ) {
2002-01-11 03:23:29 +03:00
int i ;
2003-06-25 21:41:05 +04:00
2002-01-11 03:23:29 +03:00
/* only return valid addresses for TCP connections */
for ( i = 0 ; i < count ; i + + ) {
2003-06-25 21:41:05 +04:00
char * ip_str = inet_ntoa ( ip_list [ i ] . ip ) ;
2002-01-11 03:23:29 +03:00
if ( ip_str & &
strcmp ( ip_str , " 255.255.255.255 " ) ! = 0 & &
2003-06-25 21:41:05 +04:00
strcmp ( ip_str , " 0.0.0.0 " ) ! = 0 )
{
* return_ip = ip_list [ i ] . ip ;
2002-01-11 03:23:29 +03:00
SAFE_FREE ( ip_list ) ;
return True ;
}
}
1999-11-27 02:04:19 +03:00
}
2003-06-25 21:41:05 +04:00
2001-09-17 07:33:37 +04:00
SAFE_FREE ( ip_list ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
1999-11-27 02:04:19 +03:00
1999-12-13 16:27:58 +03:00
/********************************************************
Find the IP address of the master browser or DMB for a workgroup .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-11-27 02:04:19 +03:00
2002-08-17 21:00:51 +04:00
BOOL find_master_ip ( const char * group , struct in_addr * master_ip )
1999-12-13 16:27:58 +03:00
{
2003-06-25 21:41:05 +04:00
struct ip_service * ip_list = NULL ;
1999-12-13 16:27:58 +03:00
int count = 0 ;
2002-08-17 21:00:51 +04:00
if ( lp_disable_netbios ( ) ) {
DEBUG ( 5 , ( " find_master_ip(%s): netbios is disabled \n " , group ) ) ;
return False ;
}
2003-06-25 21:41:05 +04:00
if ( internal_resolve_name ( group , 0x1D , & ip_list , & count , lp_name_resolve_order ( ) ) ) {
* master_ip = ip_list [ 0 ] . ip ;
2001-09-17 07:33:37 +04:00
SAFE_FREE ( ip_list ) ;
1999-12-13 16:27:58 +03:00
return True ;
1999-11-28 01:34:12 +03:00
}
2003-06-25 21:41:05 +04:00
if ( internal_resolve_name ( group , 0x1B , & ip_list , & count , lp_name_resolve_order ( ) ) ) {
* master_ip = ip_list [ 0 ] . ip ;
2001-09-17 07:44:52 +04:00
SAFE_FREE ( ip_list ) ;
1999-12-13 16:27:58 +03:00
return True ;
}
2001-09-17 07:33:37 +04:00
SAFE_FREE ( ip_list ) ;
1999-12-13 16:27:58 +03:00
return False ;
1999-11-27 02:04:19 +03:00
}
1998-10-04 15:25:06 +04:00
1999-12-13 16:27:58 +03:00
/********************************************************
2002-11-06 08:14:15 +03:00
Get the IP address list of the primary domain controller
for a domain .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-22 02:00:59 +03:00
2002-11-06 08:14:15 +03:00
BOOL get_pdc_ip ( const char * domain , struct in_addr * ip )
1999-12-13 16:27:58 +03:00
{
2003-06-25 21:41:05 +04:00
struct ip_service * ip_list ;
2002-11-06 08:14:15 +03:00
int count ;
/* Look up #1B name */
2003-06-25 21:41:05 +04:00
if ( ! internal_resolve_name ( domain , 0x1b , & ip_list , & count , lp_name_resolve_order ( ) ) )
2002-11-06 08:14:15 +03:00
return False ;
2002-12-04 22:01:01 +03:00
/* if we get more than 1 IP back we have to assume it is a
multi - homed PDC and not a mess up */
2003-06-25 21:41:05 +04:00
2002-12-04 22:01:01 +03:00
if ( count > 1 ) {
2003-06-25 21:41:05 +04:00
DEBUG ( 6 , ( " get_pdc_ip: PDC has %d IP addresses! \n " , count ) ) ;
sort_ip_list2 ( ip_list , count ) ;
2002-12-04 22:01:01 +03:00
}
2002-11-06 08:14:15 +03:00
2003-06-25 21:41:05 +04:00
* ip = ip_list [ 0 ] . ip ;
2002-12-04 22:01:01 +03:00
2002-11-06 08:14:15 +03:00
SAFE_FREE ( ip_list ) ;
return True ;
}
2001-11-25 09:38:17 +03:00
2002-11-06 08:14:15 +03:00
/********************************************************
Get the IP address list of the domain controllers for
a domain .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-02-08 03:54:32 +03:00
static BOOL get_dc_list ( const char * domain , struct ip_service * * ip_list ,
2004-01-09 05:38:58 +03:00
int * count , BOOL ads_only , int * ordered )
2002-11-06 08:14:15 +03:00
{
2004-01-13 22:42:53 +03:00
fstring resolve_order ;
/* if we are restricted to solely using DNS for looking
up a domain controller , make sure that host lookups
are enabled for the ' name resolve order ' . If host lookups
are disabled and ads_only is True , then set the string to
NULL . */
fstrcpy ( resolve_order , lp_name_resolve_order ( ) ) ;
strlower_m ( resolve_order ) ;
if ( ads_only ) {
if ( strstr ( resolve_order , " host " ) )
fstrcpy ( resolve_order , " ads " ) ;
else
fstrcpy ( resolve_order , " NULL " ) ;
}
2003-06-25 21:41:05 +04:00
2002-11-23 17:52:34 +03:00
* ordered = False ;
/* If it's our domain then use the 'password server' parameter. */
2001-11-22 02:00:59 +03:00
2003-06-25 21:41:05 +04:00
if ( strequal ( domain , lp_workgroup ( ) ) | | strequal ( domain , lp_realm ( ) ) ) {
2003-03-05 04:30:15 +03:00
const char * p ;
2002-11-23 17:52:34 +03:00
char * pserver = lp_passwordserver ( ) ; /* UNIX charset. */
2003-06-25 21:41:05 +04:00
char * port_str ;
int port ;
2001-11-22 02:00:59 +03:00
fstring name ;
2002-11-23 17:52:34 +03:00
int num_addresses = 0 ;
int local_count , i , j ;
2003-06-25 21:41:05 +04:00
struct ip_service * return_iplist = NULL ;
struct ip_service * auto_ip_list = NULL ;
2002-11-23 17:52:34 +03:00
BOOL done_auto_lookup = False ;
int auto_count = 0 ;
2001-11-22 02:00:59 +03:00
2002-11-06 08:14:15 +03:00
if ( ! * pserver )
2004-01-13 22:42:53 +03:00
return internal_resolve_name ( domain , 0x1C , ip_list , count , resolve_order ) ;
2001-11-22 02:00:59 +03:00
p = pserver ;
2002-11-06 08:14:15 +03:00
2002-11-23 17:52:34 +03:00
/*
* if ' * ' appears in the " password server " list then add
* an auto lookup to the list of manually configured
* DC ' s . If any DC is listed by name , then the list should be
* considered to be ordered
*/
2001-11-22 02:00:59 +03:00
while ( next_token ( & p , name , LIST_SEP , sizeof ( name ) ) ) {
2002-11-23 17:52:34 +03:00
if ( strequal ( name , " * " ) ) {
2004-01-13 22:42:53 +03:00
if ( internal_resolve_name ( domain , 0x1C , & auto_ip_list , & auto_count , resolve_order ) )
2002-11-23 17:52:34 +03:00
num_addresses + = auto_count ;
done_auto_lookup = True ;
DEBUG ( 8 , ( " Adding %d DC's from auto lookup \n " , auto_count ) ) ;
}
else
num_addresses + + ;
2001-11-22 02:00:59 +03:00
}
2002-11-06 08:14:15 +03:00
2002-11-23 17:52:34 +03:00
/* if we have no addresses and haven't done the auto lookup, then
just return the list of DC ' s */
if ( ( num_addresses = = 0 ) & & ! done_auto_lookup )
2004-01-13 22:42:53 +03:00
return internal_resolve_name ( domain , 0x1C , ip_list , count , resolve_order ) ;
2001-11-22 02:00:59 +03:00
2003-07-03 08:54:49 +04:00
/* maybe we just failed? */
if ( num_addresses = = 0 ) {
DEBUG ( 4 , ( " get_dc_list: no servers found \n " ) ) ;
return False ;
}
2003-06-25 21:41:05 +04:00
if ( ( return_iplist = ( struct ip_service * )
malloc ( num_addresses * sizeof ( struct ip_service ) ) ) = = NULL )
{
2001-11-22 02:00:59 +03:00
DEBUG ( 3 , ( " get_dc_list: malloc fail ! \n " ) ) ;
return False ;
}
2002-11-06 08:14:15 +03:00
2001-11-22 02:00:59 +03:00
p = pserver ;
2002-11-23 17:52:34 +03:00
local_count = 0 ;
2002-11-06 08:14:15 +03:00
2002-11-23 17:52:34 +03:00
/* fill in the return list now with real IP's */
2002-12-01 03:45:07 +03:00
while ( ( local_count < num_addresses ) & & next_token ( & p , name , LIST_SEP , sizeof ( name ) ) ) {
2001-11-22 02:00:59 +03:00
struct in_addr name_ip ;
2002-11-23 17:52:34 +03:00
/* copy any addersses from the auto lookup */
if ( strequal ( name , " * " ) ) {
2003-06-25 21:41:05 +04:00
for ( j = 0 ; j < auto_count ; j + + ) {
return_iplist [ local_count ] . ip = auto_ip_list [ j ] . ip ;
return_iplist [ local_count ] . port = auto_ip_list [ j ] . port ;
local_count + + ;
}
2001-11-22 02:00:59 +03:00
continue ;
2002-11-23 17:52:34 +03:00
}
2003-06-25 21:41:05 +04:00
/* added support for address:port syntax for ads (not that I think
anyone will ever run the LDAP server in an AD domain on something
other than port 389 */
port = ( lp_security ( ) = = SEC_ADS ) ? LDAP_PORT : PORT_NONE ;
if ( ( port_str = strchr ( name , ' : ' ) ) ! = NULL ) {
* port_str = ' \0 ' ;
port_str + + ;
port = atoi ( port_str ) ;
}
2002-12-04 22:01:01 +03:00
/* explicit lookup; resolve_name() will handle names & IP addresses */
2003-06-25 21:41:05 +04:00
if ( resolve_name ( name , & name_ip , 0x20 ) ) {
return_iplist [ local_count ] . ip = name_ip ;
return_iplist [ local_count ] . port = port ;
local_count + + ;
2002-11-23 17:52:34 +03:00
* ordered = True ;
}
2001-11-22 02:00:59 +03:00
}
2002-11-23 17:52:34 +03:00
2002-12-04 21:39:50 +03:00
SAFE_FREE ( auto_ip_list ) ;
2003-06-25 21:41:05 +04:00
/* need to remove duplicates in the list if we have any
explicit password servers */
2002-11-23 17:52:34 +03:00
2003-06-25 21:41:05 +04:00
if ( local_count )
local_count = remove_duplicate_addrs2 ( return_iplist , local_count ) ;
2002-11-23 17:52:34 +03:00
2003-06-23 23:05:23 +04:00
if ( DEBUGLEVEL > = 4 ) {
DEBUG ( 4 , ( " get_dc_list: returning %d ip addresses in an %sordered list \n " , local_count ,
* ordered ? " " : " un " ) ) ;
DEBUG ( 4 , ( " get_dc_list: " ) ) ;
for ( i = 0 ; i < local_count ; i + + )
2003-06-25 21:41:05 +04:00
DEBUGADD ( 4 , ( " %s:%d " , inet_ntoa ( return_iplist [ i ] . ip ) , return_iplist [ i ] . port ) ) ;
2003-06-23 23:05:23 +04:00
DEBUGADD ( 4 , ( " \n " ) ) ;
}
2001-11-22 02:00:59 +03:00
* ip_list = return_iplist ;
2002-11-23 17:52:34 +03:00
* count = local_count ;
2002-11-06 08:14:15 +03:00
2001-11-22 02:00:59 +03:00
return ( * count ! = 0 ) ;
2002-11-06 08:14:15 +03:00
}
2003-06-25 21:41:05 +04:00
DEBUG ( 10 , ( " get_dc_list: defaulting to internal auto lookup for domain %s \n " , domain ) ) ;
2004-01-13 22:42:53 +03:00
return internal_resolve_name ( domain , 0x1C , ip_list , count , resolve_order ) ;
1998-10-04 15:25:06 +04:00
}
2004-02-08 03:54:32 +03:00
/*********************************************************************
small wrapper function to get the DC list and sort it if neccessary
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL get_sorted_dc_list ( const char * domain , struct ip_service * * ip_list , int * count , BOOL ads_only )
{
BOOL ordered ;
DEBUG ( 8 , ( " get_sorted_dc_list: attempting lookup using [%s] \n " ,
( ads_only ? " ads " : lp_name_resolve_order ( ) ) ) ) ;
if ( ! get_dc_list ( domain , ip_list , count , ads_only , & ordered ) )
return False ;
/* only sort if we don't already have an ordered list */
if ( ! ordered )
sort_ip_list2 ( * ip_list , * count ) ;
return True ;
}