#!/usr/bin/perl
#
# Copyright (C) 2003 - 2004 Josip Deanovic <djosip@linuxpages.org>
# This program is copyrighted under GPL licence. See COPYING file
# for details.


# This script requires perl >= 5.8.0 and NetAddr::IP module installed.
# If you do not have perl >= 5.8.0 or NetAddr::IP module installed, you
# can use iprange2access script which will do exactly the same thing.


# We are using strict mode.
use strict;

# Variables defined by user
####
# This is the errorcode which will be used in case you want to use sendmail
# access compatible output.
my $ERRORCODE_DEFAULT = "571";

# This is the message which will be used in case you want to sendmail access
# compatible output.
my $MESSAGE_DEFAULT = "Because of previous SPAM activity from your domain, we reject your mail.";


# You should not change anything under this line unles you know what
# are you doing.
################################################################################


# Loading needed perl extensions and modules.
use Switch;
use NetAddr::IP;


# Main body of the script
####

# Variables
my $parameter_h;
my $parameter_V;
my $parameter_v;
my $parameter_d;
my $parameter_e;
my $parameter_e_value;
my $parameter_m;
my $parameter_m_value;
my @splited_common_ip;
my @splited_common_ip_start;
my $nonsplited_common_ip_start;
my $numeric_ip_start;
my $numeric_ip_end;
my $common_ip_start;
my $common_ip_end;


# Parsing command line parameters.
f_params();


# Converting IP from common notation to numeric notation.
$numeric_ip_start = new NetAddr::IP ($common_ip_start)->numeric ();
$numeric_ip_end = new NetAddr::IP ($common_ip_end)->numeric ();

# First IP in range cannot be smaller then the last IP in the range.
if ($numeric_ip_end < $numeric_ip_start)
   {
   f_help();
   exit (2);
   }


# If output should be verbose, script will prepend "#<range>" to normal output.
if ($parameter_v == 1)
   {
   print "#<$common_ip_start-$common_ip_end>\n"
   }


# This part of code is doing the most important job.
my $counter = $numeric_ip_start;
while ($counter <= $numeric_ip_end)
      {
      $nonsplited_common_ip_start = new NetAddr::IP ($counter)->addr ();
      @splited_common_ip_start = split(/\./, $nonsplited_common_ip_start);
      if ($splited_common_ip_start[1] == 0 && ($numeric_ip_end - $counter) >= 16777215)
         {
         $counter = ($counter+16777215);
         print "$splited_common_ip_start[0]";
         if ($parameter_d == 1)
            {
            if ($parameter_e == 1)
               {
               print " $parameter_e_value";
               }
            else
               {
               print " $ERRORCODE_DEFAULT";
               }
            if ($parameter_m == 1)
               {
               print " $parameter_m_value";
               }
            else
               {
               print " $MESSAGE_DEFAULT";
               }
            }
         print "\n";
         }
      elsif ($splited_common_ip_start[2] == 0 && ($numeric_ip_end - $counter) >= 65535)
            {
            $counter = ($counter+65535);
            print "$splited_common_ip_start[0].$splited_common_ip_start[1]";
            if ($parameter_d == 1)
               {
               if ($parameter_e == 1)
                  {
                  print " $parameter_e_value";
                  }
               else
                  {
                  print " $ERRORCODE_DEFAULT";
                  }
               if ($parameter_m == 1)
                  {
                  print " $parameter_m_value";
                  }
               else
                  {
                  print " $MESSAGE_DEFAULT";
                  }
               }
            print "\n";
            }
      elsif ($splited_common_ip_start[3] == 0 && ($numeric_ip_end - $counter) >= 255)
            {
            $counter = ($counter+255);
            print "$splited_common_ip_start[0].$splited_common_ip_start[1].$splited_common_ip_start[2]";
            if ($parameter_d == 1)
               {
               if ($parameter_e == 1)
                  {
                  print " $parameter_e_value";
                  }
               else
                  {
                  print " $ERRORCODE_DEFAULT";
                  }
               if ($parameter_m == 1)
                  {
                  print " $parameter_m_value";
                  }
               else
                  {
                  print " $MESSAGE_DEFAULT";
                  }
               }
            print "\n";
            }
      else
         {
         print new NetAddr::IP ($counter)->addr ();
         if ($parameter_d == 1)
            {
            if ($parameter_e == 1)
               {
               print " $parameter_e_value";
               }
            else
               {
               print " $ERRORCODE_DEFAULT";
               }
            if ($parameter_m == 1)
               {
               print " $parameter_m_value";
               }
            else
               {
               print " $MESSAGE_DEFAULT";
               }
            }
         print "\n";
         }
      $counter++;
      }


