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 + -
显示快捷键?