File Coverage

blib/lib/Net/DHCP/Config/Utilities/Subnet.pm
Criterion Covered Total %
statement 85 96 88.5
branch 27 40 67.5
condition 7 12 58.3
subroutine 15 15 100.0
pod 9 9 100.0
total 143 172 83.1


line stmt bran cond sub pod time code
1             package Net::DHCP::Config::Utilities::Subnet;
2              
3 5     5   110931 use 5.006;
  5         29  
4 5     5   24 use strict;
  5         7  
  5         96  
5 5     5   30 use warnings;
  5         9  
  5         159  
6 5     5   1346 use Net::CIDR;
  5         14401  
  5         221  
7 5     5   2065 use Net::DHCP::Config::Utilities::Options;
  5         12  
  5         144  
8 5     5   1288 use Net::CIDR::Set;
  5         22191  
  5         4175  
9              
10             =head1 NAME
11              
12             Net::DHCP::Config::Utilities::Subnet - Represents a subnet.
13              
14             =head1 VERSION
15              
16             Version 0.0.1
17              
18             =cut
19              
20             our $VERSION = '0.0.1';
21              
22              
23             =head1 SYNOPSIS
24              
25             use Net::DHCP::Config::Utilities::Subnet;
26              
27             my $options={
28             base=>'10.0.0.0',
29             mask=>'255.255.255.0',
30             dns=>'10.0.0.1 , 10.0.10.1',
31             desc=>'a example subnet',
32             };
33            
34             my $subnet = Net::DHCP::Config::Utilities::Subnet->new( $options );
35              
36              
37             =head1 METHODS
38              
39             =head2 new
40              
41             This initiates the object.
42              
43             my $options={
44             base=>'10.0.0.0',
45             mask=>'255.255.255.0',
46             dns=>'10.0.0.1 , 10.0.10.1',
47             desc=>'a example subnet',
48             };
49            
50             my $subnet = Net::DHCP::Config::Utilities::Subnet->new( $options );
51              
52             =cut
53              
54             sub new {
55 10     10 1 313 my %args;
56 10 50       25 if ( defined( $_[1] ) ){
57 10         18 %args=%{$_[1]};
  10         51  
58             }
59              
60             # make sure we have the bare minimum to succeed
61 10 50       44 if ( !defined( $args{base} ) ){
    50          
62 0         0 die('No base defined');
63             }elsif( !defined( $args{mask} ) ){
64 0         0 die('No mask defined');
65             }
66              
67             # make sure the base and mask are sane
68 10         16 my $cidr;
69 10         15 eval{
70 10         41 $cidr=Net::CIDR::addrandmask2cidr( $args{base}, $args{mask} );
71             };
72 10 50       5466 if ( $@ ){
73 0         0 die( 'Base/mask validation failed with... '.$@ );
74             }
75              
76 10 100       27 if (!defined( $args{desc} )){
77 3         18 $args{desc}='';
78             }
79              
80             my $self={
81             ranges=>[],
82             desc=>$args{desc},
83             base=>$args{base},
84             mask=>$args{mask},
85 10         56 cidr=>$cidr,
86             options=>{},
87             };
88 10         19 bless $self;
89              
90             # process any specified ranges
91 10 100       23 if (defined( $args{ranges} )){
92 4         26 my $cidr_checker=Net::CIDR::Set->new( $cidr );
93              
94 4         899 foreach my $range ( @{ $args{ranges} } ){
  4         17  
95 4         25 my @range_split=split(/\ +/, $range);
96              
97             # make sure we have both start and end
98 4 50 33     40 if (
99             (!defined( $range_split[0] )) ||
100             (!defined( $range_split[1] ))
101             ){
102 0         0 die('"'.$range.'" not a properly formed range... Should be "IP IP"');
103             }
104              
105             # make sure both the top and bottom of the range are in our subnet
106 4         17 my @cidr_list = Net::CIDR::addr2cidr( $range_split[0] );
107 4 50       1818 if (! $cidr_checker->contains_all( $cidr_list[0] ) ){
108 0         0 die('"'.$range_split[0].'" for "'.$range.'" not in the CIDR "'.$cidr.'"');
109             }
110 4         2863 @cidr_list = Net::CIDR::addr2cidr( $range_split[1] );
111 4 100       1815 if (! $cidr_checker->contains_all( $cidr_list[0] ) ){
112 1         634 die('"'.$range_split[1].'" for "'.$range.'" not in the CIDR "'.$cidr.'"');
113             }
114              
115             # if we get here, it validated and is safe to add
116 3         1887 push( @{ $self->{ranges} }, $range );
  3         19  
117             }
118             }
119              
120 9         57 my $options_helper=Net::DHCP::Config::Utilities::Options->new;
121 9         23 my $options=$options_helper->get_options;
122 9         56 delete( $options->{mask} ); # already handled this previously
123 9         16 foreach my $key ( keys( %{ $options } ) ){
  9         41  
124 108         142 my $opt=$key;
125              
126             # make sure we don't have long and short, if long is different than short
127 108 50 66     243 if (
      66        
128             defined( $args{ $key } ) &&
129             (
130             defined( $args{ $options->{$key}{long} } ) &&
131             ( $args{ $key } ne $args{ $options->{$key}{long} } )
132             )
133             ){
134 0         0 die( '"'.$key.'" and "'.$args{ $options->{$key}{long} }.'" both defined and the desired one to use is ambigous' );
135             }
136              
137             # figure out if we are using long or short and set $opt appropriately
138 108 50 66     212 if (
139             defined( $args{ $options->{$key}{long} } ) &&
140             ( ! defined( $args{ $key } ) )
141             ){
142             $opt=$options->{$key}{long}
143 0         0 }
144              
145             # finally get around to processing it if we have it
146 108 100       168 if ( defined( $args{ $opt } ) ){
147             # make sure the value for the option is sane
148 17         119 my $error=$options_helper->validate_option( $opt, $args{ $opt } );
149 17 50       42 if ( defined( $error ) ){
150 0         0 die('"'.$opt.'" option with value "'.$args{$opt}.'" did not validate... '.$error);
151             }
152             }
153              
154             # if we get here, it validated and is safe to add
155             # use $key so we are always saving it here as the short option
156 108         218 $self->{options}{$key}=$args{$opt};
157             }
158              
159 9         103 return $self;
160             }
161              
162             =head2 base_get
163              
164             This returns the base IP for the subnet.
165              
166             my $base_IP=$subnet->base;
167              
168             =cut
169              
170             sub base_get{
171 9     9 1 398 return $_[0]->{base};
172             }
173              
174             =head2 cidr
175              
176             Returns the CIDR for the subnet.
177              
178             my $cidr=$subnet->cidr;
179              
180             =cut
181              
182             sub cidr{
183 7     7 1 17 return $_[0]->{cidr};
184             }
185              
186             =head2 desc_get
187              
188             Returns the description.
189              
190             If this was not defined when initialized, '' will be returned.
191              
192             my $desc=$subnet->desc_get;
193              
194             =cut
195              
196             sub desc_get{
197 3     3 1 231 return $_[0]->{desc};
198             }
199              
200             =head2 mask_get
201              
202             This returns the current subnet mask.
203              
204             my $mask=$subnet->mask;
205              
206             =cut
207              
208             sub mask_get{
209 12     12 1 243 return $_[0]->{mask};
210             }
211              
212             =head2 option_get
213              
214             This returns the requested option.
215              
216             If the requested option is not set, undef is returned.
217              
218             Options are always saved internally using the short name, so if an
219             option has both a long name and shortname, then the short name is used.
220              
221             my $option_value=$subnet->option_get( $option );
222             if ( !defined( $option_value ) ){
223             print $option." is not set\n";
224             }
225              
226             =cut
227              
228             sub option_get{
229 27     27 1 762 my $self=$_[0];
230 27         34 my $option=$_[1];
231              
232             # this is one that may potentially be requested, but is stored else where
233 27 50       47 if ( $option eq 'mask' ){
234 0         0 return $self->{mask};
235             }
236              
237 27 100       47 if ( defined( $self->{options}{$option} ) ){
238 6         19 return $self->{options}{$option}
239             }
240              
241 21         34 return undef;
242             }
243              
244             =head2 options_list
245              
246             This list options that have been set, excluding mask.
247              
248             my @options=$subnet->options_list;
249              
250             =cut
251              
252             sub options_list{
253 2     2 1 3 return keys( %{ $_[0]->{options} } );
  2         21  
254             }
255              
256             =head2 option_set
257              
258             This sets an option.
259              
260             Two arguments are taken. The first is the option
261             and the second is the value. If the value is left undefined,
262             then the option is deleted.
263              
264             eval{
265             $subnet->option_set( $option, $value );
266             };
267             if ( $@ ){
268             warn( 'Failed to set option "'.$option.'" with value "'.$value.'"... error='.$@ );
269             }
270              
271             =cut
272              
273             sub option_set{
274 3     3 1 658 my $self=$_[0];
275 3         5 my $option=$_[1];
276 3         5 my $value=$_[2];
277              
278 3 50       8 if ( !defined( $option ) ){
279 0         0 die( 'No option defined' );
280             }
281              
282 3 100       9 if ( $option eq 'mask' ){
283 1         9 die( 'Setting subnet mask here is not supported') ;
284             }
285              
286             # if no value is defined, delete the requested option
287 2 100       6 if ( ! defined( $value ) ){
288 1 50       3 if ( defined( $self->{options}{$option} ) ){
289 1         2 delete( $self->{options}{$option} );
290             }
291 1         3 return 1;
292             }
293              
294             # make sure the specified value is valid
295 1         4 my $options_helper=Net::DHCP::Config::Utilities::Options->new;
296 1         5 my $error=$options_helper->validate_option( $option, $value );
297 1 50       4 if ( defined( $error ) ){
298 0         0 die('"'.$option.'" option with value "'.$value.'" did not validate... '.$error);
299             }
300              
301 1         3 $self->{options}{$option}=$value;
302              
303 1         8 return 1;
304             }
305              
306             =head2 range_get
307              
308             This returns a array with containing the ranges in questions.
309              
310             my @ranges=$subnet->get_ranges;
311             foreach my $range ( @range ){
312             print "range ".$range.";\n"
313             }
314              
315             =cut
316              
317             sub range_get{
318 2     2 1 4 return @{ $_[0]->{ranges} };
  2         8  
319             }
320              
321             =head1 AUTHOR
322              
323             Zane C. Bowers-Hadley, C<< >>
324              
325             =head1 BUGS
326              
327             Please report any bugs or feature requests to C, or through
328             the web interface at L. I will be notified, and then you'll
329             automatically be notified of progress on your bug as I make changes.
330              
331              
332              
333              
334             =head1 SUPPORT
335              
336             You can find documentation for this module with the perldoc command.
337              
338             perldoc Net::DHCP::Config::Utilities
339              
340              
341             You can also look for information at:
342              
343             =over 4
344              
345             =item * RT: CPAN's request tracker (report bugs here)
346              
347             L
348              
349             =item * AnnoCPAN: Annotated CPAN documentation
350              
351             L
352              
353             =item * CPAN Ratings
354              
355             L
356              
357             =item * Search CPAN
358              
359             L
360              
361             =back
362              
363              
364             =head1 ACKNOWLEDGEMENTS
365              
366              
367             =head1 LICENSE AND COPYRIGHT
368              
369             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
370              
371             This is free software, licensed under:
372              
373             The Artistic License 2.0 (GPL Compatible)
374              
375              
376             =cut
377              
378             1; # End of Net::DHCP::Config::Utilities