* Add this nice filesystem testing tool that I've recently
[dragonfly.git] / contrib / sendmail / contrib / cidrexpand
1 #!/usr/local/bin/perl -w
2
3 # v 0.2-very-beta
4 #
5 # 17 July 2000 Derek J. Balling (dredd@megacity.org)
6 #
7 # The $SENDMAIL flag tells the code to lump networks in sendmail format
8 # if applicable. If this flag is disabled, cidrexpand will literally create
9 # a single line for each entry, which may or may not be what you want. :)
10 # makes for a rather large hash table...
11 #
12 # Acts as a preparser on /etc/mail/access_db to allow you to use address/bit
13 # notation. Caveat: the address portion MUST be the start address or your
14 # results will NOT be what what you want.
15 #
16 # If you have two overlapping CIDR blocks with conflicting actions
17 # e.g.   10.2.3.128/25 REJECT and 10.2.3.143 ACCEPT
18 # make sure that the exceptions to the more general block are specified
19 # later in the access_db.
20 #
21 # the -r flag to makemap will make it "do the right thing"
22 #
23 # Modifications
24 # -------------
25 #  5 Nov  2002 Richard Rognlie (richard@sendmail.com)
26 #     Added code to deal with the prefix tags that may now be included in
27 #     the access_db
28 #
29 #     Added clarification in the notes for what to do if you have 
30 #     exceptions to a larger CIDR block.
31 #
32 # usage:
33 #  cidrexpand < /etc/mail/access | makemap -r hash /etc/mail/access
34 #
35 # Report bugs to: dredd@megacity.org
36 #
37
38 my $spaceregex = '\s+';
39
40 while (my $arg = shift @ARGV)
41 {
42      if ($arg eq '-t')
43      {
44         $spaceregex = shift;
45      }
46 }
47
48 use strict;
49
50 my $SENDMAIL = 1;
51
52 while (<>)
53 {
54      my ($prefix,$left,$right,$space);
55
56      if (! /^(|\S\S*:)(\d+\.){3}\d+\/\d\d?$spaceregex.*/ )
57      {
58         print;
59      }
60      else
61      {
62         ($prefix,$left,$space,$right) = /^(|\S\S*:)((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/;
63
64         my @new_lefts = expand_network($left);
65         foreach my $nl (@new_lefts)
66         {
67             print "$prefix$nl$space$right\n";
68         }
69
70      }
71 }
72     
73 sub expand_network
74 {
75      my ($network,$mask) = split /\//, shift;
76      my @diffs = calc_changes($network,$mask);
77      my ($first,$second,$third,$fourth) = split /\./, $network;
78
79      my @rc = ();
80
81      for my $f ($first..($first+$diffs[0]))
82      {
83         if ( ( $SENDMAIL ) and ($diffs[1] == 255))
84         {
85             push @rc, "$f";
86         }
87         else
88         {
89             for my $s ($second..($second+$diffs[1]))
90             {
91                 if ( ($SENDMAIL) and ($diffs[2] == 255) )
92                 {
93                     push @rc,"$f\.$s";
94                 }
95                 else
96                 {
97                     for my $t ($third..($third+$diffs[2]))
98                     {
99                         if ( ($SENDMAIL) and ($diffs[3] == 255))
100                         {
101                             push @rc, "$f\.$s\.$t";
102                         }
103                         else
104                         {
105                             for my $fr ($fourth..($fourth+$diffs[3]))
106                             {
107                                 push @rc, "$f\.$s\.$t\.$fr";
108                             }
109                         }
110                     }
111                 }
112             }
113         }
114      }
115      return @rc;
116 }
117
118 sub calc_changes
119 {
120      my ($network,$mask) = @_;
121     
122      my @octs = split /\./, $network;
123     
124      my ($first,$second,$third,$fourth) = (0,0,0,0);
125     
126      my $power = 32 - $mask;
127     
128      if ($mask > 24)
129      {
130         $fourth = 2**$power - 1;
131      }
132      elsif ($mask > 16)
133      {
134         $fourth = 255;
135         $third = 2**($power-8) - 1;
136      }
137      elsif ($mask > 8)
138      {
139         $fourth = 255;
140         $third  = 255;
141         $second = 2**($power-16) - 1;
142      }
143      elsif ($mask > 0)
144      {
145         $fourth = 255;
146         $third = 255;
147         $second = 255;
148         $first = 2**($power-24) - 1;
149      }
150      elsif ($mask == 0)
151      {
152         $fourth = 255;
153         $third = 255;
154         $second = 255;
155         $first = 255;
156      }
157
158      return ($first,$second,$third,$fourth);
159 }