This should be obvious, but subclass Net::IP
. Here I subclass it to SillyIP
, and wrap the set
function. In real life I'd probably subclass this to Net::IP::SillyIP
though.
package SillyIP;
use Moose;
extends 'Net::IP';
around 'set' => sub {
my ( $orig , $self, $ip, @args ) = @_;
die "invalid IP" if $ip =~ /\*{2}|\s/;
if ( $ip =~ /\.\*/ ) {
my $count = ( $ip =~ s/(\.\*)+$/.0/g );
$ip .= '/' . (abs(4- $count)*8);
}
$self->$orig( $ip, @args );
};
1;
package main;
use Test::More tests => 5;
eval { SillyIP->new('10.**.1.1') };
ok ( $@, 'Fail to accept **' );
eval { SillyIP->new(' 10.0.1.1 ') };
ok ( $@, 'Fail to accept spaces in ip' );
is ( SillyIP->new('10.*.*.*')->ip, SillyIP->new('10/8')->ip, '8 bit network' );
is ( SillyIP->new('192.168.*.*')->ip, SillyIP->new('192.168/16')->ip, '16 bit network' );
is ( SillyIP->new('192.168.1.*')->ip, SillyIP->new('192.168.1/24')->ip, '24 bit network' );
This will provide 90% of what you're asking. It doesn't however accept *
as a range for digit. This is because ipv4 addresses aren't decimal. They're actually just a 32bit data structures, which can be displayed as a.b.c.d
so long as {a,b,c,d}
is in range of 1-255 (8 bits). This means that asking *.1.2.3
, to represent 1.2.3.4
, and 2.2.3.4
, but not 1.2.3.5
has no technical merit whatsoever. There is no reason to ever need this. But you could accomplish it with a quick binary algorithm.