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 .
*/
# include "winbindd.h"
/* 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 ) ;
status = node_status_query ( fd , & nname , ip , count ) ;
close ( fd ) ;
return status ;
}
static struct in_addr * lookup_byname_backend ( const char * name , int * count )
{
int fd ;
struct in_addr * ret = NULL ;
struct in_addr p ;
int j ;
* count = 0 ;
fd = wins_lookup_open_socket_in ( ) ;
if ( fd = = - 1 )
return NULL ;
p = wins_srv_ip ( ) ;
if ( ! zero_ip ( p ) ) {
ret = name_query ( fd , name , 0x20 , False , True , p , count ) ;
goto out ;
}
if ( lp_wins_support ( ) ) {
/* we are our own WINS server */
ret = name_query ( fd , name , 0x20 , False , True , * interpret_addr2 ( " 127.0.0.1 " ) , count ) ;
goto out ;
}
/* 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 ) ;
ret = name_query ( fd , name , 0x20 , True , True , * bcast , count ) ;
if ( ret ) break ;
}
out :
close ( fd ) ;
return ret ;
}
/* Get hostname from IP */
enum winbindd_result winbindd_wins_byip ( struct winbindd_cli_state * state )
{
char response [ 1024 ] ;
int i , count , len , size ;
struct node_status * status ;
DEBUG ( 3 , ( " [%5d]: wins_byip %s \n " , state - > pid ,
state - > request . data . name ) ) ;
* response = ' \0 ' ;
len = sizeof ( response ) - 2 ;
2002-01-15 20:58:59 +03:00
if ( ( status = lookup_byaddr_backend ( state - > request . data . name , & count ) ) ) {
2002-01-15 04:42:57 +03:00
size = strlen ( state - > request . data . name ) + 1 ;
if ( size > len ) {
SAFE_FREE ( status ) ;
return WINBINDD_ERROR ;
}
len - = size ;
2002-01-15 20:58:59 +03:00
safe_strcat ( response , state - > request . data . name , size ) ;
safe_strcat ( response , " \t " , 1 ) ;
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 ) {
size = sizeof ( status [ i ] . name ) + 1 ;
if ( size > len ) {
SAFE_FREE ( status ) ;
return WINBINDD_ERROR ;
}
len - = size ;
2002-01-15 20:58:59 +03:00
safe_strcat ( response , status [ i ] . name , size ) ;
safe_strcat ( response , " " , 1 ) ;
2002-01-15 04:42:57 +03:00
}
}
response [ strlen ( response ) - 1 ] = ' \n ' ;
SAFE_FREE ( status ) ;
}
fstrcpy ( state - > response . data . name . name , response ) ;
return WINBINDD_OK ;
}
/* Get IP from hostname */
enum winbindd_result winbindd_wins_byname ( struct winbindd_cli_state * state )
{
struct in_addr * ip_list ;
int i , count , len , size ;
char response [ 1024 ] ;
char * addr ;
DEBUG ( 3 , ( " [%5d]: wins_byname %s \n " , state - > pid ,
state - > request . data . name ) ) ;
* response = ' \0 ' ;
len = sizeof ( response ) - 2 ;
2002-01-15 20:58:59 +03:00
if ( ( ip_list = lookup_byname_backend ( state - > request . data . name , & count ) ) ) {
2002-01-15 04:42:57 +03:00
for ( i = count ; i ; i - - ) {
addr = inet_ntoa ( ip_list [ i - 1 ] ) ;
size = strlen ( addr ) + 1 ;
if ( size > len ) {
SAFE_FREE ( ip_list ) ;
return WINBINDD_ERROR ;
}
len - = size ;
if ( i ! = 0 )
response [ strlen ( response ) - 1 ] = ' ' ;
2002-01-15 20:58:59 +03:00
safe_strcat ( response , addr , size ) ;
safe_strcat ( response , " \t " , 1 ) ;
2002-01-15 04:42:57 +03:00
}
size = strlen ( state - > request . data . name ) + 1 ;
if ( size > len ) {
SAFE_FREE ( ip_list ) ;
return WINBINDD_ERROR ;
}
2002-01-15 20:58:59 +03:00
safe_strcat ( response , state - > request . data . name , size ) ;
safe_strcat ( response , " \n " , 1 ) ;
2002-01-15 04:42:57 +03:00
SAFE_FREE ( ip_list ) ;
} else
return WINBINDD_ERROR ;
fstrcpy ( state - > response . data . name . name , response ) ;
return WINBINDD_OK ;
}