Various changes. Add configuration grammar to help text. Change to
[fwd] / fw.c
CommitLineData
e82f7154 1/* -*-c-*-
2 *
afd7451e 3 * $Id: fw.c,v 1.2 1999/07/03 13:55:17 mdw Exp $
e82f7154 4 *
5 * Port forwarding thingy
6 *
7 * (c) 1999 Mark Wooding
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the `fw' port forwarder.
13 *
14 * `fw' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * `fw' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with `fw'; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: fw.c,v $
afd7451e 32 * Revision 1.2 1999/07/03 13:55:17 mdw
33 * Various changes. Add configuration grammar to help text. Change to
34 * root directory and open syslog when forking into background.
35 *
36 * Revision 1.1.1.1 1999/07/01 08:56:23 mdw
37 * Initial revision.
e82f7154 38 *
39 */
40
41/*----- Header files ------------------------------------------------------*/
42
43#include "config.h"
44
45#include <ctype.h>
46#include <errno.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50
51#include <unistd.h>
52#include <syslog.h>
53
54#include <mLib/mdwopt.h>
55#include <mLib/quis.h>
56#include <mLib/report.h>
57#include <mLib/sel.h>
58#include <mLib/sub.h>
59
60#include "acl.h"
61#include "bres.h"
62#include "conf.h"
afd7451e 63#include "fw.h"
e82f7154 64#include "listener.h"
65#include "scan.h"
66
afd7451e 67/*----- Global variables --------------------------------------------------*/
e82f7154 68
69sel_state *sel; /* Multiplexor for nonblocking I/O */
afd7451e 70unsigned flags = 0; /* Global state flags */
e82f7154 71
72/*----- Main code ---------------------------------------------------------*/
73
74/* --- Standard GNU help options --- */
75
76static void version(FILE *fp)
77{
78 fprintf(fp, "%s version " VERSION "\n", QUIS);
79}
80
81static void usage(FILE *fp)
82{
afd7451e 83 fprintf(stderr, "Usage: %s [-db] [-f file] [config statements...]\n",
e82f7154 84 QUIS);
85}
86
87static void help(FILE *fp)
88{
89 version(fp);
90 fputc('\n', fp);
91 usage(fp);
92 fputs("\n\
93A fairly full-featured port-forwarder. Options available are:\n\
94\n\
95-h, --help Display this help message.\n\
96-v, --version Display the program's version number.\n\
97-u, --usage Display a terse usage summary.\n\
98\n\
99-f, --file=FILE Read configuration from a file.\n\
100-d, --dump Dump the configuration to standard output.\n\
afd7451e 101-b, --background Fork into background after initializing.\n\
e82f7154 102\n\
103Configuration may be supplied in one or more configuration files, or on\n\
104the command line (or both). If no `-f' option is present, and no\n\
105configuration is given on the command line, the standard input stream is\n\
106read.\n\
107\n\
108Configuration is free-form. Comments begin with a `#' character and\n\
afd7451e 109continue to the end of the line. Each command line argument is considered\n\
110to be a separate line. The syntax is as follows:\n\
111\n\
112config : stmt...\n\
113stmt : fwd-stmt | acl-stmt\n\
114fwd-stmt : `forward' [`port'] port [`to'] addr [`:'] port [fwd-attr] [`;']\n\
115fwd-attr : `{' acl-stmt... `}'\n\
116acl-stmt : (`allow' | `deny') [`from'] addr [`/' mask] [`;']\n\
e82f7154 117", fp);
118}
119
120/* --- @main@ --- *
121 *
122 * Arguments: @int argc@ = number of command line arguments
123 * @char *argv[]@ = vector of argument strings
124 *
125 * Returns: ---
126 *
127 * Use: Simple port-forwarding server.
128 */
129
130int main(int argc, char *argv[])
131{
132 unsigned f = 0;
133 sel_state sst;
134
135 enum {
136 f_bogus = 1,
137 f_file = 2,
138 f_dump = 4,
139 f_fork = 8
140 };
141
142 /* --- Initialize things --- */
143
144 ego(argv[0]);
145 sel = &sst;
146 sel_init(sel);
147 sub_init();
148 bres_init(sel);
149
150 /* --- Parse command line options --- */
151
152 for (;;) {
153 static struct option opts[] = {
154
155 /* --- Standard GNU help options --- */
156
157 { "help", 0, 0, 'h' },
158 { "version", 0, 0, 'v' },
159 { "usage", 0, 0, 'u' },
160
161 /* --- Other useful arguments --- */
162
163 { "file", OPTF_ARGREQ, 0, 'f' },
164 { "dump", 0, 0, 'd' },
165 { "fork", 0, 0, 'b' },
166 { "background", 0, 0, 'b' },
167
168 /* --- Magic terminator --- */
169
170 { 0, 0, 0, 0 }
171 };
172 int i = mdwopt(argc, argv, "hvu f:db", opts, 0, 0, 0);
173
174 if (i < 0)
175 break;
176 switch (i) {
177 case 'h':
178 help(stdout);
179 exit(0);
180 break;
181 case 'v':
182 version(stdout);
183 exit(0);
184 break;
185 case 'u':
186 usage(stdout);
187 exit(0);
188 break;
189 case 'f': {
190 scan_filectx ctx;
191 FILE *fp;
192 if ((fp = fopen(optarg, "r")) == 0)
193 die(1, "couldn't open file `%s': %s", optarg, strerror(errno));
194 scan_fileinit(&ctx, fp, optarg);
195 conf_parse(&ctx);
196 fclose(fp);
197 f |= f_file;
198 } break;
199 case 'd':
200 f |= f_dump;
201 break;
202 case 'b':
203 f |= f_fork;
204 break;
205 default:
206 f |= f_bogus;
207 break;
208 }
209 }
210
211 if (f & f_bogus) {
212 usage(stderr);
213 exit(1);
214 }
215
216 /* --- Deal with the remaining arguments --- */
217
218 if (optind == argc) {
219 if (f & f_file)
220 /* Cool */;
221 else if (isatty(STDIN_FILENO)) {
222 moan("no configuration given and stdin is a terminal.");
223 moan("type `%s --help' for usage information.", QUIS);
224 exit(1);
225 } else {
226 scan_filectx ctx;
227 scan_fileinit(&ctx, stdin, "<stdin>");
228 conf_parse(&ctx);
229 }
230 } else {
231 scan_argvctx ctx;
232 scan_argvinit(&ctx, argv + optind);
233 conf_parse(&ctx);
234 }
235
236 /* --- Dump out the state --- */
237
238 if (f & f_dump) {
239 sel_file *s;
240 fputs("global acl:\n", stdout);
241 acl_dump(0, stdout);
242 for (s = sel->files; s; s = s->next)
243 listener_dump((listener *)s, stdout);
244 exit(0);
245 }
246
247 /* --- Fork into the background --- */
248
249 if (f & f_fork) {
250 pid_t kid;
251
252 kid = fork();
253 if (kid == -1)
254 die(1, "couldn't fork: %s", strerror(errno));
255 if (kid != 0)
256 _exit(0);
257
258 close(0); close(1); close(2);
afd7451e 259 chdir("/");
e82f7154 260 setsid();
261
262 kid = fork();
263 if (kid != 0)
264 _exit(0);
afd7451e 265
266 flags |= FW_SYSLOG;
267 openlog(QUIS, 0, LOG_DAEMON);
e82f7154 268 }
269
270 /* --- Let rip --- */
271
e82f7154 272 for (;;)
273 sel_select(sel);
274 return (0);
275}
276
277/*----- That's all, folks -------------------------------------------------*/