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

📄 sockd.c

📁 sock protocol ,it is useful!
💻 C
📖 第 1 页 / 共 2 页
字号:
						 * initially successful, should make sure there is						 *	always enough descriptors available.						 */						case EMFILE:							/* FALLTHROUGH */						default:							SERR(client);					}#if HAVE_LINUX_BUGS				/*				 * yes, linux manages to lose the descriptor flags, workaround				 *	might be insufficient.				 */				if (fcntl(client, F_SETFL, fcntl(l->s, F_GETFL, 0)) != 0)					swarn("tried to work around linux bug via fcntl()");#endif /* HAVE_LINUX_BUGS */				++config.stat.accepted;#if NEED_ACCEPTLOCK				if (config.option.serverc > 1)					socks_unlock(l->lock);#endif				slog(LOG_DEBUG, "got accept(): %s",				sockaddr2string(&from, accepted, sizeof(accepted)));				if (send_client(negchild->s, client) == 0) {					--negchild->freec;					++config.stat.negotiate.sendt;				}				else					switch (errno) {						case EMFILE:						case ENFILE:							break;	/* child is ok, we are not. */						default:							removechild(negchild->pid);					}#if HAVE_SENDMSG_DEADLOCK				socks_unlock(negchild->lock);#endif /* HAVE_SENDMSG_DEADLOCK */				close(client);			}		}	}	/* NOTREACHED */}intpidismother(pid)	pid_t pid;{	int i;	for (i = 0; i < config.option.serverc; ++i)		if (config.state.motherpidv[i] == pid)			return i + 1;	return 0;}static voidusage(code)	int code;{	fprintf(code == 0 ? stdout : stderr,	"%s: usage: %s [-DLNdfhlnv]\n"	"\t -D             : run in daemon mode\n"	"\t -L             : shows the license for this program\n"   "\t -N <number>    : fork of <number> servers (default: 1)\n"	"\t -d             : enable debugging\n"	"\t -f <filename>  : use <filename> as configuration file\n"	"\t -h             : print this information\n"	"\t -l             : linebuffer output\n"   "\t -n             : disable TCP keep-alive\n"	"\t -v             : print version info\n",	__progname, __progname);	exit(code);}static voidshowversion(void){	printf("%s: %s v%s\n", __progname, PACKAGE, VERSION);	exit(EXIT_SUCCESS);}static voidshowlicense(void){	printf("%s: %s v%s\n%s\n", __progname, PACKAGE, VERSION,"\/*\n\ * Copyright (c) 1997, 1998, 1999\n\ *      Inferno Nettverk A/S, Norway.  All rights reserved.\n\ *\n\ * Redistribution and use in source and binary forms, with or without\n\ * modification, are permitted provided that the following conditions\n\ * are met:\n\ * 1. The above copyright notice, this list of conditions and the following\n\ *    disclaimer must appear in all copies of the software, derivative works\n\ *    or modified versions, and any portions thereof, aswell as in all\n\ *    supporting documentation.\n\ * 2. All advertising materials mentioning features or use of this software\n\ *    must display the following acknowledgement:\n\ *      This product includes software developed by\n\ *      Inferno Nettverk A/S, Norway.\n\ * 3. The name of the author may not be used to endorse or promote products\n\ *    derived from this software without specific prior written permission.\n\ *\n\ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n\ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n\ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \n\ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n\ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n\ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n\ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n\ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \n\ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n\ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ *\n\ * Inferno Nettverk A/S requests users of this software to return to\n\ * \n\ *  Software Distribution Coordinator  or  sdc@inet.no\n\ *  Inferno Nettverk A/S\n\ *  Oslo Research Park\n\ *  Gaustadal閑n 21\n\ *  N-0349 Oslo\n\ *  Norway\n\ * \n\ * any improvements or extensions that they make and grant Inferno Nettverk A/S\n\ * the rights to redistribute these changes.\n\ *\n\ */");	exit(EXIT_SUCCESS);}/* ARGSUSED */ /* need envp if no HAVE_SETPROCTITLE */static voidserverinit(argc, argv, envp)	int argc;	char *argv[];	char *envp[];{	const char *function = "serverinit()";	uid_t euid;	int ch, i;#if !HAVE_PROGNAME	if (argv[0] != NULL)		if ((__progname = strrchr(argv[0], '/')) == NULL)			__progname = argv[0];		else			++__progname;#endif  /* !HAVE_PROGNAME */#if !HAVE_SETPROCTITLE	if (initsetproctitle(argc, argv, envp) == -1)		serr(EXIT_FAILURE, "malloc");#endif  /* !HAVE_SETPROCTITLE*/	config.state.addchild	= 1;	config.state.euid			= geteuid();	config.state.type			= CHILD_MOTHER;	config.option.serverc	= 1;	/* ourselves. ;-) */	while ((ch = getopt(argc, argv, "DLN:df:hlnvw:")) != -1) {		switch (ch) {			case 'D':				config.option.daemon = 1;				break;			case 'L':				showlicense();				/* NOTREACHED */			case 'N':				if ((config.option.serverc = atoi(optarg)) < 1)					serrx(1, "%s: illegal value for -%c: %d",					function, ch, config.option.serverc);				break;			case 'd':				++config.option.debug;				break;			case 'f':#if !HAVE_SETPROCTITLE				/* let it point outside argv for replacement setproctitle(). */				if ((config.option.configfile = strdup(optarg)) == NULL)					serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);#else				config.option.configfile = optarg;#endif /* !HAVE_SETPROCTITLE */				break;			case 'h':				usage(0);				/* NOTREACHED */			case 'l':				config.option.lbuf = 1;				break;			case 'n':				config.option.keepalive = 0;				break;			case 'v':				showversion();				/* NOTREACHED */			case 'w':				config.option.sleep = atoi(optarg);				break;			default:				usage(1);		}	}	if (config.option.daemon)		if (daemon(1, 0) != 0)			serr(EXIT_FAILURE, "daemon()");	config.state.pid = getpid();	if ((config.state.motherpidv	= (pid_t *)malloc(sizeof(*config.state.motherpidv) * config.option.serverc))	== NULL)		serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);	*config.state.motherpidv = config.state.pid;	/* main server. */	if (config.option.configfile == NULL)		config.option.configfile = SOCKD_CONFIGFILE;	genericinit();	checksettings();	socks_seteuid(&euid, config.uid.privileged);	for (i = 0; i < config.internalc; ++i) {		int flags;		struct listenaddress_t *l = &config.internalv[i];		if ((l->s = socket(AF_INET, SOCK_STREAM, 0)) == -1)			serr(EXIT_FAILURE, "%s: socket(SOCK_STREAM)", function);		setsockoptions(l->s);		ch = 1;		if (setsockopt(l->s, SOL_SOCKET, SO_REUSEADDR, &ch, sizeof(ch))		!= 0)			swarn("%s: setsockopt(SO_REUSEADDR)", function);		/* LINTED pointer casts may be troublesome */		if (sockd_bind(l->s, (struct sockaddr *)&l->addr, 0) != 0) {			char badbind[MAXSOCKADDRSTRING];			/* LINTED pointer casts may be troublesome */			serr(EXIT_FAILURE, "%s: bind(%s)",			function, sockaddr2string((struct sockaddr *)&l->addr, badbind,			sizeof(badbind)));		}		if (listen(l->s, SOCKD_MAXCLIENTQUE) == -1)			serr(EXIT_FAILURE, "%s: listen(%d)", function, SOCKD_MAXCLIENTQUE);		if ((flags = fcntl(l->s, F_GETFL, 0)) == -1		||  fcntl(l->s, F_SETFL, flags | O_NONBLOCK) == -1)			serr(EXIT_FAILURE, "%s: fcntl()", function);#if NEED_ACCEPTLOCK		if (config.option.serverc > 1)			if ((l->lock = socks_mklock(SOCKS_LOCKFILE)) == -1)				serr(EXIT_FAILURE, "%s: socks_mklock()", function);#endif	}	socks_reseteuid(config.uid.privileged, euid);}static voidchecksettings(void){	const char *function = "checksettings()";	int i;	uid_t euid;	/*	 * Check arguments and settings, do they make sense?	 */	if (config.internalc == 0)		serrx(EXIT_FAILURE, "%s: no internal address given", function);	if (config.externalc == 0)		serrx(EXIT_FAILURE, "%s: no external address given", function);	for (i = 0; i < config.externalc; ++i) {		int s;		if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)			switch (errno) {				case EMFILE:				case ENFILE:				case ENOBUFS:					break; /* assume this is temporary, e.g. after sighup. */				default:					serrx(EXIT_FAILURE, "%s: socket()", function);			}		else {			char addrstring[MAXSOCKADDRSTRING];			if (bind(s, (struct sockaddr *)&config.externalv[i],			sizeof(config.externalv[i])) != 0)				serrx(EXIT_FAILURE, "%s: can't bind external address: %s",				function, sockaddr2string((struct sockaddr *)&config.externalv[i],				addrstring, sizeof(addrstring)));			close(s);		}	}	if (config.methodc == 0)		swarnx("%s: no methods enabled (total block)", function);	if (!config.uid.privileged_isset)		serrx(EXIT_FAILURE, "%s: privileged user not set", function);	socks_seteuid(&euid, config.uid.privileged);	socks_reseteuid(config.uid.privileged, euid);	if (!config.uid.unprivileged_isset)		serrx(EXIT_FAILURE, "%s: unprivileged user not set", function);	socks_seteuid(&euid, config.uid.unprivileged);	socks_reseteuid(config.uid.unprivileged, euid);#if HAVE_LIBWRAP	if (!config.uid.libwrap_isset)		serrx(EXIT_FAILURE, "%s: libwrap user not set", function);	socks_seteuid(&euid, config.uid.libwrap);	socks_reseteuid(config.uid.libwrap, euid);#endif /* HAVE_LIBWRAP */}/* ARGSUSED */static voidsiginfo(sig)	int sig;{	unsigned long seconds, days, hours, minutes;	size_t clients;	clients = 0;	clients += childcheck(-CHILD_NEGOTIATE);	clients += childcheck(-CHILD_REQUEST);	clients += childcheck(-CHILD_IO);	clients -= childcheck(CHILD_NEGOTIATE);	clients -= childcheck(CHILD_REQUEST);	clients -= childcheck(CHILD_IO);	seconds = difftime(time(NULL), config.stat.boot);	if (seconds >= 3600 * 24) {		days		= seconds / (3600 * 24);		seconds -= days * 3600 * 24;	}	else		days = 0;	if (seconds >= 3600) {		hours		= seconds / 3600;		seconds -= hours * 3600;	}	else		hours = 0;	if (seconds >= 60) {		minutes	= seconds / 60;		seconds -= minutes * 60;	}	else		minutes = 0;	slog(LOG_INFO, "%s v%s up %lu day%s, %lu:%.2lu, a: %lu, c: %lu",	PACKAGE, VERSION, days, days == 1 ? "" : "s", hours, minutes,	(unsigned long)config.stat.accepted, (unsigned long)clients);	slog(LOG_INFO, "negotiators (%d): a: %lu, h: %lu, c: %lu",	childcheck(-CHILD_NEGOTIATE) / SOCKD_NEGOTIATEMAX,	(unsigned long)config.stat.negotiate.sendt,	(unsigned long)config.stat.negotiate.received,	(unsigned long)childcheck(-CHILD_NEGOTIATE) - childcheck(CHILD_NEGOTIATE));	slog(LOG_INFO, "requests (%d): a: %lu, h: %lu, c: %lu",	childcheck(-CHILD_REQUEST) / SOCKD_REQUESTMAX,	(unsigned long)config.stat.request.sendt,	(unsigned long)config.stat.request.received,	(unsigned long)childcheck(-CHILD_REQUEST) - childcheck(CHILD_REQUEST));	slog(LOG_INFO, "iorelayers (%d): a: %lu, h: %lu, c: %lu",	childcheck(-CHILD_IO) / SOCKD_IOMAX,	(unsigned long)config.stat.io.sendt, (unsigned long)config.stat.io.sendt,	(unsigned long)childcheck(-CHILD_IO) - childcheck(CHILD_IO));	if (*config.state.motherpidv == config.state.pid)	/* main mother */		sigserverbroadcast(sig);	sigchildbroadcast(sig, CHILD_NEGOTIATE | CHILD_REQUEST | CHILD_IO);}/* ARGSUSED */static voidsighup(sig)	int sig;{	const char *function = "sighup()";	uid_t euid;	int p;	slog(LOG_INFO, function);	resetconfig();	socks_seteuid(&euid, config.state.euid);	genericinit();	socks_reseteuid(config.state.euid, euid);	checksettings();	/* LINTED assignment in conditional context */	if ((p = pidismother(config.state.pid))) {		if (p == 1) { /* main mother. */			showconfig(&config);			sigserverbroadcast(sig);		}		sigchildbroadcast(sig, CHILD_NEGOTIATE | CHILD_REQUEST | CHILD_IO);	}}/* ARGSUSED */static voidsigchld(sig)	int sig;{	const char *function = "sigchld()";	static time_t deathtime;	static int deaths;	int status;	pid_t pid;	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {		int i;		/*		 * No child should normally die, but try to cope with it happening.		 */		/* LINTED assignment in conditional context */		if ((i = pidismother(pid)))			config.state.motherpidv[i - 1] = 0;		else			; /* assume relay child. */		++deaths;	}	/*	 * If we get alot of childdeaths in a short time, assume something	 * is wrong.	 */	if (deathtime == 0)		time(&deathtime);	if (difftime(time(NULL), deathtime) > 60) { /* enough time passed; reset.	*/		deaths = 0;		time(&deathtime);	}	if (deaths >= 10) {		if (deaths == 10) { /* log once. */			slog(LOG_ERR, "%s: %d childdeaths in %.0fs; locking count for a while",			function, deaths, difftime(time(NULL), deathtime));			config.state.addchild = 0;		}		time(&deathtime); /* once the ball starts rolling... */		alarm(60);	}	else		config.state.addchild = 1; /* can try to add a new one. */}/* ARGSUSED */static voidsigalrm(sig)	int sig;{	config.state.addchild = 1;}voidsigserverbroadcast(sig)	int sig;{	int i;	SASSERTX(*config.state.motherpidv == config.state.pid);	for (i = 1; i < config.option.serverc; ++i)		if (config.state.motherpidv[i] != 0)			kill(config.state.motherpidv[i], sig);}

⌨️ 快捷键说明

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