X-Git-Url: https://git.distorted.org.uk/~mdw/fwd/blobdiff_plain/5f12a82af4f05d7677ad7661516d13c280f0d70e..61e3dbdf67c571ec4973ab19475ced6a438ab8df:/fw.c diff --git a/fw.c b/fw.c index 04235d4..202c3e7 100644 --- a/fw.c +++ b/fw.c @@ -1,10 +1,10 @@ /* -*-c-*- * - * $Id: fw.c,v 1.2 1999/07/03 13:55:17 mdw Exp $ + * $Id: fw.c,v 1.3 1999/07/26 23:30:42 mdw Exp $ * * Port forwarding thingy * - * (c) 1999 Mark Wooding + * (c) 1999 Straylight/Edgeware */ /*----- Licensing notice --------------------------------------------------* @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: fw.c,v $ + * Revision 1.3 1999/07/26 23:30:42 mdw + * Major reconstruction work for new design. + * * Revision 1.2 1999/07/03 13:55:17 mdw * Various changes. Add configuration grammar to help text. Change to * root directory and open syslog when forking into background. @@ -44,33 +47,136 @@ #include #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include #include +#include #include -#include "acl.h" #include "bres.h" #include "conf.h" +#include "endpt.h" +#include "exec.h" +#include "fattr.h" #include "fw.h" -#include "listener.h" #include "scan.h" +#include "source.h" /*----- Global variables --------------------------------------------------*/ sel_state *sel; /* Multiplexor for nonblocking I/O */ -unsigned flags = 0; /* Global state flags */ + +/*----- Static variables --------------------------------------------------*/ + +static unsigned flags = 0; /* Global state flags */ +static unsigned active = 0; /* Number of active things */ + +#define FW_SYSLOG 1u +#define FW_QUIET 2u +#define FW_SET 4u /*----- Main code ---------------------------------------------------------*/ +/* --- @fw_log@ --- * + * + * Arguments: @time_t t@ = when the connection occurred or (@-1@) + * @const char *fmt@ = format string to fill in + * @...@ = other arguments + * + * Returns: --- + * + * Use: Logs a connection. + */ + +void fw_log(time_t t, const char *fmt, ...) +{ + struct tm *tm; + dstr d = DSTR_INIT; + va_list ap; + + if (flags & FW_QUIET) + return; + + if (t == -1) + t = time(0); + tm = localtime(&t); + DENSURE(&d, 64); + d.len += strftime(d.buf, d.sz, "%Y-%m-%d %H:%M:%S", tm); + DPUTC(&d, ' '); + va_start(ap, fmt); + dstr_vputf(&d, fmt, ap); + va_end(ap); + if (flags & FW_SYSLOG) + syslog(LOG_NOTICE, "%s", d.buf); + else { + DPUTC(&d, '\n'); + dstr_write(&d, stderr); + } + DDESTROY(&d); +} + +/* --- @fw_inc@, @fw_dec@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Increments or decrements the active thing count. `fw' won't + * quit while there are active things. + */ + +void fw_inc(void) { flags |= FW_SET; active++; } +void fw_dec(void) { if (active) active--; } + +/* --- @fw_exit@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Exits when appropriate. + */ + +static void fw_exit(void) +{ + endpt_killall(); + source_killall(); +} + +/* --- @fw_tidy@ --- * + * + * Arguments: @int n@ = signal number + * @void *p@ = an uninteresting argument + * + * Returns: --- + * + * Use: Handles various signals and causes a clean tidy-up. + */ + +static void fw_tidy(int n, void *p) +{ + const char *sn = "unexpected signal (bug!)"; + if (n == SIGTERM) + sn = "SIGTERM"; + else if (n == SIGINT) + sn = "SIGINT"; + + fw_log(-1, "closing down on %s", sn); + fw_exit(); +} + /* --- Standard GNU help options --- */ static void version(FILE *fp) @@ -90,15 +196,16 @@ static void help(FILE *fp) fputc('\n', fp); usage(fp); fputs("\n\ -A fairly full-featured port-forwarder. Options available are:\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\ -f, --file=FILE Read configuration from a file.\n\ --d, --dump Dump the configuration to standard output.\n\ --b, --background Fork into background after initializing.\n\ +-d, --daemon Fork into background after initializing.\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\ @@ -107,13 +214,9 @@ read.\n\ \n\ Configuration is free-form. Comments begin with a `#' character and\n\ continue to the end of the line. Each command line argument is considered\n\ -to be a separate line. The syntax is as follows:\n\ +to be a separate line.\n\ \n\ -config : stmt...\n\ -stmt : fwd-stmt | acl-stmt\n\ -fwd-stmt : `forward' [`port'] port [`to'] addr [`:'] port [fwd-attr] [`;']\n\ -fwd-attr : `{' acl-stmt... `}'\n\ -acl-stmt : (`allow' | `deny') [`from'] addr [`/' mask] [`;']\n\ +The syntax is too complicated to describe here. Read the manual.\n\ ", fp); } @@ -131,11 +234,12 @@ int main(int argc, char *argv[]) { unsigned f = 0; sel_state sst; + sig s_term, s_int; + scanner sc; enum { f_bogus = 1, f_file = 2, - f_dump = 4, f_fork = 8 }; @@ -145,7 +249,17 @@ int main(int argc, char *argv[]) sel = &sst; sel_init(sel); sub_init(); + sig_init(sel); bres_init(sel); + exec_init(); + fattr_init(&fattr_global); + scan_create(&sc); + + /* --- Set up some signal handlers --- */ + + sig_add(&s_term, SIGTERM, fw_tidy, 0); + sig_add(&s_int, SIGINT, fw_tidy, 0); + atexit(fw_exit); /* --- Parse command line options --- */ @@ -161,15 +275,15 @@ int main(int argc, char *argv[]) /* --- Other useful arguments --- */ { "file", OPTF_ARGREQ, 0, 'f' }, - { "dump", 0, 0, 'd' }, - { "fork", 0, 0, 'b' }, - { "background", 0, 0, 'b' }, + { "fork", 0, 0, 'd' }, + { "daemon", 0, 0, 'd' }, + { "quiet", 0, 0, 'q' }, /* --- Magic terminator --- */ { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "hvu f:db", opts, 0, 0, 0); + int i = mdwopt(argc, argv, "+hvu f:d", opts, 0, 0, 0); if (i < 0) break; @@ -186,22 +300,23 @@ int main(int argc, char *argv[]) usage(stdout); exit(0); break; - case 'f': { - scan_filectx ctx; - FILE *fp; - if ((fp = fopen(optarg, "r")) == 0) - die(1, "couldn't open file `%s': %s", optarg, strerror(errno)); - scan_fileinit(&ctx, fp, optarg); - conf_parse(&ctx); - fclose(fp); + case 'f': + if (strcmp(optarg, "-") == 0) + scan_add(&sc, scan_file(stdin, "", SCF_NOCLOSE)); + else { + FILE *fp; + if ((fp = fopen(optarg, "r")) == 0) + die(1, "couldn't open file `%s': %s", optarg, strerror(errno)); + scan_add(&sc, scan_file(fp, optarg, 0)); + } f |= f_file; - } break; - case 'd': - f |= f_dump; break; - case 'b': + case 'd': f |= f_fork; break; + case 'q': + flags |= FW_QUIET; + break; default: f |= f_bogus; break; @@ -215,34 +330,21 @@ int main(int argc, char *argv[]) /* --- Deal with the remaining arguments --- */ - if (optind == argc) { - if (f & f_file) - /* Cool */; - else if (isatty(STDIN_FILENO)) { - moan("no configuration given and stdin is a terminal."); - moan("type `%s --help' for usage information.", QUIS); - exit(1); - } else { - scan_filectx ctx; - scan_fileinit(&ctx, stdin, ""); - conf_parse(&ctx); - } - } else { - scan_argvctx ctx; - scan_argvinit(&ctx, argv + optind); - conf_parse(&ctx); + if (optind < argc) + scan_add(&sc, scan_argv(argv + optind)); + else if (f & f_file) + /* Cool */; + else if (!isatty(STDIN_FILENO)) + scan_add(&sc, scan_file(stdin, "", SCF_NOCLOSE)); + else { + moan("no configuration given and stdin is a terminal."); + moan("type `%s --help' for usage information.", QUIS); + exit(1); } - /* --- Dump out the state --- */ + /* --- Parse the configuration now gathered --- */ - if (f & f_dump) { - sel_file *s; - fputs("global acl:\n", stdout); - acl_dump(0, stdout); - for (s = sel->files; s; s = s->next) - listener_dump((listener *)s, stdout); - exit(0); - } + conf_parse(&sc); /* --- Fork into the background --- */ @@ -269,7 +371,10 @@ int main(int argc, char *argv[]) /* --- Let rip --- */ - for (;;) + if (!(flags & FW_SET)) + moan("nothing to do!"); + signal(SIGPIPE, SIG_IGN); + while (active) sel_select(sel); return (0); }