#!/usr/bin/perl -Tw # # $Id: nets.cgi,v 1.12 2007/01/17 01:23:02 syzdek Exp $ # # Network Calculator # Copyright (C) 2006 David M. Syzdek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # nets.cgi - calculates common network addresses from multiple IP addresses # Can be run from commandline or as a CGI. # # +-=-=-=-=-=-+ # | | # | Headers | # | | # +-=-=-=-=-=-+ use strict; $|++; our $PROGRAM_NAME = 'nets.pl'; our $VERSION = '0.02'; our $DESCRIPTION = 'Network Calculator'; our $AUTHOR = 'David Syzdek "syzdek@gmail.com"'; $ENV{'WHOIS'} = 'http://ws.arin.net/whois/?queryinput='; # +-=-=-=-=-=-=-=+ # | | # | Prototypes | # | | # +-=-=-=-=-=-=-=+ sub button($$;$); # displays button sub cmdline(@); # parses commandline sub calc_ips(@); # generates list of IP addresses sub calc_network(@); # calculates nework address of smallest network sub display($$$); # displays network data sub form(@); # displays form sub ip2str($); # converts IP to string sub sourcedump(); # displays source sub usage(); # prints usssage sub version(); # prints version sub main(@); # +-=-=-=-=-=-=-+ # | | # | Functions | # | | # +-=-=-=-=-=-=-+ # displays button sub button($$;$) { # grabs passed args my $link = shift; my $title = shift; my $hint = shift || $title; # prints button printf(""); printf(""); printf(""); printf(""); printf("
"); printf("", $hint, $link, $hint); printf("  %s  ", $title); printf(""); printf("
"); # ends function return(0); }; # parses commandline sub cmdline(@) { # grabs passed args my @argv = @_; # declares local vars my $arg; my $buff; my $name; my $pair; my $value; my @list; my @pairs; my @timestamp; # creates headers if (! defined($ENV{'QUERY_STRING'})) { foreach $arg (@argv) { if ($arg eq '--help') { usage(); exit(0); } elsif ($arg eq '--version') { version(); exit(0); }; }; if (@argv < 1) { usage(); exit(0); }; return(calc_ips(@argv)); }; # checks path INFO if ($ENV{'PATH_INFO'}) { if ($ENV{'PATH_INFO'} eq "/" . $PROGRAM_NAME) { sourcedump(); exit(0); } elsif ($ENV{'PATH_INFO'} eq "/--help") { printf("Content-type: text/html\n\n"); help(); exit(0); } elsif ($ENV{'PATH_INFO'} eq '/--version') { printf("Content-type: text/html\n\n"); version(); exit(0); }; }; if ($ENV{'QUERY_STRING'} eq "sourcedump") { sourcedump(); exit(0); } elsif ($ENV{'QUERY_STRING'} eq "--help") { printf("Content-type: text/html\n\n"); usage(); exit(0); } elsif ($ENV{'QUERY_STRING'} eq "--version") { printf("Content-type: text/html\n\n"); version(); exit(0); }; # prints headers printf("Content-type: text/html\n\n"); # parses linked data $buff = $ENV{'QUERY_STRING'}; @pairs = split(/&/, $buff); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); if ($name eq 'ip') { $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; #if ($value =~ /^([\d]+\.[\d]+\.[\d]+\.[\d]+[ ]{0,1})+$/) if ($value =~ /^([\d]+\.[\d]+\.[\d]+\.[\d]+)$/) { $list[@list] = $1; #return(calc_ips(@list)); }; } elsif ($name eq 'noform') { if ($value eq 'true') { $ENV{'NOFORM'} = 'true'; }; } elsif ($name eq 'nowhois') { if ($value eq 'true') { $ENV{'NOWHOIS'} = 'true'; }; } elsif ($name eq 'noopts') { if ($value eq 'true') { $ENV{'NOOPTS'} = 'true'; }; }; }; # sets default IP addresses if (@list eq 0) { # sets 192.168.X.X addresses using Month, Day, hour, and minute @timestamp = localtime(time); $list[@list] = (0xc0a8 << 16) | (($timestamp[4] + 1) << 8) | ($timestamp[3]); $list[@list] = (0xc0a8 << 16) | (($timestamp[2]) << 8) | ($timestamp[1]); $ENV{'QUERY_STRING'} = 'ip='; }; # ends function return(calc_ips(@list)); }; # generates list of IP addresses sub calc_ips(@) { # grabs passed args my @ips = @_; # declares local vars my $count; my @list; # creates list of IP addresses for($count = 0; $count < @ips; $count++) { if ($ips[$count] =~ /^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/) { $list[@list] = (($1 & 0xff) << 24) | (($2 & 0xff) << 16) | (($3 & 0xff) << 8) | ($4 & 0xff); } elsif ($ips[$count] =~ /^([\d]+)$/) { $list[@list] = $1; }; }; # ends function return(@list); }; # calculates nework address of smallest network sub calc_network(@) { # grabs passed args my @list = @_; # declares local vars my $ip; my $net; my $mask; my $cidr; # sets preliminary values $net = 0xFFFFFFFF; $mask = 0; $cidr = 33; # loops through network data while ((! $mask)&&($net)) { $mask = $net; foreach $ip (@list) { if (($ip & $mask) != ($list[0] & $mask)) { $mask = 0; }; }; $net = $net << 1; $cidr--; }; # ends function return($mask, $cidr); }; # displays network data sub display($$$) { # grabs passed args my $mask = shift; my $cidr = shift; my $ip = shift; # declares local vars my $net; # prints header if ($ENV{'QUERY_STRING'}) { printf("\n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); } else { printf("%-16s %-4s %-11s %-16s %-16s %s\n", "Network", "CIDR", "Netmask", "Netmask", "Broadcast", "IP Count"); }; # prints data while($cidr > 0) { $net = $mask & $ip; if ($ENV{'QUERY_STRING'}) { printf(" \n"); if ($ENV{'NOWHOIS'}) { printf(" \n", ip2str($net)); } else { printf(" \n", $ENV{'WHOIS'}, ip2str($net), ip2str($net)); }; printf(" \n", $cidr); printf(" \n", $mask); printf(" \n", ip2str($mask)); if ($cidr == 32) { printf(" \n", ip2str($net)); printf(" \n", 1); } else { printf(" \n", ip2str( (0xFFFFFFFF>>$cidr)|$net )); printf(" \n", (0xFFFFFFFF>>($cidr))+1); }; printf(" \n"); } else { if ($cidr == 32) { printf("%-16s %-4s 0x%08X %-16s %-16s %s\n", ip2str($net), $cidr, $mask, ip2str($mask), ip2str($net), 1); } else { printf("%-16s %-4s 0x%08X %-16s %-16s %s\n", ip2str($net), $cidr, $mask, ip2str($mask), ip2str((0xFFFFFFFF>>$cidr)|$net), (0xFFFFFFFF>>($cidr))+1); }; }; $mask = $mask << 1; $cidr--; }; # prints last network if ($ENV{'QUERY_STRING'}) { printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n"); printf(" \n", 0xFFFFFFFF); } else { printf("%-16s %-4s 0x%08X %-16s %-16s %s\n", "0.0.0.0", 0, 0, "0.0.0.0", "255.255.255.255", 0xFFFFFFFF); }; # prints tailer if ($ENV{'QUERY_STRING'}) { printf("
Common Networks
  Network    CIDR    Netmask (hex)    Netmask (octets)    Broadcast    IP Count  
  %s    %s    %s    0x%08X    %s    %s    %s    %s    %s  
  0.0.0.0    0    0x00000000    0.0.0.0    255.255.255.255    %s  
