LCOV - code coverage report
Current view: top level - source4/wrepl_server - wrepl_in_call.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 163 286 57.0 %
Date: 2024-04-21 15:09:00 Functions: 8 15 53.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    
       4             :    WINS Replication server
       5             :    
       6             :    Copyright (C) Stefan Metzmacher      2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/events/events.h"
      24             : #include "lib/tsocket/tsocket.h"
      25             : #include "samba/service_task.h"
      26             : #include "samba/service_stream.h"
      27             : #include "libcli/wrepl/winsrepl.h"
      28             : #include "wrepl_server/wrepl_server.h"
      29             : #include "libcli/composite/composite.h"
      30             : #include "nbt_server/wins/winsdb.h"
      31             : #include <ldb.h>
      32             : #include <ldb_errors.h>
      33             : #include "system/time.h"
      34             : #include "lib/util/tsort.h"
      35             : #include "param/param.h"
      36             : 
      37         681 : static NTSTATUS wreplsrv_in_start_association(struct wreplsrv_in_call *call)
      38             : {
      39         681 :         struct wrepl_start *start       = &call->req_packet.message.start;
      40         681 :         struct wrepl_start *start_reply = &call->rep_packet.message.start_reply;
      41             : 
      42         681 :         if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
      43             :                 /*
      44             :                  *if the assoc_ctx doesn't match ignore the packet
      45             :                  */
      46         681 :                 if ((call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx)
      47           2 :                    && (call->req_packet.assoc_ctx != 0)) {
      48           0 :                         return ERROR_INVALID_PARAMETER;
      49             :                 }
      50             :         } else {
      51           0 :                 call->wreplconn->assoc_ctx.our_ctx = WREPLSRV_INVALID_ASSOC_CTX;
      52           0 :                 return NT_STATUS_OK;
      53             :         }
      54             : 
      55             : /*
      56             :  * it seems that we don't know all details about the start_association
      57             :  * to support replication with NT4 (it sends 1.1 instead of 5.2)
      58             :  * we ignore the version numbers until we know all details
      59             :  */
      60             : #if 0
      61             :         if (start->minor_version != 2 || start->major_version != 5) {
      62             :                 /* w2k terminate the connection if the versions doesn't match */
      63             :                 return NT_STATUS_UNKNOWN_REVISION;
      64             :         }
      65             : #endif
      66             : 
      67         681 :         call->wreplconn->assoc_ctx.stopped        = false;
      68         681 :         call->wreplconn->assoc_ctx.our_ctx        = WREPLSRV_VALID_ASSOC_CTX;
      69         681 :         call->wreplconn->assoc_ctx.peer_ctx       = start->assoc_ctx;
      70             : 
      71         681 :         call->rep_packet.mess_type           = WREPL_START_ASSOCIATION_REPLY;
      72         681 :         start_reply->assoc_ctx                       = call->wreplconn->assoc_ctx.our_ctx;
      73         681 :         start_reply->minor_version           = 2;
      74         681 :         start_reply->major_version           = 5;
      75             : 
      76             :         /*
      77             :          * nt4 uses 41 bytes for the start_association call
      78             :          * so do it the same and as we don't know the meanings of these bytes
      79             :          * we just send zeros and nt4, w2k and w2k3 seems to be happy with this
      80             :          *
      81             :          * if we don't do this nt4 uses an old version of the wins replication protocol
      82             :          * and that would break nt4 <-> samba replication
      83             :          */
      84         681 :         call->rep_packet.padding             = data_blob_talloc(call, NULL, 21);
      85         681 :         NT_STATUS_HAVE_NO_MEMORY(call->rep_packet.padding.data);
      86             : 
      87         681 :         memset(call->rep_packet.padding.data, 0, call->rep_packet.padding.length);
      88             : 
      89         681 :         return NT_STATUS_OK;
      90             : }
      91             : 
      92           0 : static NTSTATUS wreplsrv_in_stop_assoc_ctx(struct wreplsrv_in_call *call)
      93             : {
      94           0 :         struct wrepl_stop *stop_out             = &call->rep_packet.message.stop;
      95             : 
      96           0 :         call->wreplconn->assoc_ctx.stopped        = true;
      97             : 
      98           0 :         call->rep_packet.mess_type           = WREPL_STOP_ASSOCIATION;
      99           0 :         stop_out->reason                     = 4;
     100             : 
     101           0 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104           0 : static NTSTATUS wreplsrv_in_stop_association(struct wreplsrv_in_call *call)
     105             : {
     106             :         /*
     107             :          * w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
     108             :          */
     109           0 :         if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
     110             :                 /*
     111             :                  *if the assoc_ctx doesn't match ignore the packet
     112             :                  */
     113           0 :                 if (call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx) {
     114           0 :                         return ERROR_INVALID_PARAMETER;
     115             :                 }
     116             :                 /* when the opcode bits are set the connection should be directly terminated */
     117           0 :                 return NT_STATUS_CONNECTION_RESET;
     118             :         }
     119             : 
     120           0 :         if (call->wreplconn->assoc_ctx.stopped) {
     121             :                 /* this causes the connection to be directly terminated */
     122           0 :                 return NT_STATUS_CONNECTION_RESET;
     123             :         }
     124             : 
     125             :         /* this will cause to not receive packets anymore and terminate the connection if the reply is send */
     126           0 :         call->terminate_after_send = true;
     127           0 :         return wreplsrv_in_stop_assoc_ctx(call);
     128             : }
     129             : 
     130           3 : static NTSTATUS wreplsrv_in_table_query(struct wreplsrv_in_call *call)
     131             : {
     132           3 :         struct wreplsrv_service *service = call->wreplconn->service;
     133           3 :         struct wrepl_replication *repl_out = &call->rep_packet.message.replication;
     134           3 :         struct wrepl_table *table_out = &call->rep_packet.message.replication.info.table;
     135             : 
     136           3 :         repl_out->command = WREPL_REPL_TABLE_REPLY;
     137             : 
     138           6 :         return wreplsrv_fill_wrepl_table(service, call, table_out,
     139           3 :                                          service->wins_db->local_owner, true);
     140             : }
     141             : 
     142           0 : static int wreplsrv_in_sort_wins_name(struct wrepl_wins_name *n1,
     143             :                                       struct wrepl_wins_name *n2)
     144             : {
     145           0 :         if (n1->id < n2->id) return -1;
     146           0 :         if (n1->id > n2->id) return 1;
     147           0 :         return 0;
     148             : }
     149             : 
     150         527 : static NTSTATUS wreplsrv_record2wins_name(TALLOC_CTX *mem_ctx,
     151             :                                           struct wrepl_wins_name *name,
     152             :                                           struct winsdb_record *rec)
     153             : {
     154           0 :         uint32_t num_ips, i;
     155           0 :         struct wrepl_ip *ips;
     156             : 
     157         527 :         name->name           = rec->name;
     158         527 :         talloc_steal(mem_ctx, rec->name);
     159             : 
     160         527 :         name->id             = rec->version;
     161         527 :         name->unknown                = "255.255.255.255";
     162             : 
     163         527 :         name->flags          = WREPL_NAME_FLAGS(rec->type, rec->state, rec->node, rec->is_static);
     164             : 
     165         527 :         switch (name->flags & 2) {
     166         288 :         case 0:
     167         288 :                 name->addresses.ip                   = rec->addresses[0]->address;
     168         288 :                 talloc_steal(mem_ctx, rec->addresses[0]->address);
     169         288 :                 break;
     170         239 :         case 2:
     171         239 :                 num_ips = winsdb_addr_list_length(rec->addresses);
     172         239 :                 ips     = talloc_array(mem_ctx, struct wrepl_ip, num_ips);
     173         239 :                 NT_STATUS_HAVE_NO_MEMORY(ips);
     174             : 
     175         629 :                 for (i = 0; i < num_ips; i++) {
     176         390 :                         ips[i].owner    = rec->addresses[i]->wins_owner;
     177         390 :                         talloc_steal(ips, rec->addresses[i]->wins_owner);
     178         390 :                         ips[i].ip       = rec->addresses[i]->address;
     179         390 :                         talloc_steal(ips, rec->addresses[i]->address);
     180             :                 }
     181             : 
     182         239 :                 name->addresses.addresses.num_ips    = num_ips;
     183         239 :                 name->addresses.addresses.ips                = ips;
     184         239 :                 break;
     185             :         }
     186             : 
     187         527 :         return NT_STATUS_OK;
     188             : }
     189             : 
     190         780 : static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
     191             : {
     192         780 :         struct wreplsrv_service *service = call->wreplconn->service;
     193         780 :         struct wrepl_wins_owner *owner_in = &call->req_packet.message.replication.info.owner;
     194         780 :         struct wrepl_replication *repl_out = &call->rep_packet.message.replication;
     195         780 :         struct wrepl_send_reply *reply_out = &call->rep_packet.message.replication.info.reply;
     196           0 :         struct wreplsrv_owner *owner;
     197           0 :         const char *owner_filter;
     198           0 :         const char *filter;
     199         780 :         struct ldb_result *res = NULL;
     200           0 :         int ret;
     201           0 :         struct wrepl_wins_name *names;
     202           0 :         struct winsdb_record *rec;
     203           0 :         NTSTATUS status;
     204           0 :         unsigned int i, j;
     205         780 :         time_t now = time(NULL);
     206             : 
     207         780 :         owner = wreplsrv_find_owner(service, service->table, owner_in->address);
     208             : 
     209         780 :         repl_out->command    = WREPL_REPL_SEND_REPLY;
     210         780 :         reply_out->num_names = 0;
     211         780 :         reply_out->names     = NULL;
     212             : 
     213             :         /*
     214             :          * if we didn't know this owner, must be a bug in the partners client code...
     215             :          * return an empty list.
     216             :          */
     217         780 :         if (!owner) {
     218           0 :                 DEBUG(2,("WINSREPL:reply [0] records unknown owner[%s] to partner[%s]\n",
     219             :                         owner_in->address, call->wreplconn->partner->address));
     220           0 :                 return NT_STATUS_OK;
     221             :         }
     222             : 
     223             :         /*
     224             :          * the client sends a max_version of 0, interpret it as
     225             :          * (uint64_t)-1
     226             :          */
     227         780 :         if (owner_in->max_version == 0) {
     228          12 :                 owner_in->max_version = (uint64_t)-1;
     229             :         }
     230             : 
     231             :         /*
     232             :          * if the partner ask for nothing, or give invalid ranges,
     233             :          * return an empty list.
     234             :          */
     235         780 :         if (owner_in->min_version > owner_in->max_version) {
     236           0 :                 DEBUG(2,("WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
     237             :                         owner_in->address, 
     238             :                         (long long)owner_in->min_version, 
     239             :                         (long long)owner_in->max_version,
     240             :                         call->wreplconn->partner->address));
     241           0 :                 return NT_STATUS_OK;
     242             :         }
     243             : 
     244             :         /*
     245             :          * if the partner has already all records for nothing, or give invalid ranges,
     246             :          * return an empty list.
     247             :          */
     248         780 :         if (owner_in->min_version > owner->owner.max_version) {
     249           0 :                 DEBUG(2,("WINSREPL:reply [0] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
     250             :                         owner_in->address, 
     251             :                         (long long)owner_in->min_version, 
     252             :                         (long long)owner_in->max_version,
     253             :                         call->wreplconn->partner->address));
     254           0 :                 return NT_STATUS_OK;
     255             :         }
     256             : 
     257         780 :         owner_filter = wreplsrv_owner_filter(service, call, owner->owner.address);
     258         780 :         NT_STATUS_HAVE_NO_MEMORY(owner_filter);
     259         780 :         filter = talloc_asprintf(call,
     260             :                                  "(&%s(objectClass=winsRecord)"
     261             :                                  "(|(recordState=%u)(recordState=%u))"
     262             :                                  "(versionID>=%llu)(versionID<=%llu))",
     263             :                                  owner_filter,
     264             :                                  WREPL_STATE_ACTIVE, WREPL_STATE_TOMBSTONE,
     265         780 :                                  (long long)owner_in->min_version, 
     266         780 :                                  (long long)owner_in->max_version);
     267         780 :         NT_STATUS_HAVE_NO_MEMORY(filter);
     268         780 :         ret = ldb_search(service->wins_db->ldb, call, &res, NULL, LDB_SCOPE_SUBTREE, NULL, "%s", filter);
     269         780 :         if (ret != LDB_SUCCESS) return NT_STATUS_INTERNAL_DB_CORRUPTION;
     270         780 :         DEBUG(10,("WINSREPL: filter '%s' count %d\n", filter, res->count));
     271             : 
     272         780 :         if (res->count == 0) {
     273         253 :                 DEBUG(2,("WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
     274             :                         res->count, owner_in->address, 
     275             :                         (long long)owner_in->min_version, 
     276             :                         (long long)owner_in->max_version,
     277             :                         call->wreplconn->partner->address));
     278         253 :                 return NT_STATUS_OK;
     279             :         }
     280             : 
     281         527 :         names = talloc_array(call, struct wrepl_wins_name, res->count);
     282         527 :         NT_STATUS_HAVE_NO_MEMORY(names);
     283             : 
     284        1054 :         for (i=0, j=0; i < res->count; i++) {
     285         527 :                 status = winsdb_record(service->wins_db, res->msgs[i], call, now, &rec);
     286         527 :                 NT_STATUS_NOT_OK_RETURN(status);
     287             : 
     288             :                 /*
     289             :                  * it's possible that winsdb_record() made the record RELEASED
     290             :                  * because it's expired, but in the database it's still stored
     291             :                  * as ACTIVE...
     292             :                  *
     293             :                  * make sure we really only replicate ACTIVE and TOMBSTONE records
     294             :                  */
     295         527 :                 if (rec->state == WREPL_STATE_ACTIVE || rec->state == WREPL_STATE_TOMBSTONE) {
     296         527 :                         status = wreplsrv_record2wins_name(names, &names[j], rec);
     297         527 :                         NT_STATUS_NOT_OK_RETURN(status);
     298         527 :                         j++;
     299             :                 }
     300             : 
     301         527 :                 talloc_free(rec);
     302         527 :                 talloc_free(res->msgs[i]);
     303             :         }
     304             : 
     305             :         /* sort the names before we send them */
     306         527 :         TYPESAFE_QSORT(names, j, wreplsrv_in_sort_wins_name);
     307             : 
     308         527 :         DEBUG(2,("WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
     309             :                 j, owner_in->address, 
     310             :                 (long long)owner_in->min_version, 
     311             :                 (long long)owner_in->max_version,
     312             :                 call->wreplconn->partner->address));
     313             : 
     314         527 :         reply_out->num_names = j;
     315         527 :         reply_out->names     = names;
     316             : 
     317         527 :         return NT_STATUS_OK;
     318             : }
     319             : 
     320             : struct wreplsrv_in_update_state {
     321             :         struct wreplsrv_in_connection *wrepl_in;
     322             :         struct wreplsrv_out_connection *wrepl_out;
     323             :         struct composite_context *creq;
     324             :         struct wreplsrv_pull_cycle_io cycle_io;
     325             : };
     326             : 
     327         675 : static void wreplsrv_in_update_handler(struct composite_context *creq)
     328             : {
     329         675 :         struct wreplsrv_in_update_state *update_state = talloc_get_type(creq->async.private_data,
     330             :                                                         struct wreplsrv_in_update_state);
     331           0 :         NTSTATUS status;
     332             : 
     333         675 :         status = wreplsrv_pull_cycle_recv(creq);
     334             : 
     335         675 :         talloc_free(update_state->wrepl_out);
     336             : 
     337         675 :         wreplsrv_terminate_in_connection(update_state->wrepl_in, nt_errstr(status));
     338         675 : }
     339             : 
     340         675 : static NTSTATUS wreplsrv_in_update(struct wreplsrv_in_call *call)
     341             : {
     342         675 :         struct wreplsrv_in_connection *wrepl_in = call->wreplconn;
     343           0 :         struct wreplsrv_out_connection *wrepl_out;
     344         675 :         struct wrepl_table *update_in = &call->req_packet.message.replication.info.table;
     345           0 :         struct wreplsrv_in_update_state *update_state;
     346           0 :         NTSTATUS status;
     347             : 
     348         675 :         DEBUG(2,("WREPL_REPL_UPDATE: partner[%s] initiator[%s] num_owners[%u]\n",
     349             :                 call->wreplconn->partner->address,
     350             :                 update_in->initiator, update_in->partner_count));
     351             : 
     352         675 :         update_state = talloc(wrepl_in, struct wreplsrv_in_update_state);
     353         675 :         NT_STATUS_HAVE_NO_MEMORY(update_state);
     354             : 
     355         675 :         wrepl_out = talloc(update_state, struct wreplsrv_out_connection);
     356         675 :         NT_STATUS_HAVE_NO_MEMORY(wrepl_out);
     357         675 :         wrepl_out->service           = wrepl_in->service;
     358         675 :         wrepl_out->partner           = wrepl_in->partner;
     359         675 :         wrepl_out->assoc_ctx.our_ctx = wrepl_in->assoc_ctx.our_ctx;
     360         675 :         wrepl_out->assoc_ctx.peer_ctx        = wrepl_in->assoc_ctx.peer_ctx;
     361        1350 :         wrepl_out->sock                      = wrepl_socket_init(wrepl_out,
     362         675 :                                                             wrepl_in->conn->event.ctx);
     363             :                                                             
     364         675 :         if (wrepl_out->sock == NULL) {
     365           0 :                 TALLOC_FREE(update_state);
     366           0 :                 return NT_STATUS_NO_MEMORY;
     367             :         }
     368             : 
     369         675 :         TALLOC_FREE(wrepl_in->send_queue);
     370             : 
     371         675 :         status = wrepl_socket_donate_stream(wrepl_out->sock, &wrepl_in->tstream);
     372         675 :         if (!NT_STATUS_IS_OK(status)) {
     373           0 :                 TALLOC_FREE(update_state);
     374           0 :                 return status;
     375             :         }
     376             : 
     377         675 :         update_state->wrepl_in                       = wrepl_in;
     378         675 :         update_state->wrepl_out                      = wrepl_out;
     379         675 :         update_state->cycle_io.in.partner    = wrepl_out->partner;
     380         675 :         update_state->cycle_io.in.num_owners = update_in->partner_count;
     381         675 :         update_state->cycle_io.in.owners     = update_in->partners;
     382         675 :         talloc_steal(update_state, update_in->partners);
     383         675 :         update_state->cycle_io.in.wreplconn  = wrepl_out;
     384         675 :         update_state->creq = wreplsrv_pull_cycle_send(update_state, &update_state->cycle_io);
     385         675 :         if (!update_state->creq) {
     386           0 :                 talloc_free(update_state);
     387           0 :                 return NT_STATUS_INTERNAL_ERROR;
     388             :         }
     389             : 
     390         675 :         update_state->creq->async.fn              = wreplsrv_in_update_handler;
     391         675 :         update_state->creq->async.private_data    = update_state;
     392             : 
     393         675 :         return ERROR_INVALID_PARAMETER;
     394             : }
     395             : 
     396           0 : static NTSTATUS wreplsrv_in_update2(struct wreplsrv_in_call *call)
     397             : {
     398           0 :         return wreplsrv_in_update(call);
     399             : }
     400             : 
     401           0 : static NTSTATUS wreplsrv_in_inform(struct wreplsrv_in_call *call)
     402             : {
     403           0 :         struct wrepl_table *inform_in = &call->req_packet.message.replication.info.table;
     404             : 
     405           0 :         DEBUG(2,("WREPL_REPL_INFORM: partner[%s] initiator[%s] num_owners[%u]\n",
     406             :                 call->wreplconn->partner->address,
     407             :                 inform_in->initiator, inform_in->partner_count));
     408             : 
     409           0 :         wreplsrv_out_partner_pull(call->wreplconn->partner, inform_in);
     410             : 
     411             :         /* we don't reply to WREPL_REPL_INFORM messages */
     412           0 :         return ERROR_INVALID_PARAMETER;
     413             : }
     414             : 
     415           0 : static NTSTATUS wreplsrv_in_inform2(struct wreplsrv_in_call *call)
     416             : {
     417           0 :         return wreplsrv_in_inform(call);
     418             : }
     419             : 
     420        1458 : static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
     421             : {
     422        1458 :         struct wrepl_replication *repl_in = &call->req_packet.message.replication;
     423           0 :         NTSTATUS status;
     424             : 
     425             :         /*
     426             :          * w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
     427             :          */
     428        1458 :         if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
     429             :                 /*
     430             :                  *if the assoc_ctx doesn't match ignore the packet
     431             :                  */
     432        1458 :                 if (call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx) {
     433           0 :                         return ERROR_INVALID_PARAMETER;
     434             :                 }
     435             :         }
     436             : 
     437        1458 :         if (!call->wreplconn->partner) {
     438           0 :                 struct tsocket_address *peer_addr = call->wreplconn->conn->remote_address;
     439           0 :                 char *peer_ip;
     440             : 
     441           0 :                 if (!tsocket_address_is_inet(peer_addr, "ipv4")) {
     442           0 :                         DEBUG(0,("wreplsrv_in_replication: non ipv4 peer addr '%s'\n",
     443             :                                 tsocket_address_string(peer_addr, call)));
     444           0 :                         return NT_STATUS_INTERNAL_ERROR;
     445             :                 }
     446             : 
     447           0 :                 peer_ip = tsocket_address_inet_addr_string(peer_addr, call);
     448           0 :                 if (peer_ip == NULL) {
     449           0 :                         return NT_STATUS_NO_MEMORY;
     450             :                 }
     451             : 
     452           0 :                 call->wreplconn->partner = wreplsrv_find_partner(call->wreplconn->service, peer_ip);
     453           0 :                 if (!call->wreplconn->partner) {
     454           0 :                         DEBUG(1,("Failing WINS replication from non-partner %s\n", peer_ip));
     455           0 :                         return wreplsrv_in_stop_assoc_ctx(call);
     456             :                 }
     457             :         }
     458             : 
     459        1458 :         switch (repl_in->command) {
     460           3 :                 case WREPL_REPL_TABLE_QUERY:
     461           3 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PUSH)) {
     462           0 :                                 DEBUG(0,("Failing WINS replication TABLE_QUERY from non-push-partner %s\n",
     463             :                                          call->wreplconn->partner->address));
     464           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     465             :                         }
     466           3 :                         status = wreplsrv_in_table_query(call);
     467           3 :                         break;
     468             : 
     469           0 :                 case WREPL_REPL_TABLE_REPLY:
     470           0 :                         return ERROR_INVALID_PARAMETER;
     471             : 
     472         780 :                 case WREPL_REPL_SEND_REQUEST:
     473         780 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PUSH)) {
     474           0 :                                 DEBUG(0,("Failing WINS replication SEND_REQUESET from non-push-partner %s\n",
     475             :                                          call->wreplconn->partner->address));
     476           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     477             :                         }
     478         780 :                         status = wreplsrv_in_send_request(call);
     479         780 :                         break;
     480             : 
     481           0 :                 case WREPL_REPL_SEND_REPLY:
     482           0 :                         return ERROR_INVALID_PARAMETER;
     483             :         
     484         675 :                 case WREPL_REPL_UPDATE:
     485         675 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
     486           0 :                                 DEBUG(0,("Failing WINS replication UPDATE from non-pull-partner %s\n",
     487             :                                          call->wreplconn->partner->address));
     488           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     489             :                         }
     490         675 :                         status = wreplsrv_in_update(call);
     491         675 :                         break;
     492             : 
     493           0 :                 case WREPL_REPL_UPDATE2:
     494           0 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
     495           0 :                                 DEBUG(0,("Failing WINS replication UPDATE2 from non-pull-partner %s\n",
     496             :                                          call->wreplconn->partner->address));
     497           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     498             :                         }
     499           0 :                         status = wreplsrv_in_update2(call);
     500           0 :                         break;
     501             : 
     502           0 :                 case WREPL_REPL_INFORM:
     503           0 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
     504           0 :                                 DEBUG(0,("Failing WINS replication INFORM from non-pull-partner %s\n",
     505             :                                          call->wreplconn->partner->address));
     506           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     507             :                         }
     508           0 :                         status = wreplsrv_in_inform(call);
     509           0 :                         break;
     510             : 
     511           0 :                 case WREPL_REPL_INFORM2:
     512           0 :                         if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
     513           0 :                                 DEBUG(0,("Failing WINS replication INFORM2 from non-pull-partner %s\n",
     514             :                                          call->wreplconn->partner->address));
     515           0 :                                 return wreplsrv_in_stop_assoc_ctx(call);
     516             :                         }
     517           0 :                         status = wreplsrv_in_inform2(call);
     518           0 :                         break;
     519             : 
     520           0 :                 default:
     521           0 :                         return ERROR_INVALID_PARAMETER;
     522             :         }
     523             : 
     524        1458 :         if (NT_STATUS_IS_OK(status)) {
     525         783 :                 call->rep_packet.mess_type = WREPL_REPLICATION;
     526             :         }
     527             : 
     528        1458 :         return status;
     529             : }
     530             : 
     531           0 : static NTSTATUS wreplsrv_in_invalid_assoc_ctx(struct wreplsrv_in_call *call)
     532             : {
     533           0 :         struct wrepl_start *start       = &call->rep_packet.message.start;
     534             : 
     535           0 :         call->rep_packet.opcode              = 0x00008583;
     536           0 :         call->rep_packet.assoc_ctx   = 0;
     537           0 :         call->rep_packet.mess_type   = WREPL_START_ASSOCIATION;
     538             : 
     539           0 :         start->assoc_ctx             = 0x0000000a;
     540           0 :         start->minor_version         = 0x0001;
     541           0 :         start->major_version         = 0x0000;
     542             : 
     543           0 :         call->rep_packet.padding     = data_blob_talloc(call, NULL, 4);
     544           0 :         memset(call->rep_packet.padding.data, '\0', call->rep_packet.padding.length);
     545             : 
     546           0 :         return NT_STATUS_OK;
     547             : }
     548             : 
     549        2139 : NTSTATUS wreplsrv_in_call(struct wreplsrv_in_call *call)
     550             : {
     551           0 :         NTSTATUS status;
     552             : 
     553        2139 :         if (!(call->req_packet.opcode & WREPL_OPCODE_BITS)
     554           0 :             && (call->wreplconn->assoc_ctx.our_ctx == WREPLSRV_INVALID_ASSOC_CTX)) {
     555           0 :                 return wreplsrv_in_invalid_assoc_ctx(call);
     556             :         }
     557             : 
     558        2139 :         switch (call->req_packet.mess_type) {
     559         681 :                 case WREPL_START_ASSOCIATION:
     560         681 :                         status = wreplsrv_in_start_association(call);
     561         681 :                         break;
     562           0 :                 case WREPL_START_ASSOCIATION_REPLY:
     563             :                         /* this is not valid here, so we ignore it */
     564           0 :                         return ERROR_INVALID_PARAMETER;
     565             : 
     566           0 :                 case WREPL_STOP_ASSOCIATION:
     567           0 :                         status = wreplsrv_in_stop_association(call);
     568           0 :                         break;
     569             : 
     570        1458 :                 case WREPL_REPLICATION:
     571        1458 :                         status = wreplsrv_in_replication(call);
     572        1458 :                         break;
     573           0 :                 default:
     574             :                         /* everythingelse is also not valid here, so we ignore it */
     575           0 :                         return ERROR_INVALID_PARAMETER;
     576             :         }
     577             : 
     578        2139 :         if (call->wreplconn->assoc_ctx.our_ctx == WREPLSRV_INVALID_ASSOC_CTX) {
     579           0 :                 return wreplsrv_in_invalid_assoc_ctx(call);
     580             :         }
     581             : 
     582        2139 :         if (NT_STATUS_IS_OK(status)) {
     583             :                 /* let the backend to set some of the opcode bits, but always add the standards */
     584        1464 :                 call->rep_packet.opcode              |= WREPL_OPCODE_BITS;
     585        1464 :                 call->rep_packet.assoc_ctx   = call->wreplconn->assoc_ctx.peer_ctx;
     586             :         }
     587             : 
     588        2139 :         return status;
     589             : }

Generated by: LCOV version 1.14