2005-02-16 10:03:18 +00:00
/*
Unix SMB / CIFS implementation .
low level WINS replication client code
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-16 10:03:18 +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-16 10:03:18 +00:00
*/
# include "includes.h"
# include "lib/events/events.h"
2008-10-11 21:31:42 +02:00
# include "../lib/util/dlinklist.h"
2005-02-16 10:03:18 +00:00
# include "lib/socket/socket.h"
2005-09-09 16:00:02 +00:00
# include "libcli/wrepl/winsrepl.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_winsrepl.h"
2005-12-12 21:31:42 +00:00
# include "lib/stream/packet.h"
# include "libcli/composite/composite.h"
2006-03-07 11:07:23 +00:00
# include "system/network.h"
2006-08-17 13:37:04 +00:00
# include "lib/socket/netif.h"
2007-12-06 23:57:22 +01:00
# include "param/param.h"
2010-03-03 13:38:08 +01:00
# include "lib/util/tevent_ntstatus.h"
2005-12-12 21:31:42 +00:00
static struct wrepl_request * wrepl_request_finished ( struct wrepl_request * req , NTSTATUS status ) ;
2005-02-16 10:03:18 +00:00
/*
mark all pending requests as dead - called when a socket error happens
*/
2005-09-27 16:53:08 +00:00
static void wrepl_socket_dead ( struct wrepl_socket * wrepl_socket , NTSTATUS status )
2005-02-16 10:03:18 +00:00
{
2007-10-06 22:28:14 +00:00
wrepl_socket - > dead = true ;
2005-09-27 10:31:57 +00:00
2005-12-14 18:22:38 +00:00
if ( wrepl_socket - > packet ) {
2005-12-12 21:31:42 +00:00
packet_recv_disable ( wrepl_socket - > packet ) ;
packet_set_fde ( wrepl_socket - > packet , NULL ) ;
2005-12-14 18:22:38 +00:00
packet_set_socket ( wrepl_socket - > packet , NULL ) ;
}
if ( wrepl_socket - > event . fde ) {
2005-12-12 21:31:42 +00:00
talloc_free ( wrepl_socket - > event . fde ) ;
wrepl_socket - > event . fde = NULL ;
2005-09-27 16:53:08 +00:00
}
if ( wrepl_socket - > sock ) {
talloc_free ( wrepl_socket - > sock ) ;
wrepl_socket - > sock = NULL ;
}
2005-02-16 10:03:18 +00:00
2005-09-27 16:53:08 +00:00
if ( NT_STATUS_EQUAL ( NT_STATUS_UNSUCCESSFUL , status ) ) {
status = NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
2005-02-16 10:03:18 +00:00
while ( wrepl_socket - > recv_queue ) {
struct wrepl_request * req = wrepl_socket - > recv_queue ;
DLIST_REMOVE ( wrepl_socket - > recv_queue , req ) ;
2005-12-12 21:31:42 +00:00
wrepl_request_finished ( req , status ) ;
2005-02-16 10:03:18 +00:00
}
2005-12-14 21:27:29 +00:00
talloc_set_destructor ( wrepl_socket , NULL ) ;
if ( wrepl_socket - > free_skipped ) {
talloc_free ( wrepl_socket ) ;
}
2005-02-16 10:03:18 +00:00
}
2008-12-29 20:24:57 +01:00
static void wrepl_request_timeout_handler ( struct tevent_context * ev , struct tevent_timer * te ,
2005-09-27 16:53:08 +00:00
struct timeval t , void * ptr )
{
struct wrepl_request * req = talloc_get_type ( ptr , struct wrepl_request ) ;
wrepl_socket_dead ( req - > wrepl_socket , NT_STATUS_IO_TIMEOUT ) ;
}
2005-02-16 10:03:18 +00:00
/*
handle recv events
*/
2009-02-02 08:26:33 +01:00
static NTSTATUS wrepl_finish_recv ( void * private_data , DATA_BLOB packet_blob_in )
2005-02-16 10:03:18 +00:00
{
2009-02-02 08:26:33 +01:00
struct wrepl_socket * wrepl_socket = talloc_get_type ( private_data , struct wrepl_socket ) ;
2005-02-16 10:03:18 +00:00
struct wrepl_request * req = wrepl_socket - > recv_queue ;
DATA_BLOB blob ;
2007-11-09 19:24:51 +01:00
enum ndr_err_code ndr_err ;
2005-02-16 10:03:18 +00:00
2005-12-19 21:19:14 +00:00
if ( ! req ) {
2006-09-09 10:05:58 +00:00
DEBUG ( 1 , ( " Received unexpected WINS packet of length %u! \n " ,
( unsigned ) packet_blob_in . length ) ) ;
2005-12-19 21:19:14 +00:00
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2005-02-16 10:03:18 +00:00
req - > packet = talloc ( req , struct wrepl_packet ) ;
2005-12-12 21:31:42 +00:00
NT_STATUS_HAVE_NO_MEMORY ( req - > packet ) ;
2005-02-16 10:03:18 +00:00
2005-12-12 21:31:42 +00:00
blob . data = packet_blob_in . data + 4 ;
blob . length = packet_blob_in . length - 4 ;
2005-02-16 10:03:18 +00:00
/* we have a full request - parse it */
2008-02-21 17:17:37 +01:00
ndr_err = ndr_pull_struct_blob ( & blob , req - > packet , wrepl_socket - > iconv_convenience , req - > packet ,
2007-11-09 19:24:51 +01:00
( ndr_pull_flags_fn_t ) ndr_pull_wrepl_packet ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
NTSTATUS status = ndr_map_error2ntstatus ( ndr_err ) ;
2007-11-02 09:15:12 +01:00
wrepl_request_finished ( req , status ) ;
2005-12-12 21:31:42 +00:00
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
if ( DEBUGLVL ( 10 ) ) {
2006-09-09 10:05:58 +00:00
DEBUG ( 10 , ( " Received WINS packet of length %u \n " ,
( unsigned ) packet_blob_in . length ) ) ;
2005-02-16 10:03:18 +00:00
NDR_PRINT_DEBUG ( wrepl_packet , req - > packet ) ;
}
2007-11-02 09:15:12 +01:00
wrepl_request_finished ( req , NT_STATUS_OK ) ;
2005-12-12 21:31:42 +00:00
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
/*
handler for winrepl events
*/
2008-12-29 20:24:57 +01:00
static void wrepl_handler ( struct tevent_context * ev , struct tevent_fd * fde ,
2009-02-02 08:26:33 +01:00
uint16_t flags , void * private_data )
2005-02-16 10:03:18 +00:00
{
2009-02-02 08:26:33 +01:00
struct wrepl_socket * wrepl_socket = talloc_get_type ( private_data ,
2005-02-16 10:03:18 +00:00
struct wrepl_socket ) ;
if ( flags & EVENT_FD_READ ) {
2005-12-12 21:31:42 +00:00
packet_recv ( wrepl_socket - > packet ) ;
return ;
}
if ( flags & EVENT_FD_WRITE ) {
packet_queue_run ( wrepl_socket - > packet ) ;
2005-02-16 10:03:18 +00:00
}
}
2009-02-02 08:26:33 +01:00
static void wrepl_error ( void * private_data , NTSTATUS status )
2005-02-16 10:03:18 +00:00
{
2009-02-02 08:26:33 +01:00
struct wrepl_socket * wrepl_socket = talloc_get_type ( private_data ,
2005-02-16 10:03:18 +00:00
struct wrepl_socket ) ;
2005-12-12 21:31:42 +00:00
wrepl_socket_dead ( wrepl_socket , status ) ;
2005-02-16 10:03:18 +00:00
}
2005-12-12 21:31:42 +00:00
2005-09-27 16:53:08 +00:00
/*
destroy a wrepl_socket destructor
*/
2006-05-24 07:34:11 +00:00
static int wrepl_socket_destructor ( struct wrepl_socket * sock )
2005-09-27 16:53:08 +00:00
{
2005-12-14 21:27:29 +00:00
if ( sock - > dead ) {
2007-10-06 22:28:14 +00:00
sock - > free_skipped = true ;
2005-12-14 21:27:29 +00:00
return - 1 ;
}
2005-10-06 14:38:07 +00:00
wrepl_socket_dead ( sock , NT_STATUS_LOCAL_DISCONNECT ) ;
2005-09-27 16:53:08 +00:00
return 0 ;
}
2005-02-16 10:03:18 +00:00
/*
initialise a wrepl_socket . The event_ctx is optional , if provided then
operations will use that event context
*/
struct wrepl_socket * wrepl_socket_init ( TALLOC_CTX * mem_ctx ,
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx ,
2008-02-21 17:17:37 +01:00
struct smb_iconv_convenience * iconv_convenience )
2005-02-16 10:03:18 +00:00
{
struct wrepl_socket * wrepl_socket ;
NTSTATUS status ;
2005-12-12 21:31:42 +00:00
wrepl_socket = talloc_zero ( mem_ctx , struct wrepl_socket ) ;
if ( ! wrepl_socket ) return NULL ;
2005-02-16 10:03:18 +00:00
2009-08-07 17:14:13 +10:00
wrepl_socket - > event . ctx = event_ctx ;
2005-12-12 21:31:42 +00:00
if ( ! wrepl_socket - > event . ctx ) goto failed ;
2005-02-16 10:03:18 +00:00
2008-02-21 17:17:37 +01:00
wrepl_socket - > iconv_convenience = iconv_convenience ;
2005-02-16 10:03:18 +00:00
status = socket_create ( " ip " , SOCKET_TYPE_STREAM , & wrepl_socket - > sock , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
talloc_steal ( wrepl_socket , wrepl_socket - > sock ) ;
2005-09-27 16:53:08 +00:00
wrepl_socket - > request_timeout = WREPL_SOCKET_REQUEST_TIMEOUT ;
2005-09-30 01:55:29 +00:00
talloc_set_destructor ( wrepl_socket , wrepl_socket_destructor ) ;
return wrepl_socket ;
failed :
talloc_free ( wrepl_socket ) ;
return NULL ;
}
/*
initialise a wrepl_socket from an already existing connection
*/
struct wrepl_socket * wrepl_socket_merge ( TALLOC_CTX * mem_ctx ,
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx ,
2005-12-30 10:45:43 +00:00
struct socket_context * sock ,
struct packet_context * pack )
2005-09-30 01:55:29 +00:00
{
struct wrepl_socket * wrepl_socket ;
2005-12-12 21:31:42 +00:00
wrepl_socket = talloc_zero ( mem_ctx , struct wrepl_socket ) ;
2005-09-30 01:55:29 +00:00
if ( wrepl_socket = = NULL ) goto failed ;
2009-08-07 17:14:13 +10:00
wrepl_socket - > event . ctx = event_ctx ;
2005-12-12 21:31:42 +00:00
if ( wrepl_socket - > event . ctx = = NULL ) goto failed ;
2005-09-30 01:55:29 +00:00
2005-12-30 10:45:43 +00:00
wrepl_socket - > sock = sock ;
2005-09-30 01:55:29 +00:00
talloc_steal ( wrepl_socket , wrepl_socket - > sock ) ;
2005-12-12 21:31:42 +00:00
2005-09-30 01:55:29 +00:00
wrepl_socket - > request_timeout = WREPL_SOCKET_REQUEST_TIMEOUT ;
2005-12-12 21:31:42 +00:00
wrepl_socket - > event . fde = event_add_fd ( wrepl_socket - > event . ctx , wrepl_socket ,
socket_get_fd ( wrepl_socket - > sock ) ,
EVENT_FD_READ ,
wrepl_handler , wrepl_socket ) ;
if ( wrepl_socket - > event . fde = = NULL ) {
2005-09-30 01:55:29 +00:00
goto failed ;
}
2005-12-30 10:45:43 +00:00
wrepl_socket - > packet = pack ;
2005-12-12 21:31:42 +00:00
talloc_steal ( wrepl_socket , wrepl_socket - > packet ) ;
packet_set_private ( wrepl_socket - > packet , wrepl_socket ) ;
packet_set_socket ( wrepl_socket - > packet , wrepl_socket - > sock ) ;
packet_set_callback ( wrepl_socket - > packet , wrepl_finish_recv ) ;
packet_set_full_request ( wrepl_socket - > packet , packet_full_request_u32 ) ;
packet_set_error_handler ( wrepl_socket - > packet , wrepl_error ) ;
packet_set_event_context ( wrepl_socket - > packet , wrepl_socket - > event . ctx ) ;
packet_set_fde ( wrepl_socket - > packet , wrepl_socket - > event . fde ) ;
packet_set_serialise ( wrepl_socket - > packet ) ;
2005-09-27 16:53:08 +00:00
talloc_set_destructor ( wrepl_socket , wrepl_socket_destructor ) ;
2005-02-16 10:03:18 +00:00
return wrepl_socket ;
failed :
talloc_free ( wrepl_socket ) ;
return NULL ;
}
/*
destroy a wrepl_request
*/
2006-05-24 07:34:11 +00:00
static int wrepl_request_destructor ( struct wrepl_request * req )
2005-02-16 10:03:18 +00:00
{
if ( req - > state = = WREPL_REQUEST_RECV ) {
DLIST_REMOVE ( req - > wrepl_socket - > recv_queue , req ) ;
}
req - > state = WREPL_REQUEST_ERROR ;
return 0 ;
}
/*
wait for a request to complete
*/
static NTSTATUS wrepl_request_wait ( struct wrepl_request * req )
{
NT_STATUS_HAVE_NO_MEMORY ( req ) ;
while ( req - > state < WREPL_REQUEST_DONE ) {
2005-12-12 21:31:42 +00:00
event_loop_once ( req - > wrepl_socket - > event . ctx ) ;
2005-02-16 10:03:18 +00:00
}
return req - > status ;
}
2010-03-03 17:18:23 +01:00
const char * wrepl_best_ip ( struct loadparm_context * lp_ctx , const char * peer_ip )
{
struct interface * ifaces ;
load_interfaces ( lp_ctx , lp_interfaces ( lp_ctx ) , & ifaces ) ;
return iface_best_ip ( ifaces , peer_ip ) ;
}
2005-12-12 21:31:42 +00:00
struct wrepl_connect_state {
struct wrepl_socket * wrepl_socket ;
} ;
2005-02-16 10:03:18 +00:00
2010-03-03 17:18:23 +01:00
static void wrepl_connect_handler ( struct composite_context * creq ) ;
struct tevent_req * wrepl_connect_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const char * our_ip , const char * peer_ip )
{
struct tevent_req * req ;
struct wrepl_connect_state * state ;
struct composite_context * subreq ;
struct socket_address * peer , * us ;
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_connect_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > wrepl_socket = wrepl_socket ;
us = socket_address_from_strings ( state , wrepl_socket - > sock - > backend_name ,
our_ip , 0 ) ;
if ( tevent_req_nomem ( us , req ) ) {
return tevent_req_post ( req , ev ) ;
}
peer = socket_address_from_strings ( state , wrepl_socket - > sock - > backend_name ,
peer_ip , WINS_REPLICATION_PORT ) ;
if ( tevent_req_nomem ( peer , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq = socket_connect_send ( wrepl_socket - > sock , us , peer ,
0 , wrepl_socket - > event . ctx ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq - > async . fn = wrepl_connect_handler ;
subreq - > async . private_data = req ;
return req ;
}
static void wrepl_connect_handler ( struct composite_context * subreq )
2005-02-16 10:03:18 +00:00
{
2010-03-03 17:18:23 +01:00
struct tevent_req * req = talloc_get_type_abort ( subreq - > async . private_data ,
struct tevent_req ) ;
struct wrepl_connect_state * state = tevent_req_data ( req ,
2005-12-12 21:31:42 +00:00
struct wrepl_connect_state ) ;
struct wrepl_socket * wrepl_socket = state - > wrepl_socket ;
2010-03-03 17:18:23 +01:00
NTSTATUS status ;
2005-12-12 21:31:42 +00:00
2010-03-03 17:18:23 +01:00
status = socket_connect_recv ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
2005-12-12 21:31:42 +00:00
wrepl_socket - > event . fde = event_add_fd ( wrepl_socket - > event . ctx , wrepl_socket ,
socket_get_fd ( wrepl_socket - > sock ) ,
EVENT_FD_READ ,
wrepl_handler , wrepl_socket ) ;
2010-03-03 17:18:23 +01:00
if ( tevent_req_nomem ( wrepl_socket - > event . fde , req ) ) {
return ;
}
2005-12-12 21:31:42 +00:00
/* setup the stream -> packet parser */
wrepl_socket - > packet = packet_init ( wrepl_socket ) ;
2010-03-03 17:18:23 +01:00
if ( tevent_req_nomem ( wrepl_socket - > packet , req ) ) {
return ;
}
2005-12-12 21:31:42 +00:00
packet_set_private ( wrepl_socket - > packet , wrepl_socket ) ;
packet_set_socket ( wrepl_socket - > packet , wrepl_socket - > sock ) ;
packet_set_callback ( wrepl_socket - > packet , wrepl_finish_recv ) ;
packet_set_full_request ( wrepl_socket - > packet , packet_full_request_u32 ) ;
packet_set_error_handler ( wrepl_socket - > packet , wrepl_error ) ;
packet_set_event_context ( wrepl_socket - > packet , wrepl_socket - > event . ctx ) ;
packet_set_fde ( wrepl_socket - > packet , wrepl_socket - > event . fde ) ;
packet_set_serialise ( wrepl_socket - > packet ) ;
2010-03-03 17:18:23 +01:00
tevent_req_done ( req ) ;
2005-02-16 10:03:18 +00:00
}
/*
connect a wrepl_socket to a WINS server - recv side
*/
2010-03-03 17:18:23 +01:00
NTSTATUS wrepl_connect_recv ( struct tevent_req * req )
2005-02-16 10:03:18 +00:00
{
2010-03-03 17:18:23 +01:00
struct wrepl_connect_state * state = tevent_req_data ( req ,
2005-12-12 21:31:42 +00:00
struct wrepl_connect_state ) ;
struct wrepl_socket * wrepl_socket = state - > wrepl_socket ;
2010-03-03 17:18:23 +01:00
NTSTATUS status ;
2005-02-16 10:03:18 +00:00
2010-03-03 17:18:23 +01:00
if ( tevent_req_is_nterror ( req , & status ) ) {
2005-12-12 21:31:42 +00:00
wrepl_socket_dead ( wrepl_socket , status ) ;
2010-03-03 17:18:23 +01:00
tevent_req_received ( req ) ;
return status ;
2005-12-12 21:31:42 +00:00
}
2010-03-03 17:18:23 +01:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2005-12-12 21:31:42 +00:00
}
2005-02-16 10:03:18 +00:00
/*
connect a wrepl_socket to a WINS server - sync API
*/
2008-12-17 23:12:10 +01:00
NTSTATUS wrepl_connect ( struct wrepl_socket * wrepl_socket ,
2007-12-10 18:41:55 +01:00
const char * our_ip , const char * peer_ip )
2005-02-16 10:03:18 +00:00
{
2010-03-03 17:18:23 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_connect_send ( wrepl_socket , wrepl_socket - > event . ctx ,
wrepl_socket , our_ip , peer_ip ) ;
NT_STATUS_HAVE_NO_MEMORY ( subreq ) ;
ok = tevent_req_poll ( subreq , wrepl_socket - > event . ctx ) ;
if ( ! ok ) {
TALLOC_FREE ( subreq ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = wrepl_connect_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
2005-09-27 10:31:57 +00:00
/*
callback from wrepl_request_trigger ( )
*/
2008-12-29 20:24:57 +01:00
static void wrepl_request_trigger_handler ( struct tevent_context * ev , struct tevent_timer * te ,
2005-09-27 10:31:57 +00:00
struct timeval t , void * ptr )
{
struct wrepl_request * req = talloc_get_type ( ptr , struct wrepl_request ) ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
}
/*
trigger an immediate event on a wrepl_request
2005-12-12 21:31:42 +00:00
the return value should only be used in wrepl_request_send ( )
2007-10-06 22:28:14 +00:00
this is the only place where req - > trigger is true
2005-09-27 10:31:57 +00:00
*/
2005-12-12 21:31:42 +00:00
static struct wrepl_request * wrepl_request_finished ( struct wrepl_request * req , NTSTATUS status )
2005-09-27 10:31:57 +00:00
{
2008-12-29 20:24:57 +01:00
struct tevent_timer * te ;
2005-12-12 21:31:42 +00:00
2005-11-03 18:38:41 +00:00
if ( req - > state = = WREPL_REQUEST_RECV ) {
DLIST_REMOVE ( req - > wrepl_socket - > recv_queue , req ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
req - > state = WREPL_REQUEST_ERROR ;
} else {
req - > state = WREPL_REQUEST_DONE ;
}
req - > status = status ;
2005-12-12 21:31:42 +00:00
if ( req - > trigger ) {
2007-10-06 22:28:14 +00:00
req - > trigger = false ;
2005-12-12 21:31:42 +00:00
/* a zero timeout means immediate */
te = event_add_timed ( req - > wrepl_socket - > event . ctx ,
req , timeval_zero ( ) ,
wrepl_request_trigger_handler , req ) ;
if ( ! te ) {
talloc_free ( req ) ;
return NULL ;
}
return req ;
}
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
return NULL ;
2005-09-27 10:31:57 +00:00
}
2005-12-12 21:31:42 +00:00
struct wrepl_send_ctrl_state {
struct wrepl_send_ctrl ctrl ;
struct wrepl_request * req ;
struct wrepl_socket * wrepl_sock ;
} ;
2006-05-24 07:34:11 +00:00
static int wrepl_send_ctrl_destructor ( struct wrepl_send_ctrl_state * s )
2005-12-12 21:31:42 +00:00
{
struct wrepl_request * req = s - > wrepl_sock - > recv_queue ;
/* check if the request is still in WREPL_STATE_RECV,
* we need this here because the caller has may called
* talloc_free ( req ) and wrepl_send_ctrl_state isn ' t
* a talloc child of the request , so our s - > req pointer
* is maybe invalid !
*/
for ( ; req ; req = req - > next ) {
if ( req = = s - > req ) break ;
}
if ( ! req ) return 0 ;
/* here, we need to make sure the async request handler is called
* later in the next event_loop and now now
*/
2007-10-06 22:28:14 +00:00
req - > trigger = true ;
2005-12-12 21:31:42 +00:00
wrepl_request_finished ( req , NT_STATUS_OK ) ;
if ( s - > ctrl . disconnect_after_send ) {
wrepl_socket_dead ( s - > wrepl_sock , NT_STATUS_LOCAL_DISCONNECT ) ;
}
return 0 ;
}
2005-02-16 10:03:18 +00:00
/*
send a generic wins replication request
*/
struct wrepl_request * wrepl_request_send ( struct wrepl_socket * wrepl_socket ,
2005-12-12 21:31:42 +00:00
struct wrepl_packet * packet ,
struct wrepl_send_ctrl * ctrl )
2005-02-16 10:03:18 +00:00
{
struct wrepl_request * req ;
struct wrepl_wrap wrap ;
2005-12-12 21:31:42 +00:00
DATA_BLOB blob ;
2007-11-02 09:15:12 +01:00
NTSTATUS status ;
2007-11-09 19:24:51 +01:00
enum ndr_err_code ndr_err ;
2005-02-16 10:03:18 +00:00
req = talloc_zero ( wrepl_socket , struct wrepl_request ) ;
2005-12-12 21:31:42 +00:00
if ( ! req ) return NULL ;
2005-11-03 18:38:41 +00:00
req - > wrepl_socket = wrepl_socket ;
2005-12-12 21:31:42 +00:00
req - > state = WREPL_REQUEST_RECV ;
2007-10-06 22:28:14 +00:00
req - > trigger = true ;
2005-11-03 18:38:41 +00:00
2005-12-12 21:31:42 +00:00
DLIST_ADD_END ( wrepl_socket - > recv_queue , req , struct wrepl_request * ) ;
2005-11-03 18:38:41 +00:00
talloc_set_destructor ( req , wrepl_request_destructor ) ;
2005-09-27 10:31:57 +00:00
if ( wrepl_socket - > dead ) {
2005-12-12 21:31:42 +00:00
return wrepl_request_finished ( req , NT_STATUS_INVALID_CONNECTION ) ;
2005-09-27 10:31:57 +00:00
}
2005-02-16 10:03:18 +00:00
wrap . packet = * packet ;
2008-02-21 17:17:37 +01:00
ndr_err = ndr_push_struct_blob ( & blob , req , wrepl_socket - > iconv_convenience , & wrap ,
2007-11-09 19:24:51 +01:00
( ndr_push_flags_fn_t ) ndr_push_wrepl_wrap ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
2007-11-02 09:15:12 +01:00
return wrepl_request_finished ( req , status ) ;
2005-12-12 21:31:42 +00:00
}
2005-02-16 10:03:18 +00:00
if ( DEBUGLVL ( 10 ) ) {
2006-09-09 10:05:58 +00:00
DEBUG ( 10 , ( " Sending WINS packet of length %u \n " ,
( unsigned ) blob . length ) ) ;
2005-02-16 10:03:18 +00:00
NDR_PRINT_DEBUG ( wrepl_packet , & wrap . packet ) ;
}
2005-09-27 16:53:08 +00:00
if ( wrepl_socket - > request_timeout > 0 ) {
2005-12-12 21:31:42 +00:00
req - > te = event_add_timed ( wrepl_socket - > event . ctx , req ,
2005-09-27 16:53:08 +00:00
timeval_current_ofs ( wrepl_socket - > request_timeout , 0 ) ,
wrepl_request_timeout_handler , req ) ;
2005-12-12 21:31:42 +00:00
if ( ! req - > te ) return wrepl_request_finished ( req , NT_STATUS_NO_MEMORY ) ;
2005-09-27 16:53:08 +00:00
}
2005-12-12 21:31:42 +00:00
if ( ctrl & & ( ctrl - > send_only | | ctrl - > disconnect_after_send ) ) {
struct wrepl_send_ctrl_state * s = talloc ( blob . data , struct wrepl_send_ctrl_state ) ;
if ( ! s ) return wrepl_request_finished ( req , NT_STATUS_NO_MEMORY ) ;
s - > ctrl = * ctrl ;
s - > req = req ;
s - > wrepl_sock = wrepl_socket ;
talloc_set_destructor ( s , wrepl_send_ctrl_destructor ) ;
}
2005-02-16 10:03:18 +00:00
2007-11-02 09:15:12 +01:00
status = packet_send ( wrepl_socket - > packet , blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return wrepl_request_finished ( req , status ) ;
2005-12-12 21:31:42 +00:00
}
2007-10-06 22:28:14 +00:00
req - > trigger = false ;
2005-12-12 21:31:42 +00:00
return req ;
2005-02-16 10:03:18 +00:00
}
/*
receive a generic WINS replication reply
*/
NTSTATUS wrepl_request_recv ( struct wrepl_request * req ,
TALLOC_CTX * mem_ctx ,
struct wrepl_packet * * packet )
{
NTSTATUS status = wrepl_request_wait ( req ) ;
2005-12-14 19:04:45 +00:00
if ( NT_STATUS_IS_OK ( status ) & & packet ) {
2005-02-16 10:03:18 +00:00
* packet = talloc_steal ( mem_ctx , req - > packet ) ;
}
talloc_free ( req ) ;
return status ;
}
/*
a full WINS replication request / response
*/
NTSTATUS wrepl_request ( struct wrepl_socket * wrepl_socket ,
TALLOC_CTX * mem_ctx ,
struct wrepl_packet * req_packet ,
struct wrepl_packet * * reply_packet )
{
2005-12-12 21:31:42 +00:00
struct wrepl_request * req = wrepl_request_send ( wrepl_socket , req_packet , NULL ) ;
2005-02-16 10:03:18 +00:00
return wrepl_request_recv ( req , mem_ctx , reply_packet ) ;
}
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
struct wrepl_associate_state {
struct wrepl_packet packet ;
uint32_t assoc_ctx ;
uint16_t major_version ;
} ;
static void wrepl_associate_done ( struct wrepl_request * subreq ) ;
struct tevent_req * wrepl_associate_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const struct wrepl_associate * io )
2005-02-18 23:13:51 +00:00
{
2010-03-03 18:38:16 +01:00
struct tevent_req * req ;
struct wrepl_associate_state * state ;
struct wrepl_request * subreq ;
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
if ( wrepl_socket - > event . ctx ! = ev ) {
/* TODO: remove wrepl_socket->event.ctx !!! */
smb_panic ( " wrepl_associate_send event context mismatch! " ) ;
return NULL ;
}
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_associate_state ) ;
if ( req = = NULL ) {
return NULL ;
} ;
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
state - > packet . opcode = WREPL_OPCODE_BITS ;
state - > packet . mess_type = WREPL_START_ASSOCIATION ;
state - > packet . message . start . minor_version = 2 ;
state - > packet . message . start . major_version = 5 ;
2005-02-18 23:13:51 +00:00
2006-02-04 13:54:30 +00:00
/*
* nt4 uses 41 bytes for the start_association call
* so do it the same and as we don ' t know th emeanings of this bytes
* we just send zeros and nt4 , w2k and w2k3 seems to be happy with this
*
* if we don ' t do this nt4 uses an old version of the wins replication protocol
* and that would break nt4 < - > samba replication
*/
2010-03-03 18:38:16 +01:00
state - > packet . padding = data_blob_talloc ( state , NULL , 21 ) ;
if ( tevent_req_nomem ( state - > packet . padding . data , req ) ) {
return tevent_req_post ( req , ev ) ;
2006-02-04 13:54:30 +00:00
}
2010-03-03 18:38:16 +01:00
memset ( state - > packet . padding . data , 0 , state - > packet . padding . length ) ;
2006-02-04 13:54:30 +00:00
2010-03-03 18:38:16 +01:00
subreq = wrepl_request_send ( wrepl_socket , & state - > packet , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq - > async . fn = wrepl_associate_done ;
subreq - > async . private_data = req ;
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
return req ;
}
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
static void wrepl_associate_done ( struct wrepl_request * subreq )
{
struct tevent_req * req = talloc_get_type_abort ( subreq - > async . private_data ,
struct tevent_req ) ;
struct wrepl_associate_state * state = tevent_req_data ( req ,
struct wrepl_associate_state ) ;
NTSTATUS status ;
struct wrepl_packet * packet ;
status = wrepl_request_recv ( subreq , state , & packet ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
if ( packet - > mess_type ! = WREPL_START_ASSOCIATION_REPLY ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
state - > assoc_ctx = packet - > message . start_reply . assoc_ctx ;
state - > major_version = packet - > message . start_reply . major_version ;
tevent_req_done ( req ) ;
2005-02-18 23:13:51 +00:00
}
/*
setup an association - recv
*/
2010-03-03 18:38:16 +01:00
NTSTATUS wrepl_associate_recv ( struct tevent_req * req ,
2005-02-18 23:13:51 +00:00
struct wrepl_associate * io )
{
2010-03-03 18:38:16 +01:00
struct wrepl_associate_state * state = tevent_req_data ( req ,
struct wrepl_associate_state ) ;
2005-02-18 23:13:51 +00:00
NTSTATUS status ;
2010-03-03 18:38:16 +01:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 18:38:16 +01:00
io - > out . assoc_ctx = state - > assoc_ctx ;
io - > out . major_version = state - > major_version ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2005-02-18 23:13:51 +00:00
}
/*
setup an association - sync api
*/
NTSTATUS wrepl_associate ( struct wrepl_socket * wrepl_socket ,
struct wrepl_associate * io )
{
2010-03-03 18:38:16 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_associate_send ( wrepl_socket , wrepl_socket - > event . ctx ,
wrepl_socket , io ) ;
NT_STATUS_HAVE_NO_MEMORY ( subreq ) ;
2005-02-18 23:13:51 +00:00
2010-03-03 18:38:16 +01:00
ok = tevent_req_poll ( subreq , wrepl_socket - > event . ctx ) ;
if ( ! ok ) {
TALLOC_FREE ( subreq ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = wrepl_associate_recv ( subreq , io ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
}
2005-02-18 23:13:51 +00:00
2010-03-03 18:35:55 +01:00
struct wrepl_associate_stop_state {
struct wrepl_packet packet ;
2005-12-12 21:31:42 +00:00
struct wrepl_send_ctrl ctrl ;
2010-03-03 18:35:55 +01:00
} ;
static void wrepl_associate_stop_done ( struct wrepl_request * subreq ) ;
struct tevent_req * wrepl_associate_stop_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const struct wrepl_associate_stop * io )
{
struct tevent_req * req ;
struct wrepl_associate_stop_state * state ;
struct wrepl_request * subreq ;
if ( wrepl_socket - > event . ctx ! = ev ) {
/* TODO: remove wrepl_socket->event.ctx !!! */
smb_panic ( " wrepl_associate_stop_send event context mismatch! " ) ;
return NULL ;
}
2005-10-06 14:38:07 +00:00
2010-03-03 18:35:55 +01:00
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_associate_stop_state ) ;
if ( req = = NULL ) {
return NULL ;
} ;
2005-10-06 14:38:07 +00:00
2010-03-03 18:35:55 +01:00
state - > packet . opcode = WREPL_OPCODE_BITS ;
state - > packet . assoc_ctx = io - > in . assoc_ctx ;
state - > packet . mess_type = WREPL_STOP_ASSOCIATION ;
state - > packet . message . stop . reason = io - > in . reason ;
2005-10-06 14:38:07 +00:00
2005-12-12 21:31:42 +00:00
if ( io - > in . reason = = 0 ) {
2010-03-03 18:35:55 +01:00
state - > ctrl . send_only = true ;
state - > ctrl . disconnect_after_send = true ;
}
subreq = wrepl_request_send ( wrepl_socket , & state - > packet , & state - > ctrl ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2005-10-06 14:38:07 +00:00
}
2010-03-03 18:35:55 +01:00
subreq - > async . fn = wrepl_associate_stop_done ;
subreq - > async . private_data = req ;
return req ;
}
2005-10-06 14:38:07 +00:00
2010-03-03 18:35:55 +01:00
static void wrepl_associate_stop_done ( struct wrepl_request * subreq )
{
struct tevent_req * req = talloc_get_type_abort ( subreq - > async . private_data ,
struct tevent_req ) ;
struct wrepl_associate_stop_state * state = tevent_req_data ( req ,
struct wrepl_associate_stop_state ) ;
NTSTATUS status ;
2005-12-12 21:31:42 +00:00
2010-03-03 18:35:55 +01:00
/* currently we don't care about a possible response */
status = wrepl_request_recv ( subreq , state , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
2005-10-06 14:38:07 +00:00
2010-03-03 18:35:55 +01:00
tevent_req_done ( req ) ;
2005-10-06 14:38:07 +00:00
}
/*
stop an association - recv
*/
2010-03-03 18:35:55 +01:00
NTSTATUS wrepl_associate_stop_recv ( struct tevent_req * req ,
2005-10-06 14:38:07 +00:00
struct wrepl_associate_stop * io )
{
NTSTATUS status ;
2010-03-03 18:35:55 +01:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2005-10-06 14:38:07 +00:00
}
/*
setup an association - sync api
*/
NTSTATUS wrepl_associate_stop ( struct wrepl_socket * wrepl_socket ,
struct wrepl_associate_stop * io )
{
2010-03-03 18:35:55 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_associate_stop_send ( wrepl_socket , wrepl_socket - > event . ctx ,
wrepl_socket , io ) ;
NT_STATUS_HAVE_NO_MEMORY ( subreq ) ;
ok = tevent_req_poll ( subreq , wrepl_socket - > event . ctx ) ;
if ( ! ok ) {
TALLOC_FREE ( subreq ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = wrepl_associate_stop_recv ( subreq , io ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
2005-10-06 14:38:07 +00:00
}
2010-03-03 15:14:28 +01:00
struct wrepl_pull_table_state {
struct wrepl_packet packet ;
uint32_t num_partners ;
struct wrepl_wins_owner * partners ;
} ;
static void wrepl_pull_table_done ( struct wrepl_request * subreq ) ;
struct tevent_req * wrepl_pull_table_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const struct wrepl_pull_table * io )
2005-02-18 23:13:51 +00:00
{
2010-03-03 15:14:28 +01:00
struct tevent_req * req ;
struct wrepl_pull_table_state * state ;
struct wrepl_request * subreq ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
if ( wrepl_socket - > event . ctx ! = ev ) {
/* TODO: remove wrepl_socket->event.ctx !!! */
smb_panic ( " wrepl_pull_table_send event context mismatch! " ) ;
return NULL ;
}
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_pull_table_state ) ;
if ( req = = NULL ) {
return NULL ;
} ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
state - > packet . opcode = WREPL_OPCODE_BITS ;
state - > packet . assoc_ctx = io - > in . assoc_ctx ;
state - > packet . mess_type = WREPL_REPLICATION ;
state - > packet . message . replication . command = WREPL_REPL_TABLE_QUERY ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
subreq = wrepl_request_send ( wrepl_socket , & state - > packet , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq - > async . fn = wrepl_pull_table_done ;
subreq - > async . private_data = req ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
return req ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 15:14:28 +01:00
static void wrepl_pull_table_done ( struct wrepl_request * subreq )
{
struct tevent_req * req = talloc_get_type_abort ( subreq - > async . private_data ,
struct tevent_req ) ;
struct wrepl_pull_table_state * state = tevent_req_data ( req ,
struct wrepl_pull_table_state ) ;
NTSTATUS status ;
struct wrepl_packet * packet ;
struct wrepl_table * table ;
status = wrepl_request_recv ( subreq , state , & packet ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
if ( packet - > mess_type ! = WREPL_REPLICATION ) {
tevent_req_nterror ( req , NT_STATUS_NETWORK_ACCESS_DENIED ) ;
return ;
}
if ( packet - > message . replication . command ! = WREPL_REPL_TABLE_REPLY ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
table = & packet - > message . replication . info . table ;
state - > num_partners = table - > partner_count ;
state - > partners = talloc_move ( state , & table - > partners ) ;
tevent_req_done ( req ) ;
}
2005-02-18 23:13:51 +00:00
/*
fetch the partner tables - recv
*/
2010-03-03 15:14:28 +01:00
NTSTATUS wrepl_pull_table_recv ( struct tevent_req * req ,
2005-02-18 23:13:51 +00:00
TALLOC_CTX * mem_ctx ,
struct wrepl_pull_table * io )
{
2010-03-03 15:14:28 +01:00
struct wrepl_pull_table_state * state = tevent_req_data ( req ,
struct wrepl_pull_table_state ) ;
2005-02-18 23:13:51 +00:00
NTSTATUS status ;
2010-03-03 15:14:28 +01:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 15:14:28 +01:00
io - > out . num_partners = state - > num_partners ;
io - > out . partners = talloc_move ( mem_ctx , & state - > partners ) ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:14:28 +01:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2005-02-18 23:13:51 +00:00
}
/*
fetch the partner table - sync api
*/
NTSTATUS wrepl_pull_table ( struct wrepl_socket * wrepl_socket ,
TALLOC_CTX * mem_ctx ,
struct wrepl_pull_table * io )
{
2010-03-03 15:14:28 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_pull_table_send ( mem_ctx , wrepl_socket - > event . ctx ,
wrepl_socket , io ) ;
NT_STATUS_HAVE_NO_MEMORY ( subreq ) ;
ok = tevent_req_poll ( subreq , wrepl_socket - > event . ctx ) ;
if ( ! ok ) {
TALLOC_FREE ( subreq ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = wrepl_pull_table_recv ( subreq , mem_ctx , io ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 15:12:05 +01:00
struct wrepl_pull_names_state {
struct {
const struct wrepl_pull_names * io ;
} caller ;
struct wrepl_packet packet ;
uint32_t num_names ;
struct wrepl_name * names ;
} ;
static void wrepl_pull_names_done ( struct wrepl_request * subreq ) ;
struct tevent_req * wrepl_pull_names_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const struct wrepl_pull_names * io )
2005-02-18 23:13:51 +00:00
{
2010-03-03 15:12:05 +01:00
struct tevent_req * req ;
struct wrepl_pull_names_state * state ;
struct wrepl_request * subreq ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
if ( wrepl_socket - > event . ctx ! = ev ) {
/* TODO: remove wrepl_socket->event.ctx !!! */
smb_panic ( " wrepl_pull_names_send event context mismatch! " ) ;
return NULL ;
}
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_pull_names_state ) ;
if ( req = = NULL ) {
return NULL ;
} ;
state - > caller . io = io ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
state - > packet . opcode = WREPL_OPCODE_BITS ;
state - > packet . assoc_ctx = io - > in . assoc_ctx ;
state - > packet . mess_type = WREPL_REPLICATION ;
state - > packet . message . replication . command = WREPL_REPL_SEND_REQUEST ;
state - > packet . message . replication . info . owner = io - > in . partner ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
subreq = wrepl_request_send ( wrepl_socket , & state - > packet , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq - > async . fn = wrepl_pull_names_done ;
subreq - > async . private_data = req ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
return req ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 15:12:05 +01:00
static void wrepl_pull_names_done ( struct wrepl_request * subreq )
2005-02-18 23:13:51 +00:00
{
2010-03-03 15:12:05 +01:00
struct tevent_req * req = talloc_get_type_abort ( subreq - > async . private_data ,
struct tevent_req ) ;
struct wrepl_pull_names_state * state = tevent_req_data ( req ,
struct wrepl_pull_names_state ) ;
2005-02-18 23:13:51 +00:00
NTSTATUS status ;
2010-03-03 15:12:05 +01:00
struct wrepl_packet * packet ;
uint32_t i ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
status = wrepl_request_recv ( subreq , state , & packet ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
if ( packet - > mess_type ! = WREPL_REPLICATION ) {
tevent_req_nterror ( req , NT_STATUS_NETWORK_ACCESS_DENIED ) ;
return ;
}
if ( packet - > message . replication . command ! = WREPL_REPL_SEND_REPLY ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
2005-02-18 23:13:51 +00:00
}
2010-03-03 15:12:05 +01:00
state - > num_names = packet - > message . replication . info . reply . num_names ;
2005-02-18 23:13:51 +00:00
2010-03-03 15:12:05 +01:00
state - > names = talloc_array ( state , struct wrepl_name , state - > num_names ) ;
if ( tevent_req_nomem ( state - > names , req ) ) {
return ;
}
2005-02-18 23:13:51 +00:00
/* convert the list of names and addresses to a sane format */
2010-03-03 15:12:05 +01:00
for ( i = 0 ; i < state - > num_names ; i + + ) {
2005-02-18 23:13:51 +00:00
struct wrepl_wins_name * wname = & packet - > message . replication . info . reply . names [ i ] ;
2010-03-03 15:12:05 +01:00
struct wrepl_name * name = & state - > names [ i ] ;
2005-02-18 23:13:51 +00:00
2005-10-06 07:26:05 +00:00
name - > name = * wname - > name ;
2010-03-03 15:12:05 +01:00
talloc_steal ( state - > names , wname - > name ) ;
2005-09-29 14:00:07 +00:00
name - > type = WREPL_NAME_TYPE ( wname - > flags ) ;
name - > state = WREPL_NAME_STATE ( wname - > flags ) ;
2005-09-29 22:06:24 +00:00
name - > node = WREPL_NAME_NODE ( wname - > flags ) ;
2005-09-29 14:00:07 +00:00
name - > is_static = WREPL_NAME_IS_STATIC ( wname - > flags ) ;
name - > raw_flags = wname - > flags ;
2005-09-28 09:58:58 +00:00
name - > version_id = wname - > id ;
2010-03-03 15:12:05 +01:00
name - > owner = talloc_strdup ( state - > names ,
state - > caller . io - > in . partner . address ) ;
if ( tevent_req_nomem ( name - > owner , req ) ) {
return ;
}
2005-09-28 09:58:58 +00:00
2005-02-18 23:13:51 +00:00
/* trying to save 1 or 2 bytes on the wire isn't a good idea */
if ( wname - > flags & 2 ) {
2010-03-03 15:12:05 +01:00
uint32_t j ;
2005-02-18 23:13:51 +00:00
name - > num_addresses = wname - > addresses . addresses . num_ips ;
2010-03-03 15:12:05 +01:00
name - > addresses = talloc_array ( state - > names ,
struct wrepl_address ,
2005-02-18 23:13:51 +00:00
name - > num_addresses ) ;
2010-03-03 15:12:05 +01:00
if ( tevent_req_nomem ( name - > addresses , req ) ) {
return ;
}
2005-02-18 23:13:51 +00:00
for ( j = 0 ; j < name - > num_addresses ; j + + ) {
2010-03-03 15:12:05 +01:00
name - > addresses [ j ] . owner =
talloc_move ( name - > addresses ,
& wname - > addresses . addresses . ips [ j ] . owner ) ;
2005-02-18 23:13:51 +00:00
name - > addresses [ j ] . address =
2010-03-03 15:12:05 +01:00
talloc_move ( name - > addresses ,
& wname - > addresses . addresses . ips [ j ] . ip ) ;
2005-02-18 23:13:51 +00:00
}
} else {
name - > num_addresses = 1 ;
2010-03-03 15:12:05 +01:00
name - > addresses = talloc_array ( state - > names ,
struct wrepl_address ,
name - > num_addresses ) ;
if ( tevent_req_nomem ( name - > addresses , req ) ) {
return ;
}
name - > addresses [ 0 ] . owner = talloc_strdup ( name - > addresses , name - > owner ) ;
if ( tevent_req_nomem ( name - > addresses [ 0 ] . owner , req ) ) {
return ;
}
name - > addresses [ 0 ] . address = talloc_move ( name - > addresses ,
& wname - > addresses . ip ) ;
2005-02-18 23:13:51 +00:00
}
}
2010-03-03 15:12:05 +01:00
tevent_req_done ( req ) ;
}
/*
fetch the names for a WINS partner - recv
*/
NTSTATUS wrepl_pull_names_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
struct wrepl_pull_names * io )
{
struct wrepl_pull_names_state * state = tevent_req_data ( req ,
struct wrepl_pull_names_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
io - > out . num_names = state - > num_names ;
io - > out . names = talloc_move ( mem_ctx , & state - > names ) ;
tevent_req_received ( req ) ;
2005-09-28 09:58:58 +00:00
return NT_STATUS_OK ;
2005-02-18 23:13:51 +00:00
}
/*
fetch the names for a WINS partner - sync api
*/
NTSTATUS wrepl_pull_names ( struct wrepl_socket * wrepl_socket ,
TALLOC_CTX * mem_ctx ,
struct wrepl_pull_names * io )
{
2010-03-03 15:12:05 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_pull_names_send ( mem_ctx , wrepl_socket - > event . ctx ,
wrepl_socket , io ) ;
NT_STATUS_HAVE_NO_MEMORY ( subreq ) ;
ok = tevent_req_poll ( subreq , wrepl_socket - > event . ctx ) ;
if ( ! ok ) {
TALLOC_FREE ( subreq ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
status = wrepl_pull_names_recv ( subreq , mem_ctx , io ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
2005-02-18 23:13:51 +00:00
}