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

📄 tcpproxy.c

📁 tcp protocol proxy,it is userful!
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    File: tcpproxy/tcpproxy.c    Copyright (C) 1999  Wolfgang Zekoll  <wzk@quietsche-entchen.de>      This software 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. */ /*  * Version 1.1.4 - 11NOV99wzk  *  *   - shutdown(sfd, 1) wenn close() auf der Client Seite erkannt wird.  *  *   -w Option  *  *  * Version 1.1.2 - 11SEP99wzk  *  *   - Die Optionen -c und -z sind neu.  *  *  * Version 1.1.0 - 01SEP99wzk  *  * Aenderungen gegenueber den Vorgaengerversionen:  *  *   - Unterstuetzung von Server-Programmen.  *   - Der netcat-Modus wird nicht mehr unterstuetzt.  *   - Erweiterung des Kommandozeilenoptionen.  *  */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <wait.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#include <syslog.h>#include <sys/time.h>#include "ip-lib.h"#include "lib.h"#define	PIDFILE			"/var/run/tcpproxy.pid"#define	ERROR_LOG		"/tmp/tcpproxy-error.log"#define	MAX_PORT		80char	*program =		"";char	progname[80] =		"";char	logname[80] =		"";int	debug =			0;char	configfile[300] =	"";int	use_errorlog =		0;char	errorlog[200] =		ERROR_LOG;int	standalone =		0;int	uid =			-1;int	gid =			-2;char	pidfile[200] =		"";int	listports =		0;typedef struct _port {    unsigned int port;    int		count;    char	ip[40];    int		sock;    } port_t;int	binds =			0;port_t	*bindport;#define	PROXY_DEFAULT		0#define	PROXY_SERVER		1#define	PROXY_PROGRAM		2#define	MAX_ARGS		32typedef struct _config {    char	interface[300];    unsigned int port;        int		timeout;    int		cleanenv;    char	varname[80];    char	acp[200];    char	writefile[200];    int		proxytype;    union {	struct {	    char	name[300];	    unsigned int port;	    } server;	struct {	    int		exec;	    	    char	command[300];	    char	*argv[MAX_ARGS + 2];	    } program;	} u;    struct {        char	ip[300];        unsigned int port;        } incoming;    char	client_ip[300];    char	client[300];    int		local_client;    long	bytes_send;    long	bytes_received;    struct _config *next;    } config_t;config_t *first =	NULL;config_t *last =	NULL;int	config_count =	0;/* void *allocate(int size); */config_t *new_configuration(config_t *def){	config_t *x;	x = allocate(sizeof(config_t));	if (def != NULL)		memmove(x, def, sizeof(config_t));	if (first == NULL) {		first = x;		last  = x;		}	else {		last->next = x;		last = x;		}	config_count++;	return (x);}config_t *find_configuration(char *interface, unsigned int port){	config_t *x, *global;	global = NULL;	x = first;	while (x != NULL) {		if (x->port == port) {			if (*x->interface == 0  ||  strcmp(x->interface, "0.0.0.0") == 0)				global = x;			else if (strcmp(x->interface, interface) == 0)				break;			}					x = x->next;		}	if (x == NULL  &&  global != NULL)		x = global;			return (x);}int _check_interface(config_t *x, int lineno){	if (*x->interface == 0) {		fprintf (stderr, "%s: line %d: interface not set\n", program, lineno);		exit (1);		}		return (0);}int _check_proxytype(config_t *x, int lineno){	if (x->proxytype != 0) {		fprintf (stderr, "%s: line %d: service redefinition\n", program, lineno);		exit (1);		}		return (0);}int read_configuration(char *filename, config_t *def){	int	lineno;	unsigned int port;	char	*p, word[80], line[300];	FILE	*fp;	config_t *x;	/*	 * Konfiguration lesen	 */	 	if ((fp = fopen(filename, "r")) == NULL) {		fprintf (stderr, "%s: can't read config file: %s\n", program, filename);		exit (-1);		}	/*	 * Einstellungen vor dem ersten bind gehen in die	 * default-Konfiguration.	 */	 	x = def;		lineno = 0;	port   = 0;	while (fgets(line, sizeof(line), fp) != NULL) {		lineno++;		p = skip_ws(noctrl(line));		if (*p == 0  ||  *p == '#')			continue;		get_word(&p, word, sizeof(word));		strlwr(word);		p = skip_ws(p);		/*		 * globale Optionen		 */		 		if (strcmp(word, "uid") == 0)			uid = atoi(p);		else if (strcmp(word, "gid") == 0)			gid = atoi(p);		else if (strcmp(word, "pidfile") == 0) {			copy_string(pidfile, p, sizeof(pidfile));			if (*pidfile == 0)				strcpy(pidfile, PIDFILE);			}		else if (strcmp(word, "standalone") == 0) {			get_word(&p, word, sizeof(word));			strlwr(word);			if (strcmp(word, "yes") == 0  ||  strcmp(word, "on") == 0)				standalone = 1;			else if (strcmp(word, "no") == 0  ||  strcmp(word, "off") == 0)				standalone = 0;			}		else if (strcmp(word, "logname") == 0) {			if (*(p = skip_ws(p)) == 0) {				fprintf (stderr, "%s: line %d: missing logname\n", program, lineno);				exit (-1);				}			copy_string(logname, p, sizeof(logname));			}		/*		 * Globale Vorgaben, bzw. Serviceparameter		 */		else if (strcmp(word, "timeout") == 0) {			x->timeout = atoi(p);			if (x->timeout < 1)				x->timeout = 60;			}		else if (strcmp(word, "setenv") == 0) {			get_word(&p, x->varname, sizeof(x->varname));			if (*x->varname == 0)				strcpy(x->varname, "PROXY_");			}		else if (strcmp(word, "acp") == 0) {			copy_string(x->acp, p, sizeof(x->acp));			}		/*		 * Server-Konfiguration		 */		 		else if (strcmp(word, "port") == 0  ||  strcmp(word, "bind") == 0) {			if (binds >= MAX_PORT) {				fprintf (stderr, "%s: line %d: too many ports\n", program, lineno);				exit (-1);				}							port = getportnum(p);						bindport[binds].port  = port;			bindport[binds].count = 0;			binds++;			}		else if (strcmp(word, "interface") == 0) {			if (binds == 0  ||  port == 0) {				fprintf (stderr, "%s: line %d: no port specification\n", program, lineno);				exit (-1);				}			else if (*(p = skip_ws(p)) == 0) {				fprintf (stderr, "%s: line %d: no interface\n", program, lineno);				exit (-1);				}			x = new_configuration(def);			x->port = port;			get_word(&p, x->interface, sizeof(x->interface));			if (strcmp(x->interface, "*") == 0  ||  strcmp(x->interface, "any") == 0)				strcpy(x->interface, "0.0.0.0");			copy_string(bindport[binds-1].ip, x->interface, sizeof(bindport[binds-1].ip));			bindport[binds-1].count++;			get_word(&p, word, sizeof(word));			strlwr(word);			if (*word == 0)				/* nichts */ ;			else if (strcmp(word, "server") == 0) {				_check_proxytype(x, lineno);				x->proxytype = PROXY_SERVER;				copy_string(x->u.server.name, p, sizeof(x->u.server.name));				x->u.server.port = get_port(x->u.server.name, x->port);				}			else if (strcmp(word, "exec") == 0) {				_check_proxytype(x, lineno);				x->proxytype = PROXY_PROGRAM;				x->u.program.exec = 1;				copy_string(x->u.program.command, p, sizeof(x->u.program.command));				}			else {				fprintf (stderr, "%s: line %d: syntax error: %s\n", program, lineno, word);				exit (-1);				}			}		else if (strcmp(word, "server") == 0) {			_check_interface(x, lineno);			_check_proxytype(x, lineno);			copy_string(x->u.server.name, p, sizeof(x->u.server.name));			x->u.server.port = get_port(x->u.server.name, x->port);			}		else if (strcmp(word, "exec") == 0) {			int	argc;			_check_interface(x, lineno);			_check_proxytype(x, lineno);			x->proxytype = PROXY_PROGRAM;			x->u.program.exec = 1;						copy_string(x->u.program.command, p, sizeof(x->u.program.command));			argc = split(x->u.program.command, x->u.program.argv, ' ', MAX_ARGS);			if (argc >= MAX_ARGS) {				fprintf (stderr, "%s: line %d: too much command line parameters\n", program, lineno);				exit (1);				}			x->u.program.argv[argc] = NULL;			}		else if (strcmp(word, "writefile") == 0  ||  strcmp(word, "debug") == 0) {			_check_interface(x, lineno);			get_word(&p, x->writefile, sizeof(x->writefile));			}		else {			fprintf (stderr, "%s: line %d: unkown configuration directive %s\n", program, lineno, word);			exit (-1);			}		}	fclose (fp);	return (0);}int cleanenv(config_t *x, char **envp){	int	k, n;	char	*p, **env;		env = envp;	n = 0;	while (env[n] != NULL)		n++;	env = envp;	k = 0;	while (k < n  &&  *env != NULL) {		char	var[800];		p = *env;		get_quoted(&p, '=', var, sizeof(var));		/*		 * Ist nicht ungefaehrlich.  Wenn der folgende Aufruf		 * fehlschlaegt muessten wir unseren env-Pointer		 * inkrementieren, um nicht in eine Endlosschleife,		 * die immer auf derselben Variablen stehenbleibt,		 * zu landen.  Das waere falsch, wenn wir die Variable		 * erfolgreich loeschen.  Ungluecklicherweise liefert		 * unsetenv() keinen return-code zurueck.		 */			 		unsetenv(var);		k++;		}		if (*env != NULL  ||  k != n)		syslog(LOG_NOTICE, "cleanenv error");	return (0);}int set_variables(config_t *x){	char	var[200], val[200];		snprintf (var, sizeof(var) - 2, "%sINTERFACE", x->varname);	setenv(var, x->incoming.ip, 1);		snprintf (val, sizeof(val) - 2, "%u", x->port);	snprintf (var, sizeof(var) - 2, "%sPORT", x->varname);	setenv(var, val, 1);	snprintf (var, sizeof(var) - 2, "%sCLIENT", x->varname);	setenv(var, x->client_ip, 1);	snprintf (var, sizeof(var) - 2, "%sCLIENTNAME", x->varname);	setenv(var, x->client, 1);	return (0);}int run_acp(config_t *x){	int	rc, pid, pfd[2];	char	line[300];		if (*x->acp == 0)		return (0);	rc = 0;	if (pipe(pfd) != 0) {		syslog(LOG_NOTICE, "can't pipe: %m");		exit (1);		}	else if ((pid = fork()) < 0) {		syslog(LOG_NOTICE, "can't fork acp: %m");		exit (1);		}	else if (pid == 0) {		int	argc;		char	*argv[32];		close(0);		/* Das acp kann nicht vom client lesen. */		dup2(pfd[1], 2);	/* stderr wird vom parent gelesen. */		close(pfd[0]);		set_variables(x);				copy_string(line, x->acp, sizeof(line));		argc = split(line, argv, ' ', 30);		argv[argc] = NULL;		execvp(argv[0], argv);		syslog(LOG_NOTICE, "can't exec acp %s: %m", argv[0]);		exit (1);		}	else {		int	len;		char	message[300];		close(pfd[1]);		*message = 0;		if ((len = read(pfd[0], message, sizeof(message) - 2)) < 0)			len = 0;		message[len] = 0;		noctrl(message);				if (waitpid(pid, &rc, 0) < 0) {			syslog(LOG_NOTICE, "error while waiting for acp: %m");			exit (1);			}		rc = WIFEXITED(rc) != 0? WEXITSTATUS(rc): 1;		if (*message == 0)			copy_string(message, rc == 0? "access granted": "access denied", sizeof(message));		if (*message != 0)			syslog(LOG_NOTICE, "%s (rc= %d)", message, rc);		}			return (rc);}int multiaccept_loop(config_t *start){	int	i, max;	fd_set	bound, available;	FD_ZERO(&bound);	max = 0;	for (i=0; i<binds; i++) {		if (bindport[i].sock < 0) {			syslog(LOG_NOTICE, "invalid socket number found: %d", bindport[i].sock);			exit (-1);			}					FD_SET(bindport[i].sock, &bound);		if (bindport[i].sock > max)			max = bindport[i].sock;		}	while (1) {		memmove(&available, &bound, sizeof(fd_set));		if (select(max + 1, &available, NULL, NULL, NULL) < 0) {			if (errno == EINTR) {				syslog(LOG_NOTICE, "interrupted select call");				continue;				}			syslog(LOG_NOTICE, "select error: %m");			exit (-1);			}		for (i=0; i<binds; i++) {			if (FD_ISSET(bindport[i].sock, &available)) {				int	connect, pid, len;				struct sockaddr_in client;				/*				 * hier kommt ein accept an				 */				len = sizeof(client);				if ((connect = accept(bindport[i].sock, (struct sockaddr *) &client, &len)) < 0) {					if (errno == EINTR  ||  errno == ECONNABORTED)

⌨️ 快捷键说明

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