summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/contrib/cidrexpand
blob: f277481ca567e446d208bfe59c930b3ab5928909 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/perl -w

# $Id: cidrexpand,v 8.8 2006/08/07 17:18:37 ca Exp $
#
# v 0.4
#
# 17 July 2000 Derek J. Balling (dredd@megacity.org)
# 
# Acts as a preparser on /etc/mail/access_db to allow you to use address/bit
# notation. 
#
# If you have two overlapping CIDR blocks with conflicting actions
# e.g.   10.2.3.128/25 REJECT and 10.2.3.143 ACCEPT
# make sure that the exceptions to the more general block are specified
# later in the access_db.
#
# the -r flag to makemap will make it "do the right thing"
#
# Modifications
# -------------
# 26 Jul 2001 Derek Balling (dredd@megacity.org)
#     Now uses Net::CIDR because it makes life a lot easier.
#
#  5 Nov 2002 Richard Rognlie (richard@sendmail.com)
#     Added code to deal with the prefix tags that may now be included in
#     the access_db
#
#     Added clarification in the notes for what to do if you have 
#     exceptions to a larger CIDR block.
#
#  26 Jul 2006 Richard Rognlie (richard@sendmail.com>
#     Added code to strip "comments" (anything after a non-escaped #)
#     # characters after a \ or within quotes (single and double) are
#     left intact. 
#
#     e.g.
#	From:1.2.3.4	550 Die spammer # spammed us 2006.07.26
#     becomes
#	From:1.2.3.4	550 Die spammer 
#
#  3 August 2006
#
#     Corrected a bug to have it handle the special case of "0.0.0.0/0"
#     since Net::CIDR doesn't handle it properly.
#
# usage: 
#  cidrexpand < /etc/mail/access | makemap -r hash /etc/mail/access
#
#
# Report bugs to: <dredd@megacity.org>
#


use strict;
use Net::CIDR;
use Getopt::Std;

our ($opt_c,$opt_t);
getopts('ct:');

my $spaceregex = '\s+';
if ($opt_t)
{
    $spaceregex = $opt_t;
}

while (<>)
{
    chomp;
    my ($prefix,$left,$right,$space);

    if ( (/\#/) && $opt_c )
    {
	# print "checking...\n";
	my $i;
	my $qtype='';
	for ($i=0 ; $i<length($_) ; $i++) 
	{
	    my $ch = substr($_,$i,1);
	    if ($ch eq '\\') 
	    {
		$i++;
		next;
	    }
	    elsif ($qtype eq '' && $ch eq '#') 
	    {
		substr($_,$i) = '';
		last;
	    }
	    elsif ($qtype ne '' && $ch eq $qtype) 
	    {
		$qtype = '';
	    }
	    elsif ($qtype eq '' && $ch =~ /[\'\"]/) 
	    {
		$qtype = $ch;
	    }
	}
    } 
    
    if (! /^(|\S\S*:)(\d+\.){3}\d+\/\d\d?$spaceregex.*/ )
    {
	print "$_\n";
    }
    else
    {
	($prefix,$left,$space,$right) = 
	    /^(|\S\S*:)((?:\d+\.){3}\d+\/\d\d?)($spaceregex)(.*)$/;
	
	my @new_lefts = expand_network($left);
	foreach my $nl (@new_lefts)
	{
	    print "$prefix$nl$space$right\n";
	}
    }
}
    
sub expand_network
{
    my $left_input = shift;
    my @rc = ($left_input);
    my ($network,$mask) = split /\//, $left_input;
    if (defined $mask)
    {
	return (0..255)	if $mask == 0;

	my @parts = split /\./, $network;
	while ($#parts < 3)
	{
	    push @parts, "0";
	}
	my $clean_input = join '.', @parts;
	$clean_input .= "/$mask";
	my @octets = Net::CIDR::cidr2octets($clean_input);
	@rc = @octets;
    }
    return @rc;
}
OpenPOWER on IntegriCloud