]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/sendmail/contrib/cidrexpand
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / sendmail / contrib / cidrexpand
1 #!/usr/bin/perl -w
2
3 # $Id: cidrexpand,v 8.8 2006/08/07 17:18:37 ca Exp $
4 #
5 # v 0.4
6 #
7 # 17 July 2000 Derek J. Balling (dredd@megacity.org)
8
9 # Acts as a preparser on /etc/mail/access_db to allow you to use address/bit
10 # notation. 
11 #
12 # If you have two overlapping CIDR blocks with conflicting actions
13 # e.g.   10.2.3.128/25 REJECT and 10.2.3.143 ACCEPT
14 # make sure that the exceptions to the more general block are specified
15 # later in the access_db.
16 #
17 # the -r flag to makemap will make it "do the right thing"
18 #
19 # Modifications
20 # -------------
21 # 26 Jul 2001 Derek Balling (dredd@megacity.org)
22 #     Now uses Net::CIDR because it makes life a lot easier.
23 #
24 #  5 Nov 2002 Richard Rognlie (richard@sendmail.com)
25 #     Added code to deal with the prefix tags that may now be included in
26 #     the access_db
27 #
28 #     Added clarification in the notes for what to do if you have 
29 #     exceptions to a larger CIDR block.
30 #
31 #  26 Jul 2006 Richard Rognlie (richard@sendmail.com>
32 #     Added code to strip "comments" (anything after a non-escaped #)
33 #     # characters after a \ or within quotes (single and double) are
34 #     left intact. 
35 #
36 #     e.g.
37 #       From:1.2.3.4    550 Die spammer # spammed us 2006.07.26
38 #     becomes
39 #       From:1.2.3.4    550 Die spammer 
40 #
41 #  3 August 2006
42 #
43 #     Corrected a bug to have it handle the special case of "0.0.0.0/0"
44 #     since Net::CIDR doesn't handle it properly.
45 #
46 # usage: 
47 #  cidrexpand < /etc/mail/access | makemap -r hash /etc/mail/access
48 #
49 #
50 # Report bugs to: <dredd@megacity.org>
51 #
52
53
54 use strict;
55 use Net::CIDR;
56 use Getopt::Std;
57
58 our ($opt_c,$opt_t);
59 getopts('ct:');
60
61 my $spaceregex = '\s+';
62 if ($opt_t)
63 {
64     $spaceregex = $opt_t;
65 }
66
67 while (<>)
68 {
69     chomp;
70     my ($prefix,$left,$right,$space);
71
72     if ( (/\#/) && $opt_c )
73     {
74         # print "checking...\n";
75         my $i;
76         my $qtype='';
77         for ($i=0 ; $i<length($_) ; $i++) 
78         {
79             my $ch = substr($_,$i,1);
80             if ($ch eq '\\') 
81             {
82                 $i++;
83                 next;
84             }
85             elsif ($qtype eq '' && $ch eq '#') 
86             {
87                 substr($_,$i) = '';
88                 last;
89             }
90             elsif ($qtype ne '' && $ch eq $qtype) 
91             {
92                 $qtype = '';
93             }
94             elsif ($qtype eq '' && $ch =~ /[\'\"]/) 
95             {
96                 $qtype = $ch;
97             }
98         }
99     } 
100     
101     if (! /^(|\S\S*:)(\d+\.){3}\d+\/\d\d?$spaceregex.*/ )
102     {
103         print "$_\n";
104     }
105     else
106     {
107         ($prefix,$left,$space,$right) = 
108             /^(|\S\S*:)((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/;
109         
110         my @new_lefts = expand_network($left);
111         foreach my $nl (@new_lefts)
112         {
113             print "$prefix$nl$space$right\n";
114         }
115     }
116 }
117     
118 sub expand_network
119 {
120     my $left_input = shift;
121     my @rc = ($left_input);
122     my ($network,$mask) = split /\//, $left_input;
123     if (defined $mask)
124     {
125         return (0..255) if $mask == 0;
126
127         my @parts = split /\./, $network;
128         while ($#parts < 3)
129         {
130             push @parts, "0";
131         }
132         my $clean_input = join '.', @parts;
133         $clean_input .= "/$mask";
134         my @octets = Net::CIDR::cidr2octets($clean_input);
135         @rc = @octets;
136     }
137     return @rc;
138 }