/* -*-c-*-
*
- * $Id$
- *
* Port forwarding thingy
*
* (c) 1999 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of the `fw' port forwarder.
*
* 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,
* 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,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <unistd.h>
-#include <syslog.h>
-
-#include <grp.h>
-#include <pwd.h>
-
-#include <mLib/bres.h>
-#include <mLib/dstr.h>
-#include <mLib/mdwopt.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-#include <mLib/sel.h>
-#include <mLib/sig.h>
-#include <mLib/sub.h>
-
-#include "conf.h"
-#include "endpt.h"
-#include "exec.h"
-#include "fattr.h"
-#include "file.h"
#include "fw.h"
-#include "privconn.h"
-#include "scan.h"
-#include "socket.h"
-#include "source.h"
/*----- Global variables --------------------------------------------------*/
if (strcmp(sc->d.buf, "forward") == 0 ||
strcmp(sc->d.buf, "fw") == 0 ||
- strcmp(sc->d.buf, "from") == 0) {
+ strcmp(sc->d.buf, "from") == 0) {
source *s;
target *t;
static void usage(FILE *fp)
{
- pquis(fp, "Usage: $ [-dql] [-f file] [config statements...]\n");
+ pquis(fp, "Usage: $ [-dql] [-p PIDFILE] [-f FILE] [CONFIG-STMTS...]\n");
}
static void help(FILE *fp)
usage(fp);
pquis(fp, "\n\
An excessively full-featured port-forwarder, which subsumes large chunks\n\
-of the functionality of inetd, netcat, and normal cat. Options available\n\
-are:\n\
-\n\
--h, --help Display this help message.\n\
--v, --version Display the program's version number.\n\
--u, --usage Display a terse usage summary.\n\
-\n\
--G, --grammar Show a summary of the configuration language.\n\
--O, --options Show a summary of the source and target options.\n\
-\n\
--f, --file=FILE Read configuration from a file.\n\
--q, --quiet Don't emit any logging information.\n\
--d, --daemon Fork into background after initializing.\n\
--l, --syslog Send log output to the system logger.\n\
--s, --setuid=USER Change uid to USER after initializing sources.\n\
--g, --setgid=GRP Change gid to GRP after initializing sources.\n\
+of the functionality of inetd, netcat, and normal cat.\n\
\n\
Configuration may be supplied in one or more configuration files, or on\n\
the command line (or both). If no `-f' option is present, and no\n\
\n\
The grammar is fairly complicated. For a summary, run `$ --grammar'.\n\
For a summary of the various options, run `$ --options'.\n\
+\n\
+Options available are:\n\
+\n\
+Help options:\n\
+ -h, --help Display this help message.\n\
+ -v, --version Display the program's version number.\n\
+ -u, --usage Display a terse usage summary.\n\
+\n\
+Configuration summary:\n\
+ -G, --grammar Show a summary of the configuration language.\n\
+ -O, --options Show a summary of the source and target options.\n\
+\n\
+Other options:\n\
+ -f, --file=FILE Read configuration from a file.\n\
+ -q, --quiet Don't emit any logging information.\n\
+ -d, --daemon Fork into background after initializing.\n\
+ -p, --pidfile=FILE Write process-id to the named FILE.\n\
+ -l, --syslog Send log output to the system logger.\n\
+ -s, --setuid=USER Change uid to USER after initializing sources.\n\
+ -g, --setgid=GRP Change gid to GRP after initializing sources.\n\
");
}
static void grammar(FILE *fp)
{
version(fp);
- pquis(fp, "\n\
-Grammar summary\n\
-\n\
-Basic syntax\n\
- FILE ::= EMPTY | FILE STMT [`;']\n\
- STMT ::= OPTION-STMT | FW-STMT\n\
- FW-STMT ::= `fw' SOURCE OPTIONS [`to'|`->'] TARGET OPTIONS\n\
- OPTIONS ::= `{' OPTION-SEQ `}'\n\
- OPTION-SEQ ::= EMPTY | OPTION-STMT [`;'] OPTION-SEQ\n\
-\n\
-Option syntax\n\
- OPTION-STMT ::= Q-OPTION\n\
- Q-OPTION ::= OPTION\n\
- | PREFIX `.' Q-OPTION\n\
- | PREFIX `{' OPTION-SEQ `}'\n\
- PREFIX ::= WORD\n\
-\n\
-File source and target\n\
- SOURCE ::= FILE\n\
- TARGET ::= FILE\n\
- FILE ::= `file' [`.'] FSPEC [`,' FSPEC]\n\
- FSPEC ::= FD-SPEC | NAME-SPEC | NULL-SPEC\n\
- FD-SPEC ::= [[`:']`fd'[`:']] NUMBER|`stdin'|`stdout'\n\
- NAME-SPEC ::= [[`:']`name'[`:']] FILE-NAME\n\
- FILE-NAME ::= PATH-SEQ | [ PATH-SEQ ]\n\
- PATH-SEQ ::= PATH-ELT | PATH-SEQ PATH-ELT\n\
- PATH-ELT ::= `/' | WORD\n\
- NULL-SPEC ::= [`:']`null'[`:']\n\
-\n\
-Exec source and target\n\
- SOURCE ::= EXEC\n\
- TARGET ::= EXEC\n\
- EXEC ::= `exec' [`.'] CMD-SPEC\n\
- CMD-SPEC ::= SHELL-CMD | [PROG-NAME] `[' ARGV0 ARG-SEQ `]'\n\
- ARG-SEQ ::= WORD | ARG-SEQ WORD\n\
- SHELL-CMD ::= WORD\n\
- ARGV0 ::= WORD\n\
-\n\
-Socket source and target\n\
- SOURCE ::= SOCKET-SOURCE\n\
- TARGET ::= SOCKET-TARGET\n\
- SOCKET-SOURCE ::= [`socket'[`.']] [[`:']ADDR-TYPE[`:']] SOURCE-ADDR\n\
- SOCKET-TARGET ::= [`socket'[`.']] [[`:']ADDR-TYPE[`:']] TARGET-ADDR\n\
-\n\
- INET-SOURCE-ADDR ::= [`port'] PORT\n\
- INET-TARGET-ADDR ::= ADDRESS [`:'] PORT\n\
- ADDRESS ::= ADDR-ELT | ADDRESS ADDR-ELT\n\
- ADDR-ELT ::= `.' | WORD\n\
-\n\
- UNIX-SOURCE-ADDR ::= FILE-NAME\n\
- UNIX-TARGET-ADDR ::= FILE-NAME\n\
-");
+ fputs("\nGrammar summary\n\n", fp);
+ fputs(grammar_text, fp);
}
static void options(FILE *fp)
{
version(fp);
- pquis(fp, "\n\
-Options summary\n\
-\n\
-File attributes (`fattr')\n\
- prefix.FATTR.MODE [=] MODE\n\
- prefix.FATTR.OWNER [=] USER\n\
- prefix.FATTR.GROUP [=] GROUP\n\
-\n\
-File options\n\
- file.create [=] yes|no\n\
- file.open [=] no|truncate|append\n\
- file.fattr.*\n\
-\n\
-Exec options\n\
- exec.logging [=] yes|no\n\
- exec.dir [=] FILE-NAME\n\
- exec.root [=] FILE-NAME\n\
- exec.user [=] USER\n\
- exec.group [=] GROUP\n\
- exec.rlimit.LIMIT[.hard|.soft] [=] VALUE\n\
- exec.env.clear\n\
- exec.env.unset VAR\n\
- exec.env.[set] VAR [=] VALUE\n\
-\n\
-Socket options\n\
- socket.conn [=] NUMBER|unlimited|one-shot\n\
- socket.listen [=] NUMBER\n\
- socket.logging [=] yes|no\n\
-\n\
- socket.inet.source.[allow|deny] [host] ADDR [/ ADDR]\n\
- socket.inet.source.[allow|deny] priv-port\n\
- socket.inet.source.addr [=] any|ADDR\n\
- socket.inet.dest.addr [=] any|ADDR\n\
- socket.inet.dest.priv-port [=] yes|no\n\
-\n\
- socket.unix.fattr.*\n\
-");
+ fputs("\nOption summary\n\n", fp);
+ fputs(option_text, fp);
}
/* --- @main@ --- *
flags |= FW_QUIET;
break;
case 's':
- if (isdigit((unsigned char )optarg[0])) {
+ if (isdigit((unsigned char )optarg[0])) {
char *q;
drop = strtol(optarg, &q, 0);
if (*q)
}
break;
case 'g':
- if (isdigit((unsigned char )optarg[0])) {
+ if (isdigit((unsigned char )optarg[0])) {
char *q;
dropg = strtol(optarg, &q, 0);
if (*q)
sig_add(&s_hup, SIGHUP, fw_reload, 0);
}
- /* --- Drop privileges --- */
-
- if (drop != (uid_t)-1)
- privconn_split(sel);
-#ifdef HAVE_SETGROUPS
- if ((dropg != (gid_t)-1 && (setgid(dropg) || setgroups(1, &dropg))) ||
- (drop != (uid_t)-1 && setuid(drop)))
- die(1, "couldn't drop privileges: %s", strerror(errno));
-#else
- if ((dropg != (gid_t)-1 && setgid(dropg)) ||
- (drop != (uid_t)-1 && setuid(drop)))
- die(1, "couldn't drop privileges: %s", strerror(errno));
-#endif
-
/* --- Fork into the background --- */
if (f & f_fork) {
openlog(QUIS, 0, LOG_DAEMON);
}
+ /* --- Drop privileges --- */
+
+ if (drop != (uid_t)-1)
+ privconn_split(sel);
+#ifdef HAVE_SETGROUPS
+ if ((dropg != (gid_t)-1 && (setgid(dropg) || setgroups(1, &dropg))) ||
+ (drop != (uid_t)-1 && setuid(drop)))
+ die(1, "couldn't drop privileges: %s", strerror(errno));
+#else
+ if ((dropg != (gid_t)-1 && setgid(dropg)) ||
+ (drop != (uid_t)-1 && setuid(drop)))
+ die(1, "couldn't drop privileges: %s", strerror(errno));
+#endif
+
/* --- Let rip --- */
if (!(flags & FW_SET))
int selerr = 0;
while (active) {
if (!sel_select(sel))
- selerr = 0;
+ selerr = 0;
else if (errno != EINTR && errno != EAGAIN) {
fw_log(-1, "error from select: %s", strerror(errno));
selerr++;
}
}
}
-
+
return (0);
}