📄 wrepl_out_helpers.c
字号:
/* 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 the Free Software Foundation; either version 3 of the License, or (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 along with this program. If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "lib/events/events.h"#include "lib/socket/socket.h"#include "smbd/service_task.h"#include "smbd/service_stream.h"#include "librpc/gen_ndr/winsrepl.h"#include "wrepl_server/wrepl_server.h"#include "nbt_server/wins/winsdb.h"#include "libcli/composite/composite.h"#include "libcli/wrepl/winsrepl.h"#include "libcli/resolve/resolve.h"#include "param/param.h"enum wreplsrv_out_connect_stage { WREPLSRV_OUT_CONNECT_STAGE_WAIT_SOCKET, WREPLSRV_OUT_CONNECT_STAGE_WAIT_ASSOC_CTX, WREPLSRV_OUT_CONNECT_STAGE_DONE};struct wreplsrv_out_connect_state { enum wreplsrv_out_connect_stage stage; struct composite_context *c; struct wrepl_request *req; struct composite_context *c_req; struct wrepl_associate assoc_io; enum winsrepl_partner_type type; struct wreplsrv_out_connection *wreplconn;};static void wreplsrv_out_connect_handler_creq(struct composite_context *c_req);static void wreplsrv_out_connect_handler_req(struct wrepl_request *req);static NTSTATUS wreplsrv_out_connect_wait_socket(struct wreplsrv_out_connect_state *state){ NTSTATUS status; status = wrepl_connect_recv(state->c_req); NT_STATUS_NOT_OK_RETURN(status); state->req = wrepl_associate_send(state->wreplconn->sock, &state->assoc_io); NT_STATUS_HAVE_NO_MEMORY(state->req); state->req->async.fn = wreplsrv_out_connect_handler_req; state->req->async.private = state; state->stage = WREPLSRV_OUT_CONNECT_STAGE_WAIT_ASSOC_CTX; return NT_STATUS_OK;}static NTSTATUS wreplsrv_out_connect_wait_assoc_ctx(struct wreplsrv_out_connect_state *state){ NTSTATUS status; status = wrepl_associate_recv(state->req, &state->assoc_io); NT_STATUS_NOT_OK_RETURN(status); state->wreplconn->assoc_ctx.peer_ctx = state->assoc_io.out.assoc_ctx; if (state->type == WINSREPL_PARTNER_PUSH) { state->wreplconn->partner->push.wreplconn = state->wreplconn; talloc_steal(state->wreplconn->partner, state->wreplconn); } else if (state->type == WINSREPL_PARTNER_PULL) { state->wreplconn->partner->pull.wreplconn = state->wreplconn; talloc_steal(state->wreplconn->partner, state->wreplconn); } state->stage = WREPLSRV_OUT_CONNECT_STAGE_DONE; return NT_STATUS_OK;}static void wreplsrv_out_connect_handler(struct wreplsrv_out_connect_state *state){ struct composite_context *c = state->c; switch (state->stage) { case WREPLSRV_OUT_CONNECT_STAGE_WAIT_SOCKET: c->status = wreplsrv_out_connect_wait_socket(state); break; case WREPLSRV_OUT_CONNECT_STAGE_WAIT_ASSOC_CTX: c->status = wreplsrv_out_connect_wait_assoc_ctx(state); c->state = COMPOSITE_STATE_DONE; break; case WREPLSRV_OUT_CONNECT_STAGE_DONE: c->status = NT_STATUS_INTERNAL_ERROR; } if (!NT_STATUS_IS_OK(c->status)) { c->state = COMPOSITE_STATE_ERROR; } if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); }}static void wreplsrv_out_connect_handler_creq(struct composite_context *creq){ struct wreplsrv_out_connect_state *state = talloc_get_type(creq->async.private_data, struct wreplsrv_out_connect_state); wreplsrv_out_connect_handler(state); return;}static void wreplsrv_out_connect_handler_req(struct wrepl_request *req){ struct wreplsrv_out_connect_state *state = talloc_get_type(req->async.private, struct wreplsrv_out_connect_state); wreplsrv_out_connect_handler(state); return;}static struct composite_context *wreplsrv_out_connect_send(struct wreplsrv_partner *partner, enum winsrepl_partner_type type, struct wreplsrv_out_connection *wreplconn){ struct composite_context *c = NULL; struct wreplsrv_service *service = partner->service; struct wreplsrv_out_connect_state *state = NULL; struct wreplsrv_out_connection **wreplconnp = &wreplconn; bool cached_connection = false; c = talloc_zero(partner, struct composite_context); if (!c) goto failed; state = talloc_zero(c, struct wreplsrv_out_connect_state); if (!state) goto failed; state->c = c; state->type = type; c->state = COMPOSITE_STATE_IN_PROGRESS; c->event_ctx = service->task->event_ctx; c->private_data = state; if (type == WINSREPL_PARTNER_PUSH) { cached_connection = true; wreplconn = partner->push.wreplconn; wreplconnp = &partner->push.wreplconn; } else if (type == WINSREPL_PARTNER_PULL) { cached_connection = true; wreplconn = partner->pull.wreplconn; wreplconnp = &partner->pull.wreplconn; } /* we have a connection already, so use it */ if (wreplconn) { if (!wreplconn->sock->dead) { state->stage = WREPLSRV_OUT_CONNECT_STAGE_DONE; state->wreplconn= wreplconn; composite_done(c); return c; } else if (!cached_connection) { state->stage = WREPLSRV_OUT_CONNECT_STAGE_DONE; state->wreplconn= NULL; composite_done(c); return c; } else { talloc_free(wreplconn); *wreplconnp = NULL; } } wreplconn = talloc_zero(state, struct wreplsrv_out_connection); if (!wreplconn) goto failed; wreplconn->service = service; wreplconn->partner = partner; wreplconn->sock = wrepl_socket_init(wreplconn, service->task->event_ctx, lp_iconv_convenience(service->task->lp_ctx)); if (!wreplconn->sock) goto failed; state->stage = WREPLSRV_OUT_CONNECT_STAGE_WAIT_SOCKET; state->wreplconn= wreplconn; state->c_req = wrepl_connect_send(wreplconn->sock, lp_resolve_context(service->task->lp_ctx), partner->our_address?partner->our_address:wrepl_best_ip(service->task->lp_ctx, partner->address), partner->address); if (!state->c_req) goto failed; state->c_req->async.fn = wreplsrv_out_connect_handler_creq; state->c_req->async.private_data = state; return c;failed: talloc_free(c); return NULL;}static NTSTATUS wreplsrv_out_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, struct wreplsrv_out_connection **wreplconn){ NTSTATUS status; status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { struct wreplsrv_out_connect_state *state = talloc_get_type(c->private_data, struct wreplsrv_out_connect_state); if (state->wreplconn) { *wreplconn = talloc_reference(mem_ctx, state->wreplconn); if (!*wreplconn) status = NT_STATUS_NO_MEMORY; } else { status = NT_STATUS_INVALID_CONNECTION; } } talloc_free(c); return status; }struct wreplsrv_pull_table_io { struct { struct wreplsrv_partner *partner; uint32_t num_owners; struct wrepl_wins_owner *owners; } in; struct { uint32_t num_owners; struct wrepl_wins_owner *owners; } out;};enum wreplsrv_pull_table_stage { WREPLSRV_PULL_TABLE_STAGE_WAIT_CONNECTION, WREPLSRV_PULL_TABLE_STAGE_WAIT_TABLE_REPLY, WREPLSRV_PULL_TABLE_STAGE_DONE};struct wreplsrv_pull_table_state { enum wreplsrv_pull_table_stage stage; struct composite_context *c; struct wrepl_request *req; struct wrepl_pull_table table_io; struct wreplsrv_pull_table_io *io; struct composite_context *creq; struct wreplsrv_out_connection *wreplconn;};static void wreplsrv_pull_table_handler_req(struct wrepl_request *req);static NTSTATUS wreplsrv_pull_table_wait_connection(struct wreplsrv_pull_table_state *state){ NTSTATUS status; status = wreplsrv_out_connect_recv(state->creq, state, &state->wreplconn); NT_STATUS_NOT_OK_RETURN(status); state->table_io.in.assoc_ctx = state->wreplconn->assoc_ctx.peer_ctx; state->req = wrepl_pull_table_send(state->wreplconn->sock, &state->table_io); NT_STATUS_HAVE_NO_MEMORY(state->req); state->req->async.fn = wreplsrv_pull_table_handler_req; state->req->async.private = state; state->stage = WREPLSRV_PULL_TABLE_STAGE_WAIT_TABLE_REPLY; return NT_STATUS_OK;}static NTSTATUS wreplsrv_pull_table_wait_table_reply(struct wreplsrv_pull_table_state *state){ NTSTATUS status; status = wrepl_pull_table_recv(state->req, state, &state->table_io); NT_STATUS_NOT_OK_RETURN(status); state->stage = WREPLSRV_PULL_TABLE_STAGE_DONE; return NT_STATUS_OK;}static void wreplsrv_pull_table_handler(struct wreplsrv_pull_table_state *state){ struct composite_context *c = state->c; switch (state->stage) { case WREPLSRV_PULL_TABLE_STAGE_WAIT_CONNECTION: c->status = wreplsrv_pull_table_wait_connection(state); break; case WREPLSRV_PULL_TABLE_STAGE_WAIT_TABLE_REPLY: c->status = wreplsrv_pull_table_wait_table_reply(state); c->state = COMPOSITE_STATE_DONE; break; case WREPLSRV_PULL_TABLE_STAGE_DONE: c->status = NT_STATUS_INTERNAL_ERROR; } if (!NT_STATUS_IS_OK(c->status)) { c->state = COMPOSITE_STATE_ERROR; } if (c->state >= COMPOSITE_STATE_DONE && c->async.fn) { c->async.fn(c); }}static void wreplsrv_pull_table_handler_creq(struct composite_context *creq){ struct wreplsrv_pull_table_state *state = talloc_get_type(creq->async.private_data, struct wreplsrv_pull_table_state); wreplsrv_pull_table_handler(state); return;}static void wreplsrv_pull_table_handler_req(struct wrepl_request *req){ struct wreplsrv_pull_table_state *state = talloc_get_type(req->async.private, struct wreplsrv_pull_table_state); wreplsrv_pull_table_handler(state); return;}static struct composite_context *wreplsrv_pull_table_send(TALLOC_CTX *mem_ctx, struct wreplsrv_pull_table_io *io){ struct composite_context *c = NULL; struct wreplsrv_service *service = io->in.partner->service; struct wreplsrv_pull_table_state *state = NULL; c = talloc_zero(mem_ctx, struct composite_context); if (!c) goto failed; state = talloc_zero(c, struct wreplsrv_pull_table_state); if (!state) goto failed; state->c = c; state->io = io; c->state = COMPOSITE_STATE_IN_PROGRESS; c->event_ctx = service->task->event_ctx; c->private_data = state; if (io->in.num_owners) { state->table_io.out.num_partners = io->in.num_owners; state->table_io.out.partners = io->in.owners; state->stage = WREPLSRV_PULL_TABLE_STAGE_DONE; composite_done(c); return c; } state->stage = WREPLSRV_PULL_TABLE_STAGE_WAIT_CONNECTION; state->creq = wreplsrv_out_connect_send(io->in.partner, WINSREPL_PARTNER_PULL, NULL); if (!state->creq) goto failed; state->creq->async.fn = wreplsrv_pull_table_handler_creq; state->creq->async.private_data = state; return c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -