Net-CIDR-Set-0.15/0000755000175000017500000000000015015356014011265 5ustar rrrrNet-CIDR-Set-0.15/META.json0000664000175000017500000000253015015356014012710 0ustar rrrr{ "abstract" : "Manipulate sets of IP addresses", "author" : [ "Robert Rothenberg " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.74, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Net-CIDR-Set", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "overload" : "0", "strict" : "0", "warnings" : "0" } }, "test" : { "requires" : { "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Net-CIDR-Set" }, "repository" : { "type" : "git", "url" : "git://github.com/robrwo/perl-Net-CIDR-Set.git" } }, "version" : "0.15", "x_serialization_backend" : "JSON::PP version 4.06" } Net-CIDR-Set-0.15/SIGNATURE0000664000175000017500000000523415015356014012557 0ustar rrrrThis file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.89. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 SHA256 c22b96f92b120d8a46da31b0e081000242510daecc383a1b91ee34715c5f7f69 Changes SHA256 5a02a02d27b62850c0c916b1ec012ca71b21593ac6cb82d01f9b23b20759b5fb MANIFEST SHA256 d2d2a338fbd780bd4b5b055b843aefb2b68b60f81020d7a260d83866c275570b META.json SHA256 3aba537db37b0f747812898569169dc0ca41d5c9920d2f3b47b59f2ae8f91b8d META.yml SHA256 db53ecf5003ccaaf43640e1521117b25810daaa4878fdc23a882e1d526994449 Makefile.PL SHA256 9b2f097bf8c4b6ff7d3ae2ece31cbb6654e9feb9609d0aee2f1264f54cc50d31 README SHA256 6e05667d03f4a32e75d52abe4fce0fd24fa7b00e7ccf290040ace4f636cf6d22 lib/Net/CIDR/Set.pm SHA256 0b0f84558eddd6b03a467a632e419c167788fb1c9f1777c87ac1bf0cb5a64a82 lib/Net/CIDR/Set/IPv4.pm SHA256 0b4e7567eb15cf5b160afaa55898848eb7b4ef17256f5a8acbec133c702b64c3 lib/Net/CIDR/Set/IPv6.pm SHA256 23367278754969396ab295c1decde22bb7d9d513a0dba9d68309a5c242918263 t/00-load.t SHA256 418b26a02b554bcf470d9f2f28750cc2a053f4ae21e722d42cad67bfde9bf37a t/basic.t SHA256 436dac01b388165bd739dc17e6003b623e9abfac69bde95104fbcc4f7b15edb4 t/ipv6.t SHA256 bcbb915b1eeb783580e56a3c29fc2fe72f7030f7807007805eecc1e8d96ddf23 t/is_cidr.t SHA256 3d904633d371863df574e3f7438576820ea7758848fb3743de4e9f981199c50e t/misc.t SHA256 057c4f0d470458199e5b8036d713bd3f4dc5ef9850e34b8f31f4304078c880f4 t/octal.t SHA256 606a78deb7e2c0dacba1512f92d1b51852a448ffebe8eabb77c27bdbb9d179a4 t/operations.t SHA256 505f0d5c68824b3d02df44fa02031c9a379939327af4ef3565166d713cd24f70 t/pod.t SHA256 adc7df1d52c8808f0e2779227a9f662477250c3ca69133cabe7b3934a05262e2 t/private.t -----BEGIN PGP SIGNATURE----- iQGzBAEBAwAdFiEEeIwq7Pfyfxtssr5nHmWrcYGDC6wFAmg13AwACgkQHmWrcYGD C6wo2Av+OkWO7lUn78EcZGOQ539SrbtQfDN52vncR1swFKhIwV2c1kMOPyQb0hth WY+wFJzzeT0qZJl8YcWx9SJZ4F8O8BpbdUvk3Da4Je+wN1b3rD035RWdN/k3OSgI 3QS4z2y3EBRxvewBcverKjRzM1zZjgS22TdZkfg5BFA/1TQco/hsMt/NJaNmsAPg GZKOKu5mcZJu9ZSRZtjLsl+Nf5ghGZ/qQnpcYDWl6HPteYuO2UIrNUYGsRYTJJdY YVos3t14/QfQDiVaGKZNjQnoQD30X2BhyOzV3f2JW8jEv8ZWty00mkI3qTV67wk8 q5tLmS1IwcjHo5tlNOWbRR/eSos7ED3jv9xr27p2/JsBQZQFo3aQEeEVsYR1gpox w5WW7KOxU831V4AMRb45GjqKxfXIU+2BPfswjwjwlla1GIZageG1f9eL+HWL1vCp SXN1ARXG04aP5pHYSiSRd/08/qYyOWcono8Xcg/Aq6oGokvsBRWiWgVPLFScFG0q 89CSdCSe =R3q5 -----END PGP SIGNATURE----- Net-CIDR-Set-0.15/MANIFEST0000644000175000017500000000046115015356014012417 0ustar rrrrChanges lib/Net/CIDR/Set.pm lib/Net/CIDR/Set/IPv4.pm lib/Net/CIDR/Set/IPv6.pm Makefile.PL MANIFEST META.json META.yml README t/00-load.t t/basic.t t/ipv6.t t/is_cidr.t t/misc.t t/octal.t t/operations.t t/pod.t t/private.t SIGNATURE Public-key signature (added by MakeMaker) Net-CIDR-Set-0.15/t/0000755000175000017500000000000015015356014011530 5ustar rrrrNet-CIDR-Set-0.15/t/misc.t0000644000175000017500000000136715015335363012663 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 6; use Net::CIDR::Set; { eval { Net::CIDR::Set->new( 'foo' ) }; like $@, qr{Can't decode}, 'parse error on new'; } { my $set = Net::CIDR::Set->new; eval { $set->add( 'foo' ) }; like $@, qr{Can't decode}, 'parse error on add'; eval { $set->add( '10.0.0.0/8' ) }; ok !$@, 'can still parse ipv4'; eval { $set->add( '::' ) }; like $@, qr{Can't decode}, 'ipv4 personality set'; } { my $set = Net::CIDR::Set->new; eval { $set->add( 'foo' ) }; like $@, qr{Can't decode}, 'parse error on add'; eval { $set->add( '::' ) }; ok !$@, 'can still parse ipv6'; # eval { $set->add( '10.0.0.0/8' ) }; # like $@, qr{Can't decode}, 'ipv6 personality set'; } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/octal.t0000644000175000017500000000031615015352715013023 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 1; use Net::CIDR::Set; my $priv = eval { Net::CIDR::Set->new("010.0.0.0/8") }; like $@, qr{Can't decode 010.0.0.0/8}, "parse error with octal"; Net-CIDR-Set-0.15/t/ipv6.t0000644000175000017500000000156115015335363012610 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 6; use Net::CIDR::Set; { ok my $set = eval { Net::CIDR::Set->new( '2001:0db8:1234::/48' ) }, 'parsed'; ok !$@, 'no error' or diag $@; my @r = $set->as_range_array( 2 ); is_deeply [@r], ['2001:db8:1234::-2001:db8:1234:ffff:ffff:ffff:ffff:ffff'], 'range'; } { ok my $set = eval { Net::CIDR::Set->new( '2001:10::/28', '2001::/32', '2001:db8::/32', '2002::/16', '::/128', '::1/128', '::ffff:0:0/96', 'fc00::/7', 'fe80::/10', 'fec0::/10', 'ff00::/8', ); }, 'parsed'; ok !$@, 'no error' or diag $@; my @r = $set->as_cidr_array( 1 ); is_deeply [@r], [ '::/127', '::ffff:0:0/96', '2001::/32', '2001:10::/28', '2001:db8::/32', '2002::/16', 'fc00::/7', 'fe80::/9', 'ff00::/8' ], 'correct data'; } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/is_cidr.t0000644000175000017500000000375515015335363013347 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 38; use Net::CIDR::Set; # These tests are meant to exercise the _is_cidr() function. # # as_string -> as_range_array -> iterate_ranges -> decode -> _is_cidr { # 18 tests my @input = ( "194.79.0.0-194.79.1.255", "194.79.0.0-194.79.1.254", "194.79.0.1-194.79.1.255", "85.63.41.0-85.63.41.15", "85.63.41.0-85.63.41.13", "85.63.41.2-85.63.41.13", "85.63.41.2-85.63.41.15", '2001:0db8:1234::/48', '2001:0db8:1234::/48, 2001:0db8:1235::/48', '2001:0db8:1235::/48, 2001:0db8:1236::/48', '2001:0db8:1234::-2001:0db8:1234:ffff::', '2001:0db8:1234::-2001:0db8:1235:ffff::', '2001:0db8:1235::-2001:0db8:1236:ffff::', '2001:0db8:1234::-2001:0db8:1235::', "60.200.0.0/24, 60.200.1.0/24, 60.200.2.0/24, 60.200.3.0/24", "60.200.0.0/24, 60.200.1.0/24, 60.200.2.0/24", "60.200.0.0/24, 60.200.2.0/24", "60.200.0.0/24, 60.200.1.0/25", ); # 16 more tests for my $i (0..7) { my $j = $i + 1; push @input, "60.200.$i.0/24, 60.200.$j.0/24"; push @input, "60:200:${i}::/48, 60:200:${j}::/48"; } for my $orig_string (@input) { my $set = Net::CIDR::Set->new($orig_string); my $new_string = $set->as_string(); my $s2 = Net::CIDR::Set->new($new_string); ok $set->equals( $s2 ) or diag("$orig_string vs $new_string", "\n\t(strings needn't be identical, just logically equivalent)"); } } { # 4 tests my %input = ( "60.200.0.0/24, 60.200.1.0/24, 60.200.2.0/24, 60.200.3.0/24" => ['60.200.0.0/22'], "60.200.0.0/24, 60.200.1.0/24, 60.200.2.0/24" => ['60.200.0.0-60.200.2.255'], "60.200.0.0/24, 60.200.2.0/24" => ['60.200.0.0/24', '60.200.2.0/24'], "60.200.0.0/24, 60.200.1.0/25" => ['60.200.0.0-60.200.1.127'], ); for my $orig_string (sort keys %input) { my $set = Net::CIDR::Set->new($orig_string); my @range = $set->as_range_array(); is_deeply(\@range, $input{$orig_string}); } } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/basic.t0000644000175000017500000000347015015335363013006 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 10; use Net::CIDR::Set; { ok defined( my $set = Net::CIDR::Set->new ), "set created OK"; isa_ok $set, 'Net::CIDR::Set'; $set->add( '127.0.0.1' ); my @got = $set->as_address_array; is_deeply [@got], ['127.0.0.1'], "got address"; } { my $set = Net::CIDR::Set->new; $set->add( '192.168.0.0/16' ); { my @got = $set->as_cidr_array; is_deeply [@got], ['192.168.0.0/16'], "got cidr"; } $set->remove( '192.168.0.65' ); { my @got = $set->as_range_array; is_deeply [@got], [ '192.168.0.0-192.168.0.64', '192.168.0.66-192.168.255.255' ], "got range"; my $s2 = Net::CIDR::Set->new( @got ); ok $set->equals( $s2 ), "can reparse"; } { my @got = $set->as_cidr_array; is_deeply [@got], [ '192.168.0.0/26', '192.168.0.64', '192.168.0.66/31', '192.168.0.68/30', '192.168.0.72/29', '192.168.0.80/28', '192.168.0.96/27', '192.168.0.128/25', '192.168.1.0/24', '192.168.2.0/23', '192.168.4.0/22', '192.168.8.0/21', '192.168.16.0/20', '192.168.32.0/19', '192.168.64.0/18', '192.168.128.0/17' ], "got cidr"; my $s2 = Net::CIDR::Set->new( @got ); ok $set->equals( $s2 ), "can reparse"; } } { my @private = map { Net::CIDR::Set->new( $_ ) } '10.0.0.0/8', '192.168.0.0/16', '172.16.0.0/12'; my $all_priv = Net::CIDR::Set->new; for my $priv ( @private ) { $all_priv = $all_priv->union( $priv ); } my @got = $all_priv->as_cidr_array; is_deeply [@got], [ '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', ], "union"; } { my $s1 = Net::CIDR::Set->new( '10.0.0.0/9' ); my $s2 = Net::CIDR::Set->new( '10.128.0.0/9' ); my $hit = $s1->intersection( $s2 ); ok $hit->is_empty, "no intersection" or diag "got $hit"; } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/private.t0000644000175000017500000000750715015335363013404 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 150; use Net::CIDR::Set; use Net::CIDR::Set::IPv4; use Net::CIDR::Set::IPv6; { # _inc for my $b ( 0 .. 31 ) { my $n = 1 << $b; my $p = $n - 1; my $q = $n + 1; is unpack( 'N', Net::CIDR::Set::_inc( pack 'N', $p ) ), $n, "_inc($p) == $n"; is unpack( 'N', Net::CIDR::Set::_inc( pack 'N', $n ) ), $q, "_inc($n) == $q"; is unpack( 'N', Net::CIDR::Set::_dec( pack 'N', $n ) ), $p, "_dec($n) == $p"; is unpack( 'N', Net::CIDR::Set::_dec( pack 'N', $q ) ), $n, "_dec($q) == $n"; } my @big = ( { name => '0 to 1', before => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], after => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ] }, { name => 'wrap some', before => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255 ], after => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ] }, { name => 'wrap all', before => [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ], after => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }, ); for my $b ( @big ) { my $name = $b->{name}; my @inc = unpack 'C*', Net::CIDR::Set::_inc( pack 'C*', @{ $b->{before} } ); is_deeply [@inc], $b->{after}, "$name: _inc"; my @dec = unpack 'C*', Net::CIDR::Set::_dec( pack 'C*', @inc ); is_deeply [@dec], $b->{before}, "$name: _dec"; } } { my @case = ( { ip => '127.0.0.1', expect => [ [ 0, 127, 0, 0, 1 ], [ 0, 127, 0, 0, 2 ] ] }, { ip => '192.168.0.0/16', expect => [ [ 0, 192, 168, 0, 0 ], [ 0, 192, 169, 0, 0 ] ] }, { ip => '192.168.0.0/255.255.0.0', expect => [ [ 0, 192, 168, 0, 0 ], [ 0, 192, 169, 0, 0 ] ] }, { ip => '192.168.0.0/0.0.255.255', error => qr{Can't decode} }, { ip => '0.0.0.0/0', expect => [ [ 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0 ] ] }, { ip => '192.168.0.12-192.168.1.13', expect => [ [ 0, 192, 168, 0, 12 ], [ 0, 192, 168, 1, 14 ] ] }, { ip => '0.0.0.0-255.255.255.255', expect => [ [ 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0 ] ] }, ); for my $case ( @case ) { my @enc = eval { Net::CIDR::Set::IPv4->encode( $case->{ip} ) }; if ( my $error = $case->{error} ) { like $@, $error, 'error'; } else { my @got = map { [ unpack 'C*', $_ ] } @enc; is_deeply [@got], $case->{expect}, "encode $case->{ip}"; } } } { my @case = ( { range => [ [ 0, 127, 0, 0, 1 ], [ 0, 127, 0, 0, 2 ] ], generic => 0, expect => '127.0.0.1', }, { range => [ [ 0, 127, 0, 0, 1 ], [ 0, 127, 0, 0, 2 ] ], generic => 1, expect => '127.0.0.1/32', }, { range => [ [ 0, 127, 0, 0, 1 ], [ 0, 127, 0, 0, 2 ] ], generic => 2, expect => '127.0.0.1-127.0.0.1', }, { range => [ [ 0, 192, 168, 0, 12 ], [ 0, 192, 168, 1, 14 ] ], generic => 0, expect => '192.168.0.12-192.168.1.13', }, { range => [ [ 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0 ] ], generic => 0, expect => '0.0.0.0/0', }, { range => [ [ 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0 ] ], generic => 1, expect => '0.0.0.0/0', }, { range => [ [ 0, 0, 0, 0, 0 ], [ 1, 0, 0, 0, 0 ] ], generic => 2, expect => '0.0.0.0-255.255.255.255', }, ); for my $case ( @case ) { my $got = Net::CIDR::Set::IPv4->decode( ( map { pack 'C*', @$_ } @{ $case->{range} } ), $case->{generic} ); is $got, $case->{expect}, "$got"; } } { is Net::CIDR::Set::_conjunction( or => 1, 2, 3 ), '1, 2 or 3', '_conjunction'; is Net::CIDR::Set::_and( 1, 2, 3 ), '1, 2 and 3', '_and'; } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/operations.t0000644000175000017500000000132115015335363014101 0ustar rrrr#!perl use strict; use warnings; use Test::More tests => 4; use Net::CIDR::Set; use Data::Dumper; { my $s1 = Net::CIDR::Set->new( '0.0.0.0-0.0.0.255', '0.0.2.0-255.255.255.255' ); my $s2 = Net::CIDR::Set->new( '0.0.1.0-0.0.1.255' ); my $s3 = $s1->union( $s2 ); is_deeply [ $s3->as_cidr_array ], ['0.0.0.0/0'], 'union'; my $s4 = $s1->intersection( $s2 ); is_deeply [ $s4->as_cidr_array ], [], 'intersection'; my $s5 = $s1->complement->union( $s2->complement->union ); is_deeply [ $s5->as_cidr_array ], ['0.0.0.0/0'], 'complement + union'; my $s6 = $s1->complement->intersection( $s2->complement ); is_deeply [ $s6->as_cidr_array ], [], 'complement + intersection'; } # vim:ts=2:sw=2:et:ft=perl Net-CIDR-Set-0.15/t/00-load.t0000644000175000017500000000031015015335363013047 0ustar rrrruse Test::More tests => 3; BEGIN { use_ok( 'Net::CIDR::Set' ); use_ok( 'Net::CIDR::Set::IPv4' ); use_ok( 'Net::CIDR::Set::IPv6' ); } diag( "Testing Net::CIDR::Set $Net::CIDR::Set::VERSION" ); Net-CIDR-Set-0.15/t/pod.t0000644000175000017500000000021415015335363012500 0ustar rrrr#!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); Net-CIDR-Set-0.15/lib/0000755000175000017500000000000015015356014012033 5ustar rrrrNet-CIDR-Set-0.15/lib/Net/0000755000175000017500000000000015015356014012561 5ustar rrrrNet-CIDR-Set-0.15/lib/Net/CIDR/0000755000175000017500000000000015015356014013302 5ustar rrrrNet-CIDR-Set-0.15/lib/Net/CIDR/Set/0000755000175000017500000000000015015356014014035 5ustar rrrrNet-CIDR-Set-0.15/lib/Net/CIDR/Set/IPv6.pm0000644000175000017500000001154515015355332015167 0ustar rrrrpackage Net::CIDR::Set::IPv6; use warnings; use strict; use Carp; =head1 NAME Nset::CIDR::Set::IPv6 - Encode / decode IPv6 addresses =head1 VERSION This document describes Net::CIDR::Set::IPv6 version 0.15 =cut our $VERSION = '0.15'; sub new { bless \my $x, shift } sub _pack_ipv4 { my @nums = split /[.]/, shift, -1; return unless @nums == 4; for ( @nums ) { return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ < 256; } return pack "CC*", 0, @nums; } sub _426 { my @nums = split /[.]/, shift, -1; return if grep $_ > 255, @nums; return join( ":", unpack( 'H*', pack 'C*', @nums ) =~ /..../g ); } sub _pack { my $ip = shift; return pack( 'H*', '0' x 33 ) if $ip eq '::'; return if $ip =~ /^:/ and $ip !~ s/^::/:/; return if $ip =~ /:$/ and $ip !~ s/::$/:/; my @nums = split /:/, $ip, -1; return unless @nums <= 8; my ( $empty, $ipv4, $str ) = ( 0, '', '' ); for ( @nums ) { return if $ipv4; $str .= "0" x ( 4 - length ) . $_, next if /^[a-fA-F\d]{1,4}$/; do { return if $empty++ }, $str .= "X", next if $_ eq ''; next if $ipv4 = _pack_ipv4( $_ ); return; } return if $ipv4 and @nums > 6; $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty; return pack( "H*", "00" . $str ) . $ipv4; } sub _unpack { return _compress_ipv6( join( ":", unpack( "xH*", shift ) =~ /..../g ) ); } # Replace longest run of null blocks with a double colon sub _compress_ipv6 { my $ip = shift; if ( my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) { my $max = $runs[0]; for ( @runs[ 1 .. $#runs ] ) { $max = $_ if length( $max ) < length; } $ip =~ s/$max/::/; } $ip =~ s/:0{1,3}/:/g; return $ip; } sub _width2bits { my ( $width, $size ) = @_; return pack 'B*', ( '1' x ( $width + 8 ) ) . ( '0' x ( $size - $width ) ); } sub _is_cidr { my ( $lo, $hi ) = @_; my $mask = ~( $lo ^ $hi ); my $bits = unpack 'B*', $mask; return unless $hi eq ($lo | $hi); return unless $bits =~ /^(1*)0*$/; return length( $1 ) - 8; } sub _encode { my ( $self, $ip ) = @_; if ( $ip =~ m{^(.+?)/(.+)$} ) { my $mask = $2; return unless my $addr = _pack( $1 ); return unless my $bits = _width2bits( $mask, 128 ); return ( $addr & $bits, Net::CIDR::Set::_inc( $addr | ~$bits ) ); } elsif ( $ip =~ m{^(.+?)-(.+)$} ) { my ( $from, $to ) = ( $1, $2 ); return unless my $lo = _pack( $from ); return unless my $hi = _pack( $to ); return ( $lo, Net::CIDR::Set::_inc( $hi ) ); } else { return $self->_encode( "$ip/128" ); } } sub encode { my ( $self, $ip ) = @_; my @r = $self->_encode( $ip ) or croak "Can't decode $ip as an IPv6 address"; return @r; } sub decode { my $self = shift; my $lo = shift; my $hi = Net::CIDR::Set::_dec( shift ); my $generic = shift || 0; if ( $generic < 1 && $lo eq $hi ) { # Single address return _unpack( $lo ); } elsif ( $generic < 2 && defined( my $w = _is_cidr( $lo, $hi ) ) ) { # Valid CIDR range return join '/', _unpack( $lo ), $w; } else { # General range return join '-', _unpack( $lo ), _unpack( $hi ); } } sub nbits { 128 } 1; __END__ =head1 AUTHOR Andy Armstrong Maintained by Robert Rothenberg =head1 LICENCE AND COPYRIGHT This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L. Copyright (c) 2009, 2014, 2025 Message Systems, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Message Systems, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Net-CIDR-Set-0.15/lib/Net/CIDR/Set/IPv4.pm0000644000175000017500000000762215015355332015166 0ustar rrrrpackage Net::CIDR::Set::IPv4; use warnings; use strict; use Carp; =head1 NAME Net::CIDR::Set::IPv4 - Encode / decode IPv4 addresses =head1 VERSION This document describes Net::CIDR::Set::IPv4 version 0.15 =cut our $VERSION = '0.15'; sub new { bless \my $x, shift } sub _pack { my @nums = split /[.]/, shift, -1; return unless @nums == 4; for ( @nums ) { return unless /^\d{1,3}$/ and !/^0\d{1,2}$/ and $_ < 256; } return pack "CC*", 0, @nums; } sub _unpack { join ".", unpack "xC*", shift } sub _width2bits { my ( $width, $size ) = @_; return pack 'B*', ( '1' x ( $width + 8 ) ) . ( '0' x ( $size - $width ) ); } sub _ip2bits { my $ip = shift or return; vec( $ip, 0, 8 ) = 255; my $bits = unpack 'B*', $ip; return unless $bits =~ /^1*0*$/; # Valid mask? return $ip; } sub _is_cidr { my ( $lo, $hi ) = @_; my $mask = ~( $lo ^ $hi ); my $bits = unpack 'B*', $mask; return unless $hi eq ($lo | $hi); return unless $bits =~ /^(1*)0*$/; return length( $1 ) - 8; } sub _encode { my ( $self, $ip ) = @_; if ( $ip =~ m{^(.+?)/(.+)$} ) { my $mask = $2; return unless my $addr = _pack( $1 ); return unless my $bits = ( $mask =~ /^\d+$/ ) ? _width2bits( $mask, 32 ) : _ip2bits( _pack( $mask ) ); return ( $addr & $bits, Net::CIDR::Set::_inc( $addr | ~$bits ) ); } elsif ( $ip =~ m{^(.+?)-(.+)$} ) { return unless my $lo = _pack( $1 ); return unless my $hi = _pack( $2 ); return ( $lo, Net::CIDR::Set::_inc( $hi ) ); } else { return $self->_encode( "$ip/32" ); } } sub encode { my ( $self, $ip ) = @_; my @r = $self->_encode( $ip ) or croak "Can't decode $ip as an IPv4 address"; return @r; } sub decode { my $self = shift; my $lo = shift; my $hi = Net::CIDR::Set::_dec( shift ); my $generic = shift || 0; if ( $generic < 1 && $lo eq $hi ) { # Single address return _unpack( $lo ); } elsif ( $generic < 2 && defined( my $w = _is_cidr( $lo, $hi ) ) ) { # Valid CIDR range return join '/', _unpack( $lo ), $w; } else { # General range return join '-', _unpack( $lo ), _unpack( $hi ); } } sub nbits { 32 } 1; __END__ =head1 AUTHOR Andy Armstrong Maintained by Robert Rothenberg =head1 LICENCE AND COPYRIGHT This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L. Copyright (c) 2009, 2014, 2025 Message Systems, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Message Systems, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Net-CIDR-Set-0.15/lib/Net/CIDR/Set.pm0000644000175000017500000004340115015355332014377 0ustar rrrrpackage Net::CIDR::Set; use warnings; use strict; use Carp qw( croak confess ); use Net::CIDR::Set::IPv4; use Net::CIDR::Set::IPv6; use overload '""' => 'as_string'; our $VERSION = '0.15'; =head1 NAME Net::CIDR::Set - Manipulate sets of IP addresses =head1 VERSION This document describes Net::CIDR::Set version 0.15 =head1 SYNOPSIS use Net::CIDR::Set; my $priv = Net::CIDR::Set->new( '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16' ); for my $ip ( @addr ) { if ( $priv->contains( $ip ) ) { print "$ip is private\n"; } } =head1 DESCRIPTION C represents sets of IP addresses and allows standard set operations (union, intersection, membership test etc) to be performed on them. In spite of the name it can work with sets consisting of arbitrary ranges of IP addresses - not just CIDR blocks. Both IPv4 and IPv6 addresses are handled - but they may not be mixed in the same set. You may explicitly set the personality of a set: my $ip4set = Net::CIDR::Set->new({ type => 'ipv4 }, '10.0.0.0/8'); Normally this isn't necessary - the set will guess its personality from the first data that is added to it. =head1 INTERFACE =head2 C<< new >> Create a new Net::CIDR::Set. All arguments are optional. May be passed a list of list of IP addresses or ranges which, if present, will be passed to C. The first argument may be a hash reference which will be inspected for named options. Currently the only option that may be passed is C which should be 'ipv4', 'ipv6' or the name of a coder class. See L and L for examples of coder classes. =cut { my %type_map = ( ipv4 => 'Net::CIDR::Set::IPv4', ipv6 => 'Net::CIDR::Set::IPv6', ); sub new { my $self = shift; my $class = ref $self || $self; my $set = bless { ranges => [] }, $class; my $opt = 'HASH' eq ref $_[0] ? shift : {}; if ( defined( my $type = delete $opt->{type} ) ) { my $coder_class = $type_map{$type} || $type; $set->{coder} = $coder_class->new; } elsif ( ref $self ) { $set->{coder} = $self->{coder}; } my @unk = keys %$opt; croak "Unknown options: ", _and( sort @unk ) if @unk; $set->add( @_ ) if @_; return $set; } } # Return the index of the first element >= the supplied value. If the # supplied value is larger than any element in the list the returned # value will be equal to the size of the list. sub _find_pos { my $self = shift; my $val = shift; my $low = shift || 0; my $high = scalar( @{ $self->{ranges} } ); while ( $low < $high ) { my $mid = int( ( $low + $high ) / 2 ); my $cmp = $val cmp $self->{ranges}[$mid]; if ( $cmp < 0 ) { $high = $mid; } elsif ( $cmp > 0 ) { $low = $mid + 1; } else { return $mid; } } return $low; } sub _inc { my @b = reverse unpack 'C*', shift; for ( @b ) { last unless ++$_ == 256; $_ = 0; } return pack 'C*', reverse @b; } sub _dec { my @b = reverse unpack 'C*', shift; for ( @b ) { last unless $_-- == 0; $_ = 255; } return pack 'C*', reverse @b; } sub _guess_coder { my ( $self, $ip ) = @_; for my $class ( qw( Net::CIDR::Set::IPv4 Net::CIDR::Set::IPv6 ) ) { my $coder = $class->new; my @rep = eval { $coder->encode( $ip ) }; return $coder unless $@; } croak "Can't decode $ip as an IPv4 or IPv6 address"; } sub _encode { my ( $self, $ip ) = @_; my $cdr = $self->{coder} ||= $self->_guess_coder( $ip ); return $cdr->encode( $ip ); } { for my $dele ( qw( _decode _nbits ) ) { no strict 'refs'; ( my $meth = $dele ) =~ s/^_//; *{$dele} = sub { my $self = shift; my $cdr = $self->{coder} || croak "Don't know how to $meth yet"; return $cdr->$meth( @_ ); }; } } sub _conjunction { my ( $conj, @list ) = @_; my $last = pop @list; return join " $conj ", join( ', ', @list ), $last; } sub _and { _conjunction( 'and', @_ ) } sub _check_and_coerce { my ( $self, @others ) = @_; my %class = map { eval { ( defined $_ && $_->nbits || '' ) => $_ } } map { $_->{coder} } grep { defined } $self, @others; my @found = sort grep $_, keys %class; croak "Can't mix ", _and( @found ), " bit addresses" if @found > 1; $self->{coder} ||= $class{ $found[0] }; return $self; } =head2 C<< invert >> Invert (negate, complement) a set in-place. my $set = Net::CIDR::Set->new; $set->invert; =cut sub invert { my $self = shift; my @pad = ( 0 ) x ( $self->_nbits / 8 ); my ( $min, $max ) = map { pack 'C*', $_, @pad } 0, 1; if ( $self->is_empty ) { $self->{ranges} = [ $min, $max ]; return; } if ( $self->{ranges}[0] eq $min ) { shift @{ $self->{ranges} }; } else { unshift @{ $self->{ranges} }, $min; } if ( $self->{ranges}[-1] eq $max ) { pop @{ $self->{ranges} }; } else { push @{ $self->{ranges} }, $max; } } =head2 C<< copy >> Make a deep copy of a set. my $set2 = $set->copy; =cut sub copy { my $self = shift; my $copy = $self->new; @{ $copy->{ranges} } = @{ $self->{ranges} }; return $copy; } sub _add_range { my ( $self, $from, $to ) = @_; my $fpos = $self->_find_pos( $from ); my $tpos = $self->_find_pos( _inc( $to ), $fpos ); $from = $self->{ranges}[ --$fpos ] if ( $fpos & 1 ); $to = $self->{ranges}[ $tpos++ ] if ( $tpos & 1 ); splice @{ $self->{ranges} }, $fpos, $tpos - $fpos, ( $from, $to ); } =head2 C<< add >> Add a number of addresses or ranges to a set. $set->add( '10.0.0.0/8', '192.168.0.32-192.168.0.63', '127.0.0.1' ); It is legal to add ranges that overlap with each other and/or with the ranges already in the set. Overlapping ranges are merged. =cut sub add { my ( $self, @addr ) = @_; for my $ip ( map { split /\s*,\s*/ } @addr ) { my ( $lo, $hi ) = $self->_encode( $ip ) or croak "Can't decode $ip"; $self->_add_range( $lo, $hi ); } } =head2 C<< remove >> Remove a number of addresses or ranges from a set. $set->remove( '8.8.0.0/16', '158.152.1.58' ); There is no requirement that the addresses being removed be members of the set. =cut sub remove { my $self = shift; $self->invert; $self->add( @_ ); $self->invert; } =head2 C<< merge >> Merge the contents of other sets into this set. $set = Net::CIDR::Set->new; $set->merge($s1, $s2); =cut sub merge { my $self = shift; $self->_check_and_coerce( @_ ); # TODO: This isn't very efficient - and merge gets called from all # sorts of other places. for my $other ( @_ ) { my $iter = $other->_iterate_runs; while ( my ( $from, $to ) = $iter->() ) { $self->_add_range( $from, $to ); } } } =head2 C<< contains >> A synonmym for C. =head2 C<< contains_all >> Return true if the set contains all of the supplied addresses. Given this set: my $set = Net::CIDR::Set->new('244.188.12.0/8'); this condition is true: if ( $set->contains_all('244.188.12.128/3') ) { # ... } while this condition is false: if ( $set->contains_all('244.188.12.0/12') ) { # ... } =cut *contains = *contains_all; sub contains_all { my $self = shift; my $class = ref $self; return $class->new( @_ )->subset( $self ); } =head2 C<< contains_any >> Return true if there is any overlap between the supplied addresses/ranges and the contents of the set. =cut sub contains_any { my $self = shift; my $class = ref $self; return !$class->new( @_ )->intersection( $self )->is_empty; } sub _iterate_runs { my $self = shift; my $pos = 0; my $limit = scalar( @{ $self->{ranges} } ); return sub { return if $pos >= $limit; my @r = @{ $self->{ranges} }[ $pos, $pos + 1 ]; $pos += 2; return @r; }; } sub compliment { croak "That's very kind of you - but I expect you meant complement"; } =head2 C<< complement >> Return a new set that is the complement of this set. my $inv = $set->complement; =cut sub complement { my $new = shift->copy; # TODO: What if it's empty? $new->invert; return $new; } =head2 C<< union >> Return a new set that is the union of a number of sets. This is equivalent to a logical OR between sets. my $everything = $east->union($west); =cut sub union { my $new = shift->copy; $new->merge( @_ ); return $new; } =head2 C<< intersection >> Return a new set that is the intersection of a number of sets. This is equivalent to a logical AND between sets. my $overlap = $north->intersection($south); =cut sub intersection { my $self = shift; my $class = ref $self; my $new = $class->new; $new->merge( map { $_->complement } $self, @_ ); $new->invert; return $new; } =head2 C<< xor >> Return a new set that is the exclusive-or of existing sets. my $xset = $this->xor($that); The resulting set will contain all addresses that are members of one set but not the other. =cut sub xor { my $self = shift; return $self->union( @_ ) ->intersection( $self->intersection( @_ )->complement ); } =head2 C<< diff >> Return a new set containing all the addresses that are present in this set but not another. my $diff = $this->diff($that); =cut sub diff { my $self = shift; my $other = shift; return $self->intersection( $other->union( @_ )->complement ); } =head2 C<< is_empty >> Return a true value if the set is empty. if ( $set->is_empty ) { print "Nothing there!\n"; } =cut sub is_empty { my $self = shift; return @{ $self->{ranges} } == 0; } =head2 C<< superset >> Return true if this set is a superset of the supplied set. =cut sub superset { my $other = pop; return $other->subset( reverse( @_ ) ); } =head2 C<< subset >> Return true if this set is a subset of the supplied set. =cut sub subset { my $self = shift; my $other = shift || croak "I need two sets to compare"; return $self->equals( $self->intersection( $other ) ); } =head2 C<< equals >> Return true if this set is identical to another set. if ( $set->equals($foo) ) { print "We have the same addresses.\n"; } =cut sub equals { return unless @_; # Array of array refs my @edges = map { $_->{ranges} } @_; my $medge = scalar( @edges ) - 1; POS: for ( my $pos = 0;; $pos++ ) { my $v = $edges[0]->[$pos]; if ( defined( $v ) ) { for ( @edges[ 1 .. $medge ] ) { my $vv = $_->[$pos]; return unless defined( $vv ) && $vv eq $v; } } else { for ( @edges[ 1 .. $medge ] ) { return if defined $_->[$pos]; } } last POS unless defined( $v ); } return 1; } =head1 Retrieving Set Contents The following methods allow the contents of a set to be retrieved in various representations. Each of the following methods accepts an optional numeric argument that controls the formatting of the returned addresses. It may take one of the following values: =over =item C<0> Format each range of addresses as compactly as possible. If the range contains only a single address format it as such. If it can be represented as a single CIDR block use CIDR representation (/) otherwise format it as an arbitrary range (-). =item C<1> Always format as either a CIDR block or an arbitrary range even if the range is just a single address. =item C<2> Always use arbitrary range format (-) even if the range is a single address or a legal CIDR block. =back Here's an example of the different formatting options: my $set = Net::CIDR::Set->new( '127.0.0.1', '192.168.37.0/24', '10.0.0.11-10.0.0.17' ); for my $fmt ( 0 .. 2 ) { print "Using format $fmt:\n"; print " $_\n" for $set->as_range_array( $fmt ); } And here's the output from that code: Using format 0: 10.0.0.11-10.0.0.17 127.0.0.1 192.168.37.0/24 Using format 1: 10.0.0.11-10.0.0.17 127.0.0.1/32 192.168.37.0/24 Using format 2: 10.0.0.11-10.0.0.17 127.0.0.1-127.0.0.1 192.168.37.0-192.168.37.255 Note that this option never affects the addresses that are returned; only how they are formatted. For most purposes the formatting argument can be omitted; it's default value is C<0> which provides the most general formatting. =head2 C<< iterate_addresses >> Return an iterator (a closure) that will return each of the addresses in the set in ascending order. This code my $set = Net::CIDR::Set->new('192.168.37.0/24'); my $iter = $set->iterate_addresses; while ( my $ip = $iter->() ) { print "Got $ip\n"; } outputs 256 distinct addresses from 192.168.37.0 to 192.168.27.255. =cut sub iterate_addresses { my ( $self, @args ) = @_; my $iter = $self->_iterate_runs; my @r = (); return sub { while ( 1 ) { @r = $iter->() or return unless @r; return $self->_decode( ( my $last, $r[0] ) = ( $r[0], _inc( $r[0] ) ), @args ) unless $r[0] eq $r[1]; @r = (); } }; } =head2 C<< iterate_cidr >> Return an iterator (a closure) that will return each of the CIDR blocks in the set in ascending order. This code my $set = Net::CIDR::Set->new('192.168.37.9-192.168.37.134'); my $iter = $set->iterate_cidr; while ( my $cidr = $iter->() ) { print "Got $cidr\n"; } outputs Got 192.168.37.9 Got 192.168.37.10/31 Got 192.168.37.12/30 Got 192.168.37.16/28 Got 192.168.37.32/27 Got 192.168.37.64/26 Got 192.168.37.128/30 Got 192.168.37.132/31 Got 192.168.37.134 This is the most compact CIDR representation of the set because its limits don't fall on convenient CIDR boundaries. =cut sub iterate_cidr { my ( $self, @args ) = @_; my $iter = $self->_iterate_runs; my $size = $self->_nbits; my @r = (); return sub { while ( 1 ) { @r = $iter->() or return unless @r; unless ( $r[0] eq $r[1] ) { ( my $bits = unpack 'B*', $r[0] ) =~ /(0*)$/; my $pad = length $1; $pad = $size if $pad > $size; while ( 1 ) { my $next = _inc( $r[0] | pack 'B*', ( '0' x ( length( $bits ) - $pad ) ) . ( '1' x $pad ) ); return $self->_decode( ( my $last, $r[0] ) = ( $r[0], $next ), @args ) if $next le $r[1]; $pad--; } } @r = (); } }; } =head2 C<< iterate_ranges >> Return an iterator (a closure) that will return each of the ranges in the set in ascending order. This code my $set = Net::CIDR::Set->new( '192.168.37.9-192.168.37.134', '127.0.0.1', '10.0.0.0/8' ); my $iter = $set->iterate_ranges; while ( my $range = $iter->() ) { print "Got $range\n"; } outputs Got 10.0.0.0/8 Got 127.0.0.1 Got 192.168.37.9-192.168.37.134 =cut sub iterate_ranges { my ( $self, @args ) = @_; my $iter = $self->_iterate_runs; return sub { return unless my @r = $iter->(); return $self->_decode( @r, @args ); }; } =head2 C<< as_array >> Convenience method that gathers all of the output from one of the iterators above into an array. my @ranges = $set->as_array( $set->iterate_ranges ); Normally you will use one of C, C or C instead. =cut sub as_array { my ( $self, $iter ) = @_; my @addr = (); while ( my $addr = $iter->() ) { push @addr, $addr; } return @addr; } =head2 C<< as_address_array >> Return an array containing all of the distinct addresses in a set. Note that this may very easily create a very large array. At the time of writing it is, for example, unlikely that you have enough memory for an array containing all of the possible IPv6 addresses... =cut sub as_address_array { my $self = shift; return $self->as_array( $self->iterate_addresses( @_ ) ); } =head2 C<< as_cidr_array >> Return an array containing all of the distinct CIDR blocks in a set. =cut sub as_cidr_array { my $self = shift; return $self->as_array( $self->iterate_cidr( @_ ) ); } =head2 C<< as_range_array >> Return an array containing all of the ranges in a set. =cut sub as_range_array { my $self = shift; return $self->as_array( $self->iterate_ranges( @_ ) ); } =head2 C<< as_string >> Return a compact string representation of a set. =cut sub as_string { join ', ', shift->as_range_array( @_ ) } 1; __END__ =head1 AUTHOR Andy Armstrong Maintained by Robert Rothenberg =head1 CREDITS The encode and decode routines were stolen en masse from Douglas Wilson's L. =head1 LICENCE AND COPYRIGHT This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L. Copyright (c) 2009, 2014, 2025, Message Systems, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Message Systems, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Net-CIDR-Set-0.15/Changes0000644000175000017500000000164015015355757012576 0ustar rrrrRevision history for Net-CIDR-Set 0.15 2025-05-27 16:33:00+01:00 Europe/London [Documentation] - Add missing version and timestamp to Changes for v0.14. [Other] - Re-release due to possible bad signature. - Fix MANIFEST. 0.14 2025-05-27 16:16:23+01:00 Europe/London [Security] - CVE-2025-40911: Disallow IPv4 addresses with a leading 0 in the quads, e.g. "010.0.0.1". [Documentation] - Updated the current maintainer to Robert Rothenberg . - Reversed the order of the Changes file to most-recent first. - Updated copyright year. [Other] - Fixed minor typos in the MANIFEST.SKIP. - Switch to Makefile.PL for building. - Sign the distribution. 0.13 2014-02-24 - Applied Brian Gottreu's fix for https://rt.cpan.org/Public/Bug/Display.html?id=49632 0.12 2009-05-29 - Move to GitHub 0.11 2009-01-29 - Remove broken cidrcalc 0.10 2009-01-29 - Initial release Net-CIDR-Set-0.15/README0000644000175000017500000000101415015343223012137 0ustar rrrrNet-CIDR-Set version 0.13 INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install Alternatively, to install with Module::Build, you can use the following commands: perl Build.PL ./Build ./Build test ./Build install DEPENDENCIES Data::Types List::Util COPYRIGHT AND LICENCE Copyright (C) 2008, Message Systems This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Net-CIDR-Set-0.15/META.yml0000664000175000017500000000137615015356014012547 0ustar rrrr--- abstract: 'Manipulate sets of IP addresses' author: - 'Robert Rothenberg ' build_requires: ExtUtils::MakeMaker: '0' Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.74, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Net-CIDR-Set no_index: directory: - t - inc requires: Carp: '0' overload: '0' strict: '0' warnings: '0' resources: bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Net-CIDR-Set repository: git://github.com/robrwo/perl-Net-CIDR-Set.git version: '0.15' x_serialization_backend: 'CPAN::Meta::YAML version 0.020' Net-CIDR-Set-0.15/Makefile.PL0000644000175000017500000000151015015352747013245 0ustar rrrrrequire 5.006; use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'Net::CIDR::Set', 'AUTHOR' => 'Robert Rothenberg ', 'ABSTRACT_FROM' => 'lib/Net/CIDR/Set.pm', 'VERSION_FROM' => 'lib/Net/CIDR/Set.pm', "LICENSE" => "perl", 'PREREQ_PM' => { 'Carp' => 0, 'overload' => 0, 'strict' => 0, 'warnings' => 0 }, TEST_REQUIRES => { 'Test::More' => 0, }, 'INSTALLDIRS' => 'site', 'EXE_FILES' => [], 'PL_FILES' => {}, 'SIGN' => 1, 'META_MERGE' => { resources => { repository => 'git://github.com/robrwo/perl-Net-CIDR-Set.git', bugtracker => 'https://rt.cpan.org/Public/Dist/Display.html?Name=Net-CIDR-Set', }, } );