2005-10-14 16:38:07 +04:00
/*
Unix SMB / CIFS implementation .
WINS Replication server
Copyright ( C ) Stefan Metzmacher 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 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-10-14 16:38:07 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-10-14 16:38:07 +04:00
*/
# include "includes.h"
# include "lib/events/events.h"
2010-04-27 18:17:28 +04:00
# include "lib/tsocket/tsocket.h"
2020-11-20 17:27:17 +03:00
# include "samba/service_task.h"
# include "samba/service_stream.h"
2005-10-14 18:02:47 +04:00
# include "libcli/wrepl/winsrepl.h"
2005-10-14 16:38:07 +04:00
# include "wrepl_server/wrepl_server.h"
2005-10-14 18:02:47 +04:00
# include "libcli/composite/composite.h"
2005-10-14 16:52:51 +04:00
# include "nbt_server/wins/winsdb.h"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2006-01-21 11:53:56 +03:00
# include "system/time.h"
2010-02-13 05:01:22 +03:00
# include "lib/util/tsort.h"
2010-03-05 20:30:10 +03:00
# include "param/param.h"
2005-10-14 16:38:07 +04:00
static NTSTATUS wreplsrv_in_start_association ( struct wreplsrv_in_call * call )
{
2005-10-14 16:44:47 +04:00
struct wrepl_start * start = & call - > req_packet . message . start ;
struct wrepl_start * start_reply = & call - > rep_packet . message . start_reply ;
if ( call - > req_packet . opcode & WREPL_OPCODE_BITS ) {
/*
* if the assoc_ctx doesn ' t match ignore the packet
*/
if ( ( call - > req_packet . assoc_ctx ! = call - > wreplconn - > assoc_ctx . our_ctx )
& & ( call - > req_packet . assoc_ctx ! = 0 ) ) {
return ERROR_INVALID_PARAMETER ;
}
} else {
call - > wreplconn - > assoc_ctx . our_ctx = WREPLSRV_INVALID_ASSOC_CTX ;
return NT_STATUS_OK ;
}
2005-10-14 16:38:07 +04:00
2006-02-04 16:54:30 +03:00
/*
* it seems that we don ' t know all details about the start_association
* to support replication with NT4 ( it sends 1.1 instead of 5.2 )
* we ignore the version numbers until we know all details
*/
#if 0
2005-10-14 16:44:47 +04:00
if ( start - > minor_version ! = 2 | | start - > major_version ! = 5 ) {
/* w2k terminate the connection if the versions doesn't match */
return NT_STATUS_UNKNOWN_REVISION ;
}
2006-02-04 16:54:30 +03:00
# endif
2005-10-14 16:44:47 +04:00
2007-10-07 01:48:28 +04:00
call - > wreplconn - > assoc_ctx . stopped = false ;
2005-10-14 16:44:47 +04:00
call - > wreplconn - > assoc_ctx . our_ctx = WREPLSRV_VALID_ASSOC_CTX ;
call - > wreplconn - > assoc_ctx . peer_ctx = start - > assoc_ctx ;
call - > rep_packet . mess_type = WREPL_START_ASSOCIATION_REPLY ;
start_reply - > assoc_ctx = call - > wreplconn - > assoc_ctx . our_ctx ;
start_reply - > minor_version = 2 ;
start_reply - > major_version = 5 ;
2005-10-14 16:38:07 +04:00
2006-02-04 16:54:30 +03:00
/*
* nt4 uses 41 bytes for the start_association call
2023-09-06 03:06:26 +03:00
* so do it the same and as we don ' t know the meanings of these bytes
2006-02-04 16:54:30 +03:00
* 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
*/
call - > rep_packet . padding = data_blob_talloc ( call , NULL , 21 ) ;
NT_STATUS_HAVE_NO_MEMORY ( call - > rep_packet . padding . data ) ;
memset ( call - > rep_packet . padding . data , 0 , call - > rep_packet . padding . length ) ;
2005-10-14 16:38:07 +04:00
return NT_STATUS_OK ;
}
2005-10-14 16:44:47 +04:00
static NTSTATUS wreplsrv_in_stop_assoc_ctx ( struct wreplsrv_in_call * call )
{
struct wrepl_stop * stop_out = & call - > rep_packet . message . stop ;
2007-10-07 01:48:28 +04:00
call - > wreplconn - > assoc_ctx . stopped = true ;
2005-10-14 16:44:47 +04:00
call - > rep_packet . mess_type = WREPL_STOP_ASSOCIATION ;
stop_out - > reason = 4 ;
return NT_STATUS_OK ;
}
static NTSTATUS wreplsrv_in_stop_association ( struct wreplsrv_in_call * call )
{
/*
* w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
*/
if ( call - > req_packet . opcode & WREPL_OPCODE_BITS ) {
/*
* if the assoc_ctx doesn ' t match ignore the packet
*/
if ( call - > req_packet . assoc_ctx ! = call - > wreplconn - > assoc_ctx . our_ctx ) {
return ERROR_INVALID_PARAMETER ;
}
/* when the opcode bits are set the connection should be directly terminated */
return NT_STATUS_CONNECTION_RESET ;
}
if ( call - > wreplconn - > assoc_ctx . stopped ) {
/* this causes the connection to be directly terminated */
return NT_STATUS_CONNECTION_RESET ;
}
/* this will cause to not receive packets anymore and terminate the connection if the reply is send */
2007-10-07 01:48:28 +04:00
call - > terminate_after_send = true ;
2005-10-14 16:44:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
2005-10-14 16:52:51 +04:00
static NTSTATUS wreplsrv_in_table_query ( struct wreplsrv_in_call * call )
{
struct wreplsrv_service * service = call - > wreplconn - > service ;
struct wrepl_replication * repl_out = & call - > rep_packet . message . replication ;
struct wrepl_table * table_out = & call - > rep_packet . message . replication . info . table ;
repl_out - > command = WREPL_REPL_TABLE_REPLY ;
2005-10-14 18:02:47 +04:00
return wreplsrv_fill_wrepl_table ( service , call , table_out ,
2007-10-07 01:48:28 +04:00
service - > wins_db - > local_owner , true ) ;
2005-10-14 16:52:51 +04:00
}
2005-10-14 16:54:26 +04:00
static int wreplsrv_in_sort_wins_name ( struct wrepl_wins_name * n1 ,
struct wrepl_wins_name * n2 )
{
if ( n1 - > id < n2 - > id ) return - 1 ;
if ( n1 - > id > n2 - > id ) return 1 ;
return 0 ;
}
2005-10-14 18:02:47 +04:00
static NTSTATUS wreplsrv_record2wins_name ( TALLOC_CTX * mem_ctx ,
struct wrepl_wins_name * name ,
struct winsdb_record * rec )
2005-10-14 16:54:26 +04:00
{
2005-10-14 18:02:47 +04:00
uint32_t num_ips , i ;
struct wrepl_ip * ips ;
2005-10-14 16:55:27 +04:00
2005-10-14 18:02:47 +04:00
name - > name = rec - > name ;
talloc_steal ( mem_ctx , rec - > name ) ;
2005-10-14 16:54:26 +04:00
name - > id = rec - > version ;
2005-12-31 00:12:15 +03:00
name - > unknown = " 255.255.255.255 " ;
2005-10-14 16:54:26 +04:00
2005-10-14 18:02:47 +04:00
name - > flags = WREPL_NAME_FLAGS ( rec - > type , rec - > state , rec - > node , rec - > is_static ) ;
2005-10-14 16:54:26 +04:00
switch ( name - > flags & 2 ) {
case 0 :
name - > addresses . ip = rec - > addresses [ 0 ] - > address ;
talloc_steal ( mem_ctx , rec - > addresses [ 0 ] - > address ) ;
break ;
case 2 :
2005-10-14 18:02:47 +04:00
num_ips = winsdb_addr_list_length ( rec - > addresses ) ;
ips = talloc_array ( mem_ctx , struct wrepl_ip , num_ips ) ;
NT_STATUS_HAVE_NO_MEMORY ( ips ) ;
for ( i = 0 ; i < num_ips ; i + + ) {
2005-12-31 00:12:15 +03:00
ips [ i ] . owner = rec - > addresses [ i ] - > wins_owner ;
talloc_steal ( ips , rec - > addresses [ i ] - > wins_owner ) ;
2005-10-14 18:02:47 +04:00
ips [ i ] . ip = rec - > addresses [ i ] - > address ;
talloc_steal ( ips , rec - > addresses [ i ] - > address ) ;
}
name - > addresses . addresses . num_ips = num_ips ;
name - > addresses . addresses . ips = ips ;
2005-10-14 16:54:26 +04:00
break ;
}
return NT_STATUS_OK ;
}
2005-10-14 16:52:51 +04:00
static NTSTATUS wreplsrv_in_send_request ( struct wreplsrv_in_call * call )
{
2005-10-14 16:54:26 +04:00
struct wreplsrv_service * service = call - > wreplconn - > service ;
struct wrepl_wins_owner * owner_in = & call - > req_packet . message . replication . info . owner ;
2005-10-14 16:52:51 +04:00
struct wrepl_replication * repl_out = & call - > rep_packet . message . replication ;
struct wrepl_send_reply * reply_out = & call - > rep_packet . message . replication . info . reply ;
2005-10-14 16:54:26 +04:00
struct wreplsrv_owner * owner ;
2006-01-02 21:25:30 +03:00
const char * owner_filter ;
2005-10-14 16:54:26 +04:00
const char * filter ;
2005-11-08 03:11:45 +03:00
struct ldb_result * res = NULL ;
2005-10-14 16:54:26 +04:00
int ret ;
struct wrepl_wins_name * names ;
struct winsdb_record * rec ;
NTSTATUS status ;
2009-11-07 23:15:17 +03:00
unsigned int i , j ;
2006-01-21 11:53:56 +03:00
time_t now = time ( NULL ) ;
2005-10-14 16:54:26 +04:00
2006-01-02 20:19:09 +03:00
owner = wreplsrv_find_owner ( service , service - > table , owner_in - > address ) ;
2005-10-14 16:52:51 +04:00
2005-10-14 16:54:26 +04:00
repl_out - > command = WREPL_REPL_SEND_REPLY ;
2005-10-14 16:52:51 +04:00
reply_out - > num_names = 0 ;
reply_out - > names = NULL ;
2005-10-14 16:54:26 +04:00
/*
* if we didn ' t know this owner , must be a bug in the partners client code . . .
* return an empty list .
*/
if ( ! owner ) {
2006-01-02 20:19:09 +03:00
DEBUG ( 2 , ( " WINSREPL:reply [0] records unknown owner[%s] to partner[%s] \n " ,
owner_in - > address , call - > wreplconn - > partner - > address ) ) ;
2005-10-14 16:54:26 +04:00
return NT_STATUS_OK ;
}
2005-11-25 13:08:31 +03:00
/*
* the client sends a max_version of 0 , interpret it as
* ( uint64_t ) - 1
*/
if ( owner_in - > max_version = = 0 ) {
owner_in - > max_version = ( uint64_t ) - 1 ;
}
2005-10-14 16:54:26 +04:00
/*
* if the partner ask for nothing , or give invalid ranges ,
* return an empty list .
*/
2005-10-14 18:02:47 +04:00
if ( owner_in - > min_version > owner_in - > max_version ) {
2006-01-02 20:19:09 +03:00
DEBUG ( 2 , ( " WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s] \n " ,
owner_in - > address ,
( long long ) owner_in - > min_version ,
( long long ) owner_in - > max_version ,
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 16:54:26 +04:00
return NT_STATUS_OK ;
}
/*
* if the partner has already all records for nothing , or give invalid ranges ,
* return an empty list .
*/
2005-10-14 18:02:47 +04:00
if ( owner_in - > min_version > owner - > owner . max_version ) {
2006-01-02 20:19:09 +03:00
DEBUG ( 2 , ( " WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s] \n " ,
owner_in - > address ,
( long long ) owner_in - > min_version ,
( long long ) owner_in - > max_version ,
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 16:54:26 +04:00
return NT_STATUS_OK ;
}
2006-01-02 21:25:30 +03:00
owner_filter = wreplsrv_owner_filter ( service , call , owner - > owner . address ) ;
NT_STATUS_HAVE_NO_MEMORY ( owner_filter ) ;
2005-10-14 18:02:47 +04:00
filter = talloc_asprintf ( call ,
2006-01-02 21:25:30 +03:00
" (&%s(objectClass=winsRecord) "
2005-10-14 18:02:47 +04:00
" (|(recordState=%u)(recordState=%u)) "
" (versionID>=%llu)(versionID<=%llu)) " ,
2006-01-02 21:25:30 +03:00
owner_filter ,
2005-10-14 18:02:47 +04:00
WREPL_STATE_ACTIVE , WREPL_STATE_TOMBSTONE ,
2005-11-30 05:08:15 +03:00
( long long ) owner_in - > min_version ,
( long long ) owner_in - > max_version ) ;
2005-10-14 16:54:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( filter ) ;
2008-09-23 22:30:06 +04:00
ret = ldb_search ( service - > wins_db - > ldb , call , & res , NULL , LDB_SCOPE_SUBTREE , NULL , " %s " , filter ) ;
2005-11-08 03:11:45 +03:00
if ( ret ! = LDB_SUCCESS ) return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2006-01-02 21:25:30 +03:00
DEBUG ( 10 , ( " WINSREPL: filter '%s' count %d \n " , filter , res - > count ) ) ;
2005-11-08 03:11:45 +03:00
if ( res - > count = = 0 ) {
2005-10-14 18:02:47 +04:00
DEBUG ( 2 , ( " WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s] \n " ,
2005-11-30 05:08:15 +03:00
res - > count , owner_in - > address ,
( long long ) owner_in - > min_version ,
( long long ) owner_in - > max_version ,
2005-10-14 18:02:47 +04:00
call - > wreplconn - > partner - > address ) ) ;
return NT_STATUS_OK ;
}
2005-10-14 16:54:26 +04:00
2005-11-08 03:11:45 +03:00
names = talloc_array ( call , struct wrepl_wins_name , res - > count ) ;
2005-10-14 16:54:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( names ) ;
2006-01-21 11:53:56 +03:00
for ( i = 0 , j = 0 ; i < res - > count ; i + + ) {
status = winsdb_record ( service - > wins_db , res - > msgs [ i ] , call , now , & rec ) ;
2005-10-14 16:55:59 +04:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-10-14 16:54:26 +04:00
2006-01-21 11:53:56 +03:00
/*
* it ' s possible that winsdb_record ( ) made the record RELEASED
* because it ' s expired , but in the database it ' s still stored
* as ACTIVE . . .
*
* make sure we really only replicate ACTIVE and TOMBSTONE records
*/
if ( rec - > state = = WREPL_STATE_ACTIVE | | rec - > state = = WREPL_STATE_TOMBSTONE ) {
status = wreplsrv_record2wins_name ( names , & names [ j ] , rec ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
j + + ;
}
2005-10-14 16:54:26 +04:00
talloc_free ( rec ) ;
2005-11-08 03:11:45 +03:00
talloc_free ( res - > msgs [ i ] ) ;
2005-10-14 16:54:26 +04:00
}
/* sort the names before we send them */
2010-02-13 05:01:22 +03:00
TYPESAFE_QSORT ( names , j , wreplsrv_in_sort_wins_name ) ;
2005-10-14 16:54:26 +04:00
2005-10-14 18:02:47 +04:00
DEBUG ( 2 , ( " WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s] \n " ,
2006-01-21 11:53:56 +03:00
j , owner_in - > address ,
2005-11-30 05:08:15 +03:00
( long long ) owner_in - > min_version ,
( long long ) owner_in - > max_version ,
2005-10-14 18:02:47 +04:00
call - > wreplconn - > partner - > address ) ) ;
2006-01-21 11:53:56 +03:00
reply_out - > num_names = j ;
2005-10-14 16:54:26 +04:00
reply_out - > names = names ;
2005-10-14 16:52:51 +04:00
return NT_STATUS_OK ;
}
2005-10-14 18:02:47 +04:00
struct wreplsrv_in_update_state {
struct wreplsrv_in_connection * wrepl_in ;
struct wreplsrv_out_connection * wrepl_out ;
struct composite_context * creq ;
struct wreplsrv_pull_cycle_io cycle_io ;
} ;
static void wreplsrv_in_update_handler ( struct composite_context * creq )
{
struct wreplsrv_in_update_state * update_state = talloc_get_type ( creq - > async . private_data ,
struct wreplsrv_in_update_state ) ;
NTSTATUS status ;
status = wreplsrv_pull_cycle_recv ( creq ) ;
talloc_free ( update_state - > wrepl_out ) ;
wreplsrv_terminate_in_connection ( update_state - > wrepl_in , nt_errstr ( status ) ) ;
}
static NTSTATUS wreplsrv_in_update ( struct wreplsrv_in_call * call )
{
struct wreplsrv_in_connection * wrepl_in = call - > wreplconn ;
struct wreplsrv_out_connection * wrepl_out ;
struct wrepl_table * update_in = & call - > req_packet . message . replication . info . table ;
struct wreplsrv_in_update_state * update_state ;
2010-03-05 20:30:10 +03:00
NTSTATUS status ;
2005-10-14 18:02:47 +04:00
DEBUG ( 2 , ( " WREPL_REPL_UPDATE: partner[%s] initiator[%s] num_owners[%u] \n " ,
call - > wreplconn - > partner - > address ,
update_in - > initiator , update_in - > partner_count ) ) ;
2010-01-20 16:21:47 +03:00
update_state = talloc ( wrepl_in , struct wreplsrv_in_update_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( update_state ) ;
2005-10-14 18:02:47 +04:00
wrepl_out = talloc ( update_state , struct wreplsrv_out_connection ) ;
NT_STATUS_HAVE_NO_MEMORY ( wrepl_out ) ;
wrepl_out - > service = wrepl_in - > service ;
wrepl_out - > partner = wrepl_in - > partner ;
wrepl_out - > assoc_ctx . our_ctx = wrepl_in - > assoc_ctx . our_ctx ;
wrepl_out - > assoc_ctx . peer_ctx = wrepl_in - > assoc_ctx . peer_ctx ;
2010-03-05 20:30:10 +03:00
wrepl_out - > sock = wrepl_socket_init ( wrepl_out ,
2010-05-09 19:20:01 +04:00
wrepl_in - > conn - > event . ctx ) ;
2014-02-13 08:51:11 +04:00
if ( wrepl_out - > sock = = NULL ) {
TALLOC_FREE ( update_state ) ;
return NT_STATUS_NO_MEMORY ;
}
2010-03-05 20:30:10 +03:00
TALLOC_FREE ( wrepl_in - > send_queue ) ;
status = wrepl_socket_donate_stream ( wrepl_out - > sock , & wrepl_in - > tstream ) ;
2014-02-14 09:04:22 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( update_state ) ;
return status ;
}
2005-10-14 18:02:47 +04:00
update_state - > wrepl_in = wrepl_in ;
update_state - > wrepl_out = wrepl_out ;
update_state - > cycle_io . in . partner = wrepl_out - > partner ;
update_state - > cycle_io . in . num_owners = update_in - > partner_count ;
update_state - > cycle_io . in . owners = update_in - > partners ;
talloc_steal ( update_state , update_in - > partners ) ;
update_state - > cycle_io . in . wreplconn = wrepl_out ;
update_state - > creq = wreplsrv_pull_cycle_send ( update_state , & update_state - > cycle_io ) ;
if ( ! update_state - > creq ) {
2010-03-05 20:30:10 +03:00
talloc_free ( update_state ) ;
2005-10-14 18:02:47 +04:00
return NT_STATUS_INTERNAL_ERROR ;
}
update_state - > creq - > async . fn = wreplsrv_in_update_handler ;
update_state - > creq - > async . private_data = update_state ;
return ERROR_INVALID_PARAMETER ;
}
static NTSTATUS wreplsrv_in_update2 ( struct wreplsrv_in_call * call )
{
return wreplsrv_in_update ( call ) ;
}
static NTSTATUS wreplsrv_in_inform ( struct wreplsrv_in_call * call )
{
struct wrepl_table * inform_in = & call - > req_packet . message . replication . info . table ;
DEBUG ( 2 , ( " WREPL_REPL_INFORM: partner[%s] initiator[%s] num_owners[%u] \n " ,
call - > wreplconn - > partner - > address ,
inform_in - > initiator , inform_in - > partner_count ) ) ;
2005-12-20 03:55:28 +03:00
wreplsrv_out_partner_pull ( call - > wreplconn - > partner , inform_in ) ;
2005-10-14 18:02:47 +04:00
/* we don't reply to WREPL_REPL_INFORM messages */
return ERROR_INVALID_PARAMETER ;
}
static NTSTATUS wreplsrv_in_inform2 ( struct wreplsrv_in_call * call )
{
return wreplsrv_in_inform ( call ) ;
}
2005-10-14 16:38:07 +04:00
static NTSTATUS wreplsrv_in_replication ( struct wreplsrv_in_call * call )
{
struct wrepl_replication * repl_in = & call - > req_packet . message . replication ;
2005-10-14 16:52:51 +04:00
NTSTATUS status ;
2005-10-14 16:44:47 +04:00
/*
* w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
*/
if ( call - > req_packet . opcode & WREPL_OPCODE_BITS ) {
/*
* if the assoc_ctx doesn ' t match ignore the packet
*/
if ( call - > req_packet . assoc_ctx ! = call - > wreplconn - > assoc_ctx . our_ctx ) {
return ERROR_INVALID_PARAMETER ;
}
}
if ( ! call - > wreplconn - > partner ) {
2010-04-27 18:17:28 +04:00
struct tsocket_address * peer_addr = call - > wreplconn - > conn - > remote_address ;
char * peer_ip ;
2006-01-20 15:26:09 +03:00
2010-04-27 18:17:28 +04:00
if ( ! tsocket_address_is_inet ( peer_addr , " ipv4 " ) ) {
DEBUG ( 0 , ( " wreplsrv_in_replication: non ipv4 peer addr '%s' \n " ,
tsocket_address_string ( peer_addr , call ) ) ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
peer_ip = tsocket_address_inet_addr_string ( peer_addr , call ) ;
if ( peer_ip = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
call - > wreplconn - > partner = wreplsrv_find_partner ( call - > wreplconn - > service , peer_ip ) ;
2006-01-20 15:26:09 +03:00
if ( ! call - > wreplconn - > partner ) {
2010-04-27 18:17:28 +04:00
DEBUG ( 1 , ( " Failing WINS replication from non-partner %s \n " , peer_ip ) ) ;
2006-01-20 15:26:09 +03:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
2005-10-14 16:44:47 +04:00
}
2005-10-14 16:38:07 +04:00
switch ( repl_in - > command ) {
case WREPL_REPL_TABLE_QUERY :
2005-10-14 18:02:47 +04:00
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PUSH ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication TABLE_QUERY from non-push-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
2005-10-14 16:52:51 +04:00
status = wreplsrv_in_table_query ( call ) ;
2005-10-14 16:38:07 +04:00
break ;
2005-10-14 16:52:51 +04:00
2005-10-14 16:38:07 +04:00
case WREPL_REPL_TABLE_REPLY :
2005-10-14 16:52:51 +04:00
return ERROR_INVALID_PARAMETER ;
2005-10-14 16:38:07 +04:00
case WREPL_REPL_SEND_REQUEST :
2005-10-14 18:02:47 +04:00
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PUSH ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication SEND_REQUESET from non-push-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
2005-10-14 16:52:51 +04:00
status = wreplsrv_in_send_request ( call ) ;
2005-10-14 16:38:07 +04:00
break ;
2005-10-14 16:52:51 +04:00
2005-10-14 16:38:07 +04:00
case WREPL_REPL_SEND_REPLY :
2005-10-14 16:52:51 +04:00
return ERROR_INVALID_PARAMETER ;
2005-10-14 16:38:07 +04:00
case WREPL_REPL_UPDATE :
2005-10-14 18:02:47 +04:00
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PULL ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication UPDATE from non-pull-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
status = wreplsrv_in_update ( call ) ;
break ;
2005-10-14 16:52:51 +04:00
2005-10-14 18:02:47 +04:00
case WREPL_REPL_UPDATE2 :
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PULL ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication UPDATE2 from non-pull-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
status = wreplsrv_in_update2 ( call ) ;
break ;
2005-10-14 16:52:51 +04:00
2005-10-14 16:38:07 +04:00
case WREPL_REPL_INFORM :
2005-10-14 18:02:47 +04:00
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PULL ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication INFORM from non-pull-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
status = wreplsrv_in_inform ( call ) ;
break ;
2005-10-14 16:52:51 +04:00
2005-10-14 18:02:47 +04:00
case WREPL_REPL_INFORM2 :
if ( ! ( call - > wreplconn - > partner - > type & WINSREPL_PARTNER_PULL ) ) {
2008-01-14 15:52:14 +03:00
DEBUG ( 0 , ( " Failing WINS replication INFORM2 from non-pull-partner %s \n " ,
2006-01-20 15:26:09 +03:00
call - > wreplconn - > partner - > address ) ) ;
2005-10-14 18:02:47 +04:00
return wreplsrv_in_stop_assoc_ctx ( call ) ;
}
status = wreplsrv_in_inform2 ( call ) ;
break ;
2005-10-14 16:52:51 +04:00
default :
return ERROR_INVALID_PARAMETER ;
}
if ( NT_STATUS_IS_OK ( status ) ) {
call - > rep_packet . mess_type = WREPL_REPLICATION ;
2005-10-14 16:38:07 +04:00
}
2005-10-14 16:52:51 +04:00
return status ;
2005-10-14 16:44:47 +04:00
}
static NTSTATUS wreplsrv_in_invalid_assoc_ctx ( struct wreplsrv_in_call * call )
{
struct wrepl_start * start = & call - > rep_packet . message . start ;
call - > rep_packet . opcode = 0x00008583 ;
2005-10-14 16:38:07 +04:00
call - > rep_packet . assoc_ctx = 0 ;
2005-10-14 16:44:47 +04:00
call - > rep_packet . mess_type = WREPL_START_ASSOCIATION ;
start - > assoc_ctx = 0x0000000a ;
start - > minor_version = 0x0001 ;
start - > major_version = 0x0000 ;
call - > rep_packet . padding = data_blob_talloc ( call , NULL , 4 ) ;
memset ( call - > rep_packet . padding . data , ' \0 ' , call - > rep_packet . padding . length ) ;
2005-10-14 16:38:07 +04:00
return NT_STATUS_OK ;
}
NTSTATUS wreplsrv_in_call ( struct wreplsrv_in_call * call )
{
2005-10-14 16:44:47 +04:00
NTSTATUS status ;
2005-10-14 16:38:07 +04:00
2005-10-14 16:44:47 +04:00
if ( ! ( call - > req_packet . opcode & WREPL_OPCODE_BITS )
& & ( call - > wreplconn - > assoc_ctx . our_ctx = = WREPLSRV_INVALID_ASSOC_CTX ) ) {
return wreplsrv_in_invalid_assoc_ctx ( call ) ;
}
2005-10-14 16:38:07 +04:00
switch ( call - > req_packet . mess_type ) {
case WREPL_START_ASSOCIATION :
2005-10-14 16:44:47 +04:00
status = wreplsrv_in_start_association ( call ) ;
2005-10-14 16:38:07 +04:00
break ;
2005-10-14 16:44:47 +04:00
case WREPL_START_ASSOCIATION_REPLY :
/* this is not valid here, so we ignore it */
return ERROR_INVALID_PARAMETER ;
2005-10-14 16:38:07 +04:00
case WREPL_STOP_ASSOCIATION :
2005-10-14 16:44:47 +04:00
status = wreplsrv_in_stop_association ( call ) ;
2005-10-14 16:38:07 +04:00
break ;
case WREPL_REPLICATION :
2005-10-14 16:44:47 +04:00
status = wreplsrv_in_replication ( call ) ;
break ;
default :
/* everythingelse is also not valid here, so we ignore it */
return ERROR_INVALID_PARAMETER ;
2005-10-14 16:38:07 +04:00
}
2005-10-14 16:44:47 +04:00
if ( call - > wreplconn - > assoc_ctx . our_ctx = = WREPLSRV_INVALID_ASSOC_CTX ) {
return wreplsrv_in_invalid_assoc_ctx ( call ) ;
}
2005-10-14 16:38:07 +04:00
2005-10-14 16:44:47 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2005-10-14 18:02:47 +04:00
/* let the backend to set some of the opcode bits, but always add the standards */
call - > rep_packet . opcode | = WREPL_OPCODE_BITS ;
2005-10-14 16:44:47 +04:00
call - > rep_packet . assoc_ctx = call - > wreplconn - > assoc_ctx . peer_ctx ;
}
2005-10-14 16:38:07 +04:00
2005-10-14 16:44:47 +04:00
return status ;
}