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

📄 sockd.c

📁 sock protocol ,it is useful!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1997, 1998, 1999 *      Inferno Nettverk A/S, Norway.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following *    disclaimer must appear in all copies of the software, derivative works *    or modified versions, and any portions thereof, aswell as in all *    supporting documentation. * 2. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by *      Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * *  Software Distribution Coordinator  or  sdc@inet.no *  Inferno Nettverk A/S *  Oslo Research Park *  Gaustadal閑n 21 *  N-0349 Oslo *  Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"static const char rcsid[] ="$Id: sockd.c,v 1.248 1999/12/20 13:07:42 karls Exp $";	/*	 * signal handlers    */__BEGIN_DECLSstatic voidchecksettings __P((void));static voidsiginfo __P((int sig));static voidsigchld __P((int sig));static voidsigalrm __P((int sig));static voidsighup __P((int sig));static voidsigserverbroadcast __P((int sig));/* * Broadcasts "sig" to all other servers. * */static voidserverinit __P((int argc, char *argv[], char *envp[]));/* * Initialises options/config.  "argc" and "argv" should be * the arguments passed to main(). * Exits on failure. */static voidusage __P((int code));/* * print usage. */static voidshowversion __P((void));/* * show versioninfo and exits. */static voidshowlicense __P((void));/* * shows license and exits. */#if DIAGNOSTIC && HAVE_MALLOC_OPTIONS	extern char *malloc_options;#endif  /* DIAGNOSTIC && HAVE_MALLOC_OPTIONS */#if HAVE_PROGNAMEextern char *__progname;#elsechar *__progname = "sockd";	/* default. */#endif  /* HAVE_PROGNAME */extern char *optarg;__END_DECLSint#if HAVE_SETPROCTITLEmain(argc, argv)#elsemain(argc, argv, envp)#endif /* HAVE_SETPROCTITLE */	int	argc;	char	*argv[];#if !HAVE_SETPROCTITLE	char    *envp[];#endif  /* HAVE_SETPROCTITLE */{	struct sigaction sigact;	int p, maxfd, dforchild;	FILE *fp;#if HAVE_SETPROCTITLE	char *envp[] = { NULL }; /* dummy. */#endif /* HAVE_SETPROCTITLE */	const int exitsignalv[] = {		SIGINT, SIGQUIT, SIGBUS, SIGSEGV, SIGTERM	};	const size_t exitsignalc = ELEMENTS(exitsignalv);	const int ignoresignalv[] = {		SIGPIPE	};	const size_t ignoresignalc = ELEMENTS(ignoresignalv);#if DIAGNOSTIC && HAVE_MALLOC_OPTIONS	malloc_options = "AJ";#endif  /* DIAGNOSTIC && HAVE_MALLOC_OPTIONS */	serverinit(argc, argv, envp);	showconfig(&config);	socks_seteuid(NULL, config.uid.unprivileged);	/* for chroot and needing every descriptor we can get. */	dforchild = config.log.type & LOGTYPE_SYSLOG ? -1 : 0; /* syslog takes one */	for (p = 0, maxfd = getdtablesize(); p < maxfd; ++p) {		int i;		/* don't close config/log files. */		if (socks_logmatch((size_t)p, &config.log))			continue;		++dforchild; /* descriptor will be usable by child. */		/* sockets we listen on. */		for (i = 0; i < config.internalc; ++i) {			if (p == config.internalv[i].s)				break;#if NEED_ACCEPTLOCK			if (config.option.serverc > 1)				if (p == config.internalv[i].lock)					break;#endif		}		if (i < config.internalc)			continue;		close(p);	}	initlog(); /* for syslog. */	/*	 * Check system limits against what we need.	 * Enough descriptors for each childprocess?  +2 for mother connections.	 */	/* CONSTCOND */	maxfd = MAX(SOCKD_NEGOTIATEMAX,	MAX(SOCKD_REQUESTMAX, SOCKD_IOMAX * FDPASS_MAX)) + 2;	if (dforchild < maxfd) {		struct rlimit rlimit;		rlimit.rlim_cur = maxfd;		rlimit.rlim_max = maxfd;		if (setrlimit(RLIMIT_OFILE, &rlimit) != 0) {			if (errno != EPERM)				serr(EXIT_FAILURE, "setrlimit(RLIMIT_OFILE, %d)", rlimit.rlim_max);			else if (getdtablesize() < SOCKD_NEGOTIATEMAX + 2)				serr(EXIT_FAILURE,				"%d descriptors configured for negotiation, %d available",				SOCKD_NEGOTIATEMAX + 2, getdtablesize());			else if (getdtablesize() < SOCKD_REQUESTMAX + 2)				serr(EXIT_FAILURE,				"%d descriptors configured for requestcompletion, %d available",				SOCKD_REQUESTMAX + 2, getdtablesize());			else if (getdtablesize() < SOCKD_IOMAX * FDPASS_MAX + 2)				serr(EXIT_FAILURE,				"%d descriptors configured for i/o, %d available",				SOCKD_IOMAX * FDPASS_MAX + 2, getdtablesize());			else				SERRX(getdtablesize());		}	}	/* set up signalhandlers. */	sigemptyset(&sigact.sa_mask);	sigact.sa_flags	= SA_RESTART | SA_NOCLDSTOP;	sigact.sa_handler = siginfo;#if HAVE_SIGNAL_SIGINFO	if (sigaction(SIGINFO, &sigact, NULL) != 0) {		swarn("sigaction(SIGINFO)");		return EXIT_FAILURE;	}#endif  /* HAVE_SIGNAL_SIGINFO */	/* same handler, for systems without SIGINFO. */	if (sigaction(SIGUSR1, &sigact, NULL) != 0) {		swarn("sigaction(SIGUSR1)");		return EXIT_FAILURE;	}	sigact.sa_handler = sighup;	if (sigaction(SIGHUP, &sigact, NULL) != 0) {		swarn("sigaction(SIGHUP)");		return EXIT_FAILURE;	}	sigact.sa_handler = sigchld;	if (sigaction(SIGCHLD, &sigact, NULL) != 0) {		swarn("sigaction(SIGCHLD)");		return EXIT_FAILURE;	}	sigact.sa_handler = sockdexit;	for (p = 0; (size_t)p < exitsignalc; ++p)		if (sigaction(exitsignalv[p], &sigact, NULL) != 0)			swarn("sigaction(%d)", exitsignalv[p]);	sigact.sa_handler = SIG_IGN;	for (p = 0; (size_t)p < ignoresignalc; ++p)		if (sigaction(ignoresignalv[p], &sigact, NULL) != 0)			swarn("sigaction(%d)", ignoresignalv[p]);	sigact.sa_flags	= 0;	/* want to be interrupted. */	sigact.sa_handler = sigalrm;	if (sigaction(SIGALRM, &sigact, NULL) != 0) {		swarn("sigaction(SIGALRM)");		return EXIT_FAILURE;	}	socks_seteuid(NULL, config.uid.privileged);	if ((fp = fopen(SOCKD_PIDFILE, "w")) == NULL)		swarn("open(%s)", SOCKD_PIDFILE);	socks_seteuid(NULL, config.uid.unprivileged);	if (fp != NULL) {		if (fprintf(fp, "%lu\n", (unsigned long)config.state.pid) == EOF)			swarn("fprintf(%s)", SOCKD_PIDFILE);		fclose(fp);	}	time(&config.stat.boot);	/* fork of requested number of servers.  Start at one 'cause we are "it".  */	for (p = 1; p < config.option.serverc; ++p) {		pid_t pid;		if ((pid = fork()) == -1)			swarn("fork()");		else if (pid == 0) {			config.state.pid = getpid();			break;		}		else			config.state.motherpidv[p] = pid;	}	if (childcheck(CHILD_NEGOTIATE)	<= 0	||  childcheck(CHILD_REQUEST)		<= 0	||	 childcheck(CHILD_IO)			<= 0)		serr(EXIT_FAILURE, "childcheck() failed");	slog(LOG_INFO, "%s/server v%s running", PACKAGE, VERSION);	/*	 * main loop; accept new connections and handle our children.	 */	/* CONSTCOND */	while (1) {		int client;		struct sockd_child_t *child;		fd_set rset;		int rbits;		rbits = fillset(&rset);		++rbits;		switch ((p = select(rbits, &rset, NULL, NULL, NULL))) {			case 0:				SERR(p);				/* NOTREACHED */			case -1:				if (errno == EINTR)					continue;				SERR(p);				/* NOTREACHED */		}		/*		 * handle our children.		 */		/* first, get ack of free slots. */		while ((child = getset(SOCKD_FREESLOT, &rset)) != NULL) {			char command;			int childisbad = 0;			if ((p = readn(child->ack, &command, sizeof(command)))			!= sizeof(command)) {				swarn("readn(child->ack) from %schild %lu failed",				childtype2string(child->type), (unsigned long)child->pid);				childisbad = 1;			}			else {				SASSERTX(command == SOCKD_FREESLOT);				++child->freec;			}			clearset(SOCKD_FREESLOT, child, &rset);			if (childisbad)				removechild(child->pid);		}		/* next, get new requests. */		while ((child = getset(SOCKD_NEWREQUEST, &rset)) != NULL) {			int childisbad = 0;#if DIAGNOSTIC			int freed = freedescriptors(config.option.debug ? "start" : NULL);#endif			switch (child->type) {				/*				 * in the order a packet travels between children;				 * negotiate -> request -> io.				 */				case CHILD_NEGOTIATE: {					int flags;					struct sockd_request_t req;					struct sockd_child_t *reqchild;					if ((reqchild = nextchild(CHILD_REQUEST)) == NULL)						break;	/* no child to accept a new request. */					SASSERTX(reqchild->freec > 0);					/* receive request from negotiator child... */					if ((p = recv_req(child->s, &req)) != 0) {						childisbad = 1;						break;					}					++config.stat.negotiate.received;					/* set descriptor to blocking for request... */					if ((flags = fcntl(req.s, F_GETFL, 0)) == -1					||  fcntl(req.s, F_SETFL, flags & ~O_NONBLOCK) == -1)						swarn("%s: fcntl()");					/* and send it to a request child. */					if ((p = send_req(reqchild->s, &req)) == 0) {						--reqchild->freec;						++config.stat.request.sendt;					}					else {						clearset(SOCKD_NEWREQUEST, child, &rset);						childisbad = 1;						child = reqchild;					}					close(req.s);					break;				}				case CHILD_REQUEST: {					struct sockd_io_t io;					struct sockd_child_t *iochild;					if ((iochild = nextchild(CHILD_IO)) == NULL)						break;	/* no child to accept new io. */					SASSERTX(iochild->freec > 0);					/* get io from request child ... */					if ((p = recv_io(child->s, &io)) != 0) {						childisbad = 1;						break;					}					++config.stat.request.received;					/* and send it to a io child. */					if ((p = send_io(iochild->s, &io)) == 0) {						--iochild->freec;						++config.stat.io.sendt;					}					else {						clearset(SOCKD_NEWREQUEST, child, &rset);						childisbad = 1;						child = iochild;					}					close_iodescriptors(&io);					break;				}				case CHILD_IO:					/*					 * the only thing a iochild should return is a ack each time					 * it finishes with a io, that is handled in loop above.					 */					break;			}#if DIAGNOSTIC			SASSERTX(freed == freedescriptors(config.option.debug ? "end" : NULL));#endif			clearset(SOCKD_NEWREQUEST, child, &rset);			if (childisbad) /* error/eof from child. */				switch (errno) {					case EMFILE:					case ENFILE:						break;	/* child is ok, we are not. */					default:						removechild(child->pid);				}		}		/* handled our children.  Is there a new connection pending? */		for (p = 0; p < config.internalc; ++p) {			char accepted[MAXSOCKADDRSTRING];			if (FD_ISSET(config.internalv[p].s, &rset)) {				const struct listenaddress_t *l = &config.internalv[p];				struct sockd_child_t *negchild;				struct sockaddr from;				socklen_t len;				if ((negchild = nextchild(CHILD_NEGOTIATE)) == NULL)					break;  /* no free negotiator children, don't accept(). */#if NEED_ACCEPTLOCK				if (config.option.serverc > 1)					if (socks_lock(l->lock, F_WRLCK, 0) != 0)						continue;#endif#if HAVE_SENDMSG_DEADLOCK				if (socks_lock(negchild->lock, F_WRLCK, 0) != 0) {#if NEED_ACCEPTLOCK					if (config.option.serverc > 1)						socks_unlock(l->lock);#endif /* NEED_ACCEPTLOCK */					continue;				}#endif /* HAVE_SENDMSG_DEADLOCK */				len = sizeof(from);				if ((client = acceptn(l->s, &from, &len)) == -1)					switch (errno) {#ifdef EPROTO						case EPROTO:			/* overloaded SVR4 error */#endif						case EWOULDBLOCK:		/* BSD */						case ECONNABORTED:	/* POSIX */						/* rest appears to be linux stuff according to apache src. */#ifdef ECONNRESET						case ECONNRESET:#endif#ifdef ETIMEDOUT						case ETIMEDOUT:#endif#ifdef EHOSTUNREACH						case EHOSTUNREACH:#endif#ifdef ENETUNREACH						case ENETUNREACH:#endif#if NEED_ACCEPTLOCK							if (config.option.serverc > 1)								socks_unlock(l->lock);#endif /* NEED_ACCEPTLOCK */#if HAVE_SENDMSG_DEADLOCK							socks_unlock(negchild->lock);#endif /* HAVE_SENDMSG_DEADLOCK */							continue; /* connection aborted/failed. */						case ENFILE:							continue;						/*						 * this should never happen since childcheck(), if

⌨️ 快捷键说明

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