⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrepl_in_connection.c

📁 samba最新软件
💻 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/socket/socket.h"#include "lib/stream/packet.h"#include "smbd/service_task.h"#include "smbd/service_stream.h"#include "smbd/service.h"#include "lib/messaging/irpc.h"#include "librpc/gen_ndr/ndr_winsrepl.h"#include "wrepl_server/wrepl_server.h"#include "smbd/process_model.h"#include "system/network.h"#include "lib/socket/netif.h"#include "param/param.h"void wreplsrv_terminate_in_connection(struct wreplsrv_in_connection *wreplconn, const char *reason){	stream_terminate_connection(wreplconn->conn, reason);}static int terminate_after_send_destructor(struct wreplsrv_in_connection **tas){	wreplsrv_terminate_in_connection(*tas, "wreplsrv_in_connection: terminate_after_send");	return 0;}/*  receive some data on a WREPL connection*/static NTSTATUS wreplsrv_recv_request(void *private, DATA_BLOB blob){	struct wreplsrv_in_connection *wreplconn = talloc_get_type(private, struct wreplsrv_in_connection);	struct wreplsrv_in_call *call;	DATA_BLOB packet_in_blob;	DATA_BLOB packet_out_blob;	struct wrepl_wrap packet_out_wrap;	NTSTATUS status;	enum ndr_err_code ndr_err;	call = talloc_zero(wreplconn, struct wreplsrv_in_call);	NT_STATUS_HAVE_NO_MEMORY(call);	call->wreplconn = wreplconn;	talloc_steal(call, blob.data);	packet_in_blob.data = blob.data + 4;	packet_in_blob.length = blob.length - 4;	ndr_err = ndr_pull_struct_blob(&packet_in_blob, call, 				       lp_iconv_convenience(wreplconn->service->task->lp_ctx),				       &call->req_packet,				       (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return ndr_map_error2ntstatus(ndr_err);	}	if (DEBUGLVL(10)) {		DEBUG(10,("Received WINS-Replication packet of length %u\n", 			  (unsigned)packet_in_blob.length + 4));		NDR_PRINT_DEBUG(wrepl_packet, &call->req_packet);	}	status = wreplsrv_in_call(call);	NT_STATUS_IS_ERR_RETURN(status);	if (!NT_STATUS_IS_OK(status)) {		/* w2k just ignores invalid packets, so we do */		DEBUG(10,("Received WINS-Replication packet was invalid, we just ignore it\n"));		talloc_free(call);		return NT_STATUS_OK;	}	/* and now encode the reply */	packet_out_wrap.packet = call->rep_packet;	ndr_err = ndr_push_struct_blob(&packet_out_blob, call, 				       lp_iconv_convenience(wreplconn->service->task->lp_ctx),				       &packet_out_wrap,				      (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return ndr_map_error2ntstatus(ndr_err);	}	if (DEBUGLVL(10)) {		DEBUG(10,("Sending WINS-Replication packet of length %d\n", (int)packet_out_blob.length));		NDR_PRINT_DEBUG(wrepl_packet, &call->rep_packet);	}	if (call->terminate_after_send) {		struct wreplsrv_in_connection **tas;		tas = talloc(packet_out_blob.data, struct wreplsrv_in_connection *);		NT_STATUS_HAVE_NO_MEMORY(tas);		*tas = wreplconn;		talloc_set_destructor(tas, terminate_after_send_destructor);	}	status = packet_send(wreplconn->packet, packet_out_blob);	NT_STATUS_NOT_OK_RETURN(status);	talloc_free(call);	return NT_STATUS_OK;}/*  called when the socket becomes readable*/static void wreplsrv_recv(struct stream_connection *conn, uint16_t flags){	struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private,								   struct wreplsrv_in_connection);	packet_recv(wreplconn->packet);}/*  called when the socket becomes writable*/static void wreplsrv_send(struct stream_connection *conn, uint16_t flags){	struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private,								   struct wreplsrv_in_connection);	packet_queue_run(wreplconn->packet);}/*  handle socket recv errors*/static void wreplsrv_recv_error(void *private, NTSTATUS status){	struct wreplsrv_in_connection *wreplconn = talloc_get_type(private,								   struct wreplsrv_in_connection);	wreplsrv_terminate_in_connection(wreplconn, nt_errstr(status));}/*  called when we get a new connection*/static void wreplsrv_accept(struct stream_connection *conn){	struct wreplsrv_service *service = talloc_get_type(conn->private, struct wreplsrv_service);	struct wreplsrv_in_connection *wreplconn;	struct socket_address *peer_ip;	wreplconn = talloc_zero(conn, struct wreplsrv_in_connection);	if (!wreplconn) {		stream_terminate_connection(conn, "wreplsrv_accept: out of memory");		return;	}	wreplconn->packet = packet_init(wreplconn);	if (!wreplconn->packet) {		wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory");		return;	}	packet_set_private(wreplconn->packet, wreplconn);	packet_set_socket(wreplconn->packet, conn->socket);	packet_set_callback(wreplconn->packet, wreplsrv_recv_request);	packet_set_full_request(wreplconn->packet, packet_full_request_u32);	packet_set_error_handler(wreplconn->packet, wreplsrv_recv_error);	packet_set_event_context(wreplconn->packet, conn->event.ctx);	packet_set_fde(wreplconn->packet, conn->event.fde);	packet_set_serialise(wreplconn->packet);	wreplconn->conn		= conn;	wreplconn->service	= service;	peer_ip	= socket_get_peer_addr(conn->socket, wreplconn);	if (!peer_ip) {		wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: could not obtain peer IP from kernel");		return;	}	wreplconn->partner	= wreplsrv_find_partner(service, peer_ip->addr);	conn->private = wreplconn;	irpc_add_name(conn->msg_ctx, "wreplsrv_connection");}static const struct stream_server_ops wreplsrv_stream_ops = {	.name			= "wreplsrv",	.accept_connection	= wreplsrv_accept,	.recv_handler		= wreplsrv_recv,	.send_handler		= wreplsrv_send,};/*  called when we get a new connection*/NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,				      struct socket_context *sock,				      struct packet_context *packet,				      struct wreplsrv_in_connection **_wrepl_in){	struct wreplsrv_service *service = partner->service;	struct wreplsrv_in_connection *wrepl_in;	const struct model_ops *model_ops;	struct stream_connection *conn;	NTSTATUS status;	/* within the wrepl task we want to be a single process, so	   ask for the single process model ops and pass these to the	   stream_setup_socket() call. */	model_ops = process_model_byname("single");	if (!model_ops) {		DEBUG(0,("Can't find 'single' process model_ops"));		return NT_STATUS_INTERNAL_ERROR;	}	wrepl_in = talloc_zero(partner, struct wreplsrv_in_connection);	NT_STATUS_HAVE_NO_MEMORY(wrepl_in);	wrepl_in->service	= service;	wrepl_in->partner	= partner;	status = stream_new_connection_merge(service->task->event_ctx, service->task->lp_ctx, model_ops,					     sock, &wreplsrv_stream_ops, service->task->msg_ctx,					     wrepl_in, &conn);	NT_STATUS_NOT_OK_RETURN(status);	/*	 * make the wreplsrv_in_connection structure a child of the 	 * stream_connection, to match the hierachie of wreplsrv_accept	 */	wrepl_in->conn		= conn;	talloc_steal(conn, wrepl_in);	/*	 * now update the packet handling callback,...	 */	wrepl_in->packet	= talloc_steal(wrepl_in, packet);	packet_set_private(wrepl_in->packet, wrepl_in);	packet_set_socket(wrepl_in->packet, conn->socket);	packet_set_callback(wrepl_in->packet, wreplsrv_recv_request);	packet_set_full_request(wrepl_in->packet, packet_full_request_u32);	packet_set_error_handler(wrepl_in->packet, wreplsrv_recv_error);	packet_set_event_context(wrepl_in->packet, conn->event.ctx);	packet_set_fde(wrepl_in->packet, conn->event.fde);	packet_set_serialise(wrepl_in->packet);	*_wrepl_in = wrepl_in;	return NT_STATUS_OK;}/*  startup the wrepl port 42 server sockets*/NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadparm_context *lp_ctx){	NTSTATUS status;	struct task_server *task = service->task;	const struct model_ops *model_ops;	const char *address;	uint16_t port = WINS_REPLICATION_PORT;	/* within the wrepl task we want to be a single process, so	   ask for the single process model ops and pass these to the	   stream_setup_socket() call. */	model_ops = process_model_byname("single");	if (!model_ops) {		DEBUG(0,("Can't find 'single' process model_ops"));		return NT_STATUS_INTERNAL_ERROR;	}	if (lp_interfaces(lp_ctx) && lp_bind_interfaces_only(lp_ctx)) {		int num_interfaces;		int i;		struct interface *ifaces;		load_interfaces(task, lp_interfaces(lp_ctx), &ifaces);		num_interfaces = iface_count(ifaces);		/* We have been given an interfaces line, and been 		   told to only bind to those interfaces. Create a		   socket per interface and bind to only these.		*/		for(i = 0; i < num_interfaces; i++) {			address = iface_n_ip(ifaces, i);			status = stream_setup_socket(task->event_ctx, 						     task->lp_ctx, model_ops, 						     &wreplsrv_stream_ops,						     "ipv4", address, &port, 				     	              lp_socket_options(task->lp_ctx), 						     service);			if (!NT_STATUS_IS_OK(status)) {				DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",					 address, port, nt_errstr(status)));				return status;			}		}	} else {		address = lp_socket_address(lp_ctx);		status = stream_setup_socket(task->event_ctx, task->lp_ctx, 					     model_ops, &wreplsrv_stream_ops,					     "ipv4", address, &port, lp_socket_options(task->lp_ctx), 					     service);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",				 address, port, nt_errstr(status)));			return status;		}	}	return NT_STATUS_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -