File Coverage

blib/lib/Farly/IPv4/Network.pm
Criterion Covered Total %
statement 66 76 86.8
branch 14 18 77.7
condition 3 6 50.0
subroutine 21 26 80.7
pod 13 15 86.6
total 117 141 82.9


line stmt bran cond sub pod time code
1             package Farly::IPv4::Network;
2            
3 19     19   1668 use 5.008008;
  19         61  
  19         764  
4 19     19   92 use strict;
  19         37  
  19         576  
5 19     19   95 use warnings;
  19         40  
  19         523  
6 19     19   89 use Carp;
  19         36  
  19         1301  
7 19     19   101 use Farly::IPv4::Object;
  19         35  
  19         416  
8 19     19   106 use Farly::IPv4::Address;
  19         33  
  19         25591  
9             require Farly::IPv4::Range;
10            
11             our @ISA = qw(Farly::IPv4::Object);
12             our $VERSION = '0.26';
13            
14             sub new {
15 157     157 1 460 my ( $class, $network ) = @_;
16 157 50       513 confess "IP address and subnet mask required"
17             unless ($network);
18            
19 157         610 my $self = {
20             NETWORK => undef, #Farly::IPv4::Address object
21             MASK => undef #Farly::IPv4::Address object
22             };
23 157         819 bless( $self, $class );
24            
25 157         492 $self->_init($network);
26            
27 157         591 return $self;
28             }
29            
30             sub _init {
31 157     157   284 my ( $self, $network ) = @_;
32            
33 157         965 $network =~ s/^\s+|\s+$//g;
34            
35 157         248 my $address;
36             my $mask;
37 0         0 my $bits;
38            
39 157 100       1370 if ( $network =~ /^((\d{1,3})((\.)(\d{1,3})){3})\s+((\d{1,3})((\.)(\d{1,3})){3})$/ )
    100          
    50          
40             {
41 142         615 ( $address, $mask ) = split( /\s+/, $network );
42             }
43             elsif ( $network =~ /^(\d{1,3}(\.\d{1,3}){3})(\/)(\d+)$/ ) {
44 12         73 ( $address, $bits ) = split( "/", $network );
45 12         36 $mask = $self->_bits_to_mask($bits);
46             }
47             elsif ( $network =~ /^\d+\s+\d+$/ ) {
48 3         9 ( $address, $mask ) = split( /\s+/, $network );
49             }
50             else {
51 0         0 confess "Invalid input $network";
52             }
53            
54 157         533 $self->_set_address($address);
55 157         474 $self->_set_mask($mask);
56             }
57            
58             sub _set_address {
59 157     157   280 my ( $self, $address ) = @_;
60 157         765 $self->{NETWORK} = Farly::IPv4::Address->new($address);
61             }
62            
63             sub _set_mask {
64 157     157   319 my ( $self, $mask ) = @_;
65            
66 157 100       911 if ( $mask =~ /0.0.0.0/ ) {
    100          
67 86         320 $self->{MASK} = Farly::IPv4::Address->new($mask);
68             }
69             elsif ( $mask =~ /^0/ ) {
70 1         7 my $ip = Farly::IPv4::Address->new($mask);
71 1         6 $self->{MASK} = Farly::IPv4::Address->new( $ip->inverse() );
72             }
73             else {
74 70         218 $self->{MASK} = Farly::IPv4::Address->new($mask);
75             }
76            
77 157         518 $self->_is_valid_mask();
78             }
79            
80             sub _bits_to_mask {
81 12     12   17 my ( $self, $bits ) = @_;
82 12 50 33     74 if ( $bits >= 0 && $bits <= 32 ) {
83 12         18 my $zeroBits = 32 - $bits;
84 12         16 my $ip = ( 1 << $zeroBits ) - 1;
85 12         35 return ~$ip & 4294967295;
86             }
87             else {
88 0         0 confess "$bits is not a valid subnet mask";
89             }
90             }
91            
92             sub _is_valid_mask {
93 157     157   530 my $mask = $_[0]->{MASK}->address();
94 157         234 my $current_bit;
95 157         230 my $flag = 0;
96            
97 157         682 for ( my $i = 0 ; $i < 32 ; ++$i ) {
98 5024         4917 $current_bit = ( $mask >> $i ) & 1;
99 5024 100       7818 if ( $current_bit == 1 ) {
100 1644         1589 $flag = 1;
101             }
102 5024 50 66     16156 if ( ( $flag == 1 ) && ( $current_bit == 0 ) ) {
103 0         0 confess "$mask is not a valid subnet mask";
104             }
105             }
106            
107 157         412 return 1;
108             }
109            
110             sub address {
111 0     0 1 0 return $_[0]->{NETWORK}->address();
112             }
113            
114             sub network {
115 732     732 0 2124 return $_[0]->{NETWORK}->address() & $_[0]->{MASK}->address();
116             }
117            
118             sub mask {
119 384     384 1 1278 return $_[0]->{MASK};
120             }
121            
122             sub inverse_mask {
123 250     250 1 448 return $_[0]->mask()->inverse();
124             }
125            
126             sub first {
127 349     349 1 671 return ( $_[0]->network() );
128             }
129            
130             sub last {
131 247     247 1 435 return ( $_[0]->network() + $_[0]->inverse_mask() );
132             }
133            
134             sub as_string {
135 134     134 1 555 return join( " ", $_[0]->network_address()->as_string(), $_[0]->mask()->as_string() );
136             }
137            
138             sub as_wc_string {
139 0     0 1 0 return join( " ", $_[0]->network_address()->as_string(), $_[0]->wc_mask()->as_string() );
140             }
141            
142             sub network_address {
143 135     135 1 448 return Farly::IPv4::Address->new( $_[0]->network() );
144             }
145            
146             sub wc_mask {
147 2     2 0 18 return Farly::IPv4::Address->new( $_[0]->inverse_mask() );
148             }
149            
150             sub broadcast_address {
151 1     1 1 4 return Farly::IPv4::Address->new( $_[0]->network() + $_[0]->inverse_mask() );
152             }
153            
154             sub start {
155 0     0 1   return $_[0]->network_address();
156             }
157            
158             sub end {
159 0     0 1   return $_[0]->broadcast_address();
160             }
161            
162             sub iter {
163 0     0 1   my @iter = ( Farly::IPv4::Range->new( $_[0]->first(), $_[0]->last() ) );
164 0           return @iter;
165             }
166            
167             1;
168             __END__