1999-12-17 06:11:25 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1999-12-17 06:11:25 +00:00
a WINS nsswitch module
Copyright ( C ) Andrew Tridgell 1999
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 .
*/
# define NO_SYSLOG
# include "includes.h"
2001-12-12 16:08:32 +00:00
# ifdef HAVE_NS_API_H
# undef VOLATILE
# include <ns_daemon.h>
# endif
1999-12-17 06:11:25 +00:00
# ifndef INADDRSZ
# define INADDRSZ 4
# endif
2001-12-12 16:08:32 +00:00
static int initialised ;
2001-12-22 00:51:32 +00:00
extern BOOL AllowDebugChange ;
2001-12-12 16:08:32 +00:00
2001-05-15 21:53:19 +00: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 */
2001-12-22 00:51:32 +00:00
if ( bind ( res , ( struct sockaddr * ) & sock , sizeof ( sock ) ) < 0 ) {
close ( res ) ;
2001-05-15 21:53:19 +00:00
return ( - 1 ) ;
2001-12-22 00:51:32 +00:00
}
set_socket_options ( res , " SO_BROADCAST " ) ;
2001-05-15 21:53:19 +00:00
return res ;
}
2001-12-12 16:08:32 +00:00
static void nss_wins_init ( void )
{
initialised = 1 ;
DEBUGLEVEL = 0 ;
2001-12-22 00:51:32 +00:00
AllowDebugChange = False ;
/* needed for lp_xx() functions */
charset_initialise ( ) ;
2001-12-12 16:08:32 +00:00
2001-12-22 00:51:32 +00:00
TimeInit ( ) ;
2001-12-12 16:08:32 +00:00
setup_logging ( " nss_wins " , False ) ;
lp_load ( dyn_CONFIGFILE , True , False , False ) ;
load_interfaces ( ) ;
2001-12-22 00:51:32 +00:00
codepage_initialise ( lp_client_code_page ( ) ) ;
}
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 ;
if ( ! initialised ) {
nss_wins_init ( ) ;
}
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 ;
2001-12-12 16:08:32 +00:00
}
2001-12-22 00:51:32 +00:00
static struct in_addr * lookup_byname_backend ( const char * name , int * count )
1999-12-17 06:11:25 +00:00
{
int fd ;
2001-12-12 16:08:32 +00:00
struct in_addr * ret = NULL ;
2000-10-11 15:54:17 +00:00
struct in_addr p ;
1999-12-17 06:11:25 +00:00
int j ;
if ( ! initialised ) {
2001-12-12 16:08:32 +00:00
nss_wins_init ( ) ;
1999-12-17 06:11:25 +00:00
}
* count = 0 ;
2001-05-15 21:53:19 +00:00
fd = wins_lookup_open_socket_in ( ) ;
if ( fd = = - 1 )
return NULL ;
1999-12-17 06:11:25 +00:00
2000-10-11 15:54:17 +00:00
p = wins_srv_ip ( ) ;
2001-11-26 03:11:44 +00:00
if ( ! is_zero_ip ( p ) ) {
2000-10-11 15:54:17 +00:00
ret = name_query ( fd , name , 0x20 , False , True , p , count ) ;
1999-12-17 06:11:25 +00:00
goto out ;
}
if ( lp_wins_support ( ) ) {
/* we are our own WINS server */
2000-01-07 08:46:33 +00:00
ret = name_query ( fd , name , 0x20 , False , True , * interpret_addr2 ( " 127.0.0.1 " ) , count ) ;
1999-12-17 06:11:25 +00:00
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 ) ;
2000-01-07 08:46:33 +00:00
ret = name_query ( fd , name , 0x20 , True , True , * bcast , count ) ;
1999-12-17 06:11:25 +00:00
if ( ret ) break ;
}
out :
2001-05-15 21:53:19 +00:00
1999-12-17 06:11:25 +00:00
close ( fd ) ;
return ret ;
}
2001-12-12 16:08:32 +00:00
# ifdef HAVE_NS_API_H
/* IRIX version */
int init ( void )
{
2001-12-22 00:51:32 +00:00
nsd_logprintf ( NSD_LOG_MIN , " entering init (wins) \n " ) ;
2001-12-12 16:08:32 +00:00
nss_wins_init ( ) ;
return NSD_OK ;
}
int lookup ( nsd_file_t * rq )
{
char * map ;
char * key ;
2001-12-22 00:51:32 +00:00
char * addr ;
2001-12-12 16:08:32 +00:00
struct in_addr * ip_list ;
2001-12-22 00:51:32 +00:00
struct node_status * status ;
int i , count , len , size ;
char response [ 1024 ] ;
BOOL found = False ;
2001-12-12 16:08:32 +00:00
2001-12-22 00:51:32 +00:00
nsd_logprintf ( NSD_LOG_MIN , " entering lookup (wins) \n " ) ;
2001-12-12 16:08:32 +00:00
if ( ! rq )
return NSD_ERROR ;
map = nsd_attr_fetch_string ( rq - > f_attrs , " table " , ( char * ) 0 ) ;
if ( ! map ) {
rq - > f_status = NS_FATAL ;
return NSD_ERROR ;
}
key = nsd_attr_fetch_string ( rq - > f_attrs , " key " , ( char * ) 0 ) ;
if ( ! key | | ! * key ) {
rq - > f_status = NS_FATAL ;
return NSD_ERROR ;
}
2001-12-22 00:51:32 +00:00
response [ 0 ] = ' \0 ' ;
len = sizeof ( response ) - 2 ;
/*
* response needs to be a string of the following format
* ip_address [ ip_address ] * \ tname [ alias ] *
*/
if ( strcasecmp ( map , " hosts.byaddr " ) = = 0 ) {
if ( status = lookup_byaddr_backend ( key , & count ) ) {
size = strlen ( key ) + 1 ;
if ( size > len ) {
free ( status ) ;
return NSD_ERROR ;
}
len - = size ;
strncat ( response , key , size ) ;
strncat ( response , " \t " , 1 ) ;
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 ) {
free ( status ) ;
return NSD_ERROR ;
}
len - = size ;
strncat ( response , status [ i ] . name , size ) ;
strncat ( response , " " , 1 ) ;
found = True ;
}
}
response [ strlen ( response ) - 1 ] = ' \n ' ;
free ( status ) ;
}
} else if ( strcasecmp ( map , " hosts.byname " ) = = 0 ) {
if ( ip_list = lookup_byname_backend ( key , & count ) ) {
for ( i = count ; i ; i - - ) {
addr = inet_ntoa ( ip_list [ i - 1 ] ) ;
size = strlen ( addr ) + 1 ;
if ( size > len ) {
free ( ip_list ) ;
return NSD_ERROR ;
}
len - = size ;
if ( i ! = 0 )
response [ strlen ( response ) - 1 ] = ' ' ;
strncat ( response , addr , size ) ;
strncat ( response , " \t " , 1 ) ;
}
size = strlen ( key ) + 1 ;
if ( size > len ) {
free ( ip_list ) ;
return NSD_ERROR ;
}
strncat ( response , key , size ) ;
strncat ( response , " \n " , 1 ) ;
found = True ;
free ( ip_list ) ;
}
2001-12-12 16:08:32 +00:00
}
2001-12-22 00:51:32 +00:00
if ( found ) {
nsd_logprintf ( NSD_LOG_LOW , " lookup (wins %s) %s \n " , map , response ) ;
nsd_set_result ( rq , NS_SUCCESS , response , strlen ( response ) , VOLATILE ) ;
return NSD_OK ;
}
nsd_logprintf ( NSD_LOG_LOW , " lookup (wins) not found \n " ) ;
rq - > f_status = NS_NOTFOUND ;
return NSD_NEXT ;
2001-12-12 16:08:32 +00:00
}
# else
2001-12-22 00:51:32 +00:00
/****************************************************************************
gethostbyname ( ) - we ignore any domain portion of the name and only
handle names that are at most 15 characters long
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-12-12 16:08:32 +00:00
NSS_STATUS
1999-12-17 06:11:25 +00:00
_nss_wins_gethostbyname_r ( const char * name , struct hostent * he ,
char * buffer , size_t buflen , int * errnop ,
int * h_errnop )
{
char * * host_addresses ;
struct in_addr * ip_list ;
int i , count ;
2001-05-15 21:53:19 +00:00
size_t namelen = strlen ( name ) + 1 ;
2001-12-12 16:08:32 +00:00
2001-05-15 22:01:48 +00:00
memset ( he , ' \0 ' , sizeof ( * he ) ) ;
2001-12-22 00:51:32 +00:00
ip_list = lookup_byname_backend ( name , & count ) ;
1999-12-17 06:11:25 +00:00
if ( ! ip_list ) {
return NSS_STATUS_NOTFOUND ;
}
2001-05-15 21:53:19 +00:00
if ( buflen < namelen + ( 2 * count + 1 ) * INADDRSZ ) {
1999-12-17 06:11:25 +00:00
/* no ENOMEM error type?! */
return NSS_STATUS_NOTFOUND ;
}
host_addresses = ( char * * ) buffer ;
he - > h_addr_list = host_addresses ;
host_addresses [ count ] = NULL ;
buffer + = ( count + 1 ) * INADDRSZ ;
buflen + = ( count + 1 ) * INADDRSZ ;
he - > h_addrtype = AF_INET ;
he - > h_length = INADDRSZ ;
for ( i = 0 ; i < count ; i + + ) {
memcpy ( buffer , & ip_list [ i ] . s_addr , INADDRSZ ) ;
* host_addresses = buffer ;
buffer + = INADDRSZ ;
buflen - = INADDRSZ ;
host_addresses + + ;
}
2001-12-12 16:08:32 +00:00
if ( ip_list )
free ( ip_list ) ;
2001-05-15 21:53:19 +00:00
memcpy ( buffer , name , namelen ) ;
he - > h_name = buffer ;
1999-12-17 06:11:25 +00:00
return NSS_STATUS_SUCCESS ;
}
2001-12-12 16:08:32 +00:00
# endif