### -*-makefile-*-
###
- ### Makefile for fw
+ ### Makefile for fwd
###
### (c) 1999 Mark Wooding
###
###----- Licensing notice ---------------------------------------------------
###
- ### This file is part of the `fw' port forwarder.
+ ### This file is part of the `fwd' port forwarder.
###
- ### `fw' is free software; you can redistribute it and/or modify
+ ### `fwd' 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.
###
- ### `fw' is distributed in the hope that it will be useful,
+ ### `fwd' 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 `fw'; if not, write to the Free Software Foundation,
+ ### along with `fwd'; if not, write to the Free Software Foundation,
### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
bin_PROGRAMS =
+noinst_PROGRAMS =
man_MANS =
EXTRA_DIST =
###--------------------------------------------------------------------------
### Documentation.
- make_manpage = perl $(srcdir)/make-manpage <$(srcdir)/fw.1.in
- EXTRA_DIST += fw.1.in make-manpage
+ make_manpage = perl $(srcdir)/make-manpage <$(srcdir)/fwd.1.in
+ EXTRA_DIST += fwd.1.in make-manpage
## The manual page.
- man_MANS += fw.1
- CLEANFILES += fw.1
+ man_MANS += fwd.1
+ CLEANFILES += fwd.1
- fw.1: fw.1.in make-manpage
+ fwd.1: fwd.1.in make-manpage
$(make_manpage) man >$@.new && mv $@.new $@
## The grammar summary.
MAINTAINERCLEANFILES += $(srcdir)/GRAMMAR
EXTRA_DIST += GRAMMAR
- $(srcdir)/GRAMMAR: fw.1.in make-manpage
+ $(srcdir)/GRAMMAR: fwd.1.in make-manpage
$(make_manpage) text >$@.new && mv $@.new $@
###--------------------------------------------------------------------------
### The main port forwarder.
- bin_PROGRAMS += fw
- fw_SOURCES =
- fw_LDADD = $(mLib_LIBS)
+ bin_PROGRAMS += fwd
+ fwd_SOURCES =
+ fwd_LDADD = $(mLib_LIBS)
## Main program.
- fw_SOURCES += fw.c fw.h
+ fwd_SOURCES += fwd.c fwd.h
- fw_SOURCES += chan.c
- fw_SOURCES += endpt.c
- fw_SOURCES += source.c
+ fwd_SOURCES += chan.c
+ fwd_SOURCES += endpt.c
+ fwd_SOURCES += source.c
- fw_SOURCES += conf.c
- fw_SOURCES += scan.c
- fw_SOURCES += fattr.c
+ fwd_SOURCES += conf.c
+ fwd_SOURCES += scan.c
+ fwd_SOURCES += fattr.c
- fw_SOURCES += reffd.c
+ fwd_SOURCES += reffd.c
## Sockets.
- fw_SOURCES += socket.c
+ fwd_SOURCES += socket.c
- fw_SOURCES += un.c
+ fwd_SOURCES += un.c
- fw_SOURCES += inet.c
- fw_SOURCES += acl.c
- fw_SOURCES += identify.c
- fw_SOURCES += privconn.c
+ fwd_SOURCES += inet.c
+ fwd_SOURCES += acl.c
+ fwd_SOURCES += identify.c
+ fwd_SOURCES += privconn.c
## Files.
- fw_SOURCES += file.c
+ fwd_SOURCES += file.c
## Executables.
- fw_SOURCES += exec.c
- fw_SOURCES += rlimits.h
+ fwd_SOURCES += exec.c
+ fwd_SOURCES += rlimits.h
## Documentation.
- fw_SOURCES += mantext.c
+ fwd_SOURCES += mantext.c
CLEANFILES += mantext.c
BUILT_SOURCES += mantext.c
- mantext.c: fw.1.in make-manpage
+ mantext.c: fwd.1.in make-manpage
$(make_manpage) c >$@.new && mv $@.new $@
+###--------------------------------------------------------------------------
+### The blast tool.
+
+noinst_PROGRAMS += blast
+blast_SOURCES = blast.c
+blast_LDADD = $(mLib_LIBS)
+
###--------------------------------------------------------------------------
### Other infrastructure.
EXTRA_DIST += debian/copyright
## Run the daemon automatically.
- EXTRA_DIST += debian/fw.init
- EXTRA_DIST += debian/fw.postinst
+ EXTRA_DIST += debian/fwd.init
+ EXTRA_DIST += debian/fwd.postinst
+
+ ## Compatbility cruft.
+ EXTRA_DIST += debian/fw.sh
+ EXTRA_DIST += debian/fw.README.Debian
###----- That's all, folks --------------------------------------------------
.\" -*-nroff-*-
.\"
- .\" Manual page for fw
+ .\" Manual page for fwd
.\"
.\" (c) 1999 Straylight/Edgeware
.\"
.
.\"----- Licensing notice ---------------------------------------------------
.\"
- .\" This file is part of the `fw' port forwarder.
+ .\" This file is part of the `fwd' port forwarder.
.\"
- .\" `fw' is free software; you can redistribute it and/or modify
+ .\" `fwd' 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.
.\"
- .\" `fw' is distributed in the hope that it will be useful,
+ .\" `fwd' 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 `fw'; if not, write to the Free Software Foundation,
+ .\" along with `fwd'; if not, write to the Free Software Foundation,
.\" Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
.
.\"----- Various bits of fancy styling --------------------------------------
.
.\"--------------------------------------------------------------------------
.
- .TH fw 1 "1 July 1999" "Straylight/Edgeware" "fw port forwarder"
+ .TH fwd 1 "1 July 1999" "Straylight/Edgeware" "fwd port forwarder"
.
.\"--------------------------------------------------------------------------
.SH NAME
.
- fw \- port forwarder
+ fwd \- port forwarder
.
.\"--------------------------------------------------------------------------
.SH SYNOPSIS
.
- .B fw
+ .B fwd
.RB [ \-dlq ]
.RB [ \-p
.IR file ]
.SH "DESCRIPTION"
.
The
- .B fw
+ .B fwd
program is a simple port forwarder. It supports a number of features
the author hasn't found in similar programs:
.TP
Unix domain sockets, though. (Yet.)
.SS "Command line options"
The
- .B fw
+ .B fwd
program understands a few simple command line options:
.TP
.B "\-h, \-\-help"
.TP
.BI "\-p, \-\-pidfile=" file
Write
- .BR fw 's
+ .BR fwd 's
process-id to
.I file
during start-up. If
.SH "CONFIGURATION LANGUAGE"
.
The
- .B fw
+ .B fwd
program has a fairly sophisticated configuration language to let you
describe which things should be forwarded where and what special
features there should be.
::=
.I option-stmt
|
- .I fw-stmt
+ .I fwd-stmt
.br
- .I fw-stmt
+ .I fwd-stmt
::=
- .B fw
+ .B fwd
.I source
.I options
.RB [ to | \-> ]
.I option-seq
.GE
If you prefer, the keyword
- .RB ` fw '
+ .RB ` fwd '
may be spelt
- .RB ` forward '
+ .RB ` fwd ',
+ .RB ` forward ',
or
.RB ` from '.
All are equivalent.
destination server is the target.
.PP
Essentially, all
- .B fw
+ .B fwd
does is set up a collection of sources and targets based on your
configuration file so that when a source decides to initiate a data
flow, it tells its target to set its end up, and then squirts data back
.IR transient :
they set up one connection and then disappear. If all the sources
defined are transient, then
- .B fw
+ .B fwd
will quit when no more active sources remain and all connections have
terminated.
.PP
The
- .B fw
+ .B fwd
program is fairly versatile. It allows you to attach any supported type
of source to any supported type of target. This will, I hope, be the
case in all future versions.
.
.SS "Options structure"
Most of the objects that
- .B fw
+ .B fwd
knows about (including sources and targets, but also other more specific
things such as socket address types) can have their behaviour modified
by
on the
.IR context .
A global option, outside of a
- .I fw-stmt
+ .I fwd-stmt
has no context unless it is explicitly qualified, and affects global
behaviour. A local option, applied to a source or target in a
- .IR fw-stmt ,
+ .IR fwd-stmt ,
has the context of the type of source or target to which it is applied,
and affects only that source or target.
.PP
.BR exec.logging ,
which have separate defaults, and which one you actually get depends on
the exact implementation of
- .BR fw 's
+ .BR fwd 's
option parser. (Currently this would resolve to
.BR exec.logging ,
although this may change in a later version.)
.OE
.PP
Under no circumstances will
- .B fw
+ .B fwd
create a file through a `dangling' symbolic link.
.
.SS "The `exec' source and target types"
.PP
The standard input and output of the program are forwarded to the other
end of the connection. The standard error stream is caught by
- .B fw
+ .B fwd
and logged.
.PP
The
Socket sources support options; socket targets do not. The source
options provided are:
.OS "Socket options"
+.BR socket. [ accept | accept-count ]
+.RB [ = ]
+.IR number | \c
+.B unlimited
+.OD
+Controls the number of connections that
+.B fw
+accepts at a time on a particular socket. This parameter affects how
+.B fw
+prioritizes between keeping up with connection turnover and processing
+existing connections. The default is 1, which strongly favours existing
+connections. The special value
+.B unlimited
+(or
+.BR infinite )
+removes any limit, and therefore favours connection turnover.
+.OE
+.OS "Socket options"
.B socket.conn
.RB [ = ]
.IR number | \c
.OD
Make a privileged connection (i.e., from a low-numbered port) to the
target. This only works if
- .B fw
+ .B fwd
was started with root privileges. However, it still works if
- .B fw
+ .B fwd
has
.I dropped
privileges after initialization (the
.B \-s
option). Before dropping privileges,
- .B fw
+ .B fwd
forks off a separate process which continues to run with root
privileges, and on demand passes sockets bound to privileged ports and
connected to the appropriate peer back to the main program. The
privileged child only passes back sockets connected to peer addresses
named in the configuration; even if the
- .B fw
+ .B fwd
process is compromised, it can't make privileged connections to other
addresses. Note that because of this privilege separation, it's also
not possible to reconfigure
- .B fw
+ .B fwd
to make privileged connections to different peer addresses later by
changing configuration files and sending the daemon a
.BR SIGHUP .
.OE
.PP
Sockets are removed if
- .B fw
+ .B fwd
exits normally (which it will do if it runs out of sources or
connections, or if
- .B fw
+ .B fwd
shuts down in a clean way).
.SH "EXAMPLES"
To forward the local port 25 to a main mail server:
.SH "SIGNAL HANDLING"
.
The
- .B fw
+ .B fwd
program responds to various signals when it's running. If it receives
.B SIGTERM
or
.BR SIGINT ,
- .B fw
+ .B fwd
performs a
.I graceful
shutdown: it removes all of its sources, and will exit when no more
connections are running. (Note that if the disposition
.B SIGINT
was to ignore it,
- .B fw
+ .B fwd
does not re-enable the signal. You'll have to send
.B SIGTERM
in that case.) If
- .B fw
+ .B fwd
receives
.BR SIGQUIT ,
it performs an
.PP
Finally, if any configuration files (other than standard input) were
provided to
- .B fw
+ .B fwd
on its command line using the
.B \-f
option, a
.B SIGHUP
signal may be sent to instruct
- .B fw
+ .B fwd
to reload its configuration. Any existing connections are allowed to
run their course. If no such configuration files are available,
- .B fw
+ .B fwd
just logs a message about the signal and continues.
.
.\"--------------------------------------------------------------------------
The syntax for IP addresses and filenames is nasty.
.PP
IPv6 is not supported yet. Because of
- .BR fw 's
+ .BR fwd 's
socket address architecture, it's probably not a major piece of work to
add.
.PP
/*----- Licensing notice --------------------------------------------------*
*
- * This file is part of the `fw' port forwarder.
+ * This file is part of the `fwd' port forwarder.
*
- * `fw' is free software; you can redistribute it and/or modify
+ * `fwd' 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.
*
- * `fw' is distributed in the hope that it will be useful,
+ * `fwd' 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 `fw'; if not, write to the Free Software Foundation,
+ * along with `fwd'; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
- #include "fw.h"
+ #include "fwd.h"
/*----- Data structures ---------------------------------------------------*/
unsigned opt;
unsigned conn;
unsigned listen;
+ unsigned naccept;
} ssource_opts;
-static ssource_opts ssgo = { 256, 0, 5 };
+static ssource_opts ssgo = { 256, 0, 5, 1 };
#define SOCKOPT_LIMIT 0u
#define SOCKOPT_NOLIMIT 1u
CONF_ACCEPT;
}
+ if (strcmp(sc->d.buf, "accept") == 0 ||
+ strcmp(sc->d.buf, "accept-count") == 0) {
+ token(sc);
+ if (sc->t == '=')
+ token(sc);
+ if (sc->t != CTOK_WORD)
+ error(sc, "parse error, expected `unlimited' or number");
+ else if (isdigit((unsigned char)sc->d.buf[0])) {
+ sso->naccept = atoi(sc->d.buf);
+ if (sso->naccept == 0)
+ error(sc, "argument of `accept-count' must be positive");
+ } else {
+ sso->naccept = 0;
+ conf_enum(sc, "unlimited,infinite",
+ ENUM_ABBREV, "`accept-count' option");
+ }
+ token(sc);
+ CONF_ACCEPT;
+ }
+
if (strcmp(sc->d.buf, "logging") == 0 ||
strcmp(sc->d.buf, "log") == 0) {
addr_opts *ao = ss ? ss->ao : &gsao;
ss->a = getaddr(sc, ADDR_SRC);
if (ss->a->ops->initsrcopts)
ss->ao = ss->a->ops->initsrcopts();
- else {
+ else
ss->ao = CREATE(addr_opts);
- *ss->ao = gsao;
- }
+ *ss->ao = gsao;
ss->o = ssgo;
return (&ss->s);
}
ssept *e;
endpt *ee;
reffd *r;
+ int acceptp = 1;
+ unsigned i = 0;
- /* --- Make the file descriptor --- */
+ while (acceptp) {
- {
- int opt = 1;
- if ((r = ss->a->ops->accept(fd, ss->ao, ss->s.desc)) == 0)
- return;
- setsockopt(r->fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
- fdflags(r->fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
- }
-
- /* --- Make an endpoint --- */
+ /* --- Make the file descriptor --- */
- e = CREATE(ssept);
- e->e.ops = &ssept_ops;
- e->e.other = 0;
- e->e.f = EPF_FILE;
- e->e.t = 0;
- e->e.in = e->e.out = r;
- e->s = ss;
- REFFD_INC(r);
+ {
+ int opt = 1;
+ if ((r = ss->a->ops->accept(fd, ss->ao, ss->s.desc)) == 0)
+ return;
+ setsockopt(r->fd, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
+ fdflags(r->fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+ }
- /* --- Obtain the target endpoint and let rip --- */
+ /* --- Make an endpoint --- */
- if ((ee = ss->t->ops->create(ss->t, ss->s.desc)) == 0) {
- REFFD_DEC(r);
- REFFD_DEC(r);
- DESTROY(e);
- return;
- }
- fw_inc();
+ e = CREATE(ssept);
+ e->e.ops = &ssept_ops;
+ e->e.other = 0;
+ e->e.f = EPF_FILE;
+ e->e.t = 0;
+ e->e.in = e->e.out = r;
+ e->s = ss;
+ REFFD_INC(r);
- /* --- Remove the listening socket if necessary --- */
+ /* --- Obtain the target endpoint and let rip --- */
- switch (ss->o.opt) {
- case SOCKOPT_LIMIT:
- ss->o.conn--;
- if (!ss->o.conn) {
- if (!(ss->ao->f & ADDRF_NOLOG))
- fw_log(-1, "[%s] maximum connections reached", ss->s.desc);
+ if ((ee = ss->t->ops->create(ss->t, ss->s.desc)) == 0) {
+ REFFD_DEC(r);
+ REFFD_DEC(r);
+ DESTROY(e);
+ return;
+ }
+ fw_inc();
+
+ /* --- Note that we've done one --- */
+
+ i++;
+ if (i >= ss->o.naccept)
+ acceptp = 0;
+
+ /* --- Remove the listening socket if necessary --- */
+
+ switch (ss->o.opt) {
+ case SOCKOPT_LIMIT:
+ ss->o.conn--;
+ if (!ss->o.conn) {
+ if (!(ss->ao->f & ADDRF_NOLOG))
+ fw_log(-1, "[%s] maximum connections reached", ss->s.desc);
+ sel_rmfile(&ss->r);
+ close(ss->r.fd);
+ if (ss->a->ops->unbind)
+ ss->a->ops->unbind(ss->a);
+ acceptp = 0;
+ }
+ break;
+ case SOCKOPT_NOLIMIT:
+ break;
+ case SOCKOPT_ONESHOT:
sel_rmfile(&ss->r);
close(ss->r.fd);
if (ss->a->ops->unbind)
ss->a->ops->unbind(ss->a);
- }
- break;
- case SOCKOPT_NOLIMIT:
- break;
- case SOCKOPT_ONESHOT:
- sel_rmfile(&ss->r);
- close(ss->r.fd);
- if (ss->a->ops->unbind)
- ss->a->ops->unbind(ss->a);
- ssource_destroy(&ss->s);
- break;
- }
+ ssource_destroy(&ss->s);
+ acceptp = 0;
+ break;
+ }
- /* --- Let everything else happen --- */
+ /* --- Let everything else happen --- */
- endpt_join(&e->e, ee);
+ endpt_join(&e->e, ee);
+ }
}
/* --- @ss_listen@ --- *