# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	README
#	Makefile
#	LICENSE
#	plug.1
#	plug.c
#	plug.h
#	proto.h
#
echo x - README
sed 's/^X//' >README << 'END-of-README'
XPlugdaemon 1.2.2
X
XPlugdaemon is a tool that is inspired by, but not based on, the plug-gw from
XTrusted Information Systems. It was originally a simpler wannabe, but the
Xconnection balancing code makes up for it.
X
XNot all the planned features are implemented in 1.2. Eventually plugdaemon
Xwill provide a complete load balancing and monitoring package for servers.
X
XPlugdaemon is released for any use, commercial or otherwise, so long as
Xattribution is retained.
X
XIf you do anything interesting with it, let me know.
X
X				-- Peter da Silva <peter@taronga.com>
X
XChanges:
X
X	1.1.1		Bug fix for lost data on slow readers.
X	1.1.2		Added prototypes, minor cleanup.
X	1.1.3		Added "-V" version option, more cleanup,
X				moved OS-specific ifdefs out of plug.c.
X	1.2 (fork)	Keepalive option.
X	1.2.1		Integrated OpenBSD specific code in 1.2 with
X				cleaned up 1.1 code.
X	1.2.2		Fixed read error bug.
X
END-of-README
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X#
XCC=cc
X
XSOURCES= README Makefile LICENSE plug.1 plug.c plug.h proto.h
X
XCFLAGS=-O
XLIBS= 
X
Xall: plug plug.man
X
Xplug: plug.o
X	$(CC) plug.o -o plug $(LIBS)
X
Xplug.o: plug.h proto.h Makefile
X
Xplug.man: plug.1
X	nroff -man plug.1 > plug.man
X
Xclean:
X	rm -f plug plug.o plug.man
X
Xplug.shar: $(SOURCES)
X	shar $(SOURCES) > plug.shar
END-of-Makefile
echo x - LICENSE
sed 's/^X//' >LICENSE << 'END-of-LICENSE'
XPLUGDAEMON. Copyright (c) 1997 Peter da Silva. All rights reserved.
X
XRedistribution and use in source and binary forms, with or without
Xmodification, are permitted provided that the following conditions
Xare met:
X
X1. Redistributions of source code must retain the above copyright
X   notice, this list of conditions and the following disclaimer.
X
X2. Redistributions in binary form must reproduce the above copyright
X   notice, this list of conditions and the following disclaimer in the
X   documentation and/or other materials provided with the distribution.
X
X3. The names of the program and author may not be used to endorse or
X   promote products derived from this software without specific prior
X   written permission.
X
XTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
XINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
XAND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
XTHE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
XEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
XPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
XOR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
XOTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
XADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X
XEnd of legal shit.
X
XIn addition, if you modify the program in any significant way, or you discover
Xbugs that need fixing, I would appreciate it if you contact me about it.
X
XThanks.
X
X			Peter da Silva, September 1997.
X
END-of-LICENSE
echo x - plug.1
sed 's/^X//' >plug.1 << 'END-of-plug.1'
X.TH PLUG 1 FIREWALL
X.SH NAME
Xplug -- Plug proxy daemon.
X.SH SYNOPSIS
X.B plug -V
X.br
X.B plug
X.I [-f]
X.I [-l]
X.I [-d[d]]
X.I [-i sourceaddr]
X.I [-t timeout]
X.B sourceport
X.BI destaddr [:destport]
X.I [destaddr[:destport]]...
X.SH DESCRIPTION
X.B Plugdaemon
Xacts as a "dumb proxy", forwarding a TCP/IP stream from a port on one host
Xto a possibly different port on a separate host. It runs as a daemon to
Xreduce latency in setting up a connection, and optionally logs every
Xconnection via
X.I syslog.
X.SH OPTIONS
X.TP
X-f
XForces a given client address to continue to connect to the same host on
Xsubsequent attempts, for proxying HTTP connections so that subsequent hits
Xwill be on the same mirror.
X.TP
X-l
Xturns on connection logging.
X.TP
X-d
Xturns on debugging output and stops
X.B plug
Xfrom running as a daemon or logging errors to syslog. Errors in this mode
Xare displayed on standard error.
XAdditional -d options add more output.
X.TP
X-i interface
XBind the plug to the named interface, for use on multi-homed hosts.
X.TP
X-t timeout
XTimeout for forced connections, after no attempts in this period
Xit will connect to a new (pseudo-)randomly selected server. The
Xdefault is 1 hour.
X.SH EXAMPLES
XTo proxy an NNTP connection through a firewall to a host at 10.0.3.15:
X.P
Xplug -i 192.168.0.14 119 10.0.3.15
X.SH BUGS
X.B Plugdaemon
Xonly accepts numeric IP addresses and services. Be careful of the way
Xinet_addr(3) handles incomplete dotted quads.
X.SH "SECURITY FEATURES"
X.B Plugdaemon
Xonly accepts numeric IP addresses and services.
X.SH LICENSE
X.B Plugdaemon
Xis released under a "Berkeley" style license. See the file LICENSE for details.
X.SH AUTHOR
XPeter da Silva <peter@taronga.com>
END-of-plug.1
echo x - plug.c
sed 's/^X//' >plug.c << 'END-of-plug.c'
X/*
X * PLUGDAEMON. Copyright (c) 1997 Peter da Silva. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The names of the program and author may not be used to endorse or
X *    promote products derived from this software without specific prior
X *    written permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
X * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
X * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
X * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
X * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
X * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
X * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X */
X
X#include <unistd.h>
X#include <stdio.h>
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <sys/socket.h>
X#include <signal.h>
X#include <sys/errno.h>
X#include <sys/wait.h>
X#include <syslog.h>
X#include <string.h>
X#include <errno.h>
X#include <stdlib.h>
X#include "plug.h"
X#include "proto.h"
X
Xint daemonized = 0;
Xchar *sourceaddr = NULL, *sourceport = NULL;
Xchar *destaddr = NULL, *destport = NULL;
Xchar *prog;
Xint debug = 0;
Xint log = 0;
Xint force = 0;
Xint keepalive = 0;
Xlong timeout = 3600; /* seconds */
Xchar tag[64];
X
Xstruct dtab {
X	char *dest;
X	struct sockaddr_in addr;
X	int nclients;
X	int status;
X	time_t last_touched;
X};
X
Xstruct ctab {
X	unsigned long addr;
X	struct dtab *dest;
X	int status;
X	time_t last_touched;
X};
X
Xstruct dtab dest_tab[MAX_PROXIES];
Xstruct ctab client_tab[MAX_CLIENTS];
Xint dest_next;
X
Xint nproxies = 0;
Xint nclients = 0;
X
Xchar *version = "plugdaemon V1.2.2 Copyright (c) 1997-1998 Peter da Silva";
X
Xint
Xmain P2(int, ac, char, **av)
X{
X	int srvfd;
X	struct sockaddr_in srv_addr;
X	int pid;
X
X	parse_args(ac, av);
X
X	if (sourceaddr)
X		sprintf(tag, "(%.16s %.8s)", sourceaddr, sourceport);
X	else
X		sprintf(tag, "(%.8s)", sourceport);
X
X	if(debug>1)
X		fprintf(stderr, "%s: %s\n", prog, tag);
X
X	/* arguments parsed, get sockets ready */
X
X	if ((srvfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
X		bailout("server socket");
X
X	fill_sockaddr_in(&srv_addr,
X		sourceaddr?inet_addr(sourceaddr):htonl(INADDR_ANY),
X		htons(atoi(sourceport)));
X
X	for(dest_next = 0; dest_next < nproxies; dest_next++) {
X		char *destaddr, *portaddr;
X		struct dtab *target;
X
X		target = &dest_tab[dest_next];
X		destaddr = target->dest;
X		if((portaddr = strchr(destaddr, ':')))
X			*portaddr++ = 0;
X		else
X			portaddr = sourceport;
X
X		fill_sockaddr_in(&(target->addr),
X			inet_addr(destaddr), htons(atoi(portaddr)));
X
X		target->nclients = 0;
X		target->status = 1;
X		target->last_touched = (time_t)0;
X		target->dest = NULL; /* it's been trashed anyway */
X	}
X
X	daemonize();
X
X	prog = tag; /* for logging */
X
X	init_signals();
X
X	/* One ring to rule them all */
X	if(bind(srvfd, (struct sockaddr *)&srv_addr, sizeof srv_addr) < 0)
X		bailout("server bind");
X
X	if(log)
X		syslog(LOG_NOTICE, "%s: Plugdaemon started.", tag);
X
X	listen(srvfd, 5);
X
X	/* wait for connections and service them */
X	while(1) {
X		int clifd, prxfd, cli_len;
X		struct sockaddr_in c_addr;
X		struct dtab *target;
X
X		if(debug>1)
X		    fprintf(stderr, "%d listening for new connections.\n",
X			(int) getpid());
X
X		cli_len = sizeof c_addr;
X		clifd = accept(srvfd, (struct sockaddr *)&c_addr, &cli_len);
X		if(clifd < 0)
X			bailout("client accept");
X
X		if(!(target = select_target(clifd))) {
X			close(clifd);
X			continue;
X		}
X
X		if(debug>1)
X		    fprintf(stderr, "%d client connecting to %d.\n",
X			(int) getpid(), ntohs(c_addr.sin_port));
X
X		/* spawn a child and send the parent back to try again */
X		if((pid = fork()) == -1)
X			bailout("client fork");
X
X		if(pid) {
X			close(clifd);
X			continue;
X		}
X
X		/* ok, I'm the child. */
X		if ((prxfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
X			bailout("proxy socket");
X
X		if (connect(prxfd, (struct sockaddr *)&(target->addr), sizeof (target->addr)) < 0)
X			bailout("proxy connect");
X
X		if(debug>1)
X		    fprintf(stderr, "%d connected proxy to %s:%d.\n",
X			(int) getpid(), inet_ntoa(target->addr.sin_addr),
X			ntohs(target->addr.sin_port));
X
X		if(keepalive) {
X			int one = 1;
X
X			if(setsockopt(clifd, SOL_SOCKET, SO_KEEPALIVE,
X				      (char *)&one, sizeof one) < 0) {
X				bailout("set client socket options");
X			}
X			if(setsockopt(prxfd, SOL_SOCKET, SO_KEEPALIVE,
X				      (char *)&one, sizeof one) < 0) {
X				bailout("set proxy socket options");
X			}
X		}
X
X		plug(clifd, prxfd);
X
X		exit(0);
X	}
X}
X
Xvoid
Xbailout P1(char *, message)
X{
X	int save_errno;
X	char msgbuf[1024];
X	char *p;
X
X	save_errno = errno;
X
X	sprintf(msgbuf, "%.64s: %.64s", prog, message);
X	p = msgbuf + strlen(msgbuf);
X	if(save_errno) {
X		sprintf(p, ": %.64s", strerror(save_errno));
X	} else {
X		sprintf(p, "\nUsage is %.64s %s", prog,
X			"[-V] | [-lfkd[d]...] [-i srcaddr] [-t seconds] port destaddr[:destport]...");
X	}
X
X	if(!daemonized)
X		fprintf(stderr, "%s\n", msgbuf);
X	else {
X		syslog(LOG_ERR, msgbuf);
X		closelog();
X	}
X
X	exit (1);
X}
X
Xvoid
Xparse_args P2(int,  ac, char **, av)
X{
X	if((prog = strrchr(*av, '/')))
X		prog++;
X	else
X		prog = *av;
X
X	while (*++av) {
X		if (**av=='-') {
X			while(*++*av) switch(**av) {
X			    case 'i':
X				if(!*++*av && !*++av)
X					bailout("no value for -i option");
X				sourceaddr = *av;
X				goto nextarg;
X			    case 't':
X				if(!*++*av && !*++av)
X					bailout("no value for -t option");
X				timeout = atol(*av);
X				goto nextarg;
X			    case 'k':
X				keepalive++;
X				continue;
X			    case 'l':
X				log++;
X				continue;
X			    case 'd':
X				debug++;
X				continue;
X			    case 'f':
X				force++;
X				continue;
X			    case 'V':
X				printf("%s: %s\n", prog, version);
X				exit(0);
X			    default:
X				bailout("unknown argument");
X			}
X		} else {
X			if(!sourceport)
X				sourceport = *av;
X			else  {
X				char	*ptr;
X				
X				for (ptr = *av; *ptr != '\0'; ptr++)
X					if (strchr("0123456789:.", *ptr) == NULL)
X						bailout("proxy host specification not in addr[:port] format");
X				
X				if(nproxies >= MAX_PROXIES)
X					bailout("too many proxies");
X				dest_tab[nproxies++].dest = *av;
X			}
X		}
Xnextarg:	;
X	}
X	if(nproxies == 0)
X		bailout("not enough arguments");
X	if(!sourceport)
X		bailout("not enough arguments");
X}
X
X#define NOSET ((fd_set *) NULL)
X#define NOTIME ((struct timeval *) NULL)
X
Xvoid
Xplug P2(int, fd1, int, fd2)
X{
X	struct connx {
X		int fd;			/* socket (bidirectional) */
X		char buf[MAX_MTU];	/* Hold STUFF */
X		int len, off;		/* tail, head pointers into buffer */
X		int open;		/* socket still open for reading */
X		int shutdown_wait;	/* other socket closed for reading,
X					 * shut down writing when your buffer
X					 * is done with
X					 */
X	} s[2];
X	
X	fd_set rset, wset;
X	int nfds, nwr, nrd;
X	int i;
X
X	if(fd1>fd2)
X		nfds=fd1+1;
X	else
X		nfds=fd2+1;
X
X	s[0].fd = fd1;
X	s[1].fd = fd2;
X
X	s[0].len = s[1].len = s[0].off = s[1].off = 0;
X	s[0].open = s[1].open = 1;
X	s[0].shutdown_wait = s[1].shutdown_wait = 0;
X
X	while(s[0].open || s[1].open) {
X		FD_ZERO(&rset);
X		FD_ZERO(&wset);
X
X		for(i = 0; i < 2; i++) {
X			if(s[i].open) {
X				if(s[i].len < MAX_MTU)
X					FD_SET(s[i].fd, &rset);
X				if(s[i].len > s[i].off)
X					FD_SET(s[!i].fd, &wset);
X			}
X		}
X
X		if(select(nfds, &rset, &wset, NOSET, NOTIME) < 0)
X			bailout("proxy select");
X
X		for(i = 0; i < 2; i++) {
X			if(FD_ISSET(s[i].fd, &rset)) {
X				nrd = read(s[i].fd, s[i].buf+s[i].len, MAX_MTU-s[i].len);
X				if(nrd == 0 || nrd == -1) {
X					shutdown(s[i].fd, 0);
X					if(s[i].len > s[i].off)
X						s[!i].shutdown_wait = 1;
X					else
X						shutdown(s[!i].fd, 1);
X					s[i].open = 0;
X				}
X				s[i].len += nrd;
X			}
X			if(FD_ISSET(s[!i].fd, &wset)) {
X				nwr = write(s[!i].fd, s[i].buf+s[i].off, s[i].len-s[i].off);
X				if(nwr == 0) {
X					shutdown(s[!i].fd, 1);
X					shutdown(s[i].fd, 0);
X					s[i].open = 0;
X				} else if (nwr < 0) {
X					if(errno == EAGAIN)
X						nwr = 0;
X					else
X						bailout("proxy write");
X				}
X				s[i].off += nwr;
X				if(s[i].off == s[i].len) {
X					s[i].off = s[i].len = 0;
X					if(s[!i].shutdown_wait) {
X						shutdown(s[!i].fd, 1);
X						s[!i].shutdown_wait = 0;
X					}
X				}
X			}
X		}
X	}
X	if(debug>1) fprintf(stderr, "%d completed.\n", (int) getpid());
X}
X
Xvoid
Xlogclient P2(struct in_addr, peer, char *, status)
X{
X	char *s;
X
X	s = inet_ntoa(peer);
X
X	syslog(LOG_NOTICE, "%.64s: Connect from %.64s %s", tag, s, status);
X}
X
Xvoid
Xfill_sockaddr_in P3(struct sockaddr_in *, buffer, u_long, addr, u_short, port)
X{
X	memset(buffer, 0, sizeof *buffer);
X	buffer->sin_family = AF_INET;
X	buffer->sin_addr.s_addr = addr;
X	buffer->sin_port = port;
X}
X
Xvoid
Xdaemonize P0()
X{
X	int pid;
X
X	if(!debug) {
X		if((pid = fork()) == -1)
X			bailout("daemon fork");
X		if(pid)
X			exit(0);
X	}
X
X	(void)openlog(prog, LOG_PID|LOG_CONS, LOG_DAEMON);
X
X	if(!debug) {
X		close(0);
X		close(1);
X		close(2);
X		setsid();
X		daemonized = 1;
X	}
X}
X
Xvoid
Xwaiter P3(int, sig, SA_HANDLER_ARG2_T, code, void *, scp)
X{
X	int status, pid;
X
X	while (1) {
X		pid = waitpid(-1, &status, WNOHANG);
X
X		if(pid == 0 || pid == -1)
X			break;
X
X		if(debug>1)
X			fprintf(stderr, "%d child %d died, status is %d.\n",
X				(int) getpid(), pid, status);
X	}
X}
X
Xvoid
Xinit_signals P0()
X{
X	struct sigaction zombiesig, junksig;
X
X	/* Wait for dead kids */
X	zombiesig.SA_HANDLER = waiter;
X	sigemptyset(&zombiesig.sa_mask);
X	zombiesig.sa_flags = SA_NOCLDSTOP | SA_RESTART;
X
X	if(sigaction(SIGCHLD, &zombiesig, &junksig) < 0)
X		bailout("zombie signal");
X}
X
Xstruct dtab *select_target P1(int, clifd)
X{
X	struct sockaddr_in p_addr;
X	int len;
X	struct ctab *client = NULL;
X	struct dtab *target = NULL;
X	time_t now;
X	int i;
X
X	if(force || log) {
X		len = sizeof p_addr;
X		if(getpeername( clifd, (struct sockaddr *)&p_addr, &len) == -1)
X			bailout("getpeername");
X	}
X
X	if(force) {
X		int old_client = 0;
X
X		now = time((time_t *)0);
X
X		/* find a client and get rid of expired ones */
X		for(i = 0; i < nclients; i++) {
X			if(client_tab[i].addr == p_addr.sin_addr.s_addr)
X				break;
X			if(client_tab[i].addr) {
X				if(now - client_tab[i].last_touched > timeout) {
X					if(client_tab[i].dest)
X						client_tab[i].dest->nclients--;
X
X					/* clear */
X					client_tab[i].addr = 0;
X					client_tab[i].dest = (struct dtab *)0;
X					client_tab[i].status = 0;
X					client_tab[i].last_touched = 0;
X					old_client = i;
X				}
X			} else
X				old_client = i;
X		}
X
X		if(i < nclients) {
X			client = &client_tab[i];
X			target = client->dest;
X			if(now - client->last_touched > timeout) {
X				client->dest->nclients--;
X				client->dest = (struct dtab *)0;
X			}
X		} else {
X			if(old_client) {
X				client = &client_tab[old_client];
X			} else {
X				if(nclients >= MAX_CLIENTS) {
X					logclient(p_addr.sin_addr,
X					    "aborted: too many clients");
X					return (struct dtab *)0;
X				}
X				client = &client_tab[nclients++];
X			}
X			client->addr = p_addr.sin_addr.s_addr;
X			client->status = 1;
X			client->dest = (struct dtab *)0;
X		}
X
X		client->last_touched = now;
X	}
X
X	if(!force || !client->dest) {
X		/* select a proxy. dumb code to cycle them */
X		if(dest_next >= nproxies)
X			dest_next = 0;
X		target = &dest_tab[dest_next++];
X		if(force) {
X			client->dest = target;
X			target->nclients++;
X		}
X	}
X
X	if(log) {
X		char tmp[64]; /* big enough for IPv6, in ":" fmt */
X		sprintf(tmp, "to %s", inet_ntoa(target->addr.sin_addr));
X		logclient(p_addr.sin_addr, tmp);
X	}
X
X	return target;
X}
END-of-plug.c
echo x - plug.h
sed 's/^X//' >plug.h << 'END-of-plug.h'
X/*
X * PLUGDAEMON. Copyright (c) 1997 Peter da Silva. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The names of the program and author may not be used to endorse or
X *    promote products derived from this software without specific prior
X *    written permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
X * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
X * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
X * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
X * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
X * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
X * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X */
X
X#define MAX_PROXIES 32
X#define MAX_CLIENTS 16384 /* These are held for a whole timeout period */
X#define MAX_MTU 2048	/* not strictly MTU, but size of reads and writes */
X
X/* OS-specific variations in sigaction arguments */
X
X#ifdef sa_sigaction
X#define SA_HANDLER sa_sigaction
X#else
X#define SA_HANDLER sa_handler
X#endif
X
X#ifdef __OpenBSD__
X#define SA_HANDLER_ARG2_T siginfo_t *
X#else
X#define SA_HANDLER_ARG2_T int
X#endif
X
END-of-plug.h
echo x - proto.h
sed 's/^X//' >proto.h << 'END-of-proto.h'
X/*
X * PLUGDAEMON. Copyright (c) 1997 Peter da Silva. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The names of the program and author may not be used to endorse or
X *    promote products derived from this software without specific prior
X *    written permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
X * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
X * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
X * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
X * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
X * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
X * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
X * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X */
X
X#ifdef __STDC__
X#define P(a) a
X#define P0() (void)
X#define P1(a,b) (a b)
X#define P2(a,b,c,d) (a b, c d)
X#define P3(a,b,c,d,e,f) (a b, c d, e f)
X#else
X#define P(a) ()
X#define P0() ()
X#define P1(a,b) (b) a b;
X#define P2(a,b,c,d) (b) a b; c d;
X#define P3(a,b,c,d,e,f) (b) a b; c d; e f;
X#endif
X
Xvoid parse_args P((int ac, char **av));
Xvoid bailout P((char *message));
Xvoid logclient P((struct in_addr peer, char* status));
Xvoid fill_sockaddr_in P((struct sockaddr_in *buffer, u_long addr, u_short port));
Xvoid daemonize P((void));
Xvoid init_signals P((void));
Xvoid plug P((int fd1, int fd2));
Xstruct dtab *select_target P((int clifd));
X
END-of-proto.h
exit