\n"); }; #printf("network: %u.%u.%u.%u\n", ($mask >> 24)&0xFF, ($mask>>16)&0xFF, ($mask>>8)&0xFF, $mask&0xFF); # ends function return(0); }; # displays form sub form(@) { # grabs passed args my @list = @_; # declares local vars my $ip1; my $ip2; # checks for CGI if ((!defined($ENV{'QUERY_STRING'})) || ($ENV{'NOFORM'})) { return(0); }; # checks default if (@list < 1) { $list[@list] = (192<<24) | (168<<16) | (0<<8) | 1; }; # sets first and last IP @list = sort(@list); $ip1 = $list[0]; if (@list > 1) { $ip2 = $list[@list - 1]; }; # prints form printf("

Network Calculator

\n"); printf("
\n"); printf(" IP address:
\n", ip2str($ip1)); if ($ip2) { printf(" IP address:
\n", ip2str($ip2)); } else { printf(" IP address:
\n"); }; if ($ENV{'NOOPTS'}) { printf(" \n"); } else { if ($ENV{'NOWHOIS'}) { printf(" Hide Whois links
\n"); } else { printf(" Hide Whois links
\n"); }; }; printf("
\n"); printf(" \n"); printf("
\n"); # ends function return(0); }; # converts IP to string sub ip2str($) { my $ip = shift; my $str; $str = ($ip>>24) & 0xFF; $str = $str . '.'; $str = $str . (($ip>>16) & 0xFF); $str = $str . '.'; $str = $str . (($ip>>8) & 0xFF); $str = $str . '.'; $str = $str . ($ip & 0xFF); return($str); }; # displays source sub sourcedump() { printf("Content-type: text/plain\n\n"); if (! $ENV{'SCRIPT_FILENAME'}) { return(0); }; if (! open(FILE, "$ENV{'SCRIPT_FILENAME'}")) { return(0); }; while() { printf("%s", $_); }; close(FILE); return(0); }; # prints usssage sub usage() { if ($ENV{'QUERY_STRING'}) { printf("
\n");
   };
   printf("Command Line Usage: %s [options] address [address]\n", $PROGRAM_NAME);
   printf("      --help            print this help and exit\n");
   printf("      --version         print version number and exit\n");
   printf("CGI Usage:\n");
   printf("  ip=x.x.x.x            first IP address used to calculate IP netblock\n");
   printf("  ip=x.x.x.x            second IP address used to calculate IP netblock\n");
   printf("  noform=true           boolean value causes CGI to not print form\n");
   printf("  nowhois=true          boolean value causes CGI to not print links to whois\n");
   printf("  sourcedump            displays source code\n");
   if ($AUTHOR)
   {
      printf("\n");
      printf("Report bugs to %s.\n", $AUTHOR);
   };
   if ($ENV{'QUERY_STRING'})
   {
      printf("

\n"); printf("Version Information\n"); printf("    \n"); printf("Use Calculator\n"); if (($ENV{'QUERY_STRING'})&&($ENV{'SCRIPT_NAME'})&&($ENV{'SERVER_PROTOCOL'})) { printf("
\n"); printf("

Source Code

\n", $ENV{'SCRIPT_NAME'}, $PROGRAM_NAME); }; }; return; }; # prints version sub version() { if ($ENV{'QUERY_STRING'}) { printf("
\n");
   };
   printf("%s (%s) %s\n", $PROGRAM_NAME, $DESCRIPTION, $VERSION);
   printf("Written by %s.\n", $AUTHOR);
   printf("\n");
   printf("Copyright 2006 (c) %s\n", $AUTHOR);
   printf("This is free software; see the source for copying conditions.  There is NO\n");
   printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
   if ($ENV{'QUERY_STRING'})
   {
      printf("

\n"); printf("Help Information\n"); printf("    \n"); printf("Use Calculator\n"); if (($ENV{'QUERY_STRING'})&&($ENV{'SCRIPT_NAME'})&&($ENV{'SERVER_PROTOCOL'})) { printf("
\n"); printf("

Source Code

\n", $ENV{'SCRIPT_NAME'}, $PROGRAM_NAME); }; }; return; }; # +-=-=-=-=-=-=-=-=-+ # | | # | Main Section | # | | # +-=-=-=-=-=-=-=-=-+ sub main(@) { # grabs passed args my @argv = @_; # declares local vars my $cidr; my $mask; my @list; @list = cmdline(@ARGV); # prints form form(@list); # processes networks if (@list > 0) { # determines Network address ($mask, $cidr) = calc_network(@list); # displays data display($mask, $cidr, $list[0]); }; # show source code if (($ENV{'QUERY_STRING'})&&($ENV{'SCRIPT_NAME'})&&($ENV{'SERVER_PROTOCOL'})) { printf("

Source Code

\n", $ENV{'SCRIPT_NAME'}, $PROGRAM_NAME); }; # ends function return(0); }; exit(main(@ARGV)); # ends function