#! /usr/bin/perl use NetAddr::IP; # apt-get install libnetaddr-ip-perl my $regs=supernetciscoacl2preg("147.210.253.0/23"); print "reg=$regs\n"; $mm= $m= " permit ip 148.210.0.0 0.0.255.255 any "; $m=~ s/$regs/match/g; print "$mm -> $m\n"; $mm= $m= " permit ip 147.210.0.0 0.0.255.255 any "; $m=~ s/$regs/match/g; print "$mm -> $m\n"; $mm= $m= " permit ip 147.210.0.0 0.0.0.255 any "; $m=~ s/$regs/match/g; print "$mm -> $m\n"; $mm= $m= " permit ip 147.210.253.0 0.0.0.255 any "; $m=~ s/$regs/match/g; print "$mm -> $m\n"; $mm= $m= " permit ip 147.210.252.0 0.0.1.255 any "; $m=~ s/$regs/match/g; print "$mm -> $m\n"; # @TODO@ should write a supernet2preg whith a first parameter which could take the type # of format we want for the output matching : # if we want to match : format : sample # cisco-acl : ip inverted-dot-mask 147.210.0.0 0.0.255.255 + notations : 0.0.0.0 0.0.0.0 = any + host x.x.x.x # cisco-route : ip dot-mask 147.210.0.0 255.255.0.0 # cidr : ip/bits 147.210.0.0/16 # ... sub supernetciscoacl2preg { ## build a regexp which match nets that inlude the given subnet in the form A.B.C.D/n ## => build regexp that match "bigger" prefixes /n /n-1 /n-2 ... /0 ## can be easily modified to match any form of subnet (adresse/mask, adress mask, adress invertedmask, address/bits...) ## 02/2005 - Laurent FACQ - facq@u-bordeaux.fr - LGPL ## possibles problems when matchin acl like (have to think about it later) ## permit tcp A.B.C.D E.F.G.H I.J.K.L M.N.O.P ## may be in some case, we could badly match E.F.G.H I.J.K.L my ($net)= @_; my $ip= new NetAddr::IP($net); my ($subnet,$bits)= ($ip->addr(), $ip->masklen()); my ($b,$res); my @reg= ('any'); # always match ! if ($bits eq 32) { push @reg, '\\shost\\s+'.$subnet; } foreach $b ( 0..($bits) ) ### replace $bits by ((($bits-1)>0)?($bits-1):0) for strict inclusion { $res= applymaskprefix("$subnet",$b).'\s+'.invertmask(applymaskprefix("255.255.255.255",$b)); push @reg, $res; } $res= "(?:(? "147.210.0.0") { my ($snet,$prefix)= @_; my (@ip,@msk,$i); ### dirty but... easy :) my (@maskprefix)= ('0.0.0.0','128.0.0.0','192.0.0.0','224.0.0.0','240.0.0.0','248.0.0.0','252.0.0.0','254.0.0.0','255.0.0.0','255.128.0.0','255.192.0.0','255.224.0.0','255.240.0.0','255.248.0.0','255.252.0.0','255.254.0.0','255.255.0.0','255.255.128.0','255.255.192.0','255.255.224.0','255.255.240.0','255.255.248.0','255.255.252.0','255.255.254.0','255.255.255.0','255.255.255.128','255.255.255.192','255.255.255.224','255.255.255.240','255.255.255.248','255.255.255.252','255.255.255.254','255.255.255.255'); if ($prefix == 32) { return $snet; } @ip= split('\.',$snet); @msk= split('\.',$maskprefix[$prefix]); # print "prefix $prefix : mask ".join('.',@msk)." ip : ".join('.',@ip)."\n"; foreach $i ( 0..3 ) { $ip[$i]= ($ip[$i]+0) & ($msk[$i]+0); } return join('.',@ip); }