aboutsummaryrefslogtreecommitdiff
path: root/sbin/ipfw
diff options
context:
space:
mode:
authorJoerg Wunsch <joerg@FreeBSD.org>1998-11-23 10:54:28 +0000
committerJoerg Wunsch <joerg@FreeBSD.org>1998-11-23 10:54:28 +0000
commitaa045fa499198eb2eb8470a800289fd6c40cff0d (patch)
treed68f0aaa28e9ff5f3d77edb0354c068bb461f65d /sbin/ipfw
parentc2906d55d0f9138083cafab87721c473d901ad4c (diff)
downloadsrc-aa045fa499198eb2eb8470a800289fd6c40cff0d.tar.gz
src-aa045fa499198eb2eb8470a800289fd6c40cff0d.zip
Notes
Diffstat (limited to 'sbin/ipfw')
-rw-r--r--sbin/ipfw/ipfw.833
-rw-r--r--sbin/ipfw/ipfw.c127
2 files changed, 145 insertions, 15 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index bd70c5822db8..d7f8cd81b142 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -6,8 +6,11 @@
.Nd controlling utility for IP firewall
.Sh SYNOPSIS
.Nm ipfw
+.Op Fl q
.Oo
-.Fl q
+.Fl p Ar preproc
+.Op Fl D Ar macro Ns Op Ns =value
+.Op Fl U Ar macro
.Oc
file
.Nm ipfw
@@ -58,6 +61,32 @@ will be read line by line and applied as arguments to the
.Nm
command.
.Pp
+Optionally, a preprocessor can be specified using
+.Fl p Ar preproc
+where
+.Ar file
+is to be piped through. Useful preprocessors include
+.Xr cpp 1
+and
+.Xr m4 1 .
+If
+.Ar preproc
+doesn't start with a slash as its first character, the usual
+.Ev PATH
+name search is performed. Care should be taken with this in environments
+where not all filesystems are mounted (yet) by the time
+.Nm
+is being run (e. g. since they are mounted over NFS). Once
+.Fl p
+has been specified, optional
+.Fl D
+and
+.Fl U
+specifcations can follow and will be passed on to the preprocessor.
+This allows for flexible configuration files (like conditionalizing
+them on the local hostname) and the use of macros to centralize
+frequently required arguments like IP addresses.
+.Pp
The
.Nm
code works by going through the rule-list for each packet,
@@ -515,6 +544,8 @@ This rule diverts all incoming packets from 192.168.2.0/24 to divert port 5000:
.Pp
.Dl ipfw divert 5000 all from 192.168.2.0/24 to any in
.Sh SEE ALSO
+.Xr cpp 1 ,
+.Xr m4 1 ,
.Xr divert 4 ,
.Xr ip 4 ,
.Xr ipfirewall 4 ,
diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c
index 3f6807b11dc0..d0f06ce5c2d9 100644
--- a/sbin/ipfw/ipfw.c
+++ b/sbin/ipfw/ipfw.c
@@ -16,7 +16,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $Id: ipfw.c,v 1.59 1998/08/04 14:41:37 thepish Exp $
+ * $Id: ipfw.c,v 1.60 1998/09/28 22:56:37 alex Exp $
*
*/
@@ -25,18 +25,21 @@
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/time.h>
+#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <limits.h>
#include <netdb.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <sysexits.h>
#include <time.h>
#include <unistd.h>
-#include <sysexits.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -1199,7 +1202,7 @@ ipfw_main(ac,av)
{
int ch;
- extern int optind;
+ extern int optreset; /* XXX should be declared in <unistd.h> */
if ( ac == 1 ) {
show_usage(NULL);
@@ -1208,7 +1211,7 @@ ipfw_main(ac,av)
/* Set the force flag for non-interactive processes */
do_force = !isatty(STDIN_FILENO);
- optind = 1;
+ optind = optreset = 1;
while ((ch = getopt(ac, av, "afqtN")) != -1)
switch(ch) {
case 'a':
@@ -1289,10 +1292,11 @@ main(ac, av)
#define MAX_ARGS 32
#define WHITESP " \t\f\v\n\r"
char buf[BUFSIZ];
- char *a, *args[MAX_ARGS];
+ char *a, *p, *args[MAX_ARGS], *cmd = NULL;
char linename[10];
- int i, qflag=0;
- FILE *f;
+ int i, c, qflag, pflag, status;
+ FILE *f = NULL;
+ pid_t preproc = 0;
s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
if ( s < 0 )
@@ -1300,14 +1304,94 @@ main(ac, av)
setbuf(stdout,0);
- if (av[1] && (!access(av[1], R_OK) ||
- (av[2] && (qflag=!strcmp(av[1],"-q")) && !access(av[2], R_OK)))){
+ if (ac > 1 && access(av[ac - 1], R_OK) == 0) {
+ qflag = pflag = i = 0;
lineno = 0;
- if ((f = fopen(av[ac-1], "r")) == NULL)
- err(EX_UNAVAILABLE, "fopen: %s", av[ac-1]);
- while (fgets(buf, BUFSIZ, f)) {
- char *p;
+ while ((c = getopt(ac, av, "D:U:p:q")) != -1)
+ switch(c) {
+ case 'D':
+ if (!pflag)
+ errx(EX_USAGE, "-D requires -p");
+ if (i > MAX_ARGS - 2)
+ errx(EX_USAGE,
+ "too many -D or -U options");
+ args[i++] = "-D";
+ args[i++] = optarg;
+ break;
+
+ case 'U':
+ if (!pflag)
+ errx(EX_USAGE, "-U requires -p");
+ if (i > MAX_ARGS - 2)
+ errx(EX_USAGE,
+ "too many -D or -U options");
+ args[i++] = "-U";
+ args[i++] = optarg;
+ break;
+
+ case 'p':
+ pflag = 1;
+ cmd = optarg;
+ args[0] = cmd;
+ i = 1;
+ break;
+
+ case 'q':
+ qflag = 1;
+ break;
+
+ default:
+ show_usage(NULL);
+ }
+
+ av += optind;
+ ac -= optind;
+ if (ac != 1)
+ show_usage("extraneous filename arguments");
+
+ if ((f = fopen(av[0], "r")) == NULL)
+ err(EX_UNAVAILABLE, "fopen: %s", av[0]);
+
+ if (pflag) {
+ /* pipe through preprocessor (cpp or m4) */
+ int pipedes[2];
+
+ args[i] = 0;
+
+ if (pipe(pipedes) == -1)
+ err(EX_OSERR, "cannot create pipe");
+
+ switch((preproc = fork())) {
+ case -1:
+ err(EX_OSERR, "cannot fork");
+
+ case 0:
+ /* child */
+ if (dup2(fileno(f), 0) == -1 ||
+ dup2(pipedes[1], 1) == -1)
+ err(EX_OSERR, "dup2()");
+ fclose(f);
+ close(pipedes[1]);
+ close(pipedes[0]);
+ execvp(cmd, args);
+ err(EX_OSERR, "execvp(%s) failed", cmd);
+
+ default:
+ /* parent */
+ fclose(f);
+ close(pipedes[1]);
+ if ((f = fdopen(pipedes[0], "r")) == NULL) {
+ int savederrno = errno;
+
+ (void)kill(preproc, SIGTERM);
+ errno = savederrno;
+ err(EX_OSERR, "fdopen()");
+ }
+ }
+ }
+
+ while (fgets(buf, BUFSIZ, f)) {
lineno++;
sprintf(linename, "Line %d", lineno);
args[0] = linename;
@@ -1321,7 +1405,7 @@ main(ac, av)
for (a = strtok(buf, WHITESP);
a && i < MAX_ARGS; a = strtok(NULL, WHITESP), i++)
args[i] = a;
- if (i == 1)
+ if (i == (qflag? 2: 1))
continue;
if (i == MAX_ARGS)
errx(EX_USAGE, "%s: too many arguments", linename);
@@ -1330,6 +1414,21 @@ main(ac, av)
ipfw_main(i, args);
}
fclose(f);
+ if (pflag) {
+ if (waitpid(preproc, &status, 0) != -1) {
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != EX_OK)
+ errx(EX_UNAVAILABLE,
+ "preprocessor exited with status %d",
+ WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ errx(EX_UNAVAILABLE,
+ "preprocessor exited with signal %d",
+ WTERMSIG(status));
+ }
+ }
+ }
+
} else
ipfw_main(ac,av);
return EX_OK;