| Summary: | preprocessor for ipfilter rules | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Gerhard Sittig <Gerhard.Sittig> |
| Component: | bin | Assignee: | Darern Reed <darrenr> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.1-STABLE | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
Gerhard Sittig
2000-10-14 18:00:01 UTC
Responsible Changed From-To: freebsd-bugs->darrenr Over to ipfilter maintainer. On Sat, Oct 14, 2000 at 18:24 +0200, Gerhard Sittig wrote: > > And I slowly get the feeling that "-" isn't even an > exception to the passing to the preprocessor. Well, it turns out to be. :( Following the ipf.8 diff the code should have - either suppressed preprocessing when the "file" is stdin - or taken special care to not clobber its stdin handle And something else showed up: Separating pp_name into pp_argv[] on every procfile() invocation mangled pp_name in a way that the next loop found one word only. Therefor I made pp_argv[] global and introduced a use_pproc flag to scan the command only once when specified with -p. And while I were testing, I wasted some time searching for errors just because ipf didn't tell me option -p was not supported. That's what the usage() and getopt() arg mangling is for: When there's no code for an option, I would like to know about it. And I wonder if there would be any way of making the manpage stuff "conditional" either by cpp'ing the troff input or by specifying "when compiled with this option" in the -6 and -p sections. Feel free to ignore the patch from the previous message and consider the following one to be the relevant ipf extension: Index: ../../contrib/ipfilter/ipf.c =================================================================== RCS file: /home/fcvs/src/contrib/ipfilter/ipf.c,v retrieving revision 1.1.1.9 diff -u -r1.1.1.9 ipf.c --- ../../contrib/ipfilter/ipf.c 2000/08/13 04:57:48 1.1.1.9 +++ ../../contrib/ipfilter/ipf.c 2000/10/15 09:43:19 @@ -66,6 +66,13 @@ static int fd = -1; +#ifdef USE_PPROC +#define PP_ARG_MAX 32 +#define PP_ARG_SEP " \t" +static int use_pproc = 0; +static char *pp_argv[PP_ARG_MAX + 1] = { NULL, }; +#endif + static void procfile __P((char *, char *)), flushfilter __P((char *)); static void set_state __P((u_int)), showstats __P((friostat_t *)); static void packetlogon __P((char *)), swapactive __P((void)); @@ -77,11 +84,32 @@ static void showversion __P((void)); static int get_flags __P((void)); +/* cause getopt to barf when code for an option is not present */ +#ifdef USE_INET6 + #define SYNOPSIS_INET6 "6" + #define GETOPT_INET6 "6" +#else + #define SYNOPSIS_INET6 "" + #define GETOPT_INET6 "" +#endif +#ifdef USE_PPROC + #define SYNOPSIS_PPROC "[-p preprocessor] " + #define GETOPT_PPROC "p:" +#else + #define SYNOPSIS_PPROC "" + #define GETOPT_PPROC "" +#endif +#define SYNOPSIS_COMMON "AdDEInoPrsUvVyzZ" +#define GETOPT_COMMON "AdDEf:F:Il:noPrsUvVyzZ" +#define GETOPT_OPTIONS GETOPT_COMMON GETOPT_INET6 GETOPT_PPROC + static void usage() { - fprintf(stderr, "usage: ipf [-6AdDEInoPrsUvVyzZ] %s %s %s\n", - "[-l block|pass|nomatch]", "[-F i|o|a|s|S]", "[-f filename]"); + fprintf(stderr, "usage: ipf [-%s] %s %s %s\n", + SYNOPSIS_INET6 SYNOPSIS_COMMON, + "[-l block|pass|nomatch]", "[-F i|o|a|s|S]", + SYNOPSIS_PPROC "[-f filename]"); exit(1); } @@ -91,8 +119,12 @@ char *argv[]; { int c; +#ifdef USE_PPROC + int pp_argc; + char *pp_tmp; +#endif - while ((c = getopt(argc, argv, "6AdDEf:F:Il:noPrsUvVyzZ")) != -1) { + while ((c = getopt(argc, argv, GETOPT_OPTIONS)) != -1) { switch (c) { case '?' : @@ -131,6 +163,30 @@ break; case 'o' : break; +#ifdef USE_PPROC + case 'p' : + /* + * FreeBSD has strsep(3), but others might not; + * maybe we could use system(3) or popen(3) + * and get rid of all the dimensioning/strtok stuff? + */ + for ( pp_argc = 0, pp_tmp = strtok(optarg, PP_ARG_SEP); + (pp_tmp) && (pp_argc < PP_ARG_MAX); + pp_tmp = strtok(NULL, PP_ARG_SEP) + ) { + /* cope with adjacent delimiters */ + if (*pp_tmp) + pp_argv[pp_argc++] = pp_tmp; + } + pp_argv[pp_argc] = NULL; + if (pp_tmp) { + fprintf(stderr, "%s: too many preprocessor args, " + "ignored \"%s\" and following\n", + argv[0], pp_tmp); + } + use_pproc = (pp_argc && pp_argv[0] && *pp_argv[0]); + break; +#endif case 'P' : ipfname = IPL_AUTH; break; @@ -229,6 +285,10 @@ struct frentry *fr; u_int add, del; int linenum = 0; +#ifdef USE_PPROC + int pp_pipe[2]; + int pp_pid; +#endif (void) opendevice(ipfname); @@ -251,6 +311,62 @@ STRERROR(errno)); exit(1); } + +#ifdef USE_PPROC + /* pipe the rules through a preprocessor if specified */ + if (use_pproc) { + + if (pipe(pp_pipe) == -1) { + fprintf(stderr, "%s: pipe() failed: %s\n", + name, STRERROR(errno)); + exit(1); + } + + switch(pp_pid = fork()) { + case -1: + fprintf(stderr, "%s: fork() failed: %s\n", + name, STRERROR(errno)); + exit(1); + /* NOTREACHED */ + + case 0: /* preprocessor job (child) */ + if (dup2(pp_pipe[1], 1) == -1) { + fprintf(stderr, "%s: dup2() failed: %s\n", + name, STRERROR(errno)); + exit(1); + } + close(pp_pipe[1]); + /* only close fp & friends when it's not stdin */ + if (strcmp(file, "-")) { + if (dup2(fileno(fp), 0) == -1) { + fprintf(stderr, "%s: dup2() failed: %s\n", + name, STRERROR(errno)); + exit(1); + } + fclose(fp); + } + close(pp_pipe[0]); + execvp(pp_argv[0], pp_argv); + fprintf(stderr, "%s: exec(%s) failed: %s\n", + name, pp_argv[0], STRERROR(errno)); + exit(1); + /* NOTREACHED */ + + default: /* ipf job (parent) */ + close(pp_pipe[1]); + /* only close fp & friends when it's not stdin */ + if (strcmp(file, "-")) + fclose(fp); + if (! (fp = fdopen(pp_pipe[0], "r"))) { + fprintf(stderr, "%s: fdopen() failed: %s\n", + name, STRERROR(errno)); + kill(pp_pid, SIGTERM); + exit(1); + } + break; + } + } +#endif while (getline(line, sizeof(line), fp)) { linenum++; Index: ../../contrib/ipfilter/man/ipf.8 =================================================================== RCS file: /home/fcvs/src/contrib/ipfilter/man/ipf.8,v retrieving revision 1.4 diff -u -r1.4 ipf.8 --- ../../contrib/ipfilter/man/ipf.8 2000/05/24 02:19:15 1.4 +++ ../../contrib/ipfilter/man/ipf.8 2000/10/15 09:27:26 @@ -12,6 +12,9 @@ ] [ .B \-F <i|o|a|s|S> +] [ +.B \-p +<\fIpreprocessor\fP> ] .B \-f <\fIfilename\fP> @@ -84,6 +87,15 @@ .B \-o Force rules by default to be added/deleted to/from the output list, rather than the (default) input list. +.TP +.BR \-p \0<preprocessor> +All of the files in subsequent \fB-f\fP options +are fed into this command's stdin, its stdout +is read back and processed instead of the file's content. +This command gets invoked anew for every specified filename. +Specifying an empty command will turn this feature off, again. +Shell escapes are needed when passing arguments to this command. +Up to 31 parameters (usually some \fB-D\fP and \fB-U\fP) can be passed. .TP .B \-P Add rules as temporary entries in the authentication rule table. Let's see if some tests still work: $ cd ~/FreeBSD-source/src-current/sbin/ipf $ make CFLAGS+=-DUSE_PPROC [ ... snip ... ] $ head pp_in*.txt ==> pp_in.txt <== #define WORLD world #define HELLO hello HELLO WORLD EXTDEF works too ==> pp_in1.txt <== #define INT internal file F1 with INT and EXT ==> pp_in2.txt <== #define INT internal file F2 with INT and EXT ==> pp_in3.txt <== #define INT internal file F3 with INT and EXT $ ./ipf -v -f pp_in.txt open device: Permission denied [HELLO WORLD] 3: unknown keyword (HELLO) [EXTDEF works too] 4: unknown keyword (EXTDEF) $ ./ipf -v -f pp_in1.txt -f pp_in2.txt open device: Permission denied [file F1 with INT and EXT] 2: unknown keyword (file) open device: Permission denied [file F2 with INT and EXT] 2: unknown keyword (file) $ ./ipf -v -f pp_in1.txt -f - -f pp_in3.txt < pp_in2.txt open device: Permission denied [file F1 with INT and EXT] 2: unknown keyword (file) open device: Permission denied [file F2 with INT and EXT] 2: unknown keyword (file) open device: Permission denied [file F3 with INT and EXT] 2: unknown keyword (file) $ ./ipf -v -p 'cpp' -f pp_in1.txt -f - -f pp_in3.txt < pp_in2.txt open device: Permission denied [file F1 with internal and EXT] 2: unknown keyword (file) open device: Permission denied [file F2 with internal and EXT] 2: unknown keyword (file) open device: Permission denied [file F3 with internal and EXT] 2: unknown keyword (file) $ ./ipf -v -p 'cpp -DEXT=external' -f pp_in1.txt -f - -f pp_in3.txt < pp_in2.txt open device: Permission denied [file F1 with internal and external ] 2: unknown keyword (file) open device: Permission denied [file F2 with internal and external ] 2: unknown keyword (file) open device: Permission denied [file F3 with internal and external ] 2: unknown keyword (file) $ ./ipf -v -p 'cpp -DEXT=external' -f pp_in1.txt -f - -p '' -f pp_in3.txt < pp_in2.txt open device: Permission denied [file F1 with internal and external ] 2: unknown keyword (file) open device: Permission denied [file F2 with internal and external ] 2: unknown keyword (file) open device: Permission denied [file F3 with INT and EXT] 2: unknown keyword (file) $ ./ipf -v -p 'cpp -DEXT=ext1' -f pp_in1.txt -p 'cpp -DEXT=ext2' -f - -p 'cpp -DEXT=ext3' -f pp_in3.txt < pp_in2.txt open device: Permission denied [file F1 with internal and ext1 ] 2: unknown keyword (file) open device: Permission denied [file F2 with internal and ext2 ] 2: unknown keyword (file) open device: Permission denied [file F3 with internal and ext3 ] 2: unknown keyword (file) Now that was fun. :) virtually yours 82D1 9B9C 01DC 4FB4 D7B4 61BE 3F49 4F77 72DE DA76 Gerhard Sittig true | mail -s "get gpg key" Gerhard.Sittig@gmx.net -- If you don't understand or are scared by any of the above ask your parents or an adult to help you. State Changed From-To: open->closed I am not interested in putting a preprocessor into ipf |