2002-01-15 04:42:57 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2002-01-15 04:42:57 +03:00
Winbind daemon - WINS related functions
Copyright ( C ) Andrew Tridgell 1999
Copyright ( C ) Herb Lewis 2002
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
2002-01-15 04:42:57 +03: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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-01-15 04:42:57 +03:00
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2002-01-15 04:42:57 +03:00
# include "winbindd.h"
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2002-01-15 04:42:57 +03:00
/* Use our own create socket code so we don't recurse.... */
static int wins_lookup_open_socket_in ( void )
{
struct sockaddr_in sock ;
int val = 1 ;
int res ;
memset ( ( char * ) & sock , ' \0 ' , sizeof ( sock ) ) ;
# ifdef HAVE_SOCK_SIN_LEN
sock . sin_len = sizeof ( sock ) ;
# endif
sock . sin_port = 0 ;
sock . sin_family = AF_INET ;
sock . sin_addr . s_addr = interpret_addr ( " 0.0.0.0 " ) ;
res = socket ( AF_INET , SOCK_DGRAM , 0 ) ;
if ( res = = - 1 )
return - 1 ;
setsockopt ( res , SOL_SOCKET , SO_REUSEADDR , ( char * ) & val , sizeof ( val ) ) ;
# ifdef SO_REUSEPORT
setsockopt ( res , SOL_SOCKET , SO_REUSEPORT , ( char * ) & val , sizeof ( val ) ) ;
# endif /* SO_REUSEPORT */
/* now we've got a socket - we need to bind it */
if ( bind ( res , ( struct sockaddr * ) & sock , sizeof ( sock ) ) < 0 ) {
close ( res ) ;
return ( - 1 ) ;
}
set_socket_options ( res , " SO_BROADCAST " ) ;
return res ;
}
2007-10-25 01:16:54 +04:00
static NODE_STATUS_STRUCT * lookup_byaddr_backend ( const char * addr , int * count )
2002-01-15 04:42:57 +03:00
{
int fd ;
2007-10-25 01:16:54 +04:00
struct sockaddr_storage ss ;
2002-01-15 04:42:57 +03:00
struct nmb_name nname ;
2005-06-25 00:25:18 +04:00
NODE_STATUS_STRUCT * status ;
2002-01-15 04:42:57 +03:00
fd = wins_lookup_open_socket_in ( ) ;
if ( fd = = - 1 )
return NULL ;
make_nmb_name ( & nname , " * " , 0 ) ;
2007-10-25 01:16:54 +04:00
if ( ! interpret_string_addr ( & ss , addr , AI_NUMERICHOST ) ) {
return NULL ;
}
status = node_status_query ( fd , & nname , & ss , count , NULL ) ;
2002-01-15 04:42:57 +03:00
close ( fd ) ;
return status ;
}
2007-10-25 01:16:54 +04:00
static struct sockaddr_storage * lookup_byname_backend ( const char * name ,
int * count )
2002-01-15 04:42:57 +03:00
{
int fd ;
2003-06-28 12:24:32 +04:00
struct ip_service * ret = NULL ;
2007-10-25 01:16:54 +04:00
struct sockaddr_storage * return_ss = NULL ;
2003-06-28 12:24:32 +04:00
int j , i , flags = 0 ;
2002-01-15 04:42:57 +03:00
* count = 0 ;
2002-07-15 14:35:28 +04:00
/* always try with wins first */
2007-08-28 18:20:53 +04:00
if ( NT_STATUS_IS_OK ( resolve_wins ( name , 0x20 , & ret , count ) ) ) {
2006-11-11 20:04:08 +03:00
if ( * count = = 0 )
2003-06-28 12:24:32 +04:00
return NULL ;
2007-10-25 01:16:54 +04:00
if ( ( return_ss = SMB_MALLOC_ARRAY ( struct sockaddr_storage , * count ) ) = = NULL ) {
2003-06-28 12:24:32 +04:00
free ( ret ) ;
return NULL ;
}
/* copy the IP addresses */
2007-10-25 01:16:54 +04:00
for ( i = 0 ; i < ( * count ) ; i + + )
return_ss [ i ] = ret [ i ] . ss ;
2004-05-07 03:16:52 +04:00
free ( ret ) ;
2007-10-25 01:16:54 +04:00
return return_ss ;
2002-01-15 04:42:57 +03:00
}
2002-07-15 14:35:28 +04:00
fd = wins_lookup_open_socket_in ( ) ;
if ( fd = = - 1 ) {
return NULL ;
2002-01-15 04:42:57 +03:00
}
/* uggh, we have to broadcast to each interface in turn */
for ( j = iface_count ( ) - 1 ;
j > = 0 ;
j - - ) {
2007-10-25 01:16:54 +04:00
const struct sockaddr_storage * bcast_ss = iface_n_bcast ( j ) ;
if ( ! bcast_ss ) {
2007-10-11 05:25:16 +04:00
continue ;
}
2007-10-25 01:16:54 +04:00
return_ss = name_query ( fd , name , 0x20 , True , True , bcast_ss , count , & flags , NULL ) ;
if ( return_ss ) {
2004-11-24 04:03:23 +03:00
break ;
}
2002-01-15 04:42:57 +03:00
}
close ( fd ) ;
2007-10-25 01:16:54 +04:00
return return_ss ;
2002-01-15 04:42:57 +03:00
}
/* Get hostname from IP */
2005-06-20 17:42:29 +04:00
void winbindd_wins_byip ( struct winbindd_cli_state * state )
2002-01-15 04:42:57 +03:00
{
2002-03-29 18:37:39 +03:00
fstring response ;
int i , count , maxlen , size ;
2005-06-25 00:25:18 +04:00
NODE_STATUS_STRUCT * status ;
2002-01-15 04:42:57 +03:00
2002-08-17 21:00:51 +04:00
/* Ensure null termination */
state - > request . data . winsreq [ sizeof ( state - > request . data . winsreq ) - 1 ] = ' \0 ' ;
2003-07-22 08:31:20 +04:00
DEBUG ( 3 , ( " [%5lu]: wins_byip %s \n " , ( unsigned long ) state - > pid ,
2002-03-29 18:37:39 +03:00
state - > request . data . winsreq ) ) ;
2002-01-15 04:42:57 +03:00
* response = ' \0 ' ;
2002-03-29 18:37:39 +03:00
maxlen = sizeof ( response ) - 1 ;
2002-01-15 04:42:57 +03:00
2002-03-29 18:37:39 +03:00
if ( ( status = lookup_byaddr_backend ( state - > request . data . winsreq , & count ) ) ) {
size = strlen ( state - > request . data . winsreq ) ;
if ( size > maxlen ) {
2002-01-15 04:42:57 +03:00
SAFE_FREE ( status ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2002-01-15 04:42:57 +03:00
}
2003-03-18 14:22:52 +03:00
fstrcat ( response , state - > request . data . winsreq ) ;
fstrcat ( response , " \t " ) ;
2002-01-15 04:42:57 +03:00
for ( i = 0 ; i < count ; i + + ) {
/* ignore group names */
if ( status [ i ] . flags & 0x80 ) continue ;
if ( status [ i ] . type = = 0x20 ) {
2002-03-29 18:37:39 +03:00
size = sizeof ( status [ i ] . name ) + strlen ( response ) ;
if ( size > maxlen ) {
2002-01-15 04:42:57 +03:00
SAFE_FREE ( status ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2002-01-15 04:42:57 +03:00
}
2003-03-18 14:22:52 +03:00
fstrcat ( response , status [ i ] . name ) ;
fstrcat ( response , " " ) ;
2002-01-15 04:42:57 +03:00
}
}
2002-03-29 18:37:39 +03:00
/* make last character a newline */
2002-01-15 04:42:57 +03:00
response [ strlen ( response ) - 1 ] = ' \n ' ;
SAFE_FREE ( status ) ;
}
2002-03-29 18:37:39 +03:00
fstrcpy ( state - > response . data . winsresp , response ) ;
2005-06-20 17:42:29 +04:00
request_ok ( state ) ;
2002-01-15 04:42:57 +03:00
}
/* Get IP from hostname */
2005-06-20 17:42:29 +04:00
void winbindd_wins_byname ( struct winbindd_cli_state * state )
2002-01-15 04:42:57 +03:00
{
2007-10-25 01:16:54 +04:00
struct sockaddr_storage * ip_list = NULL ;
2002-03-29 18:37:39 +03:00
int i , count , maxlen , size ;
fstring response ;
2007-10-25 01:16:54 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2002-01-15 04:42:57 +03:00
2002-08-17 21:00:51 +04:00
/* Ensure null termination */
state - > request . data . winsreq [ sizeof ( state - > request . data . winsreq ) - 1 ] = ' \0 ' ;
2003-07-22 10:52:39 +04:00
DEBUG ( 3 , ( " [%5lu]: wins_byname %s \n " , ( unsigned long ) state - > pid ,
2002-03-29 18:37:39 +03:00
state - > request . data . winsreq ) ) ;
2002-01-15 04:42:57 +03:00
* response = ' \0 ' ;
2002-03-29 18:37:39 +03:00
maxlen = sizeof ( response ) - 1 ;
2002-01-15 04:42:57 +03:00
2002-03-29 18:37:39 +03:00
if ( ( ip_list = lookup_byname_backend ( state - > request . data . winsreq , & count ) ) ) {
2002-01-15 04:42:57 +03:00
for ( i = count ; i ; i - - ) {
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , & ip_list [ i - 1 ] ) ;
size = strlen ( addr ) ;
if ( size > maxlen ) {
SAFE_FREE ( ip_list ) ;
request_error ( state ) ;
return ;
}
if ( i ! = 0 ) {
/* Clear out the newline character */
/* But only if there is something in there,
otherwise we clobber something in the stack */
if ( strlen ( response ) ) {
response [ strlen ( response ) - 1 ] = ' ' ;
}
}
fstrcat ( response , addr ) ;
fstrcat ( response , " \t " ) ;
2002-01-15 04:42:57 +03:00
}
2002-03-29 18:37:39 +03:00
size = strlen ( state - > request . data . winsreq ) + strlen ( response ) ;
if ( size > maxlen ) {
2002-01-15 04:42:57 +03:00
SAFE_FREE ( ip_list ) ;
2005-06-20 17:42:29 +04:00
request_error ( state ) ;
return ;
2007-10-25 01:16:54 +04:00
}
2003-03-18 14:22:52 +03:00
fstrcat ( response , state - > request . data . winsreq ) ;
fstrcat ( response , " \n " ) ;
2002-01-15 04:42:57 +03:00
SAFE_FREE ( ip_list ) ;
2005-06-20 17:42:29 +04:00
} else {
request_error ( state ) ;
return ;
}
2002-01-15 04:42:57 +03:00
2002-03-29 18:37:39 +03:00
fstrcpy ( state - > response . data . winsresp , response ) ;
2002-01-15 04:42:57 +03:00
2005-06-20 17:42:29 +04:00
request_ok ( state ) ;
2002-01-15 04:42:57 +03:00
}