[wiaflos-devel] awit-perl-toolkit external COMMIT - r11 - trunk/awitpt
svn at linuxrulz.org
svn at linuxrulz.org
Thu Dec 10 10:06:32 GMT 2009
Author: nkukard
Date: 2009-12-10 10:06:32 +0000 (Thu, 10 Dec 2009)
New Revision: 11
Modified:
trunk/awitpt/netip.pm
Log:
* Fixed up network IP handling
- Robert Anderson <randerson at lbsd.net>
Modified: trunk/awitpt/netip.pm
===================================================================
--- trunk/awitpt/netip.pm 2009-12-08 06:48:47 UTC (rev 10)
+++ trunk/awitpt/netip.pm 2009-12-10 10:06:32 UTC (rev 11)
@@ -1,4 +1,4 @@
-# network IP Address Handling
+# Network IP Address Handling
# Copyright (C) 2009, AllWorldIT
# Copyright (C) 2008, LinuxRulz
#
@@ -60,6 +60,12 @@
{
my ($type,$ip) = @_;
+
+ # Make sure IP is defined
+ if (!defined($ip)) {
+ setError("IP address not defined");
+ }
+
my $self = {};
# Guess ip version
@@ -68,7 +74,7 @@
} elsif (($ip =~ /\./) || ($ip =~ /^\d{1,3}(\/\d{1,2})?$/)) {
$self->{'ip_version'} = 4;
} else {
- setError("Failed to guess ip version");
+ setError("Failed to guess IP address version");
return undef;
}
@@ -78,7 +84,7 @@
bless($self,$type);
# Clean the raw IP
- if (!$self->clean_ip()) {
+ if (!$self->_clean_ip()) {
return undef;
}
@@ -86,6 +92,152 @@
}
+# Clone an object
+sub copy
+{
+ my $self = shift;
+ my %params = @_;
+
+ my $clone = bless({
+ 'ip_version' => $self->{'ip_version'},
+ 'ip' => $self->{'ip'},
+ 'cidr' => defined($params{'cidr'}) ? $params{'cidr'} : $self->{'cidr'}
+ }, ref($self));
+
+ return $clone;
+}
+
+
+# Convert to binary
+sub to_bin
+{
+ my $self = shift;
+
+ # We already have it in bin
+ return $self->{'ip_bin'} if ($self->{'ip_bin'});
+
+ # Check how to convert to bin
+ if ($self->{'ip_version'} == 6) {
+ my $cleanIP = $self->{'ip'};
+ $cleanIP =~ s/://g;
+ $self->{'ip_bin'} = unpack('B128', pack('H32', $cleanIP));
+
+ } elsif ($self->{'ip_version'} == 4) {
+ $self->{'ip_bin'} = unpack('B32', pack('C4C4C4C4', split(/\./, $self->{'ip'})));
+ }
+
+ return $self->{'ip_bin'};
+}
+
+
+# Convert to string
+sub to_str
+{
+ my ($self,$bin) = @_;
+
+
+ # We can only add the cidr suffix if we are working on $self
+ my $suffix = "";
+
+ # Allow us to use a parameter as the bin to convert aswell, if none provided, use self
+ if (!defined($bin)) {
+ $bin = $self->to_bin();
+ $suffix = "/".$self->{'cidr'};
+ }
+
+ # Convert to string format
+ my $resIP;
+ if (length($bin) == 32) {
+ $resIP = join '.', unpack('C4C4C4C4', pack('B32', $bin));
+ } elsif (length($bin) == 128) {
+ $resIP = join(':', unpack('H4H4H4H4H4H4H4H4', pack('B128', $bin)));
+ }
+
+ return $resIP.$suffix;
+}
+
+
+# Convert address to Math::BigInt
+sub to_int
+{
+ my $self = shift;
+
+ # $n is the increment (the numerical value of the bit we about to 'set')
+ my $n = Math::BigInt->new(1);
+ # $ret is the returned value
+ my $ret = Math::BigInt->new(0);
+
+ # Reverse the bit string
+ foreach my $bit (reverse(split '', $self->to_bin())) {
+ # If the nth bit is 1, add 2**n to $ret
+ if ($bit) {
+ $ret += $n;
+ }
+ # Next bit value...
+ $n *= 2;
+ }
+
+ return $ret;
+}
+
+
+# Get the network address
+sub to_network
+{
+ my $self = shift;
+
+
+ if (!defined($self->{'network_bin'})) {
+ $self->_calc_ranges();
+ }
+
+ $self->{'ip'} = $self->to_str($self->{'network_bin'});
+ $self->{'ip_bin'} = undef;
+
+ return $self;
+}
+
+
+# Get the broadcast address
+sub to_broadcast
+{
+ my $self = shift;
+
+
+ if (!defined($self->{'broadcast_bin'})) {
+ $self->_calc_ranges();
+ }
+
+ $self->{'ip'} = $self->to_str($self->{'broadcast_bin'});
+ $self->{'ip_bin'} = undef;
+
+ return $self;
+}
+
+
+# Check if ip address is inside another ip address range
+sub is_within
+{
+ my ($self,$test) = @_;
+
+ # We can only compare IPs of same type
+ if ($self->{'ip_version'} != $test->{'ip_version'}) {
+ return 0;
+ }
+
+ my $network = $test->copy()->to_network()->to_int();
+ my $broadcast = $test->copy()->to_broadcast()->to_int();
+
+ my $self_int = $self->to_int();
+
+ if ($self_int >= $network && $self_int <= $broadcast) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
# Check for a valid ipv6/ipv4 address
sub is_valid
{
@@ -168,23 +320,8 @@
}
-# Clone an object
-sub copy
-{
- my $self = shift;
-
- my $clone = bless({
- 'ip_version' => $self->{'ip_version'},
- 'ip' => $self->{'ip'},
- 'cidr' => $self->{'cidr'}
- }, ref($self));
-
- return $clone;
-}
-
-
# Check the IP address and format accordingly
-sub clean_ip
+sub _clean_ip
{
my $self = shift;
@@ -193,24 +330,24 @@
# Pull off mask
my $mask;
if ($self->{'raw_ip'} =~ s/\/(\d{1,2})$//g) {
- $mask = $1 ? $1 : undef;
+ $mask = defined($1) ? $1 : undef;
}
# Check for invalid chars
if (!($self->{'raw_ip'} =~ m/^[\d\.]+$/)) {
- setError("IPv4 Address '".$self->{'raw_ip'}."' contains invalid characters");
+ setError("IPv4 address '".$self->{'raw_ip'}."' contains invalid characters");
return 0;
}
# Check for leading .
if ($self->{'raw_ip'} =~ m/^\./) {
- setError("IPv4 Address '".$self->{'raw_ip'}."' begins with '.'");
+ setError("IPv4 address '".$self->{'raw_ip'}."' begins with '.'");
return 0;
}
# Check for trailing .
if ($self->{'raw_ip'} =~ m/\.$/) {
- setError("IPv4 Address '".$self->{'raw_ip'}."' ends with '.'");
+ setError("IPv4 address '".$self->{'raw_ip'}."' ends with '.'");
return 0;
}
@@ -223,7 +360,7 @@
# Check for invalid octets
foreach my $octet ($a,$b,$c,$d) {
if (defined($octet) && $octet > 255) {
- setError("Address '".$self->{'raw_ip'}."' contains octets which exceed 255");
+ setError("IPv4 address '".$self->{'raw_ip'}."' contains octets which exceed 255");
return 0;
}
}
@@ -243,7 +380,7 @@
}
# Default mask
- $mask = ( defined($mask) && $mask >= 1 && $mask <= 32 ) ? $mask : 32;
+ $mask = ( defined($mask) && $mask >= 0 && $mask <= 32 ) ? $mask : 32;
$self->{'cidr'} = $mask;
# Build ip
@@ -251,11 +388,11 @@
# Check for full ipv4
if (!($self->{'ip'} =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) {
- setError("Address '".$self->{'ip'}."' is not a full ipv4 address");
+ setError("IPv4 address '".$self->{'ip'}."' is not a full ipv4 address");
return 0;
}
} else {
- setError("Address '".$self->{'raw_ip'}."' is not a supported format");
+ setError("IP address '".$self->{'raw_ip'}."' is not a supported format");
return 0;
}
@@ -264,7 +401,7 @@
# Pull off mask
my $mask;
if ($self->{'raw_ip'} =~ s/\/(\d{1,3})$//g) {
- $mask = $1 ? $1 : undef;
+ $mask = defined($1) ? $1 : undef;
}
# Count octets
@@ -274,21 +411,33 @@
return 0;
}
- # $k is a counter
- my $k;
+ # Number of specified octets
+ my $numOctets = 0;
+ # Number of octets specified on the left hand side
+ my $preOctets = 0;
# Check octets
- foreach (split /:/, $self->{'raw_ip'}) {
+ my $foundEmpty = 0;
+ foreach my $octet (split /:/, $self->{'raw_ip'}) {
- # Empty octet ?
- next if ($_ eq '');
+ # Empty octet?
+ if ($octet eq '') {
+ $foundEmpty = 1;
+ next;
+ }
+ # If we not found an empty octet, we have one more octet on the left hand side (pre)
+ if (!$foundEmpty) {
+ $preOctets++;
+ }
- $k++;
+ $numOctets++;
- # Normal v6 octet ?
- next if (/^[a-f\d]{1,4}$/i);
+ # Normal v6 octet?
+ if ($octet =~ /^[a-f\d]{1,4}$/i) {
+ next;
+ }
- setError("Address component '$_' is invalid");
+ setError("IPv6 address component '$octet' is invalid");
return 0;
}
@@ -298,27 +447,27 @@
$count++;
}
if ($count > 1) {
- setError("Address '".$self->{'raw_ip'}."' contains more than one ::");
+ setError("IPv6 address '".$self->{'raw_ip'}."' contains more than one ::");
return 0;
}
# Expand address
my $tempIP;
- if ($k < 8) {
+ if ($numOctets < 8) {
# If there is no :: return 0
if (!$self->{'raw_ip'} =~ /::/) {
- setError("Address '".$self->{'raw_ip'}."' has missing components");
+ setError("IPv6 address '".$self->{'raw_ip'}."' has missing components");
return 0;
}
# Set mask
- if (!defined($mask)) {
- $mask = 16*$k
+ if (!defined($mask) && $numOctets == $preOctets) {
+ $mask = 16 * $preOctets;
}
my @missingOctets;
- for (my $i = 0; $i < (8 - $k); $i++) {
+ for (my $i = 0; $i < (8 - $numOctets); $i++) {
push(@missingOctets, '0000');
}
my $octets = join(':', @missingOctets);
@@ -351,69 +500,19 @@
# Check for full ipv6
if (!($self->{'ip'} =~ /^[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}:[a-f\d]{4}$/i)) {
- setError("Address '".$self->{'raw_ip'}."' is not a valid IPv6 address");
+ setError("IPv6 address '".$self->{'raw_ip'}."' is not a valid IPv6 address");
return 0;
}
# Default mask
- $self->{'cidr'} = $mask ? $mask : 128;
+ $self->{'cidr'} = defined($mask) ? $mask : 128;
}
return 1;
}
-# Convert to binary
-sub to_bin
-{
- my $self = shift;
-
- # We already have it in bin
- return $self->{'ip_bin'} if ($self->{'ip_bin'});
-
- # Check how to convert to bin
- if ($self->{'ip_version'} == 6) {
- my $cleanIP = $self->{'ip'};
- $cleanIP =~ s/://g;
- $self->{'ip_bin'} = unpack('B128', pack('H32', $cleanIP));
-
- } elsif ($self->{'ip_version'} == 4) {
- $self->{'ip_bin'} = unpack('B32', pack('C4C4C4C4', split(/\./, $self->{'ip'})));
- }
-
- return $self->{'ip_bin'};
-}
-
-
-# Convert address to Math::BigInt
-sub to_int
-{
- my $self = shift;
-
- # $n is the increment (the numerical value of the bit we about to 'set')
- my $n = Math::BigInt->new(1);
- # $ret is the returned value
- my $ret = Math::BigInt->new(0);
-
- # Reverse the bit string
- foreach my $bit (reverse(split '', $self->to_bin())) {
- # If the nth bit is 1, add 2**n to $dec
- if ($bit) {
- $ret += $n;
- }
- # Next bit value...
- $n *= 2;
- }
-
-# XXX: This would convert to a string?
-# # Strip leading + sign
-# $ret =~ s/^\+//;
-
- return $ret;
-}
-
-
-# Calculate network and broadcast
+# Calculate network_bin and broadcast_bin
sub _calc_ranges
{
my $self = shift;
@@ -429,11 +528,11 @@
my $NETWORK_MASK = '1' x $cidr . '0' x ($bitlen - $cidr);
my $BROADCAST_MASK = '0' x $cidr . '1' x ($bitlen - $cidr);
- # network = remove bits (AND)
- # broadcast = add bits (OR)
+ # network_bin = remove bits (AND)
+ # broadcast_bin = add bits (OR)
my $bin = $self->to_bin();
- $self->{'network'} = '';
- $self->{'broadcast'} = '';
+ $self->{'network_bin'} = '';
+ $self->{'broadcast_bin'} = '';
# Loop with all bits
for (my $i = 0; $i < $bitlen; $i++) {
# Cut off the bits
@@ -441,63 +540,12 @@
my $b = substr($NETWORK_MASK,$i,1);
my $c = substr($BROADCAST_MASK,$i,1);
# Bit arithmatic ! , sneaky but quick
- $self->{'network'} .= ($a + $b == 2) ? 1 : 0;
- $self->{'broadcast'} .= ($a + $c > 0) ? 1 : 0;
+ $self->{'network_bin'} .= ($a + $b == 2) ? 1 : 0;
+ $self->{'broadcast_bin'} .= ($a + $c > 0) ? 1 : 0;
}
}
-# Get the network address
-sub to_network
-{
- my $self = shift;
-
- if (!defined($self->{'network'})) {
- $self->_calc_ranges();
- }
-
- $self->{'ip'} = $self->{'network'};
- $self->{'cidr'} = undef;
-
- return $self;
-}
-
-
-# Get the broadcast address
-sub to_broadcast
-{
- my $self = shift;
-
-
- if (!defined($self->{'broadcast'})) {
- $self->_calc_ranges();
- }
-
- $self->{'ip'} = $self->{'broadcast'};
- $self->{'cidr'} = undef;
-
- return $self;
-}
-
-
-# Check if ip address is inside another ip address range
-sub is_within
-{
- my ($self,$test) = @_;
-
- my $network = $test->copy()->to_network()->to_int();
- my $broadcast = $test->copy()->to_broadcast()->to_int();
-
- my $self_int = $self->to_int();
-
- if ($self_int >= $network && $self_int <= $broadcast) {
- return 1;
- }
-
- return 0;
-}
-
-
1;
# vim: ts=4
More information about the wiaflos-devel
mailing list