# If output should be verbose, script will append "#</range>" to normal output.
if ($parameter_v == 1)
   {
   print "#</$common_ip_start-$common_ip_end>\n"
   }


# Functions
####

# Help function
sub f_help {
           print STDERR "$0: Perl script for generating records for /etc/mail/access.\n".
                        "Usage: $0 first_ip [-] last_ip [options]\n".
                        "	-d	deny mode (will output line useful for sendmail access file)\n".
                        "	-v	verbose (will prepend and append lines with curent range to\n".
                        "		output). It could only be used with -d option\n".
                        "	-e errorcode	If you don't like default errorcode (571), you can\n".
                        "			change it with this option. It could only be used with\n".
                        "			-d option\n".
                        "	-m message	If you don't like default message, you can change it\n".
                        "			with this option. It could only be used with -d option\n".
                        "	-V	Output version and exit.\n".
                        "	-h	Show this help screen and exit\n".
                        "Examples:\n".
                        "	$0 first_ip - last_ip -d\n".
                        "	$0 first_ip-last_ip -d -v -e 571 -m \"No spam here!\"\n";
           }


# Function for parsing command line parameters
sub f_params {
             my $nparam = $#ARGV;
             my $counter = 0;
             while ($counter <= $nparam)
                   {
                   SWITCH: {
                           if ($ARGV[$counter] eq "-h") { $parameter_h = 1; last SWITCH; }
                           if ($ARGV[$counter] eq "-V") { $parameter_V = 1; last SWITCH; }
                           if ($ARGV[$counter] eq "-v") { $parameter_v = 1; last SWITCH; }
                           if ($ARGV[$counter] eq "-d") { $parameter_d = 1; last SWITCH; }
                           if ($ARGV[$counter] eq "-e") {
                                                        $parameter_e = 1;
                                                        if ($ARGV[$counter+1] ne "")
                                                           {
                                                           $parameter_e_value = $ARGV[++$counter];
                                                           }
                                                        else
                                                           {
                                                           f_help();
                                                           exit (3);
                                                           }
                                                        last SWITCH;
                                                        }
                           if ($ARGV[$counter] eq "-m") {
                                                        $parameter_m = 1;
                                                        if ($ARGV[$counter+1] ne "")
                                                           {
                                                           $parameter_m_value = $ARGV[++$counter];
                                                           }
                                                        else
                                                           {
                                                           f_help();
                                                           exit (4);
                                                           }
                                                        last SWITCH;
                                                        }
                           if ($ARGV[$counter] =~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/ && $ARGV[$counter+1] eq "-" && $ARGV[$counter+2] =~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/)
                              {
                              $common_ip_start = $ARGV[$counter];
                              $common_ip_end = $ARGV[$counter+2];
                              $counter = ($counter+2);
                              }
                           elsif ($ARGV[$counter] =~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/ && $ARGV[$counter+1] =~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/)
                                 {
                                 $common_ip_start = $ARGV[$counter];
                                 $common_ip_end = $ARGV[$counter+1];
                                 $counter++;
                                 }
                           elsif ($ARGV[$counter] =~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}-([0-9]{1,3}\.){3,3}[0-9]{1,3}$/)
                                 {
                                 @splited_common_ip = split(/-/, $ARGV[$counter]);
                                 $common_ip_start = @splited_common_ip[0];
                                 $common_ip_end = @splited_common_ip[1];
                                 }
                           else
                              {
                              f_help();
                              exit (5);
                              }
                           }

                   $counter++;
                   }

             if ($parameter_h == 1)
                {
                f_help ();
                exit (0);
                }
             if ($parameter_V == 1)
                {
                print STDERR "$0: iprange2access V1.0\tJosip Deanovic <djosip\@linuxpages.org>\n";
                exit (0);
                }
             if ($parameter_d != 1)
                {
                if ($parameter_v == 1)
                   {
                   f_help();
                   exit (6);
                   }
                if ($parameter_e == 1)
                   {
                   f_help();
                   exit (7);
                   }
                if ($parameter_m == 1)
                   {
                   f_help();
                   exit (8);
                   }
                }
             if ($common_ip_start !~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/)
                {
                f_help();
                exit (9);
                }
             if ($common_ip_end !~ /^([0-9]{1,3}\.){3,3}[0-9]{1,3}$/)
                {
                f_help ();
                exit (10);
                }
             }

