winsrepl.c
来自「samba最新软件」· C语言 代码 · 共 874 行 · 第 1/2 页
C
874 行
struct wrepl_request *req; struct wrepl_socket *wrepl_sock;};static int wrepl_send_ctrl_destructor(struct wrepl_send_ctrl_state *s){ struct wrepl_request *req = s->wrepl_sock->recv_queue; /* check if the request is still in WREPL_STATE_RECV, * we need this here because the caller has may called * talloc_free(req) and wrepl_send_ctrl_state isn't * a talloc child of the request, so our s->req pointer * is maybe invalid! */ for (; req; req = req->next) { if (req == s->req) break; } if (!req) return 0; /* here, we need to make sure the async request handler is called * later in the next event_loop and now now */ req->trigger = true; wrepl_request_finished(req, NT_STATUS_OK); if (s->ctrl.disconnect_after_send) { wrepl_socket_dead(s->wrepl_sock, NT_STATUS_LOCAL_DISCONNECT); } return 0;}/* send a generic wins replication request*/struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket, struct wrepl_packet *packet, struct wrepl_send_ctrl *ctrl){ struct wrepl_request *req; struct wrepl_wrap wrap; DATA_BLOB blob; NTSTATUS status; enum ndr_err_code ndr_err; req = talloc_zero(wrepl_socket, struct wrepl_request); if (!req) return NULL; req->wrepl_socket = wrepl_socket; req->state = WREPL_REQUEST_RECV; req->trigger = true; DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *); talloc_set_destructor(req, wrepl_request_destructor); if (wrepl_socket->dead) { return wrepl_request_finished(req, NT_STATUS_INVALID_CONNECTION); } wrap.packet = *packet; ndr_err = ndr_push_struct_blob(&blob, req, wrepl_socket->iconv_convenience, &wrap, (ndr_push_flags_fn_t)ndr_push_wrepl_wrap); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); return wrepl_request_finished(req, status); } if (DEBUGLVL(10)) { DEBUG(10,("Sending WINS packet of length %u\n", (unsigned)blob.length)); NDR_PRINT_DEBUG(wrepl_packet, &wrap.packet); } if (wrepl_socket->request_timeout > 0) { req->te = event_add_timed(wrepl_socket->event.ctx, req, timeval_current_ofs(wrepl_socket->request_timeout, 0), wrepl_request_timeout_handler, req); if (!req->te) return wrepl_request_finished(req, NT_STATUS_NO_MEMORY); } if (ctrl && (ctrl->send_only || ctrl->disconnect_after_send)) { struct wrepl_send_ctrl_state *s = talloc(blob.data, struct wrepl_send_ctrl_state); if (!s) return wrepl_request_finished(req, NT_STATUS_NO_MEMORY); s->ctrl = *ctrl; s->req = req; s->wrepl_sock = wrepl_socket; talloc_set_destructor(s, wrepl_send_ctrl_destructor); } status = packet_send(wrepl_socket->packet, blob); if (!NT_STATUS_IS_OK(status)) { return wrepl_request_finished(req, status); } req->trigger = false; return req;}/* receive a generic WINS replication reply*/NTSTATUS wrepl_request_recv(struct wrepl_request *req, TALLOC_CTX *mem_ctx, struct wrepl_packet **packet){ NTSTATUS status = wrepl_request_wait(req); if (NT_STATUS_IS_OK(status) && packet) { *packet = talloc_steal(mem_ctx, req->packet); } talloc_free(req); return status;}/* a full WINS replication request/response*/NTSTATUS wrepl_request(struct wrepl_socket *wrepl_socket, TALLOC_CTX *mem_ctx, struct wrepl_packet *req_packet, struct wrepl_packet **reply_packet){ struct wrepl_request *req = wrepl_request_send(wrepl_socket, req_packet, NULL); return wrepl_request_recv(req, mem_ctx, reply_packet);}/* setup an association - send*/struct wrepl_request *wrepl_associate_send(struct wrepl_socket *wrepl_socket, struct wrepl_associate *io){ struct wrepl_packet *packet; struct wrepl_request *req; packet = talloc_zero(wrepl_socket, struct wrepl_packet); if (packet == NULL) return NULL; packet->opcode = WREPL_OPCODE_BITS; packet->mess_type = WREPL_START_ASSOCIATION; packet->message.start.minor_version = 2; packet->message.start.major_version = 5; /* * nt4 uses 41 bytes for the start_association call * so do it the same and as we don't know th emeanings of this bytes * we just send zeros and nt4, w2k and w2k3 seems to be happy with this * * if we don't do this nt4 uses an old version of the wins replication protocol * and that would break nt4 <-> samba replication */ packet->padding = data_blob_talloc(packet, NULL, 21); if (packet->padding.data == NULL) { talloc_free(packet); return NULL; } memset(packet->padding.data, 0, packet->padding.length); req = wrepl_request_send(wrepl_socket, packet, NULL); talloc_free(packet); return req; }/* setup an association - recv*/NTSTATUS wrepl_associate_recv(struct wrepl_request *req, struct wrepl_associate *io){ struct wrepl_packet *packet=NULL; NTSTATUS status; status = wrepl_request_recv(req, req->wrepl_socket, &packet); NT_STATUS_NOT_OK_RETURN(status); if (packet->mess_type != WREPL_START_ASSOCIATION_REPLY) { status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; } if (NT_STATUS_IS_OK(status)) { io->out.assoc_ctx = packet->message.start_reply.assoc_ctx; } talloc_free(packet); return status;}/* setup an association - sync api*/NTSTATUS wrepl_associate(struct wrepl_socket *wrepl_socket, struct wrepl_associate *io){ struct wrepl_request *req = wrepl_associate_send(wrepl_socket, io); return wrepl_associate_recv(req, io);}/* stop an association - send*/struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socket, struct wrepl_associate_stop *io){ struct wrepl_packet *packet; struct wrepl_request *req; struct wrepl_send_ctrl ctrl; packet = talloc_zero(wrepl_socket, struct wrepl_packet); if (packet == NULL) return NULL; packet->opcode = WREPL_OPCODE_BITS; packet->assoc_ctx = io->in.assoc_ctx; packet->mess_type = WREPL_STOP_ASSOCIATION; packet->message.stop.reason = io->in.reason; ZERO_STRUCT(ctrl); if (io->in.reason == 0) { ctrl.send_only = true; ctrl.disconnect_after_send = true; } req = wrepl_request_send(wrepl_socket, packet, &ctrl); talloc_free(packet); return req; }/* stop an association - recv*/NTSTATUS wrepl_associate_stop_recv(struct wrepl_request *req, struct wrepl_associate_stop *io){ struct wrepl_packet *packet=NULL; NTSTATUS status; status = wrepl_request_recv(req, req->wrepl_socket, &packet); NT_STATUS_NOT_OK_RETURN(status); talloc_free(packet); return status;}/* setup an association - sync api*/NTSTATUS wrepl_associate_stop(struct wrepl_socket *wrepl_socket, struct wrepl_associate_stop *io){ struct wrepl_request *req = wrepl_associate_stop_send(wrepl_socket, io); return wrepl_associate_stop_recv(req, io);}/* fetch the partner tables - send*/struct wrepl_request *wrepl_pull_table_send(struct wrepl_socket *wrepl_socket, struct wrepl_pull_table *io){ struct wrepl_packet *packet; struct wrepl_request *req; packet = talloc_zero(wrepl_socket, struct wrepl_packet); if (packet == NULL) return NULL; packet->opcode = WREPL_OPCODE_BITS; packet->assoc_ctx = io->in.assoc_ctx; packet->mess_type = WREPL_REPLICATION; packet->message.replication.command = WREPL_REPL_TABLE_QUERY; req = wrepl_request_send(wrepl_socket, packet, NULL); talloc_free(packet); return req; }/* fetch the partner tables - recv*/NTSTATUS wrepl_pull_table_recv(struct wrepl_request *req, TALLOC_CTX *mem_ctx, struct wrepl_pull_table *io){ struct wrepl_packet *packet=NULL; NTSTATUS status; struct wrepl_table *table; int i; status = wrepl_request_recv(req, req->wrepl_socket, &packet); NT_STATUS_NOT_OK_RETURN(status); if (packet->mess_type != WREPL_REPLICATION) { status = NT_STATUS_NETWORK_ACCESS_DENIED; } else if (packet->message.replication.command != WREPL_REPL_TABLE_REPLY) { status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; } if (!NT_STATUS_IS_OK(status)) goto failed; table = &packet->message.replication.info.table; io->out.num_partners = table->partner_count; io->out.partners = talloc_steal(mem_ctx, table->partners); for (i=0;i<io->out.num_partners;i++) { talloc_steal(io->out.partners, io->out.partners[i].address); }failed: talloc_free(packet); return status;}/* fetch the partner table - sync api*/NTSTATUS wrepl_pull_table(struct wrepl_socket *wrepl_socket, TALLOC_CTX *mem_ctx, struct wrepl_pull_table *io){ struct wrepl_request *req = wrepl_pull_table_send(wrepl_socket, io); return wrepl_pull_table_recv(req, mem_ctx, io);}/* fetch the names for a WINS partner - send*/struct wrepl_request *wrepl_pull_names_send(struct wrepl_socket *wrepl_socket, struct wrepl_pull_names *io){ struct wrepl_packet *packet; struct wrepl_request *req; packet = talloc_zero(wrepl_socket, struct wrepl_packet); if (packet == NULL) return NULL; packet->opcode = WREPL_OPCODE_BITS; packet->assoc_ctx = io->in.assoc_ctx; packet->mess_type = WREPL_REPLICATION; packet->message.replication.command = WREPL_REPL_SEND_REQUEST; packet->message.replication.info.owner = io->in.partner; req = wrepl_request_send(wrepl_socket, packet, NULL); talloc_free(packet); return req; }/* fetch the names for a WINS partner - recv*/NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req, TALLOC_CTX *mem_ctx, struct wrepl_pull_names *io){ struct wrepl_packet *packet=NULL; NTSTATUS status; int i; status = wrepl_request_recv(req, req->wrepl_socket, &packet); NT_STATUS_NOT_OK_RETURN(status); if (packet->mess_type != WREPL_REPLICATION || packet->message.replication.command != WREPL_REPL_SEND_REPLY) { status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; } if (!NT_STATUS_IS_OK(status)) goto failed; io->out.num_names = packet->message.replication.info.reply.num_names; io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names); if (io->out.names == NULL) goto nomem; /* convert the list of names and addresses to a sane format */ for (i=0;i<io->out.num_names;i++) { struct wrepl_wins_name *wname = &packet->message.replication.info.reply.names[i]; struct wrepl_name *name = &io->out.names[i]; name->name = *wname->name; talloc_steal(io->out.names, wname->name); name->type = WREPL_NAME_TYPE(wname->flags); name->state = WREPL_NAME_STATE(wname->flags); name->node = WREPL_NAME_NODE(wname->flags); name->is_static = WREPL_NAME_IS_STATIC(wname->flags); name->raw_flags = wname->flags; name->version_id= wname->id; name->owner = talloc_strdup(io->out.names, io->in.partner.address); if (name->owner == NULL) goto nomem; /* trying to save 1 or 2 bytes on the wire isn't a good idea */ if (wname->flags & 2) { int j; name->num_addresses = wname->addresses.addresses.num_ips; name->addresses = talloc_array(io->out.names, struct wrepl_address, name->num_addresses); if (name->addresses == NULL) goto nomem; for (j=0;j<name->num_addresses;j++) { name->addresses[j].owner = talloc_steal(name->addresses, wname->addresses.addresses.ips[j].owner); name->addresses[j].address = talloc_steal(name->addresses, wname->addresses.addresses.ips[j].ip); } } else { name->num_addresses = 1; name->addresses = talloc(io->out.names, struct wrepl_address); if (name->addresses == NULL) goto nomem; name->addresses[0].owner = talloc_strdup(name->addresses,io->in.partner.address); if (name->addresses[0].owner == NULL) goto nomem; name->addresses[0].address = talloc_steal(name->addresses, wname->addresses.ip); } } talloc_steal(mem_ctx, io->out.names); talloc_free(packet); return NT_STATUS_OK;nomem: status = NT_STATUS_NO_MEMORY;failed: talloc_free(packet); return status;}/* fetch the names for a WINS partner - sync api*/NTSTATUS wrepl_pull_names(struct wrepl_socket *wrepl_socket, TALLOC_CTX *mem_ctx, struct wrepl_pull_names *io){ struct wrepl_request *req = wrepl_pull_names_send(wrepl_socket, io); return wrepl_pull_names_recv(req, mem_ctx, io);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?