process.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,793 行 · 第 1/4 页

C
1,793
字号
/*    Unix SMB/CIFS implementation.   process incoming packets - main loop   Copyright (C) Andrew Tridgell 1992-1998   Copyright (C) Volker Lendecke 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 2 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, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"extern uint16 global_smbpid;extern int keepalive;extern struct auth_context *negprot_global_auth_context;extern int smb_echo_count;struct timeval smb_last_time;static char *InBuffer = NULL;static char *OutBuffer = NULL;static char *current_inbuf = NULL;/*  * Size of data we can send to client. Set *  by the client for all protocols above CORE. *  Set by us for CORE protocol. */int max_send = BUFFER_SIZE;/* * Size of the data we can receive. Set by us. * Can be modified by the max xmit parameter. */int max_recv = BUFFER_SIZE;extern int last_message;extern userdom_struct current_user_info;extern int smb_read_error;SIG_ATOMIC_T reload_after_sighup = 0;SIG_ATOMIC_T got_sig_term = 0;extern BOOL global_machine_password_needs_changing;extern int max_send;/**************************************************************************** Function to return the current request mid from Inbuffer.****************************************************************************/uint16 get_current_mid(void){	return SVAL(InBuffer,smb_mid);}/**************************************************************************** structure to hold a linked list of queued messages. for processing.****************************************************************************/static struct pending_message_list *deferred_open_queue;/**************************************************************************** Function to push a message onto the tail of a linked list of smb messages ready for processing.****************************************************************************/static BOOL push_queued_message(char *buf, int msg_len,				struct timeval request_time,				struct timeval end_time,				char *private_data, size_t private_len){	struct pending_message_list *tmp_msg;	struct pending_message_list *msg;	msg = TALLOC_ZERO_P(NULL, struct pending_message_list);	if(msg == NULL) {		DEBUG(0,("push_message: malloc fail (1)\n"));		return False;	}	msg->buf = data_blob_talloc(msg, buf, msg_len);	if(msg->buf.data == NULL) {		DEBUG(0,("push_message: malloc fail (2)\n"));		talloc_free(msg);		return False;	}	msg->request_time = request_time;	msg->end_time = end_time;	if (private_data) {		msg->private_data = data_blob_talloc(msg, private_data,						     private_len);		if (msg->private_data.data == NULL) {			DEBUG(0,("push_message: malloc fail (3)\n"));			talloc_free(msg);			return False;		}	}	DLIST_ADD_END(deferred_open_queue, msg, tmp_msg);	DEBUG(10,("push_message: pushed message length %u on "		  "deferred_open_queue\n", (unsigned int)msg_len));	return True;}/**************************************************************************** Function to delete a sharing violation open message by mid.****************************************************************************/void remove_deferred_open_smb_message(uint16 mid){	struct pending_message_list *pml;	for (pml = deferred_open_queue; pml; pml = pml->next) {		if (mid == SVAL(pml->buf.data,smb_mid)) {			DEBUG(10,("remove_sharing_violation_open_smb_message: "				  "deleting mid %u len %u\n",				  (unsigned int)mid,				  (unsigned int)pml->buf.length ));			DLIST_REMOVE(deferred_open_queue, pml);			talloc_free(pml);			return;		}	}}/**************************************************************************** Move a sharing violation open retry message to the front of the list and schedule it for immediate processing.****************************************************************************/void schedule_deferred_open_smb_message(uint16 mid){	struct pending_message_list *pml;	int i = 0;	for (pml = deferred_open_queue; pml; pml = pml->next) {		uint16 msg_mid = SVAL(pml->buf.data,smb_mid);		DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,			(unsigned int)msg_mid ));		if (mid == msg_mid) {			DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",				mid ));			pml->end_time.tv_sec = 0;			pml->end_time.tv_usec = 0;			DLIST_PROMOTE(deferred_open_queue, pml);			return;		}	}	DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",		mid ));}/**************************************************************************** Return true if this mid is on the deferred queue.****************************************************************************/BOOL open_was_deferred(uint16 mid){	struct pending_message_list *pml;	for (pml = deferred_open_queue; pml; pml = pml->next) {		if (SVAL(pml->buf.data,smb_mid) == mid) {			set_saved_ntstatus(NT_STATUS_OK);			return True;		}	}	return False;}/**************************************************************************** Return the message queued by this mid.****************************************************************************/struct pending_message_list *get_open_deferred_message(uint16 mid){	struct pending_message_list *pml;	for (pml = deferred_open_queue; pml; pml = pml->next) {		if (SVAL(pml->buf.data,smb_mid) == mid) {			return pml;		}	}	return NULL;}/**************************************************************************** Function to push a deferred open smb message onto a linked list of local smb messages ready for processing.****************************************************************************/BOOL push_deferred_smb_message(uint16 mid,			       struct timeval request_time,			       struct timeval timeout,			       char *private_data, size_t priv_len){	struct timeval end_time;	end_time = timeval_sum(&request_time, &timeout);	DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "		  "timeout time [%u.%06u]\n",		  (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,		  (unsigned int)end_time.tv_sec,		  (unsigned int)end_time.tv_usec));	return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,				   request_time, end_time,				   private_data, priv_len);}static struct timed_event *timed_events;struct timed_event {	struct timed_event *next, *prev;	struct timeval when;	const char *event_name;	void (*handler)(struct timed_event *te,			const struct timeval *now,			void *private_data);	void *private_data;};static int timed_event_destructor(void *p){	struct timed_event *te = talloc_get_type_abort(p, struct timed_event);	DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,		   te->event_name));	DLIST_REMOVE(timed_events, te);	return 0;}/**************************************************************************** Schedule a function for future calling, cancel with talloc_free(). It's the responsibility of the handler to call talloc_free() on the event  handed to it.****************************************************************************/struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,				    struct timeval when,				    const char *event_name,				    void (*handler)(struct timed_event *te,						    const struct timeval *now,						    void *private_data),				    void *private_data){	struct timed_event *te, *last_te, *cur_te;	te = TALLOC_P(mem_ctx, struct timed_event);	if (te == NULL) {		DEBUG(0, ("talloc failed\n"));		return NULL;	}	te->when = when;	te->event_name = event_name;	te->handler = handler;	te->private_data = private_data;	/* keep the list ordered */	last_te = NULL;	for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {		/* if the new event comes before the current one break */		if (!timeval_is_zero(&cur_te->when) &&		    timeval_compare(&te->when, &cur_te->when) < 0) {			break;		}		last_te = cur_te;	}	DLIST_ADD_AFTER(timed_events, te, last_te);	talloc_set_destructor(te, timed_event_destructor);	DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,		   (unsigned long)te));	return te;}static void run_events(void){	struct timeval now;	if (timed_events == NULL) {		/* No syscall if there are no events */		DEBUG(10, ("run_events: No events\n"));		return;	}	GetTimeOfDay(&now);	if (timeval_compare(&now, &timed_events->when) < 0) {		/* Nothing to do yet */		DEBUG(10, ("run_events: Nothing to do\n"));		return;	}	DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,		   (unsigned long)timed_events));	timed_events->handler(timed_events, &now, timed_events->private_data);	return;}struct timeval timed_events_timeout(void){	struct timeval now, timeout;	if (timed_events == NULL) {		return timeval_set(SMBD_SELECT_TIMEOUT, 0);	}	now = timeval_current();	timeout = timeval_until(&now, &timed_events->when);	DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec,		   (int)timeout.tv_usec));	return timeout;}struct idle_event {	struct timed_event *te;	struct timeval interval;	BOOL (*handler)(const struct timeval *now, void *private_data);	void *private_data;};static void idle_event_handler(struct timed_event *te,			       const struct timeval *now,			       void *private_data){	struct idle_event *event =		talloc_get_type_abort(private_data, struct idle_event);	talloc_free(event->te);	if (!event->handler(now, event->private_data)) {		/* Don't repeat, delete ourselves */		talloc_free(event);		return;	}	event->te = add_timed_event(event, timeval_sum(now, &event->interval),				    "idle_event_handler",				    idle_event_handler, event);	/* We can't do much but fail here. */	SMB_ASSERT(event->te != NULL);}struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,				  struct timeval interval,				  BOOL (*handler)(const struct timeval *now,						  void *private_data),				  void *private_data){	struct idle_event *result;	struct timeval now = timeval_current();	result = TALLOC_P(mem_ctx, struct idle_event);	if (result == NULL) {		DEBUG(0, ("talloc failed\n"));		return NULL;	}	result->interval = interval;	result->handler = handler;	result->private_data = private_data;	result->te = add_timed_event(result, timeval_sum(&now, &interval),				     "idle_event_handler",				     idle_event_handler, result);	if (result->te == NULL) {		DEBUG(0, ("add_timed_event failed\n"));		talloc_free(result);		return NULL;	}	return result;}	/**************************************************************************** Do all async processing in here. This includes kernel oplock messages, change notify events etc.****************************************************************************/static void async_processing(fd_set *pfds){	DEBUG(10,("async_processing: Doing async processing.\n"));	process_aio_queue();	process_kernel_oplocks(pfds);	/* Do the aio check again after receive_local_message as it does a	   select and may have eaten our signal. */	/* Is this till true? -- vl */	process_aio_queue();	if (got_sig_term) {		exit_server("Caught TERM signal");	}	/* check for async change notify events */	process_pending_change_notify_queue(0);	/* check for sighup processing */	if (reload_after_sighup) {		change_to_root_user();		DEBUG(1,("Reloading services after SIGHUP\n"));		reload_services(False);		reload_after_sighup = 0;	}}/****************************************************************************  Do a select on an two fd's - with timeout.   If a local udp message has been pushed onto the  queue (this can only happen during oplock break  processing) call async_processing()  If a pending smb message has been pushed onto the  queue (this can only happen during oplock break  processing) return this next.  If the first smbfd is ready then read an smb from it.  if the second (loopback UDP) fd is ready then read a message  from it and setup the buffer header to identify the length  and from address.  Returns False on timeout or error.  Else returns True.The timeout is in milliseconds****************************************************************************/

⌨️ 快捷键说明

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