root/source4/wrepl_server/wrepl_in_call.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wreplsrv_in_start_association
  2. wreplsrv_in_stop_assoc_ctx
  3. wreplsrv_in_stop_association
  4. wreplsrv_in_table_query
  5. wreplsrv_in_sort_wins_name
  6. wreplsrv_record2wins_name
  7. wreplsrv_in_send_request
  8. wreplsrv_in_update_handler
  9. wreplsrv_in_update
  10. wreplsrv_in_update2
  11. wreplsrv_in_inform
  12. wreplsrv_in_inform2
  13. wreplsrv_in_replication
  14. wreplsrv_in_invalid_assoc_ctx
  15. wreplsrv_in_call

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

/* [<][>][^][v][top][bottom][index][help] */