Hi all I have dos-style wildcard ip addresses and some ip address ranges held in a text file, one per line like this ...
127.0.0.0/8 10.0.0.0-10.0.1.255 192.168.1.* 172.?.*.* 10.0.1?.* ... which I'm trying to convert into cidr notation to use with Net::CIDR to create a lookup cache. The first example is already in cidr notation so I can feed that direct to the cache and the second converts straight to cidr using 'range2cidr'. I can also code for the third and fourth examples without problems ... 192.168.1.* == 192.168.1.0 - 192.168.1.255 172.?.*.* == 172.0.0.0 - 172.9.255.255 ... because each of the affected octets contains only a wildcard thus limiting the possible minimum and maximum values. The fifth example is defeating me because the min/max values of the ? are dependent both on its relative position in the octet and on the quantity of, and values of, any prior and subsequent numbers and/or question marks, thus ... input required output [ min/max ] 10.0.1?.* == 10.0.10.0 - 10.0.19.255 [ 0/9 ] 10.0.1??.* == 10.0.100.0 - 10.0.199.255 [ 0/9 ] [ 0/9 ] 10.0.2?.* == 10.0.20.0 - 10.0.29.255 [ 0/9 ] 10.0.25?.* == 10.0.250.0 - 10.0.255.255 [ 0/5 ] 10.0.2??.* == 10.0.200.0 - 10.0.255.255 [ 0/5 ] [ 0/5 ] 10.0.?00.* == 10.0.0.0 - 10.0.200.255 [ 0/2 ] 10.0.??0.* == 10.0.0.0 - 10.0.250.255 [ 0/2 ] [ 0/5 ] I've thought about this long enough to realise that my simplistic procedural approach isn't likely to result in a good algorithm - except, that is, for the minimum values in each case! Am I missing something obvious? Is there a better way to go about this, a maths-based solution, perhaps, or a module? This is my test code thus far. I've also included the test script I've devised for subsequent queries to the cache. If there's a better (quicker, simpler, smaller) way of doing this, I'd be glad to hear about it. -- | #!perl | # test.pl | | use strict; | use warnings; | use Net::CIDR; | use Data::Dumper; | | my %cache; | | my @inputs = qw(127.0.0.0/8 10.0.0.0-10.0.1.255 192.168.1.* 172.?.*.* 10.0.1?.*); | # invalid result from last array entry | | foreach my $input (@inputs) { | print "\ninput: $input\n"; | if ($input =~ /^\d+.*\//) { | print "cidr : $input\n"; | cidr_add($input, "Some cidr text"); | } | if ($input =~ /^\d+\..*-.*\d+\./) { | my @cidr = Net::CIDR::range2cidr($input); | print "cidr : $_\n" foreach @cidr; | cidr_add($_, "Some range text") foreach @cidr; | } | if ($input =~ /\*|\?/) { | my (@lo_octs, @hi_octs); | my @in_octs = split /\./, $input; | # nb. add a check for 4 quads and pad if reqd | foreach my $in (@in_octs) { | # print "in: \'$in\'\n"; | if ($in eq "*") { | push @lo_octs, 0; | push @hi_octs, 255; | } elsif ($in eq "?") { | push @lo_octs, 0; | push @hi_octs, 9; | } elsif ($in =~ /\*|\?/) { | my ($lo_num, $hi_num); | my @nos = split '', $in; | foreach my $n (@nos) { | if ($n =~ /\d/) { | $lo_num .= $n; | $hi_num .= $n; | } elsif ($n eq "?") { | # run out of ideas | } elsif ($n eq "*") { | # run out of steam | } | } | } else { | push @lo_octs, $in; | push @hi_octs, $in; | } | } | my $result = join(".", @lo_octs)."-".join(".", @hi_octs); | print "range: $result\n"; | my @cidr = Net::CIDR::range2cidr($result); | print "cidr : $_\n" foreach @cidr; | cidr_add($_, "Some wildcard text") foreach @cidr; | } | } | | # print "\n\n", Dumper(%cache); | | # test cache | exit unless $ARGV[0]; | | my $ip = $ARGV[0]; | my ($output, $result) = lookup($ip); | print "\nip=$ip", "; result=$result", "; output=$output", "\n"; | | sub cidr_add { | my ($cidr, $text) = @_; | my @range = Net::CIDR::cidr2octets($cidr); | $cache{$_}{text} = $text foreach (@range); | print "added: $cidr\n" if (%cache); | } | | sub lookup { | my $ip = shift; | print "\nCache lookup for $ip\n"; | my @octets = split /\./, $ip; | my $count = scalar @octets; | while ($count > 0) { | my @octs; | push @octs, $octets[$_] for (0..($count - 1)); | my $oct = join ".", @octs; | print "Check $oct\n"; | if (exists $cache{$oct}) { | return($cache{$oct}{text}, "hit"); | } | $count--; | } | return($ip, "miss"); | } -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/