2005-02-16 10:03:18 +00:00
/*
Unix SMB / CIFS implementation .
low level WINS replication client code
Copyright ( C ) Andrew Tridgell 2005
2010-03-05 14:17:08 +01:00
Copyright ( C ) Stefan Metzmacher 2005 - 2010
2005-02-16 10:03:18 +00:00
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-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"
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"
2010-03-05 18:30:10 +01:00
# include "lib/tsocket/tsocket.h"
# include "libcli/util/tstream.h"
2010-03-05 15:49:27 +01:00
/*
2010-03-05 18:30:10 +01:00
main context structure for the wins replication client library
2010-03-05 15:49:27 +01:00
*/
2010-03-05 18:30:10 +01:00
struct wrepl_socket {
2010-03-05 15:49:27 +01:00
struct {
2010-03-05 18:30:10 +01:00
struct tevent_context * ctx ;
} event ;
2010-03-05 15:49:27 +01:00
2010-03-05 18:30:10 +01:00
/* the default timeout for requests, 0 means no timeout */
# define WREPL_SOCKET_REQUEST_TIMEOUT (60)
uint32_t request_timeout ;
2005-02-16 10:03:18 +00:00
2010-03-05 18:30:10 +01:00
struct smb_iconv_convenience * iconv_convenience ;
2005-09-27 10:31:57 +00:00
2010-03-05 18:30:10 +01:00
struct tevent_queue * request_queue ;
2005-12-14 18:22:38 +00:00
2010-03-05 18:30:10 +01:00
struct tstream_context * stream ;
} ;
2005-02-16 10:03:18 +00:00
2010-03-05 16:03:23 +01:00
bool wrepl_socket_is_connected ( struct wrepl_socket * wrepl_sock )
{
if ( ! wrepl_sock ) {
return false ;
}
2010-03-05 18:30:10 +01:00
if ( ! wrepl_sock - > stream ) {
2010-03-05 16:03:23 +01:00
return false ;
}
return true ;
}
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
*/
2010-03-05 18:30:10 +01:00
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 ;
2005-12-12 21:31:42 +00:00
wrepl_socket = talloc_zero ( mem_ctx , struct wrepl_socket ) ;
2010-03-05 18:30:10 +01:00
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 ;
2010-03-05 18:30:10 +01:00
if ( ! wrepl_socket - > event . ctx ) {
goto failed ;
}
2008-02-21 17:17:37 +01:00
2010-03-05 18:30:10 +01:00
wrepl_socket - > request_queue = tevent_queue_create ( wrepl_socket ,
" wrepl request queue " ) ;
if ( wrepl_socket - > request_queue = = NULL ) {
goto failed ;
}
2005-02-16 10:03:18 +00:00
2010-03-05 18:30:10 +01:00
wrepl_socket - > iconv_convenience = iconv_convenience ;
2005-02-16 10:03:18 +00:00
2005-09-27 16:53:08 +00:00
wrepl_socket - > request_timeout = WREPL_SOCKET_REQUEST_TIMEOUT ;
2005-09-30 01:55:29 +00:00
return wrepl_socket ;
failed :
talloc_free ( wrepl_socket ) ;
return NULL ;
}
/*
initialise a wrepl_socket from an already existing connection
*/
2010-03-05 18:30:10 +01:00
NTSTATUS wrepl_socket_donate_stream ( struct wrepl_socket * wrepl_socket ,
struct tstream_context * * stream )
2005-09-30 01:55:29 +00:00
{
2010-03-05 18:30:10 +01:00
if ( wrepl_socket - > stream ) {
return NT_STATUS_CONNECTION_ACTIVE ;
2005-09-30 01:55:29 +00:00
}
2010-03-05 18:30:10 +01:00
wrepl_socket - > stream = talloc_move ( wrepl_socket , stream ) ;
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
/*
2010-03-05 18:30:10 +01:00
initialise a wrepl_socket from an already existing connection
2005-02-16 10:03:18 +00:00
*/
2010-03-05 18:30:10 +01:00
NTSTATUS wrepl_socket_split_stream ( struct wrepl_socket * wrepl_socket ,
TALLOC_CTX * mem_ctx ,
struct tstream_context * * stream )
2005-02-16 10:03:18 +00:00
{
2010-03-05 18:30:10 +01:00
size_t num_requests ;
if ( ! wrepl_socket - > stream ) {
return NT_STATUS_CONNECTION_INVALID ;
2005-02-16 10:03:18 +00:00
}
2010-03-05 18:30:10 +01:00
num_requests = tevent_queue_length ( wrepl_socket - > request_queue ) ;
if ( num_requests > 0 ) {
return NT_STATUS_CONNECTION_IN_USE ;
2005-02-16 10:03:18 +00:00
}
2010-03-05 18:30:10 +01:00
* stream = talloc_move ( wrepl_socket , & wrepl_socket - > stream ) ;
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
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 {
2010-03-05 18:30:10 +01:00
struct {
struct wrepl_socket * wrepl_socket ;
struct tevent_context * ev ;
} caller ;
struct tsocket_address * local_address ;
struct tsocket_address * remote_address ;
struct tstream_context * stream ;
2005-12-12 21:31:42 +00:00
} ;
2005-02-16 10:03:18 +00:00
2010-03-05 18:30:10 +01:00
static void wrepl_connect_trigger ( struct tevent_req * req ,
void * private_date ) ;
2010-03-03 17:18:23 +01:00
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 ;
2010-03-05 18:30:10 +01:00
int ret ;
bool ok ;
2010-03-03 17:18:23 +01:00
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_connect_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2010-03-05 18:30:10 +01:00
state - > caller . wrepl_socket = wrepl_socket ;
state - > caller . ev = ev ;
2010-03-03 17:18:23 +01:00
2010-03-05 18:30:10 +01:00
if ( wrepl_socket - > stream ) {
tevent_req_nterror ( req , NT_STATUS_CONNECTION_ACTIVE ) ;
2010-03-03 17:18:23 +01:00
return tevent_req_post ( req , ev ) ;
}
2010-03-05 18:30:10 +01:00
ret = tsocket_address_inet_from_strings ( state , " ipv4 " ,
our_ip , 0 ,
& state - > local_address ) ;
if ( ret ! = 0 ) {
NTSTATUS status = map_nt_error_from_unix ( errno ) ;
tevent_req_nterror ( req , status ) ;
2010-03-03 17:18:23 +01:00
return tevent_req_post ( req , ev ) ;
}
2010-03-05 18:30:10 +01:00
ret = tsocket_address_inet_from_strings ( state , " ipv4 " ,
peer_ip , WINS_REPLICATION_PORT ,
& state - > remote_address ) ;
if ( ret ! = 0 ) {
NTSTATUS status = map_nt_error_from_unix ( errno ) ;
tevent_req_nterror ( req , status ) ;
2010-03-03 17:18:23 +01:00
return tevent_req_post ( req , ev ) ;
}
2010-03-05 18:30:10 +01:00
ok = tevent_queue_add ( wrepl_socket - > request_queue ,
ev ,
req ,
wrepl_connect_trigger ,
NULL ) ;
if ( ! ok ) {
tevent_req_nomem ( NULL , req ) ;
return tevent_req_post ( req , ev ) ;
}
if ( wrepl_socket - > request_timeout > 0 ) {
struct timeval endtime ;
endtime = tevent_timeval_current_ofs ( wrepl_socket - > request_timeout , 0 ) ;
ok = tevent_req_set_endtime ( req , ev , endtime ) ;
if ( ! ok ) {
return tevent_req_post ( req , ev ) ;
}
}
2010-03-03 17:18:23 +01:00
return req ;
}
2010-03-05 18:30:10 +01:00
static void wrepl_connect_done ( struct tevent_req * subreq ) ;
static void wrepl_connect_trigger ( struct tevent_req * req ,
void * private_date )
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 ) ;
2010-03-05 18:30:10 +01:00
struct tevent_req * subreq ;
2005-12-12 21:31:42 +00:00
2010-03-05 18:30:10 +01:00
subreq = tstream_inet_tcp_connect_send ( state ,
state - > caller . ev ,
state - > local_address ,
state - > remote_address ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-03-03 17:18:23 +01:00
return ;
}
2010-03-05 18:30:10 +01:00
tevent_req_set_callback ( subreq , wrepl_connect_done , req ) ;
2005-12-12 21:31:42 +00:00
2010-03-05 18:30:10 +01:00
return ;
}
2005-12-12 21:31:42 +00:00
2010-03-05 18:30:10 +01:00
static void wrepl_connect_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct wrepl_connect_state * state = tevent_req_data ( req ,
struct wrepl_connect_state ) ;
int ret ;
int sys_errno ;
ret = tstream_inet_tcp_connect_recv ( subreq , & sys_errno ,
state , & state - > stream ) ;
if ( ret ! = 0 ) {
NTSTATUS status = map_nt_error_from_unix ( sys_errno ) ;
tevent_req_nterror ( req , status ) ;
2010-03-03 17:18:23 +01:00
return ;
}
2005-12-12 21:31:42 +00:00
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 ) ;
2010-03-05 18:30:10 +01:00
struct wrepl_socket * wrepl_socket = state - > caller . 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 ) ) {
tevent_req_received ( req ) ;
return status ;
2005-12-12 21:31:42 +00:00
}
2010-03-05 18:30:10 +01:00
wrepl_socket - > stream = talloc_move ( wrepl_socket , & state - > stream ) ;
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
}
2010-03-05 18:30:10 +01:00
struct wrepl_request_state {
struct {
struct wrepl_socket * wrepl_socket ;
struct tevent_context * ev ;
} caller ;
2005-12-12 21:31:42 +00:00
struct wrepl_send_ctrl ctrl ;
2010-03-05 18:30:10 +01:00
struct {
struct wrepl_wrap wrap ;
DATA_BLOB blob ;
struct iovec iov ;
} req ;
bool one_way ;
struct {
DATA_BLOB blob ;
struct wrepl_packet * packet ;
} rep ;
2005-12-12 21:31:42 +00:00
} ;
2010-03-05 18:30:10 +01:00
static void wrepl_request_trigger ( struct tevent_req * req ,
void * private_data ) ;
struct tevent_req * wrepl_request_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct wrepl_socket * wrepl_socket ,
const struct wrepl_packet * packet ,
const struct wrepl_send_ctrl * ctrl )
2005-12-12 21:31:42 +00:00
{
2010-03-05 18:30:10 +01:00
struct tevent_req * req ;
struct wrepl_request_state * state ;
NTSTATUS status ;
enum ndr_err_code ndr_err ;
bool ok ;
2005-12-12 21:31:42 +00:00
2010-03-05 18:30:10 +01:00
if ( wrepl_socket - > event . ctx ! = ev ) {
/* TODO: remove wrepl_socket->event.ctx !!! */
smb_panic ( " wrepl_associate_stop_send event context mismatch! " ) ;
return NULL ;
2005-12-12 21:31:42 +00:00
}
2010-03-05 18:30:10 +01:00
req = tevent_req_create ( mem_ctx , & state ,
struct wrepl_request_state ) ;
if ( req = = NULL ) {
return NULL ;
2005-12-12 21:31:42 +00:00
}
2010-03-05 18:30:10 +01:00
state - > caller . wrepl_socket = wrepl_socket ;
state - > caller . ev = ev ;
2005-02-16 10:03:18 +00:00
2010-03-05 18:30:10 +01:00
if ( ctrl ) {
state - > ctrl = * ctrl ;
}
2005-11-03 18:38:41 +00:00
2010-03-05 18:30:10 +01:00
if ( wrepl_socket - > stream = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_CONNECTION ) ;
return tevent_req_post ( req , ev ) ;
2005-09-27 10:31:57 +00:00
}
2010-03-05 18:30:10 +01:00
state - > req . wrap . packet = * packet ;
ndr_err = ndr_push_struct_blob ( & state - > req . blob , state ,
wrepl_socket - > iconv_convenience ,
& state - > req . 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 ) ;
2010-03-05 18:30:10 +01:00
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
2005-02-16 10:03:18 +00:00
}
2010-03-05 18:30:10 +01:00
state - > req . iov . iov_base = state - > req . blob . data ;
state - > req . iov . iov_len = state - > req . blob . length ;
2005-09-27 16:53:08 +00:00
2010-03-05 18:30:10 +01:00
ok = tevent_queue_add ( wrepl_socket - > request_queue ,
ev ,
req ,
wrepl_request_trigger ,
NULL ) ;
if ( ! ok ) {
tevent_req_nomem ( NULL , req ) ;
return tevent_req_post ( req , ev ) ;
2005-12-12 21:31:42 +00:00
}
2005-02-16 10:03:18 +00:00
2010-03-05 18:30:10 +01:00
if ( wrepl_socket - > request_timeout > 0 ) {
struct timeval endtime ;
endtime = tevent_timeval_current_ofs ( wrepl_socket - > request_timeout , 0 ) ;
ok = tevent_req_set_endtime ( req , ev , endtime ) ;
if ( ! ok ) {
return tevent_req_post ( req , ev ) ;
}
2005-12-12 21:31:42 +00:00
}
return req ;
2005-02-16 10:03:18 +00:00
}
2010-03-05 18:30:10 +01:00
static void wrepl_request_writev_done ( struct tevent_req * subreq ) ;
static void wrepl_request_trigger ( struct tevent_req * req ,
void * private_data )
2005-02-16 10:03:18 +00:00
{
2010-03-05 18:30:10 +01:00
struct wrepl_request_state * state = tevent_req_data ( req ,
struct wrepl_request_state ) ;
struct tevent_req * subreq ;
2010-03-25 17:58:19 +01:00
if ( state - > caller . wrepl_socket - > stream = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_CONNECTION ) ;
return ;
}
2010-03-05 18:30:10 +01:00
if ( DEBUGLVL ( 10 ) ) {
DEBUG ( 10 , ( " Sending WINS packet of length %u \n " ,
( unsigned ) state - > req . blob . length ) ) ;
NDR_PRINT_DEBUG ( wrepl_packet , & state - > req . wrap . packet ) ;
2005-02-16 10:03:18 +00:00
}
2010-03-05 18:30:10 +01:00
subreq = tstream_writev_send ( state ,
state - > caller . ev ,
state - > caller . wrepl_socket - > stream ,
& state - > req . iov , 1 ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , wrepl_request_writev_done , req ) ;
}
2010-03-05 15:22:10 +01:00
2010-03-05 18:30:10 +01:00
static void wrepl_request_disconnect_done ( struct tevent_req * subreq ) ;
static void wrepl_request_read_pdu_done ( struct tevent_req * subreq ) ;
2010-03-05 15:22:10 +01:00
2010-03-05 18:30:10 +01:00
static void wrepl_request_writev_done ( struct tevent_req * subreq )
2010-03-05 14:44:23 +01:00
{
2010-03-05 18:30:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct wrepl_request_state * state = tevent_req_data ( req ,
struct wrepl_request_state ) ;
int ret ;
int sys_errno ;
2010-03-05 15:22:10 +01:00
2010-03-05 18:30:10 +01:00
ret = tstream_writev_recv ( subreq , & sys_errno ) ;
TALLOC_FREE ( subreq ) ;
if ( ret = = - 1 ) {
NTSTATUS status = map_nt_error_from_unix ( sys_errno ) ;
2010-03-25 17:58:19 +01:00
TALLOC_FREE ( state - > caller . wrepl_socket - > stream ) ;
2010-03-05 18:30:10 +01:00
tevent_req_nterror ( req , status ) ;
return ;
2010-03-05 15:22:10 +01:00
}
2010-03-25 17:58:19 +01:00
if ( state - > caller . wrepl_socket - > stream = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_CONNECTION ) ;
return ;
}
2010-03-05 18:30:10 +01:00
if ( state - > ctrl . disconnect_after_send ) {
subreq = tstream_disconnect_send ( state ,
state - > caller . ev ,
state - > caller . wrepl_socket - > stream ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , wrepl_request_disconnect_done , req ) ;
return ;
}
if ( state - > ctrl . send_only ) {
tevent_req_done ( req ) ;
return ;
2010-03-05 15:22:10 +01:00
}
2010-03-05 18:30:10 +01:00
subreq = tstream_read_pdu_blob_send ( state ,
state - > caller . ev ,
state - > caller . wrepl_socket - > stream ,
4 , /* initial_read_size */
packet_full_request_u32 ,
NULL ) ;
2010-03-05 15:22:10 +01:00
if ( tevent_req_nomem ( subreq , req ) ) {
2010-03-05 18:30:10 +01:00
return ;
2010-03-05 15:22:10 +01:00
}
2010-03-05 18:30:10 +01:00
tevent_req_set_callback ( subreq , wrepl_request_read_pdu_done , req ) ;
}
2010-03-05 15:22:10 +01:00
2010-03-05 18:30:10 +01:00
static void wrepl_request_disconnect_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct wrepl_request_state * state = tevent_req_data ( req ,
struct wrepl_request_state ) ;
int ret ;
int sys_errno ;
ret = tstream_disconnect_recv ( subreq , & sys_errno ) ;
TALLOC_FREE ( subreq ) ;
if ( ret = = - 1 ) {
NTSTATUS status = map_nt_error_from_unix ( sys_errno ) ;
2010-03-25 17:58:19 +01:00
TALLOC_FREE ( state - > caller . wrepl_socket - > stream ) ;
2010-03-05 18:30:10 +01:00
tevent_req_nterror ( req , status ) ;
return ;
}
DEBUG ( 10 , ( " WINS connection disconnected \n " ) ) ;
2010-03-25 17:58:19 +01:00
TALLOC_FREE ( state - > caller . wrepl_socket - > stream ) ;
2010-03-05 18:30:10 +01:00
tevent_req_done ( req ) ;
2010-03-05 14:44:23 +01:00
}
2010-03-05 18:30:10 +01:00
static void wrepl_request_read_pdu_done ( struct tevent_req * subreq )
2010-03-05 15:22:10 +01:00
{
2010-03-05 18:30:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2010-03-05 15:22:10 +01:00
struct tevent_req ) ;
struct wrepl_request_state * state = tevent_req_data ( req ,
struct wrepl_request_state ) ;
NTSTATUS status ;
2010-03-05 18:30:10 +01:00
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
2010-03-05 15:22:10 +01:00
2010-03-05 18:30:10 +01:00
status = tstream_read_pdu_blob_recv ( subreq , state , & state - > rep . blob ) ;
2010-03-05 15:22:10 +01:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-03-25 17:58:19 +01:00
TALLOC_FREE ( state - > caller . wrepl_socket - > stream ) ;
2010-03-05 15:22:10 +01:00
tevent_req_nterror ( req , status ) ;
return ;
}
2010-03-05 18:30:10 +01:00
state - > rep . packet = talloc ( state , struct wrepl_packet ) ;
if ( tevent_req_nomem ( state - > rep . packet , req ) ) {
return ;
}
blob . data = state - > rep . blob . data + 4 ;
blob . length = state - > rep . blob . length - 4 ;
/* we have a full request - parse it */
ndr_err = ndr_pull_struct_blob ( & blob ,
state - > rep . packet ,
state - > caller . wrepl_socket - > iconv_convenience ,
state - > rep . packet ,
( ndr_pull_flags_fn_t ) ndr_pull_wrepl_packet ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
tevent_req_nterror ( req , status ) ;
return ;
}
if ( DEBUGLVL ( 10 ) ) {
DEBUG ( 10 , ( " Received WINS packet of length %u \n " ,
( unsigned ) state - > rep . blob . length ) ) ;
NDR_PRINT_DEBUG ( wrepl_packet , state - > rep . packet ) ;
}
2010-03-05 15:22:10 +01:00
tevent_req_done ( req ) ;
}
NTSTATUS wrepl_request_recv ( struct tevent_req * req ,
2010-03-05 14:44:23 +01:00
TALLOC_CTX * mem_ctx ,
struct wrepl_packet * * packet )
{
2010-03-05 15:22:10 +01:00
struct wrepl_request_state * state = tevent_req_data ( req ,
struct wrepl_request_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
2010-03-25 17:58:19 +01:00
TALLOC_FREE ( state - > caller . wrepl_socket - > stream ) ;
2010-03-05 15:22:10 +01:00
tevent_req_received ( req ) ;
return status ;
}
if ( packet ) {
2010-03-05 18:30:10 +01:00
* packet = talloc_move ( mem_ctx , & state - > rep . packet ) ;
2010-03-05 15:22:10 +01:00
}
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2010-03-05 14:44:23 +01:00
}
2005-02-16 10:03:18 +00:00
/*
a full WINS replication request / response
*/
NTSTATUS wrepl_request ( struct wrepl_socket * wrepl_socket ,
TALLOC_CTX * mem_ctx ,
2010-03-05 15:22:10 +01:00
const struct wrepl_packet * req_packet ,
2005-02-16 10:03:18 +00:00
struct wrepl_packet * * reply_packet )
{
2010-03-05 15:22:10 +01:00
struct tevent_req * subreq ;
bool ok ;
NTSTATUS status ;
subreq = wrepl_request_send ( mem_ctx , wrepl_socket - > event . ctx ,
wrepl_socket , req_packet , NULL ) ;
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_request_recv ( subreq , mem_ctx , reply_packet ) ;
TALLOC_FREE ( subreq ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return NT_STATUS_OK ;
2005-02-16 10:03:18 +00:00
}
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 ;
} ;
2010-03-05 15:22:10 +01:00
static void wrepl_associate_done ( struct tevent_req * subreq ) ;
2010-03-03 18:38:16 +01:00
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 ;
2010-03-05 15:22:10 +01:00
struct tevent_req * 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-05 15:22:10 +01:00
subreq = wrepl_request_send ( state , ev , wrepl_socket , & state - > packet , NULL ) ;
2010-03-03 18:38:16 +01:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2010-03-05 15:22:10 +01:00
tevent_req_set_callback ( subreq , wrepl_associate_done , 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-05 15:22:10 +01:00
static void wrepl_associate_done ( struct tevent_req * subreq )
2010-03-03 18:38:16 +01:00
{
2010-03-05 15:22:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2010-03-03 18:38:16 +01:00
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 ) ;
2010-03-05 15:22:10 +01:00
TALLOC_FREE ( subreq ) ;
2010-03-03 18:38:16 +01:00
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
} ;
2010-03-05 15:22:10 +01:00
static void wrepl_associate_stop_done ( struct tevent_req * subreq ) ;
2010-03-03 18:35:55 +01:00
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 ;
2010-03-05 15:22:10 +01:00
struct tevent_req * subreq ;
2010-03-03 18:35:55 +01:00
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 ;
}
2010-03-05 15:22:10 +01:00
subreq = wrepl_request_send ( state , ev , wrepl_socket , & state - > packet , & state - > ctrl ) ;
2010-03-03 18:35:55 +01:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2005-10-06 14:38:07 +00:00
}
2010-03-05 15:22:10 +01:00
tevent_req_set_callback ( subreq , wrepl_associate_stop_done , req ) ;
2010-03-03 18:35:55 +01:00
return req ;
}
2005-10-06 14:38:07 +00:00
2010-03-05 15:22:10 +01:00
static void wrepl_associate_stop_done ( struct tevent_req * subreq )
2010-03-03 18:35:55 +01:00
{
2010-03-05 15:22:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2010-03-03 18:35:55 +01:00
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 ) ;
2010-03-05 15:22:10 +01:00
TALLOC_FREE ( subreq ) ;
2010-03-03 18:35:55 +01:00
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 ;
} ;
2010-03-05 15:22:10 +01:00
static void wrepl_pull_table_done ( struct tevent_req * subreq ) ;
2010-03-03 15:14:28 +01:00
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 ;
2010-03-05 15:22:10 +01:00
struct tevent_req * 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-05 15:22:10 +01:00
subreq = wrepl_request_send ( state , ev , wrepl_socket , & state - > packet , NULL ) ;
2010-03-03 15:14:28 +01:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2010-03-05 15:22:10 +01:00
tevent_req_set_callback ( subreq , wrepl_pull_table_done , 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-05 15:22:10 +01:00
static void wrepl_pull_table_done ( struct tevent_req * subreq )
2010-03-03 15:14:28 +01:00
{
2010-03-05 15:22:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2010-03-03 15:14:28 +01:00
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 ) ;
2010-03-05 15:22:10 +01:00
TALLOC_FREE ( subreq ) ;
2010-03-03 15:14:28 +01:00
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 ;
} ;
2010-03-05 15:22:10 +01:00
static void wrepl_pull_names_done ( struct tevent_req * subreq ) ;
2010-03-03 15:12:05 +01:00
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 ;
2010-03-05 15:22:10 +01:00
struct tevent_req * 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-05 15:22:10 +01:00
subreq = wrepl_request_send ( state , ev , wrepl_socket , & state - > packet , NULL ) ;
2010-03-03 15:12:05 +01:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2010-03-05 15:22:10 +01:00
tevent_req_set_callback ( subreq , wrepl_pull_names_done , 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-05 15:22:10 +01:00
static void wrepl_pull_names_done ( struct tevent_req * subreq )
2005-02-18 23:13:51 +00:00
{
2010-03-05 15:22:10 +01:00
struct tevent_req * req = tevent_req_callback_data ( subreq ,
2010-03-03 15:12:05 +01:00
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 ) ;
2010-03-05 15:22:10 +01:00
TALLOC_FREE ( subreq ) ;
2010-03-03 15:12:05 +01:00
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
}