]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ipfilter/perl/ipfmeta.pl
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ipfilter / perl / ipfmeta.pl
1 #!/usr/bin/perl -w
2 #
3 # Written by Camiel Dobbelaar <cd@sentia.nl>, Aug-2000
4 # ipfmeta is in the Public Domain.
5 #
6
7 use strict;
8 use Getopt::Std;
9
10 ## PROCESS COMMANDLINE
11 our($opt_v); $opt_v=1;
12 getopts('v:') || die "usage: ipfmeta [-v verboselevel] [objfile]\n";
13 my $verbose = $opt_v + 0;
14 my $objfile = shift || "ipf.objs";
15 my $MAXRECURSION = 10;
16
17 ## READ OBJECTS
18 open(FH, "$objfile") || die "cannot open $objfile: $!\n";
19 my @tokens;
20 while (<FH>) {
21         chomp;
22         s/#.*$//;       # remove comments
23         s/^\s+//;       # compress whitespace
24         s/\s+$//;
25         next if m/^$/;  # skip empty lines
26         push (@tokens, split);
27 }
28 close(FH) || die "cannot close $objfile: $!\n";
29 # link objects with their values
30 my $obj="";
31 my %objs;
32 while (@tokens) {
33         my $token = shift(@tokens);
34         if ($token =~ m/^\[([^]]*)\]$/) {
35                 # new object
36                 $obj = $1;
37         } else {
38                 # new value
39                 push(@{$objs{$obj}}, $token) unless ($obj eq "");
40         }
41 }
42
43 # sort objects: longest first
44 my @objs = sort { length($b) <=> length($a) } keys %objs;
45
46 ## SUBSTITUTE OBJECTS WITH THEIR VALUES FROM STDIN
47 foreach (<STDIN>) {
48         foreach (expand($_, 0)) {
49                 print;
50         }
51 }
52
53 ## END
54
55 sub expand {
56         my $line = shift;
57         my $level = shift;
58         my @retlines = $line;
59         my $obj;
60         my $val;
61
62         # coarse protection
63         if ($level > $MAXRECURSION) {
64                 print STDERR "ERR: recursion exceeds $MAXRECURSION levels\n";
65                 return;
66         }
67
68         foreach $obj (@objs) {
69                 if ($line =~ m/$obj/) {
70                         @retlines = "";
71                         if ($level < $verbose) {
72                                 # add metarule as a comment
73                                 push(@retlines, "# ".$line);
74                         }
75                         foreach $val (@{$objs{$obj}}) {
76                                 my $newline = $line;
77                                 $newline =~ s/$obj/$val/;
78                                 push(@retlines, expand($newline, $level+1));
79                         }
80                         last;
81                 }
82         }
83
84         return @retlines;
85 }
86                                 
87 __END__
88
89 =head1 NAME
90
91 B<ipfmeta> - use objects in IP filter files
92
93 =head1 SYNOPSIS
94
95 B<ipfmeta> [F<options>] [F<objfile>]
96
97 =head1 DESCRIPTION
98
99 B<ipfmeta> is used to simplify the maintenance of your IP filter
100 ruleset. It does this through the use of 'objects'.  A matching
101 object gets replaced by its values at runtime.  This is similar to
102 what a macro processor like m4 does.
103
104 B<ipfmeta> is specifically geared towards IP filter. It is line
105 oriented, if an object has multiple values, the line with the object
106 is duplicated and substituted for each value. It is also recursive,
107 an object may have another object as a value.
108
109 Rules to be processed are read from stdin, output goes to stdout.
110
111 The verbose option allows for the inclusion of the metarules in the
112 output as comments.
113
114 Definition of the objects and their values is done in a separate
115 file, the filename defaults to F<ipf.objs>.  An object is delimited
116 by square brackets. A value is delimited by whitespace.  Comments
117 start with '#' and end with a newline. Empty lines and extraneous
118 whitespace are allowed.  A value belongs to the first object that
119 precedes it.
120
121 It is recommended that you use all caps or another distinguishing
122 feature for object names. You can use B<ipfmeta> for NAT rules also,
123 for instance to keep them in sync with filter rules.  Combine
124 B<ipfmeta> with a Makefile to save typing.
125
126 =head1 OPTIONS
127
128 =over 4
129
130 =item B<-v> I<verboselevel>
131
132 Include metarules in output as comments. Default is 1, the top level
133 metarules. Higher levels cause expanded metarules to be included.
134 Level 0 does not add comments at all.
135
136 =back
137
138 =head1 BUGS
139
140 A value can not have whitespace in it.
141
142 =head1 EXAMPLE
143
144 (this does not look good, formatted)
145
146 I<ipf.objs>
147
148 [PRIVATE] 10.0.0.0/8 127.0.0.0/8 172.16.0.0/12 192.168.0.0/16
149
150 [MULTICAST] 224.0.0.0/4
151
152 [UNWANTED] PRIVATE MULTICAST
153
154 [NOC] xxx.yy.zz.1/32 xxx.yy.zz.2/32
155
156 [WEBSERVERS] 192.168.1.1/32 192.168.1.2/32
157
158 [MGMT-PORTS] 22 23
159
160 I<ipf.metarules>
161
162 block in from UNWANTED to any
163
164 pass  in from NOC to WEBSERVERS port = MGMT-PORTS
165
166 pass  out all
167  
168 I<Run>
169
170 ipfmeta ipf.objs <ipf.metarules >ipf.rules
171
172 I<Output>
173
174 # block in from UNWANTED to any
175
176 block in from 10.0.0.0/8 to any
177
178 block in from 127.0.0.0/8 to any
179
180 block in from 172.16.0.0/12 to any
181
182 block in from 192.168.0.0/16 to any
183
184 block in from 224.0.0.0/4 to any
185
186 # pass  in from NOC to WEBSERVERS port = MGMT-PORTS
187
188 pass  in from xxx.yy.zz.1/32 to 192.168.1.1/32 port = 22
189
190 pass  in from xxx.yy.zz.1/32 to 192.168.1.1/32 port = 23
191
192 pass  in from xxx.yy.zz.1/32 to 192.168.1.2/32 port = 22
193
194 pass  in from xxx.yy.zz.1/32 to 192.168.1.2/32 port = 23
195
196 pass  in from xxx.yy.zz.2/32 to 192.168.1.1/32 port = 22
197
198 pass  in from xxx.yy.zz.2/32 to 192.168.1.1/32 port = 23
199
200 pass  in from xxx.yy.zz.2/32 to 192.168.1.2/32 port = 22
201
202 pass  in from xxx.yy.zz.2/32 to 192.168.1.2/32 port = 23
203
204 pass  out all
205
206 =head1 AUTHOR
207
208 Camiel Dobbelaar <cd@sentia.nl>. B<ipfmeta> is in the Public Domain.
209
210 =cut