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
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 .
*/
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 ;
}
static struct node_status * lookup_byaddr_backend ( char * addr , int * count )
{
int fd ;
struct in_addr ip ;
struct nmb_name nname ;
struct node_status * status ;
fd = wins_lookup_open_socket_in ( ) ;
if ( fd = = - 1 )
return NULL ;
make_nmb_name ( & nname , " * " , 0 ) ;
ip = * interpret_addr2 ( addr ) ;
2004-04-16 07:57:30 +04:00
status = node_status_query ( fd , & nname , ip , count , NULL ) ;
2002-01-15 04:42:57 +03:00
close ( fd ) ;
return status ;
}
static struct in_addr * lookup_byname_backend ( const char * name , int * count )
{
int fd ;
2003-06-28 12:24:32 +04:00
struct ip_service * ret = NULL ;
2004-11-24 04:03:23 +03:00
struct in_addr * return_ip = 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 */
if ( resolve_wins ( name , 0x20 , & ret , count ) ) {
2003-06-28 12:24:32 +04:00
if ( count = = 0 )
return NULL ;
2004-12-07 21:25:53 +03:00
if ( ( return_ip = SMB_MALLOC_ARRAY ( struct in_addr , * count ) ) = = NULL ) {
2003-06-28 12:24:32 +04:00
free ( ret ) ;
return NULL ;
}
/* copy the IP addresses */
for ( i = 0 ; i < ( * count ) ; i + + )
return_ip [ i ] = ret [ i ] . ip ;
2004-05-07 03:16:52 +04:00
free ( ret ) ;
2003-06-28 12:24:32 +04:00
return return_ip ;
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 - - ) {
struct in_addr * bcast = iface_n_bcast ( j ) ;
2003-06-28 12:24:32 +04:00
return_ip = name_query ( fd , name , 0x20 , True , True , * bcast , count , & flags , NULL ) ;
2004-11-24 04:03:23 +03:00
if ( return_ip ) {
break ;
}
2002-01-15 04:42:57 +03:00
}
close ( fd ) ;
2003-06-28 12:24:32 +04:00
return return_ip ;
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 ;
2002-01-15 04:42:57 +03:00
struct node_status * status ;
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
{
struct in_addr * ip_list ;
2002-03-29 18:37:39 +03:00
int i , count , maxlen , size ;
fstring response ;
2002-01-15 04:42:57 +03:00
char * addr ;
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 - - ) {
addr = inet_ntoa ( ip_list [ i - 1 ] ) ;
2002-03-29 18:37:39 +03:00
size = strlen ( addr ) ;
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 ;
2002-01-15 04:42:57 +03:00
}
2002-03-29 18:37:39 +03:00
if ( i ! = 0 ) {
/* Clear out the newline character */
2004-03-30 12:11:59 +04:00
/* But only if there is something in there,
otherwise we clobber something in the stack */
if ( strlen ( response ) )
response [ strlen ( response ) - 1 ] = ' ' ;
2002-03-29 18:37:39 +03:00
}
2003-03-18 14:22:52 +03:00
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 ;
2002-01-15 04:42:57 +03: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
}