server.c

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

C
671
字号
/*    Unix SMB/CIFS implementation.   Main SMB server routines   Copyright (C) Jean Fran鏾is Micouleau      1998-2002.      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"#include "wins_repl.h"extern pstring user_socket_options;extern WINS_OWNER *global_wins_table;extern int partner_count;extern fd_set *listen_set;extern int listen_number;extern int *sock_array;extern TALLOC_CTX *mem_ctx;int wins_port = 42;/****************************************************************************  when exiting, take the whole family****************************************************************************/static void *dflt_sig(void){	exit_server("caught signal");	return NULL;}/****************************************************************************  reload the services file  **************************************************************************/BOOL reload_services(BOOL test){	BOOL ret;		if (lp_loaded()) {		pstring fname;		pstrcpy(fname,lp_configfile());		if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {			pstrcpy(dyn_CONFIGFILE,fname);			test = False;		}	}	reopen_logs();	if (test && !lp_file_list_changed())		return(True);	ret = lp_load(dyn_CONFIGFILE,False,False,True);	/* perhaps the config filename is now set */	if (!test)		reload_services(True);	reopen_logs();	load_interfaces();	return(ret);}/**************************************************************************** Catch a sighup.****************************************************************************/VOLATILE sig_atomic_t reload_after_sighup = False;static void sig_hup(int sig){	BlockSignals(True,SIGHUP);	DEBUG(0,("Got SIGHUP\n"));	sys_select_signal(SIGHUP);	reload_after_sighup = True;	BlockSignals(False,SIGHUP);}#if DUMP_CORE/*******************************************************************prepare to dump a core file - carefully!********************************************************************/static BOOL dump_core(void){	char *p;	pstring dname;	pstrcpy(dname,lp_logfile());	if ((p=strrchr_m(dname,'/'))) *p=0;	pstrcat(dname,"/corefiles");	mkdir(dname,0700);	sys_chown(dname,getuid(),getgid());	chmod(dname,0700);	if (chdir(dname)) return(False);	umask(~(0700));#ifdef HAVE_GETRLIMIT#ifdef RLIMIT_CORE	{		struct rlimit rlp;		getrlimit(RLIMIT_CORE, &rlp);		rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);		setrlimit(RLIMIT_CORE, &rlp);		getrlimit(RLIMIT_CORE, &rlp);		DEBUG(3,("Core limits now %d %d\n",			 (int)rlp.rlim_cur,(int)rlp.rlim_max));	}#endif#endif	DEBUG(0,("Dumping core in %s\n",dname));	abort();	return(True);}#endif/****************************************************************************exit the server****************************************************************************/void exit_server(const char *reason){	static int firsttime=1;	if (!firsttime)		exit(0);	firsttime = 0;	DEBUG(2,("Closing connections\n"));	if (!reason) {   		int oldlevel = DEBUGLEVEL;		DEBUGLEVEL = 10;		DEBUGLEVEL = oldlevel;		DEBUG(0,("===============================================================\n"));#if DUMP_CORE		if (dump_core()) return;#endif	}	DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));	exit(0);}/****************************************************************************  Create an fd_set containing all the sockets in the subnet structures,  plus the broadcast sockets.***************************************************************************/static BOOL create_listen_fdset( int *maxfd){	int i;	int num_interfaces = iface_count();	int s;	listen_set = (fd_set *)malloc(sizeof(fd_set));	if(listen_set == NULL) {		DEBUG(0,("create_listen_fdset: malloc fail !\n"));		return True;	}#ifdef HAVE_ATEXIT	{		static int atexit_set;		if(atexit_set == 0) {			atexit_set=1;		}	}#endif	FD_ZERO(listen_set);	if(lp_interfaces() && lp_bind_interfaces_only()) {		/* 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.		*/				if(num_interfaces > FD_SETSIZE) {			DEBUG(0,("create_listen_fdset: Too many interfaces specified to bind to. Number was %d max can be %d\n", num_interfaces, FD_SETSIZE));			return False;		}		/* Now open a listen socket for each of the interfaces. */		for(i = 0; i < num_interfaces; i++) {			struct in_addr *ifip = iface_n_ip(i);						if(ifip == NULL) {				DEBUG(0,("create_listen_fdset: interface %d has NULL IP address !\n", i));				continue;			}			s = open_socket_in(SOCK_STREAM, wins_port, 0, ifip->s_addr, True);			if(s == -1)				return False;			/* ready to listen */			set_socket_options(s,"SO_KEEPALIVE"); 			set_socket_options(s,user_socket_options);      			if (listen(s, 5) == -1) {				DEBUG(5,("listen: %s\n",strerror(errno)));				close(s);				return False;			}			add_fd_to_sock_array(s);			FD_SET(s, listen_set);			*maxfd = MAX( *maxfd, s);		}	} else {		/* Just bind to 0.0.0.0 - accept connections from anywhere. */		num_interfaces = 1;				/* open an incoming socket */		s = open_socket_in(SOCK_STREAM, wins_port, 0, interpret_addr(lp_socket_address()),True);		if (s == -1)			return(False);				/* ready to listen */		set_socket_options(s,"SO_KEEPALIVE"); 		set_socket_options(s,user_socket_options);		if (listen(s, 5) == -1) {			DEBUG(0,("create_listen_fdset: listen: %s\n", strerror(errno)));			close(s);			return False;		}				add_fd_to_sock_array(s);		FD_SET(s, listen_set);		*maxfd = MAX( *maxfd, s);	} 	return True;}/*******************************************************************  read a packet from a socket and parse it, returning a packet ready  to be used or put on the queue. This assumes a UDP socket  ******************************************************************/static struct wins_packet_struct *read_wins_packet(int fd, int timeout){	struct wins_packet_struct *p;	GENERIC_PACKET *q;	struct BUFFER inbuf;	ssize_t len=0;	size_t total=0;  	ssize_t ret;	BOOL ok = False;	inbuf.buffer=NULL;	inbuf.length=0;	inbuf.offset=0;	if(!grow_buffer(&inbuf, 4))		return NULL;	ok = (read(fd, inbuf.buffer,4) == 4);	if (!ok)		return NULL;	len = smb_len(inbuf.buffer);	if (len<=0)		return NULL;	if(!grow_buffer(&inbuf, len))		return NULL;			while (total < len) {		ret = read(fd, inbuf.buffer + total + 4, len - total);		if (ret == 0) {			DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(len - total), strerror(errno) ));			return NULL;		}		if (ret == -1) {			DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(len - total), strerror(errno) ));			return NULL;		}		total += ret;	}	q = talloc(mem_ctx, GENERIC_PACKET);	p = talloc(mem_ctx, struct wins_packet_struct);	if (q==NULL || p==NULL)		return NULL;	decode_generic_packet(&inbuf, q);	q->fd=fd;		p->next = NULL;	p->prev = NULL;	p->stop_packet = False;	p->timestamp = time(NULL);	p->fd = fd;	p->packet=q;		return p;}static struct wins_packet_struct *packet_queue = NULL;/*******************************************************************  Queue a packet into a packet queue******************************************************************/static void queue_packet(struct wins_packet_struct *packet){	struct wins_packet_struct *p;	if (!packet_queue) {		packet->prev = NULL;		packet->next = NULL;		packet_queue = packet;		return;	}  	/* find the bottom */	for (p=packet_queue;p->next;p=p->next) 		;

⌨️ 快捷键说明

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