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