$General::noipprefix = 'noipg-';
$General::adminmanualurl = 'http://wiki.ipfire.org';
+require "${General::swroot}/network-functions.pl";
+
#
# log ("message") use default 'ipcop' tag
# log ("tag","message") use your tag
}
}
-sub validmask
-{
- my $mask = $_[0];
+sub validmask {
+ my $mask = shift;
- # secord part an ip?
- if (&validip($mask)) {
- return 1; }
- # second part a number?
- if (/^0/) {
- return 0; }
- if (!($mask =~ /^\d+$/)) {
- return 0; }
- if ($mask >= 0 && $mask <= 32) {
- return 1; }
- return 0;
+ return &Network::check_netmask($mask) or &Network::check_prefix($mask);
}
sub validipormask
return &validmask($mask);
}
-sub subtocidr
-{
- #gets: Subnet in decimal (255.255.255.0)
- #Gives: 24 (The cidr of network)
- my ($byte1, $byte2, $byte3, $byte4) = split(/\./, $_[0].".0.0.0.0");
- my $num = ($byte1 * 16777216) + ($byte2 * 65536) + ($byte3 * 256) + $byte4;
- my $bin = unpack("B*", pack("N", $num));
- my $count = ($bin =~ tr/1/1/);
- return $count;
+sub subtocidr {
+ return &Network::convert_netmask2prefix(shift);
}
-sub cidrtosub
-{
- #gets: Cidr of network (20-30 for ccd)
- #Konverts 30 to 255.255.255.252 e.g
- my $cidr=$_[0];
- my $netmask = &Net::IPv4Addr::ipv4_cidr2msk($cidr);
- return "$netmask";
+sub cidrtosub {
+ return &Network::convert_prefix2netmask(shift);
}
sub iporsubtodec
return 3;
}
-sub getnetworkip
-{
- #Gets: IP, CIDR (10.10.10.0-255, 24)
- #Gives: 10.10.10.0
- my ($ccdip,$ccdsubnet) = @_;
- my $ip_address_binary = &Socket::inet_pton( AF_INET,$ccdip );
- my $netmask_binary = &Socket::inet_pton(AF_INET,&iporsubtodec($ccdsubnet));
- my $network_address = &Socket::inet_ntop( AF_INET,$ip_address_binary & $netmask_binary );
- return $network_address;
+sub getnetworkip {
+ return &Network::get_netaddress(shift);
}
sub getccdbc
return $broadcast_address;
}
-sub ip2dec
-{
- my $ip_num;
- my $ip=$_[0];
- if ( $ip =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/ ) {
- $ip_num = (($1*256**3) + ($2*256**2) + ($3*256) + $4);
- } else {
- $ip_num = -1;
- }
- $ip_num = (($1*256**3) + ($2*256**2) + ($3*256) + $4);
- return($ip_num);
+sub ip2dec {
+ return &Network::ip2bin(shift);
}
-sub dec2ip
-{
- my $ip;
- my $ip_num=$_[0];
- my $o1=$ip_num%256;
- $ip_num=int($ip_num/256);
- my $o2=$ip_num%256;
- $ip_num=int($ip_num/256);
- my $o3=$ip_num%256;
- $ip_num=int($ip_num/256);
- my $o4=$ip_num%256;
- $ip="$o4.$o3.$o2.$o1";
- return ($ip);
+sub dec2ip {
+ return &Network::bin2ip(shift);
}
-sub getnextip
-{
- my $decip=&ip2dec($_[0]);
- $decip=$decip+4;
- return &dec2ip($decip);
+sub getnextip {
+ return &Network::find_next_ip_address(shift, 4);
}
-sub getlastip
-{
- my $decip=&ip2dec($_[0]);
- $decip--;
- return &dec2ip($decip);
+sub getlastip {
+ return &Network::find_next_ip_address(shift, -1);
}
sub validipandmask
}
}
-# Test if IP is within a subnet
-# Call: IpInSubnet (Addr, Subnet, Subnet Mask)
-# Subnet can be an IP of the subnet: 10.0.0.0 or 10.0.0.1
-# Everything in dottted notation
-# Return: TRUE/FALSE
-sub IpInSubnet
-{
+sub IpInSubnet {
my $addr = shift;
my $network = shift;
my $netmask = shift;
- my $addr_num = &Socket::inet_pton(AF_INET,$addr);
- my $network_num = &Socket::inet_pton(AF_INET,$network);
- my $netmask_num = &Socket::inet_pton(AF_INET,$netmask);
-
- # Find start address
- my $network_start = $network_num & $netmask_num;
-
- # Find end address
- my $network_end = $network_start ^ ~$netmask_num;
-
- return (($addr_num ge $network_start) && ($addr_num le $network_end));
+ return &Network::ip_address_in_network($addr, "$network/$netmask");
}
#
# Call: NextIP ('1.1.1.1');
# Return: '1.1.1.2'
#
-sub NextIP
-{
- return &Socket::inet_ntoa( pack("N", 1 + unpack('N', &Socket::inet_aton(shift))
- )
- );
+sub NextIP {
+ return &Network::find_next_ip_address(shift, 1);
}
-sub NextIP2
-{
- return &Socket::inet_ntoa( pack("N", 4 + unpack('N', &Socket::inet_aton(shift))
- )
- );
+
+sub NextIP2 {
+ return &Network::find_next_ip_address(shift, 4);
}
-sub ipcidr
-{
+
+sub ipcidr {
my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
return "$ip\/$cidr";
}
-sub ipcidr2msk
-{
+sub ipcidr2msk {
my ($ip,$cidr) = &Net::IPv4Addr::ipv4_parse(shift);
my $netmask = &Net::IPv4Addr::ipv4_cidr2msk($cidr);
return "$ip\/$netmask";
}
-
sub validemail {
my $mail = shift;
return 0 if ( $mail !~ /^[0-9a-zA-Z\.\-\_]+\@[0-9a-zA-Z\.\-]+$/ );
--- /dev/null
+#!/usr/bin/perl -w
+############################################################################
+# #
+# This file is part of the IPFire Firewall. #
+# #
+# IPFire 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. #
+# #
+# IPFire 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 IPFire; if not, write to the Free Software #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+# #
+# Copyright (C) 2014 IPFire Team <info@ipfire.org>. #
+# #
+############################################################################
+
+package Network;
+
+use Socket;
+
+my %PREFIX2NETMASK = (
+ 32 => "255.255.255.255",
+ 31 => "255.255.255.254",
+ 30 => "255.255.255.252",
+ 29 => "255.255.255.248",
+ 28 => "255.255.255.240",
+ 27 => "255.255.255.224",
+ 26 => "255.255.255.192",
+ 25 => "255.255.255.128",
+ 24 => "255.255.255.0",
+ 23 => "255.255.254.0",
+ 22 => "255.255.252.0",
+ 21 => "255.255.248.0",
+ 20 => "255.255.240.0",
+ 19 => "255.255.224.0",
+ 18 => "255.255.192.0",
+ 17 => "255.255.128.0",
+ 16 => "255.255.0.0",
+ 15 => "255.254.0.0",
+ 14 => "255.252.0.0",
+ 13 => "255.248.0.0",
+ 12 => "255.240.0.0",
+ 11 => "255.224.0.0",
+ 10 => "255.192.0.0",
+ 9 => "255.128.0.0",
+ 8 => "255.0.0.0",
+ 7 => "254.0.0.0",
+ 6 => "252.0.0.0",
+ 5 => "248.0.0.0",
+ 4 => "240.0.0.0",
+ 3 => "224.0.0.0",
+ 2 => "192.0.0.0",
+ 1 => "128.0.0.0",
+ 0 => "0.0.0.0"
+);
+
+my %NETMASK2PREFIX = reverse(%PREFIX2NETMASK);
+
+# Takes an IP address in dotted decimal notation and
+# returns a 32 bit integer representing that IP addresss.
+# Will return undef for invalid inputs.
+sub ip2bin($) {
+ my $address = shift;
+
+ # This function returns undef for undefined input.
+ if (!defined $address) {
+ return undef;
+ }
+
+ my $address_bin = &Socket::inet_pton(AF_INET, $address);
+ if ($address_bin) {
+ $address_bin = unpack('N', $address_bin);
+ }
+
+ return $address_bin;
+}
+
+# Does the reverse of ip2bin().
+# Will return undef for invalid inputs.
+sub bin2ip($) {
+ my $address_bin = shift;
+
+ # This function returns undef for undefined input.
+ if (!defined $address_bin) {
+ return undef;
+ }
+
+ my $address = pack('N', $address_bin);
+ if ($address) {
+ $address = &Socket::inet_ntop(AF_INET, $address);
+ }
+
+ return $address;
+}
+
+# Takes a network in either a.b.c.d/a.b.c.d or a.b.c.d/e notation
+# and will return an 32 bit integer representing the start
+# address and an other one representing the network mask.
+sub network2bin($) {
+ my $network = shift;
+
+ my ($address, $netmask) = split(/\//, $network, 2);
+
+ if (&check_prefix($netmask)) {
+ $netmask = &convert_prefix2netmask($netmask);
+ }
+
+ my $address_bin = &ip2bin($address);
+ my $netmask_bin = &ip2bin($netmask);
+
+ my $network_start = $address_bin & $netmask_bin;
+
+ return ($network_start, $netmask_bin);
+}
+
+# Returns True for all valid IP addresses
+sub check_ip_address($) {
+ my $address = shift;
+
+ # Normalise the IP address and compare the result with
+ # the input - which should obviously the same.
+ my $normalised_address = &_normalise_ip_address($address);
+
+ return ((defined $normalised_address) && ($address eq $normalised_address));
+}
+
+# Returns True for all valid prefixes.
+sub check_prefix($) {
+ my $prefix = shift;
+
+ return (exists $PREFIX2NETMASK{$prefix});
+}
+
+# Returns True for all valid subnet masks.
+sub check_netmask($) {
+ my $netmask = shift;
+
+ return (exists $NETMASK2PREFIX{$netmask});
+}
+
+# Returns True for all valid inputs like a.b.c.d/a.b.c.d.
+sub check_ip_address_and_netmask($$) {
+ my $network = shift;
+
+ my ($address, $netmask) = split(/\//, $network, 2);
+
+ # Check if the IP address is fine.
+ #
+ my $result = &check_ip_address($address);
+ unless ($result) {
+ return $result;
+ }
+
+ return &check_netmask($netmask);
+}
+
+# For internal use only. Will take an IP address and
+# return it in a normalised style. Like 8.8.8.010 -> 8.8.8.8.
+sub _normalise_ip_address($) {
+ my $address = shift;
+
+ my $address_bin = &ip2bin($address);
+ if (!defined $address_bin) {
+ return undef;
+ }
+
+ return &bin2ip($address_bin);
+}
+
+# Returns the prefix for the given subnet mask.
+sub convert_netmask2prefix($) {
+ my $netmask = shift;
+
+ if (exists $NETMASK2PREFIX{$netmask}) {
+ return $NETMASK2PREFIX{$netmask};
+ }
+
+ return undef;
+}
+
+# Returns the subnet mask for the given prefix.
+sub convert_prefix2netmask($) {
+ my $prefix = shift;
+
+ if (exists $PREFIX2NETMASK{$prefix}) {
+ return $PREFIX2NETMASK{$prefix};
+ }
+
+ return undef;
+}
+
+# Takes an IP address and an offset and
+# will return the offset'th IP address.
+sub find_next_ip_address($$) {
+ my $address = shift;
+ my $offset = shift;
+
+ my $address_bin = &ip2bin($address);
+ $address_bin += $offset;
+
+ return &bin2ip($address_bin);
+}
+
+# Returns the network address of the given network.
+sub get_netaddress($) {
+ my $network = shift;
+ my ($network_bin, $netmask_bin) = &network2bin($network);
+
+ if (defined $network_bin) {
+ return &bin2ip($network_bin);
+ }
+
+ return undef;
+}
+
+# Returns the broadcast of the given network.
+sub get_broadcast($) {
+ my $network = shift;
+ my ($network_bin, $netmask_bin) = &network2bin($network);
+
+ return &bin2ip($network_bin ^ ~$netmask_bin);
+}
+
+# Returns True if $address is in $network.
+sub ip_address_in_network($$) {
+ my $address = shift;
+ my $network = shift;
+
+ my $address_bin = &ip2bin($address);
+ return undef unless (defined $address_bin);
+
+ my ($network_bin, $netmask_bin) = &network2bin($network);
+
+ # Find end address
+ my $broadcast_bin = $network_bin ^ ~$netmask_bin;
+
+ return (($address_bin ge $network_bin) && ($address_bin le $broadcast_bin));
+}
+
+1;
+
+# Remove the next line to enable the testsuite
+__END__
+
+sub assert($) {
+ my $ret = shift;
+
+ if ($ret) {
+ return;
+ }
+
+ print "ASSERTION ERROR";
+ exit(1);
+}
+
+sub testsuite() {
+ my $result;
+
+ my $address1 = &ip2bin("8.8.8.8");
+ assert($address1 == 134744072);
+
+ my $address2 = &bin2ip($address1);
+ assert($address2 eq "8.8.8.8");
+
+ # Check if valid IP addresses are correctly recognised.
+ foreach my $address ("1.2.3.4", "192.168.180.1", "127.0.0.1") {
+ if (!&check_ip_address($address)) {
+ print "$address is not correctly recognised as a valid IP address!\n";
+ exit 1;
+ };
+ }
+
+ # Check if invalid IP addresses are correctly found.
+ foreach my $address ("456.2.3.4", "192.768.180.1", "127.1", "1", "a.b.c.d", "1.2.3.4.5", "1.2.3.4/12") {
+ if (&check_ip_address($address)) {
+ print "$address is recognised as a valid IP address!\n";
+ exit 1;
+ };
+ }
+
+ $result = &check_ip_address_and_netmask("192.168.180.0/255.255.255.0");
+ assert($result);
+
+ $result = &convert_netmask2prefix("255.255.254.0");
+ assert($result == 23);
+
+ $result = &convert_prefix2netmask(8);
+ assert($result eq "255.0.0.0");
+
+ $result = &find_next_ip_address("1.2.3.4", 2);
+ assert($result eq "1.2.3.6");
+
+ $result = &ip_address_in_network("10.0.1.4", "10.0.0.0/8");
+ assert($result);
+
+ return 0;
+}
+
+&testsuite();