public inbox for ipfire-scm@lists.ipfire.org
 help / color / mirror / Atom feed
From: git@ipfire.org
To: ipfire-scm@lists.ipfire.org
Subject: [git.ipfire.org] IPFire 2.x development tree branch, next, updated. 4e9a2b57320fc17a2eaee06b60ee508ec79e59b0
Date: Sun, 27 Jul 2014 23:00:57 +0200	[thread overview]
Message-ID: <20140727210057.A107A212C4@argus.ipfire.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 17305 bytes --]

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "IPFire 2.x development tree".

The branch, next has been updated
       via  4e9a2b57320fc17a2eaee06b60ee508ec79e59b0 (commit)
      from  10cd52ba8e0f1c44666cd4a2bf9845c4e783a238 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4e9a2b57320fc17a2eaee06b60ee508ec79e59b0
Author: Michael Tremer <michael.tremer(a)ipfire.org>
Date:   Sun Jul 27 22:46:20 2014 +0200

    general-functions.pl: Replace lots of broken network code.
    
    The state of some code especially in general-functions.pl
    is in such a bad shape and faulty.
    This is a first step that replaces some of the network
    functions with those who have been tested and work for
    undefined inputs.
    
    The old functions have been left in place as stubs
    and must be removed at some time.

-----------------------------------------------------------------------

Summary of changes:
 config/cfgroot/general-functions.pl | 135 ++++------------
 config/cfgroot/network-functions.pl | 306 ++++++++++++++++++++++++++++++++++++
 config/firewall/rules.pl            |   2 +
 config/rootfiles/common/configroot  |   1 +
 lfs/configroot                      |   1 +
 5 files changed, 339 insertions(+), 106 deletions(-)
 create mode 100644 config/cfgroot/network-functions.pl

Difference in files:
diff --git a/config/cfgroot/general-functions.pl b/config/cfgroot/general-functions.pl
index 6994f33..66286ed 100644
--- a/config/cfgroot/general-functions.pl
+++ b/config/cfgroot/general-functions.pl
@@ -26,6 +26,8 @@ $General::swroot = 'CONFIG_ROOT';
 $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
@@ -281,21 +283,10 @@ sub validip
 	}
 }
 
-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
@@ -316,24 +307,12 @@ 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
@@ -408,15 +387,8 @@ sub iporsubtocidr
 	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
@@ -431,46 +403,20 @@ 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
@@ -766,28 +712,12 @@ sub validportrange # used to check a port range
 	}
 }
 
-# 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");
 }
 
 #
@@ -795,32 +725,25 @@ sub IpInSubnet
 # 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\.\-]+$/ );
diff --git a/config/cfgroot/network-functions.pl b/config/cfgroot/network-functions.pl
new file mode 100644
index 0000000..029ffc0
--- /dev/null
+++ b/config/cfgroot/network-functions.pl
@@ -0,0 +1,306 @@
+#!/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(a)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();
diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl
index c0ddcb2..aa8870c 100755
--- a/config/firewall/rules.pl
+++ b/config/firewall/rules.pl
@@ -291,6 +291,7 @@ sub buildrules {
 
 			foreach my $src (@sources) {
 				# Skip invalid source.
+				next unless (defined $src);
 				next unless ($src);
 
 				# Sanitize source.
@@ -301,6 +302,7 @@ sub buildrules {
 
 				foreach my $dst (@destinations) {
 					# Skip invalid rules.
+					next unless (defined $dst);
 					next if (!$dst || ($dst eq "none"));
 
 					# Sanitize destination.
diff --git a/config/rootfiles/common/configroot b/config/rootfiles/common/configroot
index 6afe6cd..8e5aff8 100644
--- a/config/rootfiles/common/configroot
+++ b/config/rootfiles/common/configroot
@@ -117,6 +117,7 @@ var/ipfire/modem
 #var/ipfire/modem/defaults
 #var/ipfire/modem/settings
 var/ipfire/modem-lib.pl
+var/ipfire/network-functions.pl
 var/ipfire/net-traffic
 #var/ipfire/net-traffic/net-traffic-admin.pl
 #var/ipfire/net-traffic/net-traffic-lib.pl
diff --git a/lfs/configroot b/lfs/configroot
index fcb08b0..e0bb346 100644
--- a/lfs/configroot
+++ b/lfs/configroot
@@ -77,6 +77,7 @@ $(TARGET) :
 	# Copy initial configfiles
 	cp $(DIR_SRC)/config/cfgroot/header.pl			$(CONFIG_ROOT)/
 	cp $(DIR_SRC)/config/cfgroot/general-functions.pl	$(CONFIG_ROOT)/
+	cp $(DIR_SRC)/config/cfgroot/network-functions.pl	$(CONFIG_ROOT)/
 	cp $(DIR_SRC)/config/cfgroot/lang.pl			$(CONFIG_ROOT)/
 	cp $(DIR_SRC)/config/cfgroot/countries.pl		$(CONFIG_ROOT)/
 	cp $(DIR_SRC)/config/cfgroot/graphs.pl			$(CONFIG_ROOT)/


hooks/post-receive
--
IPFire 2.x development tree

                 reply	other threads:[~2014-07-27 21:00 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140727210057.A107A212C4@argus.ipfire.org \
    --to=git@ipfire.org \
    --cc=ipfire-scm@lists.ipfire.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox