summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2001-04-13 01:31:17 +0000
committergshapiro <gshapiro@FreeBSD.org>2001-04-13 01:31:17 +0000
commit1e64929334857078402f8d9d2cf000518e8790c1 (patch)
tree1a29a4309a06aa97064cad1fa16979b5a13b03dc /sbin
parente767472b727197cefeea3ddb87b7bd0821d673b4 (diff)
downloadFreeBSD-src-1e64929334857078402f8d9d2cf000518e8790c1.zip
FreeBSD-src-1e64929334857078402f8d9d2cf000518e8790c1.tar.gz
Match ip6fw's command line options to those of ipfw (specifically, added
the ability to use a preprocessor, use the -q (quiet) flag when reading from a file). The source used is from ipfw. Clean up exit codes while I am here. KAME has been informed and plans on integrating these patches into their own source as well.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ip6fw/ip6fw.853
-rw-r--r--sbin/ip6fw/ip6fw.c144
2 files changed, 176 insertions, 21 deletions
diff --git a/sbin/ip6fw/ip6fw.8 b/sbin/ip6fw/ip6fw.8
index 84c1216..7482b19 100644
--- a/sbin/ip6fw/ip6fw.8
+++ b/sbin/ip6fw/ip6fw.8
@@ -9,7 +9,15 @@
.Nd controlling utility for IPv6 firewall
.Sh SYNOPSIS
.Nm
-.Ar file
+.Op Fl q
+.Oo
+.Fl p Ar preproc
+.Oo Fl D
+.Ar macro Ns Op = Ns Ar value
+.Oc
+.Op Fl U Ar macro
+.Oc
+.Ar pathname
.Nm
.Op Fl f | Fl q
flush
@@ -42,11 +50,48 @@ to
.Op via Ar name | ipv6no
.Op Ar options
.Sh DESCRIPTION
-If used as shown in the first synopsis line, the
-.Ar file
+To ease configuration, rules can be put into a file which is
+processed using
+.Nm
+as shown in the first synopsis line.
+An absolute
+.Ar pathname
+must be used.
+The file
will be read line by line and applied as arguments to the
.Nm
-command.
+utility.
+.Pp
+Optionally, a preprocessor can be specified using
+.Fl p Ar preproc
+where
+.Ar pathname
+is to be piped through.
+Useful preprocessors include
+.Xr cpp 1
+and
+.Xr m4 1 .
+If
+.Ar preproc
+doesn't start with a slash
+.Pq Ql /
+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. when they are mounted over NFS).
+Once
+.Fl p
+has been specified, optional
+.Fl D
+and
+.Fl U
+specifications 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
diff --git a/sbin/ip6fw/ip6fw.c b/sbin/ip6fw/ip6fw.c
index 89050cd..ff0a096 100644
--- a/sbin/ip6fw/ip6fw.c
+++ b/sbin/ip6fw/ip6fw.c
@@ -26,6 +26,7 @@
#include <sys/sockio.h>
#include <sys/time.h>
#include <sys/ioctl.h>
+#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
@@ -38,6 +39,8 @@
#include <time.h>
#include <unistd.h>
#include <errno.h>
+#include <signal.h>
+#include <sysexits.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -242,7 +245,7 @@ show_ip6fw(struct ip6_fw *chain)
}
break;
default:
- errx(1, "impossible");
+ errx(EX_OSERR, "impossible");
}
if (chain->fw_flg & IPV6_FW_F_PRN)
@@ -425,10 +428,10 @@ list(ac, av)
nalloc = nalloc * 2 + 200;
bytes = nalloc;
if ((rules = realloc(rules, bytes)) == NULL)
- err(2, "realloc");
+ err(EX_OSERR, "realloc");
i = getsockopt(s, IPPROTO_IPV6, IPV6_FW_GET, rules, &bytes);
if ((i < 0 && errno != EINVAL) || nalloc > maxbytes)
- err(2, "getsockopt(IPV6_FW_GET)");
+ err(EX_OSERR, "getsockopt(IPV6_FW_GET)");
}
if (!ac) {
/* display all rules */
@@ -1117,7 +1120,7 @@ badviacombo:
show_ip6fw(&rule);
i = setsockopt(s, IPPROTO_IPV6, IPV6_FW_ADD, &rule, sizeof rule);
if (i)
- err(1, "setsockopt(%s)", "IPV6_FW_ADD");
+ err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_ADD");
}
static void
@@ -1130,7 +1133,7 @@ zero (ac, av)
if (!ac) {
/* clear all entries */
if (setsockopt(s,IPPROTO_IPV6,IPV6_FW_ZERO,NULL,0)<0)
- err(1, "setsockopt(%s)", "IPV6_FW_ZERO");
+ err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_ZERO");
if (!do_quiet)
printf("Accounting cleared.\n");
} else {
@@ -1230,7 +1233,7 @@ ip6fw_main(ac,av)
}
if ( do_flush ) {
if (setsockopt(s,IPPROTO_IPV6,IPV6_FW_FLUSH,NULL,0) < 0)
- err(1, "setsockopt(%s)", "IPV6_FW_FLUSH");
+ err(EX_UNAVAILABLE, "setsockopt(%s)", "IPV6_FW_FLUSH");
if (!do_quiet)
printf("Flushed all rules.\n");
}
@@ -1257,41 +1260,148 @@ 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;
- FILE *f;
+ int i, c, lineno, qflag, pflag, status;
+ FILE *f = NULL;
+ pid_t preproc = 0;
s = socket( AF_INET6, SOCK_RAW, IPPROTO_RAW );
if ( s < 0 )
- err(1, "socket");
+ err(EX_UNAVAILABLE, "socket");
setbuf(stdout,0);
- if (av[1] && !access(av[1], R_OK)) {
+ /*
+ * this is a nasty check on the last argument!!!
+ * If there happens to be a filename matching a keyword in the current
+ * directory, things will fail miserably.
+ */
+
+ if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0) {
+ qflag = pflag = i = 0;
lineno = 0;
- if ((f = fopen(av[1], "r")) == NULL)
- err(1, "fopen: %s", av[1]);
- while (fgets(buf, BUFSIZ, f)) {
+ 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;
if (*buf == '#')
continue;
- for (i = 1, a = strtok(buf, WHITESP);
+ if ((p = strchr(buf, '#')) != NULL)
+ *p = '\0';
+ i=1;
+ if (qflag) args[i++]="-q";
+ 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(1, "%s: too many arguments", linename);
+ errx(EX_USAGE, "%s: too many arguments", linename);
args[i] = NULL;
ip6fw_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
ip6fw_main(ac,av);
return 0;
OpenPOWER on IntegriCloud