2005-02-06 08:25:53 +00:00
/*
Unix SMB / CIFS implementation .
wins client name registration and refresh
Copyright ( C ) Andrew Tridgell 2005
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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-02-06 08:25:53 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-02-06 08:25:53 +00:00
*/
# include "includes.h"
# include "nbt_server/nbt_server.h"
2005-12-30 12:43:11 +00:00
# include "nbt_server/wins/winsserver.h"
2005-02-06 08:25:53 +00:00
# include "libcli/composite/composite.h"
# include "lib/events/events.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_nbt.h"
2020-11-20 15:27:17 +01:00
# include "samba/service_task.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2005-02-06 08:25:53 +00:00
2005-02-08 01:09:21 +00:00
/* we send WINS client requests using our primary network interface
*/
static struct nbt_name_socket * wins_socket ( struct nbtd_interface * iface )
{
struct nbtd_server * nbtsrv = iface - > nbtsrv ;
return nbtsrv - > interfaces - > nbtsock ;
}
2008-12-29 20:24:57 +01:00
static void nbtd_wins_refresh ( struct tevent_context * ev , struct tevent_timer * te ,
2005-09-26 11:47:55 +00:00
struct timeval t , void * private_data ) ;
2005-02-08 01:09:21 +00:00
2005-02-06 08:25:53 +00:00
/*
2005-02-08 01:09:21 +00:00
retry a WINS name registration
2005-02-06 08:25:53 +00:00
*/
2008-12-29 20:24:57 +01:00
static void nbtd_wins_register_retry ( struct tevent_context * ev , struct tevent_timer * te ,
2005-09-26 11:47:55 +00:00
struct timeval t , void * private_data )
2005-02-06 08:25:53 +00:00
{
2005-09-26 11:47:55 +00:00
struct nbtd_iface_name * iname = talloc_get_type ( private_data , struct nbtd_iface_name ) ;
2005-02-08 01:09:21 +00:00
nbtd_winsclient_register ( iname ) ;
2005-02-06 08:25:53 +00:00
}
2006-01-18 16:27:29 +00:00
/*
start a timer to refresh this name
*/
static void nbtd_wins_start_refresh_timer ( struct nbtd_iface_name * iname )
{
uint32_t refresh_time ;
2010-07-16 14:32:42 +10:00
uint32_t max_refresh_time = lpcfg_parm_int ( iname - > iface - > nbtsrv - > task - > lp_ctx , NULL , " nbtd " , " max_refresh_time " , 7200 ) ;
2006-01-18 16:27:29 +00:00
refresh_time = MIN ( max_refresh_time , iname - > ttl / 2 ) ;
2010-05-25 15:29:14 -04:00
tevent_add_timer ( iname - > iface - > nbtsrv - > task - > event_ctx ,
2006-01-18 16:27:29 +00:00
iname ,
timeval_add ( & iname - > registration_time , refresh_time , 0 ) ,
nbtd_wins_refresh , iname ) ;
}
2005-02-08 01:09:21 +00:00
2010-10-11 09:41:16 +02:00
struct nbtd_wins_refresh_state {
struct nbtd_iface_name * iname ;
struct nbt_name_refresh_wins io ;
} ;
2005-02-06 08:25:53 +00:00
/*
called when a wins name refresh has completed
*/
2010-10-11 08:54:27 +02:00
static void nbtd_wins_refresh_handler ( struct tevent_req * subreq )
2005-02-06 08:25:53 +00:00
{
NTSTATUS status ;
2010-10-11 09:41:16 +02:00
struct nbtd_wins_refresh_state * state =
2010-10-11 08:54:27 +02:00
tevent_req_callback_data ( subreq ,
2010-10-11 09:41:16 +02:00
struct nbtd_wins_refresh_state ) ;
struct nbtd_iface_name * iname = state - > iname ;
2005-02-06 08:25:53 +00:00
2010-10-11 09:41:16 +02:00
status = nbt_name_refresh_wins_recv ( subreq , state , & state - > io ) ;
2010-10-11 08:54:27 +02:00
TALLOC_FREE ( subreq ) ;
2005-02-08 01:09:21 +00:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_IO_TIMEOUT ) ) {
/* our WINS server is dead - start registration over
from scratch */
2005-02-12 01:00:15 +00:00
DEBUG ( 2 , ( " Failed to refresh %s with WINS server %s \n " ,
2010-10-11 09:41:16 +02:00
nbt_name_string ( state , & iname - > name ) , iname - > wins_server ) ) ;
talloc_free ( state ) ;
2005-02-08 01:09:21 +00:00
nbtd_winsclient_register ( iname ) ;
return ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-02-12 01:00:15 +00:00
DEBUG ( 1 , ( " Name refresh failure with WINS for %s - %s \n " ,
2010-10-11 09:41:16 +02:00
nbt_name_string ( state , & iname - > name ) , nt_errstr ( status ) ) ) ;
talloc_free ( state ) ;
2005-02-08 01:09:21 +00:00
return ;
2005-09-26 11:47:55 +00:00
}
2005-02-08 01:09:21 +00:00
2010-10-11 09:41:16 +02:00
if ( state - > io . out . rcode ! = 0 ) {
2005-02-12 01:00:15 +00:00
DEBUG ( 1 , ( " WINS server %s rejected name refresh of %s - %s \n " ,
2010-10-11 09:41:16 +02:00
state - > io . out . wins_server ,
nbt_name_string ( state , & iname - > name ) ,
nt_errstr ( nbt_rcode_to_ntstatus ( state - > io . out . rcode ) ) ) ) ;
2005-02-08 01:09:21 +00:00
iname - > nb_flags | = NBT_NM_CONFLICT ;
2010-10-11 09:41:16 +02:00
talloc_free ( state ) ;
2005-02-08 01:09:21 +00:00
return ;
}
2005-02-12 01:00:15 +00:00
DEBUG ( 4 , ( " Refreshed name %s with WINS server %s \n " ,
2010-10-11 09:41:16 +02:00
nbt_name_string ( state , & iname - > name ) , iname - > wins_server ) ) ;
2005-02-08 01:09:21 +00:00
/* success - start a periodic name refresh */
iname - > nb_flags | = NBT_NM_ACTIVE ;
if ( iname - > wins_server ) {
2006-08-24 11:24:06 +00:00
/*
* talloc_free ( ) would generate a warning ,
* so steal it into the tmp context
*/
2010-10-11 09:41:16 +02:00
talloc_steal ( state , iname - > wins_server ) ;
2005-02-08 01:09:21 +00:00
}
2010-10-11 09:41:16 +02:00
iname - > wins_server = talloc_move ( iname , & state - > io . out . wins_server ) ;
2005-02-08 01:09:21 +00:00
iname - > registration_time = timeval_current ( ) ;
2010-10-11 09:41:16 +02:00
talloc_free ( state ) ;
nbtd_wins_start_refresh_timer ( iname ) ;
2005-02-08 01:09:21 +00:00
}
/*
refresh a WINS name registration
*/
2008-12-29 20:24:57 +01:00
static void nbtd_wins_refresh ( struct tevent_context * ev , struct tevent_timer * te ,
2005-09-26 11:47:55 +00:00
struct timeval t , void * private_data )
2005-02-08 01:09:21 +00:00
{
2005-09-26 11:47:55 +00:00
struct nbtd_iface_name * iname = talloc_get_type ( private_data , struct nbtd_iface_name ) ;
2005-02-08 01:09:21 +00:00
struct nbtd_interface * iface = iname - > iface ;
2010-10-11 09:41:16 +02:00
struct nbt_name_socket * nbtsock = wins_socket ( iface ) ;
2010-10-11 08:54:27 +02:00
struct tevent_req * subreq ;
2010-10-11 09:41:16 +02:00
struct nbtd_wins_refresh_state * state ;
2014-02-27 09:29:36 +01:00
char * * l ;
2005-02-08 01:09:21 +00:00
2010-10-11 09:41:16 +02:00
state = talloc_zero ( iname , struct nbtd_wins_refresh_state ) ;
if ( state = = NULL ) {
2005-12-22 22:03:25 +00:00
return ;
}
2010-10-11 09:41:16 +02:00
state - > iname = iname ;
/* setup a wins name refresh request */
state - > io . in . name = iname - > name ;
2014-02-27 09:29:36 +01:00
l = str_list_make_single ( state , iname - > wins_server ) ;
state - > io . in . wins_servers = discard_const_p ( const char * , l ) ;
2010-10-11 09:41:16 +02:00
state - > io . in . wins_port = lpcfg_nbt_port ( iface - > nbtsrv - > task - > lp_ctx ) ;
state - > io . in . addresses = nbtd_address_list ( iface , state ) ;
state - > io . in . nb_flags = iname - > nb_flags ;
state - > io . in . ttl = iname - > ttl ;
if ( ! state - > io . in . addresses ) {
talloc_free ( state ) ;
2005-02-08 01:09:21 +00:00
return ;
}
2010-10-11 08:54:27 +02:00
subreq = nbt_name_refresh_wins_send ( state , ev , nbtsock , & state - > io ) ;
2010-10-11 09:41:16 +02:00
if ( subreq = = NULL ) {
talloc_free ( state ) ;
return ;
}
2005-02-08 01:09:21 +00:00
2010-10-11 08:54:27 +02:00
tevent_req_set_callback ( subreq , nbtd_wins_refresh_handler , state ) ;
2005-02-08 01:09:21 +00:00
}
2010-10-11 20:49:28 +02:00
struct nbtd_wins_register_state {
struct nbtd_iface_name * iname ;
struct nbt_name_register_wins io ;
} ;
2005-02-08 01:09:21 +00:00
/*
called when a wins name register has completed
*/
2010-10-11 21:58:29 +02:00
static void nbtd_wins_register_handler ( struct tevent_req * subreq )
2005-02-08 01:09:21 +00:00
{
NTSTATUS status ;
2010-10-11 20:49:28 +02:00
struct nbtd_wins_register_state * state =
2010-10-11 21:58:29 +02:00
tevent_req_callback_data ( subreq ,
2010-10-11 20:49:28 +02:00
struct nbtd_wins_register_state ) ;
struct nbtd_iface_name * iname = state - > iname ;
2005-02-08 01:09:21 +00:00
2010-10-11 20:49:28 +02:00
status = nbt_name_register_wins_recv ( subreq , state , & state - > io ) ;
2010-10-11 21:58:29 +02:00
TALLOC_FREE ( subreq ) ;
2005-02-06 08:25:53 +00:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_IO_TIMEOUT ) ) {
/* none of the WINS servers responded - try again
periodically */
2010-07-16 14:32:42 +10:00
int wins_retry_time = lpcfg_parm_int ( iname - > iface - > nbtsrv - > task - > lp_ctx , NULL , " nbtd " , " wins_retry " , 300 ) ;
2010-05-25 15:29:14 -04:00
tevent_add_timer ( iname - > iface - > nbtsrv - > task - > event_ctx ,
2005-02-06 08:25:53 +00:00
iname ,
timeval_current_ofs ( wins_retry_time , 0 ) ,
2005-02-08 01:09:21 +00:00
nbtd_wins_register_retry ,
2005-02-06 08:25:53 +00:00
iname ) ;
2010-10-11 20:49:28 +02:00
talloc_free ( state ) ;
2005-02-06 08:25:53 +00:00
return ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-02-12 01:00:15 +00:00
DEBUG ( 1 , ( " Name register failure with WINS for %s - %s \n " ,
2010-10-11 20:49:28 +02:00
nbt_name_string ( state , & iname - > name ) , nt_errstr ( status ) ) ) ;
talloc_free ( state ) ;
2005-02-06 08:25:53 +00:00
return ;
}
2010-10-11 20:49:28 +02:00
if ( state - > io . out . rcode ! = 0 ) {
2005-02-12 01:00:15 +00:00
DEBUG ( 1 , ( " WINS server %s rejected name register of %s - %s \n " ,
2010-10-11 20:49:28 +02:00
state - > io . out . wins_server ,
nbt_name_string ( state , & iname - > name ) ,
nt_errstr ( nbt_rcode_to_ntstatus ( state - > io . out . rcode ) ) ) ) ;
2005-02-06 08:25:53 +00:00
iname - > nb_flags | = NBT_NM_CONFLICT ;
2010-10-11 20:49:28 +02:00
talloc_free ( state ) ;
2005-02-06 08:25:53 +00:00
return ;
}
/* success - start a periodic name refresh */
iname - > nb_flags | = NBT_NM_ACTIVE ;
if ( iname - > wins_server ) {
2006-08-24 11:24:06 +00:00
/*
* talloc_free ( ) would generate a warning ,
* so steal it into the tmp context
*/
2010-10-11 20:49:28 +02:00
talloc_steal ( state , iname - > wins_server ) ;
2005-02-06 08:25:53 +00:00
}
2010-10-11 20:49:28 +02:00
iname - > wins_server = talloc_move ( iname , & state - > io . out . wins_server ) ;
2005-02-06 08:25:53 +00:00
iname - > registration_time = timeval_current ( ) ;
2005-02-12 01:00:15 +00:00
DEBUG ( 3 , ( " Registered %s with WINS server %s \n " ,
2010-10-11 20:49:28 +02:00
nbt_name_string ( state , & iname - > name ) , iname - > wins_server ) ) ;
talloc_free ( state ) ;
2005-02-08 01:09:21 +00:00
2010-10-11 20:49:28 +02:00
nbtd_wins_start_refresh_timer ( iname ) ;
2005-02-06 08:25:53 +00:00
}
/*
2005-02-08 01:09:21 +00:00
register a name with our WINS servers
2005-02-06 08:25:53 +00:00
*/
2005-02-08 01:09:21 +00:00
void nbtd_winsclient_register ( struct nbtd_iface_name * iname )
2005-02-06 08:25:53 +00:00
{
struct nbtd_interface * iface = iname - > iface ;
2010-10-11 20:49:28 +02:00
struct nbt_name_socket * nbtsock = wins_socket ( iface ) ;
struct nbtd_wins_register_state * state ;
2010-10-11 21:58:29 +02:00
struct tevent_req * subreq ;
2010-10-11 20:49:28 +02:00
state = talloc_zero ( iname , struct nbtd_wins_register_state ) ;
if ( state = = NULL ) {
return ;
}
state - > iname = iname ;
2005-02-06 08:25:53 +00:00
2005-02-08 01:09:21 +00:00
/* setup a wins name register request */
2010-10-11 20:49:28 +02:00
state - > io . in . name = iname - > name ;
state - > io . in . wins_port = lpcfg_nbt_port ( iface - > nbtsrv - > task - > lp_ctx ) ;
state - > io . in . wins_servers = lpcfg_wins_server_list ( iface - > nbtsrv - > task - > lp_ctx ) ;
state - > io . in . addresses = nbtd_address_list ( iface , state ) ;
state - > io . in . nb_flags = iname - > nb_flags ;
state - > io . in . ttl = iname - > ttl ;
if ( state - > io . in . addresses = = NULL ) {
talloc_free ( state ) ;
2005-12-22 22:03:25 +00:00
return ;
}
2010-10-11 21:58:29 +02:00
subreq = nbt_name_register_wins_send ( state , iface - > nbtsrv - > task - > event_ctx ,
nbtsock , & state - > io ) ;
2010-10-11 20:49:28 +02:00
if ( subreq = = NULL ) {
talloc_free ( state ) ;
2005-02-06 08:25:53 +00:00
return ;
}
2010-10-11 21:58:29 +02:00
tevent_req_set_callback ( subreq , nbtd_wins_register_handler , state ) ;
2005-02-06 08:25:53 +00:00
}