I don't understand the 31 versus 32 bit distinction well enough to give a complete solution but here is a partial one:
#!/usr/bin/perl
use strict;
use warnings;
my @examples = ('255.102.25.02/32', '255.102.25.02/31');
my @results;
foreach my $example(@examples){
my ($ip, $bits) = split /\//, $example;
if ($bits == 32){
push @results, convert32($ip);
}
else {
push @results, convert31($ip);
}
}
my $i = 0;
foreach(@examples){
print "$_ ==> $results[$i++]\n";
}
sub convert32{
my $ip = shift;
my @octets = split /\./, $ip;
my $result;
foreach (@octets){
$result .= sprintf("%02X", $_);
}
return $result;
}
sub convert31{
#This subroutine needs more work
my $ip = shift;
#I don't know the rules for converting a 31-bit ip
return "I don't know how to convert $ip/31";
}
d5e5
Practically a Posting Shark
831 posts since Sep 2009
Reputation Points: 162
Solved Threads: 163
Skill Endorsements: 1
Thank you very much :) but can some one tell me how to proceed with 31 bit convertion.
Can you tell us the rule for generating two hex values for the 31-bit conversion? Your example looks like the first value for the 31-bit conversion is identical to the result of the 32-bit conversion, and the second value is created by adding one to the first value. Is that the rule?
d5e5
Practically a Posting Shark
831 posts since Sep 2009
Reputation Points: 162
Solved Threads: 163
Skill Endorsements: 1
Can you tell us the rule for generating two hex values for the 31-bit conversion? Your example looks like the first value for the 31-bit conversion is identical to the result of the 32-bit conversion, and the second value is created by adding one to the first value. Is that the rule?
Assuming the above rule for 31-bit conversion, the following should give the results given in your example:
#!/usr/bin/perl
use strict;
use warnings;
my @examples = ('255.102.25.02/32', '255.102.25.02/31');
my @results;
foreach my $example(@examples){
my ($ip, $bits) = split /\//, $example;
if ($bits == 32){
push @results, convert32($ip);
}
else {
push @results, convert31($ip);
}
}
my $i = 0;
foreach(@examples){
my $string = join(', ', @{$results[$i++]});
print "$_ ==> $string\n";
}
sub convert32{
my $ip = shift;
my @octets = split /\./, $ip;
my $result;
my @arr;
foreach (@octets){
$result .= sprintf("%02X", $_);
}
push @arr, $result;
return \@arr;#Reference to array
}
sub convert31{
my $ip = shift;
my @arr;
#The first value
my $firstvalue = convert32($ip);
push @arr, @$firstvalue;
#The second value
my $val2 = sprintf('%08X', hex($$firstvalue[0]) + 1);
push @arr, $val2;
return \@arr;#Reference to array;
}
d5e5
Practically a Posting Shark
831 posts since Sep 2009
Reputation Points: 162
Solved Threads: 163
Skill Endorsements: 1
Thanks for the explanation. I tried today to come up with a solution but so far this stumps me. Does anyone else know how to do this?
d5e5
Practically a Posting Shark
831 posts since Sep 2009
Reputation Points: 162
Solved Threads: 163
Skill Endorsements: 1
How about converting the 32-bit hex string to a string of ones and zeros representing the value converted to binary? Then you can keep the first n number of bits and concatenate with the possible ending strings of bits to get one or more 32-bit binary strings which you can convert to hex strings.
#!/usr/bin/perl
use strict;
use warnings;
my @examples = ('255.102.25.02/32',
'255.102.25.02/31',
'131.166.254.0/29');
my @results;
foreach my $example(@examples){
my ($ip, $bits) = split /\//, $example;
push @results, ip2hex($ip, $bits);
}
my $i = 0;
foreach(@examples){
my $string = join(', ', @{$results[$i++]});
print "$_ ==> $string\n";
}
sub convert32{
my $ip = shift;
my @octets = split /\./, $ip;
my $result;
my @arr;
foreach (@octets){
$result .= sprintf("%02X", $_);
}
return $result;
}
sub ip2hex{
my ($ip, $n) = @_;
my @arrbin;
my @arrhex;
#The nearest 32-bit string
my $str32 = convert32($ip);
if ($n == 32){
return [$str32];
}
my $onesandzeros = dec2bin(hex($str32));
my $keepbits = substr($onesandzeros, 0, $n);
my @varybits;
my $len = 32 - $n;
my $start = '0' x ($len);
my $end = '1' x ($len);
push @varybits, sprintf("%0${len}s", dec2bin($_)) foreach (bin2dec($start) .. bin2dec($end));
push @arrbin, $keepbits . $_ foreach (@varybits);
push @arrhex, convert32(bin2dec($_)) foreach (@arrbin);
return \@arrhex;#Reference to array;
}
sub dec2bin {
#see http://docstore.mik.ua/orelly/perl/cookbook/ch02_05.htm
my $str = unpack("B32", pack("N", shift));
$str =~ s/^0+(?=\d)//; # otherwise you'll get leading zeros
return $str;
}
sub bin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}
This gives the following output:
255.102.25.02/32 ==> FF661902
255.102.25.02/31 ==> FF661902, FF661903
131.166.254.0/29 ==> 83A6FE00, 83A6FE01, 83A6FE02, 83A6FE03, 83A6FE04, 83A6FE05, 83A6FE06, 83A6FE07
d5e5
Practically a Posting Shark
831 posts since Sep 2009
Reputation Points: 162
Solved Threads: 163
Skill Endorsements: 